2 * Support for Intel Camera Imaging ISP subsystem.
3 * Copyright (c) 2015, Intel Corporation.
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 #include "ia_css_types.h"
16 #include "sh_css_defs.h"
17 #ifndef IA_CSS_NO_DEBUG
18 #include "ia_css_debug.h"
20 #include "sh_css_frac.h"
21 #include "assert_support.h"
23 #include "bh/bh_2/ia_css_bh.host.h"
24 #include "ia_css_s3a.host.h"
26 const struct ia_css_3a_config default_3a_config = {
33 {-3344, -6104, -19143, 19143, 6104, 3344, 0},
34 {1027, 0, -9219, 16384, -9219, 1027, 0}
37 static unsigned int s3a_raw_bit_depth;
40 ia_css_s3a_configure(unsigned int raw_bit_depth)
42 s3a_raw_bit_depth = raw_bit_depth;
47 struct sh_css_isp_ae_params *to,
48 const struct ia_css_3a_config *from,
52 /* coefficients to calculate Y */
54 uDIGIT_FITTING(from->ae_y_coef_r, 16, SH_CSS_AE_YCOEF_SHIFT);
56 uDIGIT_FITTING(from->ae_y_coef_g, 16, SH_CSS_AE_YCOEF_SHIFT);
58 uDIGIT_FITTING(from->ae_y_coef_b, 16, SH_CSS_AE_YCOEF_SHIFT);
63 struct sh_css_isp_awb_params *to,
64 const struct ia_css_3a_config *from,
70 uDIGIT_FITTING(from->awb_lg_high_raw, 16, s3a_raw_bit_depth);
72 uDIGIT_FITTING(from->awb_lg_low, 16, SH_CSS_BAYER_BITS);
74 uDIGIT_FITTING(from->awb_lg_high, 16, SH_CSS_BAYER_BITS);
79 struct sh_css_isp_af_params *to,
80 const struct ia_css_3a_config *from,
86 /* af fir coefficients */
87 for (i = 0; i < 7; ++i) {
89 sDIGIT_FITTING(from->af_fir1_coef[i], 15,
92 sDIGIT_FITTING(from->af_fir2_coef[i], 15,
99 struct sh_css_isp_s3a_params *to,
100 const struct ia_css_3a_config *from,
105 ia_css_ae_encode(&to->ae, from, sizeof(to->ae));
106 ia_css_awb_encode(&to->awb, from, sizeof(to->awb));
107 ia_css_af_encode(&to->af, from, sizeof(to->af));
114 const struct ia_css_pipeline_stage *stage,
115 struct ia_css_isp_parameters *params)
117 short dmem_offset = stage->binary->info->mem_offsets->dmem.s3a;
119 assert(params != NULL);
121 if (dmem_offset >= 0) {
122 ia_css_s3a_encode((struct sh_css_isp_s3a_params *)
123 &stage->isp_mem_params[IA_CSS_ISP_DMEM0].address[dmem_offset],
124 ¶ms->s3a_config);
125 ia_css_bh_encode((struct sh_css_isp_bh_params *)
126 &stage->isp_mem_params[IA_CSS_ISP_DMEM0].address[dmem_offset],
127 ¶ms->s3a_config);
128 params->isp_params_changed = true;
129 params->isp_mem_params_changed[pipe_id][stage->stage_num][IA_CSS_ISP_DMEM0] = true;
132 params->isp_params_changed = true;
136 #ifndef IA_CSS_NO_DEBUG
139 const struct sh_css_isp_ae_params *ae,
143 ia_css_debug_dtrace(level, "\t%-32s = %d\n",
144 "ae_y_coef_r", ae->y_coef_r);
145 ia_css_debug_dtrace(level, "\t%-32s = %d\n",
146 "ae_y_coef_g", ae->y_coef_g);
147 ia_css_debug_dtrace(level, "\t%-32s = %d\n",
148 "ae_y_coef_b", ae->y_coef_b);
153 const struct sh_css_isp_awb_params *awb,
156 ia_css_debug_dtrace(level, "\t%-32s = %d\n",
157 "awb_lg_high_raw", awb->lg_high_raw);
158 ia_css_debug_dtrace(level, "\t%-32s = %d\n",
159 "awb_lg_low", awb->lg_low);
160 ia_css_debug_dtrace(level, "\t%-32s = %d\n",
161 "awb_lg_high", awb->lg_high);
166 const struct sh_css_isp_af_params *af,
169 ia_css_debug_dtrace(level, "\t%-32s = %d\n",
170 "af_fir1[0]", af->fir1[0]);
171 ia_css_debug_dtrace(level, "\t%-32s = %d\n",
172 "af_fir1[1]", af->fir1[1]);
173 ia_css_debug_dtrace(level, "\t%-32s = %d\n",
174 "af_fir1[2]", af->fir1[2]);
175 ia_css_debug_dtrace(level, "\t%-32s = %d\n",
176 "af_fir1[3]", af->fir1[3]);
177 ia_css_debug_dtrace(level, "\t%-32s = %d\n",
178 "af_fir1[4]", af->fir1[4]);
179 ia_css_debug_dtrace(level, "\t%-32s = %d\n",
180 "af_fir1[5]", af->fir1[5]);
181 ia_css_debug_dtrace(level, "\t%-32s = %d\n",
182 "af_fir1[6]", af->fir1[6]);
183 ia_css_debug_dtrace(level, "\t%-32s = %d\n",
184 "af_fir2[0]", af->fir2[0]);
185 ia_css_debug_dtrace(level, "\t%-32s = %d\n",
186 "af_fir2[1]", af->fir2[1]);
187 ia_css_debug_dtrace(level, "\t%-32s = %d\n",
188 "af_fir2[2]", af->fir2[2]);
189 ia_css_debug_dtrace(level, "\t%-32s = %d\n",
190 "af_fir2[3]", af->fir2[3]);
191 ia_css_debug_dtrace(level, "\t%-32s = %d\n",
192 "af_fir2[4]", af->fir2[4]);
193 ia_css_debug_dtrace(level, "\t%-32s = %d\n",
194 "af_fir2[5]", af->fir2[5]);
195 ia_css_debug_dtrace(level, "\t%-32s = %d\n",
196 "af_fir2[6]", af->fir2[6]);
201 const struct sh_css_isp_s3a_params *s3a,
204 ia_css_debug_dtrace(level, "S3A Support:\n");
205 ia_css_ae_dump (&s3a->ae, level);
206 ia_css_awb_dump (&s3a->awb, level);
207 ia_css_af_dump (&s3a->af, level);
211 ia_css_s3a_debug_dtrace(
212 const struct ia_css_3a_config *config,
215 ia_css_debug_dtrace(level,
216 "config.ae_y_coef_r=%d, config.ae_y_coef_g=%d, "
217 "config.ae_y_coef_b=%d, config.awb_lg_high_raw=%d, "
218 "config.awb_lg_low=%d, config.awb_lg_high=%d\n",
219 config->ae_y_coef_r, config->ae_y_coef_g,
220 config->ae_y_coef_b, config->awb_lg_high_raw,
221 config->awb_lg_low, config->awb_lg_high);
226 ia_css_s3a_hmem_decode(
227 struct ia_css_3a_statistics *host_stats,
228 const struct ia_css_bh_table *hmem_buf)
230 #if defined(HAS_NO_HMEM)
234 struct ia_css_3a_rgby_output *out_ptr;
237 /* pixel counts(BQ) for 3A area */
241 assert(host_stats != NULL);
242 assert(host_stats->rgby_data != NULL);
243 assert(hmem_buf != NULL);
245 count_for_3a = host_stats->grid.width * host_stats->grid.height
246 * host_stats->grid.bqs_per_grid_cell
247 * host_stats->grid.bqs_per_grid_cell;
249 out_ptr = host_stats->rgby_data;
251 ia_css_bh_hmem_decode(out_ptr, hmem_buf);
253 /* Calculate sum of histogram of R,
254 which should not be less than count_for_3a */
256 for (i = 0; i < HMEM_UNIT_SIZE; i++) {
257 sum_r += out_ptr[i].r;
259 if (sum_r < count_for_3a) {
260 /* histogram is invalid */
264 /* Verify for sum of histogram of R/G/B/Y */
270 for (i = 0; i < HMEM_UNIT_SIZE; i++) {
271 sum_g += out_ptr[i].g;
272 sum_b += out_ptr[i].b;
273 sum_y += out_ptr[i].y;
275 if (sum_g != sum_r || sum_b != sum_r || sum_y != sum_r) {
276 /* histogram is invalid */
283 * Limit the histogram area only to 3A area.
284 * In DSP, the histogram of 0 is incremented for pixels
285 * which are outside of 3A area. That amount should be subtracted here.
286 * hist[0] = hist[0] - ((sum of all hist[]) - (pixel count for 3A area))
288 diff = sum_r - count_for_3a;
289 out_ptr[0].r -= diff;
290 out_ptr[0].g -= diff;
291 out_ptr[0].b -= diff;
292 out_ptr[0].y -= diff;
297 ia_css_s3a_dmem_decode(
298 struct ia_css_3a_statistics *host_stats,
299 const struct ia_css_3a_output *isp_stats)
301 int isp_width, host_width, height, i;
302 struct ia_css_3a_output *host_ptr;
304 assert(host_stats != NULL);
305 assert(host_stats->data != NULL);
306 assert(isp_stats != NULL);
308 isp_width = host_stats->grid.aligned_width;
309 host_width = host_stats->grid.width;
310 height = host_stats->grid.height;
311 host_ptr = host_stats->data;
313 /* Getting 3A statistics from DMEM does not involve any
314 * transformation (like the VMEM version), we just copy the data
315 * using a different output width. */
316 for (i = 0; i < height; i++) {
317 memcpy(host_ptr, isp_stats, host_width * sizeof(*host_ptr));
318 isp_stats += isp_width;
319 host_ptr += host_width;
323 /* MW: this is an ISP function */
324 STORAGE_CLASS_INLINE int
325 merge_hi_lo_14(unsigned short hi, unsigned short lo)
327 int val = (int) ((((unsigned int) hi << 14) & 0xfffc000) |
328 ((unsigned int) lo & 0x3fff));
333 ia_css_s3a_vmem_decode(
334 struct ia_css_3a_statistics *host_stats,
335 const uint16_t *isp_stats_hi,
336 const uint16_t *isp_stats_lo)
338 int out_width, out_height, chunk, rest, kmax, y, x, k, elm_start, elm, ofs;
339 const uint16_t *hi, *lo;
340 struct ia_css_3a_output *output;
342 assert(host_stats!= NULL);
343 assert(host_stats->data != NULL);
344 assert(isp_stats_hi != NULL);
345 assert(isp_stats_lo != NULL);
347 output = host_stats->data;
348 out_width = host_stats->grid.width;
349 out_height = host_stats->grid.height;
353 chunk = ISP_VEC_NELEMS >> host_stats->grid.deci_factor_log2;
354 chunk = max(chunk, 1);
356 for (y = 0; y < out_height; y++) {
357 elm_start = y * ISP_S3ATBL_HI_LO_STRIDE;
360 while (x < out_width) {
361 kmax = (rest > chunk) ? chunk : rest;
362 ofs = y * out_width + x;
363 elm = elm_start + x * sizeof(*output) / sizeof(int32_t);
364 for (k = 0; k < kmax; k++, elm++) {
365 output[ofs + k].ae_y = merge_hi_lo_14(
366 hi[elm + chunk * 0], lo[elm + chunk * 0]);
367 output[ofs + k].awb_cnt = merge_hi_lo_14(
368 hi[elm + chunk * 1], lo[elm + chunk * 1]);
369 output[ofs + k].awb_gr = merge_hi_lo_14(
370 hi[elm + chunk * 2], lo[elm + chunk * 2]);
371 output[ofs + k].awb_r = merge_hi_lo_14(
372 hi[elm + chunk * 3], lo[elm + chunk * 3]);
373 output[ofs + k].awb_b = merge_hi_lo_14(
374 hi[elm + chunk * 4], lo[elm + chunk * 4]);
375 output[ofs + k].awb_gb = merge_hi_lo_14(
376 hi[elm + chunk * 5], lo[elm + chunk * 5]);
377 output[ofs + k].af_hpf1 = merge_hi_lo_14(
378 hi[elm + chunk * 6], lo[elm + chunk * 6]);
379 output[ofs + k].af_hpf2 = merge_hi_lo_14(
380 hi[elm + chunk * 7], lo[elm + chunk * 7]);