Files
android_kernel_samsung_sm86…/driver/vidc/src/msm_vidc.c
Maheshwar Ajja 7509e9f16b video: driver: add power changes
Add or amend below functionalities
- scale clocks
- scale buses
- buffer counts
- buffer sizes

Change-Id: I3cddbb7112cd85a84cf86256134059f52b66a3af
Signed-off-by: Maheshwar Ajja <majja@codeaurora.org>
2020-12-21 15:31:54 -08:00

863 righe
22 KiB
C

// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
*/
#include "msm_vidc.h"
#include "msm_vidc_core.h"
#include "msm_vidc_inst.h"
#include "msm_vdec.h"
#include "msm_venc.h"
#include "msm_vidc_internal.h"
#include "msm_vidc_driver.h"
#include "msm_vidc_vb2.h"
#include "msm_vidc_v4l2.h"
#include "msm_vidc_debug.h"
#include "msm_vidc_control.h"
#include "msm_vidc_power.h"
#define MSM_VIDC_DRV_NAME "msm_vidc_driver"
/* kernel/msm-4.19 */
#define MSM_VIDC_VERSION ((0 << 16) + (4 << 8) + 19)
#define MAX_EVENTS 30
bool valid_v4l2_buffer(struct v4l2_buffer *b,
struct msm_vidc_inst *inst)
{
return true;
}
static int get_poll_flags(struct msm_vidc_inst *inst, u32 port)
{
int poll = 0;
struct vb2_queue *q = NULL;
struct vb2_buffer *vb = NULL;
unsigned long flags = 0;
if (!inst || port >= MAX_PORT) {
d_vpr_e("%s: invalid params, inst %pK, port %d\n",
__func__, inst, port);
return poll;
}
q = &inst->vb2q[port];
spin_lock_irqsave(&q->done_lock, flags);
if (!list_empty(&q->done_list))
vb = list_first_entry(&q->done_list, struct vb2_buffer,
done_entry);
if (vb && (vb->state == VB2_BUF_STATE_DONE ||
vb->state == VB2_BUF_STATE_ERROR)) {
if (port == OUTPUT_PORT || port == OUTPUT_META_PORT)
poll |= POLLIN | POLLRDNORM;
else if (port == INPUT_PORT || port == INPUT_META_PORT)
poll |= POLLOUT | POLLWRNORM;
}
spin_unlock_irqrestore(&q->done_lock, flags);
return poll;
}
int msm_vidc_poll(void *instance, struct file *filp,
struct poll_table_struct *wait)
{
int poll = 0;
struct msm_vidc_inst *inst = instance;
if (!inst) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
poll_wait(filp, &inst->event_handler.wait, wait);
poll_wait(filp, &inst->vb2q[INPUT_META_PORT].done_wq, wait);
poll_wait(filp, &inst->vb2q[OUTPUT_META_PORT].done_wq, wait);
poll_wait(filp, &inst->vb2q[INPUT_PORT].done_wq, wait);
poll_wait(filp, &inst->vb2q[OUTPUT_PORT].done_wq, wait);
if (v4l2_event_pending(&inst->event_handler))
poll |= POLLPRI;
poll |= get_poll_flags(inst, INPUT_META_PORT);
poll |= get_poll_flags(inst, OUTPUT_META_PORT);
poll |= get_poll_flags(inst, INPUT_PORT);
poll |= get_poll_flags(inst, OUTPUT_PORT);
return poll;
}
EXPORT_SYMBOL(msm_vidc_poll);
int msm_vidc_querycap(void *instance, struct v4l2_capability *cap)
{
struct msm_vidc_inst *inst = instance;
if (!inst || !cap) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
strlcpy(cap->driver, MSM_VIDC_DRV_NAME, sizeof(cap->driver));
cap->bus_info[0] = 0;
cap->version = MSM_VIDC_VERSION;
cap->device_caps = V4L2_CAP_VIDEO_CAPTURE_MPLANE |
V4L2_CAP_VIDEO_OUTPUT_MPLANE |
V4L2_CAP_META_CAPTURE |
V4L2_CAP_META_OUTPUT |
V4L2_CAP_STREAMING;
cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
memset(cap->reserved, 0, sizeof(cap->reserved));
if (inst->domain == MSM_VIDC_DECODER)
strlcpy(cap->card, "msm_vidc_decoder", sizeof(cap->card));
else if (inst->domain == MSM_VIDC_ENCODER)
strlcpy(cap->card, "msm_vidc_encoder", sizeof(cap->card));
else
return -EINVAL;
return 0;
}
EXPORT_SYMBOL(msm_vidc_querycap);
int msm_vidc_enum_fmt(void *instance, struct v4l2_fmtdesc *f)
{
struct msm_vidc_inst *inst = instance;
if (!inst || !f) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
if (inst->domain == MSM_VIDC_DECODER)
return msm_vdec_enum_fmt(inst, f);
if (inst->domain == MSM_VIDC_ENCODER)
return msm_venc_enum_fmt(inst, f);
return -EINVAL;
}
EXPORT_SYMBOL(msm_vidc_enum_fmt);
int msm_vidc_query_ctrl(void *instance, struct v4l2_queryctrl *q_ctrl)
{
int rc = 0;
struct msm_vidc_inst *inst = instance;
struct v4l2_ctrl *ctrl;
if (!inst || !q_ctrl) {
d_vpr_e("%s: invalid params %pK %pK\n",
__func__, inst, q_ctrl);
return -EINVAL;
}
ctrl = v4l2_ctrl_find(&inst->ctrl_handler, q_ctrl->id);
if (!ctrl) {
s_vpr_e(inst->sid, "%s: get_ctrl failed for id %d\n",
__func__, q_ctrl->id);
return -EINVAL;
}
q_ctrl->minimum = ctrl->minimum;
q_ctrl->maximum = ctrl->maximum;
q_ctrl->default_value = ctrl->default_value;
q_ctrl->flags = 0;
q_ctrl->step = ctrl->step;
s_vpr_h(inst->sid,
"query ctrl: %s: min %d, max %d, default %d step %d flags %#x\n",
ctrl->name, q_ctrl->minimum, q_ctrl->maximum,
q_ctrl->default_value, q_ctrl->step, q_ctrl->flags);
return rc;
}
EXPORT_SYMBOL(msm_vidc_query_ctrl);
int msm_vidc_query_menu(void *instance, struct v4l2_querymenu *qmenu)
{
int rc = 0;
struct msm_vidc_inst *inst = instance;
struct v4l2_ctrl *ctrl;
if (!inst || !qmenu) {
d_vpr_e("%s: invalid params %pK %pK\n",
__func__, inst, qmenu);
return -EINVAL;
}
ctrl = v4l2_ctrl_find(&inst->ctrl_handler, qmenu->id);
if (!ctrl) {
s_vpr_e(inst->sid, "%s: get_ctrl failed for id %d\n",
__func__, qmenu->id);
return -EINVAL;
}
if (ctrl->type != V4L2_CTRL_TYPE_MENU) {
s_vpr_e(inst->sid, "%s: ctrl: %s: type (%d) is not MENU type\n",
__func__, ctrl->name, ctrl->type);
return -EINVAL;
}
if (qmenu->index < ctrl->minimum || qmenu->index > ctrl->maximum)
return -EINVAL;
if (ctrl->menu_skip_mask & (1 << qmenu->index))
rc = -EINVAL;
s_vpr_h(inst->sid,
"%s: ctrl: %s: min %d, max %d, menu_skip_mask %#x, qmenu: id %d, index %d, %s\n",
__func__, ctrl->name, ctrl->minimum, ctrl->maximum,
ctrl->menu_skip_mask, qmenu->id, qmenu->index,
rc ? "not supported" : "supported");
return rc;
}
EXPORT_SYMBOL(msm_vidc_query_menu);
int msm_vidc_s_fmt(void *instance, struct v4l2_format *f)
{
int rc = 0;
struct msm_vidc_inst *inst = instance;
if (!inst || !f) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
if (f->type == INPUT_MPLANE) {
if (inst->state != MSM_VIDC_OPEN &&
inst->state != MSM_VIDC_START_OUTPUT) {
s_vpr_e(inst->sid,
"%s: s_fmt(%d) not allowed in %d state\n",
__func__, f->type, inst->state);
return -EINVAL;
}
} else if (f->type == OUTPUT_MPLANE) {
if (inst->state != MSM_VIDC_OPEN &&
inst->state != MSM_VIDC_START_INPUT &&
inst->state != MSM_VIDC_DRAIN_START_INPUT) {
s_vpr_e(inst->sid,
"%s: s_fmt(%d) not allowed in %d state\n",
__func__, f->type, inst->state);
return -EINVAL;
}
}
if (inst->domain == MSM_VIDC_DECODER)
rc = msm_vdec_s_fmt(inst, f);
if (inst->domain == MSM_VIDC_ENCODER)
rc = msm_venc_s_fmt(inst, f);
if (rc)
s_vpr_e(inst->sid, "%s: s_fmt(%d) failed %d\n",
__func__, f->type, rc);
return rc;
}
EXPORT_SYMBOL(msm_vidc_s_fmt);
int msm_vidc_g_fmt(void *instance, struct v4l2_format *f)
{
int rc = 0;
struct msm_vidc_inst *inst = instance;
if (!inst || !f) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
if (inst->domain == MSM_VIDC_DECODER)
rc = msm_vdec_g_fmt(inst, f);
if (inst->domain == MSM_VIDC_ENCODER)
rc = msm_venc_g_fmt(inst, f);
return rc;
}
EXPORT_SYMBOL(msm_vidc_g_fmt);
int msm_vidc_s_ctrl(void *instance, struct v4l2_control *control)
{
struct msm_vidc_inst *inst = instance;
if (!inst || !control)
return -EINVAL;
return v4l2_s_ctrl(NULL, &inst->ctrl_handler, control);
}
EXPORT_SYMBOL(msm_vidc_s_ctrl);
int msm_vidc_g_ctrl(void *instance, struct v4l2_control *control)
{
struct msm_vidc_inst *inst = instance;
struct v4l2_ctrl *ctrl = NULL;
int rc = 0;
if (!inst || !control) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
ctrl = v4l2_ctrl_find(&inst->ctrl_handler, control->id);
if (ctrl) {
rc = msm_vidc_get_control(inst, ctrl);
if (!rc)
control->value = ctrl->val;
}
if (rc)
s_vpr_e(inst->sid, "%s: failed for control id %#x\n",
__func__, control->id);
else
s_vpr_h(inst->sid, "%s: control id %#x, value %d\n",
__func__, control->id, control->value);
return rc;
}
EXPORT_SYMBOL(msm_vidc_g_ctrl);
int msm_vidc_reqbufs(void *instance, struct v4l2_requestbuffers *b)
{
int rc = 0;
struct msm_vidc_inst *inst = instance;
int port;
if (!inst || !b) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
mutex_lock(&inst->lock);
if (b->type == INPUT_MPLANE) {
if (inst->state != MSM_VIDC_OPEN &&
inst->state != MSM_VIDC_START_OUTPUT) {
s_vpr_e(inst->sid,
"%s: reqbufs(%d) not allowed in %d state\n",
__func__, b->type, inst->state);
rc = -EINVAL;
goto unlock;
}
} else if (b->type == OUTPUT_MPLANE) {
if (inst->state != MSM_VIDC_OPEN &&
inst->state != MSM_VIDC_START_INPUT &&
inst->state != MSM_VIDC_DRAIN_START_INPUT) {
s_vpr_e(inst->sid,
"%s: reqbufs(%d) not allowed in %d state\n",
__func__, b->type, inst->state);
rc = -EINVAL;
goto unlock;
}
}
port = v4l2_type_to_driver_port(inst, b->type, __func__);
if (port < 0) {
rc = -EINVAL;
goto unlock;
}
rc = vb2_reqbufs(&inst->vb2q[port], b);
if (rc) {
s_vpr_e(inst->sid, "%s: vb2_reqbufs(%d) failed, %d\n",
__func__, b->type, rc);
goto unlock;
}
unlock:
mutex_unlock(&inst->lock);
return rc;
}
EXPORT_SYMBOL(msm_vidc_reqbufs);
int msm_vidc_qbuf(void *instance, struct media_device *mdev,
struct v4l2_buffer *b)
{
int rc = 0;
struct msm_vidc_inst *inst = instance;
struct vb2_queue *q;
if (!inst || !inst->core || !b || !valid_v4l2_buffer(b, inst)) {
d_vpr_e("%s: invalid params %pK %pK\n", __func__, inst, b);
return -EINVAL;
}
mutex_lock(&inst->lock);
if (inst->state == MSM_VIDC_ERROR) {
s_vpr_e(inst->sid, "%s: error state\n", __func__);
rc = -EINVAL;
goto unlock;
}
if (b->type == INPUT_MPLANE) {
q = &inst->vb2q[INPUT_PORT];
} else if (b->type == OUTPUT_MPLANE) {
q = &inst->vb2q[OUTPUT_PORT];
} else if (b->type == INPUT_META_PLANE) {
q = &inst->vb2q[INPUT_META_PORT];
} else if (b->type == OUTPUT_META_PLANE) {
q = &inst->vb2q[OUTPUT_META_PORT];
} else {
s_vpr_e(inst->sid, "%s: invalid buffer type %d\n",
__func__, b->type);
rc = -EINVAL;
goto unlock;
}
rc = vb2_qbuf(q, mdev, b);
if (rc)
s_vpr_e(inst->sid, "%s: failed with %d\n", __func__, rc);
unlock:
mutex_unlock(&inst->lock);
return rc;
}
EXPORT_SYMBOL(msm_vidc_qbuf);
int msm_vidc_dqbuf(void *instance, struct v4l2_buffer *b)
{
int rc = 0;
struct msm_vidc_inst *inst = instance;
struct vb2_queue *q;
if (!inst || !b || !valid_v4l2_buffer(b, inst)) {
d_vpr_e("%s: invalid params %pK %pK\n", __func__, inst, b);
return -EINVAL;
}
mutex_lock(&inst->lock);
if (b->type == INPUT_MPLANE) {
q = &inst->vb2q[INPUT_PORT];
} else if (b->type == OUTPUT_MPLANE) {
q = &inst->vb2q[OUTPUT_PORT];
} else if (b->type == INPUT_META_PLANE) {
q = &inst->vb2q[INPUT_META_PORT];
} else if (b->type == OUTPUT_META_PLANE) {
q = &inst->vb2q[OUTPUT_META_PORT];
} else {
s_vpr_e(inst->sid, "%s: invalid buffer type %d\n",
__func__, b->type);
rc = -EINVAL;
goto unlock;
}
rc = vb2_dqbuf(q, b, true);
if (rc == -EAGAIN) {
goto unlock;
} else if (rc) {
s_vpr_e(inst->sid, "%s: failed with %d\n", __func__, rc);
goto unlock;
}
unlock:
mutex_unlock(&inst->lock);
return rc;
}
EXPORT_SYMBOL(msm_vidc_dqbuf);
int msm_vidc_streamon(void *instance, enum v4l2_buf_type type)
{
int rc = 0;
struct msm_vidc_inst *inst = instance;
enum msm_vidc_inst_state new_state = MSM_VIDC_ERROR;
int port;
if (!inst) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
mutex_lock(&inst->lock);
if (type == INPUT_MPLANE) {
if (inst->state != MSM_VIDC_OPEN &&
inst->state != MSM_VIDC_START_OUTPUT) {
s_vpr_e(inst->sid,
"%s: streamon(%d) not allowed in %d state\n",
__func__, type, inst->state);
rc = -EINVAL;
goto unlock;
}
} else if (type == OUTPUT_MPLANE) {
if (inst->state != MSM_VIDC_OPEN &&
inst->state != MSM_VIDC_START_INPUT &&
inst->state != MSM_VIDC_DRAIN_START_INPUT) {
s_vpr_e(inst->sid,
"%s: streamon(%d) not allowed in %d state\n",
__func__, type, inst->state);
rc = -EINVAL;
goto unlock;
}
}
port = v4l2_type_to_driver_port(inst, type, __func__);
if (port < 0) {
rc = -EINVAL;
goto unlock;
}
rc = vb2_streamon(&inst->vb2q[port], type);
if (rc) {
s_vpr_e(inst->sid, "%s: vb2_streamon(%d) failed, %d\n",
__func__, type, rc);
goto unlock;
}
if (type == INPUT_MPLANE) {
if (inst->state == MSM_VIDC_OPEN) {
new_state = MSM_VIDC_START_INPUT;
} else if (inst->state == MSM_VIDC_START_OUTPUT) {
new_state = MSM_VIDC_START;
}
rc = msm_vidc_change_inst_state(inst, new_state, __func__);
if (rc)
goto unlock;
} else if (type == OUTPUT_MPLANE) {
if (inst->state == MSM_VIDC_OPEN) {
new_state = MSM_VIDC_START_OUTPUT;
} else if (inst->state == MSM_VIDC_START_INPUT) {
new_state = MSM_VIDC_START;
} else if (inst->state == MSM_VIDC_DRAIN_START_INPUT) {
if (0 /* check if input port settings change pending */)
new_state = MSM_VIDC_DRC_DRAIN;
else
new_state = MSM_VIDC_DRAIN;
}
rc = msm_vidc_change_inst_state(inst, new_state, __func__);
if (rc)
goto unlock;
}
unlock:
mutex_unlock(&inst->lock);
return rc;
}
EXPORT_SYMBOL(msm_vidc_streamon);
int msm_vidc_streamoff(void *instance, enum v4l2_buf_type type)
{
int rc = 0;
struct msm_vidc_inst *inst = instance;
enum msm_vidc_inst_state new_state = MSM_VIDC_ERROR;
int port;
if (!inst) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
mutex_lock(&inst->lock);
if (type == INPUT_MPLANE) {
if (inst->state == MSM_VIDC_OPEN ||
inst->state == MSM_VIDC_START_OUTPUT) {
s_vpr_e(inst->sid,
"%s: streamoff(%d) not allowed in %d state\n",
__func__, type, inst->state);
rc = -EINVAL;
goto unlock;
}
} else if (type == OUTPUT_MPLANE) {
if (inst->state == MSM_VIDC_OPEN ||
inst->state == MSM_VIDC_START_INPUT) {
s_vpr_e(inst->sid,
"%s: streamoff(%d) not allowed in %d state\n",
__func__, type, inst->state);
rc = -EINVAL;
goto unlock;
}
}
port = v4l2_type_to_driver_port(inst, type, __func__);
if (port < 0) {
rc = -EINVAL;
goto unlock;
}
rc = vb2_streamoff(&inst->vb2q[port], type);
if (rc) {
s_vpr_e(inst->sid, "%s: vb2_streamoff(%d) failed, %d\n",
__func__, type, rc);
goto unlock;
}
if (type == INPUT_MPLANE) {
if (inst->state == MSM_VIDC_START_INPUT) {
new_state = MSM_VIDC_OPEN;
} else if (inst->state == MSM_VIDC_START) {
new_state = MSM_VIDC_START_OUTPUT;
} else if (inst->state == MSM_VIDC_DRC ||
inst->state == MSM_VIDC_DRC_LAST_FLAG ||
inst->state == MSM_VIDC_DRAIN ||
inst->state == MSM_VIDC_DRAIN_LAST_FLAG ||
inst->state == MSM_VIDC_DRC_DRAIN ||
inst->state == MSM_VIDC_DRC_DRAIN_LAST_FLAG ||
inst->state == MSM_VIDC_DRAIN_START_INPUT) {
new_state = MSM_VIDC_START_OUTPUT;
/* discard pending port settings change if any */
}
rc = msm_vidc_change_inst_state(inst, new_state, __func__);
if (rc)
goto unlock;
} else if (type == OUTPUT_MPLANE) {
if (inst->state == MSM_VIDC_START_OUTPUT) {
new_state = MSM_VIDC_OPEN;
} else if (inst->state == MSM_VIDC_START ||
inst->state == MSM_VIDC_DRAIN ||
inst->state == MSM_VIDC_DRAIN_LAST_FLAG ||
inst->state == MSM_VIDC_DRC ||
inst->state == MSM_VIDC_DRC_LAST_FLAG ||
inst->state == MSM_VIDC_DRC_DRAIN) {
new_state = MSM_VIDC_START_INPUT;
} else if (inst->state == MSM_VIDC_DRC_DRAIN_LAST_FLAG) {
new_state = MSM_VIDC_DRAIN_START_INPUT;
}
rc = msm_vidc_change_inst_state(inst, new_state, __func__);
if (rc)
goto unlock;
}
unlock:
mutex_unlock(&inst->lock);
return rc;
}
EXPORT_SYMBOL(msm_vidc_streamoff);
int msm_vidc_cmd(void *instance, union msm_v4l2_cmd *cmd)
{
int rc = 0;
struct msm_vidc_inst *inst = instance;
struct v4l2_decoder_cmd *dec = NULL;
struct v4l2_encoder_cmd *enc = NULL;
if (is_decode_session(inst)) {
dec = (struct v4l2_decoder_cmd *)cmd;
rc = msm_vdec_process_cmd(inst, dec->cmd);
} else if (is_encode_session(inst)) {
enc = (struct v4l2_encoder_cmd *)cmd;
rc = msm_venc_process_cmd(inst, enc->cmd);
}
return 0;
}
EXPORT_SYMBOL(msm_vidc_cmd);
int msm_vidc_enum_framesizes(void *instance, struct v4l2_frmsizeenum *fsize)
{
struct msm_vidc_inst *inst = instance;
struct msm_vidc_inst_capability *capability;
if (!inst || !fsize) {
d_vpr_e("%s: invalid params: %pK %pK\n",
__func__, inst, fsize);
return -EINVAL;
}
if (!inst->capabilities) {
s_vpr_e(inst->sid, "capabilities not available\n", __func__);
return -EINVAL;
}
capability = inst->capabilities;
fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
fsize->stepwise.min_width = capability->cap[FRAME_WIDTH].min;
fsize->stepwise.max_width = capability->cap[FRAME_WIDTH].max;
fsize->stepwise.step_width =
capability->cap[FRAME_WIDTH].step_or_mask;
fsize->stepwise.min_height = capability->cap[FRAME_HEIGHT].min;
fsize->stepwise.max_height = capability->cap[FRAME_HEIGHT].max;
fsize->stepwise.step_height =
capability->cap[FRAME_HEIGHT].step_or_mask;
return 0;
}
EXPORT_SYMBOL(msm_vidc_enum_framesizes);
int msm_vidc_subscribe_event(void *instance,
const struct v4l2_event_subscription *sub)
{
int rc = 0;
struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance;
if (!inst || !sub) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
s_vpr_h(inst->sid, "%s: type %d id %d\n", __func__, sub->type, sub->id);
rc = v4l2_event_subscribe(&inst->event_handler,
sub, MAX_EVENTS, NULL);
if (rc)
s_vpr_e(inst->sid, "%s: fialed, type %d id %d\n",
__func__, sub->type, sub->id);
return rc;
}
EXPORT_SYMBOL(msm_vidc_subscribe_event);
int msm_vidc_unsubscribe_event(void *instance,
const struct v4l2_event_subscription *sub)
{
int rc = 0;
struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance;
if (!inst || !sub) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
s_vpr_h(inst->sid, "%s: type %d id %d\n", __func__, sub->type, sub->id);
rc = v4l2_event_unsubscribe(&inst->event_handler, sub);
if (rc)
s_vpr_e(inst->sid, "%s: fialed, type %d id %d\n",
__func__, sub->type, sub->id);
return rc;
}
EXPORT_SYMBOL(msm_vidc_unsubscribe_event);
int msm_vidc_dqevent(void *instance, struct v4l2_event *event)
{
int rc = 0;
struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance;
if (!inst || !event) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
rc = v4l2_event_dequeue(&inst->event_handler, event, false);
if (rc)
s_vpr_e(inst->sid, "%s: fialed\n", __func__);
return rc;
}
EXPORT_SYMBOL(msm_vidc_dqevent);
void *msm_vidc_open(void *vidc_core, u32 session_type)
{
int rc = 0;
struct msm_vidc_inst *inst;
struct msm_vidc_core *core;
int i = 0;
d_vpr_h("%s()\n", __func__);
core = vidc_core;
if (!core) {
d_vpr_e("%s: invalid params\n", __func__);
return NULL;
}
if (session_type != MSM_VIDC_DECODER &&
session_type != MSM_VIDC_ENCODER) {
d_vpr_e("%s: invalid session_type %d\n",
__func__, session_type);
return NULL;
}
if (core->state == MSM_VIDC_CORE_ERROR) {
d_vpr_e("%s: core invalid state\n", __func__);
return NULL;
}
if (core->state == MSM_VIDC_CORE_DEINIT) {
rc = msm_vidc_core_init(core);
if (rc)
return NULL;
}
inst = kzalloc(sizeof(*inst), GFP_KERNEL);
if (!inst) {
d_vpr_e("%s: failed to allocate inst memory\n", __func__);
return NULL;
}
inst->core = core;
inst->capabilities = kzalloc(
sizeof(struct msm_vidc_inst_capability), GFP_KERNEL);
if (!inst->capabilities) {
s_vpr_e(inst->sid,
"%s: inst capability allocation failed\n", __func__);
return NULL;
}
rc = msm_vidc_add_session(inst);
if (rc) {
d_vpr_e("%s: failed to get session id\n", __func__);
return NULL;
}
s_vpr_i(inst->sid, "Opening video instance: %d\n", session_type);
kref_init(&inst->kref);
mutex_init(&inst->lock);
INIT_LIST_HEAD(&inst->buffers.input.list);
INIT_LIST_HEAD(&inst->buffers.input_meta.list);
INIT_LIST_HEAD(&inst->buffers.output.list);
INIT_LIST_HEAD(&inst->buffers.output_meta.list);
INIT_LIST_HEAD(&inst->buffers.bin.list);
INIT_LIST_HEAD(&inst->buffers.arp.list);
INIT_LIST_HEAD(&inst->buffers.comv.list);
INIT_LIST_HEAD(&inst->buffers.non_comv.list);
INIT_LIST_HEAD(&inst->buffers.line.list);
INIT_LIST_HEAD(&inst->buffers.dpb.list);
INIT_LIST_HEAD(&inst->buffers.persist.list);
INIT_LIST_HEAD(&inst->allocations.bin.list);
INIT_LIST_HEAD(&inst->allocations.arp.list);
INIT_LIST_HEAD(&inst->allocations.comv.list);
INIT_LIST_HEAD(&inst->allocations.non_comv.list);
INIT_LIST_HEAD(&inst->allocations.line.list);
INIT_LIST_HEAD(&inst->allocations.dpb.list);
INIT_LIST_HEAD(&inst->allocations.persist.list);
INIT_LIST_HEAD(&inst->mappings.input.list);
INIT_LIST_HEAD(&inst->mappings.input_meta.list);
INIT_LIST_HEAD(&inst->mappings.output.list);
INIT_LIST_HEAD(&inst->mappings.output_meta.list);
INIT_LIST_HEAD(&inst->mappings.bin.list);
INIT_LIST_HEAD(&inst->mappings.arp.list);
INIT_LIST_HEAD(&inst->mappings.comv.list);
INIT_LIST_HEAD(&inst->mappings.non_comv.list);
INIT_LIST_HEAD(&inst->mappings.line.list);
INIT_LIST_HEAD(&inst->mappings.dpb.list);
INIT_LIST_HEAD(&inst->mappings.persist.list);
INIT_LIST_HEAD(&inst->children.list);
INIT_LIST_HEAD(&inst->firmware.list);
inst->domain = session_type;
inst->state = MSM_VIDC_OPEN;
inst->active = true;
inst->request = false;
inst->ipsc_properties_set = false;
inst->opsc_properties_set = false;
for (i = 0; i < MAX_SIGNAL; i++)
init_completion(&inst->completions[i]);
//inst->debugfs_root =
// msm_vidc_debugfs_init_inst(inst, core->debugfs_root);
if (is_decode_session(inst)) {
rc = msm_vdec_inst_init(inst);
if (rc)
goto error;
} else if (is_encode_session(inst)) {
rc = msm_venc_inst_init(inst);
if (rc)
goto error;
}
rc = msm_vidc_vb2_queue_init(inst);
if (rc)
goto error;
rc = msm_vidc_setup_event_queue(inst);
if (rc)
goto error;
msm_vidc_scale_power(inst, true);
rc = msm_vidc_session_open(inst);
if (rc)
goto error;
return inst;
error:
msm_vidc_close(inst);
return NULL;
}
EXPORT_SYMBOL(msm_vidc_open);
int msm_vidc_close(void *instance)
{
int rc = 0;
struct msm_vidc_inst *inst = instance;
if (!inst) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
s_vpr_h(inst->sid, "%s()\n", __func__);
msm_vidc_session_close(inst);
msm_vidc_remove_session(inst);
return rc;
}
EXPORT_SYMBOL(msm_vidc_close);