| // SPDX-License-Identifier: GPL-2.0 |
| /* |
| * Support for Intel Camera Imaging ISP subsystem. |
| * Copyright (c) 2010 - 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 "hmm.h" |
| |
| #include "ia_css_pipeline.h" |
| #include "ia_css_isp_param.h" |
| |
| /* Set functions for parameter memory descriptors */ |
| |
| void |
| ia_css_isp_param_set_mem_init( |
| struct ia_css_isp_param_host_segments *mem_init, |
| enum ia_css_param_class pclass, |
| enum ia_css_isp_memories mem, |
| char *address, size_t size) |
| { |
| mem_init->params[pclass][mem].address = address; |
| mem_init->params[pclass][mem].size = (uint32_t)size; |
| } |
| |
| void |
| ia_css_isp_param_set_css_mem_init( |
| struct ia_css_isp_param_css_segments *mem_init, |
| enum ia_css_param_class pclass, |
| enum ia_css_isp_memories mem, |
| ia_css_ptr address, size_t size) |
| { |
| mem_init->params[pclass][mem].address = address; |
| mem_init->params[pclass][mem].size = (uint32_t)size; |
| } |
| |
| void |
| ia_css_isp_param_set_isp_mem_init( |
| struct ia_css_isp_param_isp_segments *mem_init, |
| enum ia_css_param_class pclass, |
| enum ia_css_isp_memories mem, |
| u32 address, size_t size) |
| { |
| mem_init->params[pclass][mem].address = address; |
| mem_init->params[pclass][mem].size = (uint32_t)size; |
| } |
| |
| /* Get functions for parameter memory descriptors */ |
| const struct ia_css_host_data * |
| ia_css_isp_param_get_mem_init( |
| const struct ia_css_isp_param_host_segments *mem_init, |
| enum ia_css_param_class pclass, |
| enum ia_css_isp_memories mem) |
| { |
| return &mem_init->params[pclass][mem]; |
| } |
| |
| const struct ia_css_data * |
| ia_css_isp_param_get_css_mem_init( |
| const struct ia_css_isp_param_css_segments *mem_init, |
| enum ia_css_param_class pclass, |
| enum ia_css_isp_memories mem) |
| { |
| return &mem_init->params[pclass][mem]; |
| } |
| |
| const struct ia_css_isp_data * |
| ia_css_isp_param_get_isp_mem_init( |
| const struct ia_css_isp_param_isp_segments *mem_init, |
| enum ia_css_param_class pclass, |
| enum ia_css_isp_memories mem) |
| { |
| return &mem_init->params[pclass][mem]; |
| } |
| |
| void |
| ia_css_init_memory_interface( |
| struct ia_css_isp_param_css_segments *isp_mem_if, |
| const struct ia_css_isp_param_host_segments *mem_params, |
| const struct ia_css_isp_param_css_segments *css_params) |
| { |
| unsigned int pclass, mem; |
| |
| for (pclass = 0; pclass < IA_CSS_NUM_PARAM_CLASSES; pclass++) { |
| memset(isp_mem_if->params[pclass], 0, sizeof(isp_mem_if->params[pclass])); |
| for (mem = 0; mem < IA_CSS_NUM_MEMORIES; mem++) { |
| if (!mem_params->params[pclass][mem].address) |
| continue; |
| isp_mem_if->params[pclass][mem].size = mem_params->params[pclass][mem].size; |
| if (pclass != IA_CSS_PARAM_CLASS_PARAM) |
| isp_mem_if->params[pclass][mem].address = |
| css_params->params[pclass][mem].address; |
| } |
| } |
| } |
| |
| int |
| ia_css_isp_param_allocate_isp_parameters( |
| struct ia_css_isp_param_host_segments *mem_params, |
| struct ia_css_isp_param_css_segments *css_params, |
| const struct ia_css_isp_param_isp_segments *mem_initializers) { |
| int err = 0; |
| unsigned int mem, pclass; |
| |
| pclass = IA_CSS_PARAM_CLASS_PARAM; |
| for (mem = 0; mem < IA_CSS_NUM_MEMORIES; mem++) |
| { |
| for (pclass = 0; pclass < IA_CSS_NUM_PARAM_CLASSES; pclass++) { |
| u32 size = 0; |
| |
| if (mem_initializers) |
| size = mem_initializers->params[pclass][mem].size; |
| mem_params->params[pclass][mem].size = size; |
| mem_params->params[pclass][mem].address = NULL; |
| css_params->params[pclass][mem].size = size; |
| css_params->params[pclass][mem].address = 0x0; |
| if (size) { |
| mem_params->params[pclass][mem].address = kvcalloc(1, |
| size, |
| GFP_KERNEL); |
| if (!mem_params->params[pclass][mem].address) { |
| err = -ENOMEM; |
| goto cleanup; |
| } |
| if (pclass != IA_CSS_PARAM_CLASS_PARAM) { |
| css_params->params[pclass][mem].address = hmm_alloc(size, HMM_BO_PRIVATE, 0, NULL, 0); |
| if (!css_params->params[pclass][mem].address) { |
| err = -ENOMEM; |
| goto cleanup; |
| } |
| } |
| } |
| } |
| } |
| return err; |
| cleanup: |
| ia_css_isp_param_destroy_isp_parameters(mem_params, css_params); |
| return err; |
| } |
| |
| void |
| ia_css_isp_param_destroy_isp_parameters( |
| struct ia_css_isp_param_host_segments *mem_params, |
| struct ia_css_isp_param_css_segments *css_params) |
| { |
| unsigned int mem, pclass; |
| |
| for (mem = 0; mem < IA_CSS_NUM_MEMORIES; mem++) { |
| for (pclass = 0; pclass < IA_CSS_NUM_PARAM_CLASSES; pclass++) { |
| kvfree(mem_params->params[pclass][mem].address); |
| if (css_params->params[pclass][mem].address) |
| hmm_free(css_params->params[pclass][mem].address); |
| mem_params->params[pclass][mem].address = NULL; |
| css_params->params[pclass][mem].address = 0x0; |
| } |
| } |
| } |
| |
| void |
| ia_css_isp_param_load_fw_params( |
| const char *fw, |
| union ia_css_all_memory_offsets *mem_offsets, |
| const struct ia_css_isp_param_memory_offsets *memory_offsets, |
| bool init) |
| { |
| unsigned int pclass; |
| |
| for (pclass = 0; pclass < IA_CSS_NUM_PARAM_CLASSES; pclass++) { |
| mem_offsets->array[pclass].ptr = NULL; |
| if (init) |
| mem_offsets->array[pclass].ptr = (void *)(fw + memory_offsets->offsets[pclass]); |
| } |
| } |
| |
| int |
| ia_css_isp_param_copy_isp_mem_if_to_ddr( |
| struct ia_css_isp_param_css_segments *ddr, |
| const struct ia_css_isp_param_host_segments *host, |
| enum ia_css_param_class pclass) { |
| unsigned int mem; |
| |
| for (mem = 0; mem < N_IA_CSS_ISP_MEMORIES; mem++) |
| { |
| size_t size = host->params[pclass][mem].size; |
| ia_css_ptr ddr_mem_ptr = ddr->params[pclass][mem].address; |
| char *host_mem_ptr = host->params[pclass][mem].address; |
| |
| if (size != ddr->params[pclass][mem].size) |
| return -EINVAL; |
| if (!size) |
| continue; |
| hmm_store(ddr_mem_ptr, host_mem_ptr, size); |
| } |
| return 0; |
| } |
| |
| void |
| ia_css_isp_param_enable_pipeline( |
| const struct ia_css_isp_param_host_segments *mem_params) |
| { |
| /* By protocol b0 of the mandatory uint32_t first field of the |
| input parameter is a disable bit*/ |
| short dmem_offset = 0; |
| |
| if (mem_params->params[IA_CSS_PARAM_CLASS_PARAM][IA_CSS_ISP_DMEM0].size == 0) |
| return; |
| |
| *(uint32_t *) |
| &mem_params->params[IA_CSS_PARAM_CLASS_PARAM][IA_CSS_ISP_DMEM0].address[dmem_offset] |
| = 0x0; |
| } |