linux/drivers/staging/media/atomisp/pci/isp/kernels/dvs/dvs_1.0/ia_css_dvs.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 "ia_css_frame_public.h"
  19#define IA_CSS_INCLUDE_CONFIGURATIONS
  20#include "ia_css_isp_configs.h"
  21
  22#include "ia_css_types.h"
  23#include "ia_css_host_data.h"
  24#include "sh_css_param_dvs.h"
  25#include "sh_css_params.h"
  26#include "ia_css_binary.h"
  27#include "ia_css_debug.h"
  28#include "assert_support.h"
  29
  30#include "ia_css_dvs.host.h"
  31
  32static const struct ia_css_dvs_configuration default_config = {
  33        .info = (struct ia_css_frame_info *)NULL,
  34};
  35
  36void
  37ia_css_dvs_config(
  38    struct sh_css_isp_dvs_isp_config *to,
  39    const struct ia_css_dvs_configuration  *from,
  40    unsigned int size)
  41{
  42        (void)size;
  43        to->num_horizontal_blocks =
  44            DVS_NUM_BLOCKS_X(from->info->res.width);
  45        to->num_vertical_blocks =
  46            DVS_NUM_BLOCKS_Y(from->info->res.height);
  47}
  48
  49void
  50ia_css_dvs_configure(
  51    const struct ia_css_binary     *binary,
  52    const struct ia_css_frame_info *info)
  53{
  54        struct ia_css_dvs_configuration config = default_config;
  55
  56        config.info = info;
  57
  58        ia_css_configure_dvs(binary, &config);
  59}
  60
  61static void
  62convert_coords_to_ispparams(
  63    struct ia_css_host_data *gdc_warp_table,
  64    const struct ia_css_dvs_6axis_config *config,
  65    unsigned int i_stride,
  66    unsigned int o_width,
  67    unsigned int o_height,
  68    unsigned int uv_flag)
  69{
  70        unsigned int i, j;
  71        gdc_warp_param_mem_t s = { 0 };
  72        unsigned int x00, x01, x10, x11,
  73                 y00, y01, y10, y11;
  74
  75        unsigned int xmin, ymin, xmax, ymax;
  76        unsigned int topleft_x, topleft_y, bottom_x, bottom_y,
  77                 topleft_x_frac, topleft_y_frac;
  78        unsigned int dvs_interp_envelope = (DVS_GDC_INTERP_METHOD == HRT_GDC_BLI_MODE ?
  79                                            DVS_GDC_BLI_INTERP_ENVELOPE : DVS_GDC_BCI_INTERP_ENVELOPE);
  80
  81        /* number of blocks per height and width */
  82        unsigned int num_blocks_y =  (uv_flag ? DVS_NUM_BLOCKS_Y_CHROMA(
  83                                          o_height) : DVS_NUM_BLOCKS_Y(o_height));
  84        unsigned int num_blocks_x =  (uv_flag ? DVS_NUM_BLOCKS_X_CHROMA(
  85                                          o_width)  : DVS_NUM_BLOCKS_X(
  86                                          o_width)); // round num_x up to blockdim_x, if it concerns the Y0Y1 block (uv_flag==0) round up to even
  87
  88        unsigned int in_stride = i_stride * DVS_INPUT_BYTES_PER_PIXEL;
  89        unsigned int width, height;
  90        unsigned int *xbuff = NULL;
  91        unsigned int *ybuff = NULL;
  92        struct gdc_warp_param_mem_s *ptr;
  93
  94        assert(config);
  95        assert(gdc_warp_table);
  96        assert(gdc_warp_table->address);
  97
  98        ptr = (struct gdc_warp_param_mem_s *)gdc_warp_table->address;
  99
 100        ptr += (2 * uv_flag); /* format is Y0 Y1 UV, so UV starts at 3rd position */
 101
 102        if (uv_flag == 0) {
 103                xbuff = config->xcoords_y;
 104                ybuff = config->ycoords_y;
 105                width = config->width_y;
 106                height = config->height_y;
 107        } else {
 108                xbuff = config->xcoords_uv;
 109                ybuff = config->ycoords_uv;
 110                width = config->width_uv;
 111                height = config->height_uv;
 112        }
 113
 114        IA_CSS_LOG("blockdim_x %d blockdim_y %d",
 115                   DVS_BLOCKDIM_X, DVS_BLOCKDIM_Y_LUMA >> uv_flag);
 116        IA_CSS_LOG("num_blocks_x %d num_blocks_y %d", num_blocks_x, num_blocks_y);
 117        IA_CSS_LOG("width %d height %d", width, height);
 118
 119        assert(width == num_blocks_x +
 120               1); // the width and height of the provided morphing table should be 1 more than the number of blocks
 121        assert(height == num_blocks_y + 1);
 122
 123        for (j = 0; j < num_blocks_y; j++) {
 124                for (i = 0; i < num_blocks_x; i++) {
 125                        x00 = xbuff[j * width + i];
 126                        x01 = xbuff[j * width + (i + 1)];
 127                        x10 = xbuff[(j + 1) * width + i];
 128                        x11 = xbuff[(j + 1) * width + (i + 1)];
 129
 130                        y00 = ybuff[j * width + i];
 131                        y01 = ybuff[j * width + (i + 1)];
 132                        y10 = ybuff[(j + 1) * width + i];
 133                        y11 = ybuff[(j + 1) * width + (i + 1)];
 134
 135                        xmin = min(x00, x10);
 136                        xmax = max(x01, x11);
 137                        ymin = min(y00, y01);
 138                        ymax = max(y10, y11);
 139
 140                        /* Assert that right column's X is greater */
 141                        assert(x01 >= xmin);
 142                        assert(x11 >= xmin);
 143                        /* Assert that bottom row's Y is greater */
 144                        assert(y10 >= ymin);
 145                        assert(y11 >= ymin);
 146
 147                        topleft_y = ymin >> DVS_COORD_FRAC_BITS;
 148                        topleft_x = ((xmin >> DVS_COORD_FRAC_BITS)
 149                                     >> XMEM_ALIGN_LOG2)
 150                                    << (XMEM_ALIGN_LOG2);
 151                        s.in_addr_offset = topleft_y * in_stride + topleft_x;
 152
 153                        /* similar to topleft_y calculation, but round up if ymax
 154                         * has any fraction bits */
 155                        bottom_y = CEIL_DIV(ymax, 1 << DVS_COORD_FRAC_BITS);
 156                        s.in_block_height = bottom_y - topleft_y + dvs_interp_envelope;
 157
 158                        bottom_x = CEIL_DIV(xmax, 1 << DVS_COORD_FRAC_BITS);
 159                        s.in_block_width = bottom_x - topleft_x + dvs_interp_envelope;
 160
 161                        topleft_x_frac = topleft_x << (DVS_COORD_FRAC_BITS);
 162                        topleft_y_frac = topleft_y << (DVS_COORD_FRAC_BITS);
 163
 164                        s.p0_x = x00 - topleft_x_frac;
 165                        s.p1_x = x01 - topleft_x_frac;
 166                        s.p2_x = x10 - topleft_x_frac;
 167                        s.p3_x = x11 - topleft_x_frac;
 168
 169                        s.p0_y = y00 - topleft_y_frac;
 170                        s.p1_y = y01 - topleft_y_frac;
 171                        s.p2_y = y10 - topleft_y_frac;
 172                        s.p3_y = y11 - topleft_y_frac;
 173
 174                        // block should fit within the boundingbox.
 175                        assert(s.p0_x < (s.in_block_width << DVS_COORD_FRAC_BITS));
 176                        assert(s.p1_x < (s.in_block_width << DVS_COORD_FRAC_BITS));
 177                        assert(s.p2_x < (s.in_block_width << DVS_COORD_FRAC_BITS));
 178                        assert(s.p3_x < (s.in_block_width << DVS_COORD_FRAC_BITS));
 179                        assert(s.p0_y < (s.in_block_height << DVS_COORD_FRAC_BITS));
 180                        assert(s.p1_y < (s.in_block_height << DVS_COORD_FRAC_BITS));
 181                        assert(s.p2_y < (s.in_block_height << DVS_COORD_FRAC_BITS));
 182                        assert(s.p3_y < (s.in_block_height << DVS_COORD_FRAC_BITS));
 183
 184                        // block size should be greater than zero.
 185                        assert(s.p0_x < s.p1_x);
 186                        assert(s.p2_x < s.p3_x);
 187                        assert(s.p0_y < s.p2_y);
 188                        assert(s.p1_y < s.p3_y);
 189
 190#if 0
 191                        printf("j: %d\ti:%d\n", j, i);
 192                        printf("offset: %d\n", s.in_addr_offset);
 193                        printf("p0_x: %d\n", s.p0_x);
 194                        printf("p0_y: %d\n", s.p0_y);
 195                        printf("p1_x: %d\n", s.p1_x);
 196                        printf("p1_y: %d\n", s.p1_y);
 197                        printf("p2_x: %d\n", s.p2_x);
 198                        printf("p2_y: %d\n", s.p2_y);
 199                        printf("p3_x: %d\n", s.p3_x);
 200                        printf("p3_y: %d\n", s.p3_y);
 201
 202                        printf("p0_x_nofrac[0]: %d\n", s.p0_x >> DVS_COORD_FRAC_BITS);
 203                        printf("p0_y_nofrac[1]: %d\n", s.p0_y >> DVS_COORD_FRAC_BITS);
 204                        printf("p1_x_nofrac[2]: %d\n", s.p1_x >> DVS_COORD_FRAC_BITS);
 205                        printf("p1_y_nofrac[3]: %d\n", s.p1_y >> DVS_COORD_FRAC_BITS);
 206                        printf("p2_x_nofrac[0]: %d\n", s.p2_x >> DVS_COORD_FRAC_BITS);
 207                        printf("p2_y_nofrac[1]: %d\n", s.p2_y >> DVS_COORD_FRAC_BITS);
 208                        printf("p3_x_nofrac[2]: %d\n", s.p3_x >> DVS_COORD_FRAC_BITS);
 209                        printf("p3_y_nofrac[3]: %d\n", s.p3_y >> DVS_COORD_FRAC_BITS);
 210                        printf("\n");
 211#endif
 212
 213                        *ptr = s;
 214
 215                        // storage format:
 216                        // Y0 Y1 UV0 Y2 Y3 UV1
 217                        /* if uv_flag equals true increment with 2 incase x is odd, this to
 218                        skip the uv position. */
 219                        if (uv_flag)
 220                                ptr += 3;
 221                        else
 222                                ptr += (1 + (i & 1));
 223                }
 224        }
 225}
 226
 227struct ia_css_host_data *
 228convert_allocate_dvs_6axis_config(
 229    const struct ia_css_dvs_6axis_config *dvs_6axis_config,
 230    const struct ia_css_binary *binary,
 231    const struct ia_css_frame_info *dvs_in_frame_info)
 232{
 233        unsigned int i_stride;
 234        unsigned int o_width;
 235        unsigned int o_height;
 236        struct ia_css_host_data *me;
 237
 238        assert(binary);
 239        assert(dvs_6axis_config);
 240        assert(dvs_in_frame_info);
 241
 242        me = ia_css_host_data_allocate((size_t)((DVS_6AXIS_BYTES(binary) / 2) * 3));
 243
 244        if (!me)
 245                return NULL;
 246
 247        /*DVS only supports input frame of YUV420 or NV12. Fail for all other cases*/
 248        assert((dvs_in_frame_info->format == IA_CSS_FRAME_FORMAT_NV12)
 249               || (dvs_in_frame_info->format == IA_CSS_FRAME_FORMAT_YUV420));
 250
 251        i_stride  = dvs_in_frame_info->padded_width;
 252
 253        o_width  = binary->out_frame_info[0].res.width;
 254        o_height = binary->out_frame_info[0].res.height;
 255
 256        /* Y plane */
 257        convert_coords_to_ispparams(me, dvs_6axis_config,
 258                                    i_stride, o_width, o_height, 0);
 259
 260        if (dvs_in_frame_info->format == IA_CSS_FRAME_FORMAT_YUV420) {
 261                /*YUV420 has half the stride for U/V plane*/
 262                i_stride /= 2;
 263        }
 264
 265        /* UV plane (packed inside the y plane) */
 266        convert_coords_to_ispparams(me, dvs_6axis_config,
 267                                    i_stride, o_width / 2, o_height / 2, 1);
 268
 269        return me;
 270}
 271
 272int
 273store_dvs_6axis_config(
 274    const struct ia_css_dvs_6axis_config *dvs_6axis_config,
 275    const struct ia_css_binary *binary,
 276    const struct ia_css_frame_info *dvs_in_frame_info,
 277    ia_css_ptr ddr_addr_y) {
 278        struct ia_css_host_data *me;
 279
 280        assert(dvs_6axis_config);
 281        assert(ddr_addr_y != mmgr_NULL);
 282        assert(dvs_in_frame_info);
 283
 284        me = convert_allocate_dvs_6axis_config(dvs_6axis_config,
 285                                               binary,
 286                                               dvs_in_frame_info);
 287
 288        if (!me)
 289        {
 290                IA_CSS_LEAVE_ERR_PRIVATE(-ENOMEM);
 291                return -ENOMEM;
 292        }
 293
 294        ia_css_params_store_ia_css_host_data(
 295            ddr_addr_y,
 296            me);
 297        ia_css_host_data_free(me);
 298
 299        return 0;
 300}
 301