linux/drivers/staging/media/atomisp/pci/isp/kernels/sdis/sdis_1.0/ia_css_sdis.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 "hmm.h"
  17
  18#include "assert_support.h"
  19#include "ia_css_debug.h"
  20#include "ia_css_sdis_types.h"
  21#include "sdis/common/ia_css_sdis_common.host.h"
  22#include "ia_css_sdis.host.h"
  23
  24const struct ia_css_dvs_coefficients default_sdis_config = {
  25        .grid = { 0, 0, 0, 0, 0, 0, 0, 0 },
  26        .hor_coefs = NULL,
  27        .ver_coefs = NULL
  28};
  29
  30static void
  31fill_row(short *private, const short *public, unsigned int width,
  32         unsigned int padding)
  33{
  34        assert((int)width >= 0);
  35        assert((int)padding >= 0);
  36        memcpy(private, public, width * sizeof(short));
  37        memset(&private[width], 0, padding * sizeof(short));
  38}
  39
  40void ia_css_sdis_horicoef_vmem_encode(
  41    struct sh_css_isp_sdis_hori_coef_tbl *to,
  42    const struct ia_css_dvs_coefficients *from,
  43    unsigned int size)
  44{
  45        unsigned int aligned_width = from->grid.aligned_width *
  46                                     from->grid.bqs_per_grid_cell;
  47        unsigned int width         = from->grid.num_hor_coefs;
  48        int      padding       = aligned_width - width;
  49        unsigned int stride        = size / IA_CSS_DVS_NUM_COEF_TYPES / sizeof(short);
  50        unsigned int total_bytes   = aligned_width * IA_CSS_DVS_NUM_COEF_TYPES * sizeof(
  51                                         short);
  52        short   *public        = from->hor_coefs;
  53        short   *private       = (short *)to;
  54        unsigned int type;
  55
  56        /* Copy the table, add padding */
  57        assert(padding >= 0);
  58        assert(total_bytes <= size);
  59        assert(size % (IA_CSS_DVS_NUM_COEF_TYPES * ISP_VEC_NELEMS * sizeof(
  60                           short)) == 0);
  61
  62        for (type = 0; type < IA_CSS_DVS_NUM_COEF_TYPES; type++) {
  63                fill_row(&private[type * stride], &public[type * width], width, padding);
  64        }
  65}
  66
  67void ia_css_sdis_vertcoef_vmem_encode(
  68    struct sh_css_isp_sdis_vert_coef_tbl *to,
  69    const struct ia_css_dvs_coefficients *from,
  70    unsigned int size)
  71{
  72        unsigned int aligned_height = from->grid.aligned_height *
  73                                      from->grid.bqs_per_grid_cell;
  74        unsigned int height         = from->grid.num_ver_coefs;
  75        int      padding        = aligned_height - height;
  76        unsigned int stride         = size / IA_CSS_DVS_NUM_COEF_TYPES / sizeof(short);
  77        unsigned int total_bytes    = aligned_height * IA_CSS_DVS_NUM_COEF_TYPES *
  78                                      sizeof(short);
  79        short   *public         = from->ver_coefs;
  80        short   *private        = (short *)to;
  81        unsigned int type;
  82
  83        /* Copy the table, add padding */
  84        assert(padding >= 0);
  85        assert(total_bytes <= size);
  86        assert(size % (IA_CSS_DVS_NUM_COEF_TYPES * ISP_VEC_NELEMS * sizeof(
  87                           short)) == 0);
  88
  89        for (type = 0; type < IA_CSS_DVS_NUM_COEF_TYPES; type++) {
  90                fill_row(&private[type * stride], &public[type * height], height, padding);
  91        }
  92}
  93
  94void ia_css_sdis_horiproj_encode(
  95    struct sh_css_isp_sdis_hori_proj_tbl *to,
  96    const struct ia_css_dvs_coefficients *from,
  97    unsigned int size)
  98{
  99        (void)to;
 100        (void)from;
 101        (void)size;
 102}
 103
 104void ia_css_sdis_vertproj_encode(
 105    struct sh_css_isp_sdis_vert_proj_tbl *to,
 106    const struct ia_css_dvs_coefficients *from,
 107    unsigned int size)
 108{
 109        (void)to;
 110        (void)from;
 111        (void)size;
 112}
 113
 114void ia_css_get_isp_dis_coefficients(
 115    struct ia_css_stream *stream,
 116    short *horizontal_coefficients,
 117    short *vertical_coefficients)
 118{
 119        struct ia_css_isp_parameters *params;
 120        unsigned int hor_num_isp, ver_num_isp;
 121        unsigned int hor_num_3a,  ver_num_3a;
 122        int i;
 123        struct ia_css_binary *dvs_binary;
 124
 125        IA_CSS_ENTER("void");
 126
 127        assert(horizontal_coefficients);
 128        assert(vertical_coefficients);
 129
 130        params = stream->isp_params_configs;
 131
 132        /* Only video pipe supports DVS */
 133        dvs_binary = ia_css_stream_get_dvs_binary(stream);
 134        if (!dvs_binary)
 135                return;
 136
 137        hor_num_isp = dvs_binary->dis.coef.pad.width;
 138        ver_num_isp = dvs_binary->dis.coef.pad.height;
 139        hor_num_3a  = dvs_binary->dis.coef.dim.width;
 140        ver_num_3a  = dvs_binary->dis.coef.dim.height;
 141
 142        for (i = 0; i < IA_CSS_DVS_NUM_COEF_TYPES; i++) {
 143                fill_row(&horizontal_coefficients[i * hor_num_isp],
 144                         &params->dvs_coefs.hor_coefs[i * hor_num_3a], hor_num_3a,
 145                         hor_num_isp - hor_num_3a);
 146        }
 147        for (i = 0; i < SH_CSS_DIS_VER_NUM_COEF_TYPES(dvs_binary); i++) {
 148                fill_row(&vertical_coefficients[i * ver_num_isp],
 149                         &params->dvs_coefs.ver_coefs[i * ver_num_3a], ver_num_3a,
 150                         ver_num_isp - ver_num_3a);
 151        }
 152
 153        IA_CSS_LEAVE("void");
 154}
 155
 156size_t
 157ia_css_sdis_hor_coef_tbl_bytes(
 158    const struct ia_css_binary *binary)
 159{
 160        if (binary->info->sp.pipeline.isp_pipe_version == 1)
 161                return sizeof(short) * IA_CSS_DVS_NUM_COEF_TYPES  * binary->dis.coef.pad.width;
 162        else
 163                return sizeof(short) * IA_CSS_DVS2_NUM_COEF_TYPES * binary->dis.coef.pad.width;
 164}
 165
 166size_t
 167ia_css_sdis_ver_coef_tbl_bytes(
 168    const struct ia_css_binary *binary)
 169{
 170        return sizeof(short) * SH_CSS_DIS_VER_NUM_COEF_TYPES(binary) *
 171               binary->dis.coef.pad.height;
 172}
 173
 174void
 175ia_css_sdis_init_info(
 176    struct ia_css_sdis_info *dis,
 177    unsigned int sc_3a_dis_width,
 178    unsigned int sc_3a_dis_padded_width,
 179    unsigned int sc_3a_dis_height,
 180    unsigned int isp_pipe_version,
 181    unsigned int enabled)
 182{
 183        if (!enabled) {
 184                *dis = (struct ia_css_sdis_info) { };
 185                return;
 186        }
 187
 188        dis->deci_factor_log2 = SH_CSS_DIS_DECI_FACTOR_LOG2;
 189
 190        dis->grid.dim.width  =
 191            _ISP_BQS(sc_3a_dis_width) >> SH_CSS_DIS_DECI_FACTOR_LOG2;
 192        dis->grid.dim.height =
 193            _ISP_BQS(sc_3a_dis_height) >> SH_CSS_DIS_DECI_FACTOR_LOG2;
 194        dis->grid.pad.width  =
 195            CEIL_SHIFT(_ISP_BQS(sc_3a_dis_padded_width), SH_CSS_DIS_DECI_FACTOR_LOG2);
 196        dis->grid.pad.height =
 197            CEIL_SHIFT(_ISP_BQS(sc_3a_dis_height), SH_CSS_DIS_DECI_FACTOR_LOG2);
 198
 199        dis->coef.dim.width  =
 200            (_ISP_BQS(sc_3a_dis_width)  >> SH_CSS_DIS_DECI_FACTOR_LOG2) <<
 201            SH_CSS_DIS_DECI_FACTOR_LOG2;
 202        dis->coef.dim.height =
 203            (_ISP_BQS(sc_3a_dis_height) >> SH_CSS_DIS_DECI_FACTOR_LOG2) <<
 204            SH_CSS_DIS_DECI_FACTOR_LOG2;
 205        dis->coef.pad.width  =
 206            __ISP_SDIS_HOR_COEF_NUM_VECS(sc_3a_dis_padded_width) * ISP_VEC_NELEMS;
 207        dis->coef.pad.height =
 208            __ISP_SDIS_VER_COEF_NUM_VECS(sc_3a_dis_height) * ISP_VEC_NELEMS;
 209        if (isp_pipe_version == 1) {
 210                dis->proj.dim.width  =
 211                    _ISP_BQS(sc_3a_dis_height) >> SH_CSS_DIS_DECI_FACTOR_LOG2;
 212                dis->proj.dim.height =
 213                    _ISP_BQS(sc_3a_dis_width)  >> SH_CSS_DIS_DECI_FACTOR_LOG2;
 214        } else {
 215                dis->proj.dim.width  =
 216                    (_ISP_BQS(sc_3a_dis_width)  >> SH_CSS_DIS_DECI_FACTOR_LOG2) *
 217                    (_ISP_BQS(sc_3a_dis_height) >> SH_CSS_DIS_DECI_FACTOR_LOG2);
 218                dis->proj.dim.height =
 219                    (_ISP_BQS(sc_3a_dis_width)  >> SH_CSS_DIS_DECI_FACTOR_LOG2) *
 220                    (_ISP_BQS(sc_3a_dis_height) >> SH_CSS_DIS_DECI_FACTOR_LOG2);
 221        }
 222        dis->proj.pad.width  =
 223            __ISP_SDIS_HOR_PROJ_NUM_ISP(sc_3a_dis_padded_width,
 224                                        sc_3a_dis_height,
 225                                        SH_CSS_DIS_DECI_FACTOR_LOG2,
 226                                        isp_pipe_version);
 227        dis->proj.pad.height =
 228            __ISP_SDIS_VER_PROJ_NUM_ISP(sc_3a_dis_padded_width,
 229                                        SH_CSS_DIS_DECI_FACTOR_LOG2);
 230}
 231
 232void ia_css_sdis_clear_coefficients(
 233    struct ia_css_dvs_coefficients *dvs_coefs)
 234{
 235        dvs_coefs->hor_coefs = NULL;
 236        dvs_coefs->ver_coefs = NULL;
 237}
 238
 239int
 240ia_css_get_dvs_statistics(
 241    struct ia_css_dvs_statistics               *host_stats,
 242    const struct ia_css_isp_dvs_statistics *isp_stats) {
 243        struct ia_css_isp_dvs_statistics_map *map;
 244        int ret = 0;
 245
 246        IA_CSS_ENTER("host_stats=%p, isp_stats=%p", host_stats, isp_stats);
 247
 248        assert(host_stats);
 249        assert(isp_stats);
 250
 251        map = ia_css_isp_dvs_statistics_map_allocate(isp_stats, NULL);
 252        if (map)
 253        {
 254                hmm_load(isp_stats->data_ptr, map->data_ptr, isp_stats->size);
 255                ia_css_translate_dvs_statistics(host_stats, map);
 256                ia_css_isp_dvs_statistics_map_free(map);
 257        } else
 258        {
 259                IA_CSS_ERROR("out of memory");
 260                ret = -ENOMEM;
 261        }
 262
 263        IA_CSS_LEAVE_ERR(ret);
 264        return ret;
 265}
 266
 267void
 268ia_css_translate_dvs_statistics(
 269    struct ia_css_dvs_statistics               *host_stats,
 270    const struct ia_css_isp_dvs_statistics_map *isp_stats)
 271{
 272        unsigned int hor_num_isp, ver_num_isp, hor_num_dvs, ver_num_dvs, i;
 273        s32 *hor_ptr_dvs, *ver_ptr_dvs, *hor_ptr_isp, *ver_ptr_isp;
 274
 275        assert(host_stats);
 276        assert(host_stats->hor_proj);
 277        assert(host_stats->ver_proj);
 278        assert(isp_stats);
 279        assert(isp_stats->hor_proj);
 280        assert(isp_stats->ver_proj);
 281
 282        IA_CSS_ENTER("hproj=%p, vproj=%p, haddr=%p, vaddr=%p",
 283                     host_stats->hor_proj, host_stats->ver_proj,
 284                     isp_stats->hor_proj, isp_stats->ver_proj);
 285
 286        hor_num_isp = host_stats->grid.aligned_height;
 287        ver_num_isp = host_stats->grid.aligned_width;
 288        hor_ptr_isp = isp_stats->hor_proj;
 289        ver_ptr_isp = isp_stats->ver_proj;
 290        hor_num_dvs = host_stats->grid.height;
 291        ver_num_dvs = host_stats->grid.width;
 292        hor_ptr_dvs = host_stats->hor_proj;
 293        ver_ptr_dvs = host_stats->ver_proj;
 294
 295        for (i = 0; i < IA_CSS_DVS_NUM_COEF_TYPES; i++) {
 296                memcpy(hor_ptr_dvs, hor_ptr_isp, hor_num_dvs * sizeof(int32_t));
 297                hor_ptr_isp += hor_num_isp;
 298                hor_ptr_dvs += hor_num_dvs;
 299
 300                memcpy(ver_ptr_dvs, ver_ptr_isp, ver_num_dvs * sizeof(int32_t));
 301                ver_ptr_isp += ver_num_isp;
 302                ver_ptr_dvs += ver_num_dvs;
 303        }
 304
 305        IA_CSS_LEAVE("void");
 306}
 307
 308struct ia_css_isp_dvs_statistics *
 309ia_css_isp_dvs_statistics_allocate(
 310    const struct ia_css_dvs_grid_info *grid)
 311{
 312        struct ia_css_isp_dvs_statistics *me;
 313        int hor_size, ver_size;
 314
 315        assert(grid);
 316
 317        IA_CSS_ENTER("grid=%p", grid);
 318
 319        if (!grid->enable)
 320                return NULL;
 321
 322        me = kvcalloc(1, sizeof(*me), GFP_KERNEL);
 323        if (!me)
 324                goto err;
 325
 326        hor_size = CEIL_MUL(sizeof(int) * IA_CSS_DVS_NUM_COEF_TYPES *
 327                            grid->aligned_height,
 328                            HIVE_ISP_DDR_WORD_BYTES);
 329        ver_size = CEIL_MUL(sizeof(int) * IA_CSS_DVS_NUM_COEF_TYPES *
 330                            grid->aligned_width,
 331                            HIVE_ISP_DDR_WORD_BYTES);
 332
 333        me->size = hor_size + ver_size;
 334        me->data_ptr = hmm_alloc(me->size, HMM_BO_PRIVATE, 0, NULL, 0);
 335        if (me->data_ptr == mmgr_NULL)
 336                goto err;
 337        me->hor_size = hor_size;
 338        me->hor_proj = me->data_ptr;
 339        me->ver_size = ver_size;
 340        me->ver_proj = me->data_ptr + hor_size;
 341
 342        IA_CSS_LEAVE("return=%p", me);
 343
 344        return me;
 345err:
 346        ia_css_isp_dvs_statistics_free(me);
 347
 348        IA_CSS_LEAVE("return=%p", NULL);
 349
 350        return NULL;
 351}
 352
 353struct ia_css_isp_dvs_statistics_map *
 354ia_css_isp_dvs_statistics_map_allocate(
 355    const struct ia_css_isp_dvs_statistics *isp_stats,
 356    void *data_ptr)
 357{
 358        struct ia_css_isp_dvs_statistics_map *me;
 359        /* Windows compiler does not like adding sizes to a void *
 360         * so we use a local char * instead. */
 361        char *base_ptr;
 362
 363        me = kvmalloc(sizeof(*me), GFP_KERNEL);
 364        if (!me) {
 365                IA_CSS_LOG("cannot allocate memory");
 366                goto err;
 367        }
 368
 369        me->data_ptr = data_ptr;
 370        me->data_allocated = !data_ptr;
 371
 372        if (!me->data_ptr) {
 373                me->data_ptr = kvmalloc(isp_stats->size, GFP_KERNEL);
 374                if (!me->data_ptr) {
 375                        IA_CSS_LOG("cannot allocate memory");
 376                        goto err;
 377                }
 378        }
 379        base_ptr = me->data_ptr;
 380
 381        me->size = isp_stats->size;
 382        /* GCC complains when we assign a char * to a void *, so these
 383         * casts are necessary unfortunately. */
 384        me->hor_proj = (void *)base_ptr;
 385        me->ver_proj = (void *)(base_ptr + isp_stats->hor_size);
 386
 387        return me;
 388err:
 389        kvfree(me);
 390        return NULL;
 391}
 392
 393void
 394ia_css_isp_dvs_statistics_map_free(struct ia_css_isp_dvs_statistics_map *me)
 395{
 396        if (me) {
 397                if (me->data_allocated)
 398                        kvfree(me->data_ptr);
 399                kvfree(me);
 400        }
 401}
 402
 403void
 404ia_css_isp_dvs_statistics_free(struct ia_css_isp_dvs_statistics *me)
 405{
 406        if (me) {
 407                hmm_free(me->data_ptr);
 408                kvfree(me);
 409        }
 410}
 411
 412void ia_css_sdis_horicoef_debug_dtrace(
 413    const struct ia_css_dvs_coefficients *config, unsigned int level)
 414{
 415        (void)config;
 416        (void)level;
 417}
 418
 419void ia_css_sdis_vertcoef_debug_dtrace(
 420    const struct ia_css_dvs_coefficients *config, unsigned int level)
 421{
 422        (void)config;
 423        (void)level;
 424}
 425
 426void ia_css_sdis_horiproj_debug_dtrace(
 427    const struct ia_css_dvs_coefficients *config, unsigned int level)
 428{
 429        (void)config;
 430        (void)level;
 431}
 432
 433void ia_css_sdis_vertproj_debug_dtrace(
 434    const struct ia_css_dvs_coefficients *config, unsigned int level)
 435{
 436        (void)config;
 437        (void)level;
 438}
 439