xref: /openbmc/linux/drivers/staging/media/ipu3/ipu3-css-params.c (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
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  
17  struct 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  
imgu_css_scaler_get_exp(unsigned int counter,unsigned int divider)28  static 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 */
43  static void
imgu_css_scaler_setup_lut(unsigned int taps,unsigned int input_width,unsigned int output_width,int phase_step_correction,const int * coeffs,unsigned int coeffs_size,s8 coeff_lut[],struct imgu_css_scaler_info * info)44  imgu_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   */
114  static unsigned int
imgu_css_scaler_calc_scaled_output(unsigned int input,struct imgu_css_scaler_info * info)115  imgu_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   */
133  static void
imgu_css_scaler_calc(u32 input_width,u32 input_height,u32 target_width,u32 target_height,struct imgu_abi_osys_config * cfg,struct imgu_css_scaler_info * info_luma,struct imgu_css_scaler_info * info_chroma,unsigned int * output_width,unsigned int * output_height,unsigned int * procmode)134  imgu_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  
imgu_css_osys_set_format(enum imgu_abi_frame_format host_format,unsigned int * osys_format,unsigned int * osys_tiling)195  static 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   */
imgu_css_osys_calc_stripe_offset(int stripe_offset_out,int fir_phases,int phase_init,int phase_step,int pad_left)232  static 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   */
imgu_css_osys_calc_stripe_phase_init(int stripe_offset_out,int fir_phases,int phase_init,int phase_step,int pad_left)246  static 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   */
imgu_css_osys_calc_inp_stripe_width(int stripe_width_out,int fir_phases,int phase_init,int phase_step,int fir_taps,int pad_left,int pad_right)263  static 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   */
imgu_css_osys_out_stripe_width(int stripe_width_inp,int fir_phases,int phase_init,int phase_step,int fir_taps,int pad_left,int pad_right,int column_offset)280  static 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  
293  struct 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  
307  struct 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  
323  struct 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   */
imgu_css_osys_calc_frame_and_stripe_params(struct imgu_css * css,unsigned int stripes,struct imgu_abi_osys_config * osys,struct imgu_css_scaler_info * scaler_luma,struct imgu_css_scaler_info * scaler_chroma,struct imgu_css_frame_params frame_params[],struct imgu_css_stripe_params stripe_params[],unsigned int pipe)360  static 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   */
imgu_css_osys_calc(struct imgu_css * css,unsigned int pipe,unsigned int stripes,struct imgu_abi_osys_config * osys,struct imgu_css_scaler_info * scaler_luma,struct imgu_css_scaler_info * scaler_chroma,struct imgu_abi_stripes block_stripes[])845  static 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  
1249  static int
imgu_css_shd_ops_calc(struct imgu_abi_shd_intra_frame_operations_data * ops,const struct ipu3_uapi_shd_grid_config * grid,unsigned int image_height)1250  imgu_css_shd_ops_calc(struct imgu_abi_shd_intra_frame_operations_data *ops,
1251  		      const struct ipu3_uapi_shd_grid_config *grid,
1252  		      unsigned int image_height)
1253  {
1254  	unsigned int block_height = 1 << grid->block_height_log2;
1255  	unsigned int grid_height_per_slice = grid->grid_height_per_slice;
1256  	unsigned int set_height = grid_height_per_slice * block_height;
1257  
1258  	/* 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   */
1480  struct process_lines {
1481  	unsigned int image_height;
1482  	unsigned short grid_height;
1483  	unsigned short block_height;
1484  	unsigned short y_start;
1485  	unsigned char grid_height_per_slice;
1486  
1487  	unsigned short max_op; /* max operation */
1488  	unsigned short max_tr; /* max transaction */
1489  	unsigned char acc_enable;
1490  };
1491  
1492  /* Helper to config intra_frame_operations_data. */
1493  static int
imgu_css_acc_process_lines(const struct process_lines * pl,struct imgu_abi_acc_operation * p_op,struct imgu_abi_acc_process_lines_cmd_data * p_pl,struct imgu_abi_acc_transfer_op_data * p_tr)1494  imgu_css_acc_process_lines(const struct process_lines *pl,
1495  			   struct imgu_abi_acc_operation *p_op,
1496  			   struct imgu_abi_acc_process_lines_cmd_data *p_pl,
1497  			   struct imgu_abi_acc_transfer_op_data *p_tr)
1498  {
1499  	unsigned short op_idx = 0, pl_idx = 0, tr_idx = 0;
1500  	unsigned char tr_set_num = 0, pl_cfg_set = 0;
1501  	const unsigned short grid_last_line =
1502  			pl->y_start + pl->grid_height * pl->block_height;
1503  	const unsigned short process_lines =
1504  			pl->grid_height_per_slice * pl->block_height;
1505  
1506  	unsigned int process_lines_after_grid;
1507  	unsigned short first_process_lines;
1508  	unsigned short last_process_lines_in_grid;
1509  
1510  	unsigned short num_of_process_lines;
1511  	unsigned short num_of_sets;
1512  
1513  	if (pl->grid_height_per_slice == 0)
1514  		return -EINVAL;
1515  
1516  	if (pl->acc_enable && grid_last_line > pl->image_height)
1517  		return -EINVAL;
1518  
1519  	num_of_sets = pl->grid_height / pl->grid_height_per_slice;
1520  	if (num_of_sets * pl->grid_height_per_slice < pl->grid_height)
1521  		num_of_sets++;
1522  
1523  	/* 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  
imgu_css_af_ops_calc(struct imgu_css * css,unsigned int pipe,struct imgu_abi_af_config * af_config)1631  static int imgu_css_af_ops_calc(struct imgu_css *css, unsigned int pipe,
1632  				struct imgu_abi_af_config *af_config)
1633  {
1634  	struct imgu_abi_af_intra_frame_operations_data *to =
1635  		&af_config->operations_data;
1636  	struct imgu_css_pipe *css_pipe = &css->pipes[pipe];
1637  	struct imgu_fw_info *bi =
1638  		&css->fwp->binary_header[css_pipe->bindex];
1639  
1640  	struct process_lines pl = {
1641  		.image_height = css_pipe->rect[IPU3_CSS_RECT_BDS].height,
1642  		.grid_height = af_config->config.grid_cfg.height,
1643  		.block_height =
1644  			1 << af_config->config.grid_cfg.block_height_log2,
1645  		.y_start = af_config->config.grid_cfg.y_start &
1646  			IPU3_UAPI_GRID_START_MASK,
1647  		.grid_height_per_slice =
1648  			af_config->stripes[0].grid_cfg.height_per_slice,
1649  		.max_op = IMGU_ABI_AF_MAX_OPERATIONS,
1650  		.max_tr = IMGU_ABI_AF_MAX_TRANSFERS,
1651  		.acc_enable = bi->info.isp.sp.enable.af,
1652  	};
1653  
1654  	return imgu_css_acc_process_lines(&pl, to->ops, to->process_lines_data,
1655  					  NULL);
1656  }
1657  
1658  static int
imgu_css_awb_fr_ops_calc(struct imgu_css * css,unsigned int pipe,struct imgu_abi_awb_fr_config * awb_fr_config)1659  imgu_css_awb_fr_ops_calc(struct imgu_css *css, unsigned int pipe,
1660  			 struct imgu_abi_awb_fr_config *awb_fr_config)
1661  {
1662  	struct imgu_abi_awb_fr_intra_frame_operations_data *to =
1663  		&awb_fr_config->operations_data;
1664  	struct imgu_css_pipe *css_pipe = &css->pipes[pipe];
1665  	struct imgu_fw_info *bi =
1666  		&css->fwp->binary_header[css_pipe->bindex];
1667  	struct process_lines pl = {
1668  		.image_height = css_pipe->rect[IPU3_CSS_RECT_BDS].height,
1669  		.grid_height = awb_fr_config->config.grid_cfg.height,
1670  		.block_height =
1671  			1 << awb_fr_config->config.grid_cfg.block_height_log2,
1672  		.y_start = awb_fr_config->config.grid_cfg.y_start &
1673  			IPU3_UAPI_GRID_START_MASK,
1674  		.grid_height_per_slice =
1675  			awb_fr_config->stripes[0].grid_cfg.height_per_slice,
1676  		.max_op = IMGU_ABI_AWB_FR_MAX_OPERATIONS,
1677  		.max_tr = IMGU_ABI_AWB_FR_MAX_PROCESS_LINES,
1678  		.acc_enable = bi->info.isp.sp.enable.awb_fr_acc,
1679  	};
1680  
1681  	return imgu_css_acc_process_lines(&pl, to->ops, to->process_lines_data,
1682  					  NULL);
1683  }
1684  
imgu_css_awb_ops_calc(struct imgu_css * css,unsigned int pipe,struct imgu_abi_awb_config * awb_config)1685  static int imgu_css_awb_ops_calc(struct imgu_css *css, unsigned int pipe,
1686  				 struct imgu_abi_awb_config *awb_config)
1687  {
1688  	struct imgu_abi_awb_intra_frame_operations_data *to =
1689  		&awb_config->operations_data;
1690  	struct imgu_css_pipe *css_pipe = &css->pipes[pipe];
1691  	struct imgu_fw_info *bi =
1692  		&css->fwp->binary_header[css_pipe->bindex];
1693  
1694  	struct process_lines pl = {
1695  		.image_height = css_pipe->rect[IPU3_CSS_RECT_BDS].height,
1696  		.grid_height = awb_config->config.grid.height,
1697  		.block_height =
1698  			1 << awb_config->config.grid.block_height_log2,
1699  		.y_start = awb_config->config.grid.y_start,
1700  		.grid_height_per_slice =
1701  			awb_config->stripes[0].grid.height_per_slice,
1702  		.max_op = IMGU_ABI_AWB_MAX_OPERATIONS,
1703  		.max_tr = IMGU_ABI_AWB_MAX_TRANSFERS,
1704  		.acc_enable = bi->info.isp.sp.enable.awb_acc,
1705  	};
1706  
1707  	return imgu_css_acc_process_lines(&pl, to->ops, to->process_lines_data,
1708  					  to->transfer_data);
1709  }
1710  
imgu_css_grid_end(u16 start,u8 width,u8 block_width_log2)1711  static u16 imgu_css_grid_end(u16 start, u8 width, u8 block_width_log2)
1712  {
1713  	return (start & IPU3_UAPI_GRID_START_MASK) +
1714  		(width << block_width_log2) - 1;
1715  }
1716  
imgu_css_grid_end_calc(struct ipu3_uapi_grid_config * grid_cfg)1717  static void imgu_css_grid_end_calc(struct ipu3_uapi_grid_config *grid_cfg)
1718  {
1719  	grid_cfg->x_end = imgu_css_grid_end(grid_cfg->x_start, grid_cfg->width,
1720  					    grid_cfg->block_width_log2);
1721  	grid_cfg->y_end = imgu_css_grid_end(grid_cfg->y_start, grid_cfg->height,
1722  					    grid_cfg->block_height_log2);
1723  }
1724  
1725  /****************** config computation *****************************/
1726  
imgu_css_cfg_acc_stripe(struct imgu_css * css,unsigned int pipe,struct imgu_abi_acc_param * acc)1727  static int imgu_css_cfg_acc_stripe(struct imgu_css *css, unsigned int pipe,
1728  				   struct imgu_abi_acc_param *acc)
1729  {
1730  	struct imgu_css_pipe *css_pipe = &css->pipes[pipe];
1731  	const struct imgu_fw_info *bi =
1732  		&css->fwp->binary_header[css_pipe->bindex];
1733  	struct imgu_css_scaler_info scaler_luma, scaler_chroma;
1734  	const unsigned int stripes = bi->info.isp.sp.iterator.num_stripes;
1735  	const unsigned int f = IPU3_UAPI_ISP_VEC_ELEMS * 2;
1736  	unsigned int bds_ds, i;
1737  
1738  	memset(acc, 0, sizeof(*acc));
1739  
1740  	/* 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  
imgu_css_cfg_acc_dvs(struct imgu_css * css,struct imgu_abi_acc_param * acc,unsigned int pipe)1899  static void imgu_css_cfg_acc_dvs(struct imgu_css *css,
1900  				 struct imgu_abi_acc_param *acc,
1901  				 unsigned int pipe)
1902  {
1903  	unsigned int i;
1904  	struct imgu_css_pipe *css_pipe = &css->pipes[pipe];
1905  
1906  	/* 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  
acc_bds_per_stripe_data(struct imgu_css * css,struct imgu_abi_acc_param * acc,const int i,unsigned int pipe)1918  static void acc_bds_per_stripe_data(struct imgu_css *css,
1919  				    struct imgu_abi_acc_param *acc,
1920  				    const int i, unsigned int pipe)
1921  {
1922  	struct imgu_css_pipe *css_pipe = &css->pipes[pipe];
1923  
1924  	acc->bds.per_stripe.aligned_data[i].data.crop.hor_crop_en = 0;
1925  	acc->bds.per_stripe.aligned_data[i].data.crop.hor_crop_start = 0;
1926  	acc->bds.per_stripe.aligned_data[i].data.crop.hor_crop_end = 0;
1927  	acc->bds.per_stripe.aligned_data[i].data.hor_ctrl0 =
1928  		acc->bds.hor.hor_ctrl0;
1929  	acc->bds.per_stripe.aligned_data[i].data.hor_ctrl0.out_frame_width =
1930  		acc->stripe.down_scaled_stripes[i].width;
1931  	acc->bds.per_stripe.aligned_data[i].data.ver_ctrl1.out_frame_width =
1932  		acc->stripe.down_scaled_stripes[i].width;
1933  	acc->bds.per_stripe.aligned_data[i].data.ver_ctrl1.out_frame_height =
1934  		css_pipe->rect[IPU3_CSS_RECT_BDS].height;
1935  }
1936  
1937  /*
1938   * 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   */
imgu_css_cfg_acc(struct imgu_css * css,unsigned int pipe,struct ipu3_uapi_flags * use,struct imgu_abi_acc_param * acc,struct imgu_abi_acc_param * acc_old,struct ipu3_uapi_acc_param * acc_user)1943  int imgu_css_cfg_acc(struct imgu_css *css, unsigned int pipe,
1944  		     struct ipu3_uapi_flags *use,
1945  		     struct imgu_abi_acc_param *acc,
1946  		     struct imgu_abi_acc_param *acc_old,
1947  		     struct ipu3_uapi_acc_param *acc_user)
1948  {
1949  	struct imgu_css_pipe *css_pipe = &css->pipes[pipe];
1950  	const struct imgu_fw_info *bi =
1951  		&css->fwp->binary_header[css_pipe->bindex];
1952  	const unsigned int stripes = bi->info.isp.sp.iterator.num_stripes;
1953  	const unsigned int tnr_frame_width =
1954  		acc->stripe.bds_aligned_frame_width;
1955  	const unsigned int min_overlap = 10;
1956  	const struct v4l2_pix_format_mplane *pixm =
1957  		&css_pipe->queue[IPU3_CSS_QUEUE_IN].fmt.mpix;
1958  	const struct imgu_css_bds_config *cfg_bds;
1959  	struct imgu_abi_input_feeder_data *feeder_data;
1960  
1961  	unsigned int bds_ds, ofs_x, ofs_y, i, width, height;
1962  	u8 b_w_log2; /* 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   */
imgu_css_cfg_copy(struct imgu_css * css,unsigned int pipe,bool use_user,void * user_setting,void * old_binary_params,void * new_binary_params,enum imgu_abi_memories m,struct imgu_fw_isp_parameter * par,size_t par_size)2704  static void *imgu_css_cfg_copy(struct imgu_css *css,
2705  			       unsigned int pipe, bool use_user,
2706  			       void *user_setting, void *old_binary_params,
2707  			       void *new_binary_params,
2708  			       enum imgu_abi_memories m,
2709  			       struct imgu_fw_isp_parameter *par,
2710  			       size_t par_size)
2711  {
2712  	const enum imgu_abi_param_class c = IMGU_ABI_PARAM_CLASS_PARAM;
2713  	void *new_setting, *old_setting;
2714  
2715  	new_setting = imgu_css_fw_pipeline_params(css, pipe, c, m, par,
2716  						  par_size, new_binary_params);
2717  	if (!new_setting)
2718  		return ERR_PTR(-EPROTO);	/* 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   */
imgu_css_cfg_vmem0(struct imgu_css * css,unsigned int pipe,struct ipu3_uapi_flags * use,void * vmem0,void * vmem0_old,struct ipu3_uapi_params * user)2741  int imgu_css_cfg_vmem0(struct imgu_css *css, unsigned int pipe,
2742  		       struct ipu3_uapi_flags *use,
2743  		       void *vmem0, void *vmem0_old,
2744  		       struct ipu3_uapi_params *user)
2745  {
2746  	const struct imgu_fw_info *bi =
2747  		&css->fwp->binary_header[css->pipes[pipe].bindex];
2748  	struct imgu_fw_param_memory_offsets *pofs = (void *)css->fwp +
2749  		bi->blob.memory_offsets.offsets[IMGU_ABI_PARAM_CLASS_PARAM];
2750  	struct ipu3_uapi_isp_lin_vmem_params *lin_vmem = NULL;
2751  	struct ipu3_uapi_isp_tnr3_vmem_params *tnr_vmem = NULL;
2752  	struct ipu3_uapi_isp_xnr3_vmem_params *xnr_vmem = NULL;
2753  	const enum imgu_abi_param_class c = IMGU_ABI_PARAM_CLASS_PARAM;
2754  	const enum imgu_abi_memories m = IMGU_ABI_MEM_ISP_VMEM0;
2755  	unsigned int i;
2756  
2757  	/* 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   */
imgu_css_cfg_dmem0(struct imgu_css * css,unsigned int pipe,struct ipu3_uapi_flags * use,void * dmem0,void * dmem0_old,struct ipu3_uapi_params * user)2820  int imgu_css_cfg_dmem0(struct imgu_css *css, unsigned int pipe,
2821  		       struct ipu3_uapi_flags *use,
2822  		       void *dmem0, void *dmem0_old,
2823  		       struct ipu3_uapi_params *user)
2824  {
2825  	struct imgu_css_pipe *css_pipe = &css->pipes[pipe];
2826  	const struct imgu_fw_info *bi =
2827  		&css->fwp->binary_header[css_pipe->bindex];
2828  	struct imgu_fw_param_memory_offsets *pofs = (void *)css->fwp +
2829  		bi->blob.memory_offsets.offsets[IMGU_ABI_PARAM_CLASS_PARAM];
2830  
2831  	struct ipu3_uapi_isp_tnr3_params *tnr_dmem = NULL;
2832  	struct ipu3_uapi_isp_xnr3_params *xnr_dmem;
2833  
2834  	const enum imgu_abi_param_class c = IMGU_ABI_PARAM_CLASS_PARAM;
2835  	const enum imgu_abi_memories m = IMGU_ABI_MEM_ISP_DMEM0;
2836  
2837  	/* 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 */
imgu_css_cfg_gdc_table(struct imgu_abi_gdc_warp_param * gdc,int frame_in_x,int frame_in_y,int frame_out_x,int frame_out_y,int env_w,int env_h)2872  void imgu_css_cfg_gdc_table(struct imgu_abi_gdc_warp_param *gdc,
2873  			    int frame_in_x, int frame_in_y,
2874  			    int frame_out_x, int frame_out_y,
2875  			    int env_w, int env_h)
2876  {
2877  	static const unsigned int FRAC_BITS = IMGU_ABI_GDC_FRAC_BITS;
2878  	static const unsigned int XMEM_ALIGN = 1 << 4;
2879  	const unsigned int XMEM_ALIGN_MASK = ~(XMEM_ALIGN - 1);
2880  	static const unsigned int BCI_ENV = 4;
2881  	static const unsigned int BYP = 2;	/* 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  }
2960