• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_hw_config.h"
12 
rga_set_feature(struct rga_req * rga_base)13 static int rga_set_feature(struct rga_req *rga_base)
14 {
15 	int feature = 0;
16 
17 	if (rga_base->render_mode == COLOR_FILL_MODE)
18 		feature |= RGA_COLOR_FILL;
19 
20 	if (rga_base->render_mode == COLOR_PALETTE_MODE)
21 		feature |= RGA_COLOR_PALETTE;
22 
23 	if (rga_base->color_key_max > 0 || rga_base->color_key_min > 0)
24 		feature |= RGA_COLOR_KEY;
25 
26 	if ((rga_base->alpha_rop_flag >> 1) & 1)
27 		feature |= RGA_ROP_CALCULATE;
28 
29 	if ((rga_base->alpha_rop_flag >> 8) & 1)
30 		feature |= RGA_NN_QUANTIZE;
31 
32 	return feature;
33 }
34 
rga_check_format(const struct rga_hw_data * data,int rd_mode,int format,int win_num)35 static bool rga_check_format(const struct rga_hw_data *data,
36 		int rd_mode, int format, int win_num)
37 {
38 	int i;
39 	bool matched = false;
40 
41 	if (rd_mode == RGA_RASTER_MODE) {
42 		for (i = 0; i < data->win[win_num].num_of_raster_formats; i++) {
43 			if (format == data->win[win_num].raster_formats[i]) {
44 				matched = true;
45 				break;
46 			}
47 		}
48 	} else if (rd_mode == RGA_FBC_MODE) {
49 		for (i = 0; i < data->win[win_num].num_of_fbc_formats; i++) {
50 			if (format == data->win[win_num].fbc_formats[i]) {
51 				matched = true;
52 				break;
53 			}
54 		}
55 	} else if (rd_mode == RGA_TILE_MODE) {
56 		for (i = 0; i < data->win[win_num].num_of_tile_formats; i++) {
57 			if (format == data->win[win_num].tile_formats[i]) {
58 				matched = true;
59 				break;
60 			}
61 		}
62 	}
63 
64 	return matched;
65 }
66 
rga_check_src0(const struct rga_hw_data * data,struct rga_img_info_t * src0)67 static bool rga_check_src0(const struct rga_hw_data *data,
68 			 struct rga_img_info_t *src0)
69 {
70 	int format;
71 
72 	user_format_convert(&format, src0->format);
73 
74 	if (src0->act_w < data->min_input.w ||
75 		src0->act_h < data->min_input.h)
76 		return false;
77 
78 	if (src0->act_w > data->max_input.w ||
79 		src0->act_h > data->max_input.h)
80 		return false;
81 
82 	if (!rga_check_format(data, src0->rd_mode, format, 0))
83 		return false;
84 
85 	return true;
86 }
87 
rga_check_src1(const struct rga_hw_data * data,struct rga_img_info_t * src1)88 static bool rga_check_src1(const struct rga_hw_data *data,
89 			 struct rga_img_info_t *src1)
90 {
91 	int format;
92 
93 	user_format_convert(&format, src1->format);
94 
95 	if (src1->act_w < data->min_input.w ||
96 		src1->act_h < data->min_input.h)
97 		return false;
98 
99 	if (src1->act_w > data->max_input.w ||
100 		src1->act_h > data->max_input.h)
101 		return false;
102 
103 	if (!rga_check_format(data, src1->rd_mode, format, 1))
104 		return false;
105 
106 	return true;
107 }
108 
rga_check_dst(const struct rga_hw_data * data,struct rga_img_info_t * dst)109 static bool rga_check_dst(const struct rga_hw_data *data,
110 			 struct rga_img_info_t *dst)
111 {
112 	int format;
113 
114 	user_format_convert(&format, dst->format);
115 
116 	if (dst->act_w < data->min_output.w ||
117 		dst->act_h < data->min_output.h)
118 		return false;
119 
120 	if (dst->act_w > data->max_output.w ||
121 		dst->act_h > data->max_output.h)
122 		return false;
123 
124 	if (!rga_check_format(data, dst->rd_mode, format, 2))
125 		return false;
126 
127 	return true;
128 }
129 
rga_check_scale(const struct rga_hw_data * data,struct rga_req * rga_base)130 static bool rga_check_scale(const struct rga_hw_data *data,
131 				struct rga_req *rga_base)
132 {
133 	struct rga_img_info_t *src0 = &rga_base->src;
134 	struct rga_img_info_t *dst = &rga_base->dst;
135 
136 	int sw, sh;
137 	int dw, dh;
138 
139 	sw = src0->act_w;
140 	sh = src0->act_h;
141 
142 	if ((rga_base->sina == 65536 && rga_base->cosa == 0)
143 		|| (rga_base->sina == -65536 && rga_base->cosa == 0)) {
144 		dw = dst->act_h;
145 		dh = dst->act_w;
146 	} else {
147 		dw = dst->act_w;
148 		dh = dst->act_h;
149 	}
150 
151 	if (sw > dw) {
152 		if ((sw >> data->max_downscale_factor) > dw)
153 			return false;
154 	} else if (sw < dw) {
155 		if ((sw << data->max_upscale_factor) < dw)
156 			return false;
157 	}
158 
159 	if (sh > dh) {
160 		if ((sh >> data->max_downscale_factor) > dh)
161 			return false;
162 	} else if (sh < dh) {
163 		if ((sh << data->max_upscale_factor) < dh)
164 			return false;
165 	}
166 
167 	return true;
168 }
169 
rga_job_assign(struct rga_job * job)170 int rga_job_assign(struct rga_job *job)
171 {
172 	struct rga_img_info_t *src0 = &job->rga_command_base.src;
173 	struct rga_img_info_t *src1 = &job->rga_command_base.pat;
174 	struct rga_img_info_t *dst = &job->rga_command_base.dst;
175 
176 	struct rga_req *rga_base = &job->rga_command_base;
177 	const struct rga_hw_data *data;
178 	struct rga_scheduler_t *scheduler = NULL;
179 
180 	int feature;
181 	int core = RGA_NONE_CORE;
182 	int optional_cores = RGA_NONE_CORE;
183 	int i;
184 	int min_of_job_count = 0;
185 	unsigned long flags;
186 
187 	/* assigned by userspace */
188 	if (rga_base->core > RGA_NONE_CORE) {
189 		if (rga_base->core > RGA_CORE_MASK) {
190 			pr_err("invalid setting core by user\n");
191 			goto finish;
192 		} else if (rga_base->core & RGA_CORE_MASK) {
193 			optional_cores = rga_base->core;
194 			goto skip_functional_policy;
195 		}
196 	}
197 
198 	feature = rga_set_feature(rga_base);
199 
200 	/* function */
201 	for (i = 0; i < rga_drvdata->num_of_scheduler; i++) {
202 		data = rga_drvdata->rga_scheduler[i]->data;
203 		scheduler = rga_drvdata->rga_scheduler[i];
204 
205 		if (DEBUGGER_EN(MSG))
206 			pr_err("start policy on core = %d", scheduler->core);
207 
208 		if (scheduler->core == RGA2_SCHEDULER_CORE0 &&
209 		    job->flags & RGA_JOB_UNSUPPORT_RGA2) {
210 			if (DEBUGGER_EN(MSG))
211 				pr_debug("RGA2 only support under 4G memory!\n");
212 				continue;
213 		}
214 
215 		if (feature > 0) {
216 			if (!(feature & data->feature)) {
217 				if (DEBUGGER_EN(MSG))
218 					pr_err("core = %d, break on feature",
219 						scheduler->core);
220 				continue;
221 			}
222 		}
223 
224 		/* only colorfill need single win (colorpalette?) */
225 		if (!(feature & 1)) {
226 			if (src1->yrgb_addr > 0) {
227 				if ((!(src0->rd_mode & data->win[0].rd_mode)) ||
228 					(!(src1->rd_mode & data->win[1].rd_mode)) ||
229 					(!(dst->rd_mode & data->win[2].rd_mode))) {
230 					if (DEBUGGER_EN(MSG))
231 						pr_err("core = %d, ABC break on rd_mode",
232 							scheduler->core);
233 					continue;
234 				}
235 			} else {
236 				if ((!(src0->rd_mode & data->win[0].rd_mode)) ||
237 					(!(dst->rd_mode & data->win[2].rd_mode))) {
238 					if (DEBUGGER_EN(MSG))
239 						pr_err("core = %d, ABB break on rd_mode",
240 							scheduler->core);
241 					continue;
242 				}
243 			}
244 
245 			if (!rga_check_scale(data, rga_base)) {
246 				if (DEBUGGER_EN(MSG))
247 					pr_err("core = %d, break on rga_check_scale",
248 						scheduler->core);
249 				continue;
250 			}
251 
252 			if (!rga_check_src0(data, src0)) {
253 				if (DEBUGGER_EN(MSG))
254 					pr_err("core = %d, break on rga_check_src0",
255 						scheduler->core);
256 				continue;
257 			}
258 
259 			if (src1->yrgb_addr > 0) {
260 				if (!rga_check_src1(data, src1)) {
261 					if (DEBUGGER_EN(MSG))
262 						pr_err("core = %d, break on rga_check_src1",
263 						scheduler->core);
264 					continue;
265 				}
266 			}
267 		}
268 
269 		if (!rga_check_dst(data, dst)) {
270 			if (DEBUGGER_EN(MSG))
271 				pr_err("core = %d, break on rga_check_dst",
272 					scheduler->core);
273 			continue;
274 		}
275 
276 		optional_cores |= scheduler->core;
277 	}
278 
279 	if (DEBUGGER_EN(MSG))
280 		pr_info("optional_cores = %d\n", optional_cores);
281 
282 	if (optional_cores == 0) {
283 		core = -1;
284 		pr_err("invalid function policy\n");
285 		goto finish;
286 	}
287 
288 skip_functional_policy:
289 	for (i = 0; i < rga_drvdata->num_of_scheduler; i++) {
290 		scheduler = rga_drvdata->rga_scheduler[i];
291 
292 		if (optional_cores & scheduler->core) {
293 			spin_lock_irqsave(&scheduler->irq_lock, flags);
294 
295 			if (scheduler->running_job == NULL) {
296 				core = scheduler->core;
297 				spin_unlock_irqrestore(&scheduler->irq_lock,
298 							 flags);
299 				break;
300 			} else {
301 				if ((min_of_job_count > scheduler->job_count) ||
302 					(min_of_job_count == 0)) {
303 					min_of_job_count = scheduler->job_count;
304 					core = scheduler->core;
305 				}
306 			}
307 
308 			spin_unlock_irqrestore(&scheduler->irq_lock, flags);
309 		}
310 	}
311 
312 	/* TODO: need consider full load */
313 finish:
314 	if (DEBUGGER_EN(MSG))
315 		pr_info("assign core: %d\n", core);
316 
317 	return core;
318 }