linux/drivers/staging/media/atomisp/pci/isp/kernels/xnr/xnr_3.0/ia_css_xnr3.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 "type_support.h"
  17#include "math_support.h"
  18#include "sh_css_defs.h"
  19#include "ia_css_types.h"
  20#include "assert_support.h"
  21#include "ia_css_xnr3.host.h"
  22
  23/* Maximum value for alpha on ISP interface */
  24#define XNR_MAX_ALPHA  ((1 << (ISP_VEC_ELEMBITS - 1)) - 1)
  25
  26/* Minimum value for sigma on host interface. Lower values translate to
  27 * max_alpha.
  28 */
  29#define XNR_MIN_SIGMA  (IA_CSS_XNR3_SIGMA_SCALE / 100)
  30
  31/*
  32 * division look-up table
  33 * Refers to XNR3.0.5
  34 */
  35#define XNR3_LOOK_UP_TABLE_POINTS 16
  36
  37static const s16 x[XNR3_LOOK_UP_TABLE_POINTS] = {
  38        1024, 1164, 1320, 1492, 1680, 1884, 2108, 2352,
  39        2616, 2900, 3208, 3540, 3896, 4276, 4684, 5120
  40};
  41
  42static const s16 a[XNR3_LOOK_UP_TABLE_POINTS] = {
  43        -7213, -5580, -4371, -3421, -2722, -2159, -6950, -5585,
  44            -4529, -3697, -3010, -2485, -2070, -1727, -1428, 0
  45    };
  46
  47static const s16 b[XNR3_LOOK_UP_TABLE_POINTS] = {
  48        4096, 3603, 3178, 2811, 2497, 2226, 1990, 1783,
  49        1603, 1446, 1307, 1185, 1077, 981, 895, 819
  50};
  51
  52static const s16 c[XNR3_LOOK_UP_TABLE_POINTS] = {
  53        1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  54};
  55
  56/*
  57 * Default kernel parameters. In general, default is bypass mode or as close
  58 * to the ineffective values as possible. Due to the chroma down+upsampling,
  59 * perfect bypass mode is not possible for xnr3 filter itself. Instead, the
  60 * 'blending' parameter is used to create a bypass.
  61 */
  62const struct ia_css_xnr3_config default_xnr3_config = {
  63        /* sigma */
  64        { 0, 0, 0, 0, 0, 0 },
  65        /* coring */
  66        { 0, 0, 0, 0 },
  67        /* blending */
  68        { 0 }
  69};
  70
  71/*
  72 * Compute an alpha value for the ISP kernel from sigma value on the host
  73 * parameter interface as: alpha_scale * 1/(sigma/sigma_scale)
  74 */
  75static int32_t
  76compute_alpha(int sigma)
  77{
  78        s32 alpha;
  79        int offset = sigma / 2;
  80
  81        if (sigma < XNR_MIN_SIGMA) {
  82                alpha = XNR_MAX_ALPHA;
  83        } else {
  84                alpha = ((IA_CSS_XNR3_SIGMA_SCALE * XNR_ALPHA_SCALE_FACTOR) + offset) / sigma;
  85
  86                if (alpha > XNR_MAX_ALPHA)
  87                        alpha = XNR_MAX_ALPHA;
  88        }
  89
  90        return alpha;
  91}
  92
  93/*
  94 * Compute the scaled coring value for the ISP kernel from the value on the
  95 * host parameter interface.
  96 */
  97static int32_t
  98compute_coring(int coring)
  99{
 100        s32 isp_coring;
 101        s32 isp_scale = XNR_CORING_SCALE_FACTOR;
 102        s32 host_scale = IA_CSS_XNR3_CORING_SCALE;
 103        s32 offset = host_scale / 2; /* fixed-point 0.5 */
 104
 105        /* Convert from public host-side scale factor to isp-side scale
 106         * factor. Clip to [0, isp_scale-1).
 107         */
 108        isp_coring = ((coring * isp_scale) + offset) / host_scale;
 109        return min(max(isp_coring, 0), isp_scale - 1);
 110}
 111
 112/*
 113 * Compute the scaled blending strength for the ISP kernel from the value on
 114 * the host parameter interface.
 115 */
 116static int32_t
 117compute_blending(int strength)
 118{
 119        s32 isp_strength;
 120        s32 isp_scale = XNR_BLENDING_SCALE_FACTOR;
 121        s32 host_scale = IA_CSS_XNR3_BLENDING_SCALE;
 122        s32 offset = host_scale / 2; /* fixed-point 0.5 */
 123
 124        /* Convert from public host-side scale factor to isp-side scale
 125         * factor. The blending factor is positive on the host side, but
 126         * negative on the ISP side because +1.0 cannot be represented
 127         * exactly as s0.11 fixed point, but -1.0 can.
 128         */
 129        isp_strength = -(((strength * isp_scale) + offset) / host_scale);
 130        return MAX(MIN(isp_strength, 0), -isp_scale);
 131}
 132
 133void
 134ia_css_xnr3_encode(
 135    struct sh_css_isp_xnr3_params *to,
 136    const struct ia_css_xnr3_config *from,
 137    unsigned int size)
 138{
 139        int kernel_size = XNR_FILTER_SIZE;
 140        /* The adjust factor is the next power of 2
 141           w.r.t. the kernel size*/
 142        int adjust_factor = ceil_pow2(kernel_size);
 143        s32 max_diff = (1 << (ISP_VEC_ELEMBITS - 1)) - 1;
 144        s32 min_diff = -(1 << (ISP_VEC_ELEMBITS - 1));
 145
 146        s32 alpha_y0 = compute_alpha(from->sigma.y0);
 147        s32 alpha_y1 = compute_alpha(from->sigma.y1);
 148        s32 alpha_u0 = compute_alpha(from->sigma.u0);
 149        s32 alpha_u1 = compute_alpha(from->sigma.u1);
 150        s32 alpha_v0 = compute_alpha(from->sigma.v0);
 151        s32 alpha_v1 = compute_alpha(from->sigma.v1);
 152        s32 alpha_ydiff = (alpha_y1 - alpha_y0) * adjust_factor / kernel_size;
 153        s32 alpha_udiff = (alpha_u1 - alpha_u0) * adjust_factor / kernel_size;
 154        s32 alpha_vdiff = (alpha_v1 - alpha_v0) * adjust_factor / kernel_size;
 155
 156        s32 coring_u0 = compute_coring(from->coring.u0);
 157        s32 coring_u1 = compute_coring(from->coring.u1);
 158        s32 coring_v0 = compute_coring(from->coring.v0);
 159        s32 coring_v1 = compute_coring(from->coring.v1);
 160        s32 coring_udiff = (coring_u1 - coring_u0) * adjust_factor / kernel_size;
 161        s32 coring_vdiff = (coring_v1 - coring_v0) * adjust_factor / kernel_size;
 162
 163        s32 blending = compute_blending(from->blending.strength);
 164
 165        (void)size;
 166
 167        /* alpha's are represented in qN.5 format */
 168        to->alpha.y0 = alpha_y0;
 169        to->alpha.u0 = alpha_u0;
 170        to->alpha.v0 = alpha_v0;
 171        to->alpha.ydiff = min(max(alpha_ydiff, min_diff), max_diff);
 172        to->alpha.udiff = min(max(alpha_udiff, min_diff), max_diff);
 173        to->alpha.vdiff = min(max(alpha_vdiff, min_diff), max_diff);
 174
 175        /* coring parameters are expressed in q1.NN format */
 176        to->coring.u0 = coring_u0;
 177        to->coring.v0 = coring_v0;
 178        to->coring.udiff = min(max(coring_udiff, min_diff), max_diff);
 179        to->coring.vdiff = min(max(coring_vdiff, min_diff), max_diff);
 180
 181        /* blending strength is expressed in q1.NN format */
 182        to->blending.strength = blending;
 183}
 184
 185/* ISP2401 */
 186/* (void) = ia_css_xnr3_vmem_encode(*to, *from)
 187 * -----------------------------------------------
 188 * VMEM Encode Function to translate UV parameters from userspace into ISP space
 189*/
 190void
 191ia_css_xnr3_vmem_encode(
 192    struct sh_css_isp_xnr3_vmem_params *to,
 193    const struct ia_css_xnr3_config *from,
 194    unsigned int size)
 195{
 196        unsigned int i, j, base;
 197        const unsigned int total_blocks = 4;
 198        const unsigned int shuffle_block = 16;
 199
 200        (void)from;
 201        (void)size;
 202
 203        /* Init */
 204        for (i = 0; i < ISP_VEC_NELEMS; i++) {
 205                to->x[0][i] = 0;
 206                to->a[0][i] = 0;
 207                to->b[0][i] = 0;
 208                to->c[0][i] = 0;
 209        }
 210
 211        /* Constraints on "x":
 212         * - values should be greater or equal to 0.
 213         * - values should be ascending.
 214         */
 215        assert(x[0] >= 0);
 216
 217        for (j = 1; j < XNR3_LOOK_UP_TABLE_POINTS; j++) {
 218                assert(x[j] >= 0);
 219                assert(x[j] > x[j - 1]);
 220        }
 221
 222        /* The implementation of the calulating 1/x is based on the availability
 223         * of the OP_vec_shuffle16 operation.
 224         * A 64 element vector is split up in 4 blocks of 16 element. Each array is copied to
 225         * a vector 4 times, (starting at 0, 16, 32 and 48). All array elements are copied or
 226         * initialised as described in the KFS. The remaining elements of a vector are set to 0.
 227         */
 228        /* TODO: guard this code with above assumptions */
 229        for (i = 0; i < total_blocks; i++) {
 230                base = shuffle_block * i;
 231
 232                for (j = 0; j < XNR3_LOOK_UP_TABLE_POINTS; j++) {
 233                        to->x[0][base + j] = x[j];
 234                        to->a[0][base + j] = a[j];
 235                        to->b[0][base + j] = b[j];
 236                        to->c[0][base + j] = c[j];
 237                }
 238        }
 239}
 240
 241/* Dummy Function added as the tool expects it*/
 242void
 243ia_css_xnr3_debug_dtrace(
 244    const struct ia_css_xnr3_config *config,
 245    unsigned int level)
 246{
 247        (void)config;
 248        (void)level;
 249}
 250