1
2
3
4#include <linux/device.h>
5
6#include "ipu3-css.h"
7#include "ipu3-css-fw.h"
8#include "ipu3-tables.h"
9#include "ipu3-css-params.h"
10
11#define DIV_ROUND_CLOSEST_DOWN(a, b) (((a) + ((b) / 2) - 1) / (b))
12#define roundclosest_down(a, b) (DIV_ROUND_CLOSEST_DOWN(a, b) * (b))
13
14#define IPU3_UAPI_ANR_MAX_RESET ((1 << 12) - 1)
15#define IPU3_UAPI_ANR_MIN_RESET (((-1) << 12) + 1)
16
17struct imgu_css_scaler_info {
18 unsigned int phase_step;
19 int exp_shift;
20
21 unsigned int phase_init;
22 int pad_left;
23 int pad_right;
24 int crop_left;
25 int crop_top;
26};
27
28static unsigned int imgu_css_scaler_get_exp(unsigned int counter,
29 unsigned int divider)
30{
31 int i = fls(divider) - fls(counter);
32
33 if (i <= 0)
34 return 0;
35
36 if (divider >> i < counter)
37 i = i - 1;
38
39 return i;
40}
41
42
43static void
44imgu_css_scaler_setup_lut(unsigned int taps, unsigned int input_width,
45 unsigned int output_width, int phase_step_correction,
46 const int *coeffs, unsigned int coeffs_size,
47 s8 coeff_lut[], struct imgu_css_scaler_info *info)
48{
49 int tap, phase, phase_sum_left, phase_sum_right;
50 int exponent = imgu_css_scaler_get_exp(output_width, input_width);
51 int mantissa = (1 << exponent) * output_width;
52 unsigned int phase_step, phase_taps;
53
54 if (input_width == output_width) {
55 for (phase = 0; phase < IMGU_SCALER_PHASES; phase++) {
56 phase_taps = phase * IMGU_SCALER_FILTER_TAPS;
57 for (tap = 0; tap < taps; tap++)
58 coeff_lut[phase_taps + tap] = 0;
59 }
60
61 info->phase_step = IMGU_SCALER_PHASES *
62 (1 << IMGU_SCALER_PHASE_COUNTER_PREC_REF);
63 info->exp_shift = 0;
64 info->pad_left = 0;
65 info->pad_right = 0;
66 info->phase_init = 0;
67 info->crop_left = 0;
68 info->crop_top = 0;
69 return;
70 }
71
72 for (phase = 0; phase < IMGU_SCALER_PHASES; phase++) {
73 phase_taps = phase * IMGU_SCALER_FILTER_TAPS;
74 for (tap = 0; tap < taps; tap++) {
75
76 s64 coeff = coeffs[coeffs_size -
77 ((tap * (coeffs_size / taps)) + phase) - 1];
78 coeff *= mantissa;
79 coeff = div64_long(coeff, input_width);
80
81
82 coeff += 1 << (IMGU_SCALER_COEFF_BITS - 1);
83 coeff >>= IMGU_SCALER_COEFF_BITS;
84 coeff_lut[phase_taps + tap] = coeff;
85 }
86 }
87
88 phase_step = IMGU_SCALER_PHASES *
89 (1 << IMGU_SCALER_PHASE_COUNTER_PREC_REF) *
90 output_width / input_width;
91 phase_step += phase_step_correction;
92 phase_sum_left = (taps / 2 * IMGU_SCALER_PHASES *
93 (1 << IMGU_SCALER_PHASE_COUNTER_PREC_REF)) -
94 (1 << (IMGU_SCALER_PHASE_COUNTER_PREC_REF - 1));
95 phase_sum_right = (taps / 2 * IMGU_SCALER_PHASES *
96 (1 << IMGU_SCALER_PHASE_COUNTER_PREC_REF)) +
97 (1 << (IMGU_SCALER_PHASE_COUNTER_PREC_REF - 1));
98
99 info->exp_shift = IMGU_SCALER_MAX_EXPONENT_SHIFT - exponent;
100 info->pad_left = (phase_sum_left % phase_step == 0) ?
101 phase_sum_left / phase_step - 1 : phase_sum_left / phase_step;
102 info->pad_right = (phase_sum_right % phase_step == 0) ?
103 phase_sum_right / phase_step - 1 : phase_sum_right / phase_step;
104 info->phase_init = phase_sum_left - phase_step * info->pad_left;
105 info->phase_step = phase_step;
106 info->crop_left = taps - 1;
107 info->crop_top = taps - 1;
108}
109
110
111
112
113
114static unsigned int
115imgu_css_scaler_calc_scaled_output(unsigned int input,
116 struct imgu_css_scaler_info *info)
117{
118 unsigned int arg1 = input * info->phase_step +
119 (1 - IMGU_SCALER_TAPS_Y / 2) * IMGU_SCALER_FIR_PHASES -
120 IMGU_SCALER_FIR_PHASES / (2 * IMGU_SCALER_PHASES);
121 unsigned int arg2 = ((IMGU_SCALER_TAPS_Y / 2) * IMGU_SCALER_FIR_PHASES +
122 IMGU_SCALER_FIR_PHASES / (2 * IMGU_SCALER_PHASES)) *
123 IMGU_SCALER_FIR_PHASES + info->phase_step / 2;
124
125 return ((arg1 + (arg2 - IMGU_SCALER_FIR_PHASES * info->phase_step) /
126 IMGU_SCALER_FIR_PHASES) / (2 * IMGU_SCALER_FIR_PHASES)) * 2;
127}
128
129
130
131
132
133static void
134imgu_css_scaler_calc(u32 input_width, u32 input_height, u32 target_width,
135 u32 target_height, struct imgu_abi_osys_config *cfg,
136 struct imgu_css_scaler_info *info_luma,
137 struct imgu_css_scaler_info *info_chroma,
138 unsigned int *output_width, unsigned int *output_height,
139 unsigned int *procmode)
140{
141 u32 out_width = target_width;
142 u32 out_height = target_height;
143 const unsigned int height_alignment = 2;
144 int phase_step_correction = -1;
145
146
147
148
149
150
151 if (target_height * input_width > target_width * input_height)
152 target_width = DIV_ROUND_UP(target_height * input_width,
153 input_height);
154
155 if (input_width == target_width)
156 *procmode = IMGU_ABI_OSYS_PROCMODE_BYPASS;
157 else
158 *procmode = IMGU_ABI_OSYS_PROCMODE_DOWNSCALE;
159
160 memset(&cfg->scaler_coeffs_chroma, 0,
161 sizeof(cfg->scaler_coeffs_chroma));
162 memset(&cfg->scaler_coeffs_luma, 0, sizeof(cfg->scaler_coeffs_luma));
163 do {
164 phase_step_correction++;
165
166 imgu_css_scaler_setup_lut(IMGU_SCALER_TAPS_Y,
167 input_width, target_width,
168 phase_step_correction,
169 imgu_css_downscale_4taps,
170 IMGU_SCALER_DOWNSCALE_4TAPS_LEN,
171 cfg->scaler_coeffs_luma, info_luma);
172
173 imgu_css_scaler_setup_lut(IMGU_SCALER_TAPS_UV,
174 input_width, target_width,
175 phase_step_correction,
176 imgu_css_downscale_2taps,
177 IMGU_SCALER_DOWNSCALE_2TAPS_LEN,
178 cfg->scaler_coeffs_chroma,
179 info_chroma);
180
181 out_width = imgu_css_scaler_calc_scaled_output(input_width,
182 info_luma);
183 out_height = imgu_css_scaler_calc_scaled_output(input_height,
184 info_luma);
185 } while ((out_width < target_width || out_height < target_height ||
186 !IS_ALIGNED(out_height, height_alignment)) &&
187 phase_step_correction <= 5);
188
189 *output_width = out_width;
190 *output_height = out_height;
191}
192
193
194
195static void imgu_css_osys_set_format(enum imgu_abi_frame_format host_format,
196 unsigned int *osys_format,
197 unsigned int *osys_tiling)
198{
199 *osys_format = IMGU_ABI_OSYS_FORMAT_YUV420;
200 *osys_tiling = IMGU_ABI_OSYS_TILING_NONE;
201
202 switch (host_format) {
203 case IMGU_ABI_FRAME_FORMAT_YUV420:
204 *osys_format = IMGU_ABI_OSYS_FORMAT_YUV420;
205 break;
206 case IMGU_ABI_FRAME_FORMAT_YV12:
207 *osys_format = IMGU_ABI_OSYS_FORMAT_YV12;
208 break;
209 case IMGU_ABI_FRAME_FORMAT_NV12:
210 *osys_format = IMGU_ABI_OSYS_FORMAT_NV12;
211 break;
212 case IMGU_ABI_FRAME_FORMAT_NV16:
213 *osys_format = IMGU_ABI_OSYS_FORMAT_NV16;
214 break;
215 case IMGU_ABI_FRAME_FORMAT_NV21:
216 *osys_format = IMGU_ABI_OSYS_FORMAT_NV21;
217 break;
218 case IMGU_ABI_FRAME_FORMAT_NV12_TILEY:
219 *osys_format = IMGU_ABI_OSYS_FORMAT_NV12;
220 *osys_tiling = IMGU_ABI_OSYS_TILING_Y;
221 break;
222 default:
223
224 break;
225 }
226}
227
228
229
230
231
232static int imgu_css_osys_calc_stripe_offset(int stripe_offset_out,
233 int fir_phases, int phase_init,
234 int phase_step, int pad_left)
235{
236 int stripe_offset_inp = stripe_offset_out * fir_phases -
237 pad_left * phase_step;
238
239 return DIV_ROUND_UP(stripe_offset_inp - phase_init, phase_step);
240}
241
242
243
244
245
246static int imgu_css_osys_calc_stripe_phase_init(int stripe_offset_out,
247 int fir_phases, int phase_init,
248 int phase_step, int pad_left)
249{
250 int stripe_offset_inp =
251 imgu_css_osys_calc_stripe_offset(stripe_offset_out,
252 fir_phases, phase_init,
253 phase_step, pad_left);
254
255 return phase_init + ((pad_left + stripe_offset_inp) * phase_step) -
256 stripe_offset_out * fir_phases;
257}
258
259
260
261
262
263static int imgu_css_osys_calc_inp_stripe_width(int stripe_width_out,
264 int fir_phases, int phase_init,
265 int phase_step, int fir_taps,
266 int pad_left, int pad_right)
267{
268 int stripe_width_inp = (stripe_width_out + fir_taps - 1) * fir_phases;
269
270 stripe_width_inp = DIV_ROUND_UP(stripe_width_inp - phase_init,
271 phase_step);
272
273 return stripe_width_inp - pad_left - pad_right;
274}
275
276
277
278
279
280static int imgu_css_osys_out_stripe_width(int stripe_width_inp, int fir_phases,
281 int phase_init, int phase_step,
282 int fir_taps, int pad_left,
283 int pad_right, int column_offset)
284{
285 int stripe_width_out = (pad_left + stripe_width_inp +
286 pad_right - column_offset) * phase_step;
287
288 stripe_width_out = (stripe_width_out + phase_init) / fir_phases;
289
290 return stripe_width_out - (fir_taps - 1);
291}
292
293struct imgu_css_reso {
294 unsigned int input_width;
295 unsigned int input_height;
296 enum imgu_abi_frame_format input_format;
297 unsigned int pin_width[IMGU_ABI_OSYS_PINS];
298 unsigned int pin_height[IMGU_ABI_OSYS_PINS];
299 unsigned int pin_stride[IMGU_ABI_OSYS_PINS];
300 enum imgu_abi_frame_format pin_format[IMGU_ABI_OSYS_PINS];
301 int chunk_width;
302 int chunk_height;
303 int block_height;
304 int block_width;
305};
306
307struct imgu_css_frame_params {
308
309 unsigned int enable;
310 unsigned int format;
311 unsigned int flip;
312 unsigned int mirror;
313 unsigned int tiling;
314 unsigned int reduce_range;
315 unsigned int width;
316 unsigned int height;
317 unsigned int stride;
318 unsigned int scaled;
319 unsigned int crop_left;
320 unsigned int crop_top;
321};
322
323struct imgu_css_stripe_params {
324 unsigned int processing_mode;
325 unsigned int phase_step;
326 unsigned int exp_shift;
327 unsigned int phase_init_left_y;
328 unsigned int phase_init_left_uv;
329 unsigned int phase_init_top_y;
330 unsigned int phase_init_top_uv;
331 unsigned int pad_left_y;
332 unsigned int pad_left_uv;
333 unsigned int pad_right_y;
334 unsigned int pad_right_uv;
335 unsigned int pad_top_y;
336 unsigned int pad_top_uv;
337 unsigned int pad_bottom_y;
338 unsigned int pad_bottom_uv;
339 unsigned int crop_left_y;
340 unsigned int crop_top_y;
341 unsigned int crop_left_uv;
342 unsigned int crop_top_uv;
343 unsigned int start_column_y;
344 unsigned int start_column_uv;
345 unsigned int chunk_width;
346 unsigned int chunk_height;
347 unsigned int block_width;
348 unsigned int block_height;
349 unsigned int input_width;
350 unsigned int input_height;
351 int output_width[IMGU_ABI_OSYS_PINS];
352 int output_height[IMGU_ABI_OSYS_PINS];
353 int output_offset[IMGU_ABI_OSYS_PINS];
354};
355
356
357
358
359
360static int imgu_css_osys_calc_frame_and_stripe_params(
361 struct imgu_css *css, unsigned int stripes,
362 struct imgu_abi_osys_config *osys,
363 struct imgu_css_scaler_info *scaler_luma,
364 struct imgu_css_scaler_info *scaler_chroma,
365 struct imgu_css_frame_params frame_params[],
366 struct imgu_css_stripe_params stripe_params[],
367 unsigned int pipe)
368{
369 struct imgu_css_reso reso;
370 unsigned int output_width, pin, s;
371 u32 input_width, input_height, target_width, target_height;
372 unsigned int procmode = 0;
373 struct imgu_css_pipe *css_pipe = &css->pipes[pipe];
374
375 input_width = css_pipe->rect[IPU3_CSS_RECT_GDC].width;
376 input_height = css_pipe->rect[IPU3_CSS_RECT_GDC].height;
377 target_width = css_pipe->queue[IPU3_CSS_QUEUE_VF].fmt.mpix.width;
378 target_height = css_pipe->queue[IPU3_CSS_QUEUE_VF].fmt.mpix.height;
379
380
381
382
383 reso.input_width = css_pipe->rect[IPU3_CSS_RECT_GDC].width;
384
385
386 reso.input_height = css_pipe->rect[IPU3_CSS_RECT_GDC].height;
387
388 reso.input_format =
389 css_pipe->queue[IPU3_CSS_QUEUE_OUT].css_fmt->frame_format;
390
391 reso.pin_width[IMGU_ABI_OSYS_PIN_OUT] =
392 css_pipe->queue[IPU3_CSS_QUEUE_OUT].fmt.mpix.width;
393 reso.pin_height[IMGU_ABI_OSYS_PIN_OUT] =
394 css_pipe->queue[IPU3_CSS_QUEUE_OUT].fmt.mpix.height;
395 reso.pin_stride[IMGU_ABI_OSYS_PIN_OUT] =
396 css_pipe->queue[IPU3_CSS_QUEUE_OUT].width_pad;
397 reso.pin_format[IMGU_ABI_OSYS_PIN_OUT] =
398 css_pipe->queue[IPU3_CSS_QUEUE_OUT].css_fmt->frame_format;
399
400 reso.pin_width[IMGU_ABI_OSYS_PIN_VF] =
401 css_pipe->queue[IPU3_CSS_QUEUE_VF].fmt.mpix.width;
402 reso.pin_height[IMGU_ABI_OSYS_PIN_VF] =
403 css_pipe->queue[IPU3_CSS_QUEUE_VF].fmt.mpix.height;
404 reso.pin_stride[IMGU_ABI_OSYS_PIN_VF] =
405 css_pipe->queue[IPU3_CSS_QUEUE_VF].width_pad;
406 reso.pin_format[IMGU_ABI_OSYS_PIN_VF] =
407 css_pipe->queue[IPU3_CSS_QUEUE_VF].css_fmt->frame_format;
408
409
410
411 frame_params[IMGU_ABI_OSYS_PIN_OUT].width =
412 css_pipe->queue[IPU3_CSS_QUEUE_OUT].fmt.mpix.width;
413 frame_params[IMGU_ABI_OSYS_PIN_OUT].height =
414 css_pipe->queue[IPU3_CSS_QUEUE_OUT].fmt.mpix.height;
415 frame_params[IMGU_ABI_OSYS_PIN_VF].width =
416 css_pipe->queue[IPU3_CSS_QUEUE_VF].fmt.mpix.width;
417 frame_params[IMGU_ABI_OSYS_PIN_VF].height =
418 css_pipe->queue[IPU3_CSS_QUEUE_VF].fmt.mpix.height;
419 frame_params[IMGU_ABI_OSYS_PIN_VF].crop_top = 0;
420 frame_params[IMGU_ABI_OSYS_PIN_VF].crop_left = 0;
421
422 for (pin = 0; pin < IMGU_ABI_OSYS_PINS; pin++) {
423 int enable = 0;
424 int scaled = 0;
425 unsigned int format = 0;
426 unsigned int tiling = 0;
427
428 frame_params[pin].flip = 0;
429 frame_params[pin].mirror = 0;
430 frame_params[pin].reduce_range = 0;
431 if (reso.pin_width[pin] != 0 && reso.pin_height[pin] != 0) {
432 enable = 1;
433 if (pin == IMGU_ABI_OSYS_PIN_OUT) {
434 if (reso.input_width < reso.pin_width[pin] ||
435 reso.input_height < reso.pin_height[pin])
436 return -EINVAL;
437
438
439
440
441
442
443 frame_params[pin].crop_left = roundclosest_down(
444 (reso.input_width -
445 reso.pin_width[pin]) / 2,
446 IMGU_OSYS_DMA_CROP_W_LIMIT);
447 frame_params[pin].crop_top = roundclosest_down(
448 (reso.input_height -
449 reso.pin_height[pin]) / 2,
450 IMGU_OSYS_DMA_CROP_H_LIMIT);
451 } else {
452 if (reso.pin_width[pin] != reso.input_width ||
453 reso.pin_height[pin] != reso.input_height) {
454
455
456
457
458
459
460
461
462 scaled = 1;
463 }
464 }
465 imgu_css_osys_set_format(reso.pin_format[pin], &format,
466 &tiling);
467 } else {
468 enable = 0;
469 }
470 frame_params[pin].enable = enable;
471 frame_params[pin].format = format;
472 frame_params[pin].tiling = tiling;
473 frame_params[pin].stride = reso.pin_stride[pin];
474 frame_params[pin].scaled = scaled;
475 }
476
477 imgu_css_scaler_calc(input_width, input_height, target_width,
478 target_height, osys, scaler_luma, scaler_chroma,
479 &reso.pin_width[IMGU_ABI_OSYS_PIN_VF],
480 &reso.pin_height[IMGU_ABI_OSYS_PIN_VF], &procmode);
481 dev_dbg(css->dev, "osys scaler procmode is %u", procmode);
482 output_width = reso.pin_width[IMGU_ABI_OSYS_PIN_VF];
483
484 if (output_width < reso.input_width / 2) {
485
486 reso.chunk_width = IMGU_OSYS_BLOCK_WIDTH;
487 reso.block_width = IMGU_OSYS_BLOCK_WIDTH;
488 } else {
489 reso.chunk_width = IMGU_OSYS_BLOCK_WIDTH / 2;
490 reso.block_width = IMGU_OSYS_BLOCK_WIDTH;
491 }
492
493 if (output_width <= reso.input_width * 7 / 8) {
494
495 reso.chunk_height = IMGU_OSYS_BLOCK_HEIGHT;
496 reso.block_height = IMGU_OSYS_BLOCK_HEIGHT;
497 } else {
498 reso.chunk_height = IMGU_OSYS_BLOCK_HEIGHT / 2;
499 reso.block_height = IMGU_OSYS_BLOCK_HEIGHT;
500 }
501
502
503
504
505
506
507 if (frame_params[IMGU_ABI_OSYS_PIN_VF].enable) {
508
509
510
511
512
513 u32 w = reso.pin_width[IMGU_ABI_OSYS_PIN_VF] -
514 frame_params[IMGU_ABI_OSYS_PIN_VF].width;
515 u32 h = reso.pin_height[IMGU_ABI_OSYS_PIN_VF] -
516 frame_params[IMGU_ABI_OSYS_PIN_VF].height;
517
518 frame_params[IMGU_ABI_OSYS_PIN_VF].crop_left =
519 roundclosest_down(w / 2, IMGU_OSYS_DMA_CROP_W_LIMIT);
520 frame_params[IMGU_ABI_OSYS_PIN_VF].crop_top =
521 roundclosest_down(h / 2, IMGU_OSYS_DMA_CROP_H_LIMIT);
522
523 if (reso.input_height % 4 || reso.input_width % 8) {
524 dev_err(css->dev, "OSYS input width is not multiple of 8 or\n");
525 dev_err(css->dev, "height is not multiple of 4\n");
526 return -EINVAL;
527 }
528 }
529
530
531
532 if (frame_params[IMGU_ABI_OSYS_PIN_VF].enable) {
533 output_width = reso.pin_width[IMGU_ABI_OSYS_PIN_VF];
534 } else {
535
536
537
538
539
540
541
542
543 output_width = reso.input_width;
544 }
545
546 for (s = 0; s < stripes; s++) {
547 int stripe_offset_inp_y = 0;
548 int stripe_offset_inp_uv = 0;
549 int stripe_offset_out_y = 0;
550 int stripe_offset_out_uv = 0;
551 int stripe_phase_init_y = scaler_luma->phase_init;
552 int stripe_phase_init_uv = scaler_chroma->phase_init;
553 int stripe_offset_blk_y = 0;
554 int stripe_offset_blk_uv = 0;
555 int stripe_offset_col_y = 0;
556 int stripe_offset_col_uv = 0;
557 int stripe_pad_left_y = scaler_luma->pad_left;
558 int stripe_pad_left_uv = scaler_chroma->pad_left;
559 int stripe_pad_right_y = scaler_luma->pad_right;
560 int stripe_pad_right_uv = scaler_chroma->pad_right;
561 int stripe_crop_left_y = scaler_luma->crop_left;
562 int stripe_crop_left_uv = scaler_chroma->crop_left;
563 int stripe_input_width_y = reso.input_width;
564 int stripe_input_width_uv = 0;
565 int stripe_output_width_y = output_width;
566 int stripe_output_width_uv = 0;
567 int chunk_floor_y = 0;
568 int chunk_floor_uv = 0;
569 int chunk_ceil_uv = 0;
570
571 if (stripes > 1) {
572 if (s > 0) {
573
574 stripe_offset_out_y =
575 output_width * s / stripes;
576 stripe_offset_out_y =
577 rounddown(stripe_offset_out_y,
578 IPU3_UAPI_ISP_VEC_ELEMS);
579 stripe_offset_out_uv = stripe_offset_out_y /
580 IMGU_LUMA_TO_CHROMA_RATIO;
581 stripe_offset_inp_y =
582 imgu_css_osys_calc_stripe_offset(
583 stripe_offset_out_y,
584 IMGU_OSYS_FIR_PHASES,
585 scaler_luma->phase_init,
586 scaler_luma->phase_step,
587 scaler_luma->pad_left);
588 stripe_offset_inp_uv =
589 imgu_css_osys_calc_stripe_offset(
590 stripe_offset_out_uv,
591 IMGU_OSYS_FIR_PHASES,
592 scaler_chroma->phase_init,
593 scaler_chroma->phase_step,
594 scaler_chroma->pad_left);
595
596
597 stripe_phase_init_y =
598 imgu_css_osys_calc_stripe_phase_init(
599 stripe_offset_out_y,
600 IMGU_OSYS_FIR_PHASES,
601 scaler_luma->phase_init,
602 scaler_luma->phase_step,
603 scaler_luma->pad_left);
604 stripe_phase_init_uv =
605 imgu_css_osys_calc_stripe_phase_init(
606 stripe_offset_out_uv,
607 IMGU_OSYS_FIR_PHASES,
608 scaler_chroma->phase_init,
609 scaler_chroma->phase_step,
610 scaler_chroma->pad_left);
611
612
613
614
615
616 chunk_floor_y = rounddown(stripe_offset_inp_y,
617 reso.chunk_width);
618 chunk_floor_uv =
619 rounddown(stripe_offset_inp_uv,
620 reso.chunk_width /
621 IMGU_LUMA_TO_CHROMA_RATIO);
622
623 if (chunk_floor_y != chunk_floor_uv *
624 IMGU_LUMA_TO_CHROMA_RATIO) {
625
626
627
628
629
630 stripe_offset_inp_uv -= 1;
631 stripe_crop_left_uv += 1;
632 stripe_phase_init_uv -=
633 scaler_luma->phase_step;
634 if (stripe_phase_init_uv < 0)
635 stripe_phase_init_uv =
636 stripe_phase_init_uv +
637 IMGU_OSYS_FIR_PHASES;
638 }
639
640
641
642
643
644
645
646 chunk_ceil_uv =
647 roundup(stripe_offset_inp_uv,
648 reso.chunk_width /
649 IMGU_LUMA_TO_CHROMA_RATIO);
650
651 if (stripe_offset_inp_uv ==
652 chunk_ceil_uv - IMGU_OSYS_TAPS_UV) {
653
654
655
656
657 stripe_offset_inp_uv -= 1;
658 stripe_phase_init_uv -=
659 scaler_luma->phase_step;
660 if (stripe_phase_init_uv < 0) {
661 stripe_phase_init_uv +=
662 IMGU_OSYS_FIR_PHASES;
663 stripe_crop_left_uv += 1;
664 }
665 }
666
667
668
669
670
671 stripe_offset_blk_y =
672 rounddown(stripe_offset_inp_y,
673 IMGU_INPUT_BLOCK_WIDTH);
674 stripe_offset_blk_uv =
675 rounddown(stripe_offset_inp_uv,
676 IMGU_INPUT_BLOCK_WIDTH /
677 IMGU_LUMA_TO_CHROMA_RATIO);
678 stripe_offset_col_y = stripe_offset_inp_y -
679 stripe_offset_blk_y;
680 stripe_offset_col_uv = stripe_offset_inp_uv -
681 stripe_offset_blk_uv;
682
683
684 stripe_pad_left_y = 0;
685 stripe_pad_left_uv = 0;
686 }
687
688
689 if (s < stripes - 1) {
690 int next_offset;
691
692 stripe_pad_right_y = 0;
693 stripe_pad_right_uv = 0;
694
695 next_offset = output_width * (s + 1) / stripes;
696 next_offset = rounddown(next_offset, 64);
697 stripe_output_width_y = next_offset -
698 stripe_offset_out_y;
699 } else {
700 stripe_output_width_y = output_width -
701 stripe_offset_out_y;
702 }
703
704
705 stripe_output_width_uv = stripe_output_width_y /
706 IMGU_LUMA_TO_CHROMA_RATIO;
707
708 stripe_input_width_y = stripe_offset_col_y +
709 imgu_css_osys_calc_inp_stripe_width(
710 stripe_output_width_y,
711 IMGU_OSYS_FIR_PHASES,
712 stripe_phase_init_y,
713 scaler_luma->phase_step,
714 IMGU_OSYS_TAPS_Y,
715 stripe_pad_left_y,
716 stripe_pad_right_y);
717
718 stripe_input_width_uv = stripe_offset_col_uv +
719 imgu_css_osys_calc_inp_stripe_width(
720 stripe_output_width_uv,
721 IMGU_OSYS_FIR_PHASES,
722 stripe_phase_init_uv,
723 scaler_chroma->phase_step,
724 IMGU_OSYS_TAPS_UV,
725 stripe_pad_left_uv,
726 stripe_pad_right_uv);
727
728 stripe_input_width_uv = max(DIV_ROUND_UP(
729 stripe_input_width_y,
730 IMGU_LUMA_TO_CHROMA_RATIO),
731 stripe_input_width_uv);
732
733 stripe_input_width_y = stripe_input_width_uv *
734 IMGU_LUMA_TO_CHROMA_RATIO;
735
736 if (s >= stripes - 1) {
737 stripe_input_width_y = reso.input_width -
738 stripe_offset_blk_y;
739
740
741
742
743 }
744
745
746
747
748
749
750
751
752 stripe_input_width_y = ALIGN(stripe_input_width_y, 8);
753 stripe_output_width_y =
754 imgu_css_osys_out_stripe_width(
755 stripe_input_width_y,
756 IMGU_OSYS_FIR_PHASES,
757 stripe_phase_init_y,
758 scaler_luma->phase_step,
759 IMGU_OSYS_TAPS_Y,
760 stripe_pad_left_y,
761 stripe_pad_right_y,
762 stripe_offset_col_y);
763
764 stripe_output_width_y =
765 rounddown(stripe_output_width_y,
766 IMGU_LUMA_TO_CHROMA_RATIO);
767 }
768
769
770
771
772 {
773 unsigned int i;
774 int pin_scale = 0;
775
776
777 stripe_params[s].input_width = stripe_input_width_y;
778 stripe_params[s].input_height = reso.input_height;
779
780 for (i = 0; i < IMGU_ABI_OSYS_PINS; i++) {
781 if (frame_params[i].scaled) {
782
783
784
785
786
787
788 stripe_params[s].output_width[i] =
789 stripe_output_width_y;
790 stripe_params[s].output_height[i] =
791 reso.pin_height[i];
792 stripe_params[s].output_offset[i] =
793 stripe_offset_out_y;
794
795 pin_scale += frame_params[i].scaled;
796 } else {
797
798 stripe_params[s].output_width[i] =
799 stripe_params[s].input_width;
800 stripe_params[s].output_height[i] =
801 stripe_params[s].input_height;
802 stripe_params[s].output_offset[i] =
803 stripe_offset_blk_y;
804 }
805 }
806
807
808 stripe_params[s].processing_mode = procmode;
809 stripe_params[s].phase_step = scaler_luma->phase_step;
810 stripe_params[s].exp_shift = scaler_luma->exp_shift;
811 stripe_params[s].phase_init_left_y =
812 stripe_phase_init_y;
813 stripe_params[s].phase_init_left_uv =
814 stripe_phase_init_uv;
815 stripe_params[s].phase_init_top_y =
816 scaler_luma->phase_init;
817 stripe_params[s].phase_init_top_uv =
818 scaler_chroma->phase_init;
819 stripe_params[s].pad_left_y = stripe_pad_left_y;
820 stripe_params[s].pad_left_uv = stripe_pad_left_uv;
821 stripe_params[s].pad_right_y = stripe_pad_right_y;
822 stripe_params[s].pad_right_uv = stripe_pad_right_uv;
823 stripe_params[s].pad_top_y = scaler_luma->pad_left;
824 stripe_params[s].pad_top_uv = scaler_chroma->pad_left;
825 stripe_params[s].pad_bottom_y = scaler_luma->pad_right;
826 stripe_params[s].pad_bottom_uv =
827 scaler_chroma->pad_right;
828 stripe_params[s].crop_left_y = stripe_crop_left_y;
829 stripe_params[s].crop_top_y = scaler_luma->crop_top;
830 stripe_params[s].crop_left_uv = stripe_crop_left_uv;
831 stripe_params[s].crop_top_uv = scaler_chroma->crop_top;
832 stripe_params[s].start_column_y = stripe_offset_col_y;
833 stripe_params[s].start_column_uv = stripe_offset_col_uv;
834 stripe_params[s].chunk_width = reso.chunk_width;
835 stripe_params[s].chunk_height = reso.chunk_height;
836 stripe_params[s].block_width = reso.block_width;
837 stripe_params[s].block_height = reso.block_height;
838 }
839 }
840
841 return 0;
842}
843
844
845
846
847
848static int imgu_css_osys_calc(struct imgu_css *css, unsigned int pipe,
849 unsigned int stripes,
850 struct imgu_abi_osys_config *osys,
851 struct imgu_css_scaler_info *scaler_luma,
852 struct imgu_css_scaler_info *scaler_chroma,
853 struct imgu_abi_stripes block_stripes[])
854{
855 struct imgu_css_frame_params frame_params[IMGU_ABI_OSYS_PINS];
856 struct imgu_css_stripe_params stripe_params[IPU3_UAPI_MAX_STRIPES];
857 struct imgu_abi_osys_formatter_params *param;
858 unsigned int pin, s;
859 struct imgu_css_pipe *css_pipe = &css->pipes[pipe];
860
861 memset(osys, 0, sizeof(*osys));
862
863
864 if (imgu_css_osys_calc_frame_and_stripe_params(css, stripes, osys,
865 scaler_luma,
866 scaler_chroma,
867 frame_params,
868 stripe_params, pipe))
869 return -EINVAL;
870
871
872
873 for (s = 0; s < stripes; s++) {
874 struct imgu_abi_osys_scaler_params *scaler =
875 &osys->scaler[s].param;
876 int fifo_addr_fmt = IMGU_FIFO_ADDR_SCALER_TO_FMT;
877 int fifo_addr_ack = IMGU_FIFO_ADDR_SCALER_TO_SP;
878
879
880 scaler->inp_buf_y_st_addr = IMGU_VMEM1_INP_BUF_ADDR;
881
882
883
884
885
886
887
888 scaler->inp_buf_y_line_stride = IMGU_VMEM1_Y_STRIDE;
889
890
891
892
893
894
895
896
897 scaler->inp_buf_y_buffer_stride = IMGU_VMEM1_BUF_SIZE;
898 scaler->inp_buf_u_st_addr = IMGU_VMEM1_INP_BUF_ADDR +
899 IMGU_VMEM1_U_OFFSET;
900 scaler->inp_buf_v_st_addr = IMGU_VMEM1_INP_BUF_ADDR +
901 IMGU_VMEM1_V_OFFSET;
902 scaler->inp_buf_uv_line_stride = IMGU_VMEM1_UV_STRIDE;
903 scaler->inp_buf_uv_buffer_stride = IMGU_VMEM1_BUF_SIZE;
904 scaler->inp_buf_chunk_width = stripe_params[s].chunk_width;
905 scaler->inp_buf_nr_buffers = IMGU_OSYS_NUM_INPUT_BUFFERS;
906
907
908 scaler->out_buf_y_st_addr = IMGU_VMEM1_INT_BUF_ADDR;
909 scaler->out_buf_y_line_stride = stripe_params[s].block_width /
910 IMGU_VMEM1_ELEMS_PER_VEC;
911 scaler->out_buf_y_buffer_stride = IMGU_VMEM1_BUF_SIZE;
912 scaler->out_buf_u_st_addr = IMGU_VMEM1_INT_BUF_ADDR +
913 IMGU_VMEM1_U_OFFSET;
914 scaler->out_buf_v_st_addr = IMGU_VMEM1_INT_BUF_ADDR +
915 IMGU_VMEM1_V_OFFSET;
916 scaler->out_buf_uv_line_stride = stripe_params[s].block_width /
917 IMGU_VMEM1_ELEMS_PER_VEC / 2;
918 scaler->out_buf_uv_buffer_stride = IMGU_VMEM1_BUF_SIZE;
919 scaler->out_buf_nr_buffers = IMGU_OSYS_NUM_INTERM_BUFFERS;
920
921
922 scaler->int_buf_y_st_addr = IMGU_VMEM2_BUF_Y_ADDR;
923 scaler->int_buf_y_line_stride = IMGU_VMEM2_BUF_Y_STRIDE;
924 scaler->int_buf_u_st_addr = IMGU_VMEM2_BUF_U_ADDR;
925 scaler->int_buf_v_st_addr = IMGU_VMEM2_BUF_V_ADDR;
926 scaler->int_buf_uv_line_stride = IMGU_VMEM2_BUF_UV_STRIDE;
927 scaler->int_buf_height = IMGU_VMEM2_LINES_PER_BLOCK;
928 scaler->int_buf_chunk_width = stripe_params[s].chunk_height;
929 scaler->int_buf_chunk_height = stripe_params[s].block_width;
930
931
932 scaler->ctx_buf_hor_y_st_addr = IMGU_VMEM3_HOR_Y_ADDR;
933 scaler->ctx_buf_hor_u_st_addr = IMGU_VMEM3_HOR_U_ADDR;
934 scaler->ctx_buf_hor_v_st_addr = IMGU_VMEM3_HOR_V_ADDR;
935 scaler->ctx_buf_ver_y_st_addr = IMGU_VMEM3_VER_Y_ADDR;
936 scaler->ctx_buf_ver_u_st_addr = IMGU_VMEM3_VER_U_ADDR;
937 scaler->ctx_buf_ver_v_st_addr = IMGU_VMEM3_VER_V_ADDR;
938
939
940 scaler->release_inp_buf_addr = fifo_addr_ack;
941 scaler->release_inp_buf_en = 1;
942 scaler->release_out_buf_en = 1;
943 scaler->process_out_buf_addr = fifo_addr_fmt;
944
945
946 scaler->input_image_y_width = stripe_params[s].input_width;
947 scaler->input_image_y_height = stripe_params[s].input_height;
948 scaler->input_image_y_start_column =
949 stripe_params[s].start_column_y;
950 scaler->input_image_uv_start_column =
951 stripe_params[s].start_column_uv;
952 scaler->input_image_y_left_pad = stripe_params[s].pad_left_y;
953 scaler->input_image_uv_left_pad = stripe_params[s].pad_left_uv;
954 scaler->input_image_y_right_pad = stripe_params[s].pad_right_y;
955 scaler->input_image_uv_right_pad =
956 stripe_params[s].pad_right_uv;
957 scaler->input_image_y_top_pad = stripe_params[s].pad_top_y;
958 scaler->input_image_uv_top_pad = stripe_params[s].pad_top_uv;
959 scaler->input_image_y_bottom_pad =
960 stripe_params[s].pad_bottom_y;
961 scaler->input_image_uv_bottom_pad =
962 stripe_params[s].pad_bottom_uv;
963 scaler->processing_mode = stripe_params[s].processing_mode;
964 scaler->scaling_ratio = stripe_params[s].phase_step;
965 scaler->y_left_phase_init = stripe_params[s].phase_init_left_y;
966 scaler->uv_left_phase_init =
967 stripe_params[s].phase_init_left_uv;
968 scaler->y_top_phase_init = stripe_params[s].phase_init_top_y;
969 scaler->uv_top_phase_init = stripe_params[s].phase_init_top_uv;
970 scaler->coeffs_exp_shift = stripe_params[s].exp_shift;
971 scaler->out_y_left_crop = stripe_params[s].crop_left_y;
972 scaler->out_uv_left_crop = stripe_params[s].crop_left_uv;
973 scaler->out_y_top_crop = stripe_params[s].crop_top_y;
974 scaler->out_uv_top_crop = stripe_params[s].crop_top_uv;
975
976 for (pin = 0; pin < IMGU_ABI_OSYS_PINS; pin++) {
977 int in_fifo_addr;
978 int out_fifo_addr;
979 int block_width_vecs;
980 int input_width_s;
981 int input_width_vecs;
982 int input_buf_y_st_addr;
983 int input_buf_u_st_addr;
984 int input_buf_v_st_addr;
985 int input_buf_y_line_stride;
986 int input_buf_uv_line_stride;
987 int output_buf_y_line_stride;
988 int output_buf_uv_line_stride;
989 int output_buf_nr_y_lines;
990 int block_height;
991 int block_width;
992 struct imgu_abi_osys_frame_params *fr_pr;
993
994 fr_pr = &osys->frame[pin].param;
995
996
997 fr_pr->enable = frame_params[pin].enable;
998 fr_pr->format = frame_params[pin].format;
999 fr_pr->mirror = frame_params[pin].mirror;
1000 fr_pr->flip = frame_params[pin].flip;
1001 fr_pr->tiling = frame_params[pin].tiling;
1002 fr_pr->width = frame_params[pin].width;
1003 fr_pr->height = frame_params[pin].height;
1004 fr_pr->stride = frame_params[pin].stride;
1005 fr_pr->scaled = frame_params[pin].scaled;
1006
1007
1008 osys->stripe[s].crop_top[pin] =
1009 frame_params[pin].crop_top;
1010 osys->stripe[s].input_width =
1011 stripe_params[s].input_width;
1012 osys->stripe[s].input_height =
1013 stripe_params[s].input_height;
1014 osys->stripe[s].block_height =
1015 stripe_params[s].block_height;
1016 osys->stripe[s].block_width =
1017 stripe_params[s].block_width;
1018 osys->stripe[s].output_width[pin] =
1019 stripe_params[s].output_width[pin];
1020 osys->stripe[s].output_height[pin] =
1021 stripe_params[s].output_height[pin];
1022
1023 if (s == 0) {
1024
1025 osys->stripe[s].crop_left[pin] =
1026 frame_params[pin].crop_left;
1027 osys->stripe[s].output_offset[pin] =
1028 stripe_params[s].output_offset[pin];
1029 } else {
1030
1031
1032
1033
1034
1035 osys->stripe[s].crop_left[pin] = 0;
1036 osys->stripe[s].output_offset[pin] =
1037 (stripe_params[s].output_offset[pin] -
1038 osys->stripe[0].crop_left[pin]);
1039 }
1040
1041 if (!frame_params[pin].enable)
1042 continue;
1043
1044
1045
1046
1047
1048
1049
1050
1051 if (frame_params[pin].scaled) {
1052 block_height = stripe_params[s].block_height;
1053 block_width = stripe_params[s].block_width;
1054 } else {
1055 block_height = IMGU_OSYS_BLOCK_HEIGHT;
1056 block_width = IMGU_OSYS_BLOCK_WIDTH;
1057 }
1058 block_width_vecs =
1059 block_width / IMGU_VMEM1_ELEMS_PER_VEC;
1060
1061
1062
1063
1064 input_buf_y_line_stride = block_width_vecs;
1065 input_buf_uv_line_stride = block_width_vecs / 2;
1066 output_buf_y_line_stride = block_width_vecs;
1067 output_buf_uv_line_stride = block_width_vecs / 2;
1068 output_buf_nr_y_lines = block_height;
1069 if (frame_params[pin].format ==
1070 IMGU_ABI_OSYS_FORMAT_NV12 ||
1071 frame_params[pin].format ==
1072 IMGU_ABI_OSYS_FORMAT_NV21)
1073 output_buf_uv_line_stride =
1074 output_buf_y_line_stride;
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084 if (frame_params[pin].tiling) {
1085 output_buf_nr_y_lines = 8;
1086 output_buf_y_line_stride = 512 /
1087 IMGU_VMEM1_ELEMS_PER_VEC;
1088 output_buf_uv_line_stride = 256 /
1089 IMGU_VMEM1_ELEMS_PER_VEC;
1090 }
1091
1092
1093
1094
1095
1096
1097
1098 osys->stripe[s].buf_stride[pin] =
1099 output_buf_y_line_stride *
1100 IMGU_HIVE_OF_SYS_OF_SYSTEM_NWAYS;
1101 if (frame_params[pin].scaled) {
1102
1103
1104
1105
1106 input_buf_y_st_addr = IMGU_VMEM1_INT_BUF_ADDR;
1107 input_buf_u_st_addr = IMGU_VMEM1_INT_BUF_ADDR +
1108 IMGU_VMEM1_U_OFFSET;
1109 input_buf_v_st_addr = IMGU_VMEM1_INT_BUF_ADDR +
1110 IMGU_VMEM1_V_OFFSET;
1111 } else {
1112
1113
1114
1115
1116 input_buf_y_st_addr = IMGU_VMEM1_INP_BUF_ADDR;
1117 input_buf_u_st_addr = IMGU_VMEM1_INP_BUF_ADDR +
1118 IMGU_VMEM1_U_OFFSET;
1119 input_buf_v_st_addr = IMGU_VMEM1_INP_BUF_ADDR +
1120 IMGU_VMEM1_V_OFFSET;
1121 }
1122
1123
1124
1125
1126
1127
1128
1129
1130 input_width_s =
1131 roundup(stripe_params[s].output_width[pin],
1132 block_width);
1133 input_width_vecs = input_width_s /
1134 IMGU_VMEM1_ELEMS_PER_VEC;
1135 out_fifo_addr = IMGU_FIFO_ADDR_FMT_TO_SP;
1136
1137
1138
1139
1140
1141
1142 if (frame_params[pin].scaled)
1143 in_fifo_addr = IMGU_FIFO_ADDR_FMT_TO_SCALER;
1144 else
1145 in_fifo_addr = IMGU_FIFO_ADDR_FMT_TO_SP;
1146
1147
1148 param = &osys->formatter[s][pin].param;
1149
1150 param->format = frame_params[pin].format;
1151 param->flip = frame_params[pin].flip;
1152 param->mirror = frame_params[pin].mirror;
1153 param->tiling = frame_params[pin].tiling;
1154 param->reduce_range = frame_params[pin].reduce_range;
1155 param->alpha_blending = 0;
1156 param->release_inp_addr = in_fifo_addr;
1157 param->release_inp_en = 1;
1158 param->process_out_buf_addr = out_fifo_addr;
1159 param->image_width_vecs = input_width_vecs;
1160 param->image_height_lines =
1161 stripe_params[s].output_height[pin];
1162 param->inp_buff_y_st_addr = input_buf_y_st_addr;
1163 param->inp_buff_y_line_stride = input_buf_y_line_stride;
1164 param->inp_buff_y_buffer_stride = IMGU_VMEM1_BUF_SIZE;
1165 param->int_buff_u_st_addr = input_buf_u_st_addr;
1166 param->int_buff_v_st_addr = input_buf_v_st_addr;
1167 param->inp_buff_uv_line_stride =
1168 input_buf_uv_line_stride;
1169 param->inp_buff_uv_buffer_stride = IMGU_VMEM1_BUF_SIZE;
1170 param->out_buff_level = 0;
1171 param->out_buff_nr_y_lines = output_buf_nr_y_lines;
1172 param->out_buff_u_st_offset = IMGU_VMEM1_U_OFFSET;
1173 param->out_buff_v_st_offset = IMGU_VMEM1_V_OFFSET;
1174 param->out_buff_y_line_stride =
1175 output_buf_y_line_stride;
1176 param->out_buff_uv_line_stride =
1177 output_buf_uv_line_stride;
1178 param->hist_buff_st_addr = IMGU_VMEM1_HST_BUF_ADDR;
1179 param->hist_buff_line_stride =
1180 IMGU_VMEM1_HST_BUF_STRIDE;
1181 param->hist_buff_nr_lines = IMGU_VMEM1_HST_BUF_NLINES;
1182 }
1183 }
1184
1185 block_stripes[0].offset = 0;
1186 if (stripes <= 1) {
1187 block_stripes[0].width = stripe_params[0].input_width;
1188 block_stripes[0].height = stripe_params[0].input_height;
1189 } else {
1190 struct imgu_fw_info *bi =
1191 &css->fwp->binary_header[css_pipe->bindex];
1192 unsigned int sp_block_width =
1193 bi->info.isp.sp.block.block_width *
1194 IPU3_UAPI_ISP_VEC_ELEMS;
1195
1196 block_stripes[0].width = roundup(stripe_params[0].input_width,
1197 sp_block_width);
1198 block_stripes[1].offset =
1199 rounddown(css_pipe->rect[IPU3_CSS_RECT_GDC].width -
1200 stripe_params[1].input_width, sp_block_width);
1201 block_stripes[1].width =
1202 roundup(css_pipe->rect[IPU3_CSS_RECT_GDC].width -
1203 block_stripes[1].offset, sp_block_width);
1204 block_stripes[0].height = css_pipe->rect[IPU3_CSS_RECT_GDC].height;
1205 block_stripes[1].height = block_stripes[0].height;
1206 }
1207
1208 return 0;
1209}
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252static int
1253imgu_css_shd_ops_calc(struct imgu_abi_shd_intra_frame_operations_data *ops,
1254 const struct ipu3_uapi_shd_grid_config *grid,
1255 unsigned int image_height)
1256{
1257 unsigned int block_height = 1 << grid->block_height_log2;
1258 unsigned int grid_height_per_slice = grid->grid_height_per_slice;
1259 unsigned int set_height = grid_height_per_slice * block_height;
1260
1261
1262 unsigned int positive_y_start = (unsigned int)-grid->y_start;
1263 unsigned int first_process_lines =
1264 set_height - (positive_y_start % set_height);
1265 unsigned int last_set_height;
1266 unsigned int num_of_sets;
1267
1268 struct imgu_abi_acc_operation *p_op;
1269 struct imgu_abi_acc_process_lines_cmd_data *p_pl;
1270 struct imgu_abi_shd_transfer_luts_set_data *p_tr;
1271
1272 unsigned int op_idx, pl_idx, tr_idx;
1273 unsigned char tr_set_num, pl_cfg_set;
1274
1275
1276
1277
1278
1279
1280 unsigned char last_tr = 0;
1281
1282
1283 bool add_pl;
1284
1285 bool add_tr;
1286
1287
1288
1289
1290
1291 if (image_height > first_process_lines) {
1292 last_set_height =
1293 (image_height - first_process_lines) % set_height;
1294 num_of_sets = last_set_height > 0 ?
1295 (image_height - first_process_lines) / set_height + 2 :
1296 (image_height - first_process_lines) / set_height + 1;
1297 last_tr = (set_height - last_set_height <= block_height ||
1298 last_set_height == 0) ? 1 : 0;
1299 } else {
1300 last_set_height = 0;
1301 num_of_sets = 1;
1302 first_process_lines = image_height;
1303 last_tr = set_height - image_height <= block_height ? 1 : 0;
1304 }
1305
1306
1307 p_op = ops->operation_list;
1308 op_idx = 0;
1309 p_pl = ops->process_lines_data;
1310 pl_idx = 0;
1311 p_tr = ops->transfer_data;
1312 tr_idx = 0;
1313
1314 memset(ops, 0, sizeof(*ops));
1315
1316
1317 tr_set_num = 0;
1318 pl_cfg_set = 0;
1319
1320
1321
1322
1323
1324
1325 add_pl = false;
1326 add_tr = true;
1327
1328 while (add_pl || add_tr) {
1329
1330 if (add_tr) {
1331 if (op_idx >= IMGU_ABI_SHD_MAX_OPERATIONS ||
1332 tr_idx >= IMGU_ABI_SHD_MAX_TRANSFERS)
1333 return -EINVAL;
1334 p_op[op_idx].op_type =
1335 IMGU_ABI_ACC_OPTYPE_TRANSFER_DATA;
1336 p_op[op_idx].op_indicator = IMGU_ABI_ACC_OP_IDLE;
1337 op_idx++;
1338 p_tr[tr_idx].set_number = tr_set_num;
1339 tr_idx++;
1340 tr_set_num = (tr_set_num + 1) % IMGU_SHD_SETS;
1341 }
1342
1343
1344 if (add_pl) {
1345 if (op_idx >= IMGU_ABI_SHD_MAX_OPERATIONS ||
1346 pl_idx >= IMGU_ABI_SHD_MAX_PROCESS_LINES)
1347 return -EINVAL;
1348 p_op[op_idx].op_type =
1349 IMGU_ABI_ACC_OPTYPE_PROCESS_LINES;
1350
1351
1352
1353
1354
1355 if (pl_idx == 0 && num_of_sets != 1)
1356 p_op[op_idx].op_indicator =
1357 IMGU_ABI_ACC_OP_IDLE;
1358
1359
1360
1361
1362 else if (pl_idx == num_of_sets - 1)
1363 p_op[op_idx].op_indicator =
1364 IMGU_ABI_ACC_OP_END_OF_OPS;
1365
1366
1367
1368
1369
1370 else
1371 p_op[op_idx].op_indicator =
1372 IMGU_ABI_ACC_OP_END_OF_ACK;
1373
1374 op_idx++;
1375
1376
1377 if (pl_idx == 0)
1378 p_pl[pl_idx].lines = first_process_lines;
1379
1380 else if (pl_idx == num_of_sets - 1 &&
1381 last_set_height > 0)
1382 p_pl[pl_idx].lines = last_set_height;
1383 else
1384 p_pl[pl_idx].lines = set_height;
1385
1386 p_pl[pl_idx].cfg_set = pl_cfg_set;
1387 pl_idx++;
1388 pl_cfg_set = (pl_cfg_set + 1) % IMGU_SHD_SETS;
1389 }
1390
1391
1392
1393
1394
1395
1396 if (tr_idx == IMGU_SHD_SETS ||
1397 tr_idx == num_of_sets + last_tr) {
1398 add_tr = false;
1399 add_pl = true;
1400 }
1401
1402
1403
1404
1405
1406 if (pl_idx == 2) {
1407 add_tr = true;
1408 add_pl = true;
1409 }
1410
1411
1412 if (tr_idx == num_of_sets + last_tr)
1413 add_tr = false;
1414 if (pl_idx == num_of_sets)
1415 add_pl = false;
1416 }
1417
1418 return 0;
1419}
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483struct process_lines {
1484 unsigned int image_height;
1485 unsigned short grid_height;
1486 unsigned short block_height;
1487 unsigned short y_start;
1488 unsigned char grid_height_per_slice;
1489
1490 unsigned short max_op;
1491 unsigned short max_tr;
1492 unsigned char acc_enable;
1493};
1494
1495
1496static int
1497imgu_css_acc_process_lines(const struct process_lines *pl,
1498 struct imgu_abi_acc_operation *p_op,
1499 struct imgu_abi_acc_process_lines_cmd_data *p_pl,
1500 struct imgu_abi_acc_transfer_op_data *p_tr)
1501{
1502 unsigned short op_idx = 0, pl_idx = 0, tr_idx = 0;
1503 unsigned char tr_set_num = 0, pl_cfg_set = 0;
1504 const unsigned short grid_last_line =
1505 pl->y_start + pl->grid_height * pl->block_height;
1506 const unsigned short process_lines =
1507 pl->grid_height_per_slice * pl->block_height;
1508
1509 unsigned int process_lines_after_grid;
1510 unsigned short first_process_lines;
1511 unsigned short last_process_lines_in_grid;
1512
1513 unsigned short num_of_process_lines;
1514 unsigned short num_of_sets;
1515
1516 if (pl->grid_height_per_slice == 0)
1517 return -EINVAL;
1518
1519 if (pl->acc_enable && grid_last_line > pl->image_height)
1520 return -EINVAL;
1521
1522 num_of_sets = pl->grid_height / pl->grid_height_per_slice;
1523 if (num_of_sets * pl->grid_height_per_slice < pl->grid_height)
1524 num_of_sets++;
1525
1526
1527 if (pl->max_op == IMGU_ABI_AF_MAX_OPERATIONS) {
1528 first_process_lines = process_lines + pl->y_start + 2;
1529 last_process_lines_in_grid =
1530 (grid_last_line - first_process_lines) -
1531 ((num_of_sets - 2) * process_lines) + 4;
1532 process_lines_after_grid =
1533 pl->image_height - grid_last_line - 4;
1534 } else {
1535 first_process_lines = process_lines + pl->y_start;
1536 last_process_lines_in_grid =
1537 (grid_last_line - first_process_lines) -
1538 ((num_of_sets - 2) * process_lines);
1539 process_lines_after_grid = pl->image_height - grid_last_line;
1540 }
1541
1542 num_of_process_lines = num_of_sets;
1543 if (process_lines_after_grid > 0)
1544 num_of_process_lines++;
1545
1546 while (tr_idx < num_of_sets || pl_idx < num_of_process_lines) {
1547
1548 if (pl_idx >= 2 || (pl_idx == 1 && num_of_sets == 1)) {
1549 if (op_idx >= pl->max_op || tr_idx >= pl->max_tr)
1550 return -EINVAL;
1551
1552 p_op[op_idx].op_type =
1553 IMGU_ABI_ACC_OPTYPE_TRANSFER_DATA;
1554
1555 if (tr_idx == num_of_sets - 1)
1556
1557 p_op[op_idx].op_indicator =
1558 IMGU_ABI_ACC_OP_END_OF_OPS;
1559 else if (tr_idx == num_of_sets - 2)
1560 if (process_lines_after_grid == 0)
1561
1562
1563
1564
1565 p_op[op_idx].op_indicator =
1566 IMGU_ABI_ACC_OP_END_OF_ACK;
1567 else
1568
1569
1570
1571
1572 p_op[op_idx].op_indicator =
1573 IMGU_ABI_ACC_OP_IDLE;
1574 else
1575
1576 p_op[op_idx].op_indicator =
1577 IMGU_ABI_ACC_OP_IDLE;
1578
1579 op_idx++;
1580 if (p_tr) {
1581 p_tr[tr_idx].set_number = tr_set_num;
1582 tr_set_num = 1 - tr_set_num;
1583 }
1584 tr_idx++;
1585 }
1586
1587
1588 if (pl_idx < num_of_process_lines) {
1589 if (op_idx >= pl->max_op || pl_idx >= pl->max_tr)
1590 return -EINVAL;
1591
1592 p_op[op_idx].op_type =
1593 IMGU_ABI_ACC_OPTYPE_PROCESS_LINES;
1594 if (pl_idx == 0)
1595 if (num_of_process_lines == 1)
1596
1597 p_op[op_idx].op_indicator =
1598 IMGU_ABI_ACC_OP_END_OF_ACK;
1599 else
1600
1601 p_op[op_idx].op_indicator =
1602 IMGU_ABI_ACC_OP_IDLE;
1603 else
1604
1605 p_op[op_idx].op_indicator =
1606 IMGU_ABI_ACC_OP_END_OF_ACK;
1607
1608 op_idx++;
1609
1610 if (pl_idx == 0)
1611
1612 p_pl[pl_idx].lines = first_process_lines;
1613 else if (pl_idx == num_of_sets - 1)
1614
1615 p_pl[pl_idx].lines = last_process_lines_in_grid;
1616 else if (pl_idx == num_of_process_lines - 1)
1617
1618 p_pl[pl_idx].lines = process_lines_after_grid;
1619 else
1620
1621 p_pl[pl_idx].lines = process_lines;
1622
1623 if (p_tr) {
1624 p_pl[pl_idx].cfg_set = pl_cfg_set;
1625 pl_cfg_set = 1 - pl_cfg_set;
1626 }
1627 pl_idx++;
1628 }
1629 }
1630
1631 return 0;
1632}
1633
1634static int imgu_css_af_ops_calc(struct imgu_css *css, unsigned int pipe,
1635 struct imgu_abi_af_config *af_config)
1636{
1637 struct imgu_abi_af_intra_frame_operations_data *to =
1638 &af_config->operations_data;
1639 struct imgu_css_pipe *css_pipe = &css->pipes[pipe];
1640 struct imgu_fw_info *bi =
1641 &css->fwp->binary_header[css_pipe->bindex];
1642
1643 struct process_lines pl = {
1644 .image_height = css_pipe->rect[IPU3_CSS_RECT_BDS].height,
1645 .grid_height = af_config->config.grid_cfg.height,
1646 .block_height =
1647 1 << af_config->config.grid_cfg.block_height_log2,
1648 .y_start = af_config->config.grid_cfg.y_start &
1649 IPU3_UAPI_GRID_START_MASK,
1650 .grid_height_per_slice =
1651 af_config->stripes[0].grid_cfg.height_per_slice,
1652 .max_op = IMGU_ABI_AF_MAX_OPERATIONS,
1653 .max_tr = IMGU_ABI_AF_MAX_TRANSFERS,
1654 .acc_enable = bi->info.isp.sp.enable.af,
1655 };
1656
1657 return imgu_css_acc_process_lines(&pl, to->ops, to->process_lines_data,
1658 NULL);
1659}
1660
1661static int
1662imgu_css_awb_fr_ops_calc(struct imgu_css *css, unsigned int pipe,
1663 struct imgu_abi_awb_fr_config *awb_fr_config)
1664{
1665 struct imgu_abi_awb_fr_intra_frame_operations_data *to =
1666 &awb_fr_config->operations_data;
1667 struct imgu_css_pipe *css_pipe = &css->pipes[pipe];
1668 struct imgu_fw_info *bi =
1669 &css->fwp->binary_header[css_pipe->bindex];
1670 struct process_lines pl = {
1671 .image_height = css_pipe->rect[IPU3_CSS_RECT_BDS].height,
1672 .grid_height = awb_fr_config->config.grid_cfg.height,
1673 .block_height =
1674 1 << awb_fr_config->config.grid_cfg.block_height_log2,
1675 .y_start = awb_fr_config->config.grid_cfg.y_start &
1676 IPU3_UAPI_GRID_START_MASK,
1677 .grid_height_per_slice =
1678 awb_fr_config->stripes[0].grid_cfg.height_per_slice,
1679 .max_op = IMGU_ABI_AWB_FR_MAX_OPERATIONS,
1680 .max_tr = IMGU_ABI_AWB_FR_MAX_PROCESS_LINES,
1681 .acc_enable = bi->info.isp.sp.enable.awb_fr_acc,
1682 };
1683
1684 return imgu_css_acc_process_lines(&pl, to->ops, to->process_lines_data,
1685 NULL);
1686}
1687
1688static int imgu_css_awb_ops_calc(struct imgu_css *css, unsigned int pipe,
1689 struct imgu_abi_awb_config *awb_config)
1690{
1691 struct imgu_abi_awb_intra_frame_operations_data *to =
1692 &awb_config->operations_data;
1693 struct imgu_css_pipe *css_pipe = &css->pipes[pipe];
1694 struct imgu_fw_info *bi =
1695 &css->fwp->binary_header[css_pipe->bindex];
1696
1697 struct process_lines pl = {
1698 .image_height = css_pipe->rect[IPU3_CSS_RECT_BDS].height,
1699 .grid_height = awb_config->config.grid.height,
1700 .block_height =
1701 1 << awb_config->config.grid.block_height_log2,
1702 .y_start = awb_config->config.grid.y_start,
1703 .grid_height_per_slice =
1704 awb_config->stripes[0].grid.height_per_slice,
1705 .max_op = IMGU_ABI_AWB_MAX_OPERATIONS,
1706 .max_tr = IMGU_ABI_AWB_MAX_TRANSFERS,
1707 .acc_enable = bi->info.isp.sp.enable.awb_acc,
1708 };
1709
1710 return imgu_css_acc_process_lines(&pl, to->ops, to->process_lines_data,
1711 to->transfer_data);
1712}
1713
1714static u16 imgu_css_grid_end(u16 start, u8 width, u8 block_width_log2)
1715{
1716 return (start & IPU3_UAPI_GRID_START_MASK) +
1717 (width << block_width_log2) - 1;
1718}
1719
1720static void imgu_css_grid_end_calc(struct ipu3_uapi_grid_config *grid_cfg)
1721{
1722 grid_cfg->x_end = imgu_css_grid_end(grid_cfg->x_start, grid_cfg->width,
1723 grid_cfg->block_width_log2);
1724 grid_cfg->y_end = imgu_css_grid_end(grid_cfg->y_start, grid_cfg->height,
1725 grid_cfg->block_height_log2);
1726}
1727
1728
1729
1730static int imgu_css_cfg_acc_stripe(struct imgu_css *css, unsigned int pipe,
1731 struct imgu_abi_acc_param *acc)
1732{
1733 struct imgu_css_pipe *css_pipe = &css->pipes[pipe];
1734 const struct imgu_fw_info *bi =
1735 &css->fwp->binary_header[css_pipe->bindex];
1736 struct imgu_css_scaler_info scaler_luma, scaler_chroma;
1737 const unsigned int stripes = bi->info.isp.sp.iterator.num_stripes;
1738 const unsigned int f = IPU3_UAPI_ISP_VEC_ELEMS * 2;
1739 unsigned int bds_ds, i;
1740
1741 memset(acc, 0, sizeof(*acc));
1742
1743
1744
1745 if (imgu_css_osys_calc(css, pipe, stripes, &acc->osys, &scaler_luma,
1746 &scaler_chroma, acc->stripe.block_stripes))
1747 return -EINVAL;
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760 acc->stripe.num_of_stripes = stripes;
1761 acc->stripe.input_frame.width =
1762 css_pipe->queue[IPU3_CSS_QUEUE_IN].fmt.mpix.width;
1763 acc->stripe.input_frame.height =
1764 css_pipe->queue[IPU3_CSS_QUEUE_IN].fmt.mpix.height;
1765 acc->stripe.input_frame.bayer_order =
1766 css_pipe->queue[IPU3_CSS_QUEUE_IN].css_fmt->bayer_order;
1767
1768 for (i = 0; i < stripes; i++)
1769 acc->stripe.bds_out_stripes[i].height =
1770 css_pipe->rect[IPU3_CSS_RECT_BDS].height;
1771 acc->stripe.bds_out_stripes[0].offset = 0;
1772 if (stripes <= 1) {
1773 acc->stripe.bds_out_stripes[0].width =
1774 ALIGN(css_pipe->rect[IPU3_CSS_RECT_BDS].width, f);
1775 } else {
1776
1777 acc->stripe.bds_out_stripes[0].width =
1778 acc->stripe.bds_out_stripes[1].width =
1779 (css_pipe->rect[IPU3_CSS_RECT_BDS].width / 2 & ~(f - 1)) + f;
1780
1781
1782
1783
1784
1785 if ((css_pipe->rect[IPU3_CSS_RECT_BDS].width / f & 1) !=
1786 !!(css_pipe->rect[IPU3_CSS_RECT_BDS].width & (f - 1)))
1787 acc->stripe.bds_out_stripes[0].width += f;
1788 if ((css_pipe->rect[IPU3_CSS_RECT_BDS].width / f & 1) &&
1789 (css_pipe->rect[IPU3_CSS_RECT_BDS].width & (f - 1))) {
1790 acc->stripe.bds_out_stripes[0].width += f;
1791 acc->stripe.bds_out_stripes[1].width += f;
1792 }
1793
1794 acc->stripe.bds_out_stripes[1].offset =
1795 acc->stripe.bds_out_stripes[0].width - 2 * f;
1796 }
1797
1798 acc->stripe.effective_stripes[0].height =
1799 css_pipe->rect[IPU3_CSS_RECT_EFFECTIVE].height;
1800 acc->stripe.effective_stripes[0].offset = 0;
1801 acc->stripe.bds_out_stripes_no_overlap[0].height =
1802 css_pipe->rect[IPU3_CSS_RECT_BDS].height;
1803 acc->stripe.bds_out_stripes_no_overlap[0].offset = 0;
1804 acc->stripe.output_stripes[0].height =
1805 css_pipe->queue[IPU3_CSS_QUEUE_OUT].fmt.mpix.height;
1806 acc->stripe.output_stripes[0].offset = 0;
1807 if (stripes <= 1) {
1808 acc->stripe.down_scaled_stripes[0].width =
1809 css_pipe->rect[IPU3_CSS_RECT_BDS].width;
1810 acc->stripe.down_scaled_stripes[0].height =
1811 css_pipe->rect[IPU3_CSS_RECT_BDS].height;
1812 acc->stripe.down_scaled_stripes[0].offset = 0;
1813
1814 acc->stripe.effective_stripes[0].width =
1815 css_pipe->rect[IPU3_CSS_RECT_EFFECTIVE].width;
1816 acc->stripe.bds_out_stripes_no_overlap[0].width =
1817 ALIGN(css_pipe->rect[IPU3_CSS_RECT_BDS].width, f);
1818
1819 acc->stripe.output_stripes[0].width =
1820 css_pipe->queue[IPU3_CSS_QUEUE_OUT].fmt.mpix.width;
1821 } else {
1822 bds_ds = css_pipe->rect[IPU3_CSS_RECT_EFFECTIVE].width *
1823 IMGU_BDS_GRANULARITY /
1824 css_pipe->rect[IPU3_CSS_RECT_BDS].width;
1825
1826 acc->stripe.down_scaled_stripes[0] =
1827 acc->stripe.bds_out_stripes[0];
1828 acc->stripe.down_scaled_stripes[1] =
1829 acc->stripe.bds_out_stripes[1];
1830 if (!IS_ALIGNED(css_pipe->rect[IPU3_CSS_RECT_BDS].width, f))
1831 acc->stripe.down_scaled_stripes[1].width +=
1832 (css_pipe->rect[IPU3_CSS_RECT_BDS].width
1833 & (f - 1)) - f;
1834
1835 acc->stripe.effective_stripes[0].width = bds_ds *
1836 acc->stripe.down_scaled_stripes[0].width /
1837 IMGU_BDS_GRANULARITY;
1838 acc->stripe.effective_stripes[1].width = bds_ds *
1839 acc->stripe.down_scaled_stripes[1].width /
1840 IMGU_BDS_GRANULARITY;
1841 acc->stripe.effective_stripes[1].height =
1842 css_pipe->rect[IPU3_CSS_RECT_EFFECTIVE].height;
1843 acc->stripe.effective_stripes[1].offset = bds_ds *
1844 acc->stripe.down_scaled_stripes[1].offset /
1845 IMGU_BDS_GRANULARITY;
1846
1847 acc->stripe.bds_out_stripes_no_overlap[0].width =
1848 acc->stripe.bds_out_stripes_no_overlap[1].offset =
1849 ALIGN(css_pipe->rect[IPU3_CSS_RECT_BDS].width, 2 * f) / 2;
1850 acc->stripe.bds_out_stripes_no_overlap[1].width =
1851 DIV_ROUND_UP(css_pipe->rect[IPU3_CSS_RECT_BDS].width, f)
1852 / 2 * f;
1853 acc->stripe.bds_out_stripes_no_overlap[1].height =
1854 css_pipe->rect[IPU3_CSS_RECT_BDS].height;
1855
1856 acc->stripe.output_stripes[0].width =
1857 acc->stripe.down_scaled_stripes[0].width - f;
1858 acc->stripe.output_stripes[1].width =
1859 acc->stripe.down_scaled_stripes[1].width - f;
1860 acc->stripe.output_stripes[1].height =
1861 css_pipe->queue[IPU3_CSS_QUEUE_OUT].fmt.mpix.height;
1862 acc->stripe.output_stripes[1].offset =
1863 acc->stripe.output_stripes[0].width;
1864 }
1865
1866 acc->stripe.output_system_in_frame_width =
1867 css_pipe->rect[IPU3_CSS_RECT_GDC].width;
1868 acc->stripe.output_system_in_frame_height =
1869 css_pipe->rect[IPU3_CSS_RECT_GDC].height;
1870
1871 acc->stripe.effective_frame_width =
1872 css_pipe->rect[IPU3_CSS_RECT_EFFECTIVE].width;
1873 acc->stripe.bds_frame_width = css_pipe->rect[IPU3_CSS_RECT_BDS].width;
1874 acc->stripe.out_frame_width =
1875 css_pipe->queue[IPU3_CSS_QUEUE_OUT].fmt.mpix.width;
1876 acc->stripe.out_frame_height =
1877 css_pipe->queue[IPU3_CSS_QUEUE_OUT].fmt.mpix.height;
1878 acc->stripe.gdc_in_buffer_width =
1879 css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_REF].bytesperline /
1880 css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_REF].bytesperpixel;
1881 acc->stripe.gdc_in_buffer_height =
1882 css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_REF].height;
1883 acc->stripe.gdc_in_buffer_offset_x = IMGU_GDC_BUF_X;
1884 acc->stripe.gdc_in_buffer_offset_y = IMGU_GDC_BUF_Y;
1885 acc->stripe.display_frame_width =
1886 css_pipe->queue[IPU3_CSS_QUEUE_VF].fmt.mpix.width;
1887 acc->stripe.display_frame_height =
1888 css_pipe->queue[IPU3_CSS_QUEUE_VF].fmt.mpix.height;
1889 acc->stripe.bds_aligned_frame_width =
1890 roundup(css_pipe->rect[IPU3_CSS_RECT_BDS].width,
1891 2 * IPU3_UAPI_ISP_VEC_ELEMS);
1892
1893 if (stripes > 1)
1894 acc->stripe.half_overlap_vectors =
1895 IMGU_STRIPE_FIXED_HALF_OVERLAP;
1896 else
1897 acc->stripe.half_overlap_vectors = 0;
1898
1899 return 0;
1900}
1901
1902static void imgu_css_cfg_acc_dvs(struct imgu_css *css,
1903 struct imgu_abi_acc_param *acc,
1904 unsigned int pipe)
1905{
1906 unsigned int i;
1907 struct imgu_css_pipe *css_pipe = &css->pipes[pipe];
1908
1909
1910 acc->dvs_stat.operations_data.process_lines_data[0].lines =
1911 css_pipe->rect[IPU3_CSS_RECT_BDS].height;
1912 acc->dvs_stat.operations_data.process_lines_data[0].cfg_set = 0;
1913 acc->dvs_stat.operations_data.ops[0].op_type =
1914 IMGU_ABI_ACC_OPTYPE_PROCESS_LINES;
1915 acc->dvs_stat.operations_data.ops[0].op_indicator =
1916 IMGU_ABI_ACC_OP_NO_OPS;
1917 for (i = 0; i < IMGU_ABI_DVS_STAT_LEVELS; i++)
1918 acc->dvs_stat.cfg.grd_config[i].enable = 0;
1919}
1920
1921static void acc_bds_per_stripe_data(struct imgu_css *css,
1922 struct imgu_abi_acc_param *acc,
1923 const int i, unsigned int pipe)
1924{
1925 struct imgu_css_pipe *css_pipe = &css->pipes[pipe];
1926
1927 acc->bds.per_stripe.aligned_data[i].data.crop.hor_crop_en = 0;
1928 acc->bds.per_stripe.aligned_data[i].data.crop.hor_crop_start = 0;
1929 acc->bds.per_stripe.aligned_data[i].data.crop.hor_crop_end = 0;
1930 acc->bds.per_stripe.aligned_data[i].data.hor_ctrl0 =
1931 acc->bds.hor.hor_ctrl0;
1932 acc->bds.per_stripe.aligned_data[i].data.hor_ctrl0.out_frame_width =
1933 acc->stripe.down_scaled_stripes[i].width;
1934 acc->bds.per_stripe.aligned_data[i].data.ver_ctrl1.out_frame_width =
1935 acc->stripe.down_scaled_stripes[i].width;
1936 acc->bds.per_stripe.aligned_data[i].data.ver_ctrl1.out_frame_height =
1937 css_pipe->rect[IPU3_CSS_RECT_BDS].height;
1938}
1939
1940
1941
1942
1943
1944
1945
1946int imgu_css_cfg_acc(struct imgu_css *css, unsigned int pipe,
1947 struct ipu3_uapi_flags *use,
1948 struct imgu_abi_acc_param *acc,
1949 struct imgu_abi_acc_param *acc_old,
1950 struct ipu3_uapi_acc_param *acc_user)
1951{
1952 struct imgu_css_pipe *css_pipe = &css->pipes[pipe];
1953 const struct imgu_fw_info *bi =
1954 &css->fwp->binary_header[css_pipe->bindex];
1955 const unsigned int stripes = bi->info.isp.sp.iterator.num_stripes;
1956 const unsigned int tnr_frame_width =
1957 acc->stripe.bds_aligned_frame_width;
1958 const unsigned int min_overlap = 10;
1959 const struct v4l2_pix_format_mplane *pixm =
1960 &css_pipe->queue[IPU3_CSS_QUEUE_IN].fmt.mpix;
1961 const struct imgu_css_bds_config *cfg_bds;
1962 struct imgu_abi_input_feeder_data *feeder_data;
1963
1964 unsigned int bds_ds, ofs_x, ofs_y, i, width, height;
1965 u8 b_w_log2;
1966
1967
1968
1969 if (imgu_css_cfg_acc_stripe(css, pipe, acc))
1970 return -EINVAL;
1971
1972
1973
1974 ofs_x = ((pixm->width -
1975 css_pipe->rect[IPU3_CSS_RECT_EFFECTIVE].width) >> 1) & ~1;
1976 ofs_x += css_pipe->queue[IPU3_CSS_QUEUE_IN].css_fmt->bayer_order ==
1977 IMGU_ABI_BAYER_ORDER_RGGB ||
1978 css_pipe->queue[IPU3_CSS_QUEUE_IN].css_fmt->bayer_order ==
1979 IMGU_ABI_BAYER_ORDER_GBRG ? 1 : 0;
1980 ofs_y = ((pixm->height -
1981 css_pipe->rect[IPU3_CSS_RECT_EFFECTIVE].height) >> 1) & ~1;
1982 ofs_y += css_pipe->queue[IPU3_CSS_QUEUE_IN].css_fmt->bayer_order ==
1983 IMGU_ABI_BAYER_ORDER_BGGR ||
1984 css_pipe->queue[IPU3_CSS_QUEUE_IN].css_fmt->bayer_order ==
1985 IMGU_ABI_BAYER_ORDER_GBRG ? 1 : 0;
1986 acc->input_feeder.data.row_stride = pixm->plane_fmt[0].bytesperline;
1987 acc->input_feeder.data.start_row_address =
1988 ofs_x / IMGU_PIXELS_PER_WORD * IMGU_BYTES_PER_WORD +
1989 ofs_y * acc->input_feeder.data.row_stride;
1990 acc->input_feeder.data.start_pixel = ofs_x % IMGU_PIXELS_PER_WORD;
1991
1992 acc->input_feeder.data_per_stripe.input_feeder_data[0].data =
1993 acc->input_feeder.data;
1994
1995 ofs_x += acc->stripe.effective_stripes[1].offset;
1996
1997 feeder_data =
1998 &acc->input_feeder.data_per_stripe.input_feeder_data[1].data;
1999 feeder_data->row_stride = acc->input_feeder.data.row_stride;
2000 feeder_data->start_row_address =
2001 ofs_x / IMGU_PIXELS_PER_WORD * IMGU_BYTES_PER_WORD +
2002 ofs_y * acc->input_feeder.data.row_stride;
2003 feeder_data->start_pixel = ofs_x % IMGU_PIXELS_PER_WORD;
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015 if (use && use->acc_bnr) {
2016
2017 acc->bnr = acc_user->bnr;
2018 } else if (acc_old) {
2019
2020 acc->bnr = acc_old->bnr;
2021 } else {
2022
2023 acc->bnr = imgu_css_bnr_defaults;
2024 }
2025
2026 acc->bnr.column_size = tnr_frame_width;
2027
2028
2029
2030 if (use && use->acc_green_disparity) {
2031
2032 acc->green_disparity = acc_user->green_disparity;
2033 } else if (acc_old) {
2034
2035 acc->green_disparity = acc_old->green_disparity;
2036 } else {
2037
2038 memset(&acc->green_disparity, 0, sizeof(acc->green_disparity));
2039 }
2040
2041
2042
2043 if (use && use->acc_dm) {
2044
2045 acc->dm = acc_user->dm;
2046 } else if (acc_old) {
2047
2048 acc->dm = acc_old->dm;
2049 } else {
2050
2051 acc->dm = imgu_css_dm_defaults;
2052 }
2053
2054 acc->dm.frame_width = tnr_frame_width;
2055
2056
2057
2058 if (use && use->acc_ccm) {
2059
2060 acc->ccm = acc_user->ccm;
2061 } else if (acc_old) {
2062
2063 acc->ccm = acc_old->ccm;
2064 } else {
2065
2066 acc->ccm = imgu_css_ccm_defaults;
2067 }
2068
2069
2070
2071 if (use && use->acc_gamma) {
2072
2073 acc->gamma = acc_user->gamma;
2074 } else if (acc_old) {
2075
2076 acc->gamma = acc_old->gamma;
2077 } else {
2078
2079 acc->gamma.gc_ctrl.enable = 1;
2080 acc->gamma.gc_lut = imgu_css_gamma_lut;
2081 }
2082
2083
2084
2085 if (use && use->acc_csc) {
2086
2087 acc->csc = acc_user->csc;
2088 } else if (acc_old) {
2089
2090 acc->csc = acc_old->csc;
2091 } else {
2092
2093 acc->csc = imgu_css_csc_defaults;
2094 }
2095
2096
2097
2098 if (use && use->acc_cds) {
2099
2100 acc->cds = acc_user->cds;
2101 } else if (acc_old) {
2102
2103 acc->cds = acc_old->cds;
2104 } else {
2105
2106 acc->cds = imgu_css_cds_defaults;
2107 }
2108
2109
2110
2111 if (use && use->acc_shd) {
2112
2113 acc->shd.shd = acc_user->shd.shd;
2114 acc->shd.shd_lut = acc_user->shd.shd_lut;
2115 } else if (acc_old) {
2116
2117 acc->shd.shd = acc_old->shd.shd;
2118 acc->shd.shd_lut = acc_old->shd.shd_lut;
2119 } else {
2120
2121 acc->shd.shd = imgu_css_shd_defaults;
2122 memset(&acc->shd.shd_lut, 0, sizeof(acc->shd.shd_lut));
2123 }
2124
2125 if (acc->shd.shd.grid.width <= 0)
2126 return -EINVAL;
2127
2128 acc->shd.shd.grid.grid_height_per_slice =
2129 IMGU_ABI_SHD_MAX_CELLS_PER_SET / acc->shd.shd.grid.width;
2130
2131 if (acc->shd.shd.grid.grid_height_per_slice <= 0)
2132 return -EINVAL;
2133
2134 acc->shd.shd.general.init_set_vrt_offst_ul =
2135 (-acc->shd.shd.grid.y_start >>
2136 acc->shd.shd.grid.block_height_log2) %
2137 acc->shd.shd.grid.grid_height_per_slice;
2138
2139 if (imgu_css_shd_ops_calc(&acc->shd.shd_ops, &acc->shd.shd.grid,
2140 css_pipe->rect[IPU3_CSS_RECT_BDS].height))
2141 return -EINVAL;
2142
2143
2144 imgu_css_cfg_acc_dvs(css, acc, pipe);
2145
2146
2147
2148 if (use && use->acc_iefd) {
2149
2150 acc->iefd = acc_user->iefd;
2151 } else if (acc_old) {
2152
2153 acc->iefd = acc_old->iefd;
2154 } else {
2155
2156 acc->iefd = imgu_css_iefd_defaults;
2157 }
2158
2159
2160
2161 if (use && use->acc_yds_c0) {
2162
2163 acc->yds_c0 = acc_user->yds_c0;
2164 } else if (acc_old) {
2165
2166 acc->yds_c0 = acc_old->yds_c0;
2167 } else {
2168
2169 acc->yds_c0 = imgu_css_yds_defaults;
2170 }
2171
2172
2173
2174 if (use && use->acc_chnr_c0) {
2175
2176 acc->chnr_c0 = acc_user->chnr_c0;
2177 } else if (acc_old) {
2178
2179 acc->chnr_c0 = acc_old->chnr_c0;
2180 } else {
2181
2182 acc->chnr_c0 = imgu_css_chnr_defaults;
2183 }
2184
2185
2186
2187 if (use && use->acc_y_ee_nr) {
2188
2189 acc->y_ee_nr = acc_user->y_ee_nr;
2190 } else if (acc_old) {
2191
2192 acc->y_ee_nr = acc_old->y_ee_nr;
2193 } else {
2194
2195 acc->y_ee_nr = imgu_css_y_ee_nr_defaults;
2196 }
2197
2198
2199
2200 if (use && use->acc_yds) {
2201
2202 acc->yds = acc_user->yds;
2203 } else if (acc_old) {
2204
2205 acc->yds = acc_old->yds;
2206 } else {
2207
2208 acc->yds = imgu_css_yds_defaults;
2209 }
2210
2211
2212
2213 if (use && use->acc_chnr) {
2214
2215 acc->chnr = acc_user->chnr;
2216 } else if (acc_old) {
2217
2218 acc->chnr = acc_old->chnr;
2219 } else {
2220
2221 acc->chnr = imgu_css_chnr_defaults;
2222 }
2223
2224
2225
2226 for (i = 0; i < IMGU_ABI_YUVP2_YTM_LUT_ENTRIES; i++)
2227 acc->ytm.entries[i] = i * 32;
2228 acc->ytm.enable = 0;
2229
2230
2231
2232 if (use && use->acc_yds2) {
2233
2234 acc->yds2 = acc_user->yds2;
2235 } else if (acc_old) {
2236
2237 acc->yds2 = acc_old->yds2;
2238 } else {
2239
2240 acc->yds2 = imgu_css_yds_defaults;
2241 }
2242
2243
2244
2245 if (use && use->acc_tcc) {
2246
2247 acc->tcc = acc_user->tcc;
2248 } else if (acc_old) {
2249
2250 acc->tcc = acc_old->tcc;
2251 } else {
2252
2253 memset(&acc->tcc, 0, sizeof(acc->tcc));
2254
2255 acc->tcc.gen_control.en = 1;
2256 acc->tcc.gen_control.blend_shift = 3;
2257 acc->tcc.gen_control.gain_according_to_y_only = 1;
2258 acc->tcc.gen_control.gamma = 8;
2259 acc->tcc.gen_control.delta = 0;
2260
2261 for (i = 0; i < IPU3_UAPI_YUVP2_TCC_MACC_TABLE_ELEMENTS; i++) {
2262 acc->tcc.macc_table.entries[i].a = 1024;
2263 acc->tcc.macc_table.entries[i].b = 0;
2264 acc->tcc.macc_table.entries[i].c = 0;
2265 acc->tcc.macc_table.entries[i].d = 1024;
2266 }
2267
2268 acc->tcc.inv_y_lut.entries[6] = 1023;
2269 for (i = 7; i < IPU3_UAPI_YUVP2_TCC_INV_Y_LUT_ELEMENTS; i++)
2270 acc->tcc.inv_y_lut.entries[i] = 1024 >> (i - 6);
2271
2272 acc->tcc.gain_pcwl = imgu_css_tcc_gain_pcwl_lut;
2273 acc->tcc.r_sqr_lut = imgu_css_tcc_r_sqr_lut;
2274 }
2275
2276
2277
2278 if (use && use->acc_dpc)
2279 return -EINVAL;
2280
2281
2282 memset(&acc->dpc, 0, sizeof(acc->dpc));
2283
2284
2285
2286 bds_ds = (css_pipe->rect[IPU3_CSS_RECT_EFFECTIVE].height *
2287 IMGU_BDS_GRANULARITY) / css_pipe->rect[IPU3_CSS_RECT_BDS].height;
2288 if (bds_ds < IMGU_BDS_MIN_SF_INV ||
2289 bds_ds - IMGU_BDS_MIN_SF_INV >= ARRAY_SIZE(imgu_css_bds_configs))
2290 return -EINVAL;
2291
2292 cfg_bds = &imgu_css_bds_configs[bds_ds - IMGU_BDS_MIN_SF_INV];
2293 acc->bds.hor.hor_ctrl1.hor_crop_en = 0;
2294 acc->bds.hor.hor_ctrl1.hor_crop_start = 0;
2295 acc->bds.hor.hor_ctrl1.hor_crop_end = 0;
2296 acc->bds.hor.hor_ctrl0.sample_patrn_length =
2297 cfg_bds->sample_patrn_length;
2298 acc->bds.hor.hor_ctrl0.hor_ds_en = cfg_bds->hor_ds_en;
2299 acc->bds.hor.hor_ctrl0.min_clip_val = IMGU_BDS_MIN_CLIP_VAL;
2300 acc->bds.hor.hor_ctrl0.max_clip_val = IMGU_BDS_MAX_CLIP_VAL;
2301 acc->bds.hor.hor_ctrl0.out_frame_width =
2302 css_pipe->rect[IPU3_CSS_RECT_BDS].width;
2303 acc->bds.hor.hor_ptrn_arr = cfg_bds->ptrn_arr;
2304 acc->bds.hor.hor_phase_arr = cfg_bds->hor_phase_arr;
2305 acc->bds.hor.hor_ctrl2.input_frame_height =
2306 css_pipe->rect[IPU3_CSS_RECT_EFFECTIVE].height;
2307 acc->bds.ver.ver_ctrl0.min_clip_val = IMGU_BDS_MIN_CLIP_VAL;
2308 acc->bds.ver.ver_ctrl0.max_clip_val = IMGU_BDS_MAX_CLIP_VAL;
2309 acc->bds.ver.ver_ctrl0.sample_patrn_length =
2310 cfg_bds->sample_patrn_length;
2311 acc->bds.ver.ver_ctrl0.ver_ds_en = cfg_bds->ver_ds_en;
2312 acc->bds.ver.ver_ptrn_arr = cfg_bds->ptrn_arr;
2313 acc->bds.ver.ver_phase_arr = cfg_bds->ver_phase_arr;
2314 acc->bds.ver.ver_ctrl1.out_frame_width =
2315 css_pipe->rect[IPU3_CSS_RECT_BDS].width;
2316 acc->bds.ver.ver_ctrl1.out_frame_height =
2317 css_pipe->rect[IPU3_CSS_RECT_BDS].height;
2318 for (i = 0; i < stripes; i++)
2319 acc_bds_per_stripe_data(css, acc, i, pipe);
2320
2321 acc->bds.enabled = cfg_bds->hor_ds_en || cfg_bds->ver_ds_en;
2322
2323
2324
2325 if (use && use->acc_anr) {
2326
2327 acc->anr.transform = acc_user->anr.transform;
2328 acc->anr.stitch.anr_stitch_en =
2329 acc_user->anr.stitch.anr_stitch_en;
2330 memcpy(acc->anr.stitch.pyramid, acc_user->anr.stitch.pyramid,
2331 sizeof(acc->anr.stitch.pyramid));
2332 } else if (acc_old) {
2333
2334 acc->anr.transform = acc_old->anr.transform;
2335 acc->anr.stitch.anr_stitch_en =
2336 acc_old->anr.stitch.anr_stitch_en;
2337 memcpy(acc->anr.stitch.pyramid, acc_old->anr.stitch.pyramid,
2338 sizeof(acc->anr.stitch.pyramid));
2339 } else {
2340
2341 acc->anr = imgu_css_anr_defaults;
2342 }
2343
2344
2345 acc->anr.search.enable = 1;
2346 acc->anr.transform.enable = 1;
2347 acc->anr.tile2strm.enable = 1;
2348 acc->anr.tile2strm.frame_width =
2349 ALIGN(css_pipe->rect[IPU3_CSS_RECT_BDS].width, IMGU_ISP_VMEM_ALIGN);
2350 acc->anr.search.frame_width = acc->anr.tile2strm.frame_width;
2351 acc->anr.stitch.frame_width = acc->anr.tile2strm.frame_width;
2352 acc->anr.tile2strm.frame_height = css_pipe->rect[IPU3_CSS_RECT_BDS].height;
2353 acc->anr.search.frame_height = acc->anr.tile2strm.frame_height;
2354 acc->anr.stitch.frame_height = acc->anr.tile2strm.frame_height;
2355
2356 width = ALIGN(css_pipe->rect[IPU3_CSS_RECT_BDS].width, IMGU_ISP_VMEM_ALIGN);
2357 height = css_pipe->rect[IPU3_CSS_RECT_BDS].height;
2358
2359 if (acc->anr.transform.xreset + width > IPU3_UAPI_ANR_MAX_RESET)
2360 acc->anr.transform.xreset = IPU3_UAPI_ANR_MAX_RESET - width;
2361 if (acc->anr.transform.xreset < IPU3_UAPI_ANR_MIN_RESET)
2362 acc->anr.transform.xreset = IPU3_UAPI_ANR_MIN_RESET;
2363
2364 if (acc->anr.transform.yreset + height > IPU3_UAPI_ANR_MAX_RESET)
2365 acc->anr.transform.yreset = IPU3_UAPI_ANR_MAX_RESET - height;
2366 if (acc->anr.transform.yreset < IPU3_UAPI_ANR_MIN_RESET)
2367 acc->anr.transform.yreset = IPU3_UAPI_ANR_MIN_RESET;
2368
2369
2370
2371 if (use && use->acc_awb_fr) {
2372
2373 acc->awb_fr.config = acc_user->awb_fr;
2374 } else if (acc_old) {
2375
2376 acc->awb_fr.config = acc_old->awb_fr.config;
2377 } else {
2378
2379 acc->awb_fr.config = imgu_css_awb_fr_defaults;
2380 }
2381
2382 imgu_css_grid_end_calc(&acc->awb_fr.config.grid_cfg);
2383
2384 if (acc->awb_fr.config.grid_cfg.width <= 0)
2385 return -EINVAL;
2386
2387 acc->awb_fr.config.grid_cfg.height_per_slice =
2388 IMGU_ABI_AWB_FR_MAX_CELLS_PER_SET /
2389 acc->awb_fr.config.grid_cfg.width;
2390
2391 for (i = 0; i < stripes; i++)
2392 acc->awb_fr.stripes[i] = acc->awb_fr.config;
2393
2394 if (acc->awb_fr.config.grid_cfg.x_start >=
2395 acc->stripe.down_scaled_stripes[1].offset + min_overlap) {
2396
2397 acc->awb_fr.stripes[0].grid_cfg.y_start &=
2398 ~IPU3_UAPI_GRID_Y_START_EN;
2399 } else if (acc->awb_fr.config.grid_cfg.x_end <=
2400 acc->stripe.bds_out_stripes[0].width - min_overlap) {
2401
2402 acc->awb_fr.stripes[1].grid_cfg.y_start &=
2403 ~IPU3_UAPI_GRID_Y_START_EN;
2404 } else {
2405
2406 u16 end;
2407
2408 acc->awb_fr.stripes[0].grid_cfg.width =
2409 (acc->stripe.bds_out_stripes[0].width - min_overlap -
2410 acc->awb_fr.config.grid_cfg.x_start + 1) >>
2411 acc->awb_fr.config.grid_cfg.block_width_log2;
2412 acc->awb_fr.stripes[1].grid_cfg.width =
2413 acc->awb_fr.config.grid_cfg.width -
2414 acc->awb_fr.stripes[0].grid_cfg.width;
2415
2416 b_w_log2 = acc->awb_fr.stripes[0].grid_cfg.block_width_log2;
2417 end = imgu_css_grid_end(acc->awb_fr.stripes[0].grid_cfg.x_start,
2418 acc->awb_fr.stripes[0].grid_cfg.width,
2419 b_w_log2);
2420 acc->awb_fr.stripes[0].grid_cfg.x_end = end;
2421
2422 acc->awb_fr.stripes[1].grid_cfg.x_start =
2423 (acc->awb_fr.stripes[0].grid_cfg.x_end + 1 -
2424 acc->stripe.down_scaled_stripes[1].offset) &
2425 IPU3_UAPI_GRID_START_MASK;
2426 b_w_log2 = acc->awb_fr.stripes[1].grid_cfg.block_width_log2;
2427 end = imgu_css_grid_end(acc->awb_fr.stripes[1].grid_cfg.x_start,
2428 acc->awb_fr.stripes[1].grid_cfg.width,
2429 b_w_log2);
2430 acc->awb_fr.stripes[1].grid_cfg.x_end = end;
2431
2432
2433
2434
2435
2436
2437 for (i = 0; i < stripes; i++)
2438 acc->awb_fr.stripes[i].grid_cfg.height_per_slice = 1;
2439 }
2440
2441 if (imgu_css_awb_fr_ops_calc(css, pipe, &acc->awb_fr))
2442 return -EINVAL;
2443
2444
2445
2446 if (use && use->acc_ae) {
2447
2448 acc->ae.grid_cfg = acc_user->ae.grid_cfg;
2449 acc->ae.ae_ccm = acc_user->ae.ae_ccm;
2450 for (i = 0; i < IPU3_UAPI_AE_WEIGHTS; i++)
2451 acc->ae.weights[i] = acc_user->ae.weights[i];
2452 } else if (acc_old) {
2453
2454 acc->ae.grid_cfg = acc_old->ae.grid_cfg;
2455 acc->ae.ae_ccm = acc_old->ae.ae_ccm;
2456 for (i = 0; i < IPU3_UAPI_AE_WEIGHTS; i++)
2457 acc->ae.weights[i] = acc_old->ae.weights[i];
2458 } else {
2459
2460 static const struct ipu3_uapi_ae_weight_elem
2461 weight_def = { 1, 1, 1, 1, 1, 1, 1, 1 };
2462
2463 acc->ae.grid_cfg = imgu_css_ae_grid_defaults;
2464 acc->ae.ae_ccm = imgu_css_ae_ccm_defaults;
2465 for (i = 0; i < IPU3_UAPI_AE_WEIGHTS; i++)
2466 acc->ae.weights[i] = weight_def;
2467 }
2468
2469 b_w_log2 = acc->ae.grid_cfg.block_width_log2;
2470 acc->ae.grid_cfg.x_end = imgu_css_grid_end(acc->ae.grid_cfg.x_start,
2471 acc->ae.grid_cfg.width,
2472 b_w_log2);
2473 b_w_log2 = acc->ae.grid_cfg.block_height_log2;
2474 acc->ae.grid_cfg.y_end = imgu_css_grid_end(acc->ae.grid_cfg.y_start,
2475 acc->ae.grid_cfg.height,
2476 b_w_log2);
2477
2478 for (i = 0; i < stripes; i++)
2479 acc->ae.stripes[i].grid = acc->ae.grid_cfg;
2480
2481 if (acc->ae.grid_cfg.x_start >=
2482 acc->stripe.down_scaled_stripes[1].offset) {
2483
2484 acc->ae.stripes[0].grid.ae_en = 0;
2485 } else if (acc->ae.grid_cfg.x_end <=
2486 acc->stripe.bds_out_stripes[0].width) {
2487
2488 acc->ae.stripes[1].grid.ae_en = 0;
2489 } else {
2490
2491 u8 b_w_log2;
2492
2493 acc->ae.stripes[0].grid.width =
2494 (acc->stripe.bds_out_stripes[0].width -
2495 acc->ae.grid_cfg.x_start + 1) >>
2496 acc->ae.grid_cfg.block_width_log2;
2497
2498 acc->ae.stripes[1].grid.width =
2499 acc->ae.grid_cfg.width - acc->ae.stripes[0].grid.width;
2500
2501 b_w_log2 = acc->ae.stripes[0].grid.block_width_log2;
2502 acc->ae.stripes[0].grid.x_end =
2503 imgu_css_grid_end(acc->ae.stripes[0].grid.x_start,
2504 acc->ae.stripes[0].grid.width,
2505 b_w_log2);
2506
2507 acc->ae.stripes[1].grid.x_start =
2508 (acc->ae.stripes[0].grid.x_end + 1 -
2509 acc->stripe.down_scaled_stripes[1].offset) &
2510 IPU3_UAPI_GRID_START_MASK;
2511 b_w_log2 = acc->ae.stripes[1].grid.block_width_log2;
2512 acc->ae.stripes[1].grid.x_end =
2513 imgu_css_grid_end(acc->ae.stripes[1].grid.x_start,
2514 acc->ae.stripes[1].grid.width,
2515 b_w_log2);
2516 }
2517
2518
2519
2520 if (use && use->acc_af) {
2521
2522 acc->af.config.filter_config = acc_user->af.filter_config;
2523 acc->af.config.grid_cfg = acc_user->af.grid_cfg;
2524 } else if (acc_old) {
2525
2526 acc->af.config = acc_old->af.config;
2527 } else {
2528
2529 acc->af.config.filter_config =
2530 imgu_css_af_defaults.filter_config;
2531 acc->af.config.grid_cfg = imgu_css_af_defaults.grid_cfg;
2532 }
2533
2534 imgu_css_grid_end_calc(&acc->af.config.grid_cfg);
2535
2536 if (acc->af.config.grid_cfg.width <= 0)
2537 return -EINVAL;
2538
2539 acc->af.config.grid_cfg.height_per_slice =
2540 IMGU_ABI_AF_MAX_CELLS_PER_SET / acc->af.config.grid_cfg.width;
2541 acc->af.config.frame_size.width =
2542 ALIGN(css_pipe->rect[IPU3_CSS_RECT_BDS].width, IMGU_ISP_VMEM_ALIGN);
2543 acc->af.config.frame_size.height =
2544 css_pipe->rect[IPU3_CSS_RECT_BDS].height;
2545
2546 if (acc->stripe.bds_out_stripes[0].width <= min_overlap)
2547 return -EINVAL;
2548
2549 for (i = 0; i < stripes; i++) {
2550 acc->af.stripes[i].grid_cfg = acc->af.config.grid_cfg;
2551 acc->af.stripes[i].frame_size.height =
2552 css_pipe->rect[IPU3_CSS_RECT_BDS].height;
2553 acc->af.stripes[i].frame_size.width =
2554 acc->stripe.bds_out_stripes[i].width;
2555 }
2556
2557 if (acc->af.config.grid_cfg.x_start >=
2558 acc->stripe.down_scaled_stripes[1].offset + min_overlap) {
2559
2560 acc->af.stripes[0].grid_cfg.y_start &=
2561 ~IPU3_UAPI_GRID_Y_START_EN;
2562 } else if (acc->af.config.grid_cfg.x_end <=
2563 acc->stripe.bds_out_stripes[0].width - min_overlap) {
2564
2565 acc->af.stripes[1].grid_cfg.y_start &=
2566 ~IPU3_UAPI_GRID_Y_START_EN;
2567 } else {
2568
2569
2570 acc->af.stripes[0].grid_cfg.width =
2571 (acc->stripe.bds_out_stripes[0].width - min_overlap -
2572 acc->af.config.grid_cfg.x_start + 1) >>
2573 acc->af.config.grid_cfg.block_width_log2;
2574 acc->af.stripes[1].grid_cfg.width =
2575 acc->af.config.grid_cfg.width -
2576 acc->af.stripes[0].grid_cfg.width;
2577
2578 b_w_log2 = acc->af.stripes[0].grid_cfg.block_width_log2;
2579 acc->af.stripes[0].grid_cfg.x_end =
2580 imgu_css_grid_end(acc->af.stripes[0].grid_cfg.x_start,
2581 acc->af.stripes[0].grid_cfg.width,
2582 b_w_log2);
2583
2584 acc->af.stripes[1].grid_cfg.x_start =
2585 (acc->af.stripes[0].grid_cfg.x_end + 1 -
2586 acc->stripe.down_scaled_stripes[1].offset) &
2587 IPU3_UAPI_GRID_START_MASK;
2588
2589 b_w_log2 = acc->af.stripes[1].grid_cfg.block_width_log2;
2590 acc->af.stripes[1].grid_cfg.x_end =
2591 imgu_css_grid_end(acc->af.stripes[1].grid_cfg.x_start,
2592 acc->af.stripes[1].grid_cfg.width,
2593 b_w_log2);
2594
2595
2596
2597
2598
2599 for (i = 0; i < stripes; i++)
2600 acc->af.stripes[i].grid_cfg.height_per_slice = 1;
2601 }
2602
2603 if (imgu_css_af_ops_calc(css, pipe, &acc->af))
2604 return -EINVAL;
2605
2606
2607
2608 if (use && use->acc_awb) {
2609
2610 acc->awb.config = acc_user->awb.config;
2611 } else if (acc_old) {
2612
2613 acc->awb.config = acc_old->awb.config;
2614 } else {
2615
2616 acc->awb.config = imgu_css_awb_defaults;
2617 }
2618
2619 if (acc->awb.config.grid.width <= 0)
2620 return -EINVAL;
2621
2622 acc->awb.config.grid.height_per_slice =
2623 IMGU_ABI_AWB_MAX_CELLS_PER_SET / acc->awb.config.grid.width,
2624 imgu_css_grid_end_calc(&acc->awb.config.grid);
2625
2626 for (i = 0; i < stripes; i++)
2627 acc->awb.stripes[i] = acc->awb.config;
2628
2629 if (acc->awb.config.grid.x_start >=
2630 acc->stripe.down_scaled_stripes[1].offset + min_overlap) {
2631
2632 acc->awb.stripes[0].rgbs_thr_b &= ~IPU3_UAPI_AWB_RGBS_THR_B_EN;
2633 } else if (acc->awb.config.grid.x_end <=
2634 acc->stripe.bds_out_stripes[0].width - min_overlap) {
2635
2636 acc->awb.stripes[1].rgbs_thr_b &= ~IPU3_UAPI_AWB_RGBS_THR_B_EN;
2637 } else {
2638
2639
2640 acc->awb.stripes[0].grid.width =
2641 (acc->stripe.bds_out_stripes[0].width -
2642 acc->awb.config.grid.x_start + 1) >>
2643 acc->awb.config.grid.block_width_log2;
2644 acc->awb.stripes[1].grid.width = acc->awb.config.grid.width -
2645 acc->awb.stripes[0].grid.width;
2646
2647 b_w_log2 = acc->awb.stripes[0].grid.block_width_log2;
2648 acc->awb.stripes[0].grid.x_end =
2649 imgu_css_grid_end(acc->awb.stripes[0].grid.x_start,
2650 acc->awb.stripes[0].grid.width,
2651 b_w_log2);
2652
2653 acc->awb.stripes[1].grid.x_start =
2654 (acc->awb.stripes[0].grid.x_end + 1 -
2655 acc->stripe.down_scaled_stripes[1].offset) &
2656 IPU3_UAPI_GRID_START_MASK;
2657
2658 b_w_log2 = acc->awb.stripes[1].grid.block_width_log2;
2659 acc->awb.stripes[1].grid.x_end =
2660 imgu_css_grid_end(acc->awb.stripes[1].grid.x_start,
2661 acc->awb.stripes[1].grid.width,
2662 b_w_log2);
2663
2664
2665
2666
2667
2668 for (i = 0; i < stripes; i++)
2669 acc->awb.stripes[i].grid.height_per_slice = 1;
2670 }
2671
2672 if (imgu_css_awb_ops_calc(css, pipe, &acc->awb))
2673 return -EINVAL;
2674
2675 return 0;
2676}
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687static void *imgu_css_cfg_copy(struct imgu_css *css,
2688 unsigned int pipe, bool use_user,
2689 void *user_setting, void *old_binary_params,
2690 void *new_binary_params,
2691 enum imgu_abi_memories m,
2692 struct imgu_fw_isp_parameter *par,
2693 size_t par_size)
2694{
2695 const enum imgu_abi_param_class c = IMGU_ABI_PARAM_CLASS_PARAM;
2696 void *new_setting, *old_setting;
2697
2698 new_setting = imgu_css_fw_pipeline_params(css, pipe, c, m, par,
2699 par_size, new_binary_params);
2700 if (!new_setting)
2701 return ERR_PTR(-EPROTO);
2702
2703 if (use_user) {
2704
2705 memcpy(new_setting, user_setting, par_size);
2706 } else if (old_binary_params) {
2707
2708 old_setting = imgu_css_fw_pipeline_params(css, pipe, c, m, par,
2709 par_size,
2710 old_binary_params);
2711 if (!old_setting)
2712 return ERR_PTR(-EPROTO);
2713 memcpy(new_setting, old_setting, par_size);
2714 } else {
2715 return new_setting;
2716 }
2717
2718 return NULL;
2719}
2720
2721
2722
2723
2724int imgu_css_cfg_vmem0(struct imgu_css *css, unsigned int pipe,
2725 struct ipu3_uapi_flags *use,
2726 void *vmem0, void *vmem0_old,
2727 struct ipu3_uapi_params *user)
2728{
2729 const struct imgu_fw_info *bi =
2730 &css->fwp->binary_header[css->pipes[pipe].bindex];
2731 struct imgu_fw_param_memory_offsets *pofs = (void *)css->fwp +
2732 bi->blob.memory_offsets.offsets[IMGU_ABI_PARAM_CLASS_PARAM];
2733 struct ipu3_uapi_isp_lin_vmem_params *lin_vmem = NULL;
2734 struct ipu3_uapi_isp_tnr3_vmem_params *tnr_vmem = NULL;
2735 struct ipu3_uapi_isp_xnr3_vmem_params *xnr_vmem = NULL;
2736 const enum imgu_abi_param_class c = IMGU_ABI_PARAM_CLASS_PARAM;
2737 const enum imgu_abi_memories m = IMGU_ABI_MEM_ISP_VMEM0;
2738 unsigned int i;
2739
2740
2741
2742 memset(vmem0, 0, bi->info.isp.sp.mem_initializers.params[c][m].size);
2743
2744
2745
2746 lin_vmem = imgu_css_cfg_copy(css, pipe, use && use->lin_vmem_params,
2747 &user->lin_vmem_params, vmem0_old, vmem0,
2748 m, &pofs->vmem.lin, sizeof(*lin_vmem));
2749 if (!IS_ERR_OR_NULL(lin_vmem)) {
2750
2751 for (i = 0; i < IPU3_UAPI_LIN_LUT_SIZE; i++) {
2752 lin_vmem->lin_lutlow_gr[i] = 32 * i;
2753 lin_vmem->lin_lutlow_r[i] = 32 * i;
2754 lin_vmem->lin_lutlow_b[i] = 32 * i;
2755 lin_vmem->lin_lutlow_gb[i] = 32 * i;
2756
2757 lin_vmem->lin_lutdif_gr[i] = 32;
2758 lin_vmem->lin_lutdif_r[i] = 32;
2759 lin_vmem->lin_lutdif_b[i] = 32;
2760 lin_vmem->lin_lutdif_gb[i] = 32;
2761 }
2762 }
2763
2764
2765 if (css->pipes[pipe].pipe_id == IPU3_CSS_PIPE_ID_VIDEO) {
2766 tnr_vmem = imgu_css_cfg_copy(css, pipe,
2767 use && use->tnr3_vmem_params,
2768 &user->tnr3_vmem_params,
2769 vmem0_old, vmem0, m,
2770 &pofs->vmem.tnr3,
2771 sizeof(*tnr_vmem));
2772 if (!IS_ERR_OR_NULL(tnr_vmem)) {
2773
2774 for (i = 0; i < IPU3_UAPI_ISP_TNR3_VMEM_LEN; i++)
2775 tnr_vmem->sigma[i] = 256;
2776 }
2777 }
2778 i = IPU3_UAPI_ISP_TNR3_VMEM_LEN;
2779
2780
2781
2782 xnr_vmem = imgu_css_cfg_copy(css, pipe, use && use->xnr3_vmem_params,
2783 &user->xnr3_vmem_params, vmem0_old, vmem0,
2784 m, &pofs->vmem.xnr3, sizeof(*xnr_vmem));
2785 if (!IS_ERR_OR_NULL(xnr_vmem)) {
2786 xnr_vmem->x[i] = imgu_css_xnr3_vmem_defaults.x
2787 [i % IMGU_XNR3_VMEM_LUT_LEN];
2788 xnr_vmem->a[i] = imgu_css_xnr3_vmem_defaults.a
2789 [i % IMGU_XNR3_VMEM_LUT_LEN];
2790 xnr_vmem->b[i] = imgu_css_xnr3_vmem_defaults.b
2791 [i % IMGU_XNR3_VMEM_LUT_LEN];
2792 xnr_vmem->c[i] = imgu_css_xnr3_vmem_defaults.c
2793 [i % IMGU_XNR3_VMEM_LUT_LEN];
2794 }
2795
2796 return IS_ERR(lin_vmem) || IS_ERR(tnr_vmem) || IS_ERR(xnr_vmem) ?
2797 -EPROTO : 0;
2798}
2799
2800
2801
2802
2803int imgu_css_cfg_dmem0(struct imgu_css *css, unsigned int pipe,
2804 struct ipu3_uapi_flags *use,
2805 void *dmem0, void *dmem0_old,
2806 struct ipu3_uapi_params *user)
2807{
2808 struct imgu_css_pipe *css_pipe = &css->pipes[pipe];
2809 const struct imgu_fw_info *bi =
2810 &css->fwp->binary_header[css_pipe->bindex];
2811 struct imgu_fw_param_memory_offsets *pofs = (void *)css->fwp +
2812 bi->blob.memory_offsets.offsets[IMGU_ABI_PARAM_CLASS_PARAM];
2813
2814 struct ipu3_uapi_isp_tnr3_params *tnr_dmem = NULL;
2815 struct ipu3_uapi_isp_xnr3_params *xnr_dmem;
2816
2817 const enum imgu_abi_param_class c = IMGU_ABI_PARAM_CLASS_PARAM;
2818 const enum imgu_abi_memories m = IMGU_ABI_MEM_ISP_DMEM0;
2819
2820
2821
2822 memset(dmem0, 0, bi->info.isp.sp.mem_initializers.params[c][m].size);
2823
2824
2825 if (css_pipe->pipe_id == IPU3_CSS_PIPE_ID_VIDEO) {
2826 tnr_dmem = imgu_css_cfg_copy(css, pipe,
2827 use && use->tnr3_dmem_params,
2828 &user->tnr3_dmem_params,
2829 dmem0_old, dmem0, m,
2830 &pofs->dmem.tnr3,
2831 sizeof(*tnr_dmem));
2832 if (!IS_ERR_OR_NULL(tnr_dmem)) {
2833
2834 tnr_dmem->knee_y1 = 768;
2835 tnr_dmem->knee_y2 = 1280;
2836 }
2837 }
2838
2839
2840
2841 xnr_dmem = imgu_css_cfg_copy(css, pipe, use && use->xnr3_dmem_params,
2842 &user->xnr3_dmem_params, dmem0_old, dmem0,
2843 m, &pofs->dmem.xnr3, sizeof(*xnr_dmem));
2844 if (!IS_ERR_OR_NULL(xnr_dmem)) {
2845
2846 xnr_dmem->alpha.y0 = 2047;
2847 xnr_dmem->alpha.u0 = 2047;
2848 xnr_dmem->alpha.v0 = 2047;
2849 }
2850
2851 return IS_ERR(tnr_dmem) || IS_ERR(xnr_dmem) ? -EPROTO : 0;
2852}
2853
2854
2855void imgu_css_cfg_gdc_table(struct imgu_abi_gdc_warp_param *gdc,
2856 int frame_in_x, int frame_in_y,
2857 int frame_out_x, int frame_out_y,
2858 int env_w, int env_h)
2859{
2860 static const unsigned int FRAC_BITS = IMGU_ABI_GDC_FRAC_BITS;
2861 static const unsigned int XMEM_ALIGN = 1 << 4;
2862 const unsigned int XMEM_ALIGN_MASK = ~(XMEM_ALIGN - 1);
2863 static const unsigned int BCI_ENV = 4;
2864 static const unsigned int BYP = 2;
2865 const unsigned int OFFSET_X = 2 * IMGU_DVS_BLOCK_W + env_w + 1;
2866 const unsigned int OFFSET_Y = IMGU_DVS_BLOCK_H + env_h + 1;
2867
2868 struct imgu_abi_gdc_warp_param gdc_luma, gdc_chroma;
2869
2870 unsigned int blocks_x = ALIGN(DIV_ROUND_UP(frame_out_x,
2871 IMGU_DVS_BLOCK_W), 2);
2872 unsigned int blocks_y = DIV_ROUND_UP(frame_out_y, IMGU_DVS_BLOCK_H);
2873 unsigned int y0, x0, x1, x, y;
2874
2875
2876 gdc_luma.origin_x = 0;
2877 gdc_luma.origin_y = 0;
2878 gdc_luma.p0_x = (OFFSET_X - (OFFSET_X & XMEM_ALIGN_MASK)) << FRAC_BITS;
2879 gdc_luma.p0_y = 0;
2880 gdc_luma.p1_x = gdc_luma.p0_x + (IMGU_DVS_BLOCK_W << FRAC_BITS);
2881 gdc_luma.p1_y = gdc_luma.p0_y;
2882 gdc_luma.p2_x = gdc_luma.p0_x;
2883 gdc_luma.p2_y = gdc_luma.p0_y + (IMGU_DVS_BLOCK_H << FRAC_BITS);
2884 gdc_luma.p3_x = gdc_luma.p1_x;
2885 gdc_luma.p3_y = gdc_luma.p2_y;
2886
2887 gdc_luma.in_block_width = IMGU_DVS_BLOCK_W + BCI_ENV +
2888 OFFSET_X - (OFFSET_X & XMEM_ALIGN_MASK);
2889 gdc_luma.in_block_width_a = DIV_ROUND_UP(gdc_luma.in_block_width,
2890 IPU3_UAPI_ISP_VEC_ELEMS);
2891 gdc_luma.in_block_width_b = DIV_ROUND_UP(gdc_luma.in_block_width,
2892 IMGU_ABI_ISP_DDR_WORD_BYTES /
2893 BYP);
2894 gdc_luma.in_block_height = IMGU_DVS_BLOCK_H + BCI_ENV;
2895 gdc_luma.padding = 0;
2896
2897
2898 gdc_chroma.origin_x = 0;
2899 gdc_chroma.origin_y = 0;
2900 gdc_chroma.p0_x = (OFFSET_X / 2 - (OFFSET_X / 2 & XMEM_ALIGN_MASK)) <<
2901 FRAC_BITS;
2902 gdc_chroma.p0_y = 0;
2903 gdc_chroma.p1_x = gdc_chroma.p0_x + (IMGU_DVS_BLOCK_W << FRAC_BITS);
2904 gdc_chroma.p1_y = gdc_chroma.p0_y;
2905 gdc_chroma.p2_x = gdc_chroma.p0_x;
2906 gdc_chroma.p2_y = gdc_chroma.p0_y + (IMGU_DVS_BLOCK_H / 2 << FRAC_BITS);
2907 gdc_chroma.p3_x = gdc_chroma.p1_x;
2908 gdc_chroma.p3_y = gdc_chroma.p2_y;
2909
2910 gdc_chroma.in_block_width = IMGU_DVS_BLOCK_W + BCI_ENV;
2911 gdc_chroma.in_block_width_a = DIV_ROUND_UP(gdc_chroma.in_block_width,
2912 IPU3_UAPI_ISP_VEC_ELEMS);
2913 gdc_chroma.in_block_width_b = DIV_ROUND_UP(gdc_chroma.in_block_width,
2914 IMGU_ABI_ISP_DDR_WORD_BYTES /
2915 BYP);
2916 gdc_chroma.in_block_height = IMGU_DVS_BLOCK_H / 2 + BCI_ENV;
2917 gdc_chroma.padding = 0;
2918
2919
2920 for (y0 = 0; y0 < blocks_y; y0++) {
2921 for (x0 = 0; x0 < blocks_x / 2; x0++) {
2922 for (x1 = 0; x1 < 2; x1++) {
2923
2924 x = (x0 * 2 + x1) * IMGU_DVS_BLOCK_W + OFFSET_X;
2925 x &= XMEM_ALIGN_MASK;
2926 y = y0 * IMGU_DVS_BLOCK_H + OFFSET_Y;
2927 *gdc = gdc_luma;
2928 gdc->in_addr_offset =
2929 (y * frame_in_x + x) * BYP;
2930 gdc++;
2931 }
2932
2933
2934 x = x0 * IMGU_DVS_BLOCK_W + OFFSET_X / 2;
2935 x &= XMEM_ALIGN_MASK;
2936 y = y0 * (IMGU_DVS_BLOCK_H / 2) + OFFSET_Y / 2;
2937 *gdc = gdc_chroma;
2938 gdc->in_addr_offset = (y * frame_in_x + x) * BYP;
2939 gdc++;
2940 }
2941 }
2942}
2943