diff options
Diffstat (limited to 'drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/xnr/xnr_3.0/ia_css_xnr3.host.c')
-rw-r--r-- | drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/xnr/xnr_3.0/ia_css_xnr3.host.c | 265 |
1 files changed, 265 insertions, 0 deletions
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/xnr/xnr_3.0/ia_css_xnr3.host.c b/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/xnr/xnr_3.0/ia_css_xnr3.host.c new file mode 100644 index 0000000..955b6c8 --- /dev/null +++ b/drivers/staging/media/atomisp/pci/atomisp2/css2400/isp/kernels/xnr/xnr_3.0/ia_css_xnr3.host.c @@ -0,0 +1,265 @@ +/* + * Support for Intel Camera Imaging ISP subsystem. + * Copyright (c) 2015, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include "type_support.h" +#include "math_support.h" +#include "sh_css_defs.h" +#include "ia_css_types.h" +#ifdef ISP2401 +#include "assert_support.h" +#endif +#include "ia_css_xnr3.host.h" + +/* Maximum value for alpha on ISP interface */ +#define XNR_MAX_ALPHA ((1 << (ISP_VEC_ELEMBITS - 1)) - 1) + +/* Minimum value for sigma on host interface. Lower values translate to + * max_alpha. + */ +#define XNR_MIN_SIGMA (IA_CSS_XNR3_SIGMA_SCALE / 100) + +/* +#ifdef ISP2401 + * division look-up table + * Refers to XNR3.0.5 + */ +#define XNR3_LOOK_UP_TABLE_POINTS 16 + +static const int16_t x[XNR3_LOOK_UP_TABLE_POINTS] = { +1024, 1164, 1320, 1492, 1680, 1884, 2108, 2352, +2616, 2900, 3208, 3540, 3896, 4276, 4684, 5120}; + +static const int16_t a[XNR3_LOOK_UP_TABLE_POINTS] = { +-7213, -5580, -4371, -3421, -2722, -2159, -6950, -5585, +-4529, -3697, -3010, -2485, -2070, -1727, -1428, 0}; + +static const int16_t b[XNR3_LOOK_UP_TABLE_POINTS] = { +4096, 3603, 3178, 2811, 2497, 2226, 1990, 1783, +1603, 1446, 1307, 1185, 1077, 981, 895, 819}; + +static const int16_t c[XNR3_LOOK_UP_TABLE_POINTS] = { +1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + +/* +#endif + * Default kernel parameters. In general, default is bypass mode or as close + * to the ineffective values as possible. Due to the chroma down+upsampling, + * perfect bypass mode is not possible for xnr3 filter itself. Instead, the + * 'blending' parameter is used to create a bypass. + */ +const struct ia_css_xnr3_config default_xnr3_config = { + /* sigma */ + { 0, 0, 0, 0, 0, 0 }, + /* coring */ + { 0, 0, 0, 0 }, + /* blending */ + { 0 } +}; + +/* + * Compute an alpha value for the ISP kernel from sigma value on the host + * parameter interface as: alpha_scale * 1/(sigma/sigma_scale) + */ +static int32_t +compute_alpha(int sigma) +{ + int32_t alpha; +#if defined(XNR_ATE_ROUNDING_BUG) + int32_t alpha_unscaled; +#else + int offset = sigma / 2; +#endif + if (sigma < XNR_MIN_SIGMA) { + alpha = XNR_MAX_ALPHA; + } else { +#if defined(XNR_ATE_ROUNDING_BUG) + /* The scale factor for alpha must be the same as on the ISP, + * For sigma, it must match the public interface. The code + * below mimics the rounding and unintended loss of precision + * of the ATE reference code. It computes an unscaled alpha, + * rounds down, and then scales it to get the required fixed + * point representation. It would have been more precise to + * round after scaling. */ + alpha_unscaled = IA_CSS_XNR3_SIGMA_SCALE / sigma; + alpha = alpha_unscaled * XNR_ALPHA_SCALE_FACTOR; +#else + alpha = ((IA_CSS_XNR3_SIGMA_SCALE * XNR_ALPHA_SCALE_FACTOR) + offset)/ sigma; +#endif + + if (alpha > XNR_MAX_ALPHA) + alpha = XNR_MAX_ALPHA; + } + + return alpha; +} + +/* + * Compute the scaled coring value for the ISP kernel from the value on the + * host parameter interface. + */ +static int32_t +compute_coring(int coring) +{ + int32_t isp_coring; + int32_t isp_scale = XNR_CORING_SCALE_FACTOR; + int32_t host_scale = IA_CSS_XNR3_CORING_SCALE; + int32_t offset = host_scale / 2; /* fixed-point 0.5 */ + + /* Convert from public host-side scale factor to isp-side scale + * factor. Clip to [0, isp_scale-1). + */ + isp_coring = ((coring * isp_scale) + offset) / host_scale; + return min(max(isp_coring, 0), isp_scale - 1); +} + +/* + * Compute the scaled blending strength for the ISP kernel from the value on + * the host parameter interface. + */ +static int32_t +compute_blending(int strength) +{ + int32_t isp_strength; + int32_t isp_scale = XNR_BLENDING_SCALE_FACTOR; + int32_t host_scale = IA_CSS_XNR3_BLENDING_SCALE; + int32_t offset = host_scale / 2; /* fixed-point 0.5 */ + + /* Convert from public host-side scale factor to isp-side scale + * factor. The blending factor is positive on the host side, but + * negative on the ISP side because +1.0 cannot be represented + * exactly as s0.11 fixed point, but -1.0 can. + */ + isp_strength = -(((strength * isp_scale) + offset) / host_scale); + return max(min(isp_strength, 0), -XNR_BLENDING_SCALE_FACTOR); +} + +void +ia_css_xnr3_encode( + struct sh_css_isp_xnr3_params *to, + const struct ia_css_xnr3_config *from, + unsigned size) +{ + int kernel_size = XNR_FILTER_SIZE; + /* The adjust factor is the next power of 2 + w.r.t. the kernel size*/ + int adjust_factor = ceil_pow2(kernel_size); + int32_t max_diff = (1 << (ISP_VEC_ELEMBITS - 1)) - 1; + int32_t min_diff = -(1 << (ISP_VEC_ELEMBITS - 1)); + + int32_t alpha_y0 = compute_alpha(from->sigma.y0); + int32_t alpha_y1 = compute_alpha(from->sigma.y1); + int32_t alpha_u0 = compute_alpha(from->sigma.u0); + int32_t alpha_u1 = compute_alpha(from->sigma.u1); + int32_t alpha_v0 = compute_alpha(from->sigma.v0); + int32_t alpha_v1 = compute_alpha(from->sigma.v1); + int32_t alpha_ydiff = (alpha_y1 - alpha_y0) * adjust_factor / kernel_size; + int32_t alpha_udiff = (alpha_u1 - alpha_u0) * adjust_factor / kernel_size; + int32_t alpha_vdiff = (alpha_v1 - alpha_v0) * adjust_factor / kernel_size; + + int32_t coring_u0 = compute_coring(from->coring.u0); + int32_t coring_u1 = compute_coring(from->coring.u1); + int32_t coring_v0 = compute_coring(from->coring.v0); + int32_t coring_v1 = compute_coring(from->coring.v1); + int32_t coring_udiff = (coring_u1 - coring_u0) * adjust_factor / kernel_size; + int32_t coring_vdiff = (coring_v1 - coring_v0) * adjust_factor / kernel_size; + + int32_t blending = compute_blending(from->blending.strength); + + (void)size; + + /* alpha's are represented in qN.5 format */ + to->alpha.y0 = alpha_y0; + to->alpha.u0 = alpha_u0; + to->alpha.v0 = alpha_v0; + to->alpha.ydiff = min(max(alpha_ydiff, min_diff), max_diff); + to->alpha.udiff = min(max(alpha_udiff, min_diff), max_diff); + to->alpha.vdiff = min(max(alpha_vdiff, min_diff), max_diff); + + /* coring parameters are expressed in q1.NN format */ + to->coring.u0 = coring_u0; + to->coring.v0 = coring_v0; + to->coring.udiff = min(max(coring_udiff, min_diff), max_diff); + to->coring.vdiff = min(max(coring_vdiff, min_diff), max_diff); + + /* blending strength is expressed in q1.NN format */ + to->blending.strength = blending; +} + +#ifdef ISP2401 +/* (void) = ia_css_xnr3_vmem_encode(*to, *from) + * ----------------------------------------------- + * VMEM Encode Function to translate UV parameters from userspace into ISP space +*/ +void +ia_css_xnr3_vmem_encode( + struct sh_css_isp_xnr3_vmem_params *to, + const struct ia_css_xnr3_config *from, + unsigned size) +{ + unsigned i, j, base; + const unsigned total_blocks = 4; + const unsigned shuffle_block = 16; + + (void)from; + (void)size; + + /* Init */ + for (i = 0; i < ISP_VEC_NELEMS; i++) { + to->x[0][i] = 0; + to->a[0][i] = 0; + to->b[0][i] = 0; + to->c[0][i] = 0; + } + + /* Constraints on "x": + * - values should be greater or equal to 0. + * - values should be ascending. + */ + assert(x[0] >= 0); + + for (j = 1; j < XNR3_LOOK_UP_TABLE_POINTS; j++) { + assert(x[j] >= 0); + assert(x[j] > x[j - 1]); + + } + + /* The implementation of the calulating 1/x is based on the availability + * of the OP_vec_shuffle16 operation. + * A 64 element vector is split up in 4 blocks of 16 element. Each array is copied to + * a vector 4 times, (starting at 0, 16, 32 and 48). All array elements are copied or + * initialised as described in the KFS. The remaining elements of a vector are set to 0. + */ + /* TODO: guard this code with above assumptions */ + for (i = 0; i < total_blocks; i++) { + base = shuffle_block * i; + + for (j = 0; j < XNR3_LOOK_UP_TABLE_POINTS; j++) { + to->x[0][base + j] = x[j]; + to->a[0][base + j] = a[j]; + to->b[0][base + j] = b[j]; + to->c[0][base + j] = c[j]; + } + } +} + +#endif +/* Dummy Function added as the tool expects it*/ +void +ia_css_xnr3_debug_dtrace( + const struct ia_css_xnr3_config *config, + unsigned level) +{ + (void)config; + (void)level; +} |