diff options
Diffstat (limited to 'drivers/staging/media/atomisp/pci/sh_css_firmware.c')
-rw-r--r-- | drivers/staging/media/atomisp/pci/sh_css_firmware.c | 127 |
1 files changed, 89 insertions, 38 deletions
diff --git a/drivers/staging/media/atomisp/pci/sh_css_firmware.c b/drivers/staging/media/atomisp/pci/sh_css_firmware.c index eb3c01574853..d4ab15b6d1ac 100644 --- a/drivers/staging/media/atomisp/pci/sh_css_firmware.c +++ b/drivers/staging/media/atomisp/pci/sh_css_firmware.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Support for Intel Camera Imaging ISP subsystem. * Copyright (c) 2015, Intel Corporation. @@ -12,9 +13,12 @@ * more details. */ +#include <linux/string.h> /* for memcpy() */ #include <linux/slab.h> #include <linux/vmalloc.h> +#include "hmm.h" + #include <math_support.h> #include "platform_support.h" #include "sh_css_firmware.h" @@ -24,9 +28,7 @@ #include "sh_css_internal.h" #include "ia_css_isp_param.h" -#include "memory_access.h" #include "assert_support.h" -#include "string_support.h" #include "isp.h" /* PMEM_WIDTH_LOG2 */ @@ -74,13 +76,13 @@ char *sh_css_get_fw_version(void) */ /* Setup sp/sp1 binary */ -static enum ia_css_err +static int setup_binary(struct ia_css_fw_info *fw, const char *fw_data, struct ia_css_fw_info *sh_css_fw, unsigned int binary_id) { const char *blob_data; if ((!fw) || (!fw_data)) - return IA_CSS_ERR_INVALID_ARGUMENTS; + return -EINVAL; blob_data = fw_data + fw->blob.offset; @@ -88,16 +90,16 @@ setup_binary(struct ia_css_fw_info *fw, const char *fw_data, sh_css_fw->blob.code = vmalloc(fw->blob.size); if (!sh_css_fw->blob.code) - return IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; + return -ENOMEM; memcpy((void *)sh_css_fw->blob.code, blob_data, fw->blob.size); sh_css_fw->blob.data = (char *)sh_css_fw->blob.code + fw->blob.data_source; fw_minibuffer[binary_id].buffer = sh_css_fw->blob.code; - return IA_CSS_SUCCESS; + return 0; } -enum ia_css_err +int sh_css_load_blob_info(const char *fw, const struct ia_css_fw_info *bi, struct ia_css_blob_descr *bd, unsigned int index) { @@ -105,7 +107,7 @@ sh_css_load_blob_info(const char *fw, const struct ia_css_fw_info *bi, const unsigned char *blob; if ((!fw) || (!bd)) - return IA_CSS_ERR_INVALID_ARGUMENTS; + return -EINVAL; /* Special case: only one binary in fw */ if (!bi) bi = (const struct ia_css_fw_info *)fw; @@ -117,11 +119,11 @@ sh_css_load_blob_info(const char *fw, const struct ia_css_fw_info *bi, if (bi->blob.size != bi->blob.text_size + bi->blob.icache_size + bi->blob.data_size + bi->blob.padding_size) { /* sanity check, note the padding bytes added for section to DDR alignment */ - return IA_CSS_ERR_INVALID_ARGUMENTS; + return -EINVAL; } if ((bi->blob.offset % (1UL << (ISP_PMEM_WIDTH_LOG2 - 3))) != 0) - return IA_CSS_ERR_INVALID_ARGUMENTS; + return -EINVAL; bd->blob = blob; bd->header = *bi; @@ -132,7 +134,7 @@ sh_css_load_blob_info(const char *fw, const struct ia_css_fw_info *bi, namebuffer = kstrdup(name, GFP_KERNEL); if (!namebuffer) - return IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; + return -ENOMEM; bd->name = fw_minibuffer[index].name = namebuffer; } else { @@ -149,7 +151,7 @@ sh_css_load_blob_info(const char *fw, const struct ia_css_fw_info *bi, statestruct_size, GFP_KERNEL); if (!parambuf) - return IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; + return -ENOMEM; bd->mem_offsets.array[IA_CSS_PARAM_CLASS_PARAM].ptr = NULL; bd->mem_offsets.array[IA_CSS_PARAM_CLASS_CONFIG].ptr = NULL; @@ -177,7 +179,7 @@ sh_css_load_blob_info(const char *fw, const struct ia_css_fw_info *bi, bd->mem_offsets.array[IA_CSS_PARAM_CLASS_STATE].ptr = parambuf + paramstruct_size + configstruct_size; } - return IA_CSS_SUCCESS; + return 0; } bool @@ -187,7 +189,7 @@ sh_css_check_firmware_version(struct device *dev, const char *fw_data) const char *release_version; - if (!atomisp_hw_is_isp2401) + if (!IS_ISP2401) release_version = isp2400_release_version; else release_version = isp2401_release_version; @@ -202,19 +204,33 @@ sh_css_check_firmware_version(struct device *dev, const char *fw_data) } /* For now, let's just accept a wrong version, even if wrong */ - return true; + return 0; } -enum ia_css_err +static const char * const fw_type_name[] = { + [ia_css_sp_firmware] = "SP", + [ia_css_isp_firmware] = "ISP", + [ia_css_bootloader_firmware] = "BootLoader", + [ia_css_acc_firmware] = "accel", +}; + +static const char * const fw_acc_type_name[] = { + [IA_CSS_ACC_NONE] = "Normal", + [IA_CSS_ACC_OUTPUT] = "Accel for output", + [IA_CSS_ACC_VIEWFINDER] = "Accel for viewfinder", + [IA_CSS_ACC_STANDALONE] = "Stand-alone accel", +}; + +int sh_css_load_firmware(struct device *dev, const char *fw_data, unsigned int fw_size) { unsigned int i; struct ia_css_fw_info *binaries; struct sh_css_fw_bi_file_h *file_header; - bool valid_firmware = false; + int ret; const char *release_version; - if (!atomisp_hw_is_isp2401) + if (!IS_ISP2401) release_version = isp2400_release_version; else release_version = isp2401_release_version; @@ -223,21 +239,21 @@ sh_css_load_firmware(struct device *dev, const char *fw_data, file_header = &firmware_header->file_header; binaries = &firmware_header->binary_header; strscpy(FW_rel_ver_name, file_header->version, min(sizeof(FW_rel_ver_name), sizeof(file_header->version))); - valid_firmware = sh_css_check_firmware_version(dev, fw_data); - if (!valid_firmware) { + ret = sh_css_check_firmware_version(dev, fw_data); + if (ret) { IA_CSS_ERROR("CSS code version (%s) and firmware version (%s) mismatch!", file_header->version, release_version); - return IA_CSS_ERR_VERSION_MISMATCH; + return -EINVAL; } else { IA_CSS_LOG("successfully load firmware version %s", release_version); } /* some sanity checks */ if (!fw_data || fw_size < sizeof(struct sh_css_fw_bi_file_h)) - return IA_CSS_ERR_INTERNAL_ERROR; + return -EINVAL; if (file_header->h_size != sizeof(struct sh_css_fw_bi_file_h)) - return IA_CSS_ERR_INTERNAL_ERROR; + return -EINVAL; sh_css_num_binaries = file_header->binary_nr; /* Only allocate memory for ISP blob info */ @@ -247,7 +263,7 @@ sh_css_load_firmware(struct device *dev, const char *fw_data, (sh_css_num_binaries - NUM_OF_SPS) * sizeof(*sh_css_blob_info), GFP_KERNEL); if (!sh_css_blob_info) - return IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; + return -ENOMEM; } else { sh_css_blob_info = NULL; } @@ -255,7 +271,7 @@ sh_css_load_firmware(struct device *dev, const char *fw_data, fw_minibuffer = kcalloc(sh_css_num_binaries, sizeof(struct fw_param), GFP_KERNEL); if (!fw_minibuffer) - return IA_CSS_ERR_CANNOT_ALLOCATE_MEMORY; + return -ENOMEM; for (i = 0; i < sh_css_num_binaries; i++) { @@ -265,36 +281,71 @@ sh_css_load_firmware(struct device *dev, const char *fw_data, cause issues for drivers */ static struct ia_css_blob_descr bd; - enum ia_css_err err; + int err; err = sh_css_load_blob_info(fw_data, bi, &bd, i); - if (err != IA_CSS_SUCCESS) - return IA_CSS_ERR_INTERNAL_ERROR; + if (err) + return -EINVAL; if (bi->blob.offset + bi->blob.size > fw_size) - return IA_CSS_ERR_INTERNAL_ERROR; + return -EINVAL; + + switch (bd.header.type) { + case ia_css_isp_firmware: + if (bd.header.info.isp.type > IA_CSS_ACC_STANDALONE) { + dev_err(dev, "binary #%2d: invalid SP type\n", + i); + return -EINVAL; + } + + dev_dbg(dev, + "binary #%-2d type %s (%s), binary id is %2d: %s\n", + i, + fw_type_name[bd.header.type], + fw_acc_type_name[bd.header.info.isp.type], + bd.header.info.isp.sp.id, + bd.name); + break; + case ia_css_sp_firmware: + case ia_css_bootloader_firmware: + case ia_css_acc_firmware: + dev_dbg(dev, + "binary #%-2d type %s: %s\n", + i, fw_type_name[bd.header.type], + bd.name); + break; + default: + if (bd.header.info.isp.type > IA_CSS_ACC_STANDALONE) { + dev_err(dev, + "binary #%2d: invalid firmware type\n", + i); + return -EINVAL; + } + break; + } if (bi->type == ia_css_sp_firmware) { if (i != SP_FIRMWARE) - return IA_CSS_ERR_INTERNAL_ERROR; + return -EINVAL; err = setup_binary(bi, fw_data, &sh_css_sp_fw, i); - if (err != IA_CSS_SUCCESS) + if (err) return err; + } else { /* All subsequent binaries (including bootloaders) (i>NUM_OF_SPS) are ISP firmware */ if (i < NUM_OF_SPS) - return IA_CSS_ERR_INTERNAL_ERROR; + return -EINVAL; if (bi->type != ia_css_isp_firmware) - return IA_CSS_ERR_INTERNAL_ERROR; + return -EINVAL; if (!sh_css_blob_info) /* cannot happen but KW does not see this */ - return IA_CSS_ERR_INTERNAL_ERROR; + return -EINVAL; sh_css_blob_info[i - NUM_OF_SPS] = bd; } } - return IA_CSS_SUCCESS; + return 0; } void sh_css_unload_firmware(void) @@ -319,15 +370,15 @@ void sh_css_unload_firmware(void) sh_css_num_binaries = 0; } -hrt_vaddress +ia_css_ptr sh_css_load_blob(const unsigned char *blob, unsigned int size) { - hrt_vaddress target_addr = mmgr_malloc(size); + ia_css_ptr target_addr = hmm_alloc(size, HMM_BO_PRIVATE, 0, NULL, 0); /* this will allocate memory aligned to a DDR word boundary which is required for the CSS DMA to read the instructions. */ assert(blob); if (target_addr) - mmgr_store(target_addr, blob, size); + hmm_store(target_addr, blob, size); return target_addr; } |