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