0001
0002
0003
0004 #include <linux/device.h>
0005
0006 #include "ipu3-css.h"
0007 #include "ipu3-css-fw.h"
0008 #include "ipu3-tables.h"
0009 #include "ipu3-css-params.h"
0010
0011 #define DIV_ROUND_CLOSEST_DOWN(a, b) (((a) + ((b) / 2) - 1) / (b))
0012 #define roundclosest_down(a, b) (DIV_ROUND_CLOSEST_DOWN(a, b) * (b))
0013
0014 #define IPU3_UAPI_ANR_MAX_RESET ((1 << 12) - 1)
0015 #define IPU3_UAPI_ANR_MIN_RESET (((-1) << 12) + 1)
0016
0017 struct imgu_css_scaler_info {
0018 unsigned int phase_step;
0019 int exp_shift;
0020
0021 unsigned int phase_init;
0022 int pad_left;
0023 int pad_right;
0024 int crop_left;
0025 int crop_top;
0026 };
0027
0028 static unsigned int imgu_css_scaler_get_exp(unsigned int counter,
0029 unsigned int divider)
0030 {
0031 int i = fls(divider) - fls(counter);
0032
0033 if (i <= 0)
0034 return 0;
0035
0036 if (divider >> i < counter)
0037 i = i - 1;
0038
0039 return i;
0040 }
0041
0042
0043 static void
0044 imgu_css_scaler_setup_lut(unsigned int taps, unsigned int input_width,
0045 unsigned int output_width, int phase_step_correction,
0046 const int *coeffs, unsigned int coeffs_size,
0047 s8 coeff_lut[], struct imgu_css_scaler_info *info)
0048 {
0049 int tap, phase, phase_sum_left, phase_sum_right;
0050 int exponent = imgu_css_scaler_get_exp(output_width, input_width);
0051 int mantissa = (1 << exponent) * output_width;
0052 unsigned int phase_step, phase_taps;
0053
0054 if (input_width == output_width) {
0055 for (phase = 0; phase < IMGU_SCALER_PHASES; phase++) {
0056 phase_taps = phase * IMGU_SCALER_FILTER_TAPS;
0057 for (tap = 0; tap < taps; tap++)
0058 coeff_lut[phase_taps + tap] = 0;
0059 }
0060
0061 info->phase_step = IMGU_SCALER_PHASES *
0062 (1 << IMGU_SCALER_PHASE_COUNTER_PREC_REF);
0063 info->exp_shift = 0;
0064 info->pad_left = 0;
0065 info->pad_right = 0;
0066 info->phase_init = 0;
0067 info->crop_left = 0;
0068 info->crop_top = 0;
0069 return;
0070 }
0071
0072 for (phase = 0; phase < IMGU_SCALER_PHASES; phase++) {
0073 phase_taps = phase * IMGU_SCALER_FILTER_TAPS;
0074 for (tap = 0; tap < taps; tap++) {
0075
0076 s64 coeff = coeffs[coeffs_size -
0077 ((tap * (coeffs_size / taps)) + phase) - 1];
0078 coeff *= mantissa;
0079 coeff = div64_long(coeff, input_width);
0080
0081
0082 coeff += 1 << (IMGU_SCALER_COEFF_BITS - 1);
0083 coeff >>= IMGU_SCALER_COEFF_BITS;
0084 coeff_lut[phase_taps + tap] = coeff;
0085 }
0086 }
0087
0088 phase_step = IMGU_SCALER_PHASES *
0089 (1 << IMGU_SCALER_PHASE_COUNTER_PREC_REF) *
0090 output_width / input_width;
0091 phase_step += phase_step_correction;
0092 phase_sum_left = (taps / 2 * IMGU_SCALER_PHASES *
0093 (1 << IMGU_SCALER_PHASE_COUNTER_PREC_REF)) -
0094 (1 << (IMGU_SCALER_PHASE_COUNTER_PREC_REF - 1));
0095 phase_sum_right = (taps / 2 * IMGU_SCALER_PHASES *
0096 (1 << IMGU_SCALER_PHASE_COUNTER_PREC_REF)) +
0097 (1 << (IMGU_SCALER_PHASE_COUNTER_PREC_REF - 1));
0098
0099 info->exp_shift = IMGU_SCALER_MAX_EXPONENT_SHIFT - exponent;
0100 info->pad_left = (phase_sum_left % phase_step == 0) ?
0101 phase_sum_left / phase_step - 1 : phase_sum_left / phase_step;
0102 info->pad_right = (phase_sum_right % phase_step == 0) ?
0103 phase_sum_right / phase_step - 1 : phase_sum_right / phase_step;
0104 info->phase_init = phase_sum_left - phase_step * info->pad_left;
0105 info->phase_step = phase_step;
0106 info->crop_left = taps - 1;
0107 info->crop_top = taps - 1;
0108 }
0109
0110
0111
0112
0113
0114 static unsigned int
0115 imgu_css_scaler_calc_scaled_output(unsigned int input,
0116 struct imgu_css_scaler_info *info)
0117 {
0118 unsigned int arg1 = input * info->phase_step +
0119 (1 - IMGU_SCALER_TAPS_Y / 2) * IMGU_SCALER_FIR_PHASES -
0120 IMGU_SCALER_FIR_PHASES / (2 * IMGU_SCALER_PHASES);
0121 unsigned int arg2 = ((IMGU_SCALER_TAPS_Y / 2) * IMGU_SCALER_FIR_PHASES +
0122 IMGU_SCALER_FIR_PHASES / (2 * IMGU_SCALER_PHASES)) *
0123 IMGU_SCALER_FIR_PHASES + info->phase_step / 2;
0124
0125 return ((arg1 + (arg2 - IMGU_SCALER_FIR_PHASES * info->phase_step) /
0126 IMGU_SCALER_FIR_PHASES) / (2 * IMGU_SCALER_FIR_PHASES)) * 2;
0127 }
0128
0129
0130
0131
0132
0133 static void
0134 imgu_css_scaler_calc(u32 input_width, u32 input_height, u32 target_width,
0135 u32 target_height, struct imgu_abi_osys_config *cfg,
0136 struct imgu_css_scaler_info *info_luma,
0137 struct imgu_css_scaler_info *info_chroma,
0138 unsigned int *output_width, unsigned int *output_height,
0139 unsigned int *procmode)
0140 {
0141 u32 out_width = target_width;
0142 u32 out_height = target_height;
0143 const unsigned int height_alignment = 2;
0144 int phase_step_correction = -1;
0145
0146
0147
0148
0149
0150
0151 if (target_height * input_width > target_width * input_height)
0152 target_width = DIV_ROUND_UP(target_height * input_width,
0153 input_height);
0154
0155 if (input_width == target_width)
0156 *procmode = IMGU_ABI_OSYS_PROCMODE_BYPASS;
0157 else
0158 *procmode = IMGU_ABI_OSYS_PROCMODE_DOWNSCALE;
0159
0160 memset(&cfg->scaler_coeffs_chroma, 0,
0161 sizeof(cfg->scaler_coeffs_chroma));
0162 memset(&cfg->scaler_coeffs_luma, 0, sizeof(cfg->scaler_coeffs_luma));
0163 do {
0164 phase_step_correction++;
0165
0166 imgu_css_scaler_setup_lut(IMGU_SCALER_TAPS_Y,
0167 input_width, target_width,
0168 phase_step_correction,
0169 imgu_css_downscale_4taps,
0170 IMGU_SCALER_DOWNSCALE_4TAPS_LEN,
0171 cfg->scaler_coeffs_luma, info_luma);
0172
0173 imgu_css_scaler_setup_lut(IMGU_SCALER_TAPS_UV,
0174 input_width, target_width,
0175 phase_step_correction,
0176 imgu_css_downscale_2taps,
0177 IMGU_SCALER_DOWNSCALE_2TAPS_LEN,
0178 cfg->scaler_coeffs_chroma,
0179 info_chroma);
0180
0181 out_width = imgu_css_scaler_calc_scaled_output(input_width,
0182 info_luma);
0183 out_height = imgu_css_scaler_calc_scaled_output(input_height,
0184 info_luma);
0185 } while ((out_width < target_width || out_height < target_height ||
0186 !IS_ALIGNED(out_height, height_alignment)) &&
0187 phase_step_correction <= 5);
0188
0189 *output_width = out_width;
0190 *output_height = out_height;
0191 }
0192
0193
0194
0195 static void imgu_css_osys_set_format(enum imgu_abi_frame_format host_format,
0196 unsigned int *osys_format,
0197 unsigned int *osys_tiling)
0198 {
0199 *osys_format = IMGU_ABI_OSYS_FORMAT_YUV420;
0200 *osys_tiling = IMGU_ABI_OSYS_TILING_NONE;
0201
0202 switch (host_format) {
0203 case IMGU_ABI_FRAME_FORMAT_YUV420:
0204 *osys_format = IMGU_ABI_OSYS_FORMAT_YUV420;
0205 break;
0206 case IMGU_ABI_FRAME_FORMAT_YV12:
0207 *osys_format = IMGU_ABI_OSYS_FORMAT_YV12;
0208 break;
0209 case IMGU_ABI_FRAME_FORMAT_NV12:
0210 *osys_format = IMGU_ABI_OSYS_FORMAT_NV12;
0211 break;
0212 case IMGU_ABI_FRAME_FORMAT_NV16:
0213 *osys_format = IMGU_ABI_OSYS_FORMAT_NV16;
0214 break;
0215 case IMGU_ABI_FRAME_FORMAT_NV21:
0216 *osys_format = IMGU_ABI_OSYS_FORMAT_NV21;
0217 break;
0218 case IMGU_ABI_FRAME_FORMAT_NV12_TILEY:
0219 *osys_format = IMGU_ABI_OSYS_FORMAT_NV12;
0220 *osys_tiling = IMGU_ABI_OSYS_TILING_Y;
0221 break;
0222 default:
0223
0224 break;
0225 }
0226 }
0227
0228
0229
0230
0231
0232 static int imgu_css_osys_calc_stripe_offset(int stripe_offset_out,
0233 int fir_phases, int phase_init,
0234 int phase_step, int pad_left)
0235 {
0236 int stripe_offset_inp = stripe_offset_out * fir_phases -
0237 pad_left * phase_step;
0238
0239 return DIV_ROUND_UP(stripe_offset_inp - phase_init, phase_step);
0240 }
0241
0242
0243
0244
0245
0246 static int imgu_css_osys_calc_stripe_phase_init(int stripe_offset_out,
0247 int fir_phases, int phase_init,
0248 int phase_step, int pad_left)
0249 {
0250 int stripe_offset_inp =
0251 imgu_css_osys_calc_stripe_offset(stripe_offset_out,
0252 fir_phases, phase_init,
0253 phase_step, pad_left);
0254
0255 return phase_init + ((pad_left + stripe_offset_inp) * phase_step) -
0256 stripe_offset_out * fir_phases;
0257 }
0258
0259
0260
0261
0262
0263 static int imgu_css_osys_calc_inp_stripe_width(int stripe_width_out,
0264 int fir_phases, int phase_init,
0265 int phase_step, int fir_taps,
0266 int pad_left, int pad_right)
0267 {
0268 int stripe_width_inp = (stripe_width_out + fir_taps - 1) * fir_phases;
0269
0270 stripe_width_inp = DIV_ROUND_UP(stripe_width_inp - phase_init,
0271 phase_step);
0272
0273 return stripe_width_inp - pad_left - pad_right;
0274 }
0275
0276
0277
0278
0279
0280 static int imgu_css_osys_out_stripe_width(int stripe_width_inp, int fir_phases,
0281 int phase_init, int phase_step,
0282 int fir_taps, int pad_left,
0283 int pad_right, int column_offset)
0284 {
0285 int stripe_width_out = (pad_left + stripe_width_inp +
0286 pad_right - column_offset) * phase_step;
0287
0288 stripe_width_out = (stripe_width_out + phase_init) / fir_phases;
0289
0290 return stripe_width_out - (fir_taps - 1);
0291 }
0292
0293 struct imgu_css_reso {
0294 unsigned int input_width;
0295 unsigned int input_height;
0296 enum imgu_abi_frame_format input_format;
0297 unsigned int pin_width[IMGU_ABI_OSYS_PINS];
0298 unsigned int pin_height[IMGU_ABI_OSYS_PINS];
0299 unsigned int pin_stride[IMGU_ABI_OSYS_PINS];
0300 enum imgu_abi_frame_format pin_format[IMGU_ABI_OSYS_PINS];
0301 int chunk_width;
0302 int chunk_height;
0303 int block_height;
0304 int block_width;
0305 };
0306
0307 struct imgu_css_frame_params {
0308
0309 unsigned int enable;
0310 unsigned int format;
0311 unsigned int flip;
0312 unsigned int mirror;
0313 unsigned int tiling;
0314 unsigned int reduce_range;
0315 unsigned int width;
0316 unsigned int height;
0317 unsigned int stride;
0318 unsigned int scaled;
0319 unsigned int crop_left;
0320 unsigned int crop_top;
0321 };
0322
0323 struct imgu_css_stripe_params {
0324 unsigned int processing_mode;
0325 unsigned int phase_step;
0326 unsigned int exp_shift;
0327 unsigned int phase_init_left_y;
0328 unsigned int phase_init_left_uv;
0329 unsigned int phase_init_top_y;
0330 unsigned int phase_init_top_uv;
0331 unsigned int pad_left_y;
0332 unsigned int pad_left_uv;
0333 unsigned int pad_right_y;
0334 unsigned int pad_right_uv;
0335 unsigned int pad_top_y;
0336 unsigned int pad_top_uv;
0337 unsigned int pad_bottom_y;
0338 unsigned int pad_bottom_uv;
0339 unsigned int crop_left_y;
0340 unsigned int crop_top_y;
0341 unsigned int crop_left_uv;
0342 unsigned int crop_top_uv;
0343 unsigned int start_column_y;
0344 unsigned int start_column_uv;
0345 unsigned int chunk_width;
0346 unsigned int chunk_height;
0347 unsigned int block_width;
0348 unsigned int block_height;
0349 unsigned int input_width;
0350 unsigned int input_height;
0351 int output_width[IMGU_ABI_OSYS_PINS];
0352 int output_height[IMGU_ABI_OSYS_PINS];
0353 int output_offset[IMGU_ABI_OSYS_PINS];
0354 };
0355
0356
0357
0358
0359
0360 static int imgu_css_osys_calc_frame_and_stripe_params(
0361 struct imgu_css *css, unsigned int stripes,
0362 struct imgu_abi_osys_config *osys,
0363 struct imgu_css_scaler_info *scaler_luma,
0364 struct imgu_css_scaler_info *scaler_chroma,
0365 struct imgu_css_frame_params frame_params[],
0366 struct imgu_css_stripe_params stripe_params[],
0367 unsigned int pipe)
0368 {
0369 struct imgu_css_reso reso;
0370 unsigned int output_width, pin, s;
0371 u32 input_width, input_height, target_width, target_height;
0372 unsigned int procmode = 0;
0373 struct imgu_css_pipe *css_pipe = &css->pipes[pipe];
0374
0375 input_width = css_pipe->rect[IPU3_CSS_RECT_GDC].width;
0376 input_height = css_pipe->rect[IPU3_CSS_RECT_GDC].height;
0377 target_width = css_pipe->queue[IPU3_CSS_QUEUE_VF].fmt.mpix.width;
0378 target_height = css_pipe->queue[IPU3_CSS_QUEUE_VF].fmt.mpix.height;
0379
0380
0381
0382
0383 reso.input_width = css_pipe->rect[IPU3_CSS_RECT_GDC].width;
0384
0385
0386 reso.input_height = css_pipe->rect[IPU3_CSS_RECT_GDC].height;
0387
0388 reso.input_format =
0389 css_pipe->queue[IPU3_CSS_QUEUE_OUT].css_fmt->frame_format;
0390
0391 reso.pin_width[IMGU_ABI_OSYS_PIN_OUT] =
0392 css_pipe->queue[IPU3_CSS_QUEUE_OUT].fmt.mpix.width;
0393 reso.pin_height[IMGU_ABI_OSYS_PIN_OUT] =
0394 css_pipe->queue[IPU3_CSS_QUEUE_OUT].fmt.mpix.height;
0395 reso.pin_stride[IMGU_ABI_OSYS_PIN_OUT] =
0396 css_pipe->queue[IPU3_CSS_QUEUE_OUT].width_pad;
0397 reso.pin_format[IMGU_ABI_OSYS_PIN_OUT] =
0398 css_pipe->queue[IPU3_CSS_QUEUE_OUT].css_fmt->frame_format;
0399
0400 reso.pin_width[IMGU_ABI_OSYS_PIN_VF] =
0401 css_pipe->queue[IPU3_CSS_QUEUE_VF].fmt.mpix.width;
0402 reso.pin_height[IMGU_ABI_OSYS_PIN_VF] =
0403 css_pipe->queue[IPU3_CSS_QUEUE_VF].fmt.mpix.height;
0404 reso.pin_stride[IMGU_ABI_OSYS_PIN_VF] =
0405 css_pipe->queue[IPU3_CSS_QUEUE_VF].width_pad;
0406 reso.pin_format[IMGU_ABI_OSYS_PIN_VF] =
0407 css_pipe->queue[IPU3_CSS_QUEUE_VF].css_fmt->frame_format;
0408
0409
0410
0411 frame_params[IMGU_ABI_OSYS_PIN_OUT].width =
0412 css_pipe->queue[IPU3_CSS_QUEUE_OUT].fmt.mpix.width;
0413 frame_params[IMGU_ABI_OSYS_PIN_OUT].height =
0414 css_pipe->queue[IPU3_CSS_QUEUE_OUT].fmt.mpix.height;
0415 frame_params[IMGU_ABI_OSYS_PIN_VF].width =
0416 css_pipe->queue[IPU3_CSS_QUEUE_VF].fmt.mpix.width;
0417 frame_params[IMGU_ABI_OSYS_PIN_VF].height =
0418 css_pipe->queue[IPU3_CSS_QUEUE_VF].fmt.mpix.height;
0419 frame_params[IMGU_ABI_OSYS_PIN_VF].crop_top = 0;
0420 frame_params[IMGU_ABI_OSYS_PIN_VF].crop_left = 0;
0421
0422 for (pin = 0; pin < IMGU_ABI_OSYS_PINS; pin++) {
0423 int enable = 0;
0424 int scaled = 0;
0425 unsigned int format = 0;
0426 unsigned int tiling = 0;
0427
0428 frame_params[pin].flip = 0;
0429 frame_params[pin].mirror = 0;
0430 frame_params[pin].reduce_range = 0;
0431 if (reso.pin_width[pin] != 0 && reso.pin_height[pin] != 0) {
0432 enable = 1;
0433 if (pin == IMGU_ABI_OSYS_PIN_OUT) {
0434 if (reso.input_width < reso.pin_width[pin] ||
0435 reso.input_height < reso.pin_height[pin])
0436 return -EINVAL;
0437
0438
0439
0440
0441
0442
0443 frame_params[pin].crop_left = roundclosest_down(
0444 (reso.input_width -
0445 reso.pin_width[pin]) / 2,
0446 IMGU_OSYS_DMA_CROP_W_LIMIT);
0447 frame_params[pin].crop_top = roundclosest_down(
0448 (reso.input_height -
0449 reso.pin_height[pin]) / 2,
0450 IMGU_OSYS_DMA_CROP_H_LIMIT);
0451 } else {
0452 if (reso.pin_width[pin] != reso.input_width ||
0453 reso.pin_height[pin] != reso.input_height) {
0454
0455
0456
0457
0458
0459
0460
0461
0462 scaled = 1;
0463 }
0464 }
0465 imgu_css_osys_set_format(reso.pin_format[pin], &format,
0466 &tiling);
0467 } else {
0468 enable = 0;
0469 }
0470 frame_params[pin].enable = enable;
0471 frame_params[pin].format = format;
0472 frame_params[pin].tiling = tiling;
0473 frame_params[pin].stride = reso.pin_stride[pin];
0474 frame_params[pin].scaled = scaled;
0475 }
0476
0477 imgu_css_scaler_calc(input_width, input_height, target_width,
0478 target_height, osys, scaler_luma, scaler_chroma,
0479 &reso.pin_width[IMGU_ABI_OSYS_PIN_VF],
0480 &reso.pin_height[IMGU_ABI_OSYS_PIN_VF], &procmode);
0481 dev_dbg(css->dev, "osys scaler procmode is %u", procmode);
0482 output_width = reso.pin_width[IMGU_ABI_OSYS_PIN_VF];
0483
0484 if (output_width < reso.input_width / 2) {
0485
0486 reso.chunk_width = IMGU_OSYS_BLOCK_WIDTH;
0487 reso.block_width = IMGU_OSYS_BLOCK_WIDTH;
0488 } else {
0489 reso.chunk_width = IMGU_OSYS_BLOCK_WIDTH / 2;
0490 reso.block_width = IMGU_OSYS_BLOCK_WIDTH;
0491 }
0492
0493 if (output_width <= reso.input_width * 7 / 8) {
0494
0495 reso.chunk_height = IMGU_OSYS_BLOCK_HEIGHT;
0496 reso.block_height = IMGU_OSYS_BLOCK_HEIGHT;
0497 } else {
0498 reso.chunk_height = IMGU_OSYS_BLOCK_HEIGHT / 2;
0499 reso.block_height = IMGU_OSYS_BLOCK_HEIGHT;
0500 }
0501
0502
0503
0504
0505
0506
0507 if (frame_params[IMGU_ABI_OSYS_PIN_VF].enable) {
0508
0509
0510
0511
0512
0513 u32 w = reso.pin_width[IMGU_ABI_OSYS_PIN_VF] -
0514 frame_params[IMGU_ABI_OSYS_PIN_VF].width;
0515 u32 h = reso.pin_height[IMGU_ABI_OSYS_PIN_VF] -
0516 frame_params[IMGU_ABI_OSYS_PIN_VF].height;
0517
0518 frame_params[IMGU_ABI_OSYS_PIN_VF].crop_left =
0519 roundclosest_down(w / 2, IMGU_OSYS_DMA_CROP_W_LIMIT);
0520 frame_params[IMGU_ABI_OSYS_PIN_VF].crop_top =
0521 roundclosest_down(h / 2, IMGU_OSYS_DMA_CROP_H_LIMIT);
0522
0523 if (reso.input_height % 4 || reso.input_width % 8) {
0524 dev_err(css->dev, "OSYS input width is not multiple of 8 or\n");
0525 dev_err(css->dev, "height is not multiple of 4\n");
0526 return -EINVAL;
0527 }
0528 }
0529
0530
0531
0532 if (frame_params[IMGU_ABI_OSYS_PIN_VF].enable) {
0533 output_width = reso.pin_width[IMGU_ABI_OSYS_PIN_VF];
0534 } else {
0535
0536
0537
0538
0539
0540
0541
0542
0543 output_width = reso.input_width;
0544 }
0545
0546 for (s = 0; s < stripes; s++) {
0547 int stripe_offset_inp_y = 0;
0548 int stripe_offset_inp_uv = 0;
0549 int stripe_offset_out_y = 0;
0550 int stripe_offset_out_uv = 0;
0551 int stripe_phase_init_y = scaler_luma->phase_init;
0552 int stripe_phase_init_uv = scaler_chroma->phase_init;
0553 int stripe_offset_blk_y = 0;
0554 int stripe_offset_blk_uv = 0;
0555 int stripe_offset_col_y = 0;
0556 int stripe_offset_col_uv = 0;
0557 int stripe_pad_left_y = scaler_luma->pad_left;
0558 int stripe_pad_left_uv = scaler_chroma->pad_left;
0559 int stripe_pad_right_y = scaler_luma->pad_right;
0560 int stripe_pad_right_uv = scaler_chroma->pad_right;
0561 int stripe_crop_left_y = scaler_luma->crop_left;
0562 int stripe_crop_left_uv = scaler_chroma->crop_left;
0563 int stripe_input_width_y = reso.input_width;
0564 int stripe_input_width_uv = 0;
0565 int stripe_output_width_y = output_width;
0566 int stripe_output_width_uv = 0;
0567 int chunk_floor_y = 0;
0568 int chunk_floor_uv = 0;
0569 int chunk_ceil_uv = 0;
0570
0571 if (stripes > 1) {
0572 if (s > 0) {
0573
0574 stripe_offset_out_y =
0575 output_width * s / stripes;
0576 stripe_offset_out_y =
0577 rounddown(stripe_offset_out_y,
0578 IPU3_UAPI_ISP_VEC_ELEMS);
0579 stripe_offset_out_uv = stripe_offset_out_y /
0580 IMGU_LUMA_TO_CHROMA_RATIO;
0581 stripe_offset_inp_y =
0582 imgu_css_osys_calc_stripe_offset(
0583 stripe_offset_out_y,
0584 IMGU_OSYS_FIR_PHASES,
0585 scaler_luma->phase_init,
0586 scaler_luma->phase_step,
0587 scaler_luma->pad_left);
0588 stripe_offset_inp_uv =
0589 imgu_css_osys_calc_stripe_offset(
0590 stripe_offset_out_uv,
0591 IMGU_OSYS_FIR_PHASES,
0592 scaler_chroma->phase_init,
0593 scaler_chroma->phase_step,
0594 scaler_chroma->pad_left);
0595
0596
0597 stripe_phase_init_y =
0598 imgu_css_osys_calc_stripe_phase_init(
0599 stripe_offset_out_y,
0600 IMGU_OSYS_FIR_PHASES,
0601 scaler_luma->phase_init,
0602 scaler_luma->phase_step,
0603 scaler_luma->pad_left);
0604 stripe_phase_init_uv =
0605 imgu_css_osys_calc_stripe_phase_init(
0606 stripe_offset_out_uv,
0607 IMGU_OSYS_FIR_PHASES,
0608 scaler_chroma->phase_init,
0609 scaler_chroma->phase_step,
0610 scaler_chroma->pad_left);
0611
0612
0613
0614
0615
0616 chunk_floor_y = rounddown(stripe_offset_inp_y,
0617 reso.chunk_width);
0618 chunk_floor_uv =
0619 rounddown(stripe_offset_inp_uv,
0620 reso.chunk_width /
0621 IMGU_LUMA_TO_CHROMA_RATIO);
0622
0623 if (chunk_floor_y != chunk_floor_uv *
0624 IMGU_LUMA_TO_CHROMA_RATIO) {
0625
0626
0627
0628
0629
0630 stripe_offset_inp_uv -= 1;
0631 stripe_crop_left_uv += 1;
0632 stripe_phase_init_uv -=
0633 scaler_luma->phase_step;
0634 if (stripe_phase_init_uv < 0)
0635 stripe_phase_init_uv =
0636 stripe_phase_init_uv +
0637 IMGU_OSYS_FIR_PHASES;
0638 }
0639
0640
0641
0642
0643
0644
0645
0646 chunk_ceil_uv =
0647 roundup(stripe_offset_inp_uv,
0648 reso.chunk_width /
0649 IMGU_LUMA_TO_CHROMA_RATIO);
0650
0651 if (stripe_offset_inp_uv ==
0652 chunk_ceil_uv - IMGU_OSYS_TAPS_UV) {
0653
0654
0655
0656
0657 stripe_offset_inp_uv -= 1;
0658 stripe_phase_init_uv -=
0659 scaler_luma->phase_step;
0660 if (stripe_phase_init_uv < 0) {
0661 stripe_phase_init_uv +=
0662 IMGU_OSYS_FIR_PHASES;
0663 stripe_crop_left_uv += 1;
0664 }
0665 }
0666
0667
0668
0669
0670
0671 stripe_offset_blk_y =
0672 rounddown(stripe_offset_inp_y,
0673 IMGU_INPUT_BLOCK_WIDTH);
0674 stripe_offset_blk_uv =
0675 rounddown(stripe_offset_inp_uv,
0676 IMGU_INPUT_BLOCK_WIDTH /
0677 IMGU_LUMA_TO_CHROMA_RATIO);
0678 stripe_offset_col_y = stripe_offset_inp_y -
0679 stripe_offset_blk_y;
0680 stripe_offset_col_uv = stripe_offset_inp_uv -
0681 stripe_offset_blk_uv;
0682
0683
0684 stripe_pad_left_y = 0;
0685 stripe_pad_left_uv = 0;
0686 }
0687
0688
0689 if (s < stripes - 1) {
0690 int next_offset;
0691
0692 stripe_pad_right_y = 0;
0693 stripe_pad_right_uv = 0;
0694
0695 next_offset = output_width * (s + 1) / stripes;
0696 next_offset = rounddown(next_offset, 64);
0697 stripe_output_width_y = next_offset -
0698 stripe_offset_out_y;
0699 } else {
0700 stripe_output_width_y = output_width -
0701 stripe_offset_out_y;
0702 }
0703
0704
0705 stripe_output_width_uv = stripe_output_width_y /
0706 IMGU_LUMA_TO_CHROMA_RATIO;
0707
0708 stripe_input_width_y = stripe_offset_col_y +
0709 imgu_css_osys_calc_inp_stripe_width(
0710 stripe_output_width_y,
0711 IMGU_OSYS_FIR_PHASES,
0712 stripe_phase_init_y,
0713 scaler_luma->phase_step,
0714 IMGU_OSYS_TAPS_Y,
0715 stripe_pad_left_y,
0716 stripe_pad_right_y);
0717
0718 stripe_input_width_uv = stripe_offset_col_uv +
0719 imgu_css_osys_calc_inp_stripe_width(
0720 stripe_output_width_uv,
0721 IMGU_OSYS_FIR_PHASES,
0722 stripe_phase_init_uv,
0723 scaler_chroma->phase_step,
0724 IMGU_OSYS_TAPS_UV,
0725 stripe_pad_left_uv,
0726 stripe_pad_right_uv);
0727
0728 stripe_input_width_uv = max(DIV_ROUND_UP(
0729 stripe_input_width_y,
0730 IMGU_LUMA_TO_CHROMA_RATIO),
0731 stripe_input_width_uv);
0732
0733 stripe_input_width_y = stripe_input_width_uv *
0734 IMGU_LUMA_TO_CHROMA_RATIO;
0735
0736 if (s >= stripes - 1) {
0737 stripe_input_width_y = reso.input_width -
0738 stripe_offset_blk_y;
0739
0740
0741
0742
0743 }
0744
0745
0746
0747
0748
0749
0750
0751
0752 stripe_input_width_y = ALIGN(stripe_input_width_y, 8);
0753 stripe_output_width_y =
0754 imgu_css_osys_out_stripe_width(
0755 stripe_input_width_y,
0756 IMGU_OSYS_FIR_PHASES,
0757 stripe_phase_init_y,
0758 scaler_luma->phase_step,
0759 IMGU_OSYS_TAPS_Y,
0760 stripe_pad_left_y,
0761 stripe_pad_right_y,
0762 stripe_offset_col_y);
0763
0764 stripe_output_width_y =
0765 rounddown(stripe_output_width_y,
0766 IMGU_LUMA_TO_CHROMA_RATIO);
0767 }
0768
0769
0770
0771
0772 {
0773 unsigned int i;
0774
0775
0776 stripe_params[s].input_width = stripe_input_width_y;
0777 stripe_params[s].input_height = reso.input_height;
0778
0779 for (i = 0; i < IMGU_ABI_OSYS_PINS; i++) {
0780 if (frame_params[i].scaled) {
0781
0782
0783
0784
0785
0786
0787 stripe_params[s].output_width[i] =
0788 stripe_output_width_y;
0789 stripe_params[s].output_height[i] =
0790 reso.pin_height[i];
0791 stripe_params[s].output_offset[i] =
0792 stripe_offset_out_y;
0793 } else {
0794
0795 stripe_params[s].output_width[i] =
0796 stripe_params[s].input_width;
0797 stripe_params[s].output_height[i] =
0798 stripe_params[s].input_height;
0799 stripe_params[s].output_offset[i] =
0800 stripe_offset_blk_y;
0801 }
0802 }
0803
0804
0805 stripe_params[s].processing_mode = procmode;
0806 stripe_params[s].phase_step = scaler_luma->phase_step;
0807 stripe_params[s].exp_shift = scaler_luma->exp_shift;
0808 stripe_params[s].phase_init_left_y =
0809 stripe_phase_init_y;
0810 stripe_params[s].phase_init_left_uv =
0811 stripe_phase_init_uv;
0812 stripe_params[s].phase_init_top_y =
0813 scaler_luma->phase_init;
0814 stripe_params[s].phase_init_top_uv =
0815 scaler_chroma->phase_init;
0816 stripe_params[s].pad_left_y = stripe_pad_left_y;
0817 stripe_params[s].pad_left_uv = stripe_pad_left_uv;
0818 stripe_params[s].pad_right_y = stripe_pad_right_y;
0819 stripe_params[s].pad_right_uv = stripe_pad_right_uv;
0820 stripe_params[s].pad_top_y = scaler_luma->pad_left;
0821 stripe_params[s].pad_top_uv = scaler_chroma->pad_left;
0822 stripe_params[s].pad_bottom_y = scaler_luma->pad_right;
0823 stripe_params[s].pad_bottom_uv =
0824 scaler_chroma->pad_right;
0825 stripe_params[s].crop_left_y = stripe_crop_left_y;
0826 stripe_params[s].crop_top_y = scaler_luma->crop_top;
0827 stripe_params[s].crop_left_uv = stripe_crop_left_uv;
0828 stripe_params[s].crop_top_uv = scaler_chroma->crop_top;
0829 stripe_params[s].start_column_y = stripe_offset_col_y;
0830 stripe_params[s].start_column_uv = stripe_offset_col_uv;
0831 stripe_params[s].chunk_width = reso.chunk_width;
0832 stripe_params[s].chunk_height = reso.chunk_height;
0833 stripe_params[s].block_width = reso.block_width;
0834 stripe_params[s].block_height = reso.block_height;
0835 }
0836 }
0837
0838 return 0;
0839 }
0840
0841
0842
0843
0844
0845 static int imgu_css_osys_calc(struct imgu_css *css, unsigned int pipe,
0846 unsigned int stripes,
0847 struct imgu_abi_osys_config *osys,
0848 struct imgu_css_scaler_info *scaler_luma,
0849 struct imgu_css_scaler_info *scaler_chroma,
0850 struct imgu_abi_stripes block_stripes[])
0851 {
0852 struct imgu_css_frame_params frame_params[IMGU_ABI_OSYS_PINS];
0853 struct imgu_css_stripe_params stripe_params[IPU3_UAPI_MAX_STRIPES];
0854 struct imgu_abi_osys_formatter_params *param;
0855 unsigned int pin, s;
0856 struct imgu_css_pipe *css_pipe = &css->pipes[pipe];
0857
0858 memset(osys, 0, sizeof(*osys));
0859
0860
0861 if (imgu_css_osys_calc_frame_and_stripe_params(css, stripes, osys,
0862 scaler_luma,
0863 scaler_chroma,
0864 frame_params,
0865 stripe_params, pipe))
0866 return -EINVAL;
0867
0868
0869
0870 for (s = 0; s < stripes; s++) {
0871 struct imgu_abi_osys_scaler_params *scaler =
0872 &osys->scaler[s].param;
0873 int fifo_addr_fmt = IMGU_FIFO_ADDR_SCALER_TO_FMT;
0874 int fifo_addr_ack = IMGU_FIFO_ADDR_SCALER_TO_SP;
0875
0876
0877 scaler->inp_buf_y_st_addr = IMGU_VMEM1_INP_BUF_ADDR;
0878
0879
0880
0881
0882
0883
0884
0885 scaler->inp_buf_y_line_stride = IMGU_VMEM1_Y_STRIDE;
0886
0887
0888
0889
0890
0891
0892
0893
0894 scaler->inp_buf_y_buffer_stride = IMGU_VMEM1_BUF_SIZE;
0895 scaler->inp_buf_u_st_addr = IMGU_VMEM1_INP_BUF_ADDR +
0896 IMGU_VMEM1_U_OFFSET;
0897 scaler->inp_buf_v_st_addr = IMGU_VMEM1_INP_BUF_ADDR +
0898 IMGU_VMEM1_V_OFFSET;
0899 scaler->inp_buf_uv_line_stride = IMGU_VMEM1_UV_STRIDE;
0900 scaler->inp_buf_uv_buffer_stride = IMGU_VMEM1_BUF_SIZE;
0901 scaler->inp_buf_chunk_width = stripe_params[s].chunk_width;
0902 scaler->inp_buf_nr_buffers = IMGU_OSYS_NUM_INPUT_BUFFERS;
0903
0904
0905 scaler->out_buf_y_st_addr = IMGU_VMEM1_INT_BUF_ADDR;
0906 scaler->out_buf_y_line_stride = stripe_params[s].block_width /
0907 IMGU_VMEM1_ELEMS_PER_VEC;
0908 scaler->out_buf_y_buffer_stride = IMGU_VMEM1_BUF_SIZE;
0909 scaler->out_buf_u_st_addr = IMGU_VMEM1_INT_BUF_ADDR +
0910 IMGU_VMEM1_U_OFFSET;
0911 scaler->out_buf_v_st_addr = IMGU_VMEM1_INT_BUF_ADDR +
0912 IMGU_VMEM1_V_OFFSET;
0913 scaler->out_buf_uv_line_stride = stripe_params[s].block_width /
0914 IMGU_VMEM1_ELEMS_PER_VEC / 2;
0915 scaler->out_buf_uv_buffer_stride = IMGU_VMEM1_BUF_SIZE;
0916 scaler->out_buf_nr_buffers = IMGU_OSYS_NUM_INTERM_BUFFERS;
0917
0918
0919 scaler->int_buf_y_st_addr = IMGU_VMEM2_BUF_Y_ADDR;
0920 scaler->int_buf_y_line_stride = IMGU_VMEM2_BUF_Y_STRIDE;
0921 scaler->int_buf_u_st_addr = IMGU_VMEM2_BUF_U_ADDR;
0922 scaler->int_buf_v_st_addr = IMGU_VMEM2_BUF_V_ADDR;
0923 scaler->int_buf_uv_line_stride = IMGU_VMEM2_BUF_UV_STRIDE;
0924 scaler->int_buf_height = IMGU_VMEM2_LINES_PER_BLOCK;
0925 scaler->int_buf_chunk_width = stripe_params[s].chunk_height;
0926 scaler->int_buf_chunk_height = stripe_params[s].block_width;
0927
0928
0929 scaler->ctx_buf_hor_y_st_addr = IMGU_VMEM3_HOR_Y_ADDR;
0930 scaler->ctx_buf_hor_u_st_addr = IMGU_VMEM3_HOR_U_ADDR;
0931 scaler->ctx_buf_hor_v_st_addr = IMGU_VMEM3_HOR_V_ADDR;
0932 scaler->ctx_buf_ver_y_st_addr = IMGU_VMEM3_VER_Y_ADDR;
0933 scaler->ctx_buf_ver_u_st_addr = IMGU_VMEM3_VER_U_ADDR;
0934 scaler->ctx_buf_ver_v_st_addr = IMGU_VMEM3_VER_V_ADDR;
0935
0936
0937 scaler->release_inp_buf_addr = fifo_addr_ack;
0938 scaler->release_inp_buf_en = 1;
0939 scaler->release_out_buf_en = 1;
0940 scaler->process_out_buf_addr = fifo_addr_fmt;
0941
0942
0943 scaler->input_image_y_width = stripe_params[s].input_width;
0944 scaler->input_image_y_height = stripe_params[s].input_height;
0945 scaler->input_image_y_start_column =
0946 stripe_params[s].start_column_y;
0947 scaler->input_image_uv_start_column =
0948 stripe_params[s].start_column_uv;
0949 scaler->input_image_y_left_pad = stripe_params[s].pad_left_y;
0950 scaler->input_image_uv_left_pad = stripe_params[s].pad_left_uv;
0951 scaler->input_image_y_right_pad = stripe_params[s].pad_right_y;
0952 scaler->input_image_uv_right_pad =
0953 stripe_params[s].pad_right_uv;
0954 scaler->input_image_y_top_pad = stripe_params[s].pad_top_y;
0955 scaler->input_image_uv_top_pad = stripe_params[s].pad_top_uv;
0956 scaler->input_image_y_bottom_pad =
0957 stripe_params[s].pad_bottom_y;
0958 scaler->input_image_uv_bottom_pad =
0959 stripe_params[s].pad_bottom_uv;
0960 scaler->processing_mode = stripe_params[s].processing_mode;
0961 scaler->scaling_ratio = stripe_params[s].phase_step;
0962 scaler->y_left_phase_init = stripe_params[s].phase_init_left_y;
0963 scaler->uv_left_phase_init =
0964 stripe_params[s].phase_init_left_uv;
0965 scaler->y_top_phase_init = stripe_params[s].phase_init_top_y;
0966 scaler->uv_top_phase_init = stripe_params[s].phase_init_top_uv;
0967 scaler->coeffs_exp_shift = stripe_params[s].exp_shift;
0968 scaler->out_y_left_crop = stripe_params[s].crop_left_y;
0969 scaler->out_uv_left_crop = stripe_params[s].crop_left_uv;
0970 scaler->out_y_top_crop = stripe_params[s].crop_top_y;
0971 scaler->out_uv_top_crop = stripe_params[s].crop_top_uv;
0972
0973 for (pin = 0; pin < IMGU_ABI_OSYS_PINS; pin++) {
0974 int in_fifo_addr;
0975 int out_fifo_addr;
0976 int block_width_vecs;
0977 int input_width_s;
0978 int input_width_vecs;
0979 int input_buf_y_st_addr;
0980 int input_buf_u_st_addr;
0981 int input_buf_v_st_addr;
0982 int input_buf_y_line_stride;
0983 int input_buf_uv_line_stride;
0984 int output_buf_y_line_stride;
0985 int output_buf_uv_line_stride;
0986 int output_buf_nr_y_lines;
0987 int block_height;
0988 int block_width;
0989 struct imgu_abi_osys_frame_params *fr_pr;
0990
0991 fr_pr = &osys->frame[pin].param;
0992
0993
0994 fr_pr->enable = frame_params[pin].enable;
0995 fr_pr->format = frame_params[pin].format;
0996 fr_pr->mirror = frame_params[pin].mirror;
0997 fr_pr->flip = frame_params[pin].flip;
0998 fr_pr->tiling = frame_params[pin].tiling;
0999 fr_pr->width = frame_params[pin].width;
1000 fr_pr->height = frame_params[pin].height;
1001 fr_pr->stride = frame_params[pin].stride;
1002 fr_pr->scaled = frame_params[pin].scaled;
1003
1004
1005 osys->stripe[s].crop_top[pin] =
1006 frame_params[pin].crop_top;
1007 osys->stripe[s].input_width =
1008 stripe_params[s].input_width;
1009 osys->stripe[s].input_height =
1010 stripe_params[s].input_height;
1011 osys->stripe[s].block_height =
1012 stripe_params[s].block_height;
1013 osys->stripe[s].block_width =
1014 stripe_params[s].block_width;
1015 osys->stripe[s].output_width[pin] =
1016 stripe_params[s].output_width[pin];
1017 osys->stripe[s].output_height[pin] =
1018 stripe_params[s].output_height[pin];
1019
1020 if (s == 0) {
1021
1022 osys->stripe[s].crop_left[pin] =
1023 frame_params[pin].crop_left;
1024 osys->stripe[s].output_offset[pin] =
1025 stripe_params[s].output_offset[pin];
1026 } else {
1027
1028
1029
1030
1031
1032 osys->stripe[s].crop_left[pin] = 0;
1033 osys->stripe[s].output_offset[pin] =
1034 (stripe_params[s].output_offset[pin] -
1035 osys->stripe[0].crop_left[pin]);
1036 }
1037
1038 if (!frame_params[pin].enable)
1039 continue;
1040
1041
1042
1043
1044
1045
1046
1047
1048 if (frame_params[pin].scaled) {
1049 block_height = stripe_params[s].block_height;
1050 block_width = stripe_params[s].block_width;
1051 } else {
1052 block_height = IMGU_OSYS_BLOCK_HEIGHT;
1053 block_width = IMGU_OSYS_BLOCK_WIDTH;
1054 }
1055 block_width_vecs =
1056 block_width / IMGU_VMEM1_ELEMS_PER_VEC;
1057
1058
1059
1060
1061 input_buf_y_line_stride = block_width_vecs;
1062 input_buf_uv_line_stride = block_width_vecs / 2;
1063 output_buf_y_line_stride = block_width_vecs;
1064 output_buf_uv_line_stride = block_width_vecs / 2;
1065 output_buf_nr_y_lines = block_height;
1066 if (frame_params[pin].format ==
1067 IMGU_ABI_OSYS_FORMAT_NV12 ||
1068 frame_params[pin].format ==
1069 IMGU_ABI_OSYS_FORMAT_NV21)
1070 output_buf_uv_line_stride =
1071 output_buf_y_line_stride;
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081 if (frame_params[pin].tiling) {
1082 output_buf_nr_y_lines = 8;
1083 output_buf_y_line_stride = 512 /
1084 IMGU_VMEM1_ELEMS_PER_VEC;
1085 output_buf_uv_line_stride = 256 /
1086 IMGU_VMEM1_ELEMS_PER_VEC;
1087 }
1088
1089
1090
1091
1092
1093
1094
1095 osys->stripe[s].buf_stride[pin] =
1096 output_buf_y_line_stride *
1097 IMGU_HIVE_OF_SYS_OF_SYSTEM_NWAYS;
1098 if (frame_params[pin].scaled) {
1099
1100
1101
1102
1103 input_buf_y_st_addr = IMGU_VMEM1_INT_BUF_ADDR;
1104 input_buf_u_st_addr = IMGU_VMEM1_INT_BUF_ADDR +
1105 IMGU_VMEM1_U_OFFSET;
1106 input_buf_v_st_addr = IMGU_VMEM1_INT_BUF_ADDR +
1107 IMGU_VMEM1_V_OFFSET;
1108 } else {
1109
1110
1111
1112
1113 input_buf_y_st_addr = IMGU_VMEM1_INP_BUF_ADDR;
1114 input_buf_u_st_addr = IMGU_VMEM1_INP_BUF_ADDR +
1115 IMGU_VMEM1_U_OFFSET;
1116 input_buf_v_st_addr = IMGU_VMEM1_INP_BUF_ADDR +
1117 IMGU_VMEM1_V_OFFSET;
1118 }
1119
1120
1121
1122
1123
1124
1125
1126
1127 input_width_s =
1128 roundup(stripe_params[s].output_width[pin],
1129 block_width);
1130 input_width_vecs = input_width_s /
1131 IMGU_VMEM1_ELEMS_PER_VEC;
1132 out_fifo_addr = IMGU_FIFO_ADDR_FMT_TO_SP;
1133
1134
1135
1136
1137
1138
1139 if (frame_params[pin].scaled)
1140 in_fifo_addr = IMGU_FIFO_ADDR_FMT_TO_SCALER;
1141 else
1142 in_fifo_addr = IMGU_FIFO_ADDR_FMT_TO_SP;
1143
1144
1145 param = &osys->formatter[s][pin].param;
1146
1147 param->format = frame_params[pin].format;
1148 param->flip = frame_params[pin].flip;
1149 param->mirror = frame_params[pin].mirror;
1150 param->tiling = frame_params[pin].tiling;
1151 param->reduce_range = frame_params[pin].reduce_range;
1152 param->alpha_blending = 0;
1153 param->release_inp_addr = in_fifo_addr;
1154 param->release_inp_en = 1;
1155 param->process_out_buf_addr = out_fifo_addr;
1156 param->image_width_vecs = input_width_vecs;
1157 param->image_height_lines =
1158 stripe_params[s].output_height[pin];
1159 param->inp_buff_y_st_addr = input_buf_y_st_addr;
1160 param->inp_buff_y_line_stride = input_buf_y_line_stride;
1161 param->inp_buff_y_buffer_stride = IMGU_VMEM1_BUF_SIZE;
1162 param->int_buff_u_st_addr = input_buf_u_st_addr;
1163 param->int_buff_v_st_addr = input_buf_v_st_addr;
1164 param->inp_buff_uv_line_stride =
1165 input_buf_uv_line_stride;
1166 param->inp_buff_uv_buffer_stride = IMGU_VMEM1_BUF_SIZE;
1167 param->out_buff_level = 0;
1168 param->out_buff_nr_y_lines = output_buf_nr_y_lines;
1169 param->out_buff_u_st_offset = IMGU_VMEM1_U_OFFSET;
1170 param->out_buff_v_st_offset = IMGU_VMEM1_V_OFFSET;
1171 param->out_buff_y_line_stride =
1172 output_buf_y_line_stride;
1173 param->out_buff_uv_line_stride =
1174 output_buf_uv_line_stride;
1175 param->hist_buff_st_addr = IMGU_VMEM1_HST_BUF_ADDR;
1176 param->hist_buff_line_stride =
1177 IMGU_VMEM1_HST_BUF_STRIDE;
1178 param->hist_buff_nr_lines = IMGU_VMEM1_HST_BUF_NLINES;
1179 }
1180 }
1181
1182 block_stripes[0].offset = 0;
1183 if (stripes <= 1) {
1184 block_stripes[0].width = stripe_params[0].input_width;
1185 block_stripes[0].height = stripe_params[0].input_height;
1186 } else {
1187 struct imgu_fw_info *bi =
1188 &css->fwp->binary_header[css_pipe->bindex];
1189 unsigned int sp_block_width =
1190 bi->info.isp.sp.block.block_width *
1191 IPU3_UAPI_ISP_VEC_ELEMS;
1192
1193 block_stripes[0].width = roundup(stripe_params[0].input_width,
1194 sp_block_width);
1195 block_stripes[1].offset =
1196 rounddown(css_pipe->rect[IPU3_CSS_RECT_GDC].width -
1197 stripe_params[1].input_width, sp_block_width);
1198 block_stripes[1].width =
1199 roundup(css_pipe->rect[IPU3_CSS_RECT_GDC].width -
1200 block_stripes[1].offset, sp_block_width);
1201 block_stripes[0].height = css_pipe->rect[IPU3_CSS_RECT_GDC].height;
1202 block_stripes[1].height = block_stripes[0].height;
1203 }
1204
1205 return 0;
1206 }
1207
1208
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 static int
1250 imgu_css_shd_ops_calc(struct imgu_abi_shd_intra_frame_operations_data *ops,
1251 const struct ipu3_uapi_shd_grid_config *grid,
1252 unsigned int image_height)
1253 {
1254 unsigned int block_height = 1 << grid->block_height_log2;
1255 unsigned int grid_height_per_slice = grid->grid_height_per_slice;
1256 unsigned int set_height = grid_height_per_slice * block_height;
1257
1258
1259 unsigned int positive_y_start = (unsigned int)-grid->y_start;
1260 unsigned int first_process_lines =
1261 set_height - (positive_y_start % set_height);
1262 unsigned int last_set_height;
1263 unsigned int num_of_sets;
1264
1265 struct imgu_abi_acc_operation *p_op;
1266 struct imgu_abi_acc_process_lines_cmd_data *p_pl;
1267 struct imgu_abi_shd_transfer_luts_set_data *p_tr;
1268
1269 unsigned int op_idx, pl_idx, tr_idx;
1270 unsigned char tr_set_num, pl_cfg_set;
1271
1272
1273
1274
1275
1276
1277 unsigned char last_tr = 0;
1278
1279
1280 bool add_pl;
1281
1282 bool add_tr;
1283
1284
1285
1286
1287
1288 if (image_height > first_process_lines) {
1289 last_set_height =
1290 (image_height - first_process_lines) % set_height;
1291 num_of_sets = last_set_height > 0 ?
1292 (image_height - first_process_lines) / set_height + 2 :
1293 (image_height - first_process_lines) / set_height + 1;
1294 last_tr = (set_height - last_set_height <= block_height ||
1295 last_set_height == 0) ? 1 : 0;
1296 } else {
1297 last_set_height = 0;
1298 num_of_sets = 1;
1299 first_process_lines = image_height;
1300 last_tr = set_height - image_height <= block_height ? 1 : 0;
1301 }
1302
1303
1304 p_op = ops->operation_list;
1305 op_idx = 0;
1306 p_pl = ops->process_lines_data;
1307 pl_idx = 0;
1308 p_tr = ops->transfer_data;
1309 tr_idx = 0;
1310
1311 memset(ops, 0, sizeof(*ops));
1312
1313
1314 tr_set_num = 0;
1315 pl_cfg_set = 0;
1316
1317
1318
1319
1320
1321
1322 add_pl = false;
1323 add_tr = true;
1324
1325 while (add_pl || add_tr) {
1326
1327 if (add_tr) {
1328 if (op_idx >= IMGU_ABI_SHD_MAX_OPERATIONS ||
1329 tr_idx >= IMGU_ABI_SHD_MAX_TRANSFERS)
1330 return -EINVAL;
1331 p_op[op_idx].op_type =
1332 IMGU_ABI_ACC_OPTYPE_TRANSFER_DATA;
1333 p_op[op_idx].op_indicator = IMGU_ABI_ACC_OP_IDLE;
1334 op_idx++;
1335 p_tr[tr_idx].set_number = tr_set_num;
1336 tr_idx++;
1337 tr_set_num = (tr_set_num + 1) % IMGU_SHD_SETS;
1338 }
1339
1340
1341 if (add_pl) {
1342 if (op_idx >= IMGU_ABI_SHD_MAX_OPERATIONS ||
1343 pl_idx >= IMGU_ABI_SHD_MAX_PROCESS_LINES)
1344 return -EINVAL;
1345 p_op[op_idx].op_type =
1346 IMGU_ABI_ACC_OPTYPE_PROCESS_LINES;
1347
1348
1349
1350
1351
1352 if (pl_idx == 0 && num_of_sets != 1)
1353 p_op[op_idx].op_indicator =
1354 IMGU_ABI_ACC_OP_IDLE;
1355
1356
1357
1358
1359 else if (pl_idx == num_of_sets - 1)
1360 p_op[op_idx].op_indicator =
1361 IMGU_ABI_ACC_OP_END_OF_OPS;
1362
1363
1364
1365
1366
1367 else
1368 p_op[op_idx].op_indicator =
1369 IMGU_ABI_ACC_OP_END_OF_ACK;
1370
1371 op_idx++;
1372
1373
1374 if (pl_idx == 0)
1375 p_pl[pl_idx].lines = first_process_lines;
1376
1377 else if (pl_idx == num_of_sets - 1 &&
1378 last_set_height > 0)
1379 p_pl[pl_idx].lines = last_set_height;
1380 else
1381 p_pl[pl_idx].lines = set_height;
1382
1383 p_pl[pl_idx].cfg_set = pl_cfg_set;
1384 pl_idx++;
1385 pl_cfg_set = (pl_cfg_set + 1) % IMGU_SHD_SETS;
1386 }
1387
1388
1389
1390
1391
1392
1393 if (tr_idx == IMGU_SHD_SETS ||
1394 tr_idx == num_of_sets + last_tr) {
1395 add_tr = false;
1396 add_pl = true;
1397 }
1398
1399
1400
1401
1402
1403 if (pl_idx == 2) {
1404 add_tr = true;
1405 add_pl = true;
1406 }
1407
1408
1409 if (tr_idx == num_of_sets + last_tr)
1410 add_tr = false;
1411 if (pl_idx == num_of_sets)
1412 add_pl = false;
1413 }
1414
1415 return 0;
1416 }
1417
1418
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 struct process_lines {
1481 unsigned int image_height;
1482 unsigned short grid_height;
1483 unsigned short block_height;
1484 unsigned short y_start;
1485 unsigned char grid_height_per_slice;
1486
1487 unsigned short max_op;
1488 unsigned short max_tr;
1489 unsigned char acc_enable;
1490 };
1491
1492
1493 static int
1494 imgu_css_acc_process_lines(const struct process_lines *pl,
1495 struct imgu_abi_acc_operation *p_op,
1496 struct imgu_abi_acc_process_lines_cmd_data *p_pl,
1497 struct imgu_abi_acc_transfer_op_data *p_tr)
1498 {
1499 unsigned short op_idx = 0, pl_idx = 0, tr_idx = 0;
1500 unsigned char tr_set_num = 0, pl_cfg_set = 0;
1501 const unsigned short grid_last_line =
1502 pl->y_start + pl->grid_height * pl->block_height;
1503 const unsigned short process_lines =
1504 pl->grid_height_per_slice * pl->block_height;
1505
1506 unsigned int process_lines_after_grid;
1507 unsigned short first_process_lines;
1508 unsigned short last_process_lines_in_grid;
1509
1510 unsigned short num_of_process_lines;
1511 unsigned short num_of_sets;
1512
1513 if (pl->grid_height_per_slice == 0)
1514 return -EINVAL;
1515
1516 if (pl->acc_enable && grid_last_line > pl->image_height)
1517 return -EINVAL;
1518
1519 num_of_sets = pl->grid_height / pl->grid_height_per_slice;
1520 if (num_of_sets * pl->grid_height_per_slice < pl->grid_height)
1521 num_of_sets++;
1522
1523
1524 if (pl->max_op == IMGU_ABI_AF_MAX_OPERATIONS) {
1525 first_process_lines = process_lines + pl->y_start + 2;
1526 last_process_lines_in_grid =
1527 (grid_last_line - first_process_lines) -
1528 ((num_of_sets - 2) * process_lines) + 4;
1529 process_lines_after_grid =
1530 pl->image_height - grid_last_line - 4;
1531 } else {
1532 first_process_lines = process_lines + pl->y_start;
1533 last_process_lines_in_grid =
1534 (grid_last_line - first_process_lines) -
1535 ((num_of_sets - 2) * process_lines);
1536 process_lines_after_grid = pl->image_height - grid_last_line;
1537 }
1538
1539 num_of_process_lines = num_of_sets;
1540 if (process_lines_after_grid > 0)
1541 num_of_process_lines++;
1542
1543 while (tr_idx < num_of_sets || pl_idx < num_of_process_lines) {
1544
1545 if (pl_idx >= 2 || (pl_idx == 1 && num_of_sets == 1)) {
1546 if (op_idx >= pl->max_op || tr_idx >= pl->max_tr)
1547 return -EINVAL;
1548
1549 p_op[op_idx].op_type =
1550 IMGU_ABI_ACC_OPTYPE_TRANSFER_DATA;
1551
1552 if (tr_idx == num_of_sets - 1)
1553
1554 p_op[op_idx].op_indicator =
1555 IMGU_ABI_ACC_OP_END_OF_OPS;
1556 else if (tr_idx == num_of_sets - 2)
1557 if (process_lines_after_grid == 0)
1558
1559
1560
1561
1562 p_op[op_idx].op_indicator =
1563 IMGU_ABI_ACC_OP_END_OF_ACK;
1564 else
1565
1566
1567
1568
1569 p_op[op_idx].op_indicator =
1570 IMGU_ABI_ACC_OP_IDLE;
1571 else
1572
1573 p_op[op_idx].op_indicator =
1574 IMGU_ABI_ACC_OP_IDLE;
1575
1576 op_idx++;
1577 if (p_tr) {
1578 p_tr[tr_idx].set_number = tr_set_num;
1579 tr_set_num = 1 - tr_set_num;
1580 }
1581 tr_idx++;
1582 }
1583
1584
1585 if (pl_idx < num_of_process_lines) {
1586 if (op_idx >= pl->max_op || pl_idx >= pl->max_tr)
1587 return -EINVAL;
1588
1589 p_op[op_idx].op_type =
1590 IMGU_ABI_ACC_OPTYPE_PROCESS_LINES;
1591 if (pl_idx == 0)
1592 if (num_of_process_lines == 1)
1593
1594 p_op[op_idx].op_indicator =
1595 IMGU_ABI_ACC_OP_END_OF_ACK;
1596 else
1597
1598 p_op[op_idx].op_indicator =
1599 IMGU_ABI_ACC_OP_IDLE;
1600 else
1601
1602 p_op[op_idx].op_indicator =
1603 IMGU_ABI_ACC_OP_END_OF_ACK;
1604
1605 op_idx++;
1606
1607 if (pl_idx == 0)
1608
1609 p_pl[pl_idx].lines = first_process_lines;
1610 else if (pl_idx == num_of_sets - 1)
1611
1612 p_pl[pl_idx].lines = last_process_lines_in_grid;
1613 else if (pl_idx == num_of_process_lines - 1)
1614
1615 p_pl[pl_idx].lines = process_lines_after_grid;
1616 else
1617
1618 p_pl[pl_idx].lines = process_lines;
1619
1620 if (p_tr) {
1621 p_pl[pl_idx].cfg_set = pl_cfg_set;
1622 pl_cfg_set = 1 - pl_cfg_set;
1623 }
1624 pl_idx++;
1625 }
1626 }
1627
1628 return 0;
1629 }
1630
1631 static int imgu_css_af_ops_calc(struct imgu_css *css, unsigned int pipe,
1632 struct imgu_abi_af_config *af_config)
1633 {
1634 struct imgu_abi_af_intra_frame_operations_data *to =
1635 &af_config->operations_data;
1636 struct imgu_css_pipe *css_pipe = &css->pipes[pipe];
1637 struct imgu_fw_info *bi =
1638 &css->fwp->binary_header[css_pipe->bindex];
1639
1640 struct process_lines pl = {
1641 .image_height = css_pipe->rect[IPU3_CSS_RECT_BDS].height,
1642 .grid_height = af_config->config.grid_cfg.height,
1643 .block_height =
1644 1 << af_config->config.grid_cfg.block_height_log2,
1645 .y_start = af_config->config.grid_cfg.y_start &
1646 IPU3_UAPI_GRID_START_MASK,
1647 .grid_height_per_slice =
1648 af_config->stripes[0].grid_cfg.height_per_slice,
1649 .max_op = IMGU_ABI_AF_MAX_OPERATIONS,
1650 .max_tr = IMGU_ABI_AF_MAX_TRANSFERS,
1651 .acc_enable = bi->info.isp.sp.enable.af,
1652 };
1653
1654 return imgu_css_acc_process_lines(&pl, to->ops, to->process_lines_data,
1655 NULL);
1656 }
1657
1658 static int
1659 imgu_css_awb_fr_ops_calc(struct imgu_css *css, unsigned int pipe,
1660 struct imgu_abi_awb_fr_config *awb_fr_config)
1661 {
1662 struct imgu_abi_awb_fr_intra_frame_operations_data *to =
1663 &awb_fr_config->operations_data;
1664 struct imgu_css_pipe *css_pipe = &css->pipes[pipe];
1665 struct imgu_fw_info *bi =
1666 &css->fwp->binary_header[css_pipe->bindex];
1667 struct process_lines pl = {
1668 .image_height = css_pipe->rect[IPU3_CSS_RECT_BDS].height,
1669 .grid_height = awb_fr_config->config.grid_cfg.height,
1670 .block_height =
1671 1 << awb_fr_config->config.grid_cfg.block_height_log2,
1672 .y_start = awb_fr_config->config.grid_cfg.y_start &
1673 IPU3_UAPI_GRID_START_MASK,
1674 .grid_height_per_slice =
1675 awb_fr_config->stripes[0].grid_cfg.height_per_slice,
1676 .max_op = IMGU_ABI_AWB_FR_MAX_OPERATIONS,
1677 .max_tr = IMGU_ABI_AWB_FR_MAX_PROCESS_LINES,
1678 .acc_enable = bi->info.isp.sp.enable.awb_fr_acc,
1679 };
1680
1681 return imgu_css_acc_process_lines(&pl, to->ops, to->process_lines_data,
1682 NULL);
1683 }
1684
1685 static int imgu_css_awb_ops_calc(struct imgu_css *css, unsigned int pipe,
1686 struct imgu_abi_awb_config *awb_config)
1687 {
1688 struct imgu_abi_awb_intra_frame_operations_data *to =
1689 &awb_config->operations_data;
1690 struct imgu_css_pipe *css_pipe = &css->pipes[pipe];
1691 struct imgu_fw_info *bi =
1692 &css->fwp->binary_header[css_pipe->bindex];
1693
1694 struct process_lines pl = {
1695 .image_height = css_pipe->rect[IPU3_CSS_RECT_BDS].height,
1696 .grid_height = awb_config->config.grid.height,
1697 .block_height =
1698 1 << awb_config->config.grid.block_height_log2,
1699 .y_start = awb_config->config.grid.y_start,
1700 .grid_height_per_slice =
1701 awb_config->stripes[0].grid.height_per_slice,
1702 .max_op = IMGU_ABI_AWB_MAX_OPERATIONS,
1703 .max_tr = IMGU_ABI_AWB_MAX_TRANSFERS,
1704 .acc_enable = bi->info.isp.sp.enable.awb_acc,
1705 };
1706
1707 return imgu_css_acc_process_lines(&pl, to->ops, to->process_lines_data,
1708 to->transfer_data);
1709 }
1710
1711 static u16 imgu_css_grid_end(u16 start, u8 width, u8 block_width_log2)
1712 {
1713 return (start & IPU3_UAPI_GRID_START_MASK) +
1714 (width << block_width_log2) - 1;
1715 }
1716
1717 static void imgu_css_grid_end_calc(struct ipu3_uapi_grid_config *grid_cfg)
1718 {
1719 grid_cfg->x_end = imgu_css_grid_end(grid_cfg->x_start, grid_cfg->width,
1720 grid_cfg->block_width_log2);
1721 grid_cfg->y_end = imgu_css_grid_end(grid_cfg->y_start, grid_cfg->height,
1722 grid_cfg->block_height_log2);
1723 }
1724
1725
1726
1727 static int imgu_css_cfg_acc_stripe(struct imgu_css *css, unsigned int pipe,
1728 struct imgu_abi_acc_param *acc)
1729 {
1730 struct imgu_css_pipe *css_pipe = &css->pipes[pipe];
1731 const struct imgu_fw_info *bi =
1732 &css->fwp->binary_header[css_pipe->bindex];
1733 struct imgu_css_scaler_info scaler_luma, scaler_chroma;
1734 const unsigned int stripes = bi->info.isp.sp.iterator.num_stripes;
1735 const unsigned int f = IPU3_UAPI_ISP_VEC_ELEMS * 2;
1736 unsigned int bds_ds, i;
1737
1738 memset(acc, 0, sizeof(*acc));
1739
1740
1741
1742 if (imgu_css_osys_calc(css, pipe, stripes, &acc->osys, &scaler_luma,
1743 &scaler_chroma, acc->stripe.block_stripes))
1744 return -EINVAL;
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757 acc->stripe.num_of_stripes = stripes;
1758 acc->stripe.input_frame.width =
1759 css_pipe->queue[IPU3_CSS_QUEUE_IN].fmt.mpix.width;
1760 acc->stripe.input_frame.height =
1761 css_pipe->queue[IPU3_CSS_QUEUE_IN].fmt.mpix.height;
1762 acc->stripe.input_frame.bayer_order =
1763 css_pipe->queue[IPU3_CSS_QUEUE_IN].css_fmt->bayer_order;
1764
1765 for (i = 0; i < stripes; i++)
1766 acc->stripe.bds_out_stripes[i].height =
1767 css_pipe->rect[IPU3_CSS_RECT_BDS].height;
1768 acc->stripe.bds_out_stripes[0].offset = 0;
1769 if (stripes <= 1) {
1770 acc->stripe.bds_out_stripes[0].width =
1771 ALIGN(css_pipe->rect[IPU3_CSS_RECT_BDS].width, f);
1772 } else {
1773
1774 acc->stripe.bds_out_stripes[0].width =
1775 acc->stripe.bds_out_stripes[1].width =
1776 (css_pipe->rect[IPU3_CSS_RECT_BDS].width / 2 & ~(f - 1)) + f;
1777
1778
1779
1780
1781
1782 if ((css_pipe->rect[IPU3_CSS_RECT_BDS].width / f & 1) !=
1783 !!(css_pipe->rect[IPU3_CSS_RECT_BDS].width & (f - 1)))
1784 acc->stripe.bds_out_stripes[0].width += f;
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 acc->stripe.bds_out_stripes[1].width += f;
1789 }
1790
1791 acc->stripe.bds_out_stripes[1].offset =
1792 acc->stripe.bds_out_stripes[0].width - 2 * f;
1793 }
1794
1795 acc->stripe.effective_stripes[0].height =
1796 css_pipe->rect[IPU3_CSS_RECT_EFFECTIVE].height;
1797 acc->stripe.effective_stripes[0].offset = 0;
1798 acc->stripe.bds_out_stripes_no_overlap[0].height =
1799 css_pipe->rect[IPU3_CSS_RECT_BDS].height;
1800 acc->stripe.bds_out_stripes_no_overlap[0].offset = 0;
1801 acc->stripe.output_stripes[0].height =
1802 css_pipe->queue[IPU3_CSS_QUEUE_OUT].fmt.mpix.height;
1803 acc->stripe.output_stripes[0].offset = 0;
1804 if (stripes <= 1) {
1805 acc->stripe.down_scaled_stripes[0].width =
1806 css_pipe->rect[IPU3_CSS_RECT_BDS].width;
1807 acc->stripe.down_scaled_stripes[0].height =
1808 css_pipe->rect[IPU3_CSS_RECT_BDS].height;
1809 acc->stripe.down_scaled_stripes[0].offset = 0;
1810
1811 acc->stripe.effective_stripes[0].width =
1812 css_pipe->rect[IPU3_CSS_RECT_EFFECTIVE].width;
1813 acc->stripe.bds_out_stripes_no_overlap[0].width =
1814 ALIGN(css_pipe->rect[IPU3_CSS_RECT_BDS].width, f);
1815
1816 acc->stripe.output_stripes[0].width =
1817 css_pipe->queue[IPU3_CSS_QUEUE_OUT].fmt.mpix.width;
1818 } else {
1819 bds_ds = css_pipe->rect[IPU3_CSS_RECT_EFFECTIVE].width *
1820 IMGU_BDS_GRANULARITY /
1821 css_pipe->rect[IPU3_CSS_RECT_BDS].width;
1822
1823 acc->stripe.down_scaled_stripes[0] =
1824 acc->stripe.bds_out_stripes[0];
1825 acc->stripe.down_scaled_stripes[1] =
1826 acc->stripe.bds_out_stripes[1];
1827 if (!IS_ALIGNED(css_pipe->rect[IPU3_CSS_RECT_BDS].width, f))
1828 acc->stripe.down_scaled_stripes[1].width +=
1829 (css_pipe->rect[IPU3_CSS_RECT_BDS].width
1830 & (f - 1)) - f;
1831
1832 acc->stripe.effective_stripes[0].width = bds_ds *
1833 acc->stripe.down_scaled_stripes[0].width /
1834 IMGU_BDS_GRANULARITY;
1835 acc->stripe.effective_stripes[1].width = bds_ds *
1836 acc->stripe.down_scaled_stripes[1].width /
1837 IMGU_BDS_GRANULARITY;
1838 acc->stripe.effective_stripes[1].height =
1839 css_pipe->rect[IPU3_CSS_RECT_EFFECTIVE].height;
1840 acc->stripe.effective_stripes[1].offset = bds_ds *
1841 acc->stripe.down_scaled_stripes[1].offset /
1842 IMGU_BDS_GRANULARITY;
1843
1844 acc->stripe.bds_out_stripes_no_overlap[0].width =
1845 acc->stripe.bds_out_stripes_no_overlap[1].offset =
1846 ALIGN(css_pipe->rect[IPU3_CSS_RECT_BDS].width, 2 * f) / 2;
1847 acc->stripe.bds_out_stripes_no_overlap[1].width =
1848 DIV_ROUND_UP(css_pipe->rect[IPU3_CSS_RECT_BDS].width, f)
1849 / 2 * f;
1850 acc->stripe.bds_out_stripes_no_overlap[1].height =
1851 css_pipe->rect[IPU3_CSS_RECT_BDS].height;
1852
1853 acc->stripe.output_stripes[0].width =
1854 acc->stripe.down_scaled_stripes[0].width - f;
1855 acc->stripe.output_stripes[1].width =
1856 acc->stripe.down_scaled_stripes[1].width - f;
1857 acc->stripe.output_stripes[1].height =
1858 css_pipe->queue[IPU3_CSS_QUEUE_OUT].fmt.mpix.height;
1859 acc->stripe.output_stripes[1].offset =
1860 acc->stripe.output_stripes[0].width;
1861 }
1862
1863 acc->stripe.output_system_in_frame_width =
1864 css_pipe->rect[IPU3_CSS_RECT_GDC].width;
1865 acc->stripe.output_system_in_frame_height =
1866 css_pipe->rect[IPU3_CSS_RECT_GDC].height;
1867
1868 acc->stripe.effective_frame_width =
1869 css_pipe->rect[IPU3_CSS_RECT_EFFECTIVE].width;
1870 acc->stripe.bds_frame_width = css_pipe->rect[IPU3_CSS_RECT_BDS].width;
1871 acc->stripe.out_frame_width =
1872 css_pipe->queue[IPU3_CSS_QUEUE_OUT].fmt.mpix.width;
1873 acc->stripe.out_frame_height =
1874 css_pipe->queue[IPU3_CSS_QUEUE_OUT].fmt.mpix.height;
1875 acc->stripe.gdc_in_buffer_width =
1876 css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_REF].bytesperline /
1877 css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_REF].bytesperpixel;
1878 acc->stripe.gdc_in_buffer_height =
1879 css_pipe->aux_frames[IPU3_CSS_AUX_FRAME_REF].height;
1880 acc->stripe.gdc_in_buffer_offset_x = IMGU_GDC_BUF_X;
1881 acc->stripe.gdc_in_buffer_offset_y = IMGU_GDC_BUF_Y;
1882 acc->stripe.display_frame_width =
1883 css_pipe->queue[IPU3_CSS_QUEUE_VF].fmt.mpix.width;
1884 acc->stripe.display_frame_height =
1885 css_pipe->queue[IPU3_CSS_QUEUE_VF].fmt.mpix.height;
1886 acc->stripe.bds_aligned_frame_width =
1887 roundup(css_pipe->rect[IPU3_CSS_RECT_BDS].width,
1888 2 * IPU3_UAPI_ISP_VEC_ELEMS);
1889
1890 if (stripes > 1)
1891 acc->stripe.half_overlap_vectors =
1892 IMGU_STRIPE_FIXED_HALF_OVERLAP;
1893 else
1894 acc->stripe.half_overlap_vectors = 0;
1895
1896 return 0;
1897 }
1898
1899 static void imgu_css_cfg_acc_dvs(struct imgu_css *css,
1900 struct imgu_abi_acc_param *acc,
1901 unsigned int pipe)
1902 {
1903 unsigned int i;
1904 struct imgu_css_pipe *css_pipe = &css->pipes[pipe];
1905
1906
1907 acc->dvs_stat.operations_data.process_lines_data[0].lines =
1908 css_pipe->rect[IPU3_CSS_RECT_BDS].height;
1909 acc->dvs_stat.operations_data.process_lines_data[0].cfg_set = 0;
1910 acc->dvs_stat.operations_data.ops[0].op_type =
1911 IMGU_ABI_ACC_OPTYPE_PROCESS_LINES;
1912 acc->dvs_stat.operations_data.ops[0].op_indicator =
1913 IMGU_ABI_ACC_OP_NO_OPS;
1914 for (i = 0; i < IMGU_ABI_DVS_STAT_LEVELS; i++)
1915 acc->dvs_stat.cfg.grd_config[i].enable = 0;
1916 }
1917
1918 static void acc_bds_per_stripe_data(struct imgu_css *css,
1919 struct imgu_abi_acc_param *acc,
1920 const int i, unsigned int pipe)
1921 {
1922 struct imgu_css_pipe *css_pipe = &css->pipes[pipe];
1923
1924 acc->bds.per_stripe.aligned_data[i].data.crop.hor_crop_en = 0;
1925 acc->bds.per_stripe.aligned_data[i].data.crop.hor_crop_start = 0;
1926 acc->bds.per_stripe.aligned_data[i].data.crop.hor_crop_end = 0;
1927 acc->bds.per_stripe.aligned_data[i].data.hor_ctrl0 =
1928 acc->bds.hor.hor_ctrl0;
1929 acc->bds.per_stripe.aligned_data[i].data.hor_ctrl0.out_frame_width =
1930 acc->stripe.down_scaled_stripes[i].width;
1931 acc->bds.per_stripe.aligned_data[i].data.ver_ctrl1.out_frame_width =
1932 acc->stripe.down_scaled_stripes[i].width;
1933 acc->bds.per_stripe.aligned_data[i].data.ver_ctrl1.out_frame_height =
1934 css_pipe->rect[IPU3_CSS_RECT_BDS].height;
1935 }
1936
1937
1938
1939
1940
1941
1942
1943 int imgu_css_cfg_acc(struct imgu_css *css, unsigned int pipe,
1944 struct ipu3_uapi_flags *use,
1945 struct imgu_abi_acc_param *acc,
1946 struct imgu_abi_acc_param *acc_old,
1947 struct ipu3_uapi_acc_param *acc_user)
1948 {
1949 struct imgu_css_pipe *css_pipe = &css->pipes[pipe];
1950 const struct imgu_fw_info *bi =
1951 &css->fwp->binary_header[css_pipe->bindex];
1952 const unsigned int stripes = bi->info.isp.sp.iterator.num_stripes;
1953 const unsigned int tnr_frame_width =
1954 acc->stripe.bds_aligned_frame_width;
1955 const unsigned int min_overlap = 10;
1956 const struct v4l2_pix_format_mplane *pixm =
1957 &css_pipe->queue[IPU3_CSS_QUEUE_IN].fmt.mpix;
1958 const struct imgu_css_bds_config *cfg_bds;
1959 struct imgu_abi_input_feeder_data *feeder_data;
1960
1961 unsigned int bds_ds, ofs_x, ofs_y, i, width, height;
1962 u8 b_w_log2;
1963
1964
1965
1966 if (imgu_css_cfg_acc_stripe(css, pipe, acc))
1967 return -EINVAL;
1968
1969
1970
1971 ofs_x = ((pixm->width -
1972 css_pipe->rect[IPU3_CSS_RECT_EFFECTIVE].width) >> 1) & ~1;
1973 ofs_x += css_pipe->queue[IPU3_CSS_QUEUE_IN].css_fmt->bayer_order ==
1974 IMGU_ABI_BAYER_ORDER_RGGB ||
1975 css_pipe->queue[IPU3_CSS_QUEUE_IN].css_fmt->bayer_order ==
1976 IMGU_ABI_BAYER_ORDER_GBRG ? 1 : 0;
1977 ofs_y = ((pixm->height -
1978 css_pipe->rect[IPU3_CSS_RECT_EFFECTIVE].height) >> 1) & ~1;
1979 ofs_y += css_pipe->queue[IPU3_CSS_QUEUE_IN].css_fmt->bayer_order ==
1980 IMGU_ABI_BAYER_ORDER_BGGR ||
1981 css_pipe->queue[IPU3_CSS_QUEUE_IN].css_fmt->bayer_order ==
1982 IMGU_ABI_BAYER_ORDER_GBRG ? 1 : 0;
1983 acc->input_feeder.data.row_stride = pixm->plane_fmt[0].bytesperline;
1984 acc->input_feeder.data.start_row_address =
1985 ofs_x / IMGU_PIXELS_PER_WORD * IMGU_BYTES_PER_WORD +
1986 ofs_y * acc->input_feeder.data.row_stride;
1987 acc->input_feeder.data.start_pixel = ofs_x % IMGU_PIXELS_PER_WORD;
1988
1989 acc->input_feeder.data_per_stripe.input_feeder_data[0].data =
1990 acc->input_feeder.data;
1991
1992 ofs_x += acc->stripe.effective_stripes[1].offset;
1993
1994 feeder_data =
1995 &acc->input_feeder.data_per_stripe.input_feeder_data[1].data;
1996 feeder_data->row_stride = acc->input_feeder.data.row_stride;
1997 feeder_data->start_row_address =
1998 ofs_x / IMGU_PIXELS_PER_WORD * IMGU_BYTES_PER_WORD +
1999 ofs_y * acc->input_feeder.data.row_stride;
2000 feeder_data->start_pixel = ofs_x % IMGU_PIXELS_PER_WORD;
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012 if (use && use->acc_bnr) {
2013
2014 acc->bnr = acc_user->bnr;
2015 } else if (acc_old) {
2016
2017 acc->bnr = acc_old->bnr;
2018 } else {
2019
2020 acc->bnr = imgu_css_bnr_defaults;
2021 }
2022
2023 acc->bnr.column_size = tnr_frame_width;
2024
2025
2026
2027 if (use && use->acc_green_disparity) {
2028
2029 acc->green_disparity = acc_user->green_disparity;
2030 } else if (acc_old) {
2031
2032 acc->green_disparity = acc_old->green_disparity;
2033 } else {
2034
2035 memset(&acc->green_disparity, 0, sizeof(acc->green_disparity));
2036 }
2037
2038
2039
2040 if (use && use->acc_dm) {
2041
2042 acc->dm = acc_user->dm;
2043 } else if (acc_old) {
2044
2045 acc->dm = acc_old->dm;
2046 } else {
2047
2048 acc->dm = imgu_css_dm_defaults;
2049 }
2050
2051 acc->dm.frame_width = tnr_frame_width;
2052
2053
2054
2055 if (use && use->acc_ccm) {
2056
2057 acc->ccm = acc_user->ccm;
2058 } else if (acc_old) {
2059
2060 acc->ccm = acc_old->ccm;
2061 } else {
2062
2063 acc->ccm = imgu_css_ccm_defaults;
2064 }
2065
2066
2067
2068 if (use && use->acc_gamma) {
2069
2070 acc->gamma = acc_user->gamma;
2071 } else if (acc_old) {
2072
2073 acc->gamma = acc_old->gamma;
2074 } else {
2075
2076 acc->gamma.gc_ctrl.enable = 1;
2077 acc->gamma.gc_lut = imgu_css_gamma_lut;
2078 }
2079
2080
2081
2082 if (use && use->acc_csc) {
2083
2084 acc->csc = acc_user->csc;
2085 } else if (acc_old) {
2086
2087 acc->csc = acc_old->csc;
2088 } else {
2089
2090 acc->csc = imgu_css_csc_defaults;
2091 }
2092
2093
2094
2095 if (use && use->acc_cds) {
2096
2097 acc->cds = acc_user->cds;
2098 } else if (acc_old) {
2099
2100 acc->cds = acc_old->cds;
2101 } else {
2102
2103 acc->cds = imgu_css_cds_defaults;
2104 }
2105
2106
2107
2108 if (use && use->acc_shd) {
2109
2110 acc->shd.shd = acc_user->shd.shd;
2111 acc->shd.shd_lut = acc_user->shd.shd_lut;
2112 } else if (acc_old) {
2113
2114 acc->shd.shd = acc_old->shd.shd;
2115 acc->shd.shd_lut = acc_old->shd.shd_lut;
2116 } else {
2117
2118 acc->shd.shd = imgu_css_shd_defaults;
2119 memset(&acc->shd.shd_lut, 0, sizeof(acc->shd.shd_lut));
2120 }
2121
2122 if (acc->shd.shd.grid.width <= 0)
2123 return -EINVAL;
2124
2125 acc->shd.shd.grid.grid_height_per_slice =
2126 IMGU_ABI_SHD_MAX_CELLS_PER_SET / acc->shd.shd.grid.width;
2127
2128 if (acc->shd.shd.grid.grid_height_per_slice <= 0)
2129 return -EINVAL;
2130
2131 acc->shd.shd.general.init_set_vrt_offst_ul =
2132 (-acc->shd.shd.grid.y_start >>
2133 acc->shd.shd.grid.block_height_log2) %
2134 acc->shd.shd.grid.grid_height_per_slice;
2135
2136 if (imgu_css_shd_ops_calc(&acc->shd.shd_ops, &acc->shd.shd.grid,
2137 css_pipe->rect[IPU3_CSS_RECT_BDS].height))
2138 return -EINVAL;
2139
2140
2141 imgu_css_cfg_acc_dvs(css, acc, pipe);
2142
2143
2144
2145 if (use && use->acc_iefd) {
2146
2147 acc->iefd = acc_user->iefd;
2148 } else if (acc_old) {
2149
2150 acc->iefd = acc_old->iefd;
2151 } else {
2152
2153 acc->iefd = imgu_css_iefd_defaults;
2154 }
2155
2156
2157
2158 if (use && use->acc_yds_c0) {
2159
2160 acc->yds_c0 = acc_user->yds_c0;
2161 } else if (acc_old) {
2162
2163 acc->yds_c0 = acc_old->yds_c0;
2164 } else {
2165
2166 acc->yds_c0 = imgu_css_yds_defaults;
2167 }
2168
2169
2170
2171 if (use && use->acc_chnr_c0) {
2172
2173 acc->chnr_c0 = acc_user->chnr_c0;
2174 } else if (acc_old) {
2175
2176 acc->chnr_c0 = acc_old->chnr_c0;
2177 } else {
2178
2179 acc->chnr_c0 = imgu_css_chnr_defaults;
2180 }
2181
2182
2183
2184 if (use && use->acc_y_ee_nr) {
2185
2186 acc->y_ee_nr = acc_user->y_ee_nr;
2187 } else if (acc_old) {
2188
2189 acc->y_ee_nr = acc_old->y_ee_nr;
2190 } else {
2191
2192 acc->y_ee_nr = imgu_css_y_ee_nr_defaults;
2193 }
2194
2195
2196
2197 if (use && use->acc_yds) {
2198
2199 acc->yds = acc_user->yds;
2200 } else if (acc_old) {
2201
2202 acc->yds = acc_old->yds;
2203 } else {
2204
2205 acc->yds = imgu_css_yds_defaults;
2206 }
2207
2208
2209
2210 if (use && use->acc_chnr) {
2211
2212 acc->chnr = acc_user->chnr;
2213 } else if (acc_old) {
2214
2215 acc->chnr = acc_old->chnr;
2216 } else {
2217
2218 acc->chnr = imgu_css_chnr_defaults;
2219 }
2220
2221
2222
2223 for (i = 0; i < IMGU_ABI_YUVP2_YTM_LUT_ENTRIES; i++)
2224 acc->ytm.entries[i] = i * 32;
2225 acc->ytm.enable = 0;
2226
2227
2228
2229 if (use && use->acc_yds2) {
2230
2231 acc->yds2 = acc_user->yds2;
2232 } else if (acc_old) {
2233
2234 acc->yds2 = acc_old->yds2;
2235 } else {
2236
2237 acc->yds2 = imgu_css_yds_defaults;
2238 }
2239
2240
2241
2242 if (use && use->acc_tcc) {
2243
2244 acc->tcc = acc_user->tcc;
2245 } else if (acc_old) {
2246
2247 acc->tcc = acc_old->tcc;
2248 } else {
2249
2250 memset(&acc->tcc, 0, sizeof(acc->tcc));
2251
2252 acc->tcc.gen_control.en = 1;
2253 acc->tcc.gen_control.blend_shift = 3;
2254 acc->tcc.gen_control.gain_according_to_y_only = 1;
2255 acc->tcc.gen_control.gamma = 8;
2256 acc->tcc.gen_control.delta = 0;
2257
2258 for (i = 0; i < IPU3_UAPI_YUVP2_TCC_MACC_TABLE_ELEMENTS; i++) {
2259 acc->tcc.macc_table.entries[i].a = 1024;
2260 acc->tcc.macc_table.entries[i].b = 0;
2261 acc->tcc.macc_table.entries[i].c = 0;
2262 acc->tcc.macc_table.entries[i].d = 1024;
2263 }
2264
2265 acc->tcc.inv_y_lut.entries[6] = 1023;
2266 for (i = 7; i < IPU3_UAPI_YUVP2_TCC_INV_Y_LUT_ELEMENTS; i++)
2267 acc->tcc.inv_y_lut.entries[i] = 1024 >> (i - 6);
2268
2269 acc->tcc.gain_pcwl = imgu_css_tcc_gain_pcwl_lut;
2270 acc->tcc.r_sqr_lut = imgu_css_tcc_r_sqr_lut;
2271 }
2272
2273
2274
2275 if (use && use->acc_dpc)
2276 return -EINVAL;
2277
2278
2279 memset(&acc->dpc, 0, sizeof(acc->dpc));
2280
2281
2282
2283 bds_ds = (css_pipe->rect[IPU3_CSS_RECT_EFFECTIVE].height *
2284 IMGU_BDS_GRANULARITY) / css_pipe->rect[IPU3_CSS_RECT_BDS].height;
2285 if (bds_ds < IMGU_BDS_MIN_SF_INV ||
2286 bds_ds - IMGU_BDS_MIN_SF_INV >= ARRAY_SIZE(imgu_css_bds_configs))
2287 return -EINVAL;
2288
2289 cfg_bds = &imgu_css_bds_configs[bds_ds - IMGU_BDS_MIN_SF_INV];
2290 acc->bds.hor.hor_ctrl1.hor_crop_en = 0;
2291 acc->bds.hor.hor_ctrl1.hor_crop_start = 0;
2292 acc->bds.hor.hor_ctrl1.hor_crop_end = 0;
2293 acc->bds.hor.hor_ctrl0.sample_patrn_length =
2294 cfg_bds->sample_patrn_length;
2295 acc->bds.hor.hor_ctrl0.hor_ds_en = cfg_bds->hor_ds_en;
2296 acc->bds.hor.hor_ctrl0.min_clip_val = IMGU_BDS_MIN_CLIP_VAL;
2297 acc->bds.hor.hor_ctrl0.max_clip_val = IMGU_BDS_MAX_CLIP_VAL;
2298 acc->bds.hor.hor_ctrl0.out_frame_width =
2299 css_pipe->rect[IPU3_CSS_RECT_BDS].width;
2300 acc->bds.hor.hor_ptrn_arr = cfg_bds->ptrn_arr;
2301 acc->bds.hor.hor_phase_arr = cfg_bds->hor_phase_arr;
2302 acc->bds.hor.hor_ctrl2.input_frame_height =
2303 css_pipe->rect[IPU3_CSS_RECT_EFFECTIVE].height;
2304 acc->bds.ver.ver_ctrl0.min_clip_val = IMGU_BDS_MIN_CLIP_VAL;
2305 acc->bds.ver.ver_ctrl0.max_clip_val = IMGU_BDS_MAX_CLIP_VAL;
2306 acc->bds.ver.ver_ctrl0.sample_patrn_length =
2307 cfg_bds->sample_patrn_length;
2308 acc->bds.ver.ver_ctrl0.ver_ds_en = cfg_bds->ver_ds_en;
2309 acc->bds.ver.ver_ptrn_arr = cfg_bds->ptrn_arr;
2310 acc->bds.ver.ver_phase_arr = cfg_bds->ver_phase_arr;
2311 acc->bds.ver.ver_ctrl1.out_frame_width =
2312 css_pipe->rect[IPU3_CSS_RECT_BDS].width;
2313 acc->bds.ver.ver_ctrl1.out_frame_height =
2314 css_pipe->rect[IPU3_CSS_RECT_BDS].height;
2315 for (i = 0; i < stripes; i++)
2316 acc_bds_per_stripe_data(css, acc, i, pipe);
2317
2318 acc->bds.enabled = cfg_bds->hor_ds_en || cfg_bds->ver_ds_en;
2319
2320
2321
2322 if (use && use->acc_anr) {
2323
2324 acc->anr.transform = acc_user->anr.transform;
2325 acc->anr.stitch.anr_stitch_en =
2326 acc_user->anr.stitch.anr_stitch_en;
2327 memcpy(acc->anr.stitch.pyramid, acc_user->anr.stitch.pyramid,
2328 sizeof(acc->anr.stitch.pyramid));
2329 } else if (acc_old) {
2330
2331 acc->anr.transform = acc_old->anr.transform;
2332 acc->anr.stitch.anr_stitch_en =
2333 acc_old->anr.stitch.anr_stitch_en;
2334 memcpy(acc->anr.stitch.pyramid, acc_old->anr.stitch.pyramid,
2335 sizeof(acc->anr.stitch.pyramid));
2336 } else {
2337
2338 acc->anr = imgu_css_anr_defaults;
2339 }
2340
2341
2342 acc->anr.search.enable = 1;
2343 acc->anr.transform.enable = 1;
2344 acc->anr.tile2strm.enable = 1;
2345 acc->anr.tile2strm.frame_width =
2346 ALIGN(css_pipe->rect[IPU3_CSS_RECT_BDS].width, IMGU_ISP_VMEM_ALIGN);
2347 acc->anr.search.frame_width = acc->anr.tile2strm.frame_width;
2348 acc->anr.stitch.frame_width = acc->anr.tile2strm.frame_width;
2349 acc->anr.tile2strm.frame_height = css_pipe->rect[IPU3_CSS_RECT_BDS].height;
2350 acc->anr.search.frame_height = acc->anr.tile2strm.frame_height;
2351 acc->anr.stitch.frame_height = acc->anr.tile2strm.frame_height;
2352
2353 width = ALIGN(css_pipe->rect[IPU3_CSS_RECT_BDS].width, IMGU_ISP_VMEM_ALIGN);
2354 height = css_pipe->rect[IPU3_CSS_RECT_BDS].height;
2355
2356 if (acc->anr.transform.xreset + width > IPU3_UAPI_ANR_MAX_RESET)
2357 acc->anr.transform.xreset = IPU3_UAPI_ANR_MAX_RESET - width;
2358 if (acc->anr.transform.xreset < IPU3_UAPI_ANR_MIN_RESET)
2359 acc->anr.transform.xreset = IPU3_UAPI_ANR_MIN_RESET;
2360
2361 if (acc->anr.transform.yreset + height > IPU3_UAPI_ANR_MAX_RESET)
2362 acc->anr.transform.yreset = IPU3_UAPI_ANR_MAX_RESET - height;
2363 if (acc->anr.transform.yreset < IPU3_UAPI_ANR_MIN_RESET)
2364 acc->anr.transform.yreset = IPU3_UAPI_ANR_MIN_RESET;
2365
2366
2367
2368 if (use && use->acc_awb_fr) {
2369
2370 acc->awb_fr.config = acc_user->awb_fr;
2371 } else if (acc_old) {
2372
2373 acc->awb_fr.config = acc_old->awb_fr.config;
2374 } else {
2375
2376 acc->awb_fr.config = imgu_css_awb_fr_defaults;
2377 }
2378
2379 imgu_css_grid_end_calc(&acc->awb_fr.config.grid_cfg);
2380
2381 if (acc->awb_fr.config.grid_cfg.width <= 0)
2382 return -EINVAL;
2383
2384 acc->awb_fr.config.grid_cfg.height_per_slice =
2385 IMGU_ABI_AWB_FR_MAX_CELLS_PER_SET /
2386 acc->awb_fr.config.grid_cfg.width;
2387
2388 for (i = 0; i < stripes; i++)
2389 acc->awb_fr.stripes[i] = acc->awb_fr.config;
2390
2391 if (acc->awb_fr.config.grid_cfg.x_start >=
2392 acc->stripe.down_scaled_stripes[1].offset + min_overlap) {
2393
2394 acc->awb_fr.stripes[0].grid_cfg.y_start &=
2395 ~IPU3_UAPI_GRID_Y_START_EN;
2396 } else if (acc->awb_fr.config.grid_cfg.x_end <=
2397 acc->stripe.bds_out_stripes[0].width - min_overlap) {
2398
2399 acc->awb_fr.stripes[1].grid_cfg.y_start &=
2400 ~IPU3_UAPI_GRID_Y_START_EN;
2401 } else {
2402
2403 u16 end;
2404
2405 acc->awb_fr.stripes[0].grid_cfg.width =
2406 (acc->stripe.bds_out_stripes[0].width - min_overlap -
2407 acc->awb_fr.config.grid_cfg.x_start + 1) >>
2408 acc->awb_fr.config.grid_cfg.block_width_log2;
2409 acc->awb_fr.stripes[1].grid_cfg.width =
2410 acc->awb_fr.config.grid_cfg.width -
2411 acc->awb_fr.stripes[0].grid_cfg.width;
2412
2413 b_w_log2 = acc->awb_fr.stripes[0].grid_cfg.block_width_log2;
2414 end = imgu_css_grid_end(acc->awb_fr.stripes[0].grid_cfg.x_start,
2415 acc->awb_fr.stripes[0].grid_cfg.width,
2416 b_w_log2);
2417 acc->awb_fr.stripes[0].grid_cfg.x_end = end;
2418
2419 acc->awb_fr.stripes[1].grid_cfg.x_start =
2420 (acc->awb_fr.stripes[0].grid_cfg.x_end + 1 -
2421 acc->stripe.down_scaled_stripes[1].offset) &
2422 IPU3_UAPI_GRID_START_MASK;
2423 b_w_log2 = acc->awb_fr.stripes[1].grid_cfg.block_width_log2;
2424 end = imgu_css_grid_end(acc->awb_fr.stripes[1].grid_cfg.x_start,
2425 acc->awb_fr.stripes[1].grid_cfg.width,
2426 b_w_log2);
2427 acc->awb_fr.stripes[1].grid_cfg.x_end = end;
2428
2429
2430
2431
2432
2433
2434 for (i = 0; i < stripes; i++)
2435 acc->awb_fr.stripes[i].grid_cfg.height_per_slice = 1;
2436 }
2437
2438 if (imgu_css_awb_fr_ops_calc(css, pipe, &acc->awb_fr))
2439 return -EINVAL;
2440
2441
2442
2443 if (use && use->acc_ae) {
2444
2445 acc->ae.grid_cfg = acc_user->ae.grid_cfg;
2446 acc->ae.ae_ccm = acc_user->ae.ae_ccm;
2447 for (i = 0; i < IPU3_UAPI_AE_WEIGHTS; i++)
2448 acc->ae.weights[i] = acc_user->ae.weights[i];
2449 } else if (acc_old) {
2450
2451 acc->ae.grid_cfg = acc_old->ae.grid_cfg;
2452 acc->ae.ae_ccm = acc_old->ae.ae_ccm;
2453 for (i = 0; i < IPU3_UAPI_AE_WEIGHTS; i++)
2454 acc->ae.weights[i] = acc_old->ae.weights[i];
2455 } else {
2456
2457 static const struct ipu3_uapi_ae_weight_elem
2458 weight_def = { 1, 1, 1, 1, 1, 1, 1, 1 };
2459
2460 acc->ae.grid_cfg = imgu_css_ae_grid_defaults;
2461 acc->ae.ae_ccm = imgu_css_ae_ccm_defaults;
2462 for (i = 0; i < IPU3_UAPI_AE_WEIGHTS; i++)
2463 acc->ae.weights[i] = weight_def;
2464 }
2465
2466 b_w_log2 = acc->ae.grid_cfg.block_width_log2;
2467 acc->ae.grid_cfg.x_end = imgu_css_grid_end(acc->ae.grid_cfg.x_start,
2468 acc->ae.grid_cfg.width,
2469 b_w_log2);
2470 b_w_log2 = acc->ae.grid_cfg.block_height_log2;
2471 acc->ae.grid_cfg.y_end = imgu_css_grid_end(acc->ae.grid_cfg.y_start,
2472 acc->ae.grid_cfg.height,
2473 b_w_log2);
2474
2475 for (i = 0; i < stripes; i++)
2476 acc->ae.stripes[i].grid = acc->ae.grid_cfg;
2477
2478 if (acc->ae.grid_cfg.x_start >=
2479 acc->stripe.down_scaled_stripes[1].offset) {
2480
2481 acc->ae.stripes[0].grid.ae_en = 0;
2482 } else if (acc->ae.grid_cfg.x_end <=
2483 acc->stripe.bds_out_stripes[0].width) {
2484
2485 acc->ae.stripes[1].grid.ae_en = 0;
2486 } else {
2487
2488 u8 b_w_log2;
2489
2490 acc->ae.stripes[0].grid.width =
2491 (acc->stripe.bds_out_stripes[0].width -
2492 acc->ae.grid_cfg.x_start + 1) >>
2493 acc->ae.grid_cfg.block_width_log2;
2494
2495 acc->ae.stripes[1].grid.width =
2496 acc->ae.grid_cfg.width - acc->ae.stripes[0].grid.width;
2497
2498 b_w_log2 = acc->ae.stripes[0].grid.block_width_log2;
2499 acc->ae.stripes[0].grid.x_end =
2500 imgu_css_grid_end(acc->ae.stripes[0].grid.x_start,
2501 acc->ae.stripes[0].grid.width,
2502 b_w_log2);
2503
2504 acc->ae.stripes[1].grid.x_start =
2505 (acc->ae.stripes[0].grid.x_end + 1 -
2506 acc->stripe.down_scaled_stripes[1].offset) &
2507 IPU3_UAPI_GRID_START_MASK;
2508 b_w_log2 = acc->ae.stripes[1].grid.block_width_log2;
2509 acc->ae.stripes[1].grid.x_end =
2510 imgu_css_grid_end(acc->ae.stripes[1].grid.x_start,
2511 acc->ae.stripes[1].grid.width,
2512 b_w_log2);
2513 }
2514
2515
2516
2517 if (use && use->acc_af) {
2518
2519 acc->af.config.filter_config = acc_user->af.filter_config;
2520 acc->af.config.grid_cfg = acc_user->af.grid_cfg;
2521 } else if (acc_old) {
2522
2523 acc->af.config = acc_old->af.config;
2524 } else {
2525
2526 acc->af.config.filter_config =
2527 imgu_css_af_defaults.filter_config;
2528 acc->af.config.grid_cfg = imgu_css_af_defaults.grid_cfg;
2529 }
2530
2531 imgu_css_grid_end_calc(&acc->af.config.grid_cfg);
2532
2533 if (acc->af.config.grid_cfg.width <= 0)
2534 return -EINVAL;
2535
2536 acc->af.config.grid_cfg.height_per_slice =
2537 IMGU_ABI_AF_MAX_CELLS_PER_SET / acc->af.config.grid_cfg.width;
2538 acc->af.config.frame_size.width =
2539 ALIGN(css_pipe->rect[IPU3_CSS_RECT_BDS].width, IMGU_ISP_VMEM_ALIGN);
2540 acc->af.config.frame_size.height =
2541 css_pipe->rect[IPU3_CSS_RECT_BDS].height;
2542
2543 if (acc->stripe.bds_out_stripes[0].width <= min_overlap)
2544 return -EINVAL;
2545
2546 for (i = 0; i < stripes; i++) {
2547 acc->af.stripes[i].grid_cfg = acc->af.config.grid_cfg;
2548 acc->af.stripes[i].frame_size.height =
2549 css_pipe->rect[IPU3_CSS_RECT_BDS].height;
2550 acc->af.stripes[i].frame_size.width =
2551 acc->stripe.bds_out_stripes[i].width;
2552 }
2553
2554 if (acc->af.config.grid_cfg.x_start >=
2555 acc->stripe.down_scaled_stripes[1].offset + min_overlap) {
2556
2557 acc->af.stripes[0].grid_cfg.y_start &=
2558 ~IPU3_UAPI_GRID_Y_START_EN;
2559 acc->af.stripes[1].grid_cfg.x_start =
2560 (acc->af.stripes[1].grid_cfg.x_start -
2561 acc->stripe.down_scaled_stripes[1].offset) &
2562 IPU3_UAPI_GRID_START_MASK;
2563 b_w_log2 = acc->af.stripes[1].grid_cfg.block_width_log2;
2564 acc->af.stripes[1].grid_cfg.x_end =
2565 imgu_css_grid_end(acc->af.stripes[1].grid_cfg.x_start,
2566 acc->af.stripes[1].grid_cfg.width,
2567 b_w_log2);
2568 } else if (acc->af.config.grid_cfg.x_end <=
2569 acc->stripe.bds_out_stripes[0].width - min_overlap) {
2570
2571 acc->af.stripes[1].grid_cfg.y_start &=
2572 ~IPU3_UAPI_GRID_Y_START_EN;
2573 } else {
2574
2575
2576 acc->af.stripes[0].grid_cfg.width =
2577 (acc->stripe.bds_out_stripes[0].width - min_overlap -
2578 acc->af.config.grid_cfg.x_start + 1) >>
2579 acc->af.config.grid_cfg.block_width_log2;
2580 acc->af.stripes[1].grid_cfg.width =
2581 acc->af.config.grid_cfg.width -
2582 acc->af.stripes[0].grid_cfg.width;
2583
2584 b_w_log2 = acc->af.stripes[0].grid_cfg.block_width_log2;
2585 acc->af.stripes[0].grid_cfg.x_end =
2586 imgu_css_grid_end(acc->af.stripes[0].grid_cfg.x_start,
2587 acc->af.stripes[0].grid_cfg.width,
2588 b_w_log2);
2589
2590 acc->af.stripes[1].grid_cfg.x_start =
2591 (acc->af.stripes[0].grid_cfg.x_end + 1 -
2592 acc->stripe.down_scaled_stripes[1].offset) &
2593 IPU3_UAPI_GRID_START_MASK;
2594
2595 b_w_log2 = acc->af.stripes[1].grid_cfg.block_width_log2;
2596 acc->af.stripes[1].grid_cfg.x_end =
2597 imgu_css_grid_end(acc->af.stripes[1].grid_cfg.x_start,
2598 acc->af.stripes[1].grid_cfg.width,
2599 b_w_log2);
2600
2601
2602
2603
2604
2605 for (i = 0; i < stripes; i++)
2606 acc->af.stripes[i].grid_cfg.height_per_slice = 1;
2607 }
2608
2609 if (imgu_css_af_ops_calc(css, pipe, &acc->af))
2610 return -EINVAL;
2611
2612
2613
2614 if (use && use->acc_awb) {
2615
2616 acc->awb.config = acc_user->awb.config;
2617 } else if (acc_old) {
2618
2619 acc->awb.config = acc_old->awb.config;
2620 } else {
2621
2622 acc->awb.config = imgu_css_awb_defaults;
2623 }
2624
2625 if (acc->awb.config.grid.width <= 0)
2626 return -EINVAL;
2627
2628 acc->awb.config.grid.height_per_slice =
2629 IMGU_ABI_AWB_MAX_CELLS_PER_SET / acc->awb.config.grid.width,
2630 imgu_css_grid_end_calc(&acc->awb.config.grid);
2631
2632 for (i = 0; i < stripes; i++)
2633 acc->awb.stripes[i] = acc->awb.config;
2634
2635 if (acc->awb.config.grid.x_start >=
2636 acc->stripe.down_scaled_stripes[1].offset + min_overlap) {
2637
2638 acc->awb.stripes[0].rgbs_thr_b &= ~IPU3_UAPI_AWB_RGBS_THR_B_EN;
2639
2640 acc->awb.stripes[1].grid.x_start =
2641 (acc->awb.stripes[1].grid.x_start -
2642 acc->stripe.down_scaled_stripes[1].offset) &
2643 IPU3_UAPI_GRID_START_MASK;
2644
2645 b_w_log2 = acc->awb.stripes[1].grid.block_width_log2;
2646 acc->awb.stripes[1].grid.x_end =
2647 imgu_css_grid_end(acc->awb.stripes[1].grid.x_start,
2648 acc->awb.stripes[1].grid.width,
2649 b_w_log2);
2650 } else if (acc->awb.config.grid.x_end <=
2651 acc->stripe.bds_out_stripes[0].width - min_overlap) {
2652
2653 acc->awb.stripes[1].rgbs_thr_b &= ~IPU3_UAPI_AWB_RGBS_THR_B_EN;
2654 } else {
2655
2656
2657 acc->awb.stripes[0].grid.width =
2658 (acc->stripe.bds_out_stripes[0].width -
2659 acc->awb.config.grid.x_start + 1) >>
2660 acc->awb.config.grid.block_width_log2;
2661 acc->awb.stripes[1].grid.width = acc->awb.config.grid.width -
2662 acc->awb.stripes[0].grid.width;
2663
2664 b_w_log2 = acc->awb.stripes[0].grid.block_width_log2;
2665 acc->awb.stripes[0].grid.x_end =
2666 imgu_css_grid_end(acc->awb.stripes[0].grid.x_start,
2667 acc->awb.stripes[0].grid.width,
2668 b_w_log2);
2669
2670 acc->awb.stripes[1].grid.x_start =
2671 (acc->awb.stripes[0].grid.x_end + 1 -
2672 acc->stripe.down_scaled_stripes[1].offset) &
2673 IPU3_UAPI_GRID_START_MASK;
2674
2675 b_w_log2 = acc->awb.stripes[1].grid.block_width_log2;
2676 acc->awb.stripes[1].grid.x_end =
2677 imgu_css_grid_end(acc->awb.stripes[1].grid.x_start,
2678 acc->awb.stripes[1].grid.width,
2679 b_w_log2);
2680
2681
2682
2683
2684
2685 for (i = 0; i < stripes; i++)
2686 acc->awb.stripes[i].grid.height_per_slice = 1;
2687 }
2688
2689 if (imgu_css_awb_ops_calc(css, pipe, &acc->awb))
2690 return -EINVAL;
2691
2692 return 0;
2693 }
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704 static void *imgu_css_cfg_copy(struct imgu_css *css,
2705 unsigned int pipe, bool use_user,
2706 void *user_setting, void *old_binary_params,
2707 void *new_binary_params,
2708 enum imgu_abi_memories m,
2709 struct imgu_fw_isp_parameter *par,
2710 size_t par_size)
2711 {
2712 const enum imgu_abi_param_class c = IMGU_ABI_PARAM_CLASS_PARAM;
2713 void *new_setting, *old_setting;
2714
2715 new_setting = imgu_css_fw_pipeline_params(css, pipe, c, m, par,
2716 par_size, new_binary_params);
2717 if (!new_setting)
2718 return ERR_PTR(-EPROTO);
2719
2720 if (use_user) {
2721
2722 memcpy(new_setting, user_setting, par_size);
2723 } else if (old_binary_params) {
2724
2725 old_setting = imgu_css_fw_pipeline_params(css, pipe, c, m, par,
2726 par_size,
2727 old_binary_params);
2728 if (!old_setting)
2729 return ERR_PTR(-EPROTO);
2730 memcpy(new_setting, old_setting, par_size);
2731 } else {
2732 return new_setting;
2733 }
2734
2735 return NULL;
2736 }
2737
2738
2739
2740
2741 int imgu_css_cfg_vmem0(struct imgu_css *css, unsigned int pipe,
2742 struct ipu3_uapi_flags *use,
2743 void *vmem0, void *vmem0_old,
2744 struct ipu3_uapi_params *user)
2745 {
2746 const struct imgu_fw_info *bi =
2747 &css->fwp->binary_header[css->pipes[pipe].bindex];
2748 struct imgu_fw_param_memory_offsets *pofs = (void *)css->fwp +
2749 bi->blob.memory_offsets.offsets[IMGU_ABI_PARAM_CLASS_PARAM];
2750 struct ipu3_uapi_isp_lin_vmem_params *lin_vmem = NULL;
2751 struct ipu3_uapi_isp_tnr3_vmem_params *tnr_vmem = NULL;
2752 struct ipu3_uapi_isp_xnr3_vmem_params *xnr_vmem = NULL;
2753 const enum imgu_abi_param_class c = IMGU_ABI_PARAM_CLASS_PARAM;
2754 const enum imgu_abi_memories m = IMGU_ABI_MEM_ISP_VMEM0;
2755 unsigned int i;
2756
2757
2758
2759 memset(vmem0, 0, bi->info.isp.sp.mem_initializers.params[c][m].size);
2760
2761
2762
2763 lin_vmem = imgu_css_cfg_copy(css, pipe, use && use->lin_vmem_params,
2764 &user->lin_vmem_params, vmem0_old, vmem0,
2765 m, &pofs->vmem.lin, sizeof(*lin_vmem));
2766 if (!IS_ERR_OR_NULL(lin_vmem)) {
2767
2768 for (i = 0; i < IPU3_UAPI_LIN_LUT_SIZE; i++) {
2769 lin_vmem->lin_lutlow_gr[i] = 32 * i;
2770 lin_vmem->lin_lutlow_r[i] = 32 * i;
2771 lin_vmem->lin_lutlow_b[i] = 32 * i;
2772 lin_vmem->lin_lutlow_gb[i] = 32 * i;
2773
2774 lin_vmem->lin_lutdif_gr[i] = 32;
2775 lin_vmem->lin_lutdif_r[i] = 32;
2776 lin_vmem->lin_lutdif_b[i] = 32;
2777 lin_vmem->lin_lutdif_gb[i] = 32;
2778 }
2779 }
2780
2781
2782 if (css->pipes[pipe].pipe_id == IPU3_CSS_PIPE_ID_VIDEO) {
2783 tnr_vmem = imgu_css_cfg_copy(css, pipe,
2784 use && use->tnr3_vmem_params,
2785 &user->tnr3_vmem_params,
2786 vmem0_old, vmem0, m,
2787 &pofs->vmem.tnr3,
2788 sizeof(*tnr_vmem));
2789 if (!IS_ERR_OR_NULL(tnr_vmem)) {
2790
2791 for (i = 0; i < IPU3_UAPI_ISP_TNR3_VMEM_LEN; i++)
2792 tnr_vmem->sigma[i] = 256;
2793 }
2794 }
2795 i = IPU3_UAPI_ISP_TNR3_VMEM_LEN;
2796
2797
2798
2799 xnr_vmem = imgu_css_cfg_copy(css, pipe, use && use->xnr3_vmem_params,
2800 &user->xnr3_vmem_params, vmem0_old, vmem0,
2801 m, &pofs->vmem.xnr3, sizeof(*xnr_vmem));
2802 if (!IS_ERR_OR_NULL(xnr_vmem)) {
2803 xnr_vmem->x[i] = imgu_css_xnr3_vmem_defaults.x
2804 [i % IMGU_XNR3_VMEM_LUT_LEN];
2805 xnr_vmem->a[i] = imgu_css_xnr3_vmem_defaults.a
2806 [i % IMGU_XNR3_VMEM_LUT_LEN];
2807 xnr_vmem->b[i] = imgu_css_xnr3_vmem_defaults.b
2808 [i % IMGU_XNR3_VMEM_LUT_LEN];
2809 xnr_vmem->c[i] = imgu_css_xnr3_vmem_defaults.c
2810 [i % IMGU_XNR3_VMEM_LUT_LEN];
2811 }
2812
2813 return IS_ERR(lin_vmem) || IS_ERR(tnr_vmem) || IS_ERR(xnr_vmem) ?
2814 -EPROTO : 0;
2815 }
2816
2817
2818
2819
2820 int imgu_css_cfg_dmem0(struct imgu_css *css, unsigned int pipe,
2821 struct ipu3_uapi_flags *use,
2822 void *dmem0, void *dmem0_old,
2823 struct ipu3_uapi_params *user)
2824 {
2825 struct imgu_css_pipe *css_pipe = &css->pipes[pipe];
2826 const struct imgu_fw_info *bi =
2827 &css->fwp->binary_header[css_pipe->bindex];
2828 struct imgu_fw_param_memory_offsets *pofs = (void *)css->fwp +
2829 bi->blob.memory_offsets.offsets[IMGU_ABI_PARAM_CLASS_PARAM];
2830
2831 struct ipu3_uapi_isp_tnr3_params *tnr_dmem = NULL;
2832 struct ipu3_uapi_isp_xnr3_params *xnr_dmem;
2833
2834 const enum imgu_abi_param_class c = IMGU_ABI_PARAM_CLASS_PARAM;
2835 const enum imgu_abi_memories m = IMGU_ABI_MEM_ISP_DMEM0;
2836
2837
2838
2839 memset(dmem0, 0, bi->info.isp.sp.mem_initializers.params[c][m].size);
2840
2841
2842 if (css_pipe->pipe_id == IPU3_CSS_PIPE_ID_VIDEO) {
2843 tnr_dmem = imgu_css_cfg_copy(css, pipe,
2844 use && use->tnr3_dmem_params,
2845 &user->tnr3_dmem_params,
2846 dmem0_old, dmem0, m,
2847 &pofs->dmem.tnr3,
2848 sizeof(*tnr_dmem));
2849 if (!IS_ERR_OR_NULL(tnr_dmem)) {
2850
2851 tnr_dmem->knee_y1 = 768;
2852 tnr_dmem->knee_y2 = 1280;
2853 }
2854 }
2855
2856
2857
2858 xnr_dmem = imgu_css_cfg_copy(css, pipe, use && use->xnr3_dmem_params,
2859 &user->xnr3_dmem_params, dmem0_old, dmem0,
2860 m, &pofs->dmem.xnr3, sizeof(*xnr_dmem));
2861 if (!IS_ERR_OR_NULL(xnr_dmem)) {
2862
2863 xnr_dmem->alpha.y0 = 2047;
2864 xnr_dmem->alpha.u0 = 2047;
2865 xnr_dmem->alpha.v0 = 2047;
2866 }
2867
2868 return IS_ERR(tnr_dmem) || IS_ERR(xnr_dmem) ? -EPROTO : 0;
2869 }
2870
2871
2872 void imgu_css_cfg_gdc_table(struct imgu_abi_gdc_warp_param *gdc,
2873 int frame_in_x, int frame_in_y,
2874 int frame_out_x, int frame_out_y,
2875 int env_w, int env_h)
2876 {
2877 static const unsigned int FRAC_BITS = IMGU_ABI_GDC_FRAC_BITS;
2878 static const unsigned int XMEM_ALIGN = 1 << 4;
2879 const unsigned int XMEM_ALIGN_MASK = ~(XMEM_ALIGN - 1);
2880 static const unsigned int BCI_ENV = 4;
2881 static const unsigned int BYP = 2;
2882 const unsigned int OFFSET_X = 2 * IMGU_DVS_BLOCK_W + env_w + 1;
2883 const unsigned int OFFSET_Y = IMGU_DVS_BLOCK_H + env_h + 1;
2884
2885 struct imgu_abi_gdc_warp_param gdc_luma, gdc_chroma;
2886
2887 unsigned int blocks_x = ALIGN(DIV_ROUND_UP(frame_out_x,
2888 IMGU_DVS_BLOCK_W), 2);
2889 unsigned int blocks_y = DIV_ROUND_UP(frame_out_y, IMGU_DVS_BLOCK_H);
2890 unsigned int y0, x0, x1, x, y;
2891
2892
2893 gdc_luma.origin_x = 0;
2894 gdc_luma.origin_y = 0;
2895 gdc_luma.p0_x = (OFFSET_X - (OFFSET_X & XMEM_ALIGN_MASK)) << FRAC_BITS;
2896 gdc_luma.p0_y = 0;
2897 gdc_luma.p1_x = gdc_luma.p0_x + (IMGU_DVS_BLOCK_W << FRAC_BITS);
2898 gdc_luma.p1_y = gdc_luma.p0_y;
2899 gdc_luma.p2_x = gdc_luma.p0_x;
2900 gdc_luma.p2_y = gdc_luma.p0_y + (IMGU_DVS_BLOCK_H << FRAC_BITS);
2901 gdc_luma.p3_x = gdc_luma.p1_x;
2902 gdc_luma.p3_y = gdc_luma.p2_y;
2903
2904 gdc_luma.in_block_width = IMGU_DVS_BLOCK_W + BCI_ENV +
2905 OFFSET_X - (OFFSET_X & XMEM_ALIGN_MASK);
2906 gdc_luma.in_block_width_a = DIV_ROUND_UP(gdc_luma.in_block_width,
2907 IPU3_UAPI_ISP_VEC_ELEMS);
2908 gdc_luma.in_block_width_b = DIV_ROUND_UP(gdc_luma.in_block_width,
2909 IMGU_ABI_ISP_DDR_WORD_BYTES /
2910 BYP);
2911 gdc_luma.in_block_height = IMGU_DVS_BLOCK_H + BCI_ENV;
2912 gdc_luma.padding = 0;
2913
2914
2915 gdc_chroma.origin_x = 0;
2916 gdc_chroma.origin_y = 0;
2917 gdc_chroma.p0_x = (OFFSET_X / 2 - (OFFSET_X / 2 & XMEM_ALIGN_MASK)) <<
2918 FRAC_BITS;
2919 gdc_chroma.p0_y = 0;
2920 gdc_chroma.p1_x = gdc_chroma.p0_x + (IMGU_DVS_BLOCK_W << FRAC_BITS);
2921 gdc_chroma.p1_y = gdc_chroma.p0_y;
2922 gdc_chroma.p2_x = gdc_chroma.p0_x;
2923 gdc_chroma.p2_y = gdc_chroma.p0_y + (IMGU_DVS_BLOCK_H / 2 << FRAC_BITS);
2924 gdc_chroma.p3_x = gdc_chroma.p1_x;
2925 gdc_chroma.p3_y = gdc_chroma.p2_y;
2926
2927 gdc_chroma.in_block_width = IMGU_DVS_BLOCK_W + BCI_ENV;
2928 gdc_chroma.in_block_width_a = DIV_ROUND_UP(gdc_chroma.in_block_width,
2929 IPU3_UAPI_ISP_VEC_ELEMS);
2930 gdc_chroma.in_block_width_b = DIV_ROUND_UP(gdc_chroma.in_block_width,
2931 IMGU_ABI_ISP_DDR_WORD_BYTES /
2932 BYP);
2933 gdc_chroma.in_block_height = IMGU_DVS_BLOCK_H / 2 + BCI_ENV;
2934 gdc_chroma.padding = 0;
2935
2936
2937 for (y0 = 0; y0 < blocks_y; y0++) {
2938 for (x0 = 0; x0 < blocks_x / 2; x0++) {
2939 for (x1 = 0; x1 < 2; x1++) {
2940
2941 x = (x0 * 2 + x1) * IMGU_DVS_BLOCK_W + OFFSET_X;
2942 x &= XMEM_ALIGN_MASK;
2943 y = y0 * IMGU_DVS_BLOCK_H + OFFSET_Y;
2944 *gdc = gdc_luma;
2945 gdc->in_addr_offset =
2946 (y * frame_in_x + x) * BYP;
2947 gdc++;
2948 }
2949
2950
2951 x = x0 * IMGU_DVS_BLOCK_W + OFFSET_X / 2;
2952 x &= XMEM_ALIGN_MASK;
2953 y = y0 * (IMGU_DVS_BLOCK_H / 2) + OFFSET_Y / 2;
2954 *gdc = gdc_chroma;
2955 gdc->in_addr_offset = (y * frame_in_x + x) * BYP;
2956 gdc++;
2957 }
2958 }
2959 }