1*f5fbb83fSMauro Carvalho Chehab // SPDX-License-Identifier: GPL-2.0
29d4fa1a1SMauro Carvalho Chehab /*
39d4fa1a1SMauro Carvalho Chehab  * Support for Intel Camera Imaging ISP subsystem.
49d4fa1a1SMauro Carvalho Chehab  * Copyright (c) 2015, Intel Corporation.
59d4fa1a1SMauro Carvalho Chehab  *
69d4fa1a1SMauro Carvalho Chehab  * This program is free software; you can redistribute it and/or modify it
79d4fa1a1SMauro Carvalho Chehab  * under the terms and conditions of the GNU General Public License,
89d4fa1a1SMauro Carvalho Chehab  * version 2, as published by the Free Software Foundation.
99d4fa1a1SMauro Carvalho Chehab  *
109d4fa1a1SMauro Carvalho Chehab  * This program is distributed in the hope it will be useful, but WITHOUT
119d4fa1a1SMauro Carvalho Chehab  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
129d4fa1a1SMauro Carvalho Chehab  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
139d4fa1a1SMauro Carvalho Chehab  * more details.
149d4fa1a1SMauro Carvalho Chehab  */
159d4fa1a1SMauro Carvalho Chehab 
169d4fa1a1SMauro Carvalho Chehab #include "ia_css_types.h"
179d4fa1a1SMauro Carvalho Chehab #include "sh_css_defs.h"
189d4fa1a1SMauro Carvalho Chehab #ifndef IA_CSS_NO_DEBUG
199d4fa1a1SMauro Carvalho Chehab #include "ia_css_debug.h"
209d4fa1a1SMauro Carvalho Chehab #endif
219d4fa1a1SMauro Carvalho Chehab #include "sh_css_frac.h"
229d4fa1a1SMauro Carvalho Chehab #include "assert_support.h"
239d4fa1a1SMauro Carvalho Chehab 
249d4fa1a1SMauro Carvalho Chehab #include "bh/bh_2/ia_css_bh.host.h"
259d4fa1a1SMauro Carvalho Chehab #include "ia_css_s3a.host.h"
269d4fa1a1SMauro Carvalho Chehab 
279d4fa1a1SMauro Carvalho Chehab const struct ia_css_3a_config default_3a_config = {
289d4fa1a1SMauro Carvalho Chehab 	25559,
299d4fa1a1SMauro Carvalho Chehab 	32768,
309d4fa1a1SMauro Carvalho Chehab 	7209,
319d4fa1a1SMauro Carvalho Chehab 	65535,
329d4fa1a1SMauro Carvalho Chehab 	0,
339d4fa1a1SMauro Carvalho Chehab 	65535,
349d4fa1a1SMauro Carvalho Chehab 	{-3344, -6104, -19143, 19143, 6104, 3344, 0},
359d4fa1a1SMauro Carvalho Chehab 	{1027, 0, -9219, 16384, -9219, 1027, 0}
369d4fa1a1SMauro Carvalho Chehab };
379d4fa1a1SMauro Carvalho Chehab 
389d4fa1a1SMauro Carvalho Chehab static unsigned int s3a_raw_bit_depth;
399d4fa1a1SMauro Carvalho Chehab 
409d4fa1a1SMauro Carvalho Chehab void
ia_css_s3a_configure(unsigned int raw_bit_depth)419d4fa1a1SMauro Carvalho Chehab ia_css_s3a_configure(unsigned int raw_bit_depth)
429d4fa1a1SMauro Carvalho Chehab {
439d4fa1a1SMauro Carvalho Chehab 	s3a_raw_bit_depth = raw_bit_depth;
449d4fa1a1SMauro Carvalho Chehab }
459d4fa1a1SMauro Carvalho Chehab 
469d4fa1a1SMauro Carvalho Chehab static void
ia_css_ae_encode(struct sh_css_isp_ae_params * to,const struct ia_css_3a_config * from,unsigned int size)479d4fa1a1SMauro Carvalho Chehab ia_css_ae_encode(
489d4fa1a1SMauro Carvalho Chehab     struct sh_css_isp_ae_params *to,
499d4fa1a1SMauro Carvalho Chehab     const struct ia_css_3a_config *from,
509d4fa1a1SMauro Carvalho Chehab     unsigned int size)
519d4fa1a1SMauro Carvalho Chehab {
529d4fa1a1SMauro Carvalho Chehab 	(void)size;
539d4fa1a1SMauro Carvalho Chehab 	/* coefficients to calculate Y */
549d4fa1a1SMauro Carvalho Chehab 	to->y_coef_r =
559d4fa1a1SMauro Carvalho Chehab 	    uDIGIT_FITTING(from->ae_y_coef_r, 16, SH_CSS_AE_YCOEF_SHIFT);
569d4fa1a1SMauro Carvalho Chehab 	to->y_coef_g =
579d4fa1a1SMauro Carvalho Chehab 	    uDIGIT_FITTING(from->ae_y_coef_g, 16, SH_CSS_AE_YCOEF_SHIFT);
589d4fa1a1SMauro Carvalho Chehab 	to->y_coef_b =
599d4fa1a1SMauro Carvalho Chehab 	    uDIGIT_FITTING(from->ae_y_coef_b, 16, SH_CSS_AE_YCOEF_SHIFT);
609d4fa1a1SMauro Carvalho Chehab }
619d4fa1a1SMauro Carvalho Chehab 
629d4fa1a1SMauro Carvalho Chehab static void
ia_css_awb_encode(struct sh_css_isp_awb_params * to,const struct ia_css_3a_config * from,unsigned int size)639d4fa1a1SMauro Carvalho Chehab ia_css_awb_encode(
649d4fa1a1SMauro Carvalho Chehab     struct sh_css_isp_awb_params *to,
659d4fa1a1SMauro Carvalho Chehab     const struct ia_css_3a_config *from,
669d4fa1a1SMauro Carvalho Chehab     unsigned int size)
679d4fa1a1SMauro Carvalho Chehab {
689d4fa1a1SMauro Carvalho Chehab 	(void)size;
699d4fa1a1SMauro Carvalho Chehab 	/* AWB level gate */
709d4fa1a1SMauro Carvalho Chehab 	to->lg_high_raw =
719d4fa1a1SMauro Carvalho Chehab 	    uDIGIT_FITTING(from->awb_lg_high_raw, 16, s3a_raw_bit_depth);
729d4fa1a1SMauro Carvalho Chehab 	to->lg_low =
739d4fa1a1SMauro Carvalho Chehab 	    uDIGIT_FITTING(from->awb_lg_low, 16, SH_CSS_BAYER_BITS);
749d4fa1a1SMauro Carvalho Chehab 	to->lg_high =
759d4fa1a1SMauro Carvalho Chehab 	    uDIGIT_FITTING(from->awb_lg_high, 16, SH_CSS_BAYER_BITS);
769d4fa1a1SMauro Carvalho Chehab }
779d4fa1a1SMauro Carvalho Chehab 
789d4fa1a1SMauro Carvalho Chehab static void
ia_css_af_encode(struct sh_css_isp_af_params * to,const struct ia_css_3a_config * from,unsigned int size)799d4fa1a1SMauro Carvalho Chehab ia_css_af_encode(
809d4fa1a1SMauro Carvalho Chehab     struct sh_css_isp_af_params *to,
819d4fa1a1SMauro Carvalho Chehab     const struct ia_css_3a_config *from,
829d4fa1a1SMauro Carvalho Chehab     unsigned int size)
839d4fa1a1SMauro Carvalho Chehab {
849d4fa1a1SMauro Carvalho Chehab 	unsigned int i;
859d4fa1a1SMauro Carvalho Chehab 	(void)size;
869d4fa1a1SMauro Carvalho Chehab 
879d4fa1a1SMauro Carvalho Chehab 	/* af fir coefficients */
889d4fa1a1SMauro Carvalho Chehab 	for (i = 0; i < 7; ++i) {
899d4fa1a1SMauro Carvalho Chehab 		to->fir1[i] =
909d4fa1a1SMauro Carvalho Chehab 		    sDIGIT_FITTING(from->af_fir1_coef[i], 15,
919d4fa1a1SMauro Carvalho Chehab 				   SH_CSS_AF_FIR_SHIFT);
929d4fa1a1SMauro Carvalho Chehab 		to->fir2[i] =
939d4fa1a1SMauro Carvalho Chehab 		    sDIGIT_FITTING(from->af_fir2_coef[i], 15,
949d4fa1a1SMauro Carvalho Chehab 				   SH_CSS_AF_FIR_SHIFT);
959d4fa1a1SMauro Carvalho Chehab 	}
969d4fa1a1SMauro Carvalho Chehab }
979d4fa1a1SMauro Carvalho Chehab 
989d4fa1a1SMauro Carvalho Chehab void
ia_css_s3a_encode(struct sh_css_isp_s3a_params * to,const struct ia_css_3a_config * from,unsigned int size)999d4fa1a1SMauro Carvalho Chehab ia_css_s3a_encode(
1009d4fa1a1SMauro Carvalho Chehab     struct sh_css_isp_s3a_params *to,
1019d4fa1a1SMauro Carvalho Chehab     const struct ia_css_3a_config *from,
1029d4fa1a1SMauro Carvalho Chehab     unsigned int size)
1039d4fa1a1SMauro Carvalho Chehab {
1049d4fa1a1SMauro Carvalho Chehab 	(void)size;
1059d4fa1a1SMauro Carvalho Chehab 
1069d4fa1a1SMauro Carvalho Chehab 	ia_css_ae_encode(&to->ae,   from, sizeof(to->ae));
1079d4fa1a1SMauro Carvalho Chehab 	ia_css_awb_encode(&to->awb, from, sizeof(to->awb));
1089d4fa1a1SMauro Carvalho Chehab 	ia_css_af_encode(&to->af,   from, sizeof(to->af));
1099d4fa1a1SMauro Carvalho Chehab }
1109d4fa1a1SMauro Carvalho Chehab 
1119d4fa1a1SMauro Carvalho Chehab #if 0
1129d4fa1a1SMauro Carvalho Chehab void
1139d4fa1a1SMauro Carvalho Chehab ia_css_process_s3a(
1149d4fa1a1SMauro Carvalho Chehab     unsigned int pipe_id,
1159d4fa1a1SMauro Carvalho Chehab     const struct ia_css_pipeline_stage *stage,
1169d4fa1a1SMauro Carvalho Chehab     struct ia_css_isp_parameters *params)
1179d4fa1a1SMauro Carvalho Chehab {
1189d4fa1a1SMauro Carvalho Chehab 	short dmem_offset = stage->binary->info->mem_offsets->dmem.s3a;
1199d4fa1a1SMauro Carvalho Chehab 
1209d4fa1a1SMauro Carvalho Chehab 	assert(params);
1219d4fa1a1SMauro Carvalho Chehab 
1229d4fa1a1SMauro Carvalho Chehab 	if (dmem_offset >= 0) {
1239d4fa1a1SMauro Carvalho Chehab 		ia_css_s3a_encode((struct sh_css_isp_s3a_params *)
1249d4fa1a1SMauro Carvalho Chehab 				  &stage->isp_mem_params[IA_CSS_ISP_DMEM0].address[dmem_offset],
1259d4fa1a1SMauro Carvalho Chehab 				  &params->s3a_config);
1269d4fa1a1SMauro Carvalho Chehab 		ia_css_bh_encode((struct sh_css_isp_bh_params *)
1279d4fa1a1SMauro Carvalho Chehab 				 &stage->isp_mem_params[IA_CSS_ISP_DMEM0].address[dmem_offset],
1289d4fa1a1SMauro Carvalho Chehab 				 &params->s3a_config);
1299d4fa1a1SMauro Carvalho Chehab 		params->isp_params_changed = true;
1309d4fa1a1SMauro Carvalho Chehab 		params->isp_mem_params_changed[pipe_id][stage->stage_num][IA_CSS_ISP_DMEM0] =
1319d4fa1a1SMauro Carvalho Chehab 		    true;
1329d4fa1a1SMauro Carvalho Chehab 	}
1339d4fa1a1SMauro Carvalho Chehab 
1349d4fa1a1SMauro Carvalho Chehab 	params->isp_params_changed = true;
1359d4fa1a1SMauro Carvalho Chehab }
1369d4fa1a1SMauro Carvalho Chehab #endif
1379d4fa1a1SMauro Carvalho Chehab 
1389d4fa1a1SMauro Carvalho Chehab #ifndef IA_CSS_NO_DEBUG
1399d4fa1a1SMauro Carvalho Chehab void
ia_css_ae_dump(const struct sh_css_isp_ae_params * ae,unsigned int level)1409d4fa1a1SMauro Carvalho Chehab ia_css_ae_dump(
1419d4fa1a1SMauro Carvalho Chehab     const struct sh_css_isp_ae_params *ae,
1429d4fa1a1SMauro Carvalho Chehab     unsigned int level)
1439d4fa1a1SMauro Carvalho Chehab {
1449d4fa1a1SMauro Carvalho Chehab 	if (!ae) return;
1459d4fa1a1SMauro Carvalho Chehab 	ia_css_debug_dtrace(level, "\t%-32s = %d\n",
1469d4fa1a1SMauro Carvalho Chehab 			    "ae_y_coef_r", ae->y_coef_r);
1479d4fa1a1SMauro Carvalho Chehab 	ia_css_debug_dtrace(level, "\t%-32s = %d\n",
1489d4fa1a1SMauro Carvalho Chehab 			    "ae_y_coef_g", ae->y_coef_g);
1499d4fa1a1SMauro Carvalho Chehab 	ia_css_debug_dtrace(level, "\t%-32s = %d\n",
1509d4fa1a1SMauro Carvalho Chehab 			    "ae_y_coef_b", ae->y_coef_b);
1519d4fa1a1SMauro Carvalho Chehab }
1529d4fa1a1SMauro Carvalho Chehab 
1539d4fa1a1SMauro Carvalho Chehab void
ia_css_awb_dump(const struct sh_css_isp_awb_params * awb,unsigned int level)1549d4fa1a1SMauro Carvalho Chehab ia_css_awb_dump(
1559d4fa1a1SMauro Carvalho Chehab     const struct sh_css_isp_awb_params *awb,
1569d4fa1a1SMauro Carvalho Chehab     unsigned int level)
1579d4fa1a1SMauro Carvalho Chehab {
1589d4fa1a1SMauro Carvalho Chehab 	ia_css_debug_dtrace(level, "\t%-32s = %d\n",
1599d4fa1a1SMauro Carvalho Chehab 			    "awb_lg_high_raw", awb->lg_high_raw);
1609d4fa1a1SMauro Carvalho Chehab 	ia_css_debug_dtrace(level, "\t%-32s = %d\n",
1619d4fa1a1SMauro Carvalho Chehab 			    "awb_lg_low", awb->lg_low);
1629d4fa1a1SMauro Carvalho Chehab 	ia_css_debug_dtrace(level, "\t%-32s = %d\n",
1639d4fa1a1SMauro Carvalho Chehab 			    "awb_lg_high", awb->lg_high);
1649d4fa1a1SMauro Carvalho Chehab }
1659d4fa1a1SMauro Carvalho Chehab 
1669d4fa1a1SMauro Carvalho Chehab void
ia_css_af_dump(const struct sh_css_isp_af_params * af,unsigned int level)1679d4fa1a1SMauro Carvalho Chehab ia_css_af_dump(
1689d4fa1a1SMauro Carvalho Chehab     const struct sh_css_isp_af_params *af,
1699d4fa1a1SMauro Carvalho Chehab     unsigned int level)
1709d4fa1a1SMauro Carvalho Chehab {
1719d4fa1a1SMauro Carvalho Chehab 	ia_css_debug_dtrace(level, "\t%-32s = %d\n",
1729d4fa1a1SMauro Carvalho Chehab 			    "af_fir1[0]", af->fir1[0]);
1739d4fa1a1SMauro Carvalho Chehab 	ia_css_debug_dtrace(level, "\t%-32s = %d\n",
1749d4fa1a1SMauro Carvalho Chehab 			    "af_fir1[1]", af->fir1[1]);
1759d4fa1a1SMauro Carvalho Chehab 	ia_css_debug_dtrace(level, "\t%-32s = %d\n",
1769d4fa1a1SMauro Carvalho Chehab 			    "af_fir1[2]", af->fir1[2]);
1779d4fa1a1SMauro Carvalho Chehab 	ia_css_debug_dtrace(level, "\t%-32s = %d\n",
1789d4fa1a1SMauro Carvalho Chehab 			    "af_fir1[3]", af->fir1[3]);
1799d4fa1a1SMauro Carvalho Chehab 	ia_css_debug_dtrace(level, "\t%-32s = %d\n",
1809d4fa1a1SMauro Carvalho Chehab 			    "af_fir1[4]", af->fir1[4]);
1819d4fa1a1SMauro Carvalho Chehab 	ia_css_debug_dtrace(level, "\t%-32s = %d\n",
1829d4fa1a1SMauro Carvalho Chehab 			    "af_fir1[5]", af->fir1[5]);
1839d4fa1a1SMauro Carvalho Chehab 	ia_css_debug_dtrace(level, "\t%-32s = %d\n",
1849d4fa1a1SMauro Carvalho Chehab 			    "af_fir1[6]", af->fir1[6]);
1859d4fa1a1SMauro Carvalho Chehab 	ia_css_debug_dtrace(level, "\t%-32s = %d\n",
1869d4fa1a1SMauro Carvalho Chehab 			    "af_fir2[0]", af->fir2[0]);
1879d4fa1a1SMauro Carvalho Chehab 	ia_css_debug_dtrace(level, "\t%-32s = %d\n",
1889d4fa1a1SMauro Carvalho Chehab 			    "af_fir2[1]", af->fir2[1]);
1899d4fa1a1SMauro Carvalho Chehab 	ia_css_debug_dtrace(level, "\t%-32s = %d\n",
1909d4fa1a1SMauro Carvalho Chehab 			    "af_fir2[2]", af->fir2[2]);
1919d4fa1a1SMauro Carvalho Chehab 	ia_css_debug_dtrace(level, "\t%-32s = %d\n",
1929d4fa1a1SMauro Carvalho Chehab 			    "af_fir2[3]", af->fir2[3]);
1939d4fa1a1SMauro Carvalho Chehab 	ia_css_debug_dtrace(level, "\t%-32s = %d\n",
1949d4fa1a1SMauro Carvalho Chehab 			    "af_fir2[4]", af->fir2[4]);
1959d4fa1a1SMauro Carvalho Chehab 	ia_css_debug_dtrace(level, "\t%-32s = %d\n",
1969d4fa1a1SMauro Carvalho Chehab 			    "af_fir2[5]", af->fir2[5]);
1979d4fa1a1SMauro Carvalho Chehab 	ia_css_debug_dtrace(level, "\t%-32s = %d\n",
1989d4fa1a1SMauro Carvalho Chehab 			    "af_fir2[6]", af->fir2[6]);
1999d4fa1a1SMauro Carvalho Chehab }
2009d4fa1a1SMauro Carvalho Chehab 
2019d4fa1a1SMauro Carvalho Chehab void
ia_css_s3a_dump(const struct sh_css_isp_s3a_params * s3a,unsigned int level)2029d4fa1a1SMauro Carvalho Chehab ia_css_s3a_dump(
2039d4fa1a1SMauro Carvalho Chehab     const struct sh_css_isp_s3a_params *s3a,
2049d4fa1a1SMauro Carvalho Chehab     unsigned int level)
2059d4fa1a1SMauro Carvalho Chehab {
2069d4fa1a1SMauro Carvalho Chehab 	ia_css_debug_dtrace(level, "S3A Support:\n");
2079d4fa1a1SMauro Carvalho Chehab 	ia_css_ae_dump(&s3a->ae, level);
2089d4fa1a1SMauro Carvalho Chehab 	ia_css_awb_dump(&s3a->awb, level);
2099d4fa1a1SMauro Carvalho Chehab 	ia_css_af_dump(&s3a->af, level);
2109d4fa1a1SMauro Carvalho Chehab }
2119d4fa1a1SMauro Carvalho Chehab 
2129d4fa1a1SMauro Carvalho Chehab void
ia_css_s3a_debug_dtrace(const struct ia_css_3a_config * config,unsigned int level)2139d4fa1a1SMauro Carvalho Chehab ia_css_s3a_debug_dtrace(
2149d4fa1a1SMauro Carvalho Chehab     const struct ia_css_3a_config *config,
2159d4fa1a1SMauro Carvalho Chehab     unsigned int level)
2169d4fa1a1SMauro Carvalho Chehab {
2179d4fa1a1SMauro Carvalho Chehab 	ia_css_debug_dtrace(level,
2189d4fa1a1SMauro Carvalho Chehab 			    "config.ae_y_coef_r=%d, config.ae_y_coef_g=%d, config.ae_y_coef_b=%d, config.awb_lg_high_raw=%d, config.awb_lg_low=%d, config.awb_lg_high=%d\n",
2199d4fa1a1SMauro Carvalho Chehab 			    config->ae_y_coef_r, config->ae_y_coef_g,
2209d4fa1a1SMauro Carvalho Chehab 			    config->ae_y_coef_b, config->awb_lg_high_raw,
2219d4fa1a1SMauro Carvalho Chehab 			    config->awb_lg_low, config->awb_lg_high);
2229d4fa1a1SMauro Carvalho Chehab }
2239d4fa1a1SMauro Carvalho Chehab #endif
2249d4fa1a1SMauro Carvalho Chehab 
2259d4fa1a1SMauro Carvalho Chehab void
ia_css_s3a_hmem_decode(struct ia_css_3a_statistics * host_stats,const struct ia_css_bh_table * hmem_buf)2269d4fa1a1SMauro Carvalho Chehab ia_css_s3a_hmem_decode(
2279d4fa1a1SMauro Carvalho Chehab     struct ia_css_3a_statistics *host_stats,
2289d4fa1a1SMauro Carvalho Chehab     const struct ia_css_bh_table *hmem_buf)
2299d4fa1a1SMauro Carvalho Chehab {
2309d4fa1a1SMauro Carvalho Chehab 	struct ia_css_3a_rgby_output	*out_ptr;
2319d4fa1a1SMauro Carvalho Chehab 	int			i;
2329d4fa1a1SMauro Carvalho Chehab 
2339d4fa1a1SMauro Carvalho Chehab 	/* pixel counts(BQ) for 3A area */
2349d4fa1a1SMauro Carvalho Chehab 	int count_for_3a;
2359d4fa1a1SMauro Carvalho Chehab 	int sum_r, diff;
2369d4fa1a1SMauro Carvalho Chehab 
2379d4fa1a1SMauro Carvalho Chehab 	assert(host_stats);
2389d4fa1a1SMauro Carvalho Chehab 	assert(host_stats->rgby_data);
2399d4fa1a1SMauro Carvalho Chehab 	assert(hmem_buf);
2409d4fa1a1SMauro Carvalho Chehab 
2419d4fa1a1SMauro Carvalho Chehab 	count_for_3a = host_stats->grid.width * host_stats->grid.height
2429d4fa1a1SMauro Carvalho Chehab 		       * host_stats->grid.bqs_per_grid_cell
2439d4fa1a1SMauro Carvalho Chehab 		       * host_stats->grid.bqs_per_grid_cell;
2449d4fa1a1SMauro Carvalho Chehab 
2459d4fa1a1SMauro Carvalho Chehab 	out_ptr = host_stats->rgby_data;
2469d4fa1a1SMauro Carvalho Chehab 
2479d4fa1a1SMauro Carvalho Chehab 	ia_css_bh_hmem_decode(out_ptr, hmem_buf);
2489d4fa1a1SMauro Carvalho Chehab 
2499d4fa1a1SMauro Carvalho Chehab 	/* Calculate sum of histogram of R,
2509d4fa1a1SMauro Carvalho Chehab 	   which should not be less than count_for_3a */
2519d4fa1a1SMauro Carvalho Chehab 	sum_r = 0;
2529d4fa1a1SMauro Carvalho Chehab 	for (i = 0; i < HMEM_UNIT_SIZE; i++) {
2539d4fa1a1SMauro Carvalho Chehab 		sum_r += out_ptr[i].r;
2549d4fa1a1SMauro Carvalho Chehab 	}
2559d4fa1a1SMauro Carvalho Chehab 	if (sum_r < count_for_3a) {
2569d4fa1a1SMauro Carvalho Chehab 		/* histogram is invalid */
2579d4fa1a1SMauro Carvalho Chehab 		return;
2589d4fa1a1SMauro Carvalho Chehab 	}
2599d4fa1a1SMauro Carvalho Chehab 
2609d4fa1a1SMauro Carvalho Chehab 	/* Verify for sum of histogram of R/G/B/Y */
2619d4fa1a1SMauro Carvalho Chehab #if 0
2629d4fa1a1SMauro Carvalho Chehab 	{
2639d4fa1a1SMauro Carvalho Chehab 		int sum_g = 0;
2649d4fa1a1SMauro Carvalho Chehab 		int sum_b = 0;
2659d4fa1a1SMauro Carvalho Chehab 		int sum_y = 0;
2669d4fa1a1SMauro Carvalho Chehab 
2679d4fa1a1SMauro Carvalho Chehab 		for (i = 0; i < HMEM_UNIT_SIZE; i++) {
2689d4fa1a1SMauro Carvalho Chehab 			sum_g += out_ptr[i].g;
2699d4fa1a1SMauro Carvalho Chehab 			sum_b += out_ptr[i].b;
2709d4fa1a1SMauro Carvalho Chehab 			sum_y += out_ptr[i].y;
2719d4fa1a1SMauro Carvalho Chehab 		}
2729d4fa1a1SMauro Carvalho Chehab 		if (sum_g != sum_r || sum_b != sum_r || sum_y != sum_r) {
2739d4fa1a1SMauro Carvalho Chehab 			/* histogram is invalid */
2749d4fa1a1SMauro Carvalho Chehab 			return;
2759d4fa1a1SMauro Carvalho Chehab 		}
2769d4fa1a1SMauro Carvalho Chehab 	}
2779d4fa1a1SMauro Carvalho Chehab #endif
2789d4fa1a1SMauro Carvalho Chehab 
2799d4fa1a1SMauro Carvalho Chehab 	/*
2809d4fa1a1SMauro Carvalho Chehab 	 * Limit the histogram area only to 3A area.
2819d4fa1a1SMauro Carvalho Chehab 	 * In DSP, the histogram of 0 is incremented for pixels
2829d4fa1a1SMauro Carvalho Chehab 	 * which are outside of 3A area. That amount should be subtracted here.
2839d4fa1a1SMauro Carvalho Chehab 	 *   hist[0] = hist[0] - ((sum of all hist[]) - (pixel count for 3A area))
2849d4fa1a1SMauro Carvalho Chehab 	 */
2859d4fa1a1SMauro Carvalho Chehab 	diff = sum_r - count_for_3a;
2869d4fa1a1SMauro Carvalho Chehab 	out_ptr[0].r -= diff;
2879d4fa1a1SMauro Carvalho Chehab 	out_ptr[0].g -= diff;
2889d4fa1a1SMauro Carvalho Chehab 	out_ptr[0].b -= diff;
2899d4fa1a1SMauro Carvalho Chehab 	out_ptr[0].y -= diff;
2909d4fa1a1SMauro Carvalho Chehab }
2919d4fa1a1SMauro Carvalho Chehab 
2929d4fa1a1SMauro Carvalho Chehab void
ia_css_s3a_dmem_decode(struct ia_css_3a_statistics * host_stats,const struct ia_css_3a_output * isp_stats)2939d4fa1a1SMauro Carvalho Chehab ia_css_s3a_dmem_decode(
2949d4fa1a1SMauro Carvalho Chehab     struct ia_css_3a_statistics *host_stats,
2959d4fa1a1SMauro Carvalho Chehab     const struct ia_css_3a_output *isp_stats)
2969d4fa1a1SMauro Carvalho Chehab {
2979d4fa1a1SMauro Carvalho Chehab 	int isp_width, host_width, height, i;
2989d4fa1a1SMauro Carvalho Chehab 	struct ia_css_3a_output *host_ptr;
2999d4fa1a1SMauro Carvalho Chehab 
3009d4fa1a1SMauro Carvalho Chehab 	assert(host_stats);
3019d4fa1a1SMauro Carvalho Chehab 	assert(host_stats->data);
3029d4fa1a1SMauro Carvalho Chehab 	assert(isp_stats);
3039d4fa1a1SMauro Carvalho Chehab 
3049d4fa1a1SMauro Carvalho Chehab 	isp_width  = host_stats->grid.aligned_width;
3059d4fa1a1SMauro Carvalho Chehab 	host_width = host_stats->grid.width;
3069d4fa1a1SMauro Carvalho Chehab 	height     = host_stats->grid.height;
3079d4fa1a1SMauro Carvalho Chehab 	host_ptr   = host_stats->data;
3089d4fa1a1SMauro Carvalho Chehab 
3099d4fa1a1SMauro Carvalho Chehab 	/* Getting 3A statistics from DMEM does not involve any
3109d4fa1a1SMauro Carvalho Chehab 	 * transformation (like the VMEM version), we just copy the data
3119d4fa1a1SMauro Carvalho Chehab 	 * using a different output width. */
3129d4fa1a1SMauro Carvalho Chehab 	for (i = 0; i < height; i++) {
3139d4fa1a1SMauro Carvalho Chehab 		memcpy(host_ptr, isp_stats, host_width * sizeof(*host_ptr));
3149d4fa1a1SMauro Carvalho Chehab 		isp_stats += isp_width;
3159d4fa1a1SMauro Carvalho Chehab 		host_ptr += host_width;
3169d4fa1a1SMauro Carvalho Chehab 	}
3179d4fa1a1SMauro Carvalho Chehab }
3189d4fa1a1SMauro Carvalho Chehab 
3199d4fa1a1SMauro Carvalho Chehab /* MW: this is an ISP function */
3209d4fa1a1SMauro Carvalho Chehab static inline int
merge_hi_lo_14(unsigned short hi,unsigned short lo)3219d4fa1a1SMauro Carvalho Chehab merge_hi_lo_14(unsigned short hi, unsigned short lo)
3229d4fa1a1SMauro Carvalho Chehab {
3239d4fa1a1SMauro Carvalho Chehab 	int val = (int)((((unsigned int)hi << 14) & 0xfffc000) |
3249d4fa1a1SMauro Carvalho Chehab 			((unsigned int)lo & 0x3fff));
3259d4fa1a1SMauro Carvalho Chehab 	return val;
3269d4fa1a1SMauro Carvalho Chehab }
3279d4fa1a1SMauro Carvalho Chehab 
3289d4fa1a1SMauro Carvalho Chehab void
ia_css_s3a_vmem_decode(struct ia_css_3a_statistics * host_stats,const u16 * isp_stats_hi,const uint16_t * isp_stats_lo)3299d4fa1a1SMauro Carvalho Chehab ia_css_s3a_vmem_decode(
3309d4fa1a1SMauro Carvalho Chehab     struct ia_css_3a_statistics *host_stats,
3319d4fa1a1SMauro Carvalho Chehab     const u16 *isp_stats_hi,
3329d4fa1a1SMauro Carvalho Chehab     const uint16_t *isp_stats_lo)
3339d4fa1a1SMauro Carvalho Chehab {
3349d4fa1a1SMauro Carvalho Chehab 	int out_width, out_height, chunk, rest, kmax, y, x, k, elm_start, elm, ofs;
3359d4fa1a1SMauro Carvalho Chehab 	const u16 *hi, *lo;
3369d4fa1a1SMauro Carvalho Chehab 	struct ia_css_3a_output *output;
3379d4fa1a1SMauro Carvalho Chehab 
3389d4fa1a1SMauro Carvalho Chehab 	assert(host_stats);
3399d4fa1a1SMauro Carvalho Chehab 	assert(host_stats->data);
3409d4fa1a1SMauro Carvalho Chehab 	assert(isp_stats_hi);
3419d4fa1a1SMauro Carvalho Chehab 	assert(isp_stats_lo);
3429d4fa1a1SMauro Carvalho Chehab 
3439d4fa1a1SMauro Carvalho Chehab 	output = host_stats->data;
3449d4fa1a1SMauro Carvalho Chehab 	out_width  = host_stats->grid.width;
3459d4fa1a1SMauro Carvalho Chehab 	out_height = host_stats->grid.height;
3469d4fa1a1SMauro Carvalho Chehab 	hi = isp_stats_hi;
3479d4fa1a1SMauro Carvalho Chehab 	lo = isp_stats_lo;
3489d4fa1a1SMauro Carvalho Chehab 
3499d4fa1a1SMauro Carvalho Chehab 	chunk = ISP_VEC_NELEMS >> host_stats->grid.deci_factor_log2;
3509d4fa1a1SMauro Carvalho Chehab 	chunk = max(chunk, 1);
3519d4fa1a1SMauro Carvalho Chehab 
3529d4fa1a1SMauro Carvalho Chehab 	for (y = 0; y < out_height; y++) {
3539d4fa1a1SMauro Carvalho Chehab 		elm_start = y * ISP_S3ATBL_HI_LO_STRIDE;
3549d4fa1a1SMauro Carvalho Chehab 		rest = out_width;
3559d4fa1a1SMauro Carvalho Chehab 		x = 0;
3569d4fa1a1SMauro Carvalho Chehab 		while (x < out_width) {
3579d4fa1a1SMauro Carvalho Chehab 			kmax = (rest > chunk) ? chunk : rest;
3589d4fa1a1SMauro Carvalho Chehab 			ofs = y * out_width + x;
3599d4fa1a1SMauro Carvalho Chehab 			elm = elm_start + x * sizeof(*output) / sizeof(int32_t);
3609d4fa1a1SMauro Carvalho Chehab 			for (k = 0; k < kmax; k++, elm++) {
3619d4fa1a1SMauro Carvalho Chehab 				output[ofs + k].ae_y    = merge_hi_lo_14(
3629d4fa1a1SMauro Carvalho Chehab 							      hi[elm + chunk * 0], lo[elm + chunk * 0]);
3639d4fa1a1SMauro Carvalho Chehab 				output[ofs + k].awb_cnt = merge_hi_lo_14(
3649d4fa1a1SMauro Carvalho Chehab 							      hi[elm + chunk * 1], lo[elm + chunk * 1]);
3659d4fa1a1SMauro Carvalho Chehab 				output[ofs + k].awb_gr  = merge_hi_lo_14(
3669d4fa1a1SMauro Carvalho Chehab 							      hi[elm + chunk * 2], lo[elm + chunk * 2]);
3679d4fa1a1SMauro Carvalho Chehab 				output[ofs + k].awb_r   = merge_hi_lo_14(
3689d4fa1a1SMauro Carvalho Chehab 							      hi[elm + chunk * 3], lo[elm + chunk * 3]);
3699d4fa1a1SMauro Carvalho Chehab 				output[ofs + k].awb_b   = merge_hi_lo_14(
3709d4fa1a1SMauro Carvalho Chehab 							      hi[elm + chunk * 4], lo[elm + chunk * 4]);
3719d4fa1a1SMauro Carvalho Chehab 				output[ofs + k].awb_gb  = merge_hi_lo_14(
3729d4fa1a1SMauro Carvalho Chehab 							      hi[elm + chunk * 5], lo[elm + chunk * 5]);
3739d4fa1a1SMauro Carvalho Chehab 				output[ofs + k].af_hpf1 = merge_hi_lo_14(
3749d4fa1a1SMauro Carvalho Chehab 							      hi[elm + chunk * 6], lo[elm + chunk * 6]);
3759d4fa1a1SMauro Carvalho Chehab 				output[ofs + k].af_hpf2 = merge_hi_lo_14(
3769d4fa1a1SMauro Carvalho Chehab 							      hi[elm + chunk * 7], lo[elm + chunk * 7]);
3779d4fa1a1SMauro Carvalho Chehab 			}
3789d4fa1a1SMauro Carvalho Chehab 			x += chunk;
3799d4fa1a1SMauro Carvalho Chehab 			rest -= chunk;
3809d4fa1a1SMauro Carvalho Chehab 		}
3819d4fa1a1SMauro Carvalho Chehab 	}
3829d4fa1a1SMauro Carvalho Chehab }
383