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