Squashed backup commit (no shallow-clone history issues) of xiaomi-mt6833-dev/kernel_xiaomi_mt6833 (lineage-23.2 branch, upstream commit 9eece662e) plus all fixes applied to get everpal_defconfig building clean against a modern (GCC 15.2.0) toolchain -- see the previous commit message on the lineage-23.2 branch (also in this repo history is not available here since this is a squashed snapshot; full incremental history lives in the local DL380 checkout and the upstream GitHub remote). Upstream: https://github.com/xiaomi-mt6833-dev/kernel_xiaomi_mt6833 (lineage-23.2)
629 lines
16 KiB
C
629 lines
16 KiB
C
/*
|
|
* Copyright (c) 2019 MediaTek Inc.
|
|
* Author: Chungying Lu <chungying.lu@mediatek.com>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that 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 <linux/delay.h>
|
|
#include <linux/slab.h>
|
|
|
|
#include "vpu_load_image.h"
|
|
|
|
#define ALGO_IMAGES_NUM (2)
|
|
#define PARTITION_HEADER_SZ (0x200)
|
|
#define VPU_ALIGN_MASK (0xF)
|
|
|
|
#define VPU_IMAGE_FIRMWARE_INDEX (0)
|
|
#define VPU_IMAGE_MTK_ALGO_INDEX (1)
|
|
#define VPU_IMAGE_CUST_ALGO_INDEX (2)
|
|
#define VPU_IMAGE_ALGO_BASE_INDEX (VPU_IMAGE_MTK_ALGO_INDEX)
|
|
|
|
struct iram_desc {
|
|
uint32_t bin_offset;
|
|
uint32_t addr;
|
|
uint32_t mem_size;
|
|
};
|
|
|
|
struct iram_desc_header {
|
|
uint32_t iram_num;
|
|
struct iram_desc iram_desc[VPU_MAX_NUM_CODE_SEGMENTS];
|
|
};
|
|
|
|
static char *g_vpu_image_name[VPU_NUMS_IMAGE_HEADER] = {
|
|
"cam_vpu1.img",
|
|
"cam_vpu2.img",
|
|
"cam_vpu3.img"
|
|
};
|
|
|
|
static const uint32_t g_vpu_mva_reset_vector[] = {
|
|
VPU_MVA_RESET_VECTOR,
|
|
#if (MTK_VPU_CORE >= 2)
|
|
VPU2_MVA_RESET_VECTOR,
|
|
#endif
|
|
#if (MTK_VPU_CORE >= 3)
|
|
VPU3_MVA_RESET_VECTOR,
|
|
#endif
|
|
};
|
|
|
|
static const uint32_t g_vpu_mva_main_program[] = {
|
|
VPU_MVA_MAIN_PROGRAM,
|
|
#if (MTK_VPU_CORE >= 2)
|
|
VPU2_MVA_MAIN_PROGRAM,
|
|
#endif
|
|
#if (MTK_VPU_CORE >= 3)
|
|
VPU3_MVA_MAIN_PROGRAM,
|
|
#endif
|
|
};
|
|
|
|
static const uint32_t g_vpu_mva_kernel_lib[] = {
|
|
VPU_MVA_KERNEL_LIB,
|
|
#if (MTK_VPU_CORE >= 2)
|
|
VPU2_MVA_KERNEL_LIB,
|
|
#endif
|
|
#if (MTK_VPU_CORE >= 3)
|
|
VPU3_MVA_KERNEL_LIB,
|
|
#endif
|
|
};
|
|
|
|
static void vpu_unload_firmware(struct vpu_device *vpu_device);
|
|
static void vpu_unload_algo(struct vpu_device *vpu_device);
|
|
static void _vpu_unload_image(struct vpu_device *vpu_device);
|
|
|
|
static int vpu_load_firmware(struct vpu_device *vpu_device)
|
|
{
|
|
struct vpu_core *vpu_core = NULL;
|
|
struct vpu_shared_memory_param mem_param;
|
|
struct vpu_shared_memory *share_memory = NULL;
|
|
struct vpu_image_header *header = NULL;
|
|
struct vpu_code_segment *code_segment = NULL;
|
|
struct iram_desc_header *iram_desc_header[MTK_VPU_CORE] = {NULL};
|
|
struct iram_desc *iram_desc = NULL;
|
|
const struct firmware *fw = NULL;
|
|
uint64_t dst = 0;
|
|
uint32_t iram_bin_offset[MTK_VPU_CORE] = {0};
|
|
uint32_t iram_num = 0;
|
|
uint32_t dst_addr_mask = 0;
|
|
int i, core, len;
|
|
int ret = 0;
|
|
|
|
for (i = 0; i < vpu_device->core_num; i++) {
|
|
vpu_core = vpu_device->vpu_core[i];
|
|
|
|
/* Reset vector */
|
|
memset(&mem_param, 0x0, sizeof(mem_param));
|
|
mem_param.require_pa = true;
|
|
mem_param.size = VPU_SIZE_RESET_VECTOR;
|
|
mem_param.fixed_addr = g_vpu_mva_reset_vector[i];
|
|
ret = vpu_alloc_shared_memory(vpu_device,
|
|
&vpu_core->reset_vector,
|
|
&mem_param);
|
|
if (ret) {
|
|
LOG_ERR("fail to allocate reset vector!\n");
|
|
goto exit;
|
|
}
|
|
|
|
/* Main program */
|
|
memset(&mem_param, 0x0, sizeof(mem_param));
|
|
mem_param.require_pa = true;
|
|
mem_param.size = VPU_SIZE_MAIN_PROGRAM;
|
|
mem_param.fixed_addr = g_vpu_mva_main_program[i];
|
|
ret = vpu_alloc_shared_memory(vpu_device,
|
|
&vpu_core->main_program,
|
|
&mem_param);
|
|
if (ret) {
|
|
LOG_ERR("fail to allocate main program!\n");
|
|
goto exit;
|
|
}
|
|
|
|
/* Iram data */
|
|
memset(&mem_param, 0x0, sizeof(mem_param));
|
|
mem_param.require_pa = true;
|
|
mem_param.size = VPU_SIZE_MAIN_PROGRAM_IMEM;
|
|
ret = vpu_alloc_shared_memory(vpu_device, &vpu_core->iram_data,
|
|
&mem_param);
|
|
if (ret) {
|
|
LOG_ERR("fail to allocate iram data!\n");
|
|
goto exit;
|
|
}
|
|
|
|
iram_desc_header[i] =
|
|
(struct iram_desc_header *)(uintptr_t)vpu_core->iram_data->va;
|
|
iram_desc_header[i]->iram_num = 0;
|
|
iram_bin_offset[i] =
|
|
((sizeof(struct iram_desc_header) + VPU_ALIGN_MASK) &
|
|
~VPU_ALIGN_MASK);
|
|
|
|
vpu_core->iram_data_mva = (uint64_t)(vpu_core->iram_data->pa);
|
|
}
|
|
|
|
fw = vpu_device->fw[0];
|
|
|
|
header = &vpu_device->image_header[0];
|
|
memcpy((void *)header, fw->data + PARTITION_HEADER_SZ,
|
|
sizeof(struct vpu_image_header));
|
|
|
|
for (i = 0; i < header->code_segment_count; i++) {
|
|
code_segment = &header->code_segments[i];
|
|
|
|
for (core = 0; core < vpu_device->core_num; core++) {
|
|
if ((code_segment->vpu_core & (1 << core)) == 0)
|
|
continue;
|
|
|
|
vpu_core = vpu_device->vpu_core[core];
|
|
dst_addr_mask = code_segment->dst_addr & VPU_ADDR_MASK;
|
|
if (dst_addr_mask == g_vpu_mva_reset_vector[core]) {
|
|
share_memory = vpu_core->reset_vector;
|
|
dst = share_memory->va +
|
|
(code_segment->dst_addr -
|
|
g_vpu_mva_reset_vector[core]);
|
|
} else if (dst_addr_mask ==
|
|
g_vpu_mva_main_program[core]) {
|
|
share_memory = vpu_core->main_program;
|
|
dst = share_memory->va +
|
|
(code_segment->dst_addr -
|
|
g_vpu_mva_main_program[core]);
|
|
} else if (dst_addr_mask == 0x7FF00000) {
|
|
share_memory = vpu_core->iram_data;
|
|
iram_num = iram_desc_header[core]->iram_num;
|
|
iram_desc =
|
|
&iram_desc_header[core]->iram_desc[iram_num];
|
|
|
|
dst = share_memory->va + iram_bin_offset[core];
|
|
iram_desc->addr = code_segment->dst_addr;
|
|
iram_desc->bin_offset = iram_bin_offset[core];
|
|
iram_desc->mem_size = code_segment->length;
|
|
iram_desc_header[core]->iram_num++;
|
|
|
|
iram_bin_offset[core] +=
|
|
((iram_desc->mem_size + VPU_ALIGN_MASK)
|
|
& ~VPU_ALIGN_MASK);
|
|
} else {
|
|
break;
|
|
}
|
|
|
|
memcpy((void *)(uintptr_t)dst,
|
|
(fw->data + PARTITION_HEADER_SZ + code_segment->offset),
|
|
code_segment->file_size);
|
|
|
|
len = code_segment->length - code_segment->file_size;
|
|
if (len > 0) {
|
|
LOG_INF(
|
|
"[%s][%d] seg[%d]: memset size 0x%x from dst 0x%llx\n",
|
|
__func__, __LINE__, i, len, dst);
|
|
memset(
|
|
(void *)(uintptr_t)(dst + code_segment->file_size),
|
|
0, len);
|
|
}
|
|
}
|
|
}
|
|
|
|
exit:
|
|
if (fw)
|
|
release_firmware(fw);
|
|
|
|
vpu_device->fw[0] = NULL;
|
|
|
|
if (ret)
|
|
vpu_unload_firmware(vpu_device);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static void vpu_unload_firmware(struct vpu_device *vpu_device)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < vpu_device->core_num; i++)
|
|
vpu_unmap_mva_of_bin(vpu_device->vpu_core[i]);
|
|
|
|
memset((void *)&vpu_device->image_header[0], 0x0,
|
|
sizeof(struct vpu_image_header));
|
|
}
|
|
|
|
static int vpu_load_algo(struct vpu_device *vpu_device)
|
|
{
|
|
struct vpu_image_header *header[ALGO_IMAGES_NUM] = {NULL};
|
|
struct vpu_image_header *algo_image_header = NULL;
|
|
struct vpu_shared_memory_param mem_param;
|
|
struct vpu_shared_memory *share_memory = NULL;
|
|
struct vpu_algo_info *algo_info = NULL;
|
|
const struct firmware *fw[ALGO_IMAGES_NUM] = {NULL};
|
|
int i, j;
|
|
int num_algos[ALGO_IMAGES_NUM] = {0}, size_algos = 0;
|
|
int algos = 0, offs = 0;
|
|
int core_mask = 0;
|
|
int algo_images_num = 0;
|
|
int ret = 0;
|
|
#if 0
|
|
const char *line_bar =
|
|
"+------+-----+--------------------------------+--------+-----------+----------+"
|
|
;
|
|
#endif
|
|
|
|
/* load algo header by core */
|
|
for (i = 0; i < ALGO_IMAGES_NUM; i++) {
|
|
fw[i] = vpu_device->fw[i + 1];
|
|
|
|
header[i] = kzalloc(sizeof(struct vpu_image_header),
|
|
GFP_KERNEL);
|
|
if (header[i] == NULL) {
|
|
LOG_ERR("[%s][%d] alloc image header[%d] failed!\n",
|
|
__func__, __LINE__, i);
|
|
goto exit;
|
|
}
|
|
|
|
if (fw[i]) {
|
|
/* read header */
|
|
memcpy((void *)header[i],
|
|
fw[i]->data + PARTITION_HEADER_SZ,
|
|
sizeof(struct vpu_image_header));
|
|
algo_images_num++;
|
|
}
|
|
}
|
|
|
|
|
|
/* No algo image exist, but user can create algo by their own */
|
|
/* Hence return 0 */
|
|
if (algo_images_num == 0) {
|
|
ret = 0;
|
|
goto exit;
|
|
}
|
|
|
|
for (i = 0; i < vpu_device->core_num; i++)
|
|
core_mask |= (1 << i);
|
|
|
|
for (i = 0; i < ALGO_IMAGES_NUM; i++) {
|
|
for (j = 0; j < header[i]->algo_info_count; j++) {
|
|
algo_info = &header[i]->algo_infos[j];
|
|
if (algo_info->vpu_core & core_mask) {
|
|
size_algos +=
|
|
(algo_info->length + VPU_ALIGN_MASK)
|
|
& (~VPU_ALIGN_MASK);
|
|
num_algos[i]++;
|
|
algos++;
|
|
}
|
|
}
|
|
}
|
|
|
|
LOG_INF("total algo len = %d, num algo = %d\n", size_algos, algos);
|
|
|
|
memset(&mem_param, 0x0, sizeof(mem_param));
|
|
mem_param.require_pa = true;
|
|
mem_param.size = size_algos;
|
|
|
|
ret = vpu_alloc_shared_memory(vpu_device,
|
|
&vpu_device->algo_binary_data,
|
|
&mem_param);
|
|
if (ret) {
|
|
LOG_ERR("fail to allocate algo buffer!\n");
|
|
goto exit;
|
|
}
|
|
|
|
share_memory = vpu_device->algo_binary_data;
|
|
for (i = 0; i < vpu_device->core_num; i++)
|
|
vpu_device->vpu_core[i]->algo_data_mva = share_memory->pa;
|
|
|
|
for (i = 0; i < ALGO_IMAGES_NUM; i++) {
|
|
algo_image_header =
|
|
&vpu_device->image_header[VPU_IMAGE_ALGO_BASE_INDEX + i];
|
|
memcpy(algo_image_header, header[i],
|
|
sizeof(struct vpu_image_header));
|
|
algo_image_header->algo_info_count = num_algos[i];
|
|
|
|
algos = 0;
|
|
if (fw[i]) {
|
|
for (j = 0; j < header[i]->algo_info_count; j++) {
|
|
algo_info = &header[i]->algo_infos[j];
|
|
if ((algo_info->vpu_core & core_mask) == 0x0)
|
|
continue;
|
|
|
|
/* read algo */
|
|
memcpy((void *)(uintptr_t)
|
|
(share_memory->va + offs),
|
|
fw[i]->data + PARTITION_HEADER_SZ
|
|
+ algo_info->offset,
|
|
algo_info->length);
|
|
|
|
/* copy algo info */
|
|
memcpy(&algo_image_header->algo_infos[algos],
|
|
algo_info,
|
|
sizeof(struct vpu_algo_info));
|
|
|
|
algo_image_header->algo_infos[algos].offset =
|
|
VPU_OFFSET_ALGO_AREA + offs;
|
|
|
|
offs += (algo_info->length + VPU_ALIGN_MASK)
|
|
& (~VPU_ALIGN_MASK);
|
|
algos++;
|
|
}
|
|
}
|
|
}
|
|
|
|
#if 0
|
|
LOG_DBG("%s\n", line_bar);
|
|
LOG_DBG("|%-6s|%-5s|%-32s|%-8s|%-11s|%-10s|\n",
|
|
"Num", "Image", "Name", "Core", "Offset", "Length");
|
|
LOG_DBG("%s\n", line_bar);
|
|
for (i = 0; i < ALGO_IMAGES_NUM; i++) {
|
|
algo_image_header = &vpu_device->image_header[i + 1];
|
|
for (j = 0; j < algo_image_header->algo_info_count; j++) {
|
|
algo_info = &algo_image_header->algo_infos[j];
|
|
LOG_DBG("|%-6d|%-5d|%-32s|0x%-6lx|0x%-9x|0x%-8x|\n",
|
|
j, i, algo_info->name,
|
|
(unsigned long)(algo_info->vpu_core),
|
|
algo_info->offset,
|
|
algo_info->length);
|
|
}
|
|
}
|
|
LOG_DBG("%s\n", line_bar);
|
|
#endif
|
|
|
|
for (i = 0; i < vpu_device->core_num; i++)
|
|
vpu_total_algo_num(vpu_device->vpu_core[i]);
|
|
|
|
exit:
|
|
for (i = 0; i < ALGO_IMAGES_NUM; i++) {
|
|
if (fw[i])
|
|
release_firmware(fw[i]);
|
|
|
|
vpu_device->fw[i + 1] = NULL;
|
|
|
|
if (header[i] != NULL)
|
|
kfree(header[i]);
|
|
}
|
|
|
|
if (ret)
|
|
vpu_unload_algo(vpu_device);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static void vpu_unload_algo(struct vpu_device *vpu_device)
|
|
{
|
|
struct vpu_image_header *algo_image_header = NULL;
|
|
int i;
|
|
|
|
if (vpu_device->algo_binary_data) {
|
|
vpu_free_shared_memory(vpu_device,
|
|
vpu_device->algo_binary_data);
|
|
vpu_device->algo_binary_data = NULL;
|
|
}
|
|
|
|
for (i = 0; i < vpu_device->core_num; i++)
|
|
vpu_device->vpu_core[i]->algo_data_mva = 0;
|
|
|
|
for (i = 0; i < ALGO_IMAGES_NUM; i++) {
|
|
algo_image_header =
|
|
&vpu_device->image_header[VPU_IMAGE_ALGO_BASE_INDEX + i]
|
|
;
|
|
memset((void *)algo_image_header, 0x0,
|
|
sizeof(struct vpu_image_header));
|
|
}
|
|
}
|
|
|
|
static void vpu_request_firmware_cbk(const struct firmware *fw, void *context)
|
|
{
|
|
struct vpu_device *vpu_device = NULL;
|
|
int i, index = 0;
|
|
int ret = 0;
|
|
|
|
vpu_device = ((struct vpu_image_ctx *)context)->vpu_device;
|
|
index = ((struct vpu_image_ctx *)context)->vpu_image_index;
|
|
|
|
mutex_lock(&vpu_device->vpu_load_image_lock);
|
|
|
|
vpu_device->fw[index] = fw;
|
|
vpu_device->vpu_req_firmware_cbk[index] = true;
|
|
|
|
if (!fw) {
|
|
if (index == VPU_IMAGE_FIRMWARE_INDEX) {
|
|
LOG_ERR("[%s][%d] load firmware failed!\n",
|
|
__func__, __LINE__);
|
|
vpu_device->vpu_load_image_state =
|
|
VPU_LOAD_IMAGE_FAILED;
|
|
goto exit;
|
|
}
|
|
|
|
/* Even one of algo image is null, */
|
|
/* still have to enter vpu_load_algo */
|
|
LOG_ERR("%s: firmware %d load failed\n", __func__, index);
|
|
}
|
|
|
|
switch (index) {
|
|
case VPU_IMAGE_FIRMWARE_INDEX:
|
|
ret = vpu_load_firmware(vpu_device);
|
|
if (ret) {
|
|
LOG_ERR("[%s][%d] vpu_load_firmware failed!\n",
|
|
__func__, __LINE__);
|
|
vpu_device->vpu_load_image_state =
|
|
VPU_LOAD_IMAGE_FAILED;
|
|
}
|
|
break;
|
|
|
|
case VPU_IMAGE_MTK_ALGO_INDEX:
|
|
case VPU_IMAGE_CUST_ALGO_INDEX:
|
|
if (vpu_device->vpu_req_firmware_cbk[VPU_IMAGE_MTK_ALGO_INDEX]
|
|
&& vpu_device->vpu_req_firmware_cbk[VPU_IMAGE_CUST_ALGO_INDEX]) {
|
|
ret = vpu_load_algo(vpu_device);
|
|
if (ret)
|
|
LOG_ERR("[%s][%d] vpu_load_algo failed!\n",
|
|
__func__, __LINE__);
|
|
}
|
|
break;
|
|
}
|
|
|
|
exit:
|
|
for (i = 0; i < VPU_NUMS_IMAGE_HEADER; ++i)
|
|
if (vpu_device->vpu_req_firmware_cbk[i] == false)
|
|
break;
|
|
|
|
if (i == VPU_NUMS_IMAGE_HEADER) {
|
|
if (vpu_device->vpu_load_image_state
|
|
== VPU_LOAD_IMAGE_LOADING) {
|
|
vpu_device->vpu_load_image_state =
|
|
VPU_LOAD_IMAGE_LOADED;
|
|
LOG_INF("[%s][%d] vpu load image done!\n",
|
|
__func__, __LINE__);
|
|
} else {
|
|
_vpu_unload_image(vpu_device);
|
|
LOG_INF("[%s][%d] vpu load image failed! state: %d\n",
|
|
__func__, __LINE__,
|
|
vpu_device->vpu_load_image_state);
|
|
}
|
|
|
|
kfree(vpu_device->vpu_image_ctx);
|
|
vpu_device->vpu_image_ctx = NULL;
|
|
}
|
|
|
|
mutex_unlock(&vpu_device->vpu_load_image_lock);
|
|
}
|
|
|
|
int vpu_load_image(struct vpu_device *vpu_device)
|
|
{
|
|
struct vpu_image_header *image_header = NULL;
|
|
int i;
|
|
int ret = 0;
|
|
|
|
/* vpu_load_image_state: unload -> loading -> loaded */
|
|
|
|
mutex_lock(&vpu_device->vpu_load_image_lock);
|
|
|
|
if (vpu_device->vpu_load_image_state != VPU_LOAD_IMAGE_UNLOAD)
|
|
goto out;
|
|
|
|
vpu_device->vpu_load_image_state = VPU_LOAD_IMAGE_LOADING;
|
|
|
|
|
|
LOG_INF("[%s][%d] vpu load image start...\n", __func__, __LINE__);
|
|
|
|
image_header = kzalloc(
|
|
sizeof(struct vpu_image_header) * VPU_NUMS_IMAGE_HEADER,
|
|
GFP_KERNEL);
|
|
ret = (image_header) ? 0 : -ENOMEM;
|
|
if (ret) {
|
|
LOG_ERR("[%s][%d] alloc image header failed!\n",
|
|
__func__, __LINE__);
|
|
goto exit;
|
|
}
|
|
|
|
vpu_device->image_header = image_header;
|
|
|
|
vpu_device->vpu_image_ctx = kzalloc(
|
|
sizeof(struct vpu_image_ctx) * VPU_NUMS_IMAGE_HEADER,
|
|
GFP_KERNEL);
|
|
ret = (vpu_device->vpu_image_ctx) ? 0 : -ENOMEM;
|
|
if (ret) {
|
|
LOG_ERR("[%s][%d] alloc vpu image ctx failed!\n",
|
|
__func__, __LINE__);
|
|
goto exit;
|
|
}
|
|
|
|
for (i = 0; i < VPU_NUMS_IMAGE_HEADER; i++) {
|
|
vpu_device->vpu_image_ctx[i].vpu_device = vpu_device;
|
|
vpu_device->vpu_image_ctx[i].vpu_image_index = i;
|
|
|
|
ret = request_firmware_nowait(THIS_MODULE, 1,
|
|
g_vpu_image_name[i],
|
|
vpu_device->dev, GFP_KERNEL,
|
|
&vpu_device->vpu_image_ctx[i],
|
|
vpu_request_firmware_cbk);
|
|
if (ret)
|
|
LOG_ERR("[%s][%d] request_firmware_nowait %d failed!\n",
|
|
__func__, __LINE__, i);
|
|
}
|
|
|
|
exit:
|
|
if (ret) {
|
|
if (image_header != NULL) {
|
|
kfree(image_header);
|
|
vpu_device->image_header = NULL;
|
|
}
|
|
|
|
vpu_device->vpu_load_image_state = VPU_LOAD_IMAGE_UNLOAD;
|
|
}
|
|
|
|
out:
|
|
mutex_unlock(&vpu_device->vpu_load_image_lock);
|
|
return ret;
|
|
}
|
|
|
|
static void _vpu_unload_image(struct vpu_device *vpu_device)
|
|
{
|
|
/* unload algo */
|
|
vpu_unload_algo(vpu_device);
|
|
|
|
/* unload firmware */
|
|
vpu_unload_firmware(vpu_device);
|
|
|
|
kfree(vpu_device->image_header);
|
|
|
|
vpu_device->image_header = NULL;
|
|
}
|
|
|
|
int vpu_unload_image(struct vpu_device *vpu_device)
|
|
{
|
|
mutex_lock(&vpu_device->vpu_load_image_lock);
|
|
|
|
if (vpu_device->vpu_load_image_state != VPU_LOAD_IMAGE_LOADED)
|
|
goto exit;
|
|
|
|
_vpu_unload_image(vpu_device);
|
|
vpu_device->vpu_load_image_state = VPU_LOAD_IMAGE_UNLOAD;
|
|
|
|
exit:
|
|
mutex_unlock(&vpu_device->vpu_load_image_lock);
|
|
|
|
LOG_INF("[%s][%d] unload image\n", __func__, __LINE__);
|
|
return 0;
|
|
}
|
|
|
|
int vpu_check_load_image_state(struct vpu_device *vpu_device)
|
|
{
|
|
int ret = 1;
|
|
|
|
/* ret = 0: loaded or no need to load */
|
|
/* ret = 1: unload or loading */
|
|
/* ret = -1: load image failed */
|
|
|
|
mutex_lock(&vpu_device->vpu_load_image_lock);
|
|
|
|
if ((vpu_device->vpu_load_image_state == VPU_LOAD_IMAGE_NONE)
|
|
|| (vpu_device->vpu_load_image_state == VPU_LOAD_IMAGE_LOADED))
|
|
ret = 0;
|
|
else if (vpu_device->vpu_load_image_state == VPU_LOAD_IMAGE_FAILED)
|
|
ret = -1;
|
|
|
|
mutex_unlock(&vpu_device->vpu_load_image_lock);
|
|
return ret;
|
|
}
|
|
|
|
int vpu_wait_load_image(struct vpu_device *vpu_device)
|
|
{
|
|
int count = 0, ret = 0;
|
|
|
|
while ((ret = vpu_check_load_image_state(vpu_device)) != 0) {
|
|
if (ret == -1) {
|
|
break;
|
|
} else if (count++ == VPU_LOAD_IMAGE_USLEEP_TIMEOUT) {
|
|
LOG_INF("[%s][%d] wait vpu load image timeout!\n",
|
|
__func__, __LINE__);
|
|
ret = -1;
|
|
break;
|
|
}
|
|
|
|
usleep_range(VPU_LOAD_IMAGE_USLEEP_MIN,
|
|
VPU_LOAD_IMAGE_USLEEP_MAX);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|