diff options
author | Zhou Peng <eagle.zhou@nxp.com> | 2019-01-24 11:15:00 +0800 |
---|---|---|
committer | Dong Aisheng <aisheng.dong@nxp.com> | 2019-11-25 15:47:27 +0800 |
commit | 95b1763c0afb6ec3f58871b1fc8feae2e1856d36 (patch) | |
tree | d13e50bc8be2b926a8849f3110e751094fc60e75 /drivers/mxc/vpu_windsor/vpu_encoder_rpc.c | |
parent | c5b08a52fef39284c30c6f98de2f6f7009b9593a (diff) |
Add Malone decoder and windsor encoder for QXP/QM
Add vpu driver:
drivers/mxc/vpu_malone
drivers/mxc/vpu_windsor
Signed-off-by: Zhou Peng <eagle.zhou@nxp.com>
Diffstat (limited to 'drivers/mxc/vpu_windsor/vpu_encoder_rpc.c')
-rw-r--r-- | drivers/mxc/vpu_windsor/vpu_encoder_rpc.c | 448 |
1 files changed, 448 insertions, 0 deletions
diff --git a/drivers/mxc/vpu_windsor/vpu_encoder_rpc.c b/drivers/mxc/vpu_windsor/vpu_encoder_rpc.c new file mode 100644 index 000000000000..f670a940c8db --- /dev/null +++ b/drivers/mxc/vpu_windsor/vpu_encoder_rpc.c @@ -0,0 +1,448 @@ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2018 NXP. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2018 NXP. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <linux/kernel.h> +#include <linux/errno.h> +#include "vpu_encoder_rpc.h" + +void rpc_init_shared_memory_encoder(struct shared_addr *This, + unsigned long long base_phy_addr, + void *base_virt_addr, + u_int32 total_size, + u32 *actual_size) +{ + pENC_RPC_HOST_IFACE pSharedInterface; + unsigned int phy_addr; + unsigned int i; + unsigned int temp_addr; + BUFFER_DESCRIPTOR_TYPE *pSharedCmdBufDescPtr; + BUFFER_DESCRIPTOR_TYPE *pSharedMsgBufDescPtr; + pMEDIA_ENC_API_CONTROL_INTERFACE pEncCtrlInterface; + + This->shared_mem_phy = base_phy_addr; + This->shared_mem_vir = base_virt_addr; + This->base_offset = (unsigned long long)(base_virt_addr - base_phy_addr); + + pSharedInterface = (pENC_RPC_HOST_IFACE)This->shared_mem_vir; + This->pSharedInterface = pSharedInterface; + + pSharedInterface->FwExecBaseAddr = base_phy_addr; + pSharedInterface->FwExecAreaSize = total_size; + + pSharedCmdBufDescPtr = (BUFFER_DESCRIPTOR_TYPE *)&pSharedInterface->StreamCmdBufferDesc; + pSharedMsgBufDescPtr = (BUFFER_DESCRIPTOR_TYPE *)&pSharedInterface->StreamMsgBufferDesc; + + phy_addr = base_phy_addr + sizeof(ENC_RPC_HOST_IFACE); + This->cmd_mem_phy = phy_addr; + This->cmd_mem_vir = This->shared_mem_vir + sizeof(ENC_RPC_HOST_IFACE); + + pSharedCmdBufDescPtr->wptr = phy_addr; + pSharedCmdBufDescPtr->rptr = pSharedCmdBufDescPtr->wptr; + pSharedCmdBufDescPtr->start = pSharedCmdBufDescPtr->wptr; + pSharedCmdBufDescPtr->end = pSharedCmdBufDescPtr->start + CMD_SIZE; + + phy_addr += CMD_SIZE; + This->msg_mem_phy = phy_addr; + This->msg_mem_vir = This->cmd_mem_vir + CMD_SIZE; + + pSharedMsgBufDescPtr->wptr = phy_addr; + pSharedMsgBufDescPtr->rptr = pSharedMsgBufDescPtr->wptr; + pSharedMsgBufDescPtr->start = pSharedMsgBufDescPtr->wptr; + pSharedMsgBufDescPtr->end = pSharedMsgBufDescPtr->start + MSG_SIZE; + + phy_addr += MSG_SIZE; + + for (i = 0; i < VID_API_NUM_STREAMS; i++) { + pSharedInterface->pEncCtrlInterface[i] = phy_addr; + phy_addr += sizeof(MEDIA_ENC_API_CONTROL_INTERFACE); + } + + for (i = 0; i < VID_API_NUM_STREAMS; i++) { + temp_addr = pSharedInterface->pEncCtrlInterface[i]; + pEncCtrlInterface = (pMEDIA_ENC_API_CONTROL_INTERFACE)(temp_addr + This->base_offset); + pEncCtrlInterface->pEncYUVBufferDesc = phy_addr; + phy_addr += sizeof(MEDIAIP_ENC_YUV_BUFFER_DESC); + pEncCtrlInterface->pEncStreamBufferDesc = phy_addr; + phy_addr += sizeof(BUFFER_DESCRIPTOR_TYPE); + pEncCtrlInterface->pEncExpertModeParam = phy_addr; + phy_addr += sizeof(MEDIAIP_ENC_EXPERT_MODE_PARAM); + pEncCtrlInterface->pEncParam = phy_addr; + phy_addr += sizeof(MEDIAIP_ENC_PARAM); + pEncCtrlInterface->pEncMemPool = phy_addr; + phy_addr += sizeof(MEDIAIP_ENC_MEM_POOL); + pEncCtrlInterface->pEncEncodingStatus = phy_addr; + phy_addr += sizeof(ENC_ENCODING_STATUS); + pEncCtrlInterface->pEncDSAStatus = phy_addr; + phy_addr += sizeof(ENC_DSA_STATUS_t); + } + if (actual_size) + *actual_size = phy_addr - base_phy_addr; +} + +void rpc_set_system_cfg_value_encoder(void *Interface, u_int32 regs_base, u_int32 core_id) +{ + pENC_RPC_HOST_IFACE pSharedInterface; + MEDIAIP_FW_SYSTEM_CONFIG *pSystemCfg; + + pSharedInterface = (pENC_RPC_HOST_IFACE)Interface; + pSystemCfg = &pSharedInterface->sSystemCfg; + pSystemCfg->uNumWindsors = 1; + pSystemCfg->uWindsorIrqPin[0x0][0x0] = 0x4; // PAL_IRQ_WINDSOR_LOW + pSystemCfg->uWindsorIrqPin[0x0][0x1] = 0x5; // PAL_IRQ_WINDSOR_HI + pSystemCfg->uMaloneBaseAddress[0] = (unsigned int)(regs_base + 0x180000); + if (core_id == 0) + pSystemCfg->uWindsorBaseAddress[0] = (unsigned int)(regs_base + 0x800000); + else + pSystemCfg->uWindsorBaseAddress[0] = (unsigned int)(regs_base + 0xa00000); + pSystemCfg->uMaloneBaseAddress[0x1] = 0x0; + pSystemCfg->uHifOffset[0x0] = 0x1C000; + pSystemCfg->uHifOffset[0x1] = 0x0; + + pSystemCfg->uDPVBaseAddr = 0x0; + pSystemCfg->uDPVIrqPin = 0x0; + pSystemCfg->uPixIfBaseAddr = (unsigned int)(regs_base + 0x180000 + 0x20000); + pSystemCfg->uFSLCacheBaseAddr[0] = (unsigned int)(regs_base + 0x60000); + pSystemCfg->uFSLCacheBaseAddr[1] = (unsigned int)(regs_base + 0x68000); +} + +u_int32 rpc_MediaIPFW_Video_buffer_space_check_encoder(BUFFER_DESCRIPTOR_TYPE *pBufDesc, + BOOL bFull, + u_int32 uSize, + u_int32 *puUpdateAddress) +{ + u_int32 uPtr1; + u_int32 uPtr2; + u_int32 start; + u_int32 end; + u_int32 uTemp; + + /* bFull is FALSE when send message, write data */ + /* bFull is TRUE when process commands, read data */ + uPtr1 = (bFull) ? pBufDesc->rptr : pBufDesc->wptr; + uPtr2 = (bFull) ? pBufDesc->wptr : pBufDesc->rptr; + + if (uPtr1 == uPtr2) { + if (bFull) + /* No data at all to read */ + return 0; + else { + /* wrt pointer equal to read pointer thus the */ + /* buffer is completely empty for further writes */ + start = pBufDesc->start; + end = pBufDesc->end; + /* The address to be returned in this case is for */ + /* the updated write pointer. */ + uTemp = uPtr1 + uSize; + if (uTemp >= end) + uTemp += (start - end); + *puUpdateAddress = uTemp; + return (end - start); + } + } else if (uPtr1 < uPtr2) { + /* return updated rd pointer address */ + /* In this case if size was too big - we expect the */ + /* external ftn to compare the size against the */ + /* space returned. + */ + *puUpdateAddress = uPtr1 + uSize; + return (uPtr2 - uPtr1); + } + /* We know the system has looped!! */ + start = pBufDesc->start; + end = pBufDesc->end; + uTemp = uPtr1 + uSize; + if (uTemp >= end) + uTemp += (start - end); + *puUpdateAddress = uTemp; + return ((end - uPtr1) + (uPtr2 - start)); +} + +static void rpc_update_cmd_buffer_ptr_encoder(BUFFER_DESCRIPTOR_TYPE *pCmdDesc) +{ + u_int32 uWritePtr; + + /*avoid sw reset fail*/ + mb(); + uWritePtr = pCmdDesc->wptr + 4; + if (uWritePtr >= pCmdDesc->end) + uWritePtr = pCmdDesc->start; + pCmdDesc->wptr = uWritePtr; +} + +void rpc_send_cmd_buf_encoder(struct shared_addr *This, + u_int32 idx, + u_int32 cmdid, + u_int32 cmdnum, + u_int32 *local_cmddata) +{ + pENC_RPC_HOST_IFACE pSharedInterface = (pENC_RPC_HOST_IFACE)This->shared_mem_vir; + BUFFER_DESCRIPTOR_TYPE *pCmdDesc = &pSharedInterface->StreamCmdBufferDesc; + u_int32 *cmddata; + u_int32 i; + u_int32 *cmdword = (u_int32 *)(This->cmd_mem_vir+pCmdDesc->wptr - pCmdDesc->start); + + *cmdword = 0; + *cmdword |= ((idx & 0x000000ff) << 24); + *cmdword |= ((cmdnum & 0x000000ff) << 16); + *cmdword |= ((cmdid & 0x00003fff) << 0); + rpc_update_cmd_buffer_ptr_encoder(pCmdDesc); + + for (i = 0; i < cmdnum; i++) { + cmddata = (u_int32 *)(This->cmd_mem_vir+pCmdDesc->wptr - pCmdDesc->start); + *cmddata = local_cmddata[i]; + rpc_update_cmd_buffer_ptr_encoder(pCmdDesc); + } +} + +u_int32 rpc_MediaIPFW_Video_message_check_encoder(struct shared_addr *This) +{ + u_int32 uSpace; + u_int32 uIgnore; + pENC_RPC_HOST_IFACE pSharedInterface = (pENC_RPC_HOST_IFACE)This->shared_mem_vir; + BUFFER_DESCRIPTOR_TYPE *pMsgDesc = &pSharedInterface->StreamMsgBufferDesc; + u_int32 msgword; + u_int32 msgnum; + + uSpace = rpc_MediaIPFW_Video_buffer_space_check_encoder(pMsgDesc, TRUE, 0, &uIgnore); + uSpace = (uSpace >> 2); + if (uSpace) { + /* get current msgword word */ + msgword = *((u_int32 *)(This->msg_mem_vir+pMsgDesc->rptr - pMsgDesc->start)); + /* Find the number of additional words */ + msgnum = ((msgword & 0x00ff0000) >> 16); + + /* + * * Check the number of message words against + * * 1) a limit - some sort of maximum or at least + * * the size of the SW buffer the message is read into + * * 2) The space reported (where space is write ptr - read ptr in 32bit words) + * * It must be less than space (as opposed to <=) because + * * the message itself is not included in msgword + */ + if (msgnum < VID_API_MESSAGE_LIMIT) { + if (msgnum < uSpace) + return API_MSG_AVAILABLE; + else + return API_MSG_INCOMPLETE; + } else + return API_MSG_BUFFER_ERROR; + } + return API_MSG_UNAVAILABLE; +} + +static void rpc_update_msg_buffer_ptr_encoder(BUFFER_DESCRIPTOR_TYPE *pMsgDesc) +{ + u_int32 uReadPtr; + + uReadPtr = pMsgDesc->rptr + 4; + if (uReadPtr >= pMsgDesc->end) + uReadPtr = pMsgDesc->start; + pMsgDesc->rptr = uReadPtr; +} + +u32 rpc_read_msg_u32(struct shared_addr *shared_mem) +{ + u32 msgword; + u32 *ptr = NULL; + pENC_RPC_HOST_IFACE iface = NULL; + BUFFER_DESCRIPTOR_TYPE *msg_buf = NULL; + + if (!shared_mem) + return 0; + + iface = shared_mem->pSharedInterface; + msg_buf = &iface->StreamMsgBufferDesc; + ptr = shared_mem->msg_mem_vir + msg_buf->rptr - msg_buf->start; + rpc_update_msg_buffer_ptr_encoder(msg_buf); + msgword = *ptr; + + return msgword; +} + +int rpc_read_msg_array(struct shared_addr *shared_mem, u32 *buf, u32 number) +{ + int i; + u32 val; + + if (!shared_mem) + return -EINVAL; + + for (i = 0; i < number; i++) { + val = rpc_read_msg_u32(shared_mem); + if (buf) + buf[i] = val; + } + + return 0; +} + +int rpc_get_msg_header(struct shared_addr *shared_mem, struct msg_header *msg) +{ + u32 msgword; + + if (!shared_mem || !msg) + return -EINVAL; + + msgword = rpc_read_msg_u32(shared_mem); + msg->idx = ((msgword & 0xff000000) >> 24); + msg->msgnum = ((msgword & 0x00ff0000) >> 16); + msg->msgid = ((msgword & 0x00003fff) >> 0); + + return 0; +} + +static void *phy_to_virt(u_int32 src, unsigned long long offset) +{ + void *result; + + result = (void *)(src + offset); + return result; +} + +#define GET_CTRL_INTERFACE_MEMBER(shared_mem, index, name, member) \ + do {\ + pENC_RPC_HOST_IFACE iface = shared_mem->pSharedInterface; \ + pMEDIA_ENC_API_CONTROL_INTERFACE ctrl_interface =\ + phy_to_virt(iface->pEncCtrlInterface[index],\ + shared_mem->base_offset);\ + name = phy_to_virt(ctrl_interface->member,\ + shared_mem->base_offset);\ + } while (0) + +pMEDIAIP_ENC_YUV_BUFFER_DESC rpc_get_yuv_buffer_desc( + struct shared_addr *shared_mem, int index) +{ + pMEDIAIP_ENC_YUV_BUFFER_DESC desc = NULL; + + GET_CTRL_INTERFACE_MEMBER(shared_mem, index, desc, pEncYUVBufferDesc); + + return desc; +} + +pBUFFER_DESCRIPTOR_TYPE rpc_get_stream_buffer_desc( + struct shared_addr *shared_mem, int index) +{ + pBUFFER_DESCRIPTOR_TYPE desc = NULL; + + GET_CTRL_INTERFACE_MEMBER(shared_mem, index, + desc, pEncStreamBufferDesc); + + return desc; +} + +pMEDIAIP_ENC_EXPERT_MODE_PARAM rpc_get_expert_mode_param( + struct shared_addr *shared_mem, int index) +{ + pMEDIAIP_ENC_EXPERT_MODE_PARAM param = NULL; + + GET_CTRL_INTERFACE_MEMBER(shared_mem, index, + param, pEncExpertModeParam); + + return param; +} + +pMEDIAIP_ENC_PARAM rpc_get_enc_param( + struct shared_addr *shared_mem, int index) +{ + pMEDIAIP_ENC_PARAM param = NULL; + + GET_CTRL_INTERFACE_MEMBER(shared_mem, index, param, pEncParam); + + return param; +} + +pMEDIAIP_ENC_MEM_POOL rpc_get_mem_pool( + struct shared_addr *shared_mem, int index) +{ + pMEDIAIP_ENC_MEM_POOL pool = NULL; + + GET_CTRL_INTERFACE_MEMBER(shared_mem, index, pool, pEncMemPool); + + return pool; +} + +pENC_ENCODING_STATUS rpc_get_encoding_status( + struct shared_addr *shared_mem, int index) +{ + pENC_ENCODING_STATUS encoding_status = NULL; + + GET_CTRL_INTERFACE_MEMBER(shared_mem, index, + encoding_status, pEncEncodingStatus); + + return encoding_status; +} + +pENC_DSA_STATUS_t rpc_get_dsa_status(struct shared_addr *shared_mem, int index) +{ + pENC_DSA_STATUS_t dsa_status = NULL; + + GET_CTRL_INTERFACE_MEMBER(shared_mem, index, dsa_status, pEncDSAStatus); + + return dsa_status; +} + +void rpc_set_print_buffer(struct shared_addr *shared_mem, + unsigned long print_phy_addr, u32 size) +{ + pENC_RPC_HOST_IFACE pSharedInterface; + pBUFFER_DESCRIPTOR_TYPE debugBufDesc; + + + pSharedInterface = shared_mem->pSharedInterface; + debugBufDesc = &pSharedInterface->DebugBufferDesc; + + debugBufDesc->start = print_phy_addr; + debugBufDesc->end = debugBufDesc->start + size; + debugBufDesc->wptr = debugBufDesc->rptr = debugBufDesc->start; +} |