linux/drivers/staging/media/atomisp/pci/isp/kernels/vf/vf_1.0/ia_css_vf.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 "atomisp_internal.h"
  17
  18#include "ia_css_vf.host.h"
  19#include <assert_support.h>
  20#include <ia_css_err.h>
  21#include <ia_css_frame.h>
  22#include <ia_css_frame_public.h>
  23#include <ia_css_pipeline.h>
  24#define IA_CSS_INCLUDE_CONFIGURATIONS
  25#include "ia_css_isp_configs.h"
  26
  27#include "isp.h"
  28
  29void
  30ia_css_vf_config(
  31    struct sh_css_isp_vf_isp_config      *to,
  32    const struct ia_css_vf_configuration *from,
  33    unsigned int size)
  34{
  35        unsigned int elems_a = ISP_VEC_NELEMS;
  36
  37        (void)size;
  38        to->vf_downscale_bits = from->vf_downscale_bits;
  39        to->enable = from->info != NULL;
  40
  41        if (from->info) {
  42                ia_css_frame_info_to_frame_sp_info(&to->info, from->info);
  43                ia_css_dma_configure_from_info(&to->dma.port_b, from->info);
  44                to->dma.width_a_over_b = elems_a / to->dma.port_b.elems;
  45
  46                /* Assume divisiblity here, may need to generalize to fixed point. */
  47                assert(elems_a % to->dma.port_b.elems == 0);
  48        }
  49}
  50
  51/* compute the log2 of the downscale factor needed to get closest
  52 * to the requested viewfinder resolution on the upper side. The output cannot
  53 * be smaller than the requested viewfinder resolution.
  54 */
  55int
  56sh_css_vf_downscale_log2(
  57    const struct ia_css_frame_info *out_info,
  58    const struct ia_css_frame_info *vf_info,
  59    unsigned int *downscale_log2) {
  60        unsigned int ds_log2 = 0;
  61        unsigned int out_width;
  62
  63        if ((!out_info) || (!vf_info))
  64                return -EINVAL;
  65
  66        out_width = out_info->res.width;
  67
  68        if (out_width == 0)
  69                return -EINVAL;
  70
  71        /* downscale until width smaller than the viewfinder width. We don't
  72        * test for the height since the vmem buffers only put restrictions on
  73        * the width of a line, not on the number of lines in a frame.
  74        */
  75        while (out_width >= vf_info->res.width)
  76        {
  77                ds_log2++;
  78                out_width /= 2;
  79        }
  80        /* now width is smaller, so we go up one step */
  81        if ((ds_log2 > 0) && (out_width < ia_css_binary_max_vf_width()))
  82                ds_log2--;
  83        /* TODO: use actual max input resolution of vf_pp binary */
  84        if ((out_info->res.width >> ds_log2) >= 2 * ia_css_binary_max_vf_width())
  85                return -EINVAL;
  86        *downscale_log2 = ds_log2;
  87        return 0;
  88}
  89
  90static int
  91configure_kernel(
  92    const struct ia_css_binary_info *info,
  93    const struct ia_css_frame_info *out_info,
  94    const struct ia_css_frame_info *vf_info,
  95    unsigned int *downscale_log2,
  96    struct ia_css_vf_configuration *config) {
  97        int err;
  98        unsigned int vf_log_ds = 0;
  99
 100        /* First compute value */
 101        if (vf_info)
 102        {
 103                err = sh_css_vf_downscale_log2(out_info, vf_info, &vf_log_ds);
 104                if (err)
 105                        return err;
 106        }
 107        vf_log_ds = min(vf_log_ds, info->vf_dec.max_log_downscale);
 108        *downscale_log2 = vf_log_ds;
 109
 110        /* Then store it in isp config section */
 111        config->vf_downscale_bits = vf_log_ds;
 112        return 0;
 113}
 114
 115static void
 116configure_dma(
 117    struct ia_css_vf_configuration *config,
 118    const struct ia_css_frame_info *vf_info)
 119{
 120        config->info = vf_info;
 121}
 122
 123int
 124ia_css_vf_configure(
 125    const struct ia_css_binary *binary,
 126    const struct ia_css_frame_info *out_info,
 127    struct ia_css_frame_info *vf_info,
 128    unsigned int *downscale_log2) {
 129        int err;
 130        struct ia_css_vf_configuration config;
 131        const struct ia_css_binary_info *info = &binary->info->sp;
 132
 133        err = configure_kernel(info, out_info, vf_info, downscale_log2, &config);
 134        if (err)
 135                dev_warn(atomisp_dev, "Couldn't setup downscale\n");
 136
 137        configure_dma(&config, vf_info);
 138
 139        if (vf_info)
 140                vf_info->raw_bit_depth = info->dma.vfdec_bits_per_pixel;
 141        ia_css_configure_vf(binary, &config);
 142
 143        return 0;
 144}
 145