linux/drivers/staging/media/atomisp/pci/isp/kernels/s3a/s3a_1.0/ia_css_s3a.host.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Support for Intel Camera Imaging ISP subsystem.
   4 * Copyright (c) 2015, Intel Corporation.
   5 *
   6 * This program is free software; you can redistribute it and/or modify it
   7 * under the terms and conditions of the GNU General Public License,
   8 * version 2, as published by the Free Software Foundation.
   9 *
  10 * This program is distributed in the hope it will be useful, but WITHOUT
  11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  13 * more details.
  14 */
  15
  16#include "ia_css_types.h"
  17#include "sh_css_defs.h"
  18#ifndef IA_CSS_NO_DEBUG
  19#include "ia_css_debug.h"
  20#endif
  21#include "sh_css_frac.h"
  22#include "assert_support.h"
  23
  24#include "bh/bh_2/ia_css_bh.host.h"
  25#include "ia_css_s3a.host.h"
  26
  27const struct ia_css_3a_config default_3a_config = {
  28        25559,
  29        32768,
  30        7209,
  31        65535,
  32        0,
  33        65535,
  34        {-3344, -6104, -19143, 19143, 6104, 3344, 0},
  35        {1027, 0, -9219, 16384, -9219, 1027, 0}
  36};
  37
  38static unsigned int s3a_raw_bit_depth;
  39
  40void
  41ia_css_s3a_configure(unsigned int raw_bit_depth)
  42{
  43        s3a_raw_bit_depth = raw_bit_depth;
  44}
  45
  46static void
  47ia_css_ae_encode(
  48    struct sh_css_isp_ae_params *to,
  49    const struct ia_css_3a_config *from,
  50    unsigned int size)
  51{
  52        (void)size;
  53        /* coefficients to calculate Y */
  54        to->y_coef_r =
  55            uDIGIT_FITTING(from->ae_y_coef_r, 16, SH_CSS_AE_YCOEF_SHIFT);
  56        to->y_coef_g =
  57            uDIGIT_FITTING(from->ae_y_coef_g, 16, SH_CSS_AE_YCOEF_SHIFT);
  58        to->y_coef_b =
  59            uDIGIT_FITTING(from->ae_y_coef_b, 16, SH_CSS_AE_YCOEF_SHIFT);
  60}
  61
  62static void
  63ia_css_awb_encode(
  64    struct sh_css_isp_awb_params *to,
  65    const struct ia_css_3a_config *from,
  66    unsigned int size)
  67{
  68        (void)size;
  69        /* AWB level gate */
  70        to->lg_high_raw =
  71            uDIGIT_FITTING(from->awb_lg_high_raw, 16, s3a_raw_bit_depth);
  72        to->lg_low =
  73            uDIGIT_FITTING(from->awb_lg_low, 16, SH_CSS_BAYER_BITS);
  74        to->lg_high =
  75            uDIGIT_FITTING(from->awb_lg_high, 16, SH_CSS_BAYER_BITS);
  76}
  77
  78static void
  79ia_css_af_encode(
  80    struct sh_css_isp_af_params *to,
  81    const struct ia_css_3a_config *from,
  82    unsigned int size)
  83{
  84        unsigned int i;
  85        (void)size;
  86
  87        /* af fir coefficients */
  88        for (i = 0; i < 7; ++i) {
  89                to->fir1[i] =
  90                    sDIGIT_FITTING(from->af_fir1_coef[i], 15,
  91                                   SH_CSS_AF_FIR_SHIFT);
  92                to->fir2[i] =
  93                    sDIGIT_FITTING(from->af_fir2_coef[i], 15,
  94                                   SH_CSS_AF_FIR_SHIFT);
  95        }
  96}
  97
  98void
  99ia_css_s3a_encode(
 100    struct sh_css_isp_s3a_params *to,
 101    const struct ia_css_3a_config *from,
 102    unsigned int size)
 103{
 104        (void)size;
 105
 106        ia_css_ae_encode(&to->ae,   from, sizeof(to->ae));
 107        ia_css_awb_encode(&to->awb, from, sizeof(to->awb));
 108        ia_css_af_encode(&to->af,   from, sizeof(to->af));
 109}
 110
 111#if 0
 112void
 113ia_css_process_s3a(
 114    unsigned int pipe_id,
 115    const struct ia_css_pipeline_stage *stage,
 116    struct ia_css_isp_parameters *params)
 117{
 118        short dmem_offset = stage->binary->info->mem_offsets->dmem.s3a;
 119
 120        assert(params);
 121
 122        if (dmem_offset >= 0) {
 123                ia_css_s3a_encode((struct sh_css_isp_s3a_params *)
 124                                  &stage->isp_mem_params[IA_CSS_ISP_DMEM0].address[dmem_offset],
 125                                  &params->s3a_config);
 126                ia_css_bh_encode((struct sh_css_isp_bh_params *)
 127                                 &stage->isp_mem_params[IA_CSS_ISP_DMEM0].address[dmem_offset],
 128                                 &params->s3a_config);
 129                params->isp_params_changed = true;
 130                params->isp_mem_params_changed[pipe_id][stage->stage_num][IA_CSS_ISP_DMEM0] =
 131                    true;
 132        }
 133
 134        params->isp_params_changed = true;
 135}
 136#endif
 137
 138#ifndef IA_CSS_NO_DEBUG
 139void
 140ia_css_ae_dump(
 141    const struct sh_css_isp_ae_params *ae,
 142    unsigned int level)
 143{
 144        if (!ae) return;
 145        ia_css_debug_dtrace(level, "\t%-32s = %d\n",
 146                            "ae_y_coef_r", ae->y_coef_r);
 147        ia_css_debug_dtrace(level, "\t%-32s = %d\n",
 148                            "ae_y_coef_g", ae->y_coef_g);
 149        ia_css_debug_dtrace(level, "\t%-32s = %d\n",
 150                            "ae_y_coef_b", ae->y_coef_b);
 151}
 152
 153void
 154ia_css_awb_dump(
 155    const struct sh_css_isp_awb_params *awb,
 156    unsigned int level)
 157{
 158        ia_css_debug_dtrace(level, "\t%-32s = %d\n",
 159                            "awb_lg_high_raw", awb->lg_high_raw);
 160        ia_css_debug_dtrace(level, "\t%-32s = %d\n",
 161                            "awb_lg_low", awb->lg_low);
 162        ia_css_debug_dtrace(level, "\t%-32s = %d\n",
 163                            "awb_lg_high", awb->lg_high);
 164}
 165
 166void
 167ia_css_af_dump(
 168    const struct sh_css_isp_af_params *af,
 169    unsigned int level)
 170{
 171        ia_css_debug_dtrace(level, "\t%-32s = %d\n",
 172                            "af_fir1[0]", af->fir1[0]);
 173        ia_css_debug_dtrace(level, "\t%-32s = %d\n",
 174                            "af_fir1[1]", af->fir1[1]);
 175        ia_css_debug_dtrace(level, "\t%-32s = %d\n",
 176                            "af_fir1[2]", af->fir1[2]);
 177        ia_css_debug_dtrace(level, "\t%-32s = %d\n",
 178                            "af_fir1[3]", af->fir1[3]);
 179        ia_css_debug_dtrace(level, "\t%-32s = %d\n",
 180                            "af_fir1[4]", af->fir1[4]);
 181        ia_css_debug_dtrace(level, "\t%-32s = %d\n",
 182                            "af_fir1[5]", af->fir1[5]);
 183        ia_css_debug_dtrace(level, "\t%-32s = %d\n",
 184                            "af_fir1[6]", af->fir1[6]);
 185        ia_css_debug_dtrace(level, "\t%-32s = %d\n",
 186                            "af_fir2[0]", af->fir2[0]);
 187        ia_css_debug_dtrace(level, "\t%-32s = %d\n",
 188                            "af_fir2[1]", af->fir2[1]);
 189        ia_css_debug_dtrace(level, "\t%-32s = %d\n",
 190                            "af_fir2[2]", af->fir2[2]);
 191        ia_css_debug_dtrace(level, "\t%-32s = %d\n",
 192                            "af_fir2[3]", af->fir2[3]);
 193        ia_css_debug_dtrace(level, "\t%-32s = %d\n",
 194                            "af_fir2[4]", af->fir2[4]);
 195        ia_css_debug_dtrace(level, "\t%-32s = %d\n",
 196                            "af_fir2[5]", af->fir2[5]);
 197        ia_css_debug_dtrace(level, "\t%-32s = %d\n",
 198                            "af_fir2[6]", af->fir2[6]);
 199}
 200
 201void
 202ia_css_s3a_dump(
 203    const struct sh_css_isp_s3a_params *s3a,
 204    unsigned int level)
 205{
 206        ia_css_debug_dtrace(level, "S3A Support:\n");
 207        ia_css_ae_dump(&s3a->ae, level);
 208        ia_css_awb_dump(&s3a->awb, level);
 209        ia_css_af_dump(&s3a->af, level);
 210}
 211
 212void
 213ia_css_s3a_debug_dtrace(
 214    const struct ia_css_3a_config *config,
 215    unsigned int level)
 216{
 217        ia_css_debug_dtrace(level,
 218                            "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",
 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);
 222}
 223#endif
 224
 225void
 226ia_css_s3a_hmem_decode(
 227    struct ia_css_3a_statistics *host_stats,
 228    const struct ia_css_bh_table *hmem_buf)
 229{
 230#if defined(HAS_NO_HMEM)
 231        (void)host_stats;
 232        (void)hmem_buf;
 233#else
 234        struct ia_css_3a_rgby_output    *out_ptr;
 235        int                     i;
 236
 237        /* pixel counts(BQ) for 3A area */
 238        int count_for_3a;
 239        int sum_r, diff;
 240
 241        assert(host_stats);
 242        assert(host_stats->rgby_data);
 243        assert(hmem_buf);
 244
 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;
 248
 249        out_ptr = host_stats->rgby_data;
 250
 251        ia_css_bh_hmem_decode(out_ptr, hmem_buf);
 252
 253        /* Calculate sum of histogram of R,
 254           which should not be less than count_for_3a */
 255        sum_r = 0;
 256        for (i = 0; i < HMEM_UNIT_SIZE; i++) {
 257                sum_r += out_ptr[i].r;
 258        }
 259        if (sum_r < count_for_3a) {
 260                /* histogram is invalid */
 261                return;
 262        }
 263
 264        /* Verify for sum of histogram of R/G/B/Y */
 265#if 0
 266        {
 267                int sum_g = 0;
 268                int sum_b = 0;
 269                int sum_y = 0;
 270
 271                for (i = 0; i < HMEM_UNIT_SIZE; i++) {
 272                        sum_g += out_ptr[i].g;
 273                        sum_b += out_ptr[i].b;
 274                        sum_y += out_ptr[i].y;
 275                }
 276                if (sum_g != sum_r || sum_b != sum_r || sum_y != sum_r) {
 277                        /* histogram is invalid */
 278                        return;
 279                }
 280        }
 281#endif
 282
 283        /*
 284         * Limit the histogram area only to 3A area.
 285         * In DSP, the histogram of 0 is incremented for pixels
 286         * which are outside of 3A area. That amount should be subtracted here.
 287         *   hist[0] = hist[0] - ((sum of all hist[]) - (pixel count for 3A area))
 288         */
 289        diff = sum_r - count_for_3a;
 290        out_ptr[0].r -= diff;
 291        out_ptr[0].g -= diff;
 292        out_ptr[0].b -= diff;
 293        out_ptr[0].y -= diff;
 294#endif
 295}
 296
 297void
 298ia_css_s3a_dmem_decode(
 299    struct ia_css_3a_statistics *host_stats,
 300    const struct ia_css_3a_output *isp_stats)
 301{
 302        int isp_width, host_width, height, i;
 303        struct ia_css_3a_output *host_ptr;
 304
 305        assert(host_stats);
 306        assert(host_stats->data);
 307        assert(isp_stats);
 308
 309        isp_width  = host_stats->grid.aligned_width;
 310        host_width = host_stats->grid.width;
 311        height     = host_stats->grid.height;
 312        host_ptr   = host_stats->data;
 313
 314        /* Getting 3A statistics from DMEM does not involve any
 315         * transformation (like the VMEM version), we just copy the data
 316         * using a different output width. */
 317        for (i = 0; i < height; i++) {
 318                memcpy(host_ptr, isp_stats, host_width * sizeof(*host_ptr));
 319                isp_stats += isp_width;
 320                host_ptr += host_width;
 321        }
 322}
 323
 324/* MW: this is an ISP function */
 325static inline int
 326merge_hi_lo_14(unsigned short hi, unsigned short lo)
 327{
 328        int val = (int)((((unsigned int)hi << 14) & 0xfffc000) |
 329                        ((unsigned int)lo & 0x3fff));
 330        return val;
 331}
 332
 333void
 334ia_css_s3a_vmem_decode(
 335    struct ia_css_3a_statistics *host_stats,
 336    const u16 *isp_stats_hi,
 337    const uint16_t *isp_stats_lo)
 338{
 339        int out_width, out_height, chunk, rest, kmax, y, x, k, elm_start, elm, ofs;
 340        const u16 *hi, *lo;
 341        struct ia_css_3a_output *output;
 342
 343        assert(host_stats);
 344        assert(host_stats->data);
 345        assert(isp_stats_hi);
 346        assert(isp_stats_lo);
 347
 348        output = host_stats->data;
 349        out_width  = host_stats->grid.width;
 350        out_height = host_stats->grid.height;
 351        hi = isp_stats_hi;
 352        lo = isp_stats_lo;
 353
 354        chunk = ISP_VEC_NELEMS >> host_stats->grid.deci_factor_log2;
 355        chunk = max(chunk, 1);
 356
 357        for (y = 0; y < out_height; y++) {
 358                elm_start = y * ISP_S3ATBL_HI_LO_STRIDE;
 359                rest = out_width;
 360                x = 0;
 361                while (x < out_width) {
 362                        kmax = (rest > chunk) ? chunk : rest;
 363                        ofs = y * out_width + x;
 364                        elm = elm_start + x * sizeof(*output) / sizeof(int32_t);
 365                        for (k = 0; k < kmax; k++, elm++) {
 366                                output[ofs + k].ae_y    = merge_hi_lo_14(
 367                                                              hi[elm + chunk * 0], lo[elm + chunk * 0]);
 368                                output[ofs + k].awb_cnt = merge_hi_lo_14(
 369                                                              hi[elm + chunk * 1], lo[elm + chunk * 1]);
 370                                output[ofs + k].awb_gr  = merge_hi_lo_14(
 371                                                              hi[elm + chunk * 2], lo[elm + chunk * 2]);
 372                                output[ofs + k].awb_r   = merge_hi_lo_14(
 373                                                              hi[elm + chunk * 3], lo[elm + chunk * 3]);
 374                                output[ofs + k].awb_b   = merge_hi_lo_14(
 375                                                              hi[elm + chunk * 4], lo[elm + chunk * 4]);
 376                                output[ofs + k].awb_gb  = merge_hi_lo_14(
 377                                                              hi[elm + chunk * 5], lo[elm + chunk * 5]);
 378                                output[ofs + k].af_hpf1 = merge_hi_lo_14(
 379                                                              hi[elm + chunk * 6], lo[elm + chunk * 6]);
 380                                output[ofs + k].af_hpf2 = merge_hi_lo_14(
 381                                                              hi[elm + chunk * 7], lo[elm + chunk * 7]);
 382                        }
 383                        x += chunk;
 384                        rest -= chunk;
 385                }
 386        }
 387}
 388