xref: /OK3568_Linux_fs/kernel/drivers/video/rockchip/rga3/rga_policy.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) Rockchip Electronics Co., Ltd.
4  *
5  * Author: Huang Lee <Putin.li@rock-chips.com>
6  */
7 
8 #define pr_fmt(fmt) "rga_policy: " fmt
9 
10 #include "rga_job.h"
11 #include "rga_common.h"
12 #include "rga_hw_config.h"
13 #include "rga_debugger.h"
14 
15 #define GET_GCD(n1, n2) \
16 	({ \
17 		int i; \
18 		int gcd = 0; \
19 		for (i = 1; i <= (n1) && i <= (n2); i++) { \
20 			if ((n1) % i == 0 && (n2) % i == 0) \
21 				gcd = i; \
22 		} \
23 		gcd; \
24 	})
25 #define GET_LCM(n1, n2, gcd) (((n1) * (n2)) / gcd)
26 
rga_set_feature(struct rga_req * rga_base)27 static int rga_set_feature(struct rga_req *rga_base)
28 {
29 	int feature = 0;
30 
31 	if (rga_base->render_mode == COLOR_FILL_MODE)
32 		feature |= RGA_COLOR_FILL;
33 
34 	if (rga_base->render_mode == COLOR_PALETTE_MODE)
35 		feature |= RGA_COLOR_PALETTE;
36 
37 	if (rga_base->color_key_max > 0 || rga_base->color_key_min > 0)
38 		feature |= RGA_COLOR_KEY;
39 
40 	if ((rga_base->alpha_rop_flag >> 1) & 1)
41 		feature |= RGA_ROP_CALCULATE;
42 
43 	if ((rga_base->alpha_rop_flag >> 8) & 1)
44 		feature |= RGA_NN_QUANTIZE;
45 
46 	return feature;
47 }
48 
rga_check_resolution(const struct rga_rect_range * range,int width,int height)49 static bool rga_check_resolution(const struct rga_rect_range *range, int width, int height)
50 {
51 	if (width > range->max.width || height > range->max.height)
52 		return false;
53 
54 	if (width < range->min.width || height < range->min.height)
55 		return false;
56 
57 	return true;
58 }
59 
rga_check_format(const struct rga_hw_data * data,int rd_mode,int format,int win_num)60 static bool rga_check_format(const struct rga_hw_data *data,
61 		int rd_mode, int format, int win_num)
62 {
63 	int i;
64 	bool matched = false;
65 
66 	if (rd_mode == RGA_RASTER_MODE) {
67 		for (i = 0; i < data->win[win_num].num_of_raster_formats; i++) {
68 			if (format == data->win[win_num].raster_formats[i]) {
69 				matched = true;
70 				break;
71 			}
72 		}
73 	} else if (rd_mode == RGA_FBC_MODE) {
74 		for (i = 0; i < data->win[win_num].num_of_fbc_formats; i++) {
75 			if (format == data->win[win_num].fbc_formats[i]) {
76 				matched = true;
77 				break;
78 			}
79 		}
80 	} else if (rd_mode == RGA_TILE_MODE) {
81 		for (i = 0; i < data->win[win_num].num_of_tile_formats; i++) {
82 			if (format == data->win[win_num].tile_formats[i]) {
83 				matched = true;
84 				break;
85 			}
86 		}
87 	}
88 
89 	return matched;
90 }
91 
rga_check_align(uint32_t byte_stride_align,uint32_t format,uint16_t w_stride)92 static bool rga_check_align(uint32_t byte_stride_align, uint32_t format, uint16_t w_stride)
93 {
94 	int bit_stride, pixel_stride, align, gcd;
95 
96 	pixel_stride = rga_get_pixel_stride_from_format(format);
97 	if (pixel_stride <= 0)
98 		return false;
99 
100 	bit_stride = pixel_stride * w_stride;
101 
102 	if (bit_stride % (byte_stride_align * 8) == 0)
103 		return true;
104 
105 	if (DEBUGGER_EN(MSG)) {
106 		gcd = GET_GCD(pixel_stride, byte_stride_align * 8);
107 		align = GET_LCM(pixel_stride, byte_stride_align * 8, gcd) / pixel_stride;
108 		pr_info("unsupported width stride %d, 0x%x should be %d aligned!",
109 			w_stride, format, align);
110 	}
111 
112 	return false;
113 }
114 
rga_check_src0(const struct rga_hw_data * data,struct rga_img_info_t * src0)115 static bool rga_check_src0(const struct rga_hw_data *data,
116 			 struct rga_img_info_t *src0)
117 {
118 	if (!rga_check_resolution(&data->input_range, src0->act_w, src0->act_h))
119 		return false;
120 
121 	if (data == &rga3_data &&
122 	    !rga_check_resolution(&data->input_range,
123 				  src0->act_w + src0->x_offset,
124 				  src0->act_h + src0->y_offset))
125 		return false;
126 
127 	if (!rga_check_format(data, src0->rd_mode, src0->format, 0))
128 		return false;
129 
130 	if (!rga_check_align(data->byte_stride_align, src0->format, src0->vir_w))
131 		return false;
132 
133 	return true;
134 }
135 
rga_check_src1(const struct rga_hw_data * data,struct rga_img_info_t * src1)136 static bool rga_check_src1(const struct rga_hw_data *data,
137 			 struct rga_img_info_t *src1)
138 {
139 	if (!rga_check_resolution(&data->input_range, src1->act_w, src1->act_h))
140 		return false;
141 
142 	if (data == &rga3_data &&
143 	    !rga_check_resolution(&data->input_range,
144 				  src1->act_w + src1->x_offset,
145 				  src1->act_h + src1->y_offset))
146 		return false;
147 
148 	if (!rga_check_format(data, src1->rd_mode, src1->format, 1))
149 		return false;
150 
151 	if (!rga_check_align(data->byte_stride_align, src1->format, src1->vir_w))
152 		return false;
153 
154 	return true;
155 }
156 
rga_check_dst(const struct rga_hw_data * data,struct rga_img_info_t * dst)157 static bool rga_check_dst(const struct rga_hw_data *data,
158 			 struct rga_img_info_t *dst)
159 {
160 	if (!rga_check_resolution(&data->output_range, dst->act_w, dst->act_h))
161 		return false;
162 
163 	if (data == &rga3_data &&
164 	    !rga_check_resolution(&data->output_range,
165 				  dst->act_w + dst->x_offset,
166 				  dst->act_h + dst->y_offset))
167 		return false;
168 
169 	if (!rga_check_format(data, dst->rd_mode, dst->format, 2))
170 		return false;
171 
172 	if (!rga_check_align(data->byte_stride_align, dst->format, dst->vir_w))
173 		return false;
174 
175 	return true;
176 }
177 
rga_check_scale(const struct rga_hw_data * data,struct rga_req * rga_base)178 static bool rga_check_scale(const struct rga_hw_data *data,
179 				struct rga_req *rga_base)
180 {
181 	struct rga_img_info_t *src0 = &rga_base->src;
182 	struct rga_img_info_t *dst = &rga_base->dst;
183 
184 	int sw, sh;
185 	int dw, dh;
186 
187 	sw = src0->act_w;
188 	sh = src0->act_h;
189 
190 	if ((rga_base->sina == 65536 && rga_base->cosa == 0)
191 		|| (rga_base->sina == -65536 && rga_base->cosa == 0)) {
192 		dw = dst->act_h;
193 		dh = dst->act_w;
194 	} else {
195 		dw = dst->act_w;
196 		dh = dst->act_h;
197 	}
198 
199 	if (sw > dw) {
200 		if ((sw >> data->max_downscale_factor) > dw)
201 			return false;
202 	} else if (sw < dw) {
203 		if ((sw << data->max_upscale_factor) < dw)
204 			return false;
205 	}
206 
207 	if (sh > dh) {
208 		if ((sh >> data->max_downscale_factor) > dh)
209 			return false;
210 	} else if (sh < dh) {
211 		if ((sh << data->max_upscale_factor) < dh)
212 			return false;
213 	}
214 
215 	return true;
216 }
217 
rga_job_assign(struct rga_job * job)218 int rga_job_assign(struct rga_job *job)
219 {
220 	struct rga_img_info_t *src0 = &job->rga_command_base.src;
221 	struct rga_img_info_t *src1 = &job->rga_command_base.pat;
222 	struct rga_img_info_t *dst = &job->rga_command_base.dst;
223 
224 	struct rga_req *rga_base = &job->rga_command_base;
225 	const struct rga_hw_data *data;
226 	struct rga_scheduler_t *scheduler = NULL;
227 
228 	int feature;
229 	int core = RGA_NONE_CORE;
230 	int optional_cores = RGA_NONE_CORE;
231 	int specified_cores = RGA_NONE_CORE;
232 	int i;
233 	int min_of_job_count = -1;
234 	unsigned long flags;
235 
236 	/* assigned by userspace */
237 	if (rga_base->core > RGA_NONE_CORE) {
238 		if (rga_base->core > RGA_CORE_MASK) {
239 			pr_err("invalid setting core by user\n");
240 			goto finish;
241 		} else if (rga_base->core & RGA_CORE_MASK)
242 			specified_cores = rga_base->core;
243 	}
244 
245 	feature = rga_set_feature(rga_base);
246 
247 	/* function */
248 	for (i = 0; i < rga_drvdata->num_of_scheduler; i++) {
249 		data = rga_drvdata->scheduler[i]->data;
250 		scheduler = rga_drvdata->scheduler[i];
251 
252 		if ((specified_cores != RGA_NONE_CORE) &&
253 			(!(scheduler->core & specified_cores)))
254 			continue;
255 
256 		if (DEBUGGER_EN(MSG))
257 			pr_info("start policy on core = %d", scheduler->core);
258 
259 		if (scheduler->data->mmu == RGA_MMU &&
260 		    job->flags & RGA_JOB_UNSUPPORT_RGA_MMU) {
261 			if (DEBUGGER_EN(MSG))
262 				pr_info("RGA2 only support under 4G memory!\n");
263 			continue;
264 		}
265 
266 		if (feature > 0) {
267 			if (!(feature & data->feature)) {
268 				if (DEBUGGER_EN(MSG))
269 					pr_info("core = %d, break on feature",
270 						scheduler->core);
271 				continue;
272 			}
273 		}
274 
275 		/* only colorfill need single win (colorpalette?) */
276 		if (!(feature & 1)) {
277 			if (src1->yrgb_addr > 0) {
278 				if ((!(src0->rd_mode & data->win[0].rd_mode)) ||
279 					(!(src1->rd_mode & data->win[1].rd_mode)) ||
280 					(!(dst->rd_mode & data->win[2].rd_mode))) {
281 					if (DEBUGGER_EN(MSG))
282 						pr_info("core = %d, ABC break on rd_mode",
283 							scheduler->core);
284 					continue;
285 				}
286 			} else {
287 				if ((!(src0->rd_mode & data->win[0].rd_mode)) ||
288 					(!(dst->rd_mode & data->win[2].rd_mode))) {
289 					if (DEBUGGER_EN(MSG))
290 						pr_info("core = %d, ABB break on rd_mode",
291 							scheduler->core);
292 					continue;
293 				}
294 			}
295 
296 			if (!rga_check_scale(data, rga_base)) {
297 				if (DEBUGGER_EN(MSG))
298 					pr_info("core = %d, break on rga_check_scale",
299 						scheduler->core);
300 				continue;
301 			}
302 
303 			if (!rga_check_src0(data, src0)) {
304 				if (DEBUGGER_EN(MSG))
305 					pr_info("core = %d, break on rga_check_src0",
306 						scheduler->core);
307 				continue;
308 			}
309 
310 			if (src1->yrgb_addr > 0) {
311 				if (!rga_check_src1(data, src1)) {
312 					if (DEBUGGER_EN(MSG))
313 						pr_info("core = %d, break on rga_check_src1",
314 							scheduler->core);
315 					continue;
316 				}
317 			}
318 		}
319 
320 		if (!rga_check_dst(data, dst)) {
321 			if (DEBUGGER_EN(MSG))
322 				pr_info("core = %d, break on rga_check_dst",
323 					scheduler->core);
324 			continue;
325 		}
326 
327 		optional_cores |= scheduler->core;
328 	}
329 
330 	if (DEBUGGER_EN(MSG))
331 		pr_info("optional_cores = %d\n", optional_cores);
332 
333 	if (optional_cores == 0) {
334 		core = -1;
335 		pr_err("invalid function policy\n");
336 		goto finish;
337 	}
338 
339 	for (i = 0; i < rga_drvdata->num_of_scheduler; i++) {
340 		scheduler = rga_drvdata->scheduler[i];
341 
342 		if (optional_cores & scheduler->core) {
343 			spin_lock_irqsave(&scheduler->irq_lock, flags);
344 
345 			if (scheduler->running_job == NULL) {
346 				core = scheduler->core;
347 				job->scheduler = scheduler;
348 				spin_unlock_irqrestore(&scheduler->irq_lock,
349 							 flags);
350 				break;
351 			} else {
352 				if ((min_of_job_count == -1) ||
353 				    (min_of_job_count > scheduler->job_count)) {
354 					min_of_job_count = scheduler->job_count;
355 					core = scheduler->core;
356 					job->scheduler = scheduler;
357 				}
358 			}
359 
360 			spin_unlock_irqrestore(&scheduler->irq_lock, flags);
361 		}
362 	}
363 
364 	/* TODO: need consider full load */
365 finish:
366 	if (DEBUGGER_EN(MSG))
367 		pr_info("assign core: %d\n", core);
368 
369 	return core;
370 }
371