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