cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ipu3-css-params.c (95403B)


      1// SPDX-License-Identifier: GPL-2.0
      2// Copyright (C) 2018 Intel Corporation
      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;	/* Same for luma/chroma */
     19	int exp_shift;
     20
     21	unsigned int phase_init;	/* luma/chroma dependent */
     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/* Set up the CSS scaler look up table */
     43static void
     44imgu_css_scaler_setup_lut(unsigned int taps, unsigned int input_width,
     45			  unsigned int output_width, int phase_step_correction,
     46			  const int *coeffs, unsigned int coeffs_size,
     47			  s8 coeff_lut[], struct imgu_css_scaler_info *info)
     48{
     49	int tap, phase, phase_sum_left, phase_sum_right;
     50	int exponent = imgu_css_scaler_get_exp(output_width, input_width);
     51	int mantissa = (1 << exponent) * output_width;
     52	unsigned int phase_step, phase_taps;
     53
     54	if (input_width == output_width) {
     55		for (phase = 0; phase < IMGU_SCALER_PHASES; phase++) {
     56			phase_taps = phase * IMGU_SCALER_FILTER_TAPS;
     57			for (tap = 0; tap < taps; tap++)
     58				coeff_lut[phase_taps + tap] = 0;
     59		}
     60
     61		info->phase_step = IMGU_SCALER_PHASES *
     62			(1 << IMGU_SCALER_PHASE_COUNTER_PREC_REF);
     63		info->exp_shift = 0;
     64		info->pad_left = 0;
     65		info->pad_right = 0;
     66		info->phase_init = 0;
     67		info->crop_left = 0;
     68		info->crop_top = 0;
     69		return;
     70	}
     71
     72	for (phase = 0; phase < IMGU_SCALER_PHASES; phase++) {
     73		phase_taps = phase * IMGU_SCALER_FILTER_TAPS;
     74		for (tap = 0; tap < taps; tap++) {
     75			/* flip table to for convolution reverse indexing */
     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			/* Add +"0.5" */
     82			coeff += 1 << (IMGU_SCALER_COEFF_BITS - 1);
     83			coeff >>= IMGU_SCALER_COEFF_BITS;
     84			coeff_lut[phase_taps + tap] = coeff;
     85		}
     86	}
     87
     88	phase_step = IMGU_SCALER_PHASES *
     89			(1 << IMGU_SCALER_PHASE_COUNTER_PREC_REF) *
     90			output_width / input_width;
     91	phase_step += phase_step_correction;
     92	phase_sum_left = (taps / 2 * IMGU_SCALER_PHASES *
     93			(1 << IMGU_SCALER_PHASE_COUNTER_PREC_REF)) -
     94			(1 << (IMGU_SCALER_PHASE_COUNTER_PREC_REF - 1));
     95	phase_sum_right = (taps / 2 * IMGU_SCALER_PHASES *
     96			(1 << IMGU_SCALER_PHASE_COUNTER_PREC_REF)) +
     97			(1 << (IMGU_SCALER_PHASE_COUNTER_PREC_REF - 1));
     98
     99	info->exp_shift = IMGU_SCALER_MAX_EXPONENT_SHIFT - exponent;
    100	info->pad_left = (phase_sum_left % phase_step == 0) ?
    101		phase_sum_left / phase_step - 1 : phase_sum_left / phase_step;
    102	info->pad_right = (phase_sum_right % phase_step == 0) ?
    103		phase_sum_right / phase_step - 1 : phase_sum_right / phase_step;
    104	info->phase_init = phase_sum_left - phase_step * info->pad_left;
    105	info->phase_step = phase_step;
    106	info->crop_left = taps - 1;
    107	info->crop_top = taps - 1;
    108}
    109
    110/*
    111 * Calculates the exact output image width/height, based on phase_step setting
    112 * (must be perfectly aligned with hardware).
    113 */
    114static unsigned int
    115imgu_css_scaler_calc_scaled_output(unsigned int input,
    116				   struct imgu_css_scaler_info *info)
    117{
    118	unsigned int arg1 = input * info->phase_step +
    119			(1 - IMGU_SCALER_TAPS_Y / 2) * IMGU_SCALER_FIR_PHASES -
    120			IMGU_SCALER_FIR_PHASES / (2 * IMGU_SCALER_PHASES);
    121	unsigned int arg2 = ((IMGU_SCALER_TAPS_Y / 2) * IMGU_SCALER_FIR_PHASES +
    122			IMGU_SCALER_FIR_PHASES / (2 * IMGU_SCALER_PHASES)) *
    123			IMGU_SCALER_FIR_PHASES + info->phase_step / 2;
    124
    125	return ((arg1 + (arg2 - IMGU_SCALER_FIR_PHASES * info->phase_step) /
    126		IMGU_SCALER_FIR_PHASES) / (2 * IMGU_SCALER_FIR_PHASES)) * 2;
    127}
    128
    129/*
    130 * Calculate the output width and height, given the luma
    131 * and chroma details of a scaler
    132 */
    133static void
    134imgu_css_scaler_calc(u32 input_width, u32 input_height, u32 target_width,
    135		     u32 target_height, struct imgu_abi_osys_config *cfg,
    136		     struct imgu_css_scaler_info *info_luma,
    137		     struct imgu_css_scaler_info *info_chroma,
    138		     unsigned int *output_width, unsigned int *output_height,
    139		     unsigned int *procmode)
    140{
    141	u32 out_width = target_width;
    142	u32 out_height = target_height;
    143	const unsigned int height_alignment = 2;
    144	int phase_step_correction = -1;
    145
    146	/*
    147	 * Calculate scaled output width. If the horizontal and vertical scaling
    148	 * factor is different, then choose the biggest and crop off excess
    149	 * lines or columns after formatting.
    150	 */
    151	if (target_height * input_width > target_width * input_height)
    152		target_width = DIV_ROUND_UP(target_height * input_width,
    153					    input_height);
    154
    155	if (input_width == target_width)
    156		*procmode = IMGU_ABI_OSYS_PROCMODE_BYPASS;
    157	else
    158		*procmode = IMGU_ABI_OSYS_PROCMODE_DOWNSCALE;
    159
    160	memset(&cfg->scaler_coeffs_chroma, 0,
    161	       sizeof(cfg->scaler_coeffs_chroma));
    162	memset(&cfg->scaler_coeffs_luma, 0, sizeof(cfg->scaler_coeffs_luma));
    163	do {
    164		phase_step_correction++;
    165
    166		imgu_css_scaler_setup_lut(IMGU_SCALER_TAPS_Y,
    167					  input_width, target_width,
    168					  phase_step_correction,
    169					  imgu_css_downscale_4taps,
    170					  IMGU_SCALER_DOWNSCALE_4TAPS_LEN,
    171					  cfg->scaler_coeffs_luma, info_luma);
    172
    173		imgu_css_scaler_setup_lut(IMGU_SCALER_TAPS_UV,
    174					  input_width, target_width,
    175					  phase_step_correction,
    176					  imgu_css_downscale_2taps,
    177					  IMGU_SCALER_DOWNSCALE_2TAPS_LEN,
    178					  cfg->scaler_coeffs_chroma,
    179					  info_chroma);
    180
    181		out_width = imgu_css_scaler_calc_scaled_output(input_width,
    182							       info_luma);
    183		out_height = imgu_css_scaler_calc_scaled_output(input_height,
    184								info_luma);
    185	} while ((out_width < target_width || out_height < target_height ||
    186		 !IS_ALIGNED(out_height, height_alignment)) &&
    187		 phase_step_correction <= 5);
    188
    189	*output_width = out_width;
    190	*output_height = out_height;
    191}
    192
    193/********************** Osys routines for scaler****************************/
    194
    195static void imgu_css_osys_set_format(enum imgu_abi_frame_format host_format,
    196				     unsigned int *osys_format,
    197				     unsigned int *osys_tiling)
    198{
    199	*osys_format = IMGU_ABI_OSYS_FORMAT_YUV420;
    200	*osys_tiling = IMGU_ABI_OSYS_TILING_NONE;
    201
    202	switch (host_format) {
    203	case IMGU_ABI_FRAME_FORMAT_YUV420:
    204		*osys_format = IMGU_ABI_OSYS_FORMAT_YUV420;
    205		break;
    206	case IMGU_ABI_FRAME_FORMAT_YV12:
    207		*osys_format = IMGU_ABI_OSYS_FORMAT_YV12;
    208		break;
    209	case IMGU_ABI_FRAME_FORMAT_NV12:
    210		*osys_format = IMGU_ABI_OSYS_FORMAT_NV12;
    211		break;
    212	case IMGU_ABI_FRAME_FORMAT_NV16:
    213		*osys_format = IMGU_ABI_OSYS_FORMAT_NV16;
    214		break;
    215	case IMGU_ABI_FRAME_FORMAT_NV21:
    216		*osys_format = IMGU_ABI_OSYS_FORMAT_NV21;
    217		break;
    218	case IMGU_ABI_FRAME_FORMAT_NV12_TILEY:
    219		*osys_format = IMGU_ABI_OSYS_FORMAT_NV12;
    220		*osys_tiling = IMGU_ABI_OSYS_TILING_Y;
    221		break;
    222	default:
    223		/* For now, assume use default values */
    224		break;
    225	}
    226}
    227
    228/*
    229 * Function calculates input frame stripe offset, based
    230 * on output frame stripe offset and filter parameters.
    231 */
    232static int imgu_css_osys_calc_stripe_offset(int stripe_offset_out,
    233					    int fir_phases, int phase_init,
    234					    int phase_step, int pad_left)
    235{
    236	int stripe_offset_inp = stripe_offset_out * fir_phases -
    237				pad_left * phase_step;
    238
    239	return DIV_ROUND_UP(stripe_offset_inp - phase_init, phase_step);
    240}
    241
    242/*
    243 * Calculate input frame phase, given the output frame
    244 * stripe offset and filter parameters
    245 */
    246static int imgu_css_osys_calc_stripe_phase_init(int stripe_offset_out,
    247						int fir_phases, int phase_init,
    248						int phase_step, int pad_left)
    249{
    250	int stripe_offset_inp =
    251		imgu_css_osys_calc_stripe_offset(stripe_offset_out,
    252						 fir_phases, phase_init,
    253						 phase_step, pad_left);
    254
    255	return phase_init + ((pad_left + stripe_offset_inp) * phase_step) -
    256		stripe_offset_out * fir_phases;
    257}
    258
    259/*
    260 * This function calculates input frame stripe width,
    261 * based on output frame stripe offset and filter parameters
    262 */
    263static int imgu_css_osys_calc_inp_stripe_width(int stripe_width_out,
    264					       int fir_phases, int phase_init,
    265					       int phase_step, int fir_taps,
    266					       int pad_left, int pad_right)
    267{
    268	int stripe_width_inp = (stripe_width_out + fir_taps - 1) * fir_phases;
    269
    270	stripe_width_inp = DIV_ROUND_UP(stripe_width_inp - phase_init,
    271					phase_step);
    272
    273	return stripe_width_inp - pad_left - pad_right;
    274}
    275
    276/*
    277 * This function calculates output frame stripe width, basedi
    278 * on output frame stripe offset and filter parameters
    279 */
    280static int imgu_css_osys_out_stripe_width(int stripe_width_inp, int fir_phases,
    281					  int phase_init, int phase_step,
    282					  int fir_taps, int pad_left,
    283					  int pad_right, int column_offset)
    284{
    285	int stripe_width_out = (pad_left + stripe_width_inp +
    286				pad_right - column_offset) * phase_step;
    287
    288	stripe_width_out = (stripe_width_out + phase_init) / fir_phases;
    289
    290	return stripe_width_out - (fir_taps - 1);
    291}
    292
    293struct imgu_css_reso {
    294	unsigned int input_width;
    295	unsigned int input_height;
    296	enum imgu_abi_frame_format input_format;
    297	unsigned int pin_width[IMGU_ABI_OSYS_PINS];
    298	unsigned int pin_height[IMGU_ABI_OSYS_PINS];
    299	unsigned int pin_stride[IMGU_ABI_OSYS_PINS];
    300	enum imgu_abi_frame_format pin_format[IMGU_ABI_OSYS_PINS];
    301	int chunk_width;
    302	int chunk_height;
    303	int block_height;
    304	int block_width;
    305};
    306
    307struct imgu_css_frame_params {
    308	/* Output pins */
    309	unsigned int enable;
    310	unsigned int format;
    311	unsigned int flip;
    312	unsigned int mirror;
    313	unsigned int tiling;
    314	unsigned int reduce_range;
    315	unsigned int width;
    316	unsigned int height;
    317	unsigned int stride;
    318	unsigned int scaled;
    319	unsigned int crop_left;
    320	unsigned int crop_top;
    321};
    322
    323struct imgu_css_stripe_params {
    324	unsigned int processing_mode;
    325	unsigned int phase_step;
    326	unsigned int exp_shift;
    327	unsigned int phase_init_left_y;
    328	unsigned int phase_init_left_uv;
    329	unsigned int phase_init_top_y;
    330	unsigned int phase_init_top_uv;
    331	unsigned int pad_left_y;
    332	unsigned int pad_left_uv;
    333	unsigned int pad_right_y;
    334	unsigned int pad_right_uv;
    335	unsigned int pad_top_y;
    336	unsigned int pad_top_uv;
    337	unsigned int pad_bottom_y;
    338	unsigned int pad_bottom_uv;
    339	unsigned int crop_left_y;
    340	unsigned int crop_top_y;
    341	unsigned int crop_left_uv;
    342	unsigned int crop_top_uv;
    343	unsigned int start_column_y;
    344	unsigned int start_column_uv;
    345	unsigned int chunk_width;
    346	unsigned int chunk_height;
    347	unsigned int block_width;
    348	unsigned int block_height;
    349	unsigned int input_width;
    350	unsigned int input_height;
    351	int output_width[IMGU_ABI_OSYS_PINS];
    352	int output_height[IMGU_ABI_OSYS_PINS];
    353	int output_offset[IMGU_ABI_OSYS_PINS];
    354};
    355
    356/*
    357 * frame_params - size IMGU_ABI_OSYS_PINS
    358 * stripe_params - size IPU3_UAPI_MAX_STRIPES
    359 */
    360static int imgu_css_osys_calc_frame_and_stripe_params(
    361		struct imgu_css *css, unsigned int stripes,
    362		struct imgu_abi_osys_config *osys,
    363		struct imgu_css_scaler_info *scaler_luma,
    364		struct imgu_css_scaler_info *scaler_chroma,
    365		struct imgu_css_frame_params frame_params[],
    366		struct imgu_css_stripe_params stripe_params[],
    367		unsigned int pipe)
    368{
    369	struct imgu_css_reso reso;
    370	unsigned int output_width, pin, s;
    371	u32 input_width, input_height, target_width, target_height;
    372	unsigned int procmode = 0;
    373	struct imgu_css_pipe *css_pipe = &css->pipes[pipe];
    374
    375	input_width = css_pipe->rect[IPU3_CSS_RECT_GDC].width;
    376	input_height = css_pipe->rect[IPU3_CSS_RECT_GDC].height;
    377	target_width = css_pipe->queue[IPU3_CSS_QUEUE_VF].fmt.mpix.width;
    378	target_height = css_pipe->queue[IPU3_CSS_QUEUE_VF].fmt.mpix.height;
    379
    380	/* Frame parameters */
    381
    382	/* Input width for Output System is output width of DVS (with GDC) */
    383	reso.input_width = css_pipe->rect[IPU3_CSS_RECT_GDC].width;
    384
    385	/* Input height for Output System is output height of DVS (with GDC) */
    386	reso.input_height = css_pipe->rect[IPU3_CSS_RECT_GDC].height;
    387
    388	reso.input_format =
    389		css_pipe->queue[IPU3_CSS_QUEUE_OUT].css_fmt->frame_format;
    390
    391	reso.pin_width[IMGU_ABI_OSYS_PIN_OUT] =
    392		css_pipe->queue[IPU3_CSS_QUEUE_OUT].fmt.mpix.width;
    393	reso.pin_height[IMGU_ABI_OSYS_PIN_OUT] =
    394		css_pipe->queue[IPU3_CSS_QUEUE_OUT].fmt.mpix.height;
    395	reso.pin_stride[IMGU_ABI_OSYS_PIN_OUT] =
    396		css_pipe->queue[IPU3_CSS_QUEUE_OUT].width_pad;
    397	reso.pin_format[IMGU_ABI_OSYS_PIN_OUT] =
    398		css_pipe->queue[IPU3_CSS_QUEUE_OUT].css_fmt->frame_format;
    399
    400	reso.pin_width[IMGU_ABI_OSYS_PIN_VF] =
    401		css_pipe->queue[IPU3_CSS_QUEUE_VF].fmt.mpix.width;
    402	reso.pin_height[IMGU_ABI_OSYS_PIN_VF] =
    403		css_pipe->queue[IPU3_CSS_QUEUE_VF].fmt.mpix.height;
    404	reso.pin_stride[IMGU_ABI_OSYS_PIN_VF] =
    405		css_pipe->queue[IPU3_CSS_QUEUE_VF].width_pad;
    406	reso.pin_format[IMGU_ABI_OSYS_PIN_VF] =
    407		css_pipe->queue[IPU3_CSS_QUEUE_VF].css_fmt->frame_format;
    408
    409	/* Configure the frame parameters for all output pins */
    410
    411	frame_params[IMGU_ABI_OSYS_PIN_OUT].width =
    412		css_pipe->queue[IPU3_CSS_QUEUE_OUT].fmt.mpix.width;
    413	frame_params[IMGU_ABI_OSYS_PIN_OUT].height =
    414		css_pipe->queue[IPU3_CSS_QUEUE_OUT].fmt.mpix.height;
    415	frame_params[IMGU_ABI_OSYS_PIN_VF].width =
    416		css_pipe->queue[IPU3_CSS_QUEUE_VF].fmt.mpix.width;
    417	frame_params[IMGU_ABI_OSYS_PIN_VF].height =
    418		css_pipe->queue[IPU3_CSS_QUEUE_VF].fmt.mpix.height;
    419	frame_params[IMGU_ABI_OSYS_PIN_VF].crop_top = 0;
    420	frame_params[IMGU_ABI_OSYS_PIN_VF].crop_left = 0;
    421
    422	for (pin = 0; pin < IMGU_ABI_OSYS_PINS; pin++) {
    423		int enable = 0;
    424		int scaled = 0;
    425		unsigned int format = 0;
    426		unsigned int tiling = 0;
    427
    428		frame_params[pin].flip = 0;
    429		frame_params[pin].mirror = 0;
    430		frame_params[pin].reduce_range = 0;
    431		if (reso.pin_width[pin] != 0 && reso.pin_height[pin] != 0) {
    432			enable = 1;
    433			if (pin == IMGU_ABI_OSYS_PIN_OUT) {
    434				if (reso.input_width < reso.pin_width[pin] ||
    435				    reso.input_height < reso.pin_height[pin])
    436					return -EINVAL;
    437				/*
    438				 * When input and output resolution is
    439				 * different instead of scaling, cropping
    440				 * should happen. Determine the crop factor
    441				 * to do the symmetric cropping
    442				 */
    443				frame_params[pin].crop_left = roundclosest_down(
    444						(reso.input_width -
    445						 reso.pin_width[pin]) / 2,
    446						 IMGU_OSYS_DMA_CROP_W_LIMIT);
    447				frame_params[pin].crop_top = roundclosest_down(
    448						(reso.input_height -
    449						 reso.pin_height[pin]) / 2,
    450						 IMGU_OSYS_DMA_CROP_H_LIMIT);
    451			} else {
    452				if (reso.pin_width[pin] != reso.input_width ||
    453				    reso.pin_height[pin] != reso.input_height) {
    454					/*
    455					 * If resolution is different at input
    456					 * and output of OSYS, scaling is
    457					 * considered except when pin is MAIN.
    458					 * Later it will be decide whether
    459					 * scaler factor is 1 or other
    460					 * and cropping has to be done or not.
    461					 */
    462					scaled = 1;
    463				}
    464			}
    465			imgu_css_osys_set_format(reso.pin_format[pin], &format,
    466						 &tiling);
    467		} else {
    468			enable = 0;
    469		}
    470		frame_params[pin].enable = enable;
    471		frame_params[pin].format = format;
    472		frame_params[pin].tiling = tiling;
    473		frame_params[pin].stride = reso.pin_stride[pin];
    474		frame_params[pin].scaled = scaled;
    475	}
    476
    477	imgu_css_scaler_calc(input_width, input_height, target_width,
    478			     target_height, osys, scaler_luma, scaler_chroma,
    479			     &reso.pin_width[IMGU_ABI_OSYS_PIN_VF],
    480			     &reso.pin_height[IMGU_ABI_OSYS_PIN_VF], &procmode);
    481	dev_dbg(css->dev, "osys scaler procmode is %u", procmode);
    482	output_width = reso.pin_width[IMGU_ABI_OSYS_PIN_VF];
    483
    484	if (output_width < reso.input_width / 2) {
    485		/* Scaling factor <= 0.5 */
    486		reso.chunk_width = IMGU_OSYS_BLOCK_WIDTH;
    487		reso.block_width = IMGU_OSYS_BLOCK_WIDTH;
    488	} else { /* 0.5 <= Scaling factor <= 1.0 */
    489		reso.chunk_width = IMGU_OSYS_BLOCK_WIDTH / 2;
    490		reso.block_width = IMGU_OSYS_BLOCK_WIDTH;
    491	}
    492
    493	if (output_width <= reso.input_width * 7 / 8) {
    494		/* Scaling factor <= 0.875 */
    495		reso.chunk_height = IMGU_OSYS_BLOCK_HEIGHT;
    496		reso.block_height = IMGU_OSYS_BLOCK_HEIGHT;
    497	} else { /* 1.0 <= Scaling factor <= 1.75 */
    498		reso.chunk_height = IMGU_OSYS_BLOCK_HEIGHT / 2;
    499		reso.block_height = IMGU_OSYS_BLOCK_HEIGHT;
    500	}
    501
    502	/*
    503	 * Calculate scaler configuration parameters based on input and output
    504	 * resolution.
    505	 */
    506
    507	if (frame_params[IMGU_ABI_OSYS_PIN_VF].enable) {
    508		/*
    509		 * When aspect ratio is different between target resolution and
    510		 * required resolution, determine the crop factor to do
    511		 * symmetric cropping
    512		 */
    513		u32 w = reso.pin_width[IMGU_ABI_OSYS_PIN_VF] -
    514			frame_params[IMGU_ABI_OSYS_PIN_VF].width;
    515		u32 h = reso.pin_height[IMGU_ABI_OSYS_PIN_VF] -
    516			frame_params[IMGU_ABI_OSYS_PIN_VF].height;
    517
    518		frame_params[IMGU_ABI_OSYS_PIN_VF].crop_left =
    519			roundclosest_down(w / 2, IMGU_OSYS_DMA_CROP_W_LIMIT);
    520		frame_params[IMGU_ABI_OSYS_PIN_VF].crop_top =
    521			roundclosest_down(h / 2, IMGU_OSYS_DMA_CROP_H_LIMIT);
    522
    523		if (reso.input_height % 4 || reso.input_width % 8) {
    524			dev_err(css->dev, "OSYS input width is not multiple of 8 or\n");
    525			dev_err(css->dev, "height is not multiple of 4\n");
    526			return -EINVAL;
    527		}
    528	}
    529
    530	/* Stripe parameters */
    531
    532	if (frame_params[IMGU_ABI_OSYS_PIN_VF].enable) {
    533		output_width = reso.pin_width[IMGU_ABI_OSYS_PIN_VF];
    534	} else {
    535		/*
    536		 * in case scaler output is not enabled
    537		 * take output width as input width since
    538		 * there is no scaling at main pin.
    539		 * Due to the fact that main pin can be different
    540		 * from input resolution to osys in the case of cropping,
    541		 * main pin resolution is not taken.
    542		 */
    543		output_width = reso.input_width;
    544	}
    545
    546	for (s = 0; s < stripes; s++) {
    547		int stripe_offset_inp_y = 0;
    548		int stripe_offset_inp_uv = 0;
    549		int stripe_offset_out_y = 0;
    550		int stripe_offset_out_uv = 0;
    551		int stripe_phase_init_y = scaler_luma->phase_init;
    552		int stripe_phase_init_uv = scaler_chroma->phase_init;
    553		int stripe_offset_blk_y = 0;
    554		int stripe_offset_blk_uv = 0;
    555		int stripe_offset_col_y = 0;
    556		int stripe_offset_col_uv = 0;
    557		int stripe_pad_left_y = scaler_luma->pad_left;
    558		int stripe_pad_left_uv = scaler_chroma->pad_left;
    559		int stripe_pad_right_y = scaler_luma->pad_right;
    560		int stripe_pad_right_uv = scaler_chroma->pad_right;
    561		int stripe_crop_left_y = scaler_luma->crop_left;
    562		int stripe_crop_left_uv = scaler_chroma->crop_left;
    563		int stripe_input_width_y = reso.input_width;
    564		int stripe_input_width_uv = 0;
    565		int stripe_output_width_y = output_width;
    566		int stripe_output_width_uv = 0;
    567		int chunk_floor_y = 0;
    568		int chunk_floor_uv = 0;
    569		int chunk_ceil_uv = 0;
    570
    571		if (stripes > 1) {
    572			if (s > 0) {
    573				/* Calculate stripe offsets */
    574				stripe_offset_out_y =
    575					output_width * s / stripes;
    576				stripe_offset_out_y =
    577					rounddown(stripe_offset_out_y,
    578						  IPU3_UAPI_ISP_VEC_ELEMS);
    579				stripe_offset_out_uv = stripe_offset_out_y /
    580						IMGU_LUMA_TO_CHROMA_RATIO;
    581				stripe_offset_inp_y =
    582					imgu_css_osys_calc_stripe_offset(
    583						stripe_offset_out_y,
    584						IMGU_OSYS_FIR_PHASES,
    585						scaler_luma->phase_init,
    586						scaler_luma->phase_step,
    587						scaler_luma->pad_left);
    588				stripe_offset_inp_uv =
    589					imgu_css_osys_calc_stripe_offset(
    590						stripe_offset_out_uv,
    591						IMGU_OSYS_FIR_PHASES,
    592						scaler_chroma->phase_init,
    593						scaler_chroma->phase_step,
    594						scaler_chroma->pad_left);
    595
    596				/* Calculate stripe phase init */
    597				stripe_phase_init_y =
    598					imgu_css_osys_calc_stripe_phase_init(
    599						stripe_offset_out_y,
    600						IMGU_OSYS_FIR_PHASES,
    601						scaler_luma->phase_init,
    602						scaler_luma->phase_step,
    603						scaler_luma->pad_left);
    604				stripe_phase_init_uv =
    605					imgu_css_osys_calc_stripe_phase_init(
    606						stripe_offset_out_uv,
    607						IMGU_OSYS_FIR_PHASES,
    608						scaler_chroma->phase_init,
    609						scaler_chroma->phase_step,
    610						scaler_chroma->pad_left);
    611
    612				/*
    613				 * Chunk boundary corner case - luma and chroma
    614				 * start from different input chunks.
    615				 */
    616				chunk_floor_y = rounddown(stripe_offset_inp_y,
    617							  reso.chunk_width);
    618				chunk_floor_uv =
    619					rounddown(stripe_offset_inp_uv,
    620						  reso.chunk_width /
    621						  IMGU_LUMA_TO_CHROMA_RATIO);
    622
    623				if (chunk_floor_y != chunk_floor_uv *
    624				    IMGU_LUMA_TO_CHROMA_RATIO) {
    625					/*
    626					 * Match starting luma/chroma chunks.
    627					 * Decrease offset for UV and add output
    628					 * cropping.
    629					 */
    630					stripe_offset_inp_uv -= 1;
    631					stripe_crop_left_uv += 1;
    632					stripe_phase_init_uv -=
    633						scaler_luma->phase_step;
    634					if (stripe_phase_init_uv < 0)
    635						stripe_phase_init_uv =
    636							stripe_phase_init_uv +
    637							IMGU_OSYS_FIR_PHASES;
    638				}
    639				/*
    640				 * FW workaround for a HW bug: if the first
    641				 * chroma pixel is generated exactly at the end
    642				 * of chunck scaler HW may not output the pixel
    643				 * for downscale factors smaller than 1.5
    644				 * (timing issue).
    645				 */
    646				chunk_ceil_uv =
    647					roundup(stripe_offset_inp_uv,
    648						reso.chunk_width /
    649						IMGU_LUMA_TO_CHROMA_RATIO);
    650
    651				if (stripe_offset_inp_uv ==
    652				    chunk_ceil_uv - IMGU_OSYS_TAPS_UV) {
    653					/*
    654					 * Decrease input offset and add
    655					 * output cropping
    656					 */
    657					stripe_offset_inp_uv -= 1;
    658					stripe_phase_init_uv -=
    659						scaler_luma->phase_step;
    660					if (stripe_phase_init_uv < 0) {
    661						stripe_phase_init_uv +=
    662							IMGU_OSYS_FIR_PHASES;
    663						stripe_crop_left_uv += 1;
    664					}
    665				}
    666
    667				/*
    668				 * Calculate block and column offsets for the
    669				 * input stripe
    670				 */
    671				stripe_offset_blk_y =
    672					rounddown(stripe_offset_inp_y,
    673						  IMGU_INPUT_BLOCK_WIDTH);
    674				stripe_offset_blk_uv =
    675					rounddown(stripe_offset_inp_uv,
    676						  IMGU_INPUT_BLOCK_WIDTH /
    677						  IMGU_LUMA_TO_CHROMA_RATIO);
    678				stripe_offset_col_y = stripe_offset_inp_y -
    679							stripe_offset_blk_y;
    680				stripe_offset_col_uv = stripe_offset_inp_uv -
    681							stripe_offset_blk_uv;
    682
    683				/* Left padding is only for the first stripe */
    684				stripe_pad_left_y = 0;
    685				stripe_pad_left_uv = 0;
    686			}
    687
    688			/* Right padding is only for the last stripe */
    689			if (s < stripes - 1) {
    690				int next_offset;
    691
    692				stripe_pad_right_y = 0;
    693				stripe_pad_right_uv = 0;
    694
    695				next_offset = output_width * (s + 1) / stripes;
    696				next_offset = rounddown(next_offset, 64);
    697				stripe_output_width_y = next_offset -
    698							stripe_offset_out_y;
    699			} else {
    700				stripe_output_width_y = output_width -
    701							stripe_offset_out_y;
    702			}
    703
    704			/* Calculate target output stripe width */
    705			stripe_output_width_uv = stripe_output_width_y /
    706						IMGU_LUMA_TO_CHROMA_RATIO;
    707			/* Calculate input stripe width */
    708			stripe_input_width_y = stripe_offset_col_y +
    709				imgu_css_osys_calc_inp_stripe_width(
    710						stripe_output_width_y,
    711						IMGU_OSYS_FIR_PHASES,
    712						stripe_phase_init_y,
    713						scaler_luma->phase_step,
    714						IMGU_OSYS_TAPS_Y,
    715						stripe_pad_left_y,
    716						stripe_pad_right_y);
    717
    718			stripe_input_width_uv = stripe_offset_col_uv +
    719				imgu_css_osys_calc_inp_stripe_width(
    720						stripe_output_width_uv,
    721						IMGU_OSYS_FIR_PHASES,
    722						stripe_phase_init_uv,
    723						scaler_chroma->phase_step,
    724						IMGU_OSYS_TAPS_UV,
    725						stripe_pad_left_uv,
    726						stripe_pad_right_uv);
    727
    728			stripe_input_width_uv = max(DIV_ROUND_UP(
    729						    stripe_input_width_y,
    730						    IMGU_LUMA_TO_CHROMA_RATIO),
    731						    stripe_input_width_uv);
    732
    733			stripe_input_width_y = stripe_input_width_uv *
    734						IMGU_LUMA_TO_CHROMA_RATIO;
    735
    736			if (s >= stripes - 1) {
    737				stripe_input_width_y = reso.input_width -
    738					stripe_offset_blk_y;
    739				/*
    740				 * The scaler requires that the last stripe
    741				 * spans at least two input blocks.
    742				 */
    743			}
    744
    745			/*
    746			 * Spec: input stripe width must be a multiple of 8.
    747			 * Increase the input width and recalculate the output
    748			 * width. This may produce an extra column of junk
    749			 * blocks which will be overwritten by the
    750			 * next stripe.
    751			 */
    752			stripe_input_width_y = ALIGN(stripe_input_width_y, 8);
    753			stripe_output_width_y =
    754				imgu_css_osys_out_stripe_width(
    755						stripe_input_width_y,
    756						IMGU_OSYS_FIR_PHASES,
    757						stripe_phase_init_y,
    758						scaler_luma->phase_step,
    759						IMGU_OSYS_TAPS_Y,
    760						stripe_pad_left_y,
    761						stripe_pad_right_y,
    762						stripe_offset_col_y);
    763
    764			stripe_output_width_y =
    765					rounddown(stripe_output_width_y,
    766						  IMGU_LUMA_TO_CHROMA_RATIO);
    767		}
    768		/*
    769		 * Following section executes and process parameters
    770		 * for both cases - Striping or No Striping.
    771		 */
    772		{
    773			unsigned int i;
    774			/*Input resolution */
    775
    776			stripe_params[s].input_width = stripe_input_width_y;
    777			stripe_params[s].input_height = reso.input_height;
    778
    779			for (i = 0; i < IMGU_ABI_OSYS_PINS; i++) {
    780				if (frame_params[i].scaled) {
    781					/*
    782					 * Output stripe resolution and offset
    783					 * as produced by the scaler; actual
    784					 * output resolution may be slightly
    785					 * smaller.
    786					 */
    787					stripe_params[s].output_width[i] =
    788						stripe_output_width_y;
    789					stripe_params[s].output_height[i] =
    790						reso.pin_height[i];
    791					stripe_params[s].output_offset[i] =
    792						stripe_offset_out_y;
    793				} else {
    794					/* Unscaled pin */
    795					stripe_params[s].output_width[i] =
    796						stripe_params[s].input_width;
    797					stripe_params[s].output_height[i] =
    798						stripe_params[s].input_height;
    799					stripe_params[s].output_offset[i] =
    800						stripe_offset_blk_y;
    801				}
    802			}
    803
    804			/* If no pin use scale, we use BYPASS mode */
    805			stripe_params[s].processing_mode = procmode;
    806			stripe_params[s].phase_step = scaler_luma->phase_step;
    807			stripe_params[s].exp_shift = scaler_luma->exp_shift;
    808			stripe_params[s].phase_init_left_y =
    809				stripe_phase_init_y;
    810			stripe_params[s].phase_init_left_uv =
    811				stripe_phase_init_uv;
    812			stripe_params[s].phase_init_top_y =
    813				scaler_luma->phase_init;
    814			stripe_params[s].phase_init_top_uv =
    815				scaler_chroma->phase_init;
    816			stripe_params[s].pad_left_y = stripe_pad_left_y;
    817			stripe_params[s].pad_left_uv = stripe_pad_left_uv;
    818			stripe_params[s].pad_right_y = stripe_pad_right_y;
    819			stripe_params[s].pad_right_uv = stripe_pad_right_uv;
    820			stripe_params[s].pad_top_y = scaler_luma->pad_left;
    821			stripe_params[s].pad_top_uv = scaler_chroma->pad_left;
    822			stripe_params[s].pad_bottom_y = scaler_luma->pad_right;
    823			stripe_params[s].pad_bottom_uv =
    824				scaler_chroma->pad_right;
    825			stripe_params[s].crop_left_y = stripe_crop_left_y;
    826			stripe_params[s].crop_top_y = scaler_luma->crop_top;
    827			stripe_params[s].crop_left_uv = stripe_crop_left_uv;
    828			stripe_params[s].crop_top_uv = scaler_chroma->crop_top;
    829			stripe_params[s].start_column_y = stripe_offset_col_y;
    830			stripe_params[s].start_column_uv = stripe_offset_col_uv;
    831			stripe_params[s].chunk_width = reso.chunk_width;
    832			stripe_params[s].chunk_height = reso.chunk_height;
    833			stripe_params[s].block_width = reso.block_width;
    834			stripe_params[s].block_height = reso.block_height;
    835		}
    836	}
    837
    838	return 0;
    839}
    840
    841/*
    842 * This function configures the Output Formatter System, given the number of
    843 * stripes, scaler luma and chrome parameters
    844 */
    845static int imgu_css_osys_calc(struct imgu_css *css, unsigned int pipe,
    846			      unsigned int stripes,
    847			      struct imgu_abi_osys_config *osys,
    848			      struct imgu_css_scaler_info *scaler_luma,
    849			      struct imgu_css_scaler_info *scaler_chroma,
    850			      struct imgu_abi_stripes block_stripes[])
    851{
    852	struct imgu_css_frame_params frame_params[IMGU_ABI_OSYS_PINS];
    853	struct imgu_css_stripe_params stripe_params[IPU3_UAPI_MAX_STRIPES];
    854	struct imgu_abi_osys_formatter_params *param;
    855	unsigned int pin, s;
    856	struct imgu_css_pipe *css_pipe = &css->pipes[pipe];
    857
    858	memset(osys, 0, sizeof(*osys));
    859
    860	/* Compute the frame and stripe params */
    861	if (imgu_css_osys_calc_frame_and_stripe_params(css, stripes, osys,
    862						       scaler_luma,
    863						       scaler_chroma,
    864						       frame_params,
    865						       stripe_params, pipe))
    866		return -EINVAL;
    867
    868	/* Output formatter system parameters */
    869
    870	for (s = 0; s < stripes; s++) {
    871		struct imgu_abi_osys_scaler_params *scaler =
    872					&osys->scaler[s].param;
    873		int fifo_addr_fmt = IMGU_FIFO_ADDR_SCALER_TO_FMT;
    874		int fifo_addr_ack = IMGU_FIFO_ADDR_SCALER_TO_SP;
    875
    876		/* OUTPUT 0 / PIN 0 is only Scaler output */
    877		scaler->inp_buf_y_st_addr = IMGU_VMEM1_INP_BUF_ADDR;
    878
    879		/*
    880		 * = (IMGU_OSYS_BLOCK_WIDTH / IMGU_VMEM1_ELEMS_PER_VEC)
    881		 * = (2 * IPU3_UAPI_ISP_VEC_ELEMS) /
    882		 *   (IMGU_HIVE_OF_SYS_OF_SYSTEM_NWAYS)
    883		 * = 2 * 64 / 32 = 4
    884		 */
    885		scaler->inp_buf_y_line_stride = IMGU_VMEM1_Y_STRIDE;
    886		/*
    887		 * = (IMGU_VMEM1_V_OFFSET + VMEM1_uv_size)
    888		 * = (IMGU_VMEM1_U_OFFSET + VMEM1_uv_size) +
    889		 *	(VMEM1_y_size / 4)
    890		 * = (VMEM1_y_size) + (VMEM1_y_size / 4) +
    891		 * (IMGU_OSYS_BLOCK_HEIGHT * IMGU_VMEM1_Y_STRIDE)/4
    892		 * = (IMGU_OSYS_BLOCK_HEIGHT * IMGU_VMEM1_Y_STRIDE)
    893		 */
    894		scaler->inp_buf_y_buffer_stride = IMGU_VMEM1_BUF_SIZE;
    895		scaler->inp_buf_u_st_addr = IMGU_VMEM1_INP_BUF_ADDR +
    896						IMGU_VMEM1_U_OFFSET;
    897		scaler->inp_buf_v_st_addr = IMGU_VMEM1_INP_BUF_ADDR +
    898						IMGU_VMEM1_V_OFFSET;
    899		scaler->inp_buf_uv_line_stride = IMGU_VMEM1_UV_STRIDE;
    900		scaler->inp_buf_uv_buffer_stride = IMGU_VMEM1_BUF_SIZE;
    901		scaler->inp_buf_chunk_width = stripe_params[s].chunk_width;
    902		scaler->inp_buf_nr_buffers = IMGU_OSYS_NUM_INPUT_BUFFERS;
    903
    904		/* Output buffers */
    905		scaler->out_buf_y_st_addr = IMGU_VMEM1_INT_BUF_ADDR;
    906		scaler->out_buf_y_line_stride = stripe_params[s].block_width /
    907						IMGU_VMEM1_ELEMS_PER_VEC;
    908		scaler->out_buf_y_buffer_stride = IMGU_VMEM1_BUF_SIZE;
    909		scaler->out_buf_u_st_addr = IMGU_VMEM1_INT_BUF_ADDR +
    910						IMGU_VMEM1_U_OFFSET;
    911		scaler->out_buf_v_st_addr = IMGU_VMEM1_INT_BUF_ADDR +
    912						IMGU_VMEM1_V_OFFSET;
    913		scaler->out_buf_uv_line_stride = stripe_params[s].block_width /
    914						IMGU_VMEM1_ELEMS_PER_VEC / 2;
    915		scaler->out_buf_uv_buffer_stride = IMGU_VMEM1_BUF_SIZE;
    916		scaler->out_buf_nr_buffers = IMGU_OSYS_NUM_INTERM_BUFFERS;
    917
    918		/* Intermediate buffers */
    919		scaler->int_buf_y_st_addr = IMGU_VMEM2_BUF_Y_ADDR;
    920		scaler->int_buf_y_line_stride = IMGU_VMEM2_BUF_Y_STRIDE;
    921		scaler->int_buf_u_st_addr = IMGU_VMEM2_BUF_U_ADDR;
    922		scaler->int_buf_v_st_addr = IMGU_VMEM2_BUF_V_ADDR;
    923		scaler->int_buf_uv_line_stride = IMGU_VMEM2_BUF_UV_STRIDE;
    924		scaler->int_buf_height = IMGU_VMEM2_LINES_PER_BLOCK;
    925		scaler->int_buf_chunk_width = stripe_params[s].chunk_height;
    926		scaler->int_buf_chunk_height = stripe_params[s].block_width;
    927
    928		/* Context buffers */
    929		scaler->ctx_buf_hor_y_st_addr = IMGU_VMEM3_HOR_Y_ADDR;
    930		scaler->ctx_buf_hor_u_st_addr = IMGU_VMEM3_HOR_U_ADDR;
    931		scaler->ctx_buf_hor_v_st_addr = IMGU_VMEM3_HOR_V_ADDR;
    932		scaler->ctx_buf_ver_y_st_addr = IMGU_VMEM3_VER_Y_ADDR;
    933		scaler->ctx_buf_ver_u_st_addr = IMGU_VMEM3_VER_U_ADDR;
    934		scaler->ctx_buf_ver_v_st_addr = IMGU_VMEM3_VER_V_ADDR;
    935
    936		/* Addresses for release-input and process-output tokens */
    937		scaler->release_inp_buf_addr = fifo_addr_ack;
    938		scaler->release_inp_buf_en = 1;
    939		scaler->release_out_buf_en = 1;
    940		scaler->process_out_buf_addr = fifo_addr_fmt;
    941
    942		/* Settings dimensions, padding, cropping */
    943		scaler->input_image_y_width = stripe_params[s].input_width;
    944		scaler->input_image_y_height = stripe_params[s].input_height;
    945		scaler->input_image_y_start_column =
    946					stripe_params[s].start_column_y;
    947		scaler->input_image_uv_start_column =
    948					stripe_params[s].start_column_uv;
    949		scaler->input_image_y_left_pad = stripe_params[s].pad_left_y;
    950		scaler->input_image_uv_left_pad = stripe_params[s].pad_left_uv;
    951		scaler->input_image_y_right_pad = stripe_params[s].pad_right_y;
    952		scaler->input_image_uv_right_pad =
    953					stripe_params[s].pad_right_uv;
    954		scaler->input_image_y_top_pad = stripe_params[s].pad_top_y;
    955		scaler->input_image_uv_top_pad = stripe_params[s].pad_top_uv;
    956		scaler->input_image_y_bottom_pad =
    957					stripe_params[s].pad_bottom_y;
    958		scaler->input_image_uv_bottom_pad =
    959					stripe_params[s].pad_bottom_uv;
    960		scaler->processing_mode = stripe_params[s].processing_mode;
    961		scaler->scaling_ratio = stripe_params[s].phase_step;
    962		scaler->y_left_phase_init = stripe_params[s].phase_init_left_y;
    963		scaler->uv_left_phase_init =
    964					stripe_params[s].phase_init_left_uv;
    965		scaler->y_top_phase_init = stripe_params[s].phase_init_top_y;
    966		scaler->uv_top_phase_init = stripe_params[s].phase_init_top_uv;
    967		scaler->coeffs_exp_shift = stripe_params[s].exp_shift;
    968		scaler->out_y_left_crop = stripe_params[s].crop_left_y;
    969		scaler->out_uv_left_crop = stripe_params[s].crop_left_uv;
    970		scaler->out_y_top_crop = stripe_params[s].crop_top_y;
    971		scaler->out_uv_top_crop = stripe_params[s].crop_top_uv;
    972
    973		for (pin = 0; pin < IMGU_ABI_OSYS_PINS; pin++) {
    974			int in_fifo_addr;
    975			int out_fifo_addr;
    976			int block_width_vecs;
    977			int input_width_s;
    978			int input_width_vecs;
    979			int input_buf_y_st_addr;
    980			int input_buf_u_st_addr;
    981			int input_buf_v_st_addr;
    982			int input_buf_y_line_stride;
    983			int input_buf_uv_line_stride;
    984			int output_buf_y_line_stride;
    985			int output_buf_uv_line_stride;
    986			int output_buf_nr_y_lines;
    987			int block_height;
    988			int block_width;
    989			struct imgu_abi_osys_frame_params *fr_pr;
    990
    991			fr_pr = &osys->frame[pin].param;
    992
    993			/* Frame parameters */
    994			fr_pr->enable = frame_params[pin].enable;
    995			fr_pr->format = frame_params[pin].format;
    996			fr_pr->mirror = frame_params[pin].mirror;
    997			fr_pr->flip = frame_params[pin].flip;
    998			fr_pr->tiling = frame_params[pin].tiling;
    999			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			/* Stripe parameters */
   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				/* Only first stripe should do left cropping */
   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				 * Stripe offset for other strips should be
   1029				 * adjusted according to the cropping done
   1030				 * at the first strip
   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			/* Formatter: configurations */
   1042
   1043			/*
   1044			 * Get the dimensions of the input blocks of the
   1045			 * formatter, which is the same as the output
   1046			 * blocks of the scaler.
   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			 * The input/output line stride depends on the
   1059			 * block size.
   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			 * Tiled outputs use a different output buffer
   1075			 * configuration. The input (= scaler output) block
   1076			 * width translates to a tile height, and the block
   1077			 * height to the tile width. The default block size of
   1078			 * 128x32 maps exactly onto a 4kB tile (512x8) for Y.
   1079			 * For UV, the tile width is always half.
   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			 * Store the output buffer line stride. Will be
   1091			 * used to compute buffer offsets in boundary
   1092			 * conditions when output blocks are partially
   1093			 * outside the image.
   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				 * The input buffs are the intermediate
   1101				 * buffers (scalers' output)
   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				 * The input bufferss are the buffers
   1111				 * filled by the SP
   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			 * The formatter input width must be rounded to
   1122			 * the block width. Otherwise the formatter will
   1123			 * not recognize the end of the line, resulting
   1124			 * in incorrect tiling (system may hang!) and
   1125			 * possibly other problems.
   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			 * Process-output tokens must be sent to the SP.
   1135			 * When scaling, the release-input tokens can be
   1136			 * sent directly to the scaler, otherwise the
   1137			 * formatter should send them to the SP.
   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			/* Formatter */
   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/*********************** Mostly 3A operations ******************************/
   1209
   1210/*
   1211 * This function creates a "TO-DO list" (operations) for the sp code.
   1212 *
   1213 * There are 2 types of operations:
   1214 * 1. Transfer: Issue DMA transfer request for copying grid cells from DDR to
   1215 *    accelerator space (NOTE that this space is limited) associated data:
   1216 *    DDR address + accelerator's config set index(acc's address).
   1217 *
   1218 * 2. Issue "Process Lines Command" to shd accelerator
   1219 *    associated data: #lines + which config set to use (actually, accelerator
   1220 *    will use x AND (x+1)%num_of_sets - NOTE that this implies the restriction
   1221 *    of not touching config sets x & (x+1)%num_of_sets when process_lines(x)
   1222 *    is active).
   1223 *
   1224 * Basically there are 2 types of operations "chunks":
   1225 * 1. "initial chunk": Initially, we do as much transfers as we can (and need)
   1226 *    [0 - max sets(3) ] followed by 1 or 2 "process lines" operations.
   1227 *
   1228 * 2. "regular chunk" - 1 transfer followed by 1 process line operation.
   1229 *    (in some cases we might need additional transfer ate the last chunk).
   1230 *
   1231 * for some case:
   1232 * --> init
   1233 *	tr (0)
   1234 *	tr (1)
   1235 *	tr (2)
   1236 *	pl (0)
   1237 *	pl (1)
   1238 * --> ack (0)
   1239 *	tr (3)
   1240 *	pl (2)
   1241 * --> ack (1)
   1242 *	pl (3)
   1243 * --> ack (2)
   1244 *	do nothing
   1245 * --> ack (3)
   1246 *	do nothing
   1247 */
   1248
   1249static int
   1250imgu_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	/* We currently support only abs(y_start) > grid_height_per_slice */
   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	 * When the number of lines for the last process lines command
   1274	 * is equal to a set height, we need another line of grid cell -
   1275	 * additional transfer is required.
   1276	 */
   1277	unsigned char last_tr = 0;
   1278
   1279	/* Add "process lines" command to the list of operations */
   1280	bool add_pl;
   1281	/* Add DMA xfer (config set) command to the list of ops */
   1282	bool add_tr;
   1283
   1284	/*
   1285	 * Available partial grid (the part that fits into #IMGU_SHD_SETS sets)
   1286	 * doesn't cover whole frame - need to process in chunks
   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 { /* partial grid covers whole frame */
   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	/* Init operations lists and counters */
   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	/* Cyclic counters that holds config set number [0,IMGU_SHD_SETS) */
   1314	tr_set_num = 0;
   1315	pl_cfg_set = 0;
   1316
   1317	/*
   1318	 * Always start with a transfer - process lines command must be
   1319	 * initiated only after appropriate config sets are in place
   1320	 * (2 configuration sets per process line command, except for last one).
   1321	 */
   1322	add_pl = false;
   1323	add_tr = true;
   1324
   1325	while (add_pl || add_tr) {
   1326		/* Transfer ops */
   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		/* Process-lines ops */
   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			 * In case we have 2 process lines commands -
   1350			 * don't stop after the first one
   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			 * Initiate last process lines command -
   1357			 * end of operation list.
   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			 * Intermediate process line command - end of operation
   1364			 * "chunk" (meaning few "transfers" followed by few
   1365			 * "process lines" commands).
   1366			 */
   1367			else
   1368				p_op[op_idx].op_indicator =
   1369					IMGU_ABI_ACC_OP_END_OF_ACK;
   1370
   1371			op_idx++;
   1372
   1373			/* first process line operation */
   1374			if (pl_idx == 0)
   1375				p_pl[pl_idx].lines = first_process_lines;
   1376			/* Last process line operation */
   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	/* "regular" process lines operation */
   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		 * Initially, we always transfer
   1390		 * min(IMGU_SHD_SETS, num_of_sets) - after that we fill in the
   1391		 * corresponding process lines commands.
   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		 * We have finished the "initial" operations chunk -
   1401		 * be ready to get more chunks.
   1402		 */
   1403		if (pl_idx == 2) {
   1404			add_tr = true;
   1405			add_pl = true;
   1406		}
   1407
   1408		/* Stop conditions for each operation type */
   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 * The follow handshake procotol is the same for AF, AWB and AWB FR.
   1420 *
   1421 * for n sets of meta-data, the flow is:
   1422 * --> init
   1423 *  process-lines  (0)
   1424 *  process-lines  (1)	 eoc
   1425 *  --> ack (0)
   1426 *  read-meta-data (0)
   1427 *  process-lines  (2)	 eoc
   1428 *  --> ack (1)
   1429 *  read-meta-data (1)
   1430 *  process-lines  (3)	 eoc
   1431 *  ...
   1432 *
   1433 *  --> ack (n-3)
   1434 *  read-meta-data (n-3)
   1435 *  process-lines  (n-1) eoc
   1436 *  --> ack (n-2)
   1437 *  read-meta-data (n-2) eoc
   1438 *  --> ack (n-1)
   1439 *  read-meta-data (n-1) eof
   1440 *
   1441 * for 2 sets we get:
   1442 * --> init
   1443 * pl (0)
   1444 * pl (1) eoc
   1445 * --> ack (0)
   1446 * pl (2) - rest of image, if applicable)
   1447 * rmd (0) eoc
   1448 * --> ack (1)
   1449 * rmd (1) eof
   1450 * --> (ack (2))
   1451 * do nothing
   1452 *
   1453 * for only one set:
   1454 *
   1455 * --> init
   1456 * pl(0)   eoc
   1457 * --> ack (0)
   1458 * rmd (0) eof
   1459 *
   1460 * grid smaller than image case
   1461 * for example 128x128 grid (block size 8x8, 16x16 num of blocks)
   1462 * start at (0,0)
   1463 * 1st set holds 160 cells - 10 blocks vertical, 16 horizontal
   1464 * => 1st process lines = 80
   1465 * we're left with 128-80=48 lines (6 blocks vertical)
   1466 * => 2nd process lines = 48
   1467 * last process lines to cover the image - image_height - 128
   1468 *
   1469 * --> init
   1470 * pl (0) first
   1471 * pl (1) last-in-grid
   1472 * --> ack (0)
   1473 * rmd (0)
   1474 * pl (2) after-grid
   1475 * --> ack (1)
   1476 * rmd (1) eof
   1477 * --> ack (2)
   1478 * do nothing
   1479 */
   1480struct 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; /* max operation */
   1488	unsigned short max_tr; /* max transaction */
   1489	unsigned char acc_enable;
   1490};
   1491
   1492/* Helper to config intra_frame_operations_data. */
   1493static int
   1494imgu_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	/* Account for two line delay inside the FF */
   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		/* Read meta-data */
   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				/* The last operation is always a tr */
   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					 * No additional pl op left -
   1560					 * this op is left as lats of cycle
   1561					 */
   1562					p_op[op_idx].op_indicator =
   1563						IMGU_ABI_ACC_OP_END_OF_ACK;
   1564				else
   1565					/*
   1566					 * We still have to process-lines after
   1567					 * the grid so have one more pl op
   1568					 */
   1569					p_op[op_idx].op_indicator =
   1570						IMGU_ABI_ACC_OP_IDLE;
   1571			else
   1572				/* Default - usually there's a pl after a tr */
   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		/* process_lines */
   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					/* Only one pl op */
   1594					p_op[op_idx].op_indicator =
   1595						IMGU_ABI_ACC_OP_END_OF_ACK;
   1596				else
   1597					/* On init - do two pl ops */
   1598					p_op[op_idx].op_indicator =
   1599						IMGU_ABI_ACC_OP_IDLE;
   1600			else
   1601				/* Usually pl is the end of the ack cycle */
   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				/* First process line */
   1609				p_pl[pl_idx].lines = first_process_lines;
   1610			else if (pl_idx == num_of_sets - 1)
   1611				/* Last in grid */
   1612				p_pl[pl_idx].lines = last_process_lines_in_grid;
   1613			else if (pl_idx == num_of_process_lines - 1)
   1614				/* After the grid */
   1615				p_pl[pl_idx].lines = process_lines_after_grid;
   1616			else
   1617				/* Inside the grid */
   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
   1631static 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
   1658static int
   1659imgu_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
   1685static 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
   1711static 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
   1717static 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/****************** config computation *****************************/
   1726
   1727static 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	/* acc_param: osys_config */
   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	/* acc_param: stripe data */
   1747
   1748	/*
   1749	 * For the striped case the approach is as follows:
   1750	 * 1. down-scaled stripes are calculated - with 128 overlap
   1751	 *    (this is the main limiter therefore it's first)
   1752	 * 2. input stripes are derived by up-scaling the down-scaled stripes
   1753	 *    (there are no alignment requirements on input stripes)
   1754	 * 3. output stripes are derived from down-scaled stripes too
   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		/* Image processing is divided into two stripes */
   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		 * Sum of width of the two stripes should not be smaller
   1779		 * than output width and must be even times of overlapping
   1780		 * unit f.
   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		/* Overlap between stripes is IPU3_UAPI_ISP_VEC_ELEMS * 4 */
   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 { /* Two stripes */
   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
   1899static 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	/* Disable DVS statistics */
   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
   1918static 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 * Configure `acc' parameters. `acc_old' contains the old values (or is NULL)
   1939 * and `acc_user' contains new prospective values. `use' contains flags
   1940 * telling which fields to take from the old values (or generate if it is NULL)
   1941 * and which to take from the new user values.
   1942 */
   1943int 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; /* Block width log2 */
   1963
   1964	/* Update stripe using chroma and luma */
   1965
   1966	if (imgu_css_cfg_acc_stripe(css, pipe, acc))
   1967		return -EINVAL;
   1968
   1969	/* acc_param: input_feeder_config */
   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	/* acc_param: bnr_static_config */
   2003
   2004	/*
   2005	 * Originate from user or be the original default values if user has
   2006	 * never set them before, when user gives a new set of parameters,
   2007	 * for each chunk in the parameter structure there is a flag use->xxx
   2008	 * whether to use the user-provided parameter or not. If not, the
   2009	 * parameter remains unchanged in the driver:
   2010	 * it's value is taken from acc_old.
   2011	 */
   2012	if (use && use->acc_bnr) {
   2013		/* Take values from user */
   2014		acc->bnr = acc_user->bnr;
   2015	} else if (acc_old) {
   2016		/* Use old value */
   2017		acc->bnr = acc_old->bnr;
   2018	} else {
   2019		/* Calculate from scratch */
   2020		acc->bnr = imgu_css_bnr_defaults;
   2021	}
   2022
   2023	acc->bnr.column_size = tnr_frame_width;
   2024
   2025	/* acc_param: bnr_static_config_green_disparity */
   2026
   2027	if (use && use->acc_green_disparity) {
   2028		/* Take values from user */
   2029		acc->green_disparity = acc_user->green_disparity;
   2030	} else if (acc_old) {
   2031		/* Use old value */
   2032		acc->green_disparity = acc_old->green_disparity;
   2033	} else {
   2034		/* Calculate from scratch */
   2035		memset(&acc->green_disparity, 0, sizeof(acc->green_disparity));
   2036	}
   2037
   2038	/* acc_param: dm_config */
   2039
   2040	if (use && use->acc_dm) {
   2041		/* Take values from user */
   2042		acc->dm = acc_user->dm;
   2043	} else if (acc_old) {
   2044		/* Use old value */
   2045		acc->dm = acc_old->dm;
   2046	} else {
   2047		/* Calculate from scratch */
   2048		acc->dm = imgu_css_dm_defaults;
   2049	}
   2050
   2051	acc->dm.frame_width = tnr_frame_width;
   2052
   2053	/* acc_param: ccm_mat_config */
   2054
   2055	if (use && use->acc_ccm) {
   2056		/* Take values from user */
   2057		acc->ccm = acc_user->ccm;
   2058	} else if (acc_old) {
   2059		/* Use old value */
   2060		acc->ccm = acc_old->ccm;
   2061	} else {
   2062		/* Calculate from scratch */
   2063		acc->ccm = imgu_css_ccm_defaults;
   2064	}
   2065
   2066	/* acc_param: gamma_config */
   2067
   2068	if (use && use->acc_gamma) {
   2069		/* Take values from user */
   2070		acc->gamma = acc_user->gamma;
   2071	} else if (acc_old) {
   2072		/* Use old value */
   2073		acc->gamma = acc_old->gamma;
   2074	} else {
   2075		/* Calculate from scratch */
   2076		acc->gamma.gc_ctrl.enable = 1;
   2077		acc->gamma.gc_lut = imgu_css_gamma_lut;
   2078	}
   2079
   2080	/* acc_param: csc_mat_config */
   2081
   2082	if (use && use->acc_csc) {
   2083		/* Take values from user */
   2084		acc->csc = acc_user->csc;
   2085	} else if (acc_old) {
   2086		/* Use old value */
   2087		acc->csc = acc_old->csc;
   2088	} else {
   2089		/* Calculate from scratch */
   2090		acc->csc = imgu_css_csc_defaults;
   2091	}
   2092
   2093	/* acc_param: cds_params */
   2094
   2095	if (use && use->acc_cds) {
   2096		/* Take values from user */
   2097		acc->cds = acc_user->cds;
   2098	} else if (acc_old) {
   2099		/* Use old value */
   2100		acc->cds = acc_old->cds;
   2101	} else {
   2102		/* Calculate from scratch */
   2103		acc->cds = imgu_css_cds_defaults;
   2104	}
   2105
   2106	/* acc_param: shd_config */
   2107
   2108	if (use && use->acc_shd) {
   2109		/* Take values from user */
   2110		acc->shd.shd = acc_user->shd.shd;
   2111		acc->shd.shd_lut = acc_user->shd.shd_lut;
   2112	} else if (acc_old) {
   2113		/* Use old value */
   2114		acc->shd.shd = acc_old->shd.shd;
   2115		acc->shd.shd_lut = acc_old->shd.shd_lut;
   2116	} else {
   2117		/* Calculate from scratch */
   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	/* acc_param: dvs_stat_config */
   2141	imgu_css_cfg_acc_dvs(css, acc, pipe);
   2142
   2143	/* acc_param: yuvp1_iefd_config */
   2144
   2145	if (use && use->acc_iefd) {
   2146		/* Take values from user */
   2147		acc->iefd = acc_user->iefd;
   2148	} else if (acc_old) {
   2149		/* Use old value */
   2150		acc->iefd = acc_old->iefd;
   2151	} else {
   2152		/* Calculate from scratch */
   2153		acc->iefd = imgu_css_iefd_defaults;
   2154	}
   2155
   2156	/* acc_param: yuvp1_yds_config yds_c0 */
   2157
   2158	if (use && use->acc_yds_c0) {
   2159		/* Take values from user */
   2160		acc->yds_c0 = acc_user->yds_c0;
   2161	} else if (acc_old) {
   2162		/* Use old value */
   2163		acc->yds_c0 = acc_old->yds_c0;
   2164	} else {
   2165		/* Calculate from scratch */
   2166		acc->yds_c0 = imgu_css_yds_defaults;
   2167	}
   2168
   2169	/* acc_param: yuvp1_chnr_config chnr_c0 */
   2170
   2171	if (use && use->acc_chnr_c0) {
   2172		/* Take values from user */
   2173		acc->chnr_c0 = acc_user->chnr_c0;
   2174	} else if (acc_old) {
   2175		/* Use old value */
   2176		acc->chnr_c0 = acc_old->chnr_c0;
   2177	} else {
   2178		/* Calculate from scratch */
   2179		acc->chnr_c0 = imgu_css_chnr_defaults;
   2180	}
   2181
   2182	/* acc_param: yuvp1_y_ee_nr_config */
   2183
   2184	if (use && use->acc_y_ee_nr) {
   2185		/* Take values from user */
   2186		acc->y_ee_nr = acc_user->y_ee_nr;
   2187	} else if (acc_old) {
   2188		/* Use old value */
   2189		acc->y_ee_nr = acc_old->y_ee_nr;
   2190	} else {
   2191		/* Calculate from scratch */
   2192		acc->y_ee_nr = imgu_css_y_ee_nr_defaults;
   2193	}
   2194
   2195	/* acc_param: yuvp1_yds_config yds */
   2196
   2197	if (use && use->acc_yds) {
   2198		/* Take values from user */
   2199		acc->yds = acc_user->yds;
   2200	} else if (acc_old) {
   2201		/* Use old value */
   2202		acc->yds = acc_old->yds;
   2203	} else {
   2204		/* Calculate from scratch */
   2205		acc->yds = imgu_css_yds_defaults;
   2206	}
   2207
   2208	/* acc_param: yuvp1_chnr_config chnr */
   2209
   2210	if (use && use->acc_chnr) {
   2211		/* Take values from user */
   2212		acc->chnr = acc_user->chnr;
   2213	} else if (acc_old) {
   2214		/* Use old value */
   2215		acc->chnr = acc_old->chnr;
   2216	} else {
   2217		/* Calculate from scratch */
   2218		acc->chnr = imgu_css_chnr_defaults;
   2219	}
   2220
   2221	/* acc_param: yuvp2_y_tm_lut_static_config */
   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;	/* Always disabled on IPU3 */
   2226
   2227	/* acc_param: yuvp1_yds_config yds2 */
   2228
   2229	if (use && use->acc_yds2) {
   2230		/* Take values from user */
   2231		acc->yds2 = acc_user->yds2;
   2232	} else if (acc_old) {
   2233		/* Use old value */
   2234		acc->yds2 = acc_old->yds2;
   2235	} else {
   2236		/* Calculate from scratch */
   2237		acc->yds2 = imgu_css_yds_defaults;
   2238	}
   2239
   2240	/* acc_param: yuvp2_tcc_static_config */
   2241
   2242	if (use && use->acc_tcc) {
   2243		/* Take values from user */
   2244		acc->tcc = acc_user->tcc;
   2245	} else if (acc_old) {
   2246		/* Use old value */
   2247		acc->tcc = acc_old->tcc;
   2248	} else {
   2249		/* Calculate from scratch */
   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	/* acc_param: dpc_config */
   2274
   2275	if (use && use->acc_dpc)
   2276		return -EINVAL;	/* Not supported yet */
   2277
   2278	/* Just disable by default */
   2279	memset(&acc->dpc, 0, sizeof(acc->dpc));
   2280
   2281	/* acc_param: bds_config */
   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	/* acc_param: anr_config */
   2321
   2322	if (use && use->acc_anr) {
   2323		/* Take values from user */
   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		/* Use old value */
   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		/* Calculate from scratch */
   2338		acc->anr = imgu_css_anr_defaults;
   2339	}
   2340
   2341	/* Always enabled */
   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	/* acc_param: awb_fr_config */
   2367
   2368	if (use && use->acc_awb_fr) {
   2369		/* Take values from user */
   2370		acc->awb_fr.config = acc_user->awb_fr;
   2371	} else if (acc_old) {
   2372		/* Use old value */
   2373		acc->awb_fr.config = acc_old->awb_fr.config;
   2374	} else {
   2375		/* Set from scratch */
   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		/* Enable only for rightmost stripe, disable left */
   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		/* Enable only for leftmost stripe, disable right */
   2399		acc->awb_fr.stripes[1].grid_cfg.y_start &=
   2400					~IPU3_UAPI_GRID_Y_START_EN;
   2401	} else {
   2402		/* Enable for both stripes */
   2403		u16 end; /* width for grid 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		 * To reduce complexity of debubbling and loading
   2431		 * statistics fix grid_height_per_slice to 1 for both
   2432		 * stripes.
   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	/* acc_param: ae_config */
   2442
   2443	if (use && use->acc_ae) {
   2444		/* Take values from user */
   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		/* Use old value */
   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		/* Set from scratch */
   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		/* Enable only for rightmost stripe, disable left */
   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		/* Enable only for leftmost stripe, disable right */
   2485		acc->ae.stripes[1].grid.ae_en = 0;
   2486	} else {
   2487		/* Enable for both stripes */
   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	/* acc_param: af_config */
   2516
   2517	if (use && use->acc_af) {
   2518		/* Take values from user */
   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		/* Use old value */
   2523		acc->af.config = acc_old->af.config;
   2524	} else {
   2525		/* Set from scratch */
   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		/* Enable only for rightmost stripe, disable left */
   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		/* Enable only for leftmost stripe, disable right */
   2571		acc->af.stripes[1].grid_cfg.y_start &=
   2572			~IPU3_UAPI_GRID_Y_START_EN;
   2573	} else {
   2574		/* Enable for both stripes */
   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		 * To reduce complexity of debubbling and loading statistics
   2603		 * fix grid_height_per_slice to 1 for both stripes
   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	/* acc_param: awb_config */
   2613
   2614	if (use && use->acc_awb) {
   2615		/* Take values from user */
   2616		acc->awb.config = acc_user->awb.config;
   2617	} else if (acc_old) {
   2618		/* Use old value */
   2619		acc->awb.config = acc_old->awb.config;
   2620	} else {
   2621		/* Set from scratch */
   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		/* Enable only for rightmost stripe, disable left */
   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		/* Enable only for leftmost stripe, disable right */
   2653		acc->awb.stripes[1].rgbs_thr_b &= ~IPU3_UAPI_AWB_RGBS_THR_B_EN;
   2654	} else {
   2655		/* Enable for both stripes */
   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		 * To reduce complexity of debubbling and loading statistics
   2683		 * fix grid_height_per_slice to 1 for both stripes
   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 * Fill the indicated structure in `new_binary_params' from the possible
   2697 * sources based on `use_user' flag: if the flag is false, copy from
   2698 * `old_binary_params', or if the flag is true, copy from `user_setting'
   2699 * and return NULL (or error pointer on error).
   2700 * If the flag is false and `old_binary_params' is NULL, return pointer
   2701 * to the structure inside `new_binary_params'. In that case the caller
   2702 * should calculate and fill the structure from scratch.
   2703 */
   2704static 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);	/* Corrupted firmware */
   2719
   2720	if (use_user) {
   2721		/* Take new user parameters */
   2722		memcpy(new_setting, user_setting, par_size);
   2723	} else if (old_binary_params) {
   2724		/* Take previous value */
   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;	/* Need to calculate */
   2733	}
   2734
   2735	return NULL;		/* Copied from other value */
   2736}
   2737
   2738/*
   2739 * Configure VMEM0 parameters (late binding parameters).
   2740 */
   2741int 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	/* Configure VMEM0 */
   2758
   2759	memset(vmem0, 0, bi->info.isp.sp.mem_initializers.params[c][m].size);
   2760
   2761	/* Configure Linearization VMEM0 parameters */
   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		/* Generate parameter from scratch */
   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	/* Configure TNR3 VMEM parameters */
   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			/* Generate parameter from scratch */
   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	/* Configure XNR3 VMEM parameters */
   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 * Configure DMEM0 parameters (late binding parameters).
   2819 */
   2820int 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	/* Configure DMEM0 */
   2838
   2839	memset(dmem0, 0, bi->info.isp.sp.mem_initializers.params[c][m].size);
   2840
   2841	/* Configure TNR3 DMEM0 parameters */
   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			/* Generate parameter from scratch */
   2851			tnr_dmem->knee_y1 = 768;
   2852			tnr_dmem->knee_y2 = 1280;
   2853		}
   2854	}
   2855
   2856	/* Configure XNR3 DMEM0 parameters */
   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		/* Generate parameter from scratch */
   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/* Generate unity morphing table without morphing effect */
   2872void 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;	/* Bytes per pixel */
   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	/* Global luma settings */
   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	/* Global chroma settings */
   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	/* Calculate block offsets for luma and chroma */
   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				/* Luma blocks */
   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			/* Chroma block */
   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}