1*61890ccaSMoudy Ho // SPDX-License-Identifier: GPL-2.0-only
2*61890ccaSMoudy Ho /*
3*61890ccaSMoudy Ho  * Copyright (c) 2022 MediaTek Inc.
4*61890ccaSMoudy Ho  * Author: Ping-Hsun Wu <ping-hsun.wu@mediatek.com>
5*61890ccaSMoudy Ho  */
6*61890ccaSMoudy Ho 
7*61890ccaSMoudy Ho #include <media/v4l2-common.h>
8*61890ccaSMoudy Ho #include <media/videobuf2-v4l2.h>
9*61890ccaSMoudy Ho #include <media/videobuf2-dma-contig.h>
10*61890ccaSMoudy Ho #include "mtk-mdp3-core.h"
11*61890ccaSMoudy Ho #include "mtk-mdp3-regs.h"
12*61890ccaSMoudy Ho #include "mtk-mdp3-m2m.h"
13*61890ccaSMoudy Ho 
14*61890ccaSMoudy Ho /*
15*61890ccaSMoudy Ho  * All 10-bit related formats are not added in the basic format list,
16*61890ccaSMoudy Ho  * please add the corresponding format settings before use.
17*61890ccaSMoudy Ho  */
18*61890ccaSMoudy Ho static const struct mdp_format mdp_formats[] = {
19*61890ccaSMoudy Ho 	{
20*61890ccaSMoudy Ho 		.pixelformat	= V4L2_PIX_FMT_GREY,
21*61890ccaSMoudy Ho 		.mdp_color	= MDP_COLOR_GREY,
22*61890ccaSMoudy Ho 		.depth		= { 8 },
23*61890ccaSMoudy Ho 		.row_depth	= { 8 },
24*61890ccaSMoudy Ho 		.num_planes	= 1,
25*61890ccaSMoudy Ho 		.flags		= MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE,
26*61890ccaSMoudy Ho 	}, {
27*61890ccaSMoudy Ho 		.pixelformat	= V4L2_PIX_FMT_RGB565X,
28*61890ccaSMoudy Ho 		.mdp_color	= MDP_COLOR_BGR565,
29*61890ccaSMoudy Ho 		.depth		= { 16 },
30*61890ccaSMoudy Ho 		.row_depth	= { 16 },
31*61890ccaSMoudy Ho 		.num_planes	= 1,
32*61890ccaSMoudy Ho 		.flags		= MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE,
33*61890ccaSMoudy Ho 	}, {
34*61890ccaSMoudy Ho 		.pixelformat	= V4L2_PIX_FMT_RGB565,
35*61890ccaSMoudy Ho 		.mdp_color	= MDP_COLOR_RGB565,
36*61890ccaSMoudy Ho 		.depth		= { 16 },
37*61890ccaSMoudy Ho 		.row_depth	= { 16 },
38*61890ccaSMoudy Ho 		.num_planes	= 1,
39*61890ccaSMoudy Ho 		.flags		= MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE,
40*61890ccaSMoudy Ho 	}, {
41*61890ccaSMoudy Ho 		.pixelformat	= V4L2_PIX_FMT_RGB24,
42*61890ccaSMoudy Ho 		.mdp_color	= MDP_COLOR_RGB888,
43*61890ccaSMoudy Ho 		.depth		= { 24 },
44*61890ccaSMoudy Ho 		.row_depth	= { 24 },
45*61890ccaSMoudy Ho 		.num_planes	= 1,
46*61890ccaSMoudy Ho 		.flags		= MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE,
47*61890ccaSMoudy Ho 	}, {
48*61890ccaSMoudy Ho 		.pixelformat	= V4L2_PIX_FMT_BGR24,
49*61890ccaSMoudy Ho 		.mdp_color	= MDP_COLOR_BGR888,
50*61890ccaSMoudy Ho 		.depth		= { 24 },
51*61890ccaSMoudy Ho 		.row_depth	= { 24 },
52*61890ccaSMoudy Ho 		.num_planes	= 1,
53*61890ccaSMoudy Ho 		.flags		= MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE,
54*61890ccaSMoudy Ho 	}, {
55*61890ccaSMoudy Ho 		.pixelformat	= V4L2_PIX_FMT_ABGR32,
56*61890ccaSMoudy Ho 		.mdp_color	= MDP_COLOR_BGRA8888,
57*61890ccaSMoudy Ho 		.depth		= { 32 },
58*61890ccaSMoudy Ho 		.row_depth	= { 32 },
59*61890ccaSMoudy Ho 		.num_planes	= 1,
60*61890ccaSMoudy Ho 		.flags		= MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE,
61*61890ccaSMoudy Ho 	}, {
62*61890ccaSMoudy Ho 		.pixelformat	= V4L2_PIX_FMT_ARGB32,
63*61890ccaSMoudy Ho 		.mdp_color	= MDP_COLOR_ARGB8888,
64*61890ccaSMoudy Ho 		.depth		= { 32 },
65*61890ccaSMoudy Ho 		.row_depth	= { 32 },
66*61890ccaSMoudy Ho 		.num_planes	= 1,
67*61890ccaSMoudy Ho 		.flags		= MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE,
68*61890ccaSMoudy Ho 	}, {
69*61890ccaSMoudy Ho 		.pixelformat	= V4L2_PIX_FMT_UYVY,
70*61890ccaSMoudy Ho 		.mdp_color	= MDP_COLOR_UYVY,
71*61890ccaSMoudy Ho 		.depth		= { 16 },
72*61890ccaSMoudy Ho 		.row_depth	= { 16 },
73*61890ccaSMoudy Ho 		.num_planes	= 1,
74*61890ccaSMoudy Ho 		.walign		= 1,
75*61890ccaSMoudy Ho 		.flags		= MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE,
76*61890ccaSMoudy Ho 	}, {
77*61890ccaSMoudy Ho 		.pixelformat	= V4L2_PIX_FMT_VYUY,
78*61890ccaSMoudy Ho 		.mdp_color	= MDP_COLOR_VYUY,
79*61890ccaSMoudy Ho 		.depth		= { 16 },
80*61890ccaSMoudy Ho 		.row_depth	= { 16 },
81*61890ccaSMoudy Ho 		.num_planes	= 1,
82*61890ccaSMoudy Ho 		.walign		= 1,
83*61890ccaSMoudy Ho 		.flags		= MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE,
84*61890ccaSMoudy Ho 	}, {
85*61890ccaSMoudy Ho 		.pixelformat	= V4L2_PIX_FMT_YUYV,
86*61890ccaSMoudy Ho 		.mdp_color	= MDP_COLOR_YUYV,
87*61890ccaSMoudy Ho 		.depth		= { 16 },
88*61890ccaSMoudy Ho 		.row_depth	= { 16 },
89*61890ccaSMoudy Ho 		.num_planes	= 1,
90*61890ccaSMoudy Ho 		.walign		= 1,
91*61890ccaSMoudy Ho 		.flags		= MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE,
92*61890ccaSMoudy Ho 	}, {
93*61890ccaSMoudy Ho 		.pixelformat	= V4L2_PIX_FMT_YVYU,
94*61890ccaSMoudy Ho 		.mdp_color	= MDP_COLOR_YVYU,
95*61890ccaSMoudy Ho 		.depth		= { 16 },
96*61890ccaSMoudy Ho 		.row_depth	= { 16 },
97*61890ccaSMoudy Ho 		.num_planes	= 1,
98*61890ccaSMoudy Ho 		.walign		= 1,
99*61890ccaSMoudy Ho 		.flags		= MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE,
100*61890ccaSMoudy Ho 	}, {
101*61890ccaSMoudy Ho 		.pixelformat	= V4L2_PIX_FMT_YUV420,
102*61890ccaSMoudy Ho 		.mdp_color	= MDP_COLOR_I420,
103*61890ccaSMoudy Ho 		.depth		= { 12 },
104*61890ccaSMoudy Ho 		.row_depth	= { 8 },
105*61890ccaSMoudy Ho 		.num_planes	= 1,
106*61890ccaSMoudy Ho 		.walign		= 1,
107*61890ccaSMoudy Ho 		.halign		= 1,
108*61890ccaSMoudy Ho 		.flags		= MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE,
109*61890ccaSMoudy Ho 	}, {
110*61890ccaSMoudy Ho 		.pixelformat	= V4L2_PIX_FMT_YVU420,
111*61890ccaSMoudy Ho 		.mdp_color	= MDP_COLOR_YV12,
112*61890ccaSMoudy Ho 		.depth		= { 12 },
113*61890ccaSMoudy Ho 		.row_depth	= { 8 },
114*61890ccaSMoudy Ho 		.num_planes	= 1,
115*61890ccaSMoudy Ho 		.walign		= 1,
116*61890ccaSMoudy Ho 		.halign		= 1,
117*61890ccaSMoudy Ho 		.flags		= MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE,
118*61890ccaSMoudy Ho 	}, {
119*61890ccaSMoudy Ho 		.pixelformat	= V4L2_PIX_FMT_NV12,
120*61890ccaSMoudy Ho 		.mdp_color	= MDP_COLOR_NV12,
121*61890ccaSMoudy Ho 		.depth		= { 12 },
122*61890ccaSMoudy Ho 		.row_depth	= { 8 },
123*61890ccaSMoudy Ho 		.num_planes	= 1,
124*61890ccaSMoudy Ho 		.walign		= 1,
125*61890ccaSMoudy Ho 		.halign		= 1,
126*61890ccaSMoudy Ho 		.flags		= MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE,
127*61890ccaSMoudy Ho 	}, {
128*61890ccaSMoudy Ho 		.pixelformat	= V4L2_PIX_FMT_NV21,
129*61890ccaSMoudy Ho 		.mdp_color	= MDP_COLOR_NV21,
130*61890ccaSMoudy Ho 		.depth		= { 12 },
131*61890ccaSMoudy Ho 		.row_depth	= { 8 },
132*61890ccaSMoudy Ho 		.num_planes	= 1,
133*61890ccaSMoudy Ho 		.walign		= 1,
134*61890ccaSMoudy Ho 		.halign		= 1,
135*61890ccaSMoudy Ho 		.flags		= MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE,
136*61890ccaSMoudy Ho 	}, {
137*61890ccaSMoudy Ho 		.pixelformat	= V4L2_PIX_FMT_NV16,
138*61890ccaSMoudy Ho 		.mdp_color	= MDP_COLOR_NV16,
139*61890ccaSMoudy Ho 		.depth		= { 16 },
140*61890ccaSMoudy Ho 		.row_depth	= { 8 },
141*61890ccaSMoudy Ho 		.num_planes	= 1,
142*61890ccaSMoudy Ho 		.walign		= 1,
143*61890ccaSMoudy Ho 		.flags		= MDP_FMT_FLAG_OUTPUT,
144*61890ccaSMoudy Ho 	}, {
145*61890ccaSMoudy Ho 		.pixelformat	= V4L2_PIX_FMT_NV61,
146*61890ccaSMoudy Ho 		.mdp_color	= MDP_COLOR_NV61,
147*61890ccaSMoudy Ho 		.depth		= { 16 },
148*61890ccaSMoudy Ho 		.row_depth	= { 8 },
149*61890ccaSMoudy Ho 		.num_planes	= 1,
150*61890ccaSMoudy Ho 		.walign		= 1,
151*61890ccaSMoudy Ho 		.flags		= MDP_FMT_FLAG_OUTPUT,
152*61890ccaSMoudy Ho 	}, {
153*61890ccaSMoudy Ho 		.pixelformat	= V4L2_PIX_FMT_NV24,
154*61890ccaSMoudy Ho 		.mdp_color	= MDP_COLOR_NV24,
155*61890ccaSMoudy Ho 		.depth		= { 24 },
156*61890ccaSMoudy Ho 		.row_depth	= { 8 },
157*61890ccaSMoudy Ho 		.num_planes	= 1,
158*61890ccaSMoudy Ho 		.flags		= MDP_FMT_FLAG_OUTPUT,
159*61890ccaSMoudy Ho 	}, {
160*61890ccaSMoudy Ho 		.pixelformat	= V4L2_PIX_FMT_NV42,
161*61890ccaSMoudy Ho 		.mdp_color	= MDP_COLOR_NV42,
162*61890ccaSMoudy Ho 		.depth		= { 24 },
163*61890ccaSMoudy Ho 		.row_depth	= { 8 },
164*61890ccaSMoudy Ho 		.num_planes	= 1,
165*61890ccaSMoudy Ho 		.flags		= MDP_FMT_FLAG_OUTPUT,
166*61890ccaSMoudy Ho 	}, {
167*61890ccaSMoudy Ho 		.pixelformat	= V4L2_PIX_FMT_MT21C,
168*61890ccaSMoudy Ho 		.mdp_color	= MDP_COLOR_420_BLK_UFO,
169*61890ccaSMoudy Ho 		.depth		= { 8, 4 },
170*61890ccaSMoudy Ho 		.row_depth	= { 8, 8 },
171*61890ccaSMoudy Ho 		.num_planes	= 2,
172*61890ccaSMoudy Ho 		.walign		= 4,
173*61890ccaSMoudy Ho 		.halign		= 5,
174*61890ccaSMoudy Ho 		.flags		= MDP_FMT_FLAG_OUTPUT,
175*61890ccaSMoudy Ho 	}, {
176*61890ccaSMoudy Ho 		.pixelformat	= V4L2_PIX_FMT_MM21,
177*61890ccaSMoudy Ho 		.mdp_color	= MDP_COLOR_420_BLK,
178*61890ccaSMoudy Ho 		.depth		= { 8, 4 },
179*61890ccaSMoudy Ho 		.row_depth	= { 8, 8 },
180*61890ccaSMoudy Ho 		.num_planes	= 2,
181*61890ccaSMoudy Ho 		.walign		= 4,
182*61890ccaSMoudy Ho 		.halign		= 5,
183*61890ccaSMoudy Ho 		.flags		= MDP_FMT_FLAG_OUTPUT,
184*61890ccaSMoudy Ho 	}, {
185*61890ccaSMoudy Ho 		.pixelformat	= V4L2_PIX_FMT_NV12M,
186*61890ccaSMoudy Ho 		.mdp_color	= MDP_COLOR_NV12,
187*61890ccaSMoudy Ho 		.depth		= { 8, 4 },
188*61890ccaSMoudy Ho 		.row_depth	= { 8, 8 },
189*61890ccaSMoudy Ho 		.num_planes	= 2,
190*61890ccaSMoudy Ho 		.walign		= 1,
191*61890ccaSMoudy Ho 		.halign		= 1,
192*61890ccaSMoudy Ho 		.flags		= MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE,
193*61890ccaSMoudy Ho 	}, {
194*61890ccaSMoudy Ho 		.pixelformat	= V4L2_PIX_FMT_NV21M,
195*61890ccaSMoudy Ho 		.mdp_color	= MDP_COLOR_NV21,
196*61890ccaSMoudy Ho 		.depth		= { 8, 4 },
197*61890ccaSMoudy Ho 		.row_depth	= { 8, 8 },
198*61890ccaSMoudy Ho 		.num_planes	= 2,
199*61890ccaSMoudy Ho 		.walign		= 1,
200*61890ccaSMoudy Ho 		.halign		= 1,
201*61890ccaSMoudy Ho 		.flags		= MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE,
202*61890ccaSMoudy Ho 	}, {
203*61890ccaSMoudy Ho 		.pixelformat	= V4L2_PIX_FMT_NV16M,
204*61890ccaSMoudy Ho 		.mdp_color	= MDP_COLOR_NV16,
205*61890ccaSMoudy Ho 		.depth		= { 8, 8 },
206*61890ccaSMoudy Ho 		.row_depth	= { 8, 8 },
207*61890ccaSMoudy Ho 		.num_planes	= 2,
208*61890ccaSMoudy Ho 		.walign		= 1,
209*61890ccaSMoudy Ho 		.flags		= MDP_FMT_FLAG_OUTPUT,
210*61890ccaSMoudy Ho 	}, {
211*61890ccaSMoudy Ho 		.pixelformat	= V4L2_PIX_FMT_NV61M,
212*61890ccaSMoudy Ho 		.mdp_color	= MDP_COLOR_NV61,
213*61890ccaSMoudy Ho 		.depth		= { 8, 8 },
214*61890ccaSMoudy Ho 		.row_depth	= { 8, 8 },
215*61890ccaSMoudy Ho 		.num_planes	= 2,
216*61890ccaSMoudy Ho 		.walign		= 1,
217*61890ccaSMoudy Ho 		.flags		= MDP_FMT_FLAG_OUTPUT,
218*61890ccaSMoudy Ho 	}, {
219*61890ccaSMoudy Ho 		.pixelformat	= V4L2_PIX_FMT_YUV420M,
220*61890ccaSMoudy Ho 		.mdp_color	= MDP_COLOR_I420,
221*61890ccaSMoudy Ho 		.depth		= { 8, 2, 2 },
222*61890ccaSMoudy Ho 		.row_depth	= { 8, 4, 4 },
223*61890ccaSMoudy Ho 		.num_planes	= 3,
224*61890ccaSMoudy Ho 		.walign		= 1,
225*61890ccaSMoudy Ho 		.halign		= 1,
226*61890ccaSMoudy Ho 		.flags		= MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE,
227*61890ccaSMoudy Ho 	}, {
228*61890ccaSMoudy Ho 		.pixelformat	= V4L2_PIX_FMT_YVU420M,
229*61890ccaSMoudy Ho 		.mdp_color	= MDP_COLOR_YV12,
230*61890ccaSMoudy Ho 		.depth		= { 8, 2, 2 },
231*61890ccaSMoudy Ho 		.row_depth	= { 8, 4, 4 },
232*61890ccaSMoudy Ho 		.num_planes	= 3,
233*61890ccaSMoudy Ho 		.walign		= 1,
234*61890ccaSMoudy Ho 		.halign		= 1,
235*61890ccaSMoudy Ho 		.flags		= MDP_FMT_FLAG_OUTPUT | MDP_FMT_FLAG_CAPTURE,
236*61890ccaSMoudy Ho 	}
237*61890ccaSMoudy Ho };
238*61890ccaSMoudy Ho 
239*61890ccaSMoudy Ho static const struct mdp_limit mdp_def_limit = {
240*61890ccaSMoudy Ho 	.out_limit = {
241*61890ccaSMoudy Ho 		.wmin	= 16,
242*61890ccaSMoudy Ho 		.hmin	= 16,
243*61890ccaSMoudy Ho 		.wmax	= 8176,
244*61890ccaSMoudy Ho 		.hmax	= 8176,
245*61890ccaSMoudy Ho 	},
246*61890ccaSMoudy Ho 	.cap_limit = {
247*61890ccaSMoudy Ho 		.wmin	= 2,
248*61890ccaSMoudy Ho 		.hmin	= 2,
249*61890ccaSMoudy Ho 		.wmax	= 8176,
250*61890ccaSMoudy Ho 		.hmax	= 8176,
251*61890ccaSMoudy Ho 	},
252*61890ccaSMoudy Ho 	.h_scale_up_max = 32,
253*61890ccaSMoudy Ho 	.v_scale_up_max = 32,
254*61890ccaSMoudy Ho 	.h_scale_down_max = 20,
255*61890ccaSMoudy Ho 	.v_scale_down_max = 128,
256*61890ccaSMoudy Ho };
257*61890ccaSMoudy Ho 
258*61890ccaSMoudy Ho static const struct mdp_format *mdp_find_fmt(u32 pixelformat, u32 type)
259*61890ccaSMoudy Ho {
260*61890ccaSMoudy Ho 	u32 i, flag;
261*61890ccaSMoudy Ho 
262*61890ccaSMoudy Ho 	flag = V4L2_TYPE_IS_OUTPUT(type) ? MDP_FMT_FLAG_OUTPUT :
263*61890ccaSMoudy Ho 					MDP_FMT_FLAG_CAPTURE;
264*61890ccaSMoudy Ho 	for (i = 0; i < ARRAY_SIZE(mdp_formats); ++i) {
265*61890ccaSMoudy Ho 		if (!(mdp_formats[i].flags & flag))
266*61890ccaSMoudy Ho 			continue;
267*61890ccaSMoudy Ho 		if (mdp_formats[i].pixelformat == pixelformat)
268*61890ccaSMoudy Ho 			return &mdp_formats[i];
269*61890ccaSMoudy Ho 	}
270*61890ccaSMoudy Ho 	return NULL;
271*61890ccaSMoudy Ho }
272*61890ccaSMoudy Ho 
273*61890ccaSMoudy Ho static const struct mdp_format *mdp_find_fmt_by_index(u32 index, u32 type)
274*61890ccaSMoudy Ho {
275*61890ccaSMoudy Ho 	u32 i, flag, num = 0;
276*61890ccaSMoudy Ho 
277*61890ccaSMoudy Ho 	flag = V4L2_TYPE_IS_OUTPUT(type) ? MDP_FMT_FLAG_OUTPUT :
278*61890ccaSMoudy Ho 					MDP_FMT_FLAG_CAPTURE;
279*61890ccaSMoudy Ho 	for (i = 0; i < ARRAY_SIZE(mdp_formats); ++i) {
280*61890ccaSMoudy Ho 		if (!(mdp_formats[i].flags & flag))
281*61890ccaSMoudy Ho 			continue;
282*61890ccaSMoudy Ho 		if (index == num)
283*61890ccaSMoudy Ho 			return &mdp_formats[i];
284*61890ccaSMoudy Ho 		num++;
285*61890ccaSMoudy Ho 	}
286*61890ccaSMoudy Ho 	return NULL;
287*61890ccaSMoudy Ho }
288*61890ccaSMoudy Ho 
289*61890ccaSMoudy Ho enum mdp_ycbcr_profile mdp_map_ycbcr_prof_mplane(struct v4l2_format *f,
290*61890ccaSMoudy Ho 						 u32 mdp_color)
291*61890ccaSMoudy Ho {
292*61890ccaSMoudy Ho 	struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;
293*61890ccaSMoudy Ho 
294*61890ccaSMoudy Ho 	if (MDP_COLOR_IS_RGB(mdp_color))
295*61890ccaSMoudy Ho 		return MDP_YCBCR_PROFILE_FULL_BT601;
296*61890ccaSMoudy Ho 
297*61890ccaSMoudy Ho 	switch (pix_mp->colorspace) {
298*61890ccaSMoudy Ho 	case V4L2_COLORSPACE_JPEG:
299*61890ccaSMoudy Ho 		return MDP_YCBCR_PROFILE_JPEG;
300*61890ccaSMoudy Ho 	case V4L2_COLORSPACE_REC709:
301*61890ccaSMoudy Ho 	case V4L2_COLORSPACE_DCI_P3:
302*61890ccaSMoudy Ho 		if (pix_mp->quantization == V4L2_QUANTIZATION_FULL_RANGE)
303*61890ccaSMoudy Ho 			return MDP_YCBCR_PROFILE_FULL_BT709;
304*61890ccaSMoudy Ho 		return MDP_YCBCR_PROFILE_BT709;
305*61890ccaSMoudy Ho 	case V4L2_COLORSPACE_BT2020:
306*61890ccaSMoudy Ho 		if (pix_mp->quantization == V4L2_QUANTIZATION_FULL_RANGE)
307*61890ccaSMoudy Ho 			return MDP_YCBCR_PROFILE_FULL_BT2020;
308*61890ccaSMoudy Ho 		return MDP_YCBCR_PROFILE_BT2020;
309*61890ccaSMoudy Ho 	default:
310*61890ccaSMoudy Ho 		if (pix_mp->quantization == V4L2_QUANTIZATION_FULL_RANGE)
311*61890ccaSMoudy Ho 			return MDP_YCBCR_PROFILE_FULL_BT601;
312*61890ccaSMoudy Ho 		return MDP_YCBCR_PROFILE_BT601;
313*61890ccaSMoudy Ho 	}
314*61890ccaSMoudy Ho }
315*61890ccaSMoudy Ho 
316*61890ccaSMoudy Ho static void mdp_bound_align_image(u32 *w, u32 *h,
317*61890ccaSMoudy Ho 				  struct v4l2_frmsize_stepwise *s,
318*61890ccaSMoudy Ho 				  unsigned int salign)
319*61890ccaSMoudy Ho {
320*61890ccaSMoudy Ho 	unsigned int org_w, org_h;
321*61890ccaSMoudy Ho 
322*61890ccaSMoudy Ho 	org_w = *w;
323*61890ccaSMoudy Ho 	org_h = *h;
324*61890ccaSMoudy Ho 	v4l_bound_align_image(w, s->min_width, s->max_width, s->step_width,
325*61890ccaSMoudy Ho 			      h, s->min_height, s->max_height, s->step_height,
326*61890ccaSMoudy Ho 			      salign);
327*61890ccaSMoudy Ho 
328*61890ccaSMoudy Ho 	s->min_width = org_w;
329*61890ccaSMoudy Ho 	s->min_height = org_h;
330*61890ccaSMoudy Ho 	v4l2_apply_frmsize_constraints(w, h, s);
331*61890ccaSMoudy Ho }
332*61890ccaSMoudy Ho 
333*61890ccaSMoudy Ho static int mdp_clamp_align(s32 *x, int min, int max, unsigned int align)
334*61890ccaSMoudy Ho {
335*61890ccaSMoudy Ho 	unsigned int mask;
336*61890ccaSMoudy Ho 
337*61890ccaSMoudy Ho 	if (min < 0 || max < 0)
338*61890ccaSMoudy Ho 		return -ERANGE;
339*61890ccaSMoudy Ho 
340*61890ccaSMoudy Ho 	/* Bits that must be zero to be aligned */
341*61890ccaSMoudy Ho 	mask = ~((1 << align) - 1);
342*61890ccaSMoudy Ho 
343*61890ccaSMoudy Ho 	min = 0 ? 0 : ((min + ~mask) & mask);
344*61890ccaSMoudy Ho 	max = max & mask;
345*61890ccaSMoudy Ho 	if ((unsigned int)min > (unsigned int)max)
346*61890ccaSMoudy Ho 		return -ERANGE;
347*61890ccaSMoudy Ho 
348*61890ccaSMoudy Ho 	/* Clamp to aligned min and max */
349*61890ccaSMoudy Ho 	*x = clamp(*x, min, max);
350*61890ccaSMoudy Ho 
351*61890ccaSMoudy Ho 	/* Round to nearest aligned value */
352*61890ccaSMoudy Ho 	if (align)
353*61890ccaSMoudy Ho 		*x = (*x + (1 << (align - 1))) & mask;
354*61890ccaSMoudy Ho 	return 0;
355*61890ccaSMoudy Ho }
356*61890ccaSMoudy Ho 
357*61890ccaSMoudy Ho int mdp_enum_fmt_mplane(struct v4l2_fmtdesc *f)
358*61890ccaSMoudy Ho {
359*61890ccaSMoudy Ho 	const struct mdp_format *fmt;
360*61890ccaSMoudy Ho 
361*61890ccaSMoudy Ho 	fmt = mdp_find_fmt_by_index(f->index, f->type);
362*61890ccaSMoudy Ho 	if (!fmt)
363*61890ccaSMoudy Ho 		return -EINVAL;
364*61890ccaSMoudy Ho 
365*61890ccaSMoudy Ho 	f->pixelformat = fmt->pixelformat;
366*61890ccaSMoudy Ho 	return 0;
367*61890ccaSMoudy Ho }
368*61890ccaSMoudy Ho 
369*61890ccaSMoudy Ho const struct mdp_format *mdp_try_fmt_mplane(struct v4l2_format *f,
370*61890ccaSMoudy Ho 					    struct mdp_frameparam *param,
371*61890ccaSMoudy Ho 					    u32 ctx_id)
372*61890ccaSMoudy Ho {
373*61890ccaSMoudy Ho 	struct device *dev = &param->ctx->mdp_dev->pdev->dev;
374*61890ccaSMoudy Ho 	struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;
375*61890ccaSMoudy Ho 	const struct mdp_format *fmt;
376*61890ccaSMoudy Ho 	const struct mdp_pix_limit *pix_limit;
377*61890ccaSMoudy Ho 	struct v4l2_frmsize_stepwise s;
378*61890ccaSMoudy Ho 	u32 org_w, org_h;
379*61890ccaSMoudy Ho 	unsigned int i;
380*61890ccaSMoudy Ho 
381*61890ccaSMoudy Ho 	fmt = mdp_find_fmt(pix_mp->pixelformat, f->type);
382*61890ccaSMoudy Ho 	if (!fmt) {
383*61890ccaSMoudy Ho 		fmt = mdp_find_fmt_by_index(0, f->type);
384*61890ccaSMoudy Ho 		if (!fmt) {
385*61890ccaSMoudy Ho 			dev_dbg(dev, "%d: pixelformat %c%c%c%c invalid", ctx_id,
386*61890ccaSMoudy Ho 				(pix_mp->pixelformat & 0xff),
387*61890ccaSMoudy Ho 				(pix_mp->pixelformat >>  8) & 0xff,
388*61890ccaSMoudy Ho 				(pix_mp->pixelformat >> 16) & 0xff,
389*61890ccaSMoudy Ho 				(pix_mp->pixelformat >> 24) & 0xff);
390*61890ccaSMoudy Ho 			return NULL;
391*61890ccaSMoudy Ho 		}
392*61890ccaSMoudy Ho 	}
393*61890ccaSMoudy Ho 
394*61890ccaSMoudy Ho 	pix_mp->field = V4L2_FIELD_NONE;
395*61890ccaSMoudy Ho 	pix_mp->flags = 0;
396*61890ccaSMoudy Ho 	pix_mp->pixelformat = fmt->pixelformat;
397*61890ccaSMoudy Ho 	if (V4L2_TYPE_IS_CAPTURE(f->type)) {
398*61890ccaSMoudy Ho 		pix_mp->colorspace = param->colorspace;
399*61890ccaSMoudy Ho 		pix_mp->xfer_func = param->xfer_func;
400*61890ccaSMoudy Ho 		pix_mp->ycbcr_enc = param->ycbcr_enc;
401*61890ccaSMoudy Ho 		pix_mp->quantization = param->quant;
402*61890ccaSMoudy Ho 	}
403*61890ccaSMoudy Ho 
404*61890ccaSMoudy Ho 	pix_limit = V4L2_TYPE_IS_OUTPUT(f->type) ? &param->limit->out_limit :
405*61890ccaSMoudy Ho 						&param->limit->cap_limit;
406*61890ccaSMoudy Ho 	s.min_width = pix_limit->wmin;
407*61890ccaSMoudy Ho 	s.max_width = pix_limit->wmax;
408*61890ccaSMoudy Ho 	s.step_width = fmt->walign;
409*61890ccaSMoudy Ho 	s.min_height = pix_limit->hmin;
410*61890ccaSMoudy Ho 	s.max_height = pix_limit->hmax;
411*61890ccaSMoudy Ho 	s.step_height = fmt->halign;
412*61890ccaSMoudy Ho 	org_w = pix_mp->width;
413*61890ccaSMoudy Ho 	org_h = pix_mp->height;
414*61890ccaSMoudy Ho 
415*61890ccaSMoudy Ho 	mdp_bound_align_image(&pix_mp->width, &pix_mp->height, &s, fmt->salign);
416*61890ccaSMoudy Ho 	if (org_w != pix_mp->width || org_h != pix_mp->height)
417*61890ccaSMoudy Ho 		dev_dbg(dev, "%d: size change: %ux%u to %ux%u", ctx_id,
418*61890ccaSMoudy Ho 			org_w, org_h, pix_mp->width, pix_mp->height);
419*61890ccaSMoudy Ho 
420*61890ccaSMoudy Ho 	if (pix_mp->num_planes && pix_mp->num_planes != fmt->num_planes)
421*61890ccaSMoudy Ho 		dev_dbg(dev, "%d num of planes change: %u to %u", ctx_id,
422*61890ccaSMoudy Ho 			pix_mp->num_planes, fmt->num_planes);
423*61890ccaSMoudy Ho 	pix_mp->num_planes = fmt->num_planes;
424*61890ccaSMoudy Ho 
425*61890ccaSMoudy Ho 	for (i = 0; i < pix_mp->num_planes; ++i) {
426*61890ccaSMoudy Ho 		u32 min_bpl = (pix_mp->width * fmt->row_depth[i]) >> 3;
427*61890ccaSMoudy Ho 		u32 max_bpl = (pix_limit->wmax * fmt->row_depth[i]) >> 3;
428*61890ccaSMoudy Ho 		u32 bpl = pix_mp->plane_fmt[i].bytesperline;
429*61890ccaSMoudy Ho 		u32 min_si, max_si;
430*61890ccaSMoudy Ho 		u32 si = pix_mp->plane_fmt[i].sizeimage;
431*61890ccaSMoudy Ho 
432*61890ccaSMoudy Ho 		bpl = clamp(bpl, min_bpl, max_bpl);
433*61890ccaSMoudy Ho 		pix_mp->plane_fmt[i].bytesperline = bpl;
434*61890ccaSMoudy Ho 
435*61890ccaSMoudy Ho 		min_si = (bpl * pix_mp->height * fmt->depth[i]) /
436*61890ccaSMoudy Ho 			 fmt->row_depth[i];
437*61890ccaSMoudy Ho 		max_si = (bpl * s.max_height * fmt->depth[i]) /
438*61890ccaSMoudy Ho 			 fmt->row_depth[i];
439*61890ccaSMoudy Ho 
440*61890ccaSMoudy Ho 		si = clamp(si, min_si, max_si);
441*61890ccaSMoudy Ho 		pix_mp->plane_fmt[i].sizeimage = si;
442*61890ccaSMoudy Ho 
443*61890ccaSMoudy Ho 		dev_dbg(dev, "%d: p%u, bpl:%u [%u, %u], sizeimage:%u [%u, %u]",
444*61890ccaSMoudy Ho 			ctx_id, i, bpl, min_bpl, max_bpl, si, min_si, max_si);
445*61890ccaSMoudy Ho 	}
446*61890ccaSMoudy Ho 
447*61890ccaSMoudy Ho 	return fmt;
448*61890ccaSMoudy Ho }
449*61890ccaSMoudy Ho 
450*61890ccaSMoudy Ho static int mdp_clamp_start(s32 *x, int min, int max, unsigned int align,
451*61890ccaSMoudy Ho 			   u32 flags)
452*61890ccaSMoudy Ho {
453*61890ccaSMoudy Ho 	if (flags & V4L2_SEL_FLAG_GE)
454*61890ccaSMoudy Ho 		max = *x;
455*61890ccaSMoudy Ho 	if (flags & V4L2_SEL_FLAG_LE)
456*61890ccaSMoudy Ho 		min = *x;
457*61890ccaSMoudy Ho 	return mdp_clamp_align(x, min, max, align);
458*61890ccaSMoudy Ho }
459*61890ccaSMoudy Ho 
460*61890ccaSMoudy Ho static int mdp_clamp_end(s32 *x, int min, int max, unsigned int align,
461*61890ccaSMoudy Ho 			 u32 flags)
462*61890ccaSMoudy Ho {
463*61890ccaSMoudy Ho 	if (flags & V4L2_SEL_FLAG_GE)
464*61890ccaSMoudy Ho 		min = *x;
465*61890ccaSMoudy Ho 	if (flags & V4L2_SEL_FLAG_LE)
466*61890ccaSMoudy Ho 		max = *x;
467*61890ccaSMoudy Ho 	return mdp_clamp_align(x, min, max, align);
468*61890ccaSMoudy Ho }
469*61890ccaSMoudy Ho 
470*61890ccaSMoudy Ho int mdp_try_crop(struct mdp_m2m_ctx *ctx, struct v4l2_rect *r,
471*61890ccaSMoudy Ho 		 const struct v4l2_selection *s, struct mdp_frame *frame)
472*61890ccaSMoudy Ho {
473*61890ccaSMoudy Ho 	struct device *dev = &ctx->mdp_dev->pdev->dev;
474*61890ccaSMoudy Ho 	s32 left, top, right, bottom;
475*61890ccaSMoudy Ho 	u32 framew, frameh, walign, halign;
476*61890ccaSMoudy Ho 	int ret;
477*61890ccaSMoudy Ho 
478*61890ccaSMoudy Ho 	dev_dbg(dev, "%d target:%d, set:(%d,%d) %ux%u", ctx->id,
479*61890ccaSMoudy Ho 		s->target, s->r.left, s->r.top, s->r.width, s->r.height);
480*61890ccaSMoudy Ho 
481*61890ccaSMoudy Ho 	left = s->r.left;
482*61890ccaSMoudy Ho 	top = s->r.top;
483*61890ccaSMoudy Ho 	right = s->r.left + s->r.width;
484*61890ccaSMoudy Ho 	bottom = s->r.top + s->r.height;
485*61890ccaSMoudy Ho 	framew = frame->format.fmt.pix_mp.width;
486*61890ccaSMoudy Ho 	frameh = frame->format.fmt.pix_mp.height;
487*61890ccaSMoudy Ho 
488*61890ccaSMoudy Ho 	if (mdp_target_is_crop(s->target)) {
489*61890ccaSMoudy Ho 		walign = 1;
490*61890ccaSMoudy Ho 		halign = 1;
491*61890ccaSMoudy Ho 	} else {
492*61890ccaSMoudy Ho 		walign = frame->mdp_fmt->walign;
493*61890ccaSMoudy Ho 		halign = frame->mdp_fmt->halign;
494*61890ccaSMoudy Ho 	}
495*61890ccaSMoudy Ho 
496*61890ccaSMoudy Ho 	dev_dbg(dev, "%d align:%u,%u, bound:%ux%u", ctx->id,
497*61890ccaSMoudy Ho 		walign, halign, framew, frameh);
498*61890ccaSMoudy Ho 
499*61890ccaSMoudy Ho 	ret = mdp_clamp_start(&left, 0, right, walign, s->flags);
500*61890ccaSMoudy Ho 	if (ret)
501*61890ccaSMoudy Ho 		return ret;
502*61890ccaSMoudy Ho 	ret = mdp_clamp_start(&top, 0, bottom, halign, s->flags);
503*61890ccaSMoudy Ho 	if (ret)
504*61890ccaSMoudy Ho 		return ret;
505*61890ccaSMoudy Ho 	ret = mdp_clamp_end(&right, left, framew, walign, s->flags);
506*61890ccaSMoudy Ho 	if (ret)
507*61890ccaSMoudy Ho 		return ret;
508*61890ccaSMoudy Ho 	ret = mdp_clamp_end(&bottom, top, frameh, halign, s->flags);
509*61890ccaSMoudy Ho 	if (ret)
510*61890ccaSMoudy Ho 		return ret;
511*61890ccaSMoudy Ho 
512*61890ccaSMoudy Ho 	r->left = left;
513*61890ccaSMoudy Ho 	r->top = top;
514*61890ccaSMoudy Ho 	r->width = right - left;
515*61890ccaSMoudy Ho 	r->height = bottom - top;
516*61890ccaSMoudy Ho 
517*61890ccaSMoudy Ho 	dev_dbg(dev, "%d crop:(%d,%d) %ux%u", ctx->id,
518*61890ccaSMoudy Ho 		r->left, r->top, r->width, r->height);
519*61890ccaSMoudy Ho 	return 0;
520*61890ccaSMoudy Ho }
521*61890ccaSMoudy Ho 
522*61890ccaSMoudy Ho int mdp_check_scaling_ratio(const struct v4l2_rect *crop,
523*61890ccaSMoudy Ho 			    const struct v4l2_rect *compose, s32 rotation,
524*61890ccaSMoudy Ho 	const struct mdp_limit *limit)
525*61890ccaSMoudy Ho {
526*61890ccaSMoudy Ho 	u32 crop_w, crop_h, comp_w, comp_h;
527*61890ccaSMoudy Ho 
528*61890ccaSMoudy Ho 	crop_w = crop->width;
529*61890ccaSMoudy Ho 	crop_h = crop->height;
530*61890ccaSMoudy Ho 	if (90 == rotation || 270 == rotation) {
531*61890ccaSMoudy Ho 		comp_w = compose->height;
532*61890ccaSMoudy Ho 		comp_h = compose->width;
533*61890ccaSMoudy Ho 	} else {
534*61890ccaSMoudy Ho 		comp_w = compose->width;
535*61890ccaSMoudy Ho 		comp_h = compose->height;
536*61890ccaSMoudy Ho 	}
537*61890ccaSMoudy Ho 
538*61890ccaSMoudy Ho 	if ((crop_w / comp_w) > limit->h_scale_down_max ||
539*61890ccaSMoudy Ho 	    (crop_h / comp_h) > limit->v_scale_down_max ||
540*61890ccaSMoudy Ho 	    (comp_w / crop_w) > limit->h_scale_up_max ||
541*61890ccaSMoudy Ho 	    (comp_h / crop_h) > limit->v_scale_up_max)
542*61890ccaSMoudy Ho 		return -ERANGE;
543*61890ccaSMoudy Ho 	return 0;
544*61890ccaSMoudy Ho }
545*61890ccaSMoudy Ho 
546*61890ccaSMoudy Ho /* Stride that is accepted by MDP HW */
547*61890ccaSMoudy Ho static u32 mdp_fmt_get_stride(const struct mdp_format *fmt,
548*61890ccaSMoudy Ho 			      u32 bytesperline, unsigned int plane)
549*61890ccaSMoudy Ho {
550*61890ccaSMoudy Ho 	enum mdp_color c = fmt->mdp_color;
551*61890ccaSMoudy Ho 	u32 stride;
552*61890ccaSMoudy Ho 
553*61890ccaSMoudy Ho 	stride = (bytesperline * MDP_COLOR_BITS_PER_PIXEL(c))
554*61890ccaSMoudy Ho 		/ fmt->row_depth[0];
555*61890ccaSMoudy Ho 	if (plane == 0)
556*61890ccaSMoudy Ho 		return stride;
557*61890ccaSMoudy Ho 	if (plane < MDP_COLOR_GET_PLANE_COUNT(c)) {
558*61890ccaSMoudy Ho 		if (MDP_COLOR_IS_BLOCK_MODE(c))
559*61890ccaSMoudy Ho 			stride = stride / 2;
560*61890ccaSMoudy Ho 		return stride;
561*61890ccaSMoudy Ho 	}
562*61890ccaSMoudy Ho 	return 0;
563*61890ccaSMoudy Ho }
564*61890ccaSMoudy Ho 
565*61890ccaSMoudy Ho /* Stride that is accepted by MDP HW of format with contiguous planes */
566*61890ccaSMoudy Ho static u32 mdp_fmt_get_stride_contig(const struct mdp_format *fmt,
567*61890ccaSMoudy Ho 				     u32 pix_stride, unsigned int plane)
568*61890ccaSMoudy Ho {
569*61890ccaSMoudy Ho 	enum mdp_color c = fmt->mdp_color;
570*61890ccaSMoudy Ho 	u32 stride = pix_stride;
571*61890ccaSMoudy Ho 
572*61890ccaSMoudy Ho 	if (plane == 0)
573*61890ccaSMoudy Ho 		return stride;
574*61890ccaSMoudy Ho 	if (plane < MDP_COLOR_GET_PLANE_COUNT(c)) {
575*61890ccaSMoudy Ho 		stride = stride >> MDP_COLOR_GET_H_SUBSAMPLE(c);
576*61890ccaSMoudy Ho 		if (MDP_COLOR_IS_UV_COPLANE(c) && !MDP_COLOR_IS_BLOCK_MODE(c))
577*61890ccaSMoudy Ho 			stride = stride * 2;
578*61890ccaSMoudy Ho 		return stride;
579*61890ccaSMoudy Ho 	}
580*61890ccaSMoudy Ho 	return 0;
581*61890ccaSMoudy Ho }
582*61890ccaSMoudy Ho 
583*61890ccaSMoudy Ho /* Plane size that is accepted by MDP HW */
584*61890ccaSMoudy Ho static u32 mdp_fmt_get_plane_size(const struct mdp_format *fmt,
585*61890ccaSMoudy Ho 				  u32 stride, u32 height, unsigned int plane)
586*61890ccaSMoudy Ho {
587*61890ccaSMoudy Ho 	enum mdp_color c = fmt->mdp_color;
588*61890ccaSMoudy Ho 	u32 bytesperline;
589*61890ccaSMoudy Ho 
590*61890ccaSMoudy Ho 	bytesperline = (stride * fmt->row_depth[0])
591*61890ccaSMoudy Ho 		/ MDP_COLOR_BITS_PER_PIXEL(c);
592*61890ccaSMoudy Ho 	if (plane == 0)
593*61890ccaSMoudy Ho 		return bytesperline * height;
594*61890ccaSMoudy Ho 	if (plane < MDP_COLOR_GET_PLANE_COUNT(c)) {
595*61890ccaSMoudy Ho 		height = height >> MDP_COLOR_GET_V_SUBSAMPLE(c);
596*61890ccaSMoudy Ho 		if (MDP_COLOR_IS_BLOCK_MODE(c))
597*61890ccaSMoudy Ho 			bytesperline = bytesperline * 2;
598*61890ccaSMoudy Ho 		return bytesperline * height;
599*61890ccaSMoudy Ho 	}
600*61890ccaSMoudy Ho 	return 0;
601*61890ccaSMoudy Ho }
602*61890ccaSMoudy Ho 
603*61890ccaSMoudy Ho static void mdp_prepare_buffer(struct img_image_buffer *b,
604*61890ccaSMoudy Ho 			       struct mdp_frame *frame, struct vb2_buffer *vb)
605*61890ccaSMoudy Ho {
606*61890ccaSMoudy Ho 	struct v4l2_pix_format_mplane *pix_mp = &frame->format.fmt.pix_mp;
607*61890ccaSMoudy Ho 	unsigned int i;
608*61890ccaSMoudy Ho 
609*61890ccaSMoudy Ho 	b->format.colorformat = frame->mdp_fmt->mdp_color;
610*61890ccaSMoudy Ho 	b->format.ycbcr_prof = frame->ycbcr_prof;
611*61890ccaSMoudy Ho 	for (i = 0; i < pix_mp->num_planes; ++i) {
612*61890ccaSMoudy Ho 		u32 stride = mdp_fmt_get_stride(frame->mdp_fmt,
613*61890ccaSMoudy Ho 			pix_mp->plane_fmt[i].bytesperline, i);
614*61890ccaSMoudy Ho 
615*61890ccaSMoudy Ho 		b->format.plane_fmt[i].stride = stride;
616*61890ccaSMoudy Ho 		b->format.plane_fmt[i].size =
617*61890ccaSMoudy Ho 			mdp_fmt_get_plane_size(frame->mdp_fmt, stride,
618*61890ccaSMoudy Ho 					       pix_mp->height, i);
619*61890ccaSMoudy Ho 		b->iova[i] = vb2_dma_contig_plane_dma_addr(vb, i);
620*61890ccaSMoudy Ho 	}
621*61890ccaSMoudy Ho 	for (; i < MDP_COLOR_GET_PLANE_COUNT(b->format.colorformat); ++i) {
622*61890ccaSMoudy Ho 		u32 stride = mdp_fmt_get_stride_contig(frame->mdp_fmt,
623*61890ccaSMoudy Ho 			b->format.plane_fmt[0].stride, i);
624*61890ccaSMoudy Ho 
625*61890ccaSMoudy Ho 		b->format.plane_fmt[i].stride = stride;
626*61890ccaSMoudy Ho 		b->format.plane_fmt[i].size =
627*61890ccaSMoudy Ho 			mdp_fmt_get_plane_size(frame->mdp_fmt, stride,
628*61890ccaSMoudy Ho 					       pix_mp->height, i);
629*61890ccaSMoudy Ho 		b->iova[i] = b->iova[i - 1] + b->format.plane_fmt[i - 1].size;
630*61890ccaSMoudy Ho 	}
631*61890ccaSMoudy Ho 	b->usage = frame->usage;
632*61890ccaSMoudy Ho }
633*61890ccaSMoudy Ho 
634*61890ccaSMoudy Ho void mdp_set_src_config(struct img_input *in,
635*61890ccaSMoudy Ho 			struct mdp_frame *frame, struct vb2_buffer *vb)
636*61890ccaSMoudy Ho {
637*61890ccaSMoudy Ho 	in->buffer.format.width = frame->format.fmt.pix_mp.width;
638*61890ccaSMoudy Ho 	in->buffer.format.height = frame->format.fmt.pix_mp.height;
639*61890ccaSMoudy Ho 	mdp_prepare_buffer(&in->buffer, frame, vb);
640*61890ccaSMoudy Ho }
641*61890ccaSMoudy Ho 
642*61890ccaSMoudy Ho static u32 mdp_to_fixed(u32 *r, struct v4l2_fract *f)
643*61890ccaSMoudy Ho {
644*61890ccaSMoudy Ho 	u32 q;
645*61890ccaSMoudy Ho 
646*61890ccaSMoudy Ho 	if (f->denominator == 0) {
647*61890ccaSMoudy Ho 		*r = 0;
648*61890ccaSMoudy Ho 		return 0;
649*61890ccaSMoudy Ho 	}
650*61890ccaSMoudy Ho 
651*61890ccaSMoudy Ho 	q = f->numerator / f->denominator;
652*61890ccaSMoudy Ho 	*r = div_u64(((u64)f->numerator - q * f->denominator) <<
653*61890ccaSMoudy Ho 		     IMG_SUBPIXEL_SHIFT, f->denominator);
654*61890ccaSMoudy Ho 	return q;
655*61890ccaSMoudy Ho }
656*61890ccaSMoudy Ho 
657*61890ccaSMoudy Ho static void mdp_set_src_crop(struct img_crop *c, struct mdp_crop *crop)
658*61890ccaSMoudy Ho {
659*61890ccaSMoudy Ho 	c->left = crop->c.left
660*61890ccaSMoudy Ho 		+ mdp_to_fixed(&c->left_subpix, &crop->left_subpix);
661*61890ccaSMoudy Ho 	c->top = crop->c.top
662*61890ccaSMoudy Ho 		+ mdp_to_fixed(&c->top_subpix, &crop->top_subpix);
663*61890ccaSMoudy Ho 	c->width = crop->c.width
664*61890ccaSMoudy Ho 		+ mdp_to_fixed(&c->width_subpix, &crop->width_subpix);
665*61890ccaSMoudy Ho 	c->height = crop->c.height
666*61890ccaSMoudy Ho 		+ mdp_to_fixed(&c->height_subpix, &crop->height_subpix);
667*61890ccaSMoudy Ho }
668*61890ccaSMoudy Ho 
669*61890ccaSMoudy Ho static void mdp_set_orientation(struct img_output *out,
670*61890ccaSMoudy Ho 				s32 rotation, bool hflip, bool vflip)
671*61890ccaSMoudy Ho {
672*61890ccaSMoudy Ho 	u8 flip = 0;
673*61890ccaSMoudy Ho 
674*61890ccaSMoudy Ho 	if (hflip)
675*61890ccaSMoudy Ho 		flip ^= 1;
676*61890ccaSMoudy Ho 	if (vflip) {
677*61890ccaSMoudy Ho 		/*
678*61890ccaSMoudy Ho 		 * A vertical flip is equivalent to
679*61890ccaSMoudy Ho 		 * a 180-degree rotation with a horizontal flip
680*61890ccaSMoudy Ho 		 */
681*61890ccaSMoudy Ho 		rotation += 180;
682*61890ccaSMoudy Ho 		flip ^= 1;
683*61890ccaSMoudy Ho 	}
684*61890ccaSMoudy Ho 
685*61890ccaSMoudy Ho 	out->rotation = rotation % 360;
686*61890ccaSMoudy Ho 	if (flip != 0)
687*61890ccaSMoudy Ho 		out->flags |= IMG_CTRL_FLAG_HFLIP;
688*61890ccaSMoudy Ho 	else
689*61890ccaSMoudy Ho 		out->flags &= ~IMG_CTRL_FLAG_HFLIP;
690*61890ccaSMoudy Ho }
691*61890ccaSMoudy Ho 
692*61890ccaSMoudy Ho void mdp_set_dst_config(struct img_output *out,
693*61890ccaSMoudy Ho 			struct mdp_frame *frame, struct vb2_buffer *vb)
694*61890ccaSMoudy Ho {
695*61890ccaSMoudy Ho 	out->buffer.format.width = frame->compose.width;
696*61890ccaSMoudy Ho 	out->buffer.format.height = frame->compose.height;
697*61890ccaSMoudy Ho 	mdp_prepare_buffer(&out->buffer, frame, vb);
698*61890ccaSMoudy Ho 	mdp_set_src_crop(&out->crop, &frame->crop);
699*61890ccaSMoudy Ho 	mdp_set_orientation(out, frame->rotation, frame->hflip, frame->vflip);
700*61890ccaSMoudy Ho }
701*61890ccaSMoudy Ho 
702*61890ccaSMoudy Ho int mdp_frameparam_init(struct mdp_frameparam *param)
703*61890ccaSMoudy Ho {
704*61890ccaSMoudy Ho 	struct mdp_frame *frame;
705*61890ccaSMoudy Ho 
706*61890ccaSMoudy Ho 	if (!param)
707*61890ccaSMoudy Ho 		return -EINVAL;
708*61890ccaSMoudy Ho 
709*61890ccaSMoudy Ho 	INIT_LIST_HEAD(&param->list);
710*61890ccaSMoudy Ho 	param->limit = &mdp_def_limit;
711*61890ccaSMoudy Ho 	param->type = MDP_STREAM_TYPE_BITBLT;
712*61890ccaSMoudy Ho 
713*61890ccaSMoudy Ho 	frame = &param->output;
714*61890ccaSMoudy Ho 	frame->format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
715*61890ccaSMoudy Ho 	frame->mdp_fmt = mdp_try_fmt_mplane(&frame->format, param, 0);
716*61890ccaSMoudy Ho 	frame->ycbcr_prof =
717*61890ccaSMoudy Ho 		mdp_map_ycbcr_prof_mplane(&frame->format,
718*61890ccaSMoudy Ho 					  frame->mdp_fmt->mdp_color);
719*61890ccaSMoudy Ho 	frame->usage = MDP_BUFFER_USAGE_HW_READ;
720*61890ccaSMoudy Ho 
721*61890ccaSMoudy Ho 	param->num_captures = 1;
722*61890ccaSMoudy Ho 	frame = &param->captures[0];
723*61890ccaSMoudy Ho 	frame->format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
724*61890ccaSMoudy Ho 	frame->mdp_fmt = mdp_try_fmt_mplane(&frame->format, param, 0);
725*61890ccaSMoudy Ho 	frame->ycbcr_prof =
726*61890ccaSMoudy Ho 		mdp_map_ycbcr_prof_mplane(&frame->format,
727*61890ccaSMoudy Ho 					  frame->mdp_fmt->mdp_color);
728*61890ccaSMoudy Ho 	frame->usage = MDP_BUFFER_USAGE_MDP;
729*61890ccaSMoudy Ho 	frame->crop.c.width = param->output.format.fmt.pix_mp.width;
730*61890ccaSMoudy Ho 	frame->crop.c.height = param->output.format.fmt.pix_mp.height;
731*61890ccaSMoudy Ho 	frame->compose.width = frame->format.fmt.pix_mp.width;
732*61890ccaSMoudy Ho 	frame->compose.height = frame->format.fmt.pix_mp.height;
733*61890ccaSMoudy Ho 
734*61890ccaSMoudy Ho 	return 0;
735*61890ccaSMoudy Ho }
736