blob: e1dd50cedd36ae9b41df1f883677bde1891d541b [file] [log] [blame]
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
*/
#include "msm_cvp.h"
#include <synx_api.h>
#define MSM_CVP_NOMINAL_CYCLES (444 * 1000 * 1000)
#define MSM_CVP_UHD60E_VPSS_CYCLES (111 * 1000 * 1000)
#define MSM_CVP_UHD60E_ISE_CYCLES (175 * 1000 * 1000)
#define MAX_CVP_VPSS_CYCLES (MSM_CVP_NOMINAL_CYCLES - \
MSM_CVP_UHD60E_VPSS_CYCLES)
#define MAX_CVP_ISE_CYCLES (MSM_CVP_NOMINAL_CYCLES - \
MSM_CVP_UHD60E_ISE_CYCLES)
struct msm_cvp_fence_thread_data {
struct msm_cvp_inst *inst;
unsigned int device_id;
struct cvp_kmd_hfi_fence_packet in_fence_pkt;
unsigned int arg_type;
};
static struct msm_cvp_fence_thread_data fence_thread_data;
static void print_client_buffer(u32 tag, const char *str,
struct msm_cvp_inst *inst, struct cvp_kmd_buffer *cbuf)
{
if (!(tag & msm_cvp_debug) || !inst || !cbuf)
return;
dprintk(tag,
"%s: %x : idx %2d fd %d off %d size %d type %d flags 0x%x\n",
str, hash32_ptr(inst->session), cbuf->index, cbuf->fd,
cbuf->offset, cbuf->size, cbuf->type, cbuf->flags);
}
static void print_cvp_internal_buffer(u32 tag, const char *str,
struct msm_cvp_inst *inst, struct msm_cvp_internal_buffer *cbuf)
{
if (!(tag & msm_cvp_debug) || !inst || !cbuf)
return;
dprintk(tag,
"%s: %x : idx %2d fd %d off %d daddr %x size %d type %d flags 0x%x\n",
str, hash32_ptr(inst->session), cbuf->buf.index, cbuf->buf.fd,
cbuf->buf.offset, cbuf->smem.device_addr, cbuf->buf.size,
cbuf->buf.type, cbuf->buf.flags);
}
static enum hal_buffer get_hal_buftype(const char *str, unsigned int type)
{
enum hal_buffer buftype = HAL_BUFFER_NONE;
if (type == CVP_KMD_BUFTYPE_INPUT)
buftype = HAL_BUFFER_INPUT;
else if (type == CVP_KMD_BUFTYPE_OUTPUT)
buftype = HAL_BUFFER_OUTPUT;
else if (type == CVP_KMD_BUFTYPE_INTERNAL_1)
buftype = HAL_BUFFER_INTERNAL_SCRATCH_1;
else if (type == CVP_KMD_BUFTYPE_INTERNAL_2)
buftype = HAL_BUFFER_INTERNAL_SCRATCH_1;
else
dprintk(CVP_ERR, "%s: unknown buffer type %#x\n",
str, type);
return buftype;
}
static int msm_cvp_scale_clocks_and_bus(struct msm_cvp_inst *inst)
{
int rc = 0;
if (!inst || !inst->core) {
dprintk(CVP_ERR, "%s: invalid params\n", __func__);
return -EINVAL;
}
rc = msm_cvp_set_clocks(inst->core);
if (rc) {
dprintk(CVP_ERR,
"%s: failed set_clocks for inst %pK (%#x)\n",
__func__, inst, hash32_ptr(inst->session));
goto exit;
}
rc = msm_cvp_comm_vote_bus(inst->core);
if (rc) {
dprintk(CVP_ERR,
"%s: failed vote_bus for inst %pK (%#x)\n",
__func__, inst, hash32_ptr(inst->session));
goto exit;
}
exit:
return rc;
}
static int msm_cvp_get_session_info(struct msm_cvp_inst *inst,
struct cvp_kmd_session_info *session)
{
int rc = 0;
if (!inst || !inst->core || !session) {
dprintk(CVP_ERR, "%s: invalid params\n", __func__);
return -EINVAL;
}
session->session_id = hash32_ptr(inst->session);
dprintk(CVP_DBG, "%s: id 0x%x\n", __func__, session->session_id);
return rc;
}
static int msm_cvp_session_get_iova_addr(
struct msm_cvp_inst *inst,
struct msm_cvp_internal_buffer *cbuf,
unsigned int search_fd, unsigned int search_size,
unsigned int *iova,
unsigned int *iova_size)
{
bool found = false;
mutex_lock(&inst->cvpbufs.lock);
list_for_each_entry(cbuf, &inst->cvpbufs.list, list) {
if (cbuf->buf.fd == search_fd) {
found = true;
break;
}
}
mutex_unlock(&inst->cvpbufs.lock);
if (!found)
return -EINVAL;
*iova = cbuf->smem.device_addr;
if (search_size != cbuf->buf.size) {
dprintk(CVP_ERR,
"%s:: invalid size received fd = %d\n",
__func__, search_fd);
return -EINVAL;
}
*iova_size = cbuf->buf.size;
return 0;
}
static int msm_cvp_map_buf(struct msm_cvp_inst *inst,
struct cvp_kmd_buffer *buf)
{
int rc = 0;
bool found;
struct msm_cvp_internal_buffer *cbuf;
struct hal_session *session;
if (!inst || !inst->core || !buf) {
dprintk(CVP_ERR, "%s: invalid params\n", __func__);
return -EINVAL;
}
session = (struct hal_session *)inst->session;
mutex_lock(&inst->cvpbufs.lock);
found = false;
list_for_each_entry(cbuf, &inst->cvpbufs.list, list) {
if (cbuf->buf.fd == buf->fd &&
cbuf->buf.offset == buf->offset) {
found = true;
break;
}
}
mutex_unlock(&inst->cvpbufs.lock);
if (found) {
print_client_buffer(CVP_ERR, "duplicate", inst, buf);
return -EINVAL;
}
cbuf = kzalloc(sizeof(struct msm_cvp_internal_buffer), GFP_KERNEL);
if (!cbuf) {
dprintk(CVP_ERR, "%s: cbuf alloc failed\n", __func__);
return -ENOMEM;
}
mutex_lock(&inst->cvpbufs.lock);
list_add_tail(&cbuf->list, &inst->cvpbufs.list);
mutex_unlock(&inst->cvpbufs.lock);
memcpy(&cbuf->buf, buf, sizeof(struct cvp_kmd_buffer));
cbuf->smem.buffer_type = get_hal_buftype(__func__, buf->type);
cbuf->smem.fd = buf->fd;
cbuf->smem.offset = buf->offset;
cbuf->smem.size = buf->size;
cbuf->smem.flags = buf->flags;
rc = msm_cvp_smem_map_dma_buf(inst, &cbuf->smem);
if (rc) {
print_client_buffer(CVP_ERR, "map failed", inst, buf);
goto exit;
}
if (buf->index) {
rc = cvp_dsp_register_buffer((uint32_t)cbuf->smem.device_addr,
buf->index, buf->size, hash32_ptr(session));
if (rc) {
dprintk(CVP_ERR,
"%s: failed dsp registration for fd=%d rc=%d",
__func__, buf->fd, rc);
goto exit;
}
}
return rc;
exit:
if (cbuf->smem.device_addr)
msm_cvp_smem_unmap_dma_buf(inst, &cbuf->smem);
mutex_lock(&inst->cvpbufs.lock);
list_del(&cbuf->list);
mutex_unlock(&inst->cvpbufs.lock);
kfree(cbuf);
cbuf = NULL;
return rc;
}
static bool _cvp_msg_pending(struct msm_cvp_inst *inst,
struct cvp_session_queue *sq,
struct session_msg **msg)
{
struct session_msg *mptr = NULL;
bool result = false;
spin_lock(&sq->lock);
if (!kref_read(&inst->kref)) {
/* The session is being deleted */
spin_unlock(&sq->lock);
*msg = NULL;
return true;
}
result = list_empty(&sq->msgs);
if (!result) {
mptr = list_first_entry(&sq->msgs, struct session_msg, node);
list_del_init(&mptr->node);
sq->msg_count--;
}
spin_unlock(&sq->lock);
*msg = mptr;
return !result;
}
static int msm_cvp_session_receive_hfi(struct msm_cvp_inst *inst,
struct cvp_kmd_hfi_packet *out_pkt)
{
unsigned long wait_time;
struct session_msg *msg = NULL;
struct cvp_session_queue *sq;
if (!inst) {
dprintk(CVP_ERR, "%s invalid session\n", __func__);
return -EINVAL;
}
sq = &inst->session_queue;
wait_time = msecs_to_jiffies(CVP_MAX_WAIT_TIME);
if (wait_event_timeout(sq->wq,
_cvp_msg_pending(inst, sq, &msg), wait_time) == 0) {
dprintk(CVP_ERR, "session queue wait timeout\n");
return -ETIMEDOUT;
}
if (msg == NULL) {
dprintk(CVP_ERR, "%s: session is deleted, no msg\n", __func__);
return -EINVAL;
}
memcpy(out_pkt, &msg->pkt, sizeof(struct hfi_msg_session_hdr));
kmem_cache_free(inst->session_queue.msg_cache, msg);
return 0;
}
static int msm_cvp_session_process_hfi(
struct msm_cvp_inst *inst,
struct cvp_kmd_hfi_packet *in_pkt,
unsigned int in_offset,
unsigned int in_buf_num)
{
int i, pkt_idx, rc = 0;
struct hfi_device *hdev;
struct msm_cvp_internal_buffer *cbuf;
struct buf_desc *buf_ptr;
unsigned int offset, buf_num, signal;
if (!inst || !inst->core || !in_pkt) {
dprintk(CVP_ERR, "%s: invalid params\n", __func__);
return -EINVAL;
}
hdev = inst->core->device;
pkt_idx = get_pkt_index((struct cvp_hal_session_cmd_pkt *)in_pkt);
if (pkt_idx < 0) {
dprintk(CVP_ERR, "%s incorrect packet %d, %x\n", __func__,
in_pkt->pkt_data[0],
in_pkt->pkt_data[1]);
offset = in_offset;
buf_num = in_buf_num;
signal = HAL_NO_RESP;
} else {
offset = cvp_hfi_defs[pkt_idx].buf_offset;
buf_num = cvp_hfi_defs[pkt_idx].buf_num;
signal = cvp_hfi_defs[pkt_idx].resp;
}
if (in_offset && in_buf_num) {
if (offset != in_offset || buf_num != in_buf_num) {
dprintk(CVP_ERR, "%s incorrect offset and num %d, %d\n",
__func__, in_offset, in_buf_num);
offset = in_offset;
buf_num = in_buf_num;
}
}
if (offset != 0 && buf_num != 0) {
buf_ptr = (struct buf_desc *)&in_pkt->pkt_data[offset];
for (i = 0; i < buf_num; i++) {
if (!buf_ptr[i].fd)
continue;
rc = msm_cvp_session_get_iova_addr(inst, cbuf,
buf_ptr[i].fd,
buf_ptr[i].size,
&buf_ptr[i].fd,
&buf_ptr[i].size);
if (rc) {
dprintk(CVP_ERR,
"%s: buf %d unregistered. rc=%d\n",
__func__, i, rc);
return rc;
}
}
}
rc = call_hfi_op(hdev, session_send,
(void *)inst->session, in_pkt);
if (rc) {
dprintk(CVP_ERR,
"%s: Failed in call_hfi_op %d, %x\n",
__func__, in_pkt->pkt_data[0], in_pkt->pkt_data[1]);
}
if (signal != HAL_NO_RESP) {
rc = wait_for_sess_signal_receipt(inst, signal);
if (rc)
dprintk(CVP_ERR,
"%s: wait for signal failed, rc %d %d, %x %d\n",
__func__, rc,
in_pkt->pkt_data[0],
in_pkt->pkt_data[1],
signal);
}
return rc;
}
static int msm_cvp_thread_fence_run(void *data)
{
int i, pkt_idx, rc = 0;
unsigned long timeout_ms = 1000;
int synx_obj;
struct hfi_device *hdev;
struct msm_cvp_fence_thread_data *fence_thread_data;
struct cvp_kmd_hfi_fence_packet *in_fence_pkt;
struct cvp_kmd_hfi_packet *in_pkt;
struct msm_cvp_inst *inst;
int *fence;
struct msm_cvp_internal_buffer *cbuf;
struct buf_desc *buf_ptr;
unsigned int offset, buf_num;
if (!data) {
dprintk(CVP_ERR, "%s Wrong input data %pK\n", __func__, data);
do_exit(-EINVAL);
}
fence_thread_data = data;
inst = cvp_get_inst(get_cvp_core(fence_thread_data->device_id),
(void *)fence_thread_data->inst);
if (!inst) {
dprintk(CVP_ERR, "%s Wrong inst %pK\n", __func__, inst);
do_exit(-EINVAL);
}
in_fence_pkt = (struct cvp_kmd_hfi_fence_packet *)
&fence_thread_data->in_fence_pkt;
in_pkt = (struct cvp_kmd_hfi_packet *)(in_fence_pkt);
fence = (int *)(in_fence_pkt->fence_data);
hdev = inst->core->device;
pkt_idx = get_pkt_index((struct cvp_hal_session_cmd_pkt *)in_pkt);
if (pkt_idx < 0) {
dprintk(CVP_ERR, "%s incorrect packet %d, %x\n", __func__,
in_pkt->pkt_data[0],
in_pkt->pkt_data[1]);
do_exit(pkt_idx);
}
offset = cvp_hfi_defs[pkt_idx].buf_offset;
buf_num = cvp_hfi_defs[pkt_idx].buf_num;
if (offset != 0 && buf_num != 0) {
buf_ptr = (struct buf_desc *)&in_pkt->pkt_data[offset];
for (i = 0; i < buf_num; i++) {
if (!buf_ptr[i].fd)
continue;
rc = msm_cvp_session_get_iova_addr(inst, cbuf,
buf_ptr[i].fd,
buf_ptr[i].size,
&buf_ptr[i].fd,
&buf_ptr[i].size);
if (rc) {
dprintk(CVP_ERR,
"%s: buf %d unregistered. rc=%d\n",
__func__, i, rc);
do_exit(rc);
}
}
}
//wait on synx before signaling HFI
switch (fence_thread_data->arg_type) {
case CVP_KMD_HFI_DME_FRAME_FENCE_CMD:
{
for (i = 0; i < HFI_DME_BUF_NUM-1; i++) {
if (fence[(i<<1)]) {
rc = synx_import(fence[(i<<1)],
fence[((i<<1)+1)], &synx_obj);
if (rc) {
dprintk(CVP_ERR,
"%s: synx_import failed\n",
__func__);
do_exit(rc);
}
rc = synx_wait(synx_obj, timeout_ms);
if (rc) {
dprintk(CVP_ERR,
"%s: synx_wait failed\n",
__func__);
do_exit(rc);
}
rc = synx_release(synx_obj);
if (rc) {
dprintk(CVP_ERR,
"%s: synx_release failed\n",
__func__);
do_exit(rc);
}
}
}
rc = call_hfi_op(hdev, session_send,
(void *)inst->session, in_pkt);
if (rc) {
dprintk(CVP_ERR,
"%s: Failed in call_hfi_op %d, %x\n",
__func__, in_pkt->pkt_data[0],
in_pkt->pkt_data[1]);
do_exit(rc);
}
rc = wait_for_sess_signal_receipt(inst,
HAL_SESSION_DME_FRAME_CMD_DONE);
if (rc) {
dprintk(CVP_ERR, "%s: wait for signal failed, rc %d\n",
__func__, rc);
do_exit(rc);
}
rc = synx_import(fence[((HFI_DME_BUF_NUM-1)<<1)],
fence[((HFI_DME_BUF_NUM-1)<<1)+1],
&synx_obj);
if (rc) {
dprintk(CVP_ERR, "%s: synx_import failed\n", __func__);
do_exit(rc);
}
rc = synx_signal(synx_obj, SYNX_STATE_SIGNALED_SUCCESS);
if (rc) {
dprintk(CVP_ERR, "%s: synx_signal failed\n", __func__);
do_exit(rc);
}
if (synx_get_status(synx_obj) != SYNX_STATE_SIGNALED_SUCCESS) {
dprintk(CVP_ERR, "%s: synx_get_status failed\n",
__func__);
do_exit(rc);
}
rc = synx_release(synx_obj);
if (rc) {
dprintk(CVP_ERR, "%s: synx_release failed\n", __func__);
do_exit(rc);
}
break;
}
default:
dprintk(CVP_ERR, "%s: unknown hfi cmd type 0x%x\n",
__func__, fence_thread_data->arg_type);
rc = -EINVAL;
do_exit(rc);
break;
}
do_exit(0);
}
static int msm_cvp_session_process_hfifence(
struct msm_cvp_inst *inst,
struct cvp_kmd_arg *arg)
{
static int thread_num;
struct task_struct *thread;
int rc = 0;
char thread_fence_name[32];
dprintk(CVP_DBG, "%s:: Enter inst = %d", __func__, inst);
if (!inst || !inst->core || !arg) {
dprintk(CVP_ERR, "%s: invalid params\n", __func__);
return -EINVAL;
}
thread_num = thread_num + 1;
fence_thread_data.inst = inst;
fence_thread_data.device_id = (unsigned int)inst->core->id;
memcpy(&fence_thread_data.in_fence_pkt, &arg->data.hfi_fence_pkt,
sizeof(struct cvp_kmd_hfi_fence_packet));
fence_thread_data.arg_type = arg->type;
snprintf(thread_fence_name, sizeof(thread_fence_name),
"thread_fence_%d", thread_num);
thread = kthread_run(msm_cvp_thread_fence_run,
&fence_thread_data, thread_fence_name);
return rc;
}
static int msm_cvp_session_cvp_dfs_frame_response(
struct msm_cvp_inst *inst,
struct cvp_kmd_hfi_packet *dfs_frame)
{
int rc = 0;
dprintk(CVP_DBG, "%s:: Enter inst = %pK\n", __func__, inst);
if (!inst || !inst->core || !dfs_frame) {
dprintk(CVP_ERR, "%s: invalid params\n", __func__);
return -EINVAL;
}
rc = wait_for_sess_signal_receipt(inst,
HAL_SESSION_DFS_FRAME_CMD_DONE);
if (rc)
dprintk(CVP_ERR,
"%s: wait for signal failed, rc %d\n",
__func__, rc);
return rc;
}
static int msm_cvp_session_cvp_dme_frame_response(
struct msm_cvp_inst *inst,
struct cvp_kmd_hfi_packet *dme_frame)
{
int rc = 0;
dprintk(CVP_DBG, "%s:: Enter inst = %d", __func__, inst);
if (!inst || !inst->core || !dme_frame) {
dprintk(CVP_ERR, "%s: invalid params\n", __func__);
return -EINVAL;
}
rc = wait_for_sess_signal_receipt(inst,
HAL_SESSION_DME_FRAME_CMD_DONE);
if (rc)
dprintk(CVP_ERR,
"%s: wait for signal failed, rc %d\n",
__func__, rc);
return rc;
}
static int msm_cvp_session_cvp_persist_response(
struct msm_cvp_inst *inst,
struct cvp_kmd_hfi_packet *pbuf_cmd)
{
int rc = 0;
dprintk(CVP_DBG, "%s:: Enter inst = %d", __func__, inst);
if (!inst || !inst->core || !pbuf_cmd) {
dprintk(CVP_ERR, "%s: invalid params\n", __func__);
return -EINVAL;
}
rc = wait_for_sess_signal_receipt(inst,
HAL_SESSION_PERSIST_CMD_DONE);
if (rc)
dprintk(CVP_ERR,
"%s: wait for signal failed, rc %d\n",
__func__, rc);
return rc;
}
static int msm_cvp_send_cmd(struct msm_cvp_inst *inst,
struct cvp_kmd_send_cmd *send_cmd)
{
dprintk(CVP_ERR, "%s: UMD gave a deprecated cmd", __func__);
return 0;
}
static int msm_cvp_request_power(struct msm_cvp_inst *inst,
struct cvp_kmd_request_power *power)
{
int rc = 0;
if (!inst || !power) {
dprintk(CVP_ERR, "%s: invalid params\n", __func__);
return -EINVAL;
}
dprintk(CVP_DBG,
"%s: clock_cycles_a %d, clock_cycles_b %d, ddr_bw %d sys_cache_bw %d\n",
__func__, power->clock_cycles_a, power->clock_cycles_b,
power->ddr_bw, power->sys_cache_bw);
return rc;
}
static int msm_cvp_register_buffer(struct msm_cvp_inst *inst,
struct cvp_kmd_buffer *buf)
{
struct hfi_device *hdev;
struct hal_session *session;
if (!inst || !inst->core || !buf) {
dprintk(CVP_ERR, "%s: invalid params\n", __func__);
return -EINVAL;
}
session = (struct hal_session *)inst->session;
if (!session) {
dprintk(CVP_ERR, "%s: invalid session\n", __func__);
return -EINVAL;
}
hdev = inst->core->device;
print_client_buffer(CVP_DBG, "register", inst, buf);
return msm_cvp_map_buf(inst, buf);
}
static int msm_cvp_unregister_buffer(struct msm_cvp_inst *inst,
struct cvp_kmd_buffer *buf)
{
int rc = 0;
bool found;
struct hfi_device *hdev;
struct msm_cvp_internal_buffer *cbuf;
struct hal_session *session;
if (!inst || !inst->core || !buf) {
dprintk(CVP_ERR, "%s: invalid params\n", __func__);
return -EINVAL;
}
session = (struct hal_session *)inst->session;
if (!session) {
dprintk(CVP_ERR, "%s: invalid session\n", __func__);
return -EINVAL;
}
hdev = inst->core->device;
print_client_buffer(CVP_DBG, "unregister", inst, buf);
mutex_lock(&inst->cvpbufs.lock);
found = false;
list_for_each_entry(cbuf, &inst->cvpbufs.list, list) {
if (cbuf->buf.fd == buf->fd &&
cbuf->buf.offset == buf->offset) {
found = true;
break;
}
}
mutex_unlock(&inst->cvpbufs.lock);
if (!found) {
print_client_buffer(CVP_ERR, "invalid", inst, buf);
return -EINVAL;
}
if (buf->index) {
rc = cvp_dsp_deregister_buffer((uint32_t)cbuf->smem.device_addr,
buf->index, buf->size, hash32_ptr(session));
if (rc) {
dprintk(CVP_ERR,
"%s: failed dsp registration for fd = %d rc=%d",
__func__, buf->fd, rc);
}
}
if (cbuf->smem.device_addr)
msm_cvp_smem_unmap_dma_buf(inst, &cbuf->smem);
list_del(&cbuf->list);
kfree(cbuf);
return rc;
}
int msm_cvp_handle_syscall(struct msm_cvp_inst *inst, struct cvp_kmd_arg *arg)
{
int rc = 0;
if (!inst || !arg) {
dprintk(CVP_ERR, "%s: invalid args\n", __func__);
return -EINVAL;
}
dprintk(CVP_DBG, "%s:: arg->type = %x", __func__, arg->type);
switch (arg->type) {
case CVP_KMD_GET_SESSION_INFO:
{
struct cvp_kmd_session_info *session =
(struct cvp_kmd_session_info *)&arg->data.session;
rc = msm_cvp_get_session_info(inst, session);
break;
}
case CVP_KMD_REQUEST_POWER:
{
struct cvp_kmd_request_power *power =
(struct cvp_kmd_request_power *)&arg->data.req_power;
rc = msm_cvp_request_power(inst, power);
break;
}
case CVP_KMD_REGISTER_BUFFER:
{
struct cvp_kmd_buffer *buf =
(struct cvp_kmd_buffer *)&arg->data.regbuf;
rc = msm_cvp_register_buffer(inst, buf);
break;
}
case CVP_KMD_UNREGISTER_BUFFER:
{
struct cvp_kmd_buffer *buf =
(struct cvp_kmd_buffer *)&arg->data.unregbuf;
rc = msm_cvp_unregister_buffer(inst, buf);
break;
}
case CVP_KMD_HFI_SEND_CMD:
{
struct cvp_kmd_send_cmd *send_cmd =
(struct cvp_kmd_send_cmd *)&arg->data.send_cmd;
rc = msm_cvp_send_cmd(inst, send_cmd);
break;
}
case CVP_KMD_RECEIVE_MSG_PKT:
{
struct cvp_kmd_hfi_packet *out_pkt =
(struct cvp_kmd_hfi_packet *)&arg->data.hfi_pkt;
rc = msm_cvp_session_receive_hfi(inst, out_pkt);
break;
}
case CVP_KMD_SEND_CMD_PKT:
case CVP_KMD_HFI_DFS_CONFIG_CMD:
case CVP_KMD_HFI_DFS_FRAME_CMD:
case CVP_KMD_HFI_DME_CONFIG_CMD:
case CVP_KMD_HFI_DME_FRAME_CMD:
case CVP_KMD_HFI_PERSIST_CMD:
{
struct cvp_kmd_hfi_packet *in_pkt =
(struct cvp_kmd_hfi_packet *)&arg->data.hfi_pkt;
rc = msm_cvp_session_process_hfi(inst, in_pkt,
arg->buf_offset, arg->buf_num);
break;
}
case CVP_KMD_HFI_DFS_FRAME_CMD_RESPONSE:
{
struct cvp_kmd_hfi_packet *dfs_frame =
(struct cvp_kmd_hfi_packet *)&arg->data.hfi_pkt;
rc = msm_cvp_session_cvp_dfs_frame_response(inst, dfs_frame);
break;
}
case CVP_KMD_HFI_DME_FRAME_CMD_RESPONSE:
{
struct cvp_kmd_hfi_packet *dme_frame =
(struct cvp_kmd_hfi_packet *)&arg->data.hfi_pkt;
rc = msm_cvp_session_cvp_dme_frame_response(inst, dme_frame);
break;
}
case CVP_KMD_HFI_PERSIST_CMD_RESPONSE:
{
struct cvp_kmd_hfi_packet *pbuf_cmd =
(struct cvp_kmd_hfi_packet *)&arg->data.hfi_pkt;
rc = msm_cvp_session_cvp_persist_response(inst, pbuf_cmd);
break;
}
case CVP_KMD_HFI_DME_FRAME_FENCE_CMD:
{
rc = msm_cvp_session_process_hfifence(inst, arg);
break;
}
default:
dprintk(CVP_ERR, "%s: unknown arg type 0x%x\n",
__func__, arg->type);
rc = -ENOTSUPP;
break;
}
return rc;
}
int msm_cvp_session_deinit(struct msm_cvp_inst *inst)
{
int rc = 0;
struct msm_cvp_internal_buffer *cbuf, *temp;
if (!inst || !inst->core) {
dprintk(CVP_ERR, "%s: invalid params\n", __func__);
return -EINVAL;
}
dprintk(CVP_DBG, "%s: inst %pK (%#x)\n", __func__,
inst, hash32_ptr(inst->session));
rc = msm_cvp_comm_try_state(inst, MSM_CVP_CLOSE_DONE);
if (rc)
dprintk(CVP_ERR, "%s: close failed\n", __func__);
mutex_lock(&inst->cvpbufs.lock);
list_for_each_entry_safe(cbuf, temp, &inst->cvpbufs.list, list) {
print_cvp_internal_buffer(CVP_DBG, "unregistered", inst, cbuf);
rc = msm_cvp_smem_unmap_dma_buf(inst, &cbuf->smem);
if (rc)
dprintk(CVP_ERR, "%s: unmap failed\n", __func__);
list_del(&cbuf->list);
kfree(cbuf);
}
mutex_unlock(&inst->cvpbufs.lock);
inst->clk_data.min_freq = 0;
inst->clk_data.ddr_bw = 0;
inst->clk_data.sys_cache_bw = 0;
rc = msm_cvp_scale_clocks_and_bus(inst);
if (rc)
dprintk(CVP_ERR, "%s: failed to scale_clocks_and_bus\n",
__func__);
return rc;
}
int msm_cvp_session_init(struct msm_cvp_inst *inst)
{
int rc = 0;
if (!inst) {
dprintk(CVP_ERR, "%s: invalid params\n", __func__);
return -EINVAL;
}
dprintk(CVP_DBG, "%s: inst %pK (%#x)\n", __func__,
inst, hash32_ptr(inst->session));
/* set default frequency */
inst->clk_data.core_id = CVP_CORE_ID_2;
inst->clk_data.min_freq = 1000;
inst->clk_data.ddr_bw = 1000;
inst->clk_data.sys_cache_bw = 1000;
return rc;
}