/*
|
* Copyright 2020 Rockchip Electronics Co. LTD
|
*
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
* you may not use this file except in compliance with the License.
|
* You may obtain a copy of the License at
|
*
|
* http://www.apache.org/licenses/LICENSE-2.0
|
*
|
* Unless required by applicable law or agreed to in writing, software
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* See the License for the specific language governing permissions and
|
* limitations under the License.
|
*/
|
|
#define MODULE_TAG "mpp_device"
|
|
#include <string.h>
|
|
#include "mpp_env.h"
|
#include "mpp_mem.h"
|
#include "mpp_common.h"
|
|
#include "mpp_platform.h"
|
#include "mpp_device_debug.h"
|
#include "mpp_service_api.h"
|
#include "vcodec_service_api.h"
|
|
typedef struct MppDevImpl_t {
|
MppClientType type;
|
|
void *ctx;
|
const MppDevApi *api;
|
} MppDevImpl;
|
|
RK_U32 mpp_device_debug = 0;
|
|
MPP_RET mpp_dev_init(MppDev *ctx, MppClientType type)
|
{
|
if (NULL == ctx) {
|
mpp_err_f("found NULL input ctx\n");
|
return MPP_ERR_NULL_PTR;
|
}
|
|
mpp_env_get_u32("mpp_device_debug", &mpp_device_debug, 0);
|
|
*ctx = NULL;
|
|
RK_U32 codec_type = mpp_get_vcodec_type();
|
if (!(codec_type & (1 << type))) {
|
mpp_err_f("found unsupported client type %d in platform %x\n",
|
type, codec_type);
|
return MPP_ERR_VALUE;
|
}
|
|
MppIoctlVersion ioctl_version = mpp_get_ioctl_version();
|
const MppDevApi *api = NULL;
|
|
switch (ioctl_version) {
|
case IOCTL_VCODEC_SERVICE : {
|
api = &vcodec_service_api;
|
} break;
|
case IOCTL_MPP_SERVICE_V1 : {
|
api = &mpp_service_api;
|
} break;
|
default : {
|
mpp_err_f("invalid ioctl verstion %d\n", ioctl_version);
|
return MPP_NOK;
|
} break;
|
}
|
|
MppDevImpl *impl = mpp_calloc(MppDevImpl, 1);
|
void *impl_ctx = mpp_calloc_size(void, api->ctx_size);
|
if (NULL == impl || NULL == impl_ctx) {
|
mpp_err_f("malloc failed impl %p impl_ctx %p\n", impl, impl_ctx);
|
MPP_FREE(impl);
|
MPP_FREE(impl_ctx);
|
return MPP_ERR_MALLOC;
|
}
|
|
impl->ctx = impl_ctx;
|
impl->api = api;
|
impl->type = type;
|
*ctx = impl;
|
|
return api->init(impl_ctx, type);
|
}
|
|
MPP_RET mpp_dev_deinit(MppDev ctx)
|
{
|
if (NULL == ctx) {
|
mpp_err_f("found NULL input ctx\n");
|
return MPP_ERR_NULL_PTR;
|
}
|
|
MppDevImpl *p = (MppDevImpl *)ctx;
|
MPP_RET ret = MPP_OK;
|
|
if (p->api && p->api->deinit && p->ctx)
|
ret = p->api->deinit(p->ctx);
|
|
MPP_FREE(p->ctx);
|
MPP_FREE(p);
|
|
return ret;
|
}
|
|
MPP_RET mpp_dev_ioctl(MppDev ctx, RK_S32 cmd, void *param)
|
{
|
if (NULL == ctx) {
|
mpp_err_f("found NULL input ctx\n");
|
return MPP_ERR_NULL_PTR;
|
}
|
|
MppDevImpl *p = (MppDevImpl *)ctx;
|
const MppDevApi *api = p->api;
|
void *impl_ctx = p->ctx;
|
MPP_RET ret = MPP_OK;
|
|
if (NULL == impl_ctx || NULL == api)
|
return ret;
|
|
switch (cmd) {
|
case MPP_DEV_BATCH_ON : {
|
if (api->attach)
|
ret = api->attach(impl_ctx);
|
} break;
|
case MPP_DEV_BATCH_OFF : {
|
if (api->detach)
|
ret = api->detach(impl_ctx);
|
} break;
|
case MPP_DEV_DELIMIT : {
|
if (api->delimit)
|
ret = api->delimit(impl_ctx);
|
} break;
|
case MPP_DEV_SET_CB_CTX: {
|
if (api->set_cb_ctx)
|
ret = api->set_cb_ctx(impl_ctx, param);
|
} break;
|
case MPP_DEV_REG_WR : {
|
if (api->reg_wr)
|
ret = api->reg_wr(impl_ctx, param);
|
} break;
|
case MPP_DEV_REG_RD : {
|
if (api->reg_rd)
|
ret = api->reg_rd(impl_ctx, param);
|
} break;
|
case MPP_DEV_REG_OFFSET : {
|
if (api->reg_offset)
|
ret = api->reg_offset(impl_ctx, param);
|
} break;
|
case MPP_DEV_REG_OFFS : {
|
if (api->reg_offs)
|
ret = api->reg_offs(impl_ctx, param);
|
} break;
|
case MPP_DEV_RCB_INFO : {
|
if (api->rcb_info)
|
ret = api->rcb_info(impl_ctx, param);
|
} break;
|
case MPP_DEV_SET_INFO : {
|
if (api->set_info)
|
ret = api->set_info(impl_ctx, param);
|
} break;
|
case MPP_DEV_CMD_SEND : {
|
if (api->cmd_send)
|
ret = api->cmd_send(impl_ctx);
|
} break;
|
case MPP_DEV_CMD_POLL : {
|
if (api->cmd_poll)
|
ret = api->cmd_poll(impl_ctx, param);
|
} break;
|
default : {
|
mpp_err_f("invalid cmd %d\n", cmd);
|
} break;
|
}
|
|
return ret;
|
}
|
|
MPP_RET mpp_dev_set_reg_offset(MppDev dev, RK_S32 index, RK_U32 offset)
|
{
|
MppDevRegOffsetCfg trans_cfg;
|
|
trans_cfg.reg_idx = index;
|
trans_cfg.offset = offset;
|
|
return mpp_dev_ioctl(dev, MPP_DEV_REG_OFFSET, &trans_cfg);
|
}
|
|
/* register offset multi config */
|
MPP_RET mpp_dev_multi_offset_init(MppDevRegOffCfgs **cfgs, RK_S32 size)
|
{
|
RK_S32 cfg_size = sizeof(MppDevRegOffCfgs) + size * sizeof(MppDevRegOffsetCfg);
|
MppDevRegOffCfgs *p = NULL;
|
|
if (NULL == cfgs || size <= 0) {
|
mpp_err_f("invalid pointer %p size %d\n", cfgs, size);
|
return MPP_NOK;
|
}
|
|
p = mpp_calloc_size(MppDevRegOffCfgs, cfg_size);
|
if (p)
|
p->size = size;
|
|
*cfgs = p;
|
|
return (p) ? MPP_OK : MPP_NOK;
|
}
|
|
MPP_RET mpp_dev_multi_offset_deinit(MppDevRegOffCfgs *cfgs)
|
{
|
MPP_FREE(cfgs);
|
|
return MPP_OK;
|
}
|
|
MPP_RET mpp_dev_multi_offset_reset(MppDevRegOffCfgs *cfgs)
|
{
|
if (cfgs) {
|
memset(cfgs->cfgs, 0, cfgs->count * sizeof(cfgs->cfgs[0]));
|
cfgs->count = 0;
|
}
|
|
return MPP_OK;
|
}
|
|
MPP_RET mpp_dev_multi_offset_update(MppDevRegOffCfgs *cfgs, RK_S32 index, RK_U32 offset)
|
{
|
MppDevRegOffsetCfg *cfg;
|
RK_S32 count;
|
RK_S32 i;
|
|
if (NULL == cfgs)
|
return MPP_NOK;
|
|
if (cfgs->count >= cfgs->size) {
|
mpp_err_f("invalid cfgs count %d : %d\n", cfgs->count, cfgs->size);
|
return MPP_NOK;
|
}
|
|
count = cfgs->count;
|
cfg = cfgs->cfgs;
|
|
for (i = 0; i < count; i++, cfg++) {
|
|
if (cfg->reg_idx == (RK_U32)index) {
|
cfg->offset = offset;
|
return MPP_OK;
|
}
|
}
|
|
cfg->reg_idx = index;
|
cfg->offset = offset;
|
cfgs->count++;
|
|
return MPP_OK;
|
}
|