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 }