| /******************************************************************************* |
| * Copyright (C) Marvell International Ltd. and its affiliates |
| * |
| * Marvell GPL License Option |
| * |
| * If you received this File from Marvell, you may opt to use, redistribute and/or |
| * modify this File in accordance with the terms and conditions of the General |
| * Public License Version 2, June 1991 (the "GPL License"), a copy of which is |
| * available along with the File in the license.txt file or by writing to the Free |
| * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or |
| * on the worldwide web at http://www.gnu.org/licenses/gpl.txt. |
| * |
| * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED |
| * WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY |
| * DISCLAIMED. The GPL License provides additional details about this warranty |
| * disclaimer. |
| ********************************************************************************/ |
| |
| /******************************************************************************* |
| System head files |
| */ |
| |
| #include <linux/init.h> |
| #include <linux/module.h> |
| #include <linux/moduleparam.h> |
| #include <linux/sched.h> |
| #include <net/sock.h> |
| #include <linux/proc_fs.h> |
| |
| #include <linux/kernel.h> |
| #include <linux/slab.h> |
| #include <linux/fs.h> |
| #include <linux/errno.h> |
| #include <linux/types.h> |
| |
| #include <linux/mm.h> |
| #include <linux/kdev_t.h> |
| #include <asm/page.h> |
| #include <linux/cdev.h> |
| #include <linux/device.h> |
| #include <linux/version.h> |
| #include <linux/interrupt.h> |
| #include <linux/spinlock.h> |
| #include <asm/uaccess.h> |
| #include <linux/reboot.h> |
| |
| #include <linux/of.h> |
| #include <linux/of_irq.h> |
| /******************************************************************************* |
| Local head files |
| */ |
| |
| #include <mach/galois_generic.h> |
| |
| #include "galois_io.h" |
| #include "cinclude.h" |
| #include "zspWrapper.h" |
| |
| #include "api_avio_dhub.h" |
| #include "shm_api.h" |
| #include "cc_msgq.h" |
| #include "cc_error.h" |
| |
| #include "pe_driver.h" |
| #include "pe_agent_driver.h" |
| #include "pe_memmap.h" |
| #include "api_dhub.h" |
| |
| #ifdef CONFIG_BERLIN_FASTLOGO |
| #include "../fastlogo/fastlogo_driver.h" |
| static int pe_cpu_id = 0; |
| static int dhub_init_flag =0; |
| #endif |
| |
| enum { |
| IRQ_ZSPINT, |
| IRQ_DHUBINTRAVIO0, |
| IRQ_DHUBINTRAVIO1, |
| IRQ_DHUBINTRAVIO2, |
| IRQ_DHUBINTRVPRO, |
| IRQ_SM_CEC, |
| IRQ_PE_MAX, |
| }; |
| static int pe_irqs[IRQ_PE_MAX]; |
| /******************************************************************************* |
| Module API defined |
| */ |
| |
| // set 1 to enable message by ioctl |
| // set 0 to enable ICC message queue |
| #define CONFIG_VPP_IOCTL_MSG 1 |
| // when CONFIG_VPP_IOCTL_MSG is 1 |
| // set 1 to use internal message queue between isr and ioctl function |
| // set 0 to use no queue |
| #define CONFIG_VPP_ISR_MSGQ 1 |
| |
| // only enable when VPP use ioctl |
| #if CONFIG_VPP_IOCTL_MSG |
| // set 1 to enable message by ioctl |
| // set 0 to enable ICC message queue |
| #define CONFIG_VIP_IOCTL_MSG 1 |
| // when CONFIG_VIP_IOCTL_MSG is 1 |
| // set 1 to use internal message queue between isr and ioctl function |
| // set 0 to use no queue |
| #define CONFIG_VIP_ISR_MSGQ 1 |
| #endif |
| |
| #define CONFIG_VDEC_UNBLC_IRQ_FIX 0 |
| |
| #define PE_DEVICE_NAME "galois_pe" |
| #define PE_DEVICE_TAG "[Galois][pe_driver] " |
| #define PE_DEVICE_PATH ("/dev/" PE_DEVICE_NAME) |
| |
| #define PE_DEVICE_PROCFILE_STATUS "status" |
| #define PE_DEVICE_PROCFILE_DETAIL "detail" |
| |
| #define MV_BERLIN_CPU0 0 |
| #define PE_MODULE_MSG_ID_VPP MV_GS_VPP_Serv |
| #define PE_MODULE_MSG_ID_VDEC MV_GS_VDEC_Serv |
| #define PE_MODULE_MSG_ID_AUD MV_GS_AUD_Serv |
| #define PE_MODULE_MSG_ID_ZSP MV_GS_ZSP_Serv |
| #define PE_MODULE_MSG_ID_RLE MV_GS_RLE_Serv |
| #define PE_MODULE_MSG_ID_VIP MV_GS_VIP_Serv |
| #define PE_MODULE_MSG_ID_AIP MV_GS_AIP_Serv |
| |
| #define VPP_CC_MSG_TYPE_VPP 0x00 |
| #define VPP_CC_MSG_TYPE_CEC 0x01 |
| |
| #define ADSP_ZSPINT2Soc_IRQ0 0 |
| |
| #define VPP_IOCTL_VBI_DMA_CFGQ 0xbeef0001 |
| #define VPP_IOCTL_VBI_BCM_CFGQ 0xbeef0002 |
| #define VPP_IOCTL_VDE_BCM_CFGQ 0xbeef0003 |
| #define VPP_IOCTL_GET_MSG 0xbeef0004 |
| #define VPP_IOCTL_START_BCM_TRANSACTION 0xbeef0005 |
| #define VPP_IOCTL_BCM_SCHE_CMD 0xbeef0006 |
| #define VPP_IOCTL_INTR_MSG 0xbeef0007 |
| #define CEC_IOCTL_RX_MSG_BUF_MSG 0xbeef0008 |
| |
| #define VDEC_IOCTL_ENABLE_INT 0xbeef1001 |
| #define VDEC_IOCTL_DISABLE_INT 0xbeef1002 |
| #define AOUT_IOCTL_START_CMD 0xbeef2001 |
| #define AIP_IOCTL_START_CMD 0xbeef2002 |
| #define AIP_IOCTL_STOP_CMD 0xbeef2003 |
| #define AOUT_IOCTL_STOP_CMD 0xbeef2004 |
| #define AOUT_IOCTL_DISABLE_INT_MSG 0xbeef2005 |
| |
| #define APP_IOCTL_INIT_CMD 0xbeef3001 |
| #define APP_IOCTL_START_CMD 0xbeef3002 |
| |
| #define VIP_IOCTL_GET_MSG 0xbeef4001 |
| #define VIP_IOCTL_VBI_BCM_CFGQ 0xbeef4002 |
| #define VIP_IOCTL_SD_WRE_CFGQ 0xbeef4003 |
| #define VIP_IOCTL_SD_RDE_CFGQ 0xbeef4004 |
| #define VIP_IOCTL_SEND_MSG 0xbeef4005 |
| #define VIP_IOCTL_VDE_BCM_CFGQ 0xbeef4006 |
| #define VIP_IOCTL_INTR_MSG 0xbeef4007 |
| |
| //CEC MACRO |
| #define SM_APB_ICTL1_BASE 0xf7fce000 |
| #define SM_APB_GPIO0_BASE 0xf7fcc000 |
| #define APB_GPIO_PORTA_EOI 0x4c |
| #define APB_GPIO_INTSTATUS 0x40 |
| #define APB_ICTL_IRQ_STATUS_L 0x20 |
| #define BE_CEC_INTR_TX_SFT_FAIL 0x2008 // puneet |
| #define BE_CEC_INTR_TX_FAIL 0x200F |
| #define BE_CEC_INTR_TX_COMPLETE 0x0010 |
| #define BE_CEC_INTR_RX_COMPLETE 0x0020 |
| #define BE_CEC_INTR_RX_FAIL 0x00C0 |
| #define SOC_SM_CEC_BASE 0xF7FE1000 |
| #define CEC_INTR_STATUS0_REG_ADDR 0x0058 |
| #define CEC_INTR_STATUS1_REG_ADDR 0x0059 |
| #define CEC_INTR_ENABLE0_REG_ADDR 0x0048 |
| #define CEC_INTR_ENABLE1_REG_ADDR 0x0049 |
| #define CEC_RDY_ADDR 0x0008 |
| #define CEC_RX_BUF_READ_REG_ADDR 0x0068 |
| #define CEC_RX_EOM_READ_REG_ADDR 0x0069 |
| #define CEC_TOGGLE_FOR_READ_REG_ADDR 0x0004 |
| #define CEC_RX_RDY_ADDR 0x000c //01 |
| #define CEC_RX_FIFO_DPTR 0x0087 |
| static int pe_driver_open(struct inode *inode, struct file *filp); |
| static int pe_driver_release(struct inode *inode, struct file *filp); |
| static long pe_driver_ioctl_unlocked(struct file *filp, unsigned int cmd, |
| unsigned long arg); |
| |
| /******************************************************************************* |
| Macro Defined |
| */ |
| |
| #ifdef ENABLE_DEBUG |
| #define pe_debug(...) printk(KERN_DEBUG PE_DEVICE_TAG __VA_ARGS__) |
| #else |
| #define pe_debug(...) |
| #endif |
| |
| #define pe_trace(...) printk(KERN_WARNING PE_DEVICE_TAG __VA_ARGS__) |
| #define pe_error(...) printk(KERN_ERR PE_DEVICE_TAG __VA_ARGS__) |
| |
| //#define VPP_DBG |
| |
| #define DEBUG_TIMER_VALUE (0xFFFFFFFF) |
| |
| /******************************************************************************* |
| Module Variable |
| */ |
| |
| #if CONFIG_VDEC_UNBLC_IRQ_FIX |
| static int vdec_int_cnt; |
| static int vdec_enable_int_cnt; |
| #endif |
| |
| static struct cdev pe_dev; |
| static struct class *pe_dev_class; |
| |
| static struct file_operations pe_ops = { |
| .open = pe_driver_open, |
| .release = pe_driver_release, |
| .unlocked_ioctl = pe_driver_ioctl_unlocked, |
| .owner = THIS_MODULE, |
| }; |
| |
| typedef struct VPP_DMA_INFO_T { |
| UINT32 DmaAddr; |
| UINT32 DmaLen; |
| UINT32 cpcbID; |
| } VPP_DMA_INFO; |
| |
| typedef struct VPP_CEC_RX_MSG_BUF_T { |
| UINT8 buf[16]; |
| UINT8 len; |
| } VPP_CEC_RX_MSG_BUF; |
| |
| static VPP_DMA_INFO dma_info[3]; |
| static VPP_DMA_INFO vbi_bcm_info[3]; |
| static VPP_DMA_INFO vde_bcm_info[3]; |
| static unsigned int bcm_sche_cmd[6][2]; |
| static VPP_CEC_RX_MSG_BUF rx_buf; |
| |
| #if (BERLIN_CHIP_VERSION >= BERLIN_BG2) |
| typedef struct VIP_DMA_INFO_T { |
| UINT32 DmaAddr; |
| UINT32 DmaLen; |
| } VIP_DMA_INFO; |
| |
| static VIP_DMA_INFO vip_dma_info; |
| static VIP_DMA_INFO vip_vbi_info; |
| static VIP_DMA_INFO vip_sd_wr_info; |
| static VIP_DMA_INFO vip_sd_rd_info; |
| |
| /////////////////////////////////////////NEW_ISR related |
| #define NEW_ISR |
| //This array stores all the VIP intrs enable/disable status |
| #define MAX_INTR_NUM 0x20 |
| static UINT32 vip_intr_status[MAX_INTR_NUM]; |
| static UINT32 vpp_intr_status[MAX_INTR_NUM]; |
| |
| typedef struct INTR_MSG_T { |
| UINT32 DhubSemMap; |
| UINT32 Enable; |
| } INTR_MSG; |
| /////////////////////////////////////////End of NEW_ISR |
| |
| static void pe_vip_do_tasklet(unsigned long); |
| DECLARE_TASKLET_DISABLED(pe_vip_tasklet, pe_vip_do_tasklet, 0); |
| |
| #define VIP_MSG_DESTROY_ISR_TASK 1 |
| #endif |
| |
| static AOUT_PATH_CMD_FIFO *p_ma_fifo; |
| static AOUT_PATH_CMD_FIFO *p_sa_fifo; |
| static AOUT_PATH_CMD_FIFO *p_spdif_fifo; |
| static AOUT_PATH_CMD_FIFO *p_hdmi_fifo; |
| static HWAPP_CMD_FIFO *p_app_fifo; |
| static AIP_DMA_CMD_FIFO *p_aip_fifo; |
| |
| static int aip_i2s_pair; |
| static int disable_hdmi_int_msg = 0; |
| |
| static struct proc_dir_entry *pe_driver_procdir; |
| static int vpp_cpcb0_vbi_int_cnt; |
| static int vpp_hdmi_audio_int_cnt; |
| //static int vpp_cpcb2_vbi_int_cnt = 0; |
| |
| static DEFINE_SPINLOCK(bcm_spinlock); |
| static DEFINE_SPINLOCK(aout_spinlock); |
| static DEFINE_SPINLOCK(app_spinlock); |
| static DEFINE_SPINLOCK(aip_spinlock); |
| static DEFINE_SPINLOCK(msgQ_spinlock); |
| |
| static void pe_vpp_do_tasklet(unsigned long); |
| static void pe_vpp_cec_do_tasklet(unsigned long); // cec tasklet added |
| static void pe_vdec_do_tasklet(unsigned long); |
| |
| static void pe_ma_do_tasklet(unsigned long); |
| static void pe_sa_do_tasklet(unsigned long); |
| static void pe_spdif_do_tasklet(unsigned long); |
| static void pe_aip_do_tasklet(unsigned long); |
| static void pe_hdmi_do_tasklet(unsigned long); |
| static void pe_app_do_tasklet(unsigned long); |
| static void pe_zsp_do_tasklet(unsigned long); |
| static void pe_pg_dhub_done_tasklet(unsigned long); |
| static void pe_rle_do_err_tasklet(unsigned long); |
| static void pe_rle_do_done_tasklet(unsigned long); |
| static void aout_resume_cmd(int path_id); |
| static void aip_resume_cmd(void); |
| |
| static DECLARE_TASKLET_DISABLED(pe_vpp_tasklet, pe_vpp_do_tasklet, 0); |
| static DECLARE_TASKLET_DISABLED(pe_vpp_cec_tasklet, pe_vpp_cec_do_tasklet, 0); |
| static DECLARE_TASKLET_DISABLED(pe_vdec_tasklet, pe_vdec_do_tasklet, 0); |
| static DECLARE_TASKLET_DISABLED(pe_ma_tasklet, pe_ma_do_tasklet, 0); |
| static DECLARE_TASKLET_DISABLED(pe_sa_tasklet, pe_sa_do_tasklet, 0); |
| static DECLARE_TASKLET_DISABLED(pe_spdif_tasklet, pe_spdif_do_tasklet, 0); |
| static DECLARE_TASKLET_DISABLED(pe_aip_tasklet, pe_aip_do_tasklet, 0); |
| static DECLARE_TASKLET_DISABLED(pe_hdmi_tasklet, pe_hdmi_do_tasklet, 0); |
| static DECLARE_TASKLET_DISABLED(pe_app_tasklet, pe_app_do_tasklet, 0); |
| static DECLARE_TASKLET_DISABLED(pe_zsp_tasklet, pe_zsp_do_tasklet, 0); |
| static DECLARE_TASKLET_DISABLED(pe_pg_done_tasklet, pe_pg_dhub_done_tasklet, 0); |
| static DECLARE_TASKLET_DISABLED(pe_rle_err_tasklet, pe_rle_do_err_tasklet, 0); |
| static DECLARE_TASKLET_DISABLED(pe_rle_done_tasklet, pe_rle_do_done_tasklet, 0); |
| |
| #if (0) |
| #define CLEAR_FIGO_INTR \ |
| {(*(volatile UINT*)(MEMMAP_TSI_REG_BASE+RA_DRMDMX_figoSys+RA_FigoSys_FIGO0+BA_FigoReg_figoIntrLvl_st)) = 1;} |
| #define INTRA_MSG_DMX_FIGO_IRQ 0x3000 |
| #endif |
| |
| #if CONFIG_VPP_IOCTL_MSG |
| static INT vpp_instat; |
| static UINT vpp_intr_timestamp; |
| static DEFINE_SEMAPHORE(vpp_sem); |
| #endif |
| |
| #if (BERLIN_CHIP_VERSION >= BERLIN_BG2) |
| #if CONFIG_VIP_IOCTL_MSG |
| static UINT vip_intr_timestamp; |
| static DEFINE_SEMAPHORE(vip_sem); |
| #endif |
| #endif |
| |
| #if CONFIG_VPP_ISR_MSGQ |
| |
| struct pe_message_queue; |
| typedef struct pe_message_queue { |
| UINT q_length; |
| UINT rd_number; |
| UINT wr_number; |
| MV_CC_MSG_t *pMsg; |
| |
| HRESULT(*Add) (struct pe_message_queue *pMsgQ, MV_CC_MSG_t *pMsg); |
| HRESULT(*ReadTry) (struct pe_message_queue *pMsgQ, |
| MV_CC_MSG_t *pMsg); |
| HRESULT(*ReadFin) (struct pe_message_queue *pMsgQ); |
| HRESULT(*Destroy) (struct pe_message_queue *pMsgQ); |
| |
| } PEMsgQ_t; |
| |
| #define VPP_ISR_MSGQ_SIZE 32 |
| |
| static PEMsgQ_t hPEMsgQ; |
| |
| |
| static HRESULT PEMsgQ_Add(PEMsgQ_t *pMsgQ, MV_CC_MSG_t *pMsg) |
| { |
| INT wr_offset; |
| |
| if (NULL == pMsgQ->pMsg || pMsg == NULL) |
| return S_FALSE; |
| |
| wr_offset = pMsgQ->wr_number - pMsgQ->rd_number; |
| |
| if (wr_offset == -1 || wr_offset == (pMsgQ->q_length - 2)) { |
| return S_FALSE; |
| } else { |
| memcpy((CHAR *) & pMsgQ->pMsg[pMsgQ->wr_number], (CHAR *) pMsg, |
| sizeof(MV_CC_MSG_t)); |
| pMsgQ->wr_number++; |
| pMsgQ->wr_number %= pMsgQ->q_length; |
| } |
| |
| return S_OK; |
| } |
| |
| static HRESULT PEMsgQ_ReadTry(PEMsgQ_t *pMsgQ, MV_CC_MSG_t *pMsg) |
| { |
| INT rd_offset; |
| |
| if (NULL == pMsgQ->pMsg || pMsg == NULL) |
| return S_FALSE; |
| |
| rd_offset = pMsgQ->rd_number - pMsgQ->wr_number; |
| |
| if (rd_offset != 0) { |
| memcpy((CHAR *) pMsg, (CHAR *) & pMsgQ->pMsg[pMsgQ->rd_number], |
| sizeof(MV_CC_MSG_t)); |
| return S_OK; |
| } else { |
| return S_FALSE; |
| } |
| } |
| |
| static HRESULT PEMsgQ_ReadFinish(PEMsgQ_t *pMsgQ) |
| { |
| INT rd_offset; |
| |
| rd_offset = pMsgQ->rd_number - pMsgQ->wr_number; |
| |
| if (rd_offset != 0) { |
| pMsgQ->rd_number++; |
| pMsgQ->rd_number %= pMsgQ->q_length; |
| |
| return S_OK; |
| } else { |
| return S_FALSE; |
| } |
| } |
| |
| #define MIN(a, b) (((a) < (b)) ? (a) : (b)) |
| #define MAX(a, b) ((a) > (b) ? (a) : (b)) |
| |
| static int PEMsgQ_Dequeue(PEMsgQ_t *pMsgQ, int cnt) |
| { |
| INT fullness; |
| |
| if (cnt <= 0) |
| return -1; |
| |
| fullness = pMsgQ->wr_number - pMsgQ->rd_number; |
| if (fullness < 0) { |
| fullness += pMsgQ->q_length; |
| } |
| |
| cnt = MIN(fullness, cnt); |
| if (cnt) { |
| pMsgQ->rd_number += cnt; |
| if (pMsgQ->rd_number >= pMsgQ->q_length) |
| pMsgQ->rd_number -= pMsgQ->q_length; |
| } |
| return cnt; |
| } |
| |
| static int PEMsgQ_DequeueRead(PEMsgQ_t *pMsgQ, MV_CC_MSG_t *pMsg) |
| { |
| INT fullness; |
| |
| if (NULL == pMsgQ->pMsg || pMsg == NULL) |
| return S_FALSE; |
| |
| fullness = pMsgQ->wr_number - pMsgQ->rd_number; |
| if (fullness < 0) { |
| fullness += pMsgQ->q_length; |
| } |
| |
| if (fullness) { |
| if (pMsg) |
| memcpy((void *)pMsg, |
| (void *)&pMsgQ->pMsg[pMsgQ->rd_number], |
| sizeof(MV_CC_MSG_t)); |
| |
| pMsgQ->rd_number++; |
| if (pMsgQ->rd_number >= pMsgQ->q_length) |
| pMsgQ->rd_number -= pMsgQ->q_length; |
| |
| return 1; |
| } |
| |
| return 0; |
| } |
| |
| static int PEMsgQ_Fullness(PEMsgQ_t *pMsgQ) |
| { |
| INT fullness; |
| |
| fullness = pMsgQ->wr_number - pMsgQ->rd_number; |
| if (fullness < 0) { |
| fullness += pMsgQ->q_length; |
| } |
| |
| return fullness; |
| } |
| |
| static HRESULT PEMsgQ_Destroy(PEMsgQ_t *pMsgQ) |
| { |
| if (pMsgQ == NULL) { |
| return E_FAIL; |
| } |
| |
| if (pMsgQ->pMsg) |
| kfree(pMsgQ->pMsg); |
| |
| return S_OK; |
| } |
| |
| static HRESULT PEMsgQ_Init(PEMsgQ_t *pPEMsgQ, UINT q_length) |
| { |
| pPEMsgQ->q_length = q_length; |
| pPEMsgQ->rd_number = pPEMsgQ->wr_number = 0; |
| pPEMsgQ->pMsg = |
| (MV_CC_MSG_t *) kmalloc(sizeof(MV_CC_MSG_t) * q_length, GFP_ATOMIC); |
| |
| if (pPEMsgQ->pMsg == NULL) { |
| return E_OUTOFMEMORY; |
| } |
| |
| pPEMsgQ->Destroy = PEMsgQ_Destroy; |
| pPEMsgQ->Add = PEMsgQ_Add; |
| pPEMsgQ->ReadTry = PEMsgQ_ReadTry; |
| pPEMsgQ->ReadFin = PEMsgQ_ReadFinish; |
| // pPEMsgQ->Fullness = PEMsgQ_Fullness; |
| |
| return S_OK; |
| } |
| |
| #endif |
| |
| #if (BERLIN_CHIP_VERSION >= BERLIN_BG2) |
| |
| #if CONFIG_VIP_ISR_MSGQ |
| // MSGQ for VIP |
| #define VIP_ISR_MSGQ_SIZE 64 |
| static PEMsgQ_t hPEVIPMsgQ; |
| #endif |
| |
| static void pe_vip_do_tasklet(unsigned long unused) |
| { |
| MV_CC_MSG_t msg = { 0 }; |
| |
| MV_CC_MsgQ_PostMsgByID(PE_MODULE_MSG_ID_VIP, &msg); |
| } |
| #endif |
| |
| static void pe_vpp_do_tasklet(unsigned long unused) |
| { |
| MV_CC_MSG_t msg = { 0 }; |
| UINT32 val; |
| |
| msg.m_MsgID = VPP_CC_MSG_TYPE_VPP; |
| |
| msg.m_Param1 = unused; |
| |
| GA_REG_WORD32_READ(0xf7e82C00 + 0x04 + 7 * 0x14, &val); |
| msg.m_Param2 = DEBUG_TIMER_VALUE - val; |
| |
| MV_CC_MsgQ_PostMsgByID(PE_MODULE_MSG_ID_VPP, &msg); |
| } |
| |
| static void pe_vpp_cec_do_tasklet(unsigned long unused) |
| { |
| MV_CC_MSG_t msg = { 0 }; |
| UINT32 val; |
| |
| msg.m_MsgID = VPP_CC_MSG_TYPE_CEC; |
| |
| msg.m_Param1 = unused; |
| |
| GA_REG_WORD32_READ(0xf7e82C00 + 0x04 + 7 * 0x14, &val); |
| msg.m_Param2 = DEBUG_TIMER_VALUE - val; |
| |
| MV_CC_MsgQ_PostMsgByID(PE_MODULE_MSG_ID_VPP, &msg); |
| } |
| |
| static void pe_vdec_do_tasklet(unsigned long unused) |
| { |
| MV_CC_MSG_t msg = { 0 }; |
| |
| MV_CC_MsgQ_PostMsgByID(PE_MODULE_MSG_ID_VDEC, &msg); |
| } |
| |
| static void MV_VPP_action(struct softirq_action *h) |
| { |
| MV_CC_MSG_t msg = { 0, }; |
| |
| MV_CC_MsgQ_PostMsgByID(PE_MODULE_MSG_ID_VPP, &msg); |
| // pe_trace("ISR conext irq:%d\n", vpp_cpcb0_vbi_int_cnt); |
| } |
| |
| static int vbi_bcm_cmd_fullcnt; |
| static int vde_bcm_cmd_fullcnt; |
| |
| static void start_vbi_bcm_transaction(int cpcbID) |
| { |
| #if (BERLIN_CHIP_VERSION >= BERLIN_BG2) |
| unsigned int bcm_sched_cmd[2]; |
| |
| if (vbi_bcm_info[cpcbID].DmaLen) { |
| dhub_channel_generate_cmd(&(VPP_dhubHandle.dhub), |
| avioDhubChMap_vpp_BCM_R, |
| (INT) vbi_bcm_info[cpcbID].DmaAddr, |
| (INT) vbi_bcm_info[cpcbID].DmaLen * 8, |
| 0, 0, 0, 1, bcm_sched_cmd); |
| while (!BCM_SCHED_PushCmd(BCM_SCHED_Q12, bcm_sched_cmd, NULL)) { |
| vbi_bcm_cmd_fullcnt++; |
| } |
| } |
| #else |
| UINT32 cnt; |
| UINT32 *ptr; |
| |
| ptr = (UINT32 *) vbi_bcm_info[cpcbID].DmaAddr; |
| for (cnt = 0; cnt < vbi_bcm_info[cpcbID].DmaLen; cnt++) { |
| dhub_channel_write_cmd(&(VPP_dhubHandle.dhub), |
| avioDhubChMap_vpp_BCM_R, (INT) * ptr, |
| (INT) * (ptr + 1), 0, 0, 0, 1, 0, 0); |
| ptr += 2; |
| } |
| #endif |
| /* invalid vbi_bcm_info */ |
| vbi_bcm_info[cpcbID].DmaLen = 0; |
| } |
| |
| static void start_vde_bcm_transaction(int cpcbID) |
| { |
| #if (BERLIN_CHIP_VERSION >= BERLIN_BG2) |
| unsigned int bcm_sched_cmd[2]; |
| |
| if (vde_bcm_info[cpcbID].DmaLen) { |
| dhub_channel_generate_cmd(&(VPP_dhubHandle.dhub), |
| avioDhubChMap_vpp_BCM_R, |
| (INT) vde_bcm_info[cpcbID].DmaAddr, |
| (INT) vde_bcm_info[cpcbID].DmaLen * 8, |
| 0, 0, 0, 1, bcm_sched_cmd); |
| while (!BCM_SCHED_PushCmd(BCM_SCHED_Q12, bcm_sched_cmd, NULL)) { |
| vde_bcm_cmd_fullcnt++; |
| } |
| } |
| #else |
| UINT32 cnt; |
| UINT32 *ptr; |
| |
| ptr = (UINT32 *) vde_bcm_info[cpcbID].DmaAddr; |
| for (cnt = 0; cnt < vde_bcm_info[cpcbID].DmaLen; cnt++) { |
| dhub_channel_write_cmd(&(VPP_dhubHandle.dhub), |
| avioDhubChMap_vpp_BCM_R, (INT) * ptr, |
| (INT) * (ptr + 1), 0, 0, 0, 1, 0, 0); |
| ptr += 2; |
| } |
| #endif |
| /* invalid vde_bcm_info */ |
| vde_bcm_info[cpcbID].DmaLen = 0; |
| } |
| |
| static void start_vbi_dma_transaction(int cpcbID) |
| { |
| UINT32 cnt; |
| UINT32 *ptr; |
| |
| ptr = (UINT32 *) dma_info[cpcbID].DmaAddr; |
| for (cnt = 0; cnt < dma_info[cpcbID].DmaLen; cnt++) { |
| *((volatile int *)*(ptr + 1)) = *ptr; |
| ptr += 2; |
| } |
| /* invalid dma_info */ |
| dma_info[cpcbID].DmaLen = 0; |
| } |
| |
| static void send_bcm_sche_cmd(int q_id) |
| { |
| if ((bcm_sche_cmd[q_id][0] !=0) && (bcm_sche_cmd[q_id][1] !=0)) |
| BCM_SCHED_PushCmd(q_id, bcm_sche_cmd[q_id], NULL); |
| } |
| |
| static void pe_ma_do_tasklet(unsigned long unused) |
| { |
| MV_CC_MSG_t msg = { 0, }; |
| |
| msg.m_MsgID = 1 << avioDhubChMap_ag_MA0_R; |
| MV_CC_MsgQ_PostMsgByID(PE_MODULE_MSG_ID_AUD, &msg); |
| |
| } |
| |
| static void pe_sa_do_tasklet(unsigned long unused) |
| { |
| MV_CC_MSG_t msg = { 0, }; |
| |
| #if (BERLIN_CHIP_VERSION != BERLIN_BG2CD_A0 && BERLIN_CHIP_VERSION != BERLIN_BG2CDP) |
| msg.m_MsgID = 1 << avioDhubChMap_ag_SA_R; |
| MV_CC_MsgQ_PostMsgByID(PE_MODULE_MSG_ID_AUD, &msg); |
| #endif /* (BERLIN_CHIP_VERSION != BERLIN_BG2CD_A0) */ |
| } |
| |
| static void pe_spdif_do_tasklet(unsigned long unused) |
| { |
| MV_CC_MSG_t msg = { 0, }; |
| |
| #if (BERLIN_CHIP_VERSION != BERLIN_BG2CD_A0 && BERLIN_CHIP_VERSION != BERLIN_BG2CDP) |
| msg.m_MsgID = 1 << avioDhubChMap_ag_SPDIF_R; |
| MV_CC_MsgQ_PostMsgByID(PE_MODULE_MSG_ID_AUD, &msg); |
| #endif /* (BERLIN_CHIP_VERSION != BERLIN_BG2CD_A0) */ |
| } |
| |
| static void pe_aip_do_tasklet(unsigned long unused) |
| { |
| #if (BERLIN_CHIP_VERSION != BERLIN_BG2CDP) |
| |
| MV_CC_MSG_t msg = { 0, }; |
| #if (BERLIN_CHIP_VERSION >= BERLIN_BG2_A0) |
| msg.m_MsgID = 1 << avioDhubChMap_vip_MIC0_W; |
| #else |
| msg.m_MsgID = 1 << avioDhubChMap_ag_MIC_W; |
| #endif |
| MV_CC_MsgQ_PostMsgByID(PE_MODULE_MSG_ID_AIP, &msg); |
| #endif /* (BERLIN_CHIP_VERSION != BERLIN_BG2CDP) */ |
| } |
| |
| static void pe_hdmi_do_tasklet(unsigned long unused) |
| { |
| MV_CC_MSG_t msg = { 0, }; |
| |
| if(!disable_hdmi_int_msg) |
| { |
| msg.m_MsgID = 1 << avioDhubChMap_vpp_HDMI_R; |
| MV_CC_MsgQ_PostMsgByID(PE_MODULE_MSG_ID_AUD, &msg); |
| } |
| } |
| |
| static void pe_app_do_tasklet(unsigned long unused) |
| { |
| MV_CC_MSG_t msg = { 0, }; |
| |
| #if (BERLIN_CHIP_VERSION >= BERLIN_BG2) |
| msg.m_MsgID = 1 << avioDhubSemMap_ag_app_intr2; |
| #else |
| msg.m_MsgID = 1 << avioDhubChMap_ag_APPDAT_W; |
| #endif |
| MV_CC_MsgQ_PostMsgByID(PE_MODULE_MSG_ID_AUD, &msg); |
| } |
| |
| static void pe_zsp_do_tasklet(unsigned long unused) |
| { |
| MV_CC_MSG_t msg = { 0, }; |
| |
| msg.m_MsgID = 1 << ADSP_ZSPINT2Soc_IRQ0; |
| MV_CC_MsgQ_PostMsgByID(PE_MODULE_MSG_ID_ZSP, &msg); |
| } |
| |
| static void pe_pg_dhub_done_tasklet(unsigned long unused) |
| { |
| MV_CC_MSG_t msg = { 0, }; |
| |
| #if (BERLIN_CHIP_VERSION != BERLIN_BG2CD_A0 && BERLIN_CHIP_VERSION != BERLIN_BG2CDP) |
| msg.m_MsgID = 1 << avioDhubChMap_ag_PG_ENG_W; |
| MV_CC_MsgQ_PostMsgByID(PE_MODULE_MSG_ID_RLE, &msg); |
| #endif /* (BERLIN_CHIP_VERSION != BERLIN_BG2CD_A0) */ |
| } |
| |
| static void pe_rle_do_err_tasklet(unsigned long unused) |
| { |
| MV_CC_MSG_t msg = { 0, }; |
| #if (BERLIN_CHIP_VERSION != BERLIN_BG2CDP) |
| msg.m_MsgID = 1 << avioDhubSemMap_ag_spu_intr0; |
| MV_CC_MsgQ_PostMsgByID(PE_MODULE_MSG_ID_RLE, &msg); |
| #endif /* (BERLIN_CHIP_VERSION != BERLIN_BG2CDP) */ |
| } |
| |
| static void pe_rle_do_done_tasklet(unsigned long unused) |
| { |
| MV_CC_MSG_t msg = { 0, }; |
| |
| #if (BERLIN_CHIP_VERSION != BERLIN_BG2CDP) |
| msg.m_MsgID = 1 << avioDhubSemMap_ag_spu_intr1; |
| MV_CC_MsgQ_PostMsgByID(PE_MODULE_MSG_ID_RLE, &msg); |
| #endif /* (BERLIN_CHIP_VERSION != BERLIN_BG2CDP) */ |
| } |
| |
| static irqreturn_t pe_devices_vpp_cec_isr(int irq, void *dev_id) |
| { |
| UINT16 value = 0; |
| UINT16 reg = 0; |
| INT intr; |
| INT val; |
| INT i; |
| INT dptr_len = 0; |
| HRESULT ret = S_OK; |
| //printk("cec intr recvd\n"); |
| #if (BERLIN_CHIP_VERSION < BERLIN_BG2_A0) |
| GA_REG_WORD32_READ(SM_APB_GPIO0_BASE + APB_GPIO_INTSTATUS, &val); |
| if (val & 0x10) // check gpio status for cec intr |
| { |
| #endif |
| #if CONFIG_VPP_IOCTL_MSG |
| GA_REG_WORD32_READ(0xf7e82C00 + 0x04 + 7 * 0x14, |
| &vpp_intr_timestamp); |
| vpp_intr_timestamp = DEBUG_TIMER_VALUE - vpp_intr_timestamp; |
| #endif |
| |
| // Read CEC status register |
| GA_REG_BYTE_READ(SOC_SM_CEC_BASE + |
| (CEC_INTR_STATUS0_REG_ADDR << 2), &value); |
| reg = (UINT16) value; |
| GA_REG_BYTE_READ(SOC_SM_CEC_BASE + |
| (CEC_INTR_STATUS1_REG_ADDR << 2), &value); |
| reg |= ((UINT16) value << 8); |
| // Clear CEC interrupt |
| if (reg & BE_CEC_INTR_TX_FAIL) { |
| intr = BE_CEC_INTR_TX_FAIL; |
| #if (BERLIN_CHIP_VERSION >= BERLIN_BG2) |
| GA_REG_BYTE_WRITE(SOC_SM_CEC_BASE + |
| (CEC_RDY_ADDR << 2), |
| 0x0); |
| #endif |
| GA_REG_BYTE_READ(SOC_SM_CEC_BASE + |
| (CEC_INTR_ENABLE0_REG_ADDR << 2), |
| &value); |
| value &= ~(intr & 0x00ff); |
| GA_REG_BYTE_WRITE(SOC_SM_CEC_BASE + |
| (CEC_INTR_ENABLE0_REG_ADDR << 2), |
| value); |
| //printk("cec intr recvd tx failed\n"); |
| } |
| if (reg & BE_CEC_INTR_TX_COMPLETE) { |
| intr = BE_CEC_INTR_TX_COMPLETE; |
| GA_REG_BYTE_READ(SOC_SM_CEC_BASE + |
| (CEC_INTR_ENABLE0_REG_ADDR << 2), |
| &value); |
| value &= ~(intr & 0x00ff); |
| GA_REG_BYTE_WRITE(SOC_SM_CEC_BASE + |
| (CEC_INTR_ENABLE0_REG_ADDR << 2), |
| value); |
| //printk("cec intr recvd tx complete \n"); |
| } |
| if (reg & BE_CEC_INTR_RX_FAIL) { |
| intr = BE_CEC_INTR_RX_FAIL; |
| GA_REG_BYTE_READ(SOC_SM_CEC_BASE + |
| (CEC_INTR_ENABLE0_REG_ADDR << 2), |
| &value); |
| value &= ~(intr & 0x00ff); |
| GA_REG_BYTE_WRITE(SOC_SM_CEC_BASE + |
| (CEC_INTR_ENABLE0_REG_ADDR << 2), |
| value); |
| } |
| if (reg & BE_CEC_INTR_RX_COMPLETE) { |
| intr = BE_CEC_INTR_RX_COMPLETE; |
| GA_REG_BYTE_READ(SOC_SM_CEC_BASE + |
| (CEC_INTR_ENABLE0_REG_ADDR << 2), |
| &value); |
| value &= ~(intr & 0x00ff); |
| GA_REG_BYTE_WRITE(SOC_SM_CEC_BASE + |
| (CEC_INTR_ENABLE0_REG_ADDR << 2), |
| value); |
| // read cec mesg from rx buffer |
| GA_REG_BYTE_READ(SOC_SM_CEC_BASE + |
| (CEC_RX_FIFO_DPTR << 2), |
| &dptr_len); |
| rx_buf.len = dptr_len; |
| for (i = 0; i < dptr_len; i++) { |
| GA_REG_BYTE_READ(SOC_SM_CEC_BASE + |
| (CEC_RX_BUF_READ_REG_ADDR << 2), |
| &rx_buf.buf[i]); |
| GA_REG_BYTE_WRITE(SOC_SM_CEC_BASE + |
| (CEC_TOGGLE_FOR_READ_REG_ADDR << 2), |
| 0x01); |
| } |
| GA_REG_BYTE_WRITE(SOC_SM_CEC_BASE + |
| (CEC_RX_RDY_ADDR << 2), |
| 0x00); |
| GA_REG_BYTE_WRITE(SOC_SM_CEC_BASE + |
| (CEC_RX_RDY_ADDR << 2), |
| 0x01); |
| GA_REG_BYTE_READ(SOC_SM_CEC_BASE + |
| (CEC_INTR_ENABLE0_REG_ADDR << 2), |
| &value); |
| value |= (intr & 0x00ff); |
| GA_REG_BYTE_WRITE(SOC_SM_CEC_BASE + |
| (CEC_INTR_ENABLE0_REG_ADDR << 2), |
| value); |
| } |
| #if (BERLIN_CHIP_VERSION < BERLIN_BG2_A0) |
| //Clear GPIO interrupt |
| GA_REG_WORD32_READ(SM_APB_GPIO0_BASE + APB_GPIO_PORTA_EOI, &val); // will add macro soon |
| val |= 0x10; // clear 4 bit |
| GA_REG_WORD32_WRITE(SM_APB_GPIO0_BASE + APB_GPIO_PORTA_EOI, val); // will add macro soon |
| #endif |
| // schedule tasklet with intr status as param |
| #if CONFIG_VPP_IOCTL_MSG |
| #if CONFIG_VPP_ISR_MSGQ |
| { |
| MV_CC_MSG_t msg = |
| { VPP_CC_MSG_TYPE_CEC, reg, vpp_intr_timestamp }; |
| spin_lock(&msgQ_spinlock); |
| ret = PEMsgQ_Add(&hPEMsgQ, &msg); |
| spin_unlock(&msgQ_spinlock); |
| if (ret != S_OK) |
| { |
| return IRQ_HANDLED; |
| } |
| |
| } |
| #else |
| vpp_instat = reg; |
| #endif |
| up(&vpp_sem); |
| #else |
| pe_vpp_cec_tasklet.data = reg; // bug fix puneet |
| tasklet_hi_schedule(&pe_vpp_cec_tasklet); |
| #endif |
| |
| //pe_vpp_cec_tasklet.data = reg; |
| //tasklet_hi_schedule(&pe_vpp_cec_tasklet); |
| return IRQ_HANDLED; |
| #if (BERLIN_CHIP_VERSION < BERLIN_BG2_A0) |
| } |
| return IRQ_NONE; |
| #endif |
| } |
| |
| #ifdef CONFIG_IRQ_LATENCY_PROFILE |
| |
| typedef struct pe_irq_profiler { |
| unsigned long long vppCPCB0_intr_curr; |
| unsigned long long vppCPCB0_intr_last; |
| unsigned long long vpp_task_sched_last; |
| unsigned long long vpp_isr_start; |
| |
| unsigned long long vpp_isr_end; |
| unsigned long vpp_isr_time_last; |
| |
| unsigned long vpp_isr_time_max; |
| unsigned long vpp_isr_instat_max; |
| |
| INT vpp_isr_last_instat; |
| |
| } pe_irq_profiler_t; |
| |
| static pe_irq_profiler_t pe_irq_profiler; |
| |
| #endif |
| |
| static atomic_t vpp_isr_msg_err_cnt = ATOMIC_INIT(0); |
| |
| #define HPD_DEBOUNCE |
| |
| #ifdef HPD_DEBOUNCE |
| #define HPD_DELAY_CNT (6) |
| static int hpd_debounce_delaycnt = 0; |
| #endif |
| |
| static irqreturn_t pe_devices_vpp_isr(int irq, void *dev_id) |
| { |
| INT instat; |
| HDL_semaphore *pSemHandle; |
| INT vpp_intr = 0; |
| INT instat_used = 0; |
| HRESULT ret = S_OK; |
| /* disable interrupt */ |
| #if CONFIG_VPP_IOCTL_MSG |
| GA_REG_WORD32_READ(0xf7e82C00 + 0x04 + 7 * 0x14, &vpp_intr_timestamp); |
| vpp_intr_timestamp = DEBUG_TIMER_VALUE - vpp_intr_timestamp; |
| #endif |
| |
| #ifdef CONFIG_IRQ_LATENCY_PROFILE |
| pe_irq_profiler.vpp_isr_start = cpu_clock(smp_processor_id()); |
| #endif |
| |
| /* VPP interrupt handling */ |
| pSemHandle = dhub_semaphore(&VPP_dhubHandle.dhub); |
| instat = semaphore_chk_full(pSemHandle, -1); |
| |
| if (bTST(instat, avioDhubSemMap_vpp_vppCPCB0_intr) |
| #ifdef NEW_ISR |
| && |
| (vpp_intr_status[avioDhubSemMap_vpp_vppCPCB0_intr]) |
| #endif |
| ) { |
| #ifdef NEW_ISR |
| vpp_intr |= bSETMASK(avioDhubSemMap_vpp_vppCPCB0_intr); |
| #else |
| vpp_intr = 1; |
| #endif |
| bSET(instat_used, avioDhubSemMap_vpp_vppCPCB0_intr); |
| |
| #ifdef CONFIG_IRQ_LATENCY_PROFILE |
| pe_irq_profiler.vppCPCB0_intr_curr = |
| cpu_clock(smp_processor_id()); |
| #endif |
| /* CPCB-0 interrupt */ |
| vpp_cpcb0_vbi_int_cnt++; |
| /* clear interrupt */ |
| semaphore_pop(pSemHandle, avioDhubSemMap_vpp_vppCPCB0_intr, 1); |
| semaphore_clr_full(pSemHandle, |
| avioDhubSemMap_vpp_vppCPCB0_intr); |
| |
| /* Clear the bits for CPCB0 VDE interrupt */ |
| if (bTST(instat, avioDhubSemMap_vpp_vppOUT4_intr)) { |
| semaphore_pop(pSemHandle, |
| avioDhubSemMap_vpp_vppOUT4_intr, 1); |
| semaphore_clr_full(pSemHandle, |
| avioDhubSemMap_vpp_vppOUT4_intr); |
| bCLR(instat, avioDhubSemMap_vpp_vppOUT4_intr); |
| } |
| |
| start_vbi_dma_transaction(0); |
| start_vbi_bcm_transaction(0); |
| send_bcm_sche_cmd(BCM_SCHED_Q0); |
| } |
| |
| if (bTST(instat, avioDhubSemMap_vpp_vppCPCB1_intr) |
| #ifdef NEW_ISR |
| && |
| (vpp_intr_status[avioDhubSemMap_vpp_vppCPCB1_intr]) |
| #endif |
| ) { |
| #ifdef NEW_ISR |
| vpp_intr |= bSETMASK(avioDhubSemMap_vpp_vppCPCB1_intr); |
| #else |
| vpp_intr = 1; |
| #endif |
| bSET(instat_used, avioDhubSemMap_vpp_vppCPCB1_intr); |
| |
| /* CPCB-1 interrupt */ |
| /* clear interrupt */ |
| semaphore_pop(pSemHandle, avioDhubSemMap_vpp_vppCPCB1_intr, 1); |
| semaphore_clr_full(pSemHandle, |
| avioDhubSemMap_vpp_vppCPCB1_intr); |
| |
| /* Clear the bits for CPCB1 VDE interrupt */ |
| if (bTST(instat, avioDhubSemMap_vpp_vppOUT5_intr)) { |
| semaphore_pop(pSemHandle, |
| avioDhubSemMap_vpp_vppOUT5_intr, 1); |
| semaphore_clr_full(pSemHandle, |
| avioDhubSemMap_vpp_vppOUT5_intr); |
| bCLR(instat, avioDhubSemMap_vpp_vppOUT5_intr); |
| } |
| start_vbi_dma_transaction(1); |
| start_vbi_bcm_transaction(1); |
| send_bcm_sche_cmd(BCM_SCHED_Q1); |
| } |
| |
| |
| if (bTST(instat, avioDhubSemMap_vpp_vppCPCB2_intr) |
| #ifdef NEW_ISR |
| && |
| (vpp_intr_status[avioDhubSemMap_vpp_vppCPCB2_intr]) |
| #endif |
| ) { |
| #ifdef NEW_ISR |
| vpp_intr |= bSETMASK(avioDhubSemMap_vpp_vppCPCB2_intr); |
| #else |
| vpp_intr = 1; |
| #endif |
| bSET(instat_used, avioDhubSemMap_vpp_vppCPCB2_intr); |
| |
| /* CPCB-2 interrupt */ |
| /* clear interrupt */ |
| semaphore_pop(pSemHandle, avioDhubSemMap_vpp_vppCPCB2_intr, 1); |
| semaphore_clr_full(pSemHandle, |
| avioDhubSemMap_vpp_vppCPCB2_intr); |
| |
| /* Clear the bits for CPCB2 VDE interrupt */ |
| if (bTST(instat, avioDhubSemMap_vpp_vppOUT6_intr)) { |
| semaphore_pop(pSemHandle, |
| avioDhubSemMap_vpp_vppOUT6_intr, 1); |
| semaphore_clr_full(pSemHandle, |
| avioDhubSemMap_vpp_vppOUT6_intr); |
| bCLR(instat, avioDhubSemMap_vpp_vppOUT6_intr); |
| } |
| |
| start_vbi_dma_transaction(2); |
| start_vbi_bcm_transaction(2); |
| send_bcm_sche_cmd(BCM_SCHED_Q2); |
| } |
| |
| if (bTST(instat, avioDhubSemMap_vpp_vppOUT4_intr) |
| #ifdef NEW_ISR |
| && |
| (vpp_intr_status[avioDhubSemMap_vpp_vppOUT4_intr]) |
| #endif |
| ) { |
| #ifdef NEW_ISR |
| vpp_intr |= bSETMASK(avioDhubSemMap_vpp_vppOUT4_intr); |
| #else |
| vpp_intr = 1; |
| #endif |
| bSET(instat_used, avioDhubSemMap_vpp_vppOUT4_intr); |
| |
| /* CPCB-0 VDE interrupt */ |
| /* clear interrupt */ |
| semaphore_pop(pSemHandle, avioDhubSemMap_vpp_vppOUT4_intr, 1); |
| semaphore_clr_full(pSemHandle, avioDhubSemMap_vpp_vppOUT4_intr); |
| |
| start_vde_bcm_transaction(0); |
| send_bcm_sche_cmd(BCM_SCHED_Q3); |
| } |
| |
| if (bTST(instat, avioDhubSemMap_vpp_vppOUT5_intr) |
| #ifdef NEW_ISR |
| && |
| (vpp_intr_status[avioDhubSemMap_vpp_vppOUT5_intr]) |
| #endif |
| ) { |
| #ifdef NEW_ISR |
| vpp_intr |= bSETMASK(avioDhubSemMap_vpp_vppOUT5_intr); |
| #else |
| vpp_intr = 1; |
| #endif |
| bSET(instat_used, avioDhubSemMap_vpp_vppOUT5_intr); |
| |
| /* CPCB-1 VDE interrupt */ |
| /* clear interrupt */ |
| semaphore_pop(pSemHandle, avioDhubSemMap_vpp_vppOUT5_intr, 1); |
| semaphore_clr_full(pSemHandle, avioDhubSemMap_vpp_vppOUT5_intr); |
| |
| start_vde_bcm_transaction(1); |
| send_bcm_sche_cmd(BCM_SCHED_Q4); |
| } |
| |
| if (bTST(instat, avioDhubSemMap_vpp_vppOUT6_intr) |
| #ifdef NEW_ISR |
| && |
| (vpp_intr_status[avioDhubSemMap_vpp_vppOUT6_intr]) |
| #endif |
| ) { |
| #ifdef NEW_ISR |
| vpp_intr |= bSETMASK(avioDhubSemMap_vpp_vppOUT6_intr); |
| #else |
| vpp_intr = 1; |
| #endif |
| bSET(instat_used, avioDhubSemMap_vpp_vppOUT6_intr); |
| |
| /* CPCB-2 VDE interrupt */ |
| /* clear interrupt */ |
| semaphore_pop(pSemHandle, avioDhubSemMap_vpp_vppOUT6_intr, 1); |
| semaphore_clr_full(pSemHandle, avioDhubSemMap_vpp_vppOUT6_intr); |
| |
| start_vde_bcm_transaction(2); |
| send_bcm_sche_cmd(BCM_SCHED_Q5); |
| } |
| |
| if (bTST(instat, avioDhubSemMap_vpp_vppOUT3_intr) |
| #ifdef NEW_ISR |
| && |
| (vpp_intr_status[avioDhubSemMap_vpp_vppOUT3_intr]) |
| #endif |
| ) { |
| #ifdef HPD_DEBOUNCE |
| hpd_debounce_delaycnt = HPD_DELAY_CNT; |
| bCLR(instat, avioDhubSemMap_vpp_vppOUT3_intr); |
| #else |
| #ifdef NEW_ISR |
| vpp_intr |= bSETMASK(avioDhubSemMap_vpp_vppOUT3_intr); |
| #else |
| vpp_intr = 1; |
| #endif |
| #endif |
| |
| bSET(instat_used, avioDhubSemMap_vpp_vppOUT3_intr); |
| |
| /* VOUT3 interrupt */ |
| /* clear interrupt */ |
| semaphore_pop(pSemHandle, avioDhubSemMap_vpp_vppOUT3_intr, 1); |
| semaphore_clr_full(pSemHandle, avioDhubSemMap_vpp_vppOUT3_intr); |
| #ifdef HPD_DEBOUNCE |
| // disable interrupt |
| semaphore_intr_enable(pSemHandle, avioDhubSemMap_vpp_vppOUT3_intr, |
| 0/*empty*/, 0/*full*/, 0/*almost empty*/, 0/*almost full*/, 0/*cpu id*/); |
| #endif |
| } |
| |
| #if (BERLIN_CHIP_VERSION != BERLIN_BG2CD_A0 && BERLIN_CHIP_VERSION != BERLIN_BG2CDP) |
| if (bTST(instat, avioDhubSemMap_vpp_CH10_intr) |
| |
| #else /* (BERLIN_CHIP_VERSION == BERLIN_BG2CD_A0) */ |
| if (bTST(instat, avioDhubSemMap_vpp_CH7_intr) |
| #endif /* (BERLIN_CHIP_VERSION != BERLIN_BG2CD_A0) */ |
| #ifdef NEW_ISR |
| && |
| #if (BERLIN_CHIP_VERSION != BERLIN_BG2CD_A0 && BERLIN_CHIP_VERSION != BERLIN_BG2CDP) |
| (vpp_intr_status[avioDhubSemMap_vpp_CH10_intr]) |
| #else /* (BERLIN_CHIP_VERSION == BERLIN_BG2CD_A0) */ |
| (vpp_intr_status[avioDhubSemMap_vpp_CH7_intr]) |
| #endif /* (BERLIN_CHIP_VERSION != BERLIN_BG2CD_A0) */ |
| #endif |
| ) { |
| #if (BERLIN_CHIP_VERSION != BERLIN_BG2CD_A0 && BERLIN_CHIP_VERSION != BERLIN_BG2CDP) |
| bSET(instat_used, avioDhubSemMap_vpp_CH10_intr); |
| #else /* (BERLIN_CHIP_VERSION == BERLIN_BG2CD_A0) */ |
| bSET(instat_used, avioDhubSemMap_vpp_CH7_intr); |
| #endif /* (BERLIN_CHIP_VERSION != BERLIN_BG2CD_A0) */ |
| /* HDMI audio interrupt */ |
| vpp_hdmi_audio_int_cnt++; |
| /* clear interrupt */ |
| #if (BERLIN_CHIP_VERSION != BERLIN_BG2CD_A0 && BERLIN_CHIP_VERSION != BERLIN_BG2CDP) |
| semaphore_pop(pSemHandle, avioDhubSemMap_vpp_CH10_intr, 1); |
| semaphore_clr_full(pSemHandle, avioDhubSemMap_vpp_CH10_intr); |
| #else /* (BERLIN_CHIP_VERSION == BERLIN_BG2CD_A0) */ |
| semaphore_pop(pSemHandle, avioDhubSemMap_vpp_CH7_intr, 1); |
| semaphore_clr_full(pSemHandle, avioDhubSemMap_vpp_CH7_intr); |
| #endif /* (BERLIN_CHIP_VERSION != BERLIN_BG2CD_A0) */ |
| aout_resume_cmd(HDMI_PATH); |
| tasklet_hi_schedule(&pe_hdmi_tasklet); |
| #if (BERLIN_CHIP_VERSION != BERLIN_BG2CD_A0 && BERLIN_CHIP_VERSION != BERLIN_BG2CDP) |
| bCLR(instat, avioDhubSemMap_vpp_CH10_intr); |
| #else /* (BERLIN_CHIP_VERSION == BERLIN_BG2CD_A0) */ |
| bCLR(instat, avioDhubSemMap_vpp_CH7_intr); |
| #endif /* (BERLIN_CHIP_VERSION != BERLIN_BG2CD_A0) */ |
| } |
| |
| if (bTST(instat, avioDhubSemMap_vpp_vppOUT0_intr) |
| #ifdef NEW_ISR |
| && |
| (vpp_intr_status[avioDhubSemMap_vpp_vppOUT0_intr]) |
| #endif |
| ) { |
| #ifdef NEW_ISR |
| vpp_intr |= bSETMASK(avioDhubSemMap_vpp_vppOUT0_intr); |
| #else |
| vpp_intr = 1; |
| #endif |
| bSET(instat_used, avioDhubSemMap_vpp_vppOUT0_intr); |
| |
| /* VOUT0 interrupt */ |
| /* clear interrupt */ |
| semaphore_pop(pSemHandle, avioDhubSemMap_vpp_vppOUT0_intr, 1); |
| semaphore_clr_full(pSemHandle, avioDhubSemMap_vpp_vppOUT0_intr); |
| } |
| |
| if (bTST(instat, avioDhubSemMap_vpp_vppOUT1_intr) |
| #ifdef NEW_ISR |
| && |
| (vpp_intr_status[avioDhubSemMap_vpp_vppOUT1_intr]) |
| #endif |
| ) { |
| #ifdef NEW_ISR |
| vpp_intr |= bSETMASK(avioDhubSemMap_vpp_vppOUT1_intr); |
| #else |
| vpp_intr = 1; |
| #endif |
| bSET(instat_used, avioDhubSemMap_vpp_vppOUT1_intr); |
| |
| /* VOUT1 interrupt */ |
| /* clear interrupt */ |
| semaphore_pop(pSemHandle, avioDhubSemMap_vpp_vppOUT1_intr, 1); |
| semaphore_clr_full(pSemHandle, avioDhubSemMap_vpp_vppOUT1_intr); |
| } |
| #ifdef VPP_DBG |
| // pe_trace("ISR instat:%x\n", instat); |
| #endif |
| |
| if (vpp_intr) { |
| #ifdef HPD_DEBOUNCE |
| if(hpd_debounce_delaycnt) |
| { |
| if (bTST(instat, avioDhubSemMap_vpp_vppCPCB0_intr)) |
| { // use display interrupt as debounce counter. |
| hpd_debounce_delaycnt--; |
| } |
| if(hpd_debounce_delaycnt == 0) |
| { |
| semaphore_clr_full(pSemHandle, avioDhubSemMap_vpp_vppOUT3_intr); |
| // enable interrupt |
| semaphore_intr_enable(pSemHandle, avioDhubSemMap_vpp_vppOUT3_intr, |
| 0/*empty*/, 1/*full*/, 0/*almost empty*/, 0/*almost full*/, 0/*cpu id*/); |
| #ifdef NEW_ISR |
| vpp_intr |= bSETMASK(avioDhubSemMap_vpp_vppOUT3_intr); |
| #else |
| vpp_intr = 1; |
| #endif |
| bSET(instat, avioDhubSemMap_vpp_vppOUT3_intr); |
| } |
| } |
| #endif |
| #if CONFIG_VPP_IOCTL_MSG |
| |
| #if CONFIG_VPP_ISR_MSGQ |
| MV_CC_MSG_t msg = |
| { VPP_CC_MSG_TYPE_VPP, |
| #ifdef NEW_ISR |
| vpp_intr, |
| #else |
| instat, |
| #endif |
| vpp_intr_timestamp }; |
| spin_lock(&msgQ_spinlock); |
| ret = PEMsgQ_Add(&hPEMsgQ, &msg); |
| spin_unlock(&msgQ_spinlock); |
| |
| if(ret != S_OK) { |
| if (!atomic_read(&vpp_isr_msg_err_cnt)) { |
| pe_error(" E/[vpp isr] MsgQ full, task deadlock or segment fault\n"); |
| } |
| atomic_inc(&vpp_isr_msg_err_cnt); |
| return IRQ_HANDLED; |
| } |
| |
| #else |
| vpp_instat = instat; |
| #endif |
| up(&vpp_sem); |
| #else |
| pe_vpp_tasklet.data = instat; |
| tasklet_hi_schedule(&pe_vpp_tasklet); |
| #endif |
| |
| #ifdef CONFIG_IRQ_LATENCY_PROFILE |
| |
| pe_irq_profiler.vpp_isr_end = cpu_clock(smp_processor_id()); |
| unsigned long isr_time = |
| pe_irq_profiler.vpp_isr_end - pe_irq_profiler.vpp_isr_start; |
| int32_t jitter = 0; |
| isr_time /= 1000; |
| |
| if (bTST(instat, avioDhubSemMap_vpp_vppCPCB0_intr)) { |
| if (pe_irq_profiler.vppCPCB0_intr_last) { |
| jitter = |
| (int64_t) pe_irq_profiler. |
| vppCPCB0_intr_curr - |
| (int64_t) pe_irq_profiler. |
| vppCPCB0_intr_last; |
| |
| //nanosec_rem = do_div(interval, 1000000000); |
| // transform to us unit |
| jitter /= 1000; |
| jitter -= 16667; |
| } |
| pe_irq_profiler.vppCPCB0_intr_last = |
| pe_irq_profiler.vppCPCB0_intr_curr; |
| } |
| |
| if ((jitter > 670) || (jitter < -670) || (isr_time > 1000)) { |
| pe_trace |
| (" W/[vpp isr] jitter:%6d > +-670 us, instat:0x%x last_instat:0x%0x max_instat:0x%0x, isr_time:%d us last:%d max:%d \n", |
| jitter, instat_used, |
| pe_irq_profiler.vpp_isr_last_instat, |
| pe_irq_profiler.vpp_isr_instat_max, isr_time, |
| pe_irq_profiler.vpp_isr_time_last, |
| pe_irq_profiler.vpp_isr_time_max); |
| } |
| |
| pe_irq_profiler.vpp_isr_last_instat = instat_used; |
| pe_irq_profiler.vpp_isr_time_last = isr_time; |
| |
| if (isr_time > pe_irq_profiler.vpp_isr_time_max) { |
| pe_irq_profiler.vpp_isr_time_max = isr_time; |
| pe_irq_profiler.vpp_isr_instat_max = instat_used; |
| } |
| #endif |
| |
| #if CONFIG_VPP_ISR_MSGQ |
| /* |
| INT fullness = PEMsgQ_Fullness(&hPEMsgQ); |
| |
| if ( (!atomic_read(&vpp_isr_msg_err_cnt)) && fullness > 1) |
| pe_trace(" W/[vpp isr] message queued:%d, task lag\n", fullness); |
| */ |
| #endif |
| } |
| #ifdef CONFIG_IRQ_LATENCY_PROFILE |
| else { |
| pe_irq_profiler.vpp_isr_end = cpu_clock(smp_processor_id()); |
| unsigned long isr_time = |
| pe_irq_profiler.vpp_isr_end - pe_irq_profiler.vpp_isr_start; |
| isr_time /= 1000; |
| |
| if (isr_time > 1000) { |
| pe_trace("###isr_time:%d us instat:%x last:%x\n", |
| isr_time, vpp_intr, instat, |
| pe_irq_profiler.vpp_isr_last_instat); |
| } |
| |
| pe_irq_profiler.vpp_isr_time_last = isr_time; |
| } |
| #endif |
| |
| return IRQ_HANDLED; |
| } |
| |
| #if (BERLIN_CHIP_VERSION >= BERLIN_BG2_A0) |
| static void start_vip_vbi_bcm(void) |
| { |
| unsigned int bcm_sched_cmd[2]; |
| |
| if (vip_vbi_info.DmaLen) { |
| dhub_channel_generate_cmd(&(VPP_dhubHandle.dhub), |
| avioDhubChMap_vpp_BCM_R, |
| (INT) vip_vbi_info.DmaAddr, |
| (INT) vip_vbi_info.DmaLen * 8, 0, 0, |
| 0, 1, bcm_sched_cmd); |
| while (!BCM_SCHED_PushCmd(BCM_SCHED_Q12, bcm_sched_cmd, NULL)) ; |
| } |
| |
| /* invalid vbi_bcm_info */ |
| vip_vbi_info.DmaLen = 0; |
| } |
| #endif |
| |
| #if (BERLIN_CHIP_VERSION >= BERLIN_BG2) |
| static void start_vip_dvi_bcm(void) |
| { |
| #if (BERLIN_CHIP_VERSION >= BERLIN_BG2) |
| unsigned int bcm_sched_cmd[2]; |
| |
| if (vip_dma_info.DmaLen) { |
| dhub_channel_generate_cmd(&(VPP_dhubHandle.dhub), |
| avioDhubChMap_vpp_BCM_R, |
| (INT) vip_dma_info.DmaAddr, |
| (INT) vip_dma_info.DmaLen * 8, 0, 0, |
| 0, 1, bcm_sched_cmd); |
| while (!BCM_SCHED_PushCmd(BCM_SCHED_Q12, bcm_sched_cmd, NULL)) ; |
| } |
| #else |
| UINT32 cnt; |
| UINT32 *ptr; |
| |
| ptr = (UINT32 *) vip_dma_info.DmaAddr; |
| for (cnt = 0; cnt < vip_dma_info.DmaLen; cnt++) { |
| dhub_channel_write_cmd(&(VPP_dhubHandle.dhub), |
| avioDhubChMap_vpp_BCM_R, (INT) * ptr, |
| (INT) * (ptr + 1), 0, 0, 0, 1, 0, 0); |
| ptr += 2; |
| } |
| #endif |
| |
| /* invalid vbi_bcm_info */ |
| vip_dma_info.DmaLen = 0; |
| } |
| |
| static void start_vip_sd_wr_bcm(void) |
| { |
| #if (BERLIN_CHIP_VERSION >= BERLIN_BG2) |
| unsigned int bcm_sched_cmd[2]; |
| |
| if (vip_sd_wr_info.DmaLen) { |
| dhub_channel_generate_cmd(&(VPP_dhubHandle.dhub), |
| avioDhubChMap_vpp_BCM_R, |
| (INT) vip_sd_wr_info.DmaAddr, |
| (INT) vip_sd_wr_info.DmaLen * 8, 0, 0, |
| 0, 1, bcm_sched_cmd); |
| while (!BCM_SCHED_PushCmd(BCM_SCHED_Q12, bcm_sched_cmd, NULL)) ; |
| } |
| #else |
| UINT32 cnt; |
| UINT32 *ptr; |
| |
| ptr = (UINT32 *) vip_sd_wr_info.DmaAddr; |
| for (cnt = 0; cnt < vip_sd_wr_info.DmaLen; cnt++) { |
| dhub_channel_write_cmd(&(VPP_dhubHandle.dhub), |
| avioDhubChMap_vpp_BCM_R, (INT) * ptr, |
| (INT) * (ptr + 1), 0, 0, 0, 1, 0, 0); |
| ptr += 2; |
| } |
| #endif |
| |
| /* invalid vbi_bcm_info */ |
| vip_sd_wr_info.DmaLen = 0; |
| } |
| |
| static void start_vip_sd_rd_bcm(void) |
| { |
| #if (BERLIN_CHIP_VERSION >= BERLIN_BG2) |
| unsigned int bcm_sched_cmd[2]; |
| |
| if (vip_sd_rd_info.DmaLen) { |
| dhub_channel_generate_cmd(&(VPP_dhubHandle.dhub), |
| avioDhubChMap_vpp_BCM_R, |
| (INT) vip_sd_rd_info.DmaAddr, |
| (INT) vip_sd_rd_info.DmaLen * 8, 0, 0, |
| 0, 1, bcm_sched_cmd); |
| while (!BCM_SCHED_PushCmd(BCM_SCHED_Q12, bcm_sched_cmd, NULL)) ; |
| } |
| #else |
| UINT32 cnt; |
| UINT32 *ptr; |
| |
| ptr = (UINT32 *) vip_sd_rd_info.DmaAddr; |
| for (cnt = 0; cnt < vip_sd_rd_info.DmaLen; cnt++) { |
| //FIXME: does this use Q12? |
| dhub_channel_write_cmd(&(VPP_dhubHandle.dhub), |
| avioDhubChMap_vpp_BCM_R, (INT) * ptr, |
| (INT) * (ptr + 1), 0, 0, 0, 1, 0, 0); |
| ptr += 2; |
| } |
| #endif |
| |
| /* invalid vbi_bcm_info */ |
| vip_sd_rd_info.DmaLen = 0; |
| } |
| |
| static irqreturn_t pe_devices_vip_isr(int irq, void *dev_id) |
| { |
| #if (BERLIN_CHIP_VERSION != BERLIN_BG2CDP) |
| INT instat; |
| HDL_semaphore *pSemHandle; |
| INT vip_intr = 0; |
| INT chanId; |
| |
| /* VIP interrupt handling */ |
| pSemHandle = dhub_semaphore(&VIP_dhubHandle.dhub); |
| instat = semaphore_chk_full(pSemHandle, -1); |
| |
| if (bTST(instat, avioDhubSemMap_vip_wre_event_intr) |
| #ifdef NEW_ISR |
| && |
| (vip_intr_status[avioDhubSemMap_vip_wre_event_intr]) |
| #endif |
| ) { |
| /* SD decoder write enable interrupt */ |
| semaphore_pop(pSemHandle, avioDhubSemMap_vip_wre_event_intr, 1); |
| semaphore_clr_full(pSemHandle, |
| avioDhubSemMap_vip_wre_event_intr); |
| |
| #ifdef NEW_ISR |
| vip_intr |= bSETMASK(avioDhubSemMap_vip_wre_event_intr); |
| #else |
| vip_intr = 1; |
| #endif |
| } |
| |
| if (bTST(instat, avioDhubSemMap_vip_dvi_vde_intr) |
| #ifdef NEW_ISR |
| && |
| (vip_intr_status[avioDhubSemMap_vip_dvi_vde_intr]) |
| #endif |
| ) { |
| /* DVI VDE interrupt */ |
| semaphore_pop(pSemHandle, avioDhubSemMap_vip_dvi_vde_intr, 1); |
| semaphore_clr_full(pSemHandle, avioDhubSemMap_vip_dvi_vde_intr); |
| |
| start_vip_dvi_bcm(); |
| #ifdef NEW_ISR |
| vip_intr |= bSETMASK(avioDhubSemMap_vip_dvi_vde_intr); |
| #else |
| vip_intr = 1; |
| #endif |
| } |
| #if (BERLIN_CHIP_VERSION >= BERLIN_BG2_A0 && BERLIN_CHIP_VERSION != BERLIN_BG2CDP) |
| if (bTST(instat, avioDhubSemMap_vip_vbi_vde_intr) |
| #ifdef NEW_ISR |
| && |
| (vip_intr_status[avioDhubSemMap_vip_vbi_vde_intr]) |
| #endif |
| ) { |
| /* VBI VDE interrupt */ |
| semaphore_pop(pSemHandle, avioDhubSemMap_vip_vbi_vde_intr, 1); |
| semaphore_clr_full(pSemHandle, avioDhubSemMap_vip_vbi_vde_intr); |
| |
| start_vip_vbi_bcm(); |
| #ifdef NEW_ISR |
| vip_intr |= bSETMASK(avioDhubSemMap_vip_vbi_vde_intr); |
| #else |
| vip_intr = 1; |
| #endif |
| } |
| |
| for (chanId = avioDhubChMap_vip_MIC0_W; |
| chanId <= avioDhubChMap_vip_MIC3_W; chanId++) { |
| if (bTST(instat, chanId)) { |
| semaphore_pop(pSemHandle, chanId, 1); |
| semaphore_clr_full(pSemHandle, chanId); |
| if (chanId == avioDhubChMap_vip_MIC0_W) { |
| aip_resume_cmd(); |
| tasklet_hi_schedule(&pe_aip_tasklet); |
| } |
| } |
| } |
| #endif |
| |
| if (vip_intr) { |
| #if CONFIG_VIP_IOCTL_MSG |
| #if CONFIG_VIP_ISR_MSGQ |
| MV_CC_MSG_t msg = |
| { /*VPP_CC_MSG_TYPE_VPP */ 0, |
| #ifdef NEW_ISR |
| vip_intr, |
| #else |
| instat, |
| #endif |
| vip_intr_timestamp }; |
| PEMsgQ_Add(&hPEVIPMsgQ, &msg); |
| #endif |
| up(&vip_sem); |
| #else |
| tasklet_hi_schedule(&pe_vip_tasklet); |
| #endif |
| } |
| |
| #endif /* (BERLIN_CHIP_VERSION != BERLIN_BG2CDP) */ |
| return IRQ_HANDLED; |
| } |
| #endif |
| |
| static irqreturn_t pe_devices_vdec_isr(int irq, void *dev_id) |
| { |
| /* disable interrupt */ |
| disable_irq_nosync(irq); |
| |
| #if CONFIG_VDEC_UNBLC_IRQ_FIX |
| vdec_int_cnt++; |
| #endif |
| |
| tasklet_hi_schedule(&pe_vdec_tasklet); |
| |
| return IRQ_HANDLED; |
| } |
| |
| static void *AoutFifoGetKernelRdDMAInfo(AOUT_PATH_CMD_FIFO *p_aout_cmd_fifo, |
| int pair) |
| { |
| void *pHandle; |
| pHandle = |
| &(p_aout_cmd_fifo-> |
| aout_dma_info[pair][p_aout_cmd_fifo->kernel_rd_offset]); |
| return pHandle; |
| } |
| |
| static void AoutFifoKernelRdUpdate(AOUT_PATH_CMD_FIFO *p_aout_cmd_fifo, |
| int adv) |
| { |
| p_aout_cmd_fifo->kernel_rd_offset += adv; |
| if (p_aout_cmd_fifo->kernel_rd_offset >= p_aout_cmd_fifo->size) |
| p_aout_cmd_fifo->kernel_rd_offset -= p_aout_cmd_fifo->size; |
| return; |
| } |
| |
| static int AoutFifoCheckKernelFullness(AOUT_PATH_CMD_FIFO *p_aout_cmd_fifo) |
| { |
| int full; |
| full = p_aout_cmd_fifo->wr_offset - p_aout_cmd_fifo->kernel_rd_offset; |
| if (full < 0) |
| full += p_aout_cmd_fifo->size; |
| return full; |
| } |
| |
| static void aout_disable_int_msg_update(int *aout_info) |
| { |
| int *p = aout_info; |
| if(*p == HDMI_PATH) |
| disable_hdmi_int_msg = *(p+1); |
| |
| return; |
| } |
| |
| static void aout_start_cmd(int *aout_info) |
| { |
| int *p = aout_info; |
| int i, chanId; |
| AOUT_DMA_INFO *p_dma_info; |
| |
| if (*p == MULTI_PATH) { |
| p_ma_fifo = |
| (AOUT_PATH_CMD_FIFO *) MV_SHM_GetNonCacheVirtAddr(*(p + 1)); |
| for (i = 0; i < 4; i++) { |
| p_dma_info = |
| (AOUT_DMA_INFO *) |
| AoutFifoGetKernelRdDMAInfo(p_ma_fifo, i); |
| chanId = pri_audio_chanId[i]; |
| dhub_channel_write_cmd(&AG_dhubHandle.dhub, chanId, |
| p_dma_info->addr0, |
| p_dma_info->size0, 0, 0, 0, |
| i == 0 ? 1 : 0, 0, 0); |
| } |
| } else if (*p == LoRo_PATH) { |
| p_sa_fifo = |
| (AOUT_PATH_CMD_FIFO *) MV_SHM_GetNonCacheVirtAddr(*(p + 1)); |
| #if (BERLIN_CHIP_VERSION != BERLIN_BG2CD_A0 && BERLIN_CHIP_VERSION != BERLIN_BG2CDP) |
| p_dma_info = |
| (AOUT_DMA_INFO *) AoutFifoGetKernelRdDMAInfo(p_sa_fifo, 0); |
| chanId = avioDhubChMap_ag_SA_R; |
| dhub_channel_write_cmd(&AG_dhubHandle.dhub, chanId, |
| p_dma_info->addr0, p_dma_info->size0, 0, |
| 0, 0, 1, 0, 0); |
| #endif /* (BERLIN_CHIP_VERSION != BERLIN_BG2CD_A0) */ |
| } else if (*p == SPDIF_PATH) { |
| p_spdif_fifo = |
| (AOUT_PATH_CMD_FIFO *) MV_SHM_GetNonCacheVirtAddr(*(p + 1)); |
| #if (BERLIN_CHIP_VERSION != BERLIN_BG2CD_A0 && BERLIN_CHIP_VERSION != BERLIN_BG2CDP) |
| p_dma_info = |
| (AOUT_DMA_INFO *) AoutFifoGetKernelRdDMAInfo(p_spdif_fifo, |
| 0); |
| chanId = avioDhubChMap_ag_SPDIF_R; |
| dhub_channel_write_cmd(&AG_dhubHandle.dhub, chanId, |
| p_dma_info->addr0, p_dma_info->size0, 0, |
| 0, 0, 1, 0, 0); |
| #endif /* (BERLIN_CHIP_VERSION != BERLIN_BG2CD_A0) */ |
| } else if (*p == HDMI_PATH) { |
| p_hdmi_fifo = |
| (AOUT_PATH_CMD_FIFO *) MV_SHM_GetNonCacheVirtAddr(*(p + 1)); |
| p_dma_info = |
| (AOUT_DMA_INFO *) AoutFifoGetKernelRdDMAInfo(p_hdmi_fifo, |
| 0); |
| chanId = avioDhubChMap_vpp_HDMI_R; |
| dhub_channel_write_cmd(&VPP_dhubHandle.dhub, chanId, |
| p_dma_info->addr0, p_dma_info->size0, 0, |
| 0, 0, 1, 0, 0); |
| } |
| } |
| |
| static void aout_resume_cmd(int path_id) |
| { |
| AOUT_DMA_INFO *p_dma_info; |
| unsigned int i, chanId; |
| |
| if (path_id == MULTI_PATH) { |
| if (!p_ma_fifo->fifo_underflow) |
| AoutFifoKernelRdUpdate(p_ma_fifo, 1); |
| |
| if (AoutFifoCheckKernelFullness(p_ma_fifo)) { |
| p_ma_fifo->fifo_underflow = 0; |
| for (i = 0; i < 4; i++) { |
| p_dma_info = |
| (AOUT_DMA_INFO *) |
| AoutFifoGetKernelRdDMAInfo(p_ma_fifo, i); |
| chanId = pri_audio_chanId[i]; |
| dhub_channel_write_cmd(&AG_dhubHandle.dhub, |
| chanId, |
| p_dma_info->addr0, |
| p_dma_info->size0, 0, 0, |
| 0, |
| (p_dma_info->size1 == 0 |
| && i == 0) ? 1 : 0, 0, |
| 0); |
| if (p_dma_info->size1) |
| dhub_channel_write_cmd(&AG_dhubHandle. |
| dhub, chanId, |
| p_dma_info-> |
| addr1, |
| p_dma_info-> |
| size1, 0, 0, 0, |
| (i == 0) ? 1 : 0, |
| 0, 0); |
| } |
| } else { |
| p_ma_fifo->fifo_underflow = 1; |
| for (i = 0; i < 4; i++) { |
| chanId = pri_audio_chanId[i]; |
| dhub_channel_write_cmd(&AG_dhubHandle.dhub, |
| chanId, |
| p_ma_fifo->zero_buffer, |
| p_ma_fifo-> |
| zero_buffer_size, 0, 0, |
| 0, i == 0 ? 1 : 0, 0, 0); |
| } |
| } |
| } else if (path_id == LoRo_PATH) { |
| #if (BERLIN_CHIP_VERSION != BERLIN_BG2CD_A0 && BERLIN_CHIP_VERSION != BERLIN_BG2CDP) |
| if (!p_sa_fifo->fifo_underflow) |
| AoutFifoKernelRdUpdate(p_sa_fifo, 1); |
| |
| if (AoutFifoCheckKernelFullness(p_sa_fifo)) { |
| p_sa_fifo->fifo_underflow = 0; |
| p_dma_info = |
| (AOUT_DMA_INFO *) |
| AoutFifoGetKernelRdDMAInfo(p_sa_fifo, 0); |
| chanId = avioDhubChMap_ag_SA_R; |
| dhub_channel_write_cmd(&AG_dhubHandle.dhub, chanId, |
| p_dma_info->addr0, |
| p_dma_info->size0, 0, 0, 0, |
| p_dma_info->size1 ? 0 : 1, 0, 0); |
| if (p_dma_info->size1) |
| dhub_channel_write_cmd(&AG_dhubHandle.dhub, |
| chanId, |
| p_dma_info->addr1, |
| p_dma_info->size1, 0, 0, |
| 0, 1, 0, 0); |
| } else { |
| p_sa_fifo->fifo_underflow = 1; |
| chanId = avioDhubChMap_ag_SA_R; |
| dhub_channel_write_cmd(&AG_dhubHandle.dhub, chanId, |
| p_sa_fifo->zero_buffer, |
| p_sa_fifo->zero_buffer_size, 0, |
| 0, 0, 1, 0, 0); |
| } |
| #endif /* (BERLIN_CHIP_VERSION != BERLIN_BG2CD_A0) */ |
| } else if (path_id == SPDIF_PATH) { |
| #if (BERLIN_CHIP_VERSION != BERLIN_BG2CD_A0 && BERLIN_CHIP_VERSION != BERLIN_BG2CDP) |
| if (!p_spdif_fifo->fifo_underflow) |
| AoutFifoKernelRdUpdate(p_spdif_fifo, 1); |
| |
| if (AoutFifoCheckKernelFullness(p_spdif_fifo)) { |
| p_spdif_fifo->fifo_underflow = 0; |
| p_dma_info = |
| (AOUT_DMA_INFO *) |
| AoutFifoGetKernelRdDMAInfo(p_spdif_fifo, 0); |
| chanId = avioDhubChMap_ag_SPDIF_R; |
| dhub_channel_write_cmd(&AG_dhubHandle.dhub, chanId, |
| p_dma_info->addr0, |
| p_dma_info->size0, 0, 0, 0, |
| p_dma_info->size1 ? 0 : 1, 0, 0); |
| if (p_dma_info->size1) |
| dhub_channel_write_cmd(&AG_dhubHandle.dhub, |
| chanId, |
| p_dma_info->addr1, |
| p_dma_info->size1, 0, 0, |
| 0, 1, 0, 0); |
| } else { |
| p_spdif_fifo->fifo_underflow = 1; |
| chanId = avioDhubChMap_ag_SPDIF_R; |
| dhub_channel_write_cmd(&AG_dhubHandle.dhub, chanId, |
| p_spdif_fifo->zero_buffer, |
| p_spdif_fifo->zero_buffer_size, |
| 0, 0, 0, 1, 0, 0); |
| } |
| #endif /* (BERLIN_CHIP_VERSION != BERLIN_BG2CD_A0) */ |
| } else if (path_id == HDMI_PATH) { |
| if (!p_hdmi_fifo->fifo_underflow) |
| AoutFifoKernelRdUpdate(p_hdmi_fifo, 1); |
| |
| if (AoutFifoCheckKernelFullness(p_hdmi_fifo)) { |
| p_hdmi_fifo->fifo_underflow = 0; |
| p_dma_info = |
| (AOUT_DMA_INFO *) |
| AoutFifoGetKernelRdDMAInfo(p_hdmi_fifo, 0); |
| chanId = avioDhubChMap_vpp_HDMI_R; |
| dhub_channel_write_cmd(&VPP_dhubHandle.dhub, chanId, |
| p_dma_info->addr0, |
| p_dma_info->size0, 0, 0, 0, |
| p_dma_info->size1 ? 0 : 1, 0, 0); |
| if (p_dma_info->size1) |
| dhub_channel_write_cmd(&VPP_dhubHandle.dhub, |
| chanId, |
| p_dma_info->addr1, |
| p_dma_info->size1, 0, 0, |
| 0, 1, 0, 0); |
| } else { |
| p_hdmi_fifo->fifo_underflow = 1; |
| chanId = avioDhubChMap_vpp_HDMI_R; |
| dhub_channel_write_cmd(&VPP_dhubHandle.dhub, chanId, |
| p_hdmi_fifo->zero_buffer, |
| p_hdmi_fifo->zero_buffer_size, 0, |
| 0, 0, 1, 0, 0); |
| } |
| } |
| return; |
| } |
| |
| static void *AIPFifoGetKernelPreRdDMAInfo(AIP_DMA_CMD_FIFO * p_aip_cmd_fifo, int pair) |
| { |
| void *pHandle; |
| pHandle = &(p_aip_cmd_fifo->aip_dma_cmd[pair][p_aip_cmd_fifo->kernel_pre_rd_offset]); |
| return pHandle; |
| } |
| |
| static void AIPFifoKernelPreRdUpdate(AIP_DMA_CMD_FIFO * p_aip_cmd_fifo, int adv) |
| { |
| int tmp; |
| tmp = p_aip_cmd_fifo->kernel_pre_rd_offset + adv; |
| p_aip_cmd_fifo->kernel_pre_rd_offset = tmp >= p_aip_cmd_fifo->size ? |
| tmp - p_aip_cmd_fifo->size : tmp; |
| return; |
| } |
| |
| static void AIPFifoKernelRdUpdate(AIP_DMA_CMD_FIFO *p_aip_cmd_fifo, int adv) |
| { |
| int tmp; |
| tmp = p_aip_cmd_fifo->kernel_rd_offset + adv; |
| p_aip_cmd_fifo->kernel_rd_offset = tmp >= p_aip_cmd_fifo->size ? |
| tmp - p_aip_cmd_fifo->size : tmp; |
| return; |
| } |
| |
| static int AIPFifoCheckKernelFullness(AIP_DMA_CMD_FIFO *p_aip_cmd_fifo) |
| { |
| int full; |
| full = p_aip_cmd_fifo->wr_offset - p_aip_cmd_fifo->kernel_pre_rd_offset; |
| if (full < 0) |
| full += p_aip_cmd_fifo->size; |
| return full; |
| } |
| |
| static void aip_start_cmd(int *aip_info) |
| { |
| #if (BERLIN_CHIP_VERSION != BERLIN_BG2CDP) |
| |
| int *p = aip_info; |
| int chanId, pair; |
| AIP_DMA_CMD *p_dma_cmd; |
| |
| if (*p == 1) { |
| aip_i2s_pair = 1; |
| p_aip_fifo = |
| (AIP_DMA_CMD_FIFO *) MV_SHM_GetNonCacheVirtAddr(*(p + 1)); |
| p_dma_cmd = |
| (AIP_DMA_CMD *) AIPFifoGetKernelPreRdDMAInfo(p_aip_fifo, 0); |
| |
| #if (BERLIN_CHIP_VERSION >= BERLIN_BG2_A0) |
| chanId = avioDhubChMap_vip_MIC0_W; |
| dhub_channel_write_cmd(&VIP_dhubHandle.dhub, chanId, |
| p_dma_cmd->addr0, p_dma_cmd->size0, 0, 0, |
| 0, 1, 0, 0); |
| #else |
| chanId = avioDhubChMap_ag_MIC_W; |
| dhub_channel_write_cmd(&AG_dhubHandle.dhub, chanId, |
| p_dma_cmd->addr0, p_dma_cmd->size0, 0, 0, |
| 0, 1, 0, 0); |
| #endif |
| AIPFifoKernelPreRdUpdate(p_aip_fifo, 1); |
| |
| // push 2nd dHub command |
| p_dma_cmd = (AIP_DMA_CMD *) AIPFifoGetKernelPreRdDMAInfo(p_aip_fifo, 0); |
| #if (BERLIN_CHIP_VERSION >= BERLIN_BG2_A0) |
| chanId = avioDhubChMap_vip_MIC0_W; |
| dhub_channel_write_cmd(&VIP_dhubHandle.dhub, chanId, |
| p_dma_cmd->addr0, p_dma_cmd->size0, 0, 0, |
| 0, 1, 0, 0); |
| #else |
| chanId = avioDhubChMap_ag_MIC_W; |
| dhub_channel_write_cmd(&AG_dhubHandle.dhub, chanId, |
| p_dma_cmd->addr0, p_dma_cmd->size0, 0, 0, |
| 0, 1, 0, 0); |
| #endif |
| AIPFifoKernelPreRdUpdate(p_aip_fifo, 1); |
| } else if (*p == 4) { |
| /* 4 I2S will be introduced since BG2 A0 */ |
| aip_i2s_pair = 4; |
| p_aip_fifo = (AIP_DMA_CMD_FIFO *) MV_SHM_GetNonCacheVirtAddr(*(p + 1)); |
| for (pair = 0; pair < 4; pair++) { |
| p_dma_cmd = |
| (AIP_DMA_CMD *)AIPFifoGetKernelPreRdDMAInfo(p_aip_fifo, pair); |
| #if (BERLIN_CHIP_VERSION >= BERLIN_BG2_A0) |
| chanId = avioDhubChMap_vip_MIC0_W + pair; |
| dhub_channel_write_cmd(&VIP_dhubHandle.dhub, chanId, |
| p_dma_cmd->addr0, |
| p_dma_cmd->size0, 0, 0, 0, 1, 0, |
| 0); |
| #else |
| chanId = avioDhubChMap_ag_MIC_W; |
| dhub_channel_write_cmd(&AG_dhubHandle.dhub, chanId, |
| p_dma_cmd->addr0, |
| p_dma_cmd->size0, 0, 0, 0, 1, 0, |
| 0); |
| #endif |
| } |
| AIPFifoKernelPreRdUpdate(p_aip_fifo, 1); |
| |
| // push 2nd dHub command |
| for (pair = 0; pair < 4; pair++) { |
| p_dma_cmd = (AIP_DMA_CMD *)AIPFifoGetKernelPreRdDMAInfo(p_aip_fifo, pair); |
| #if (BERLIN_CHIP_VERSION >= BERLIN_BG2_A0) |
| chanId = avioDhubChMap_vip_MIC0_W + pair; |
| dhub_channel_write_cmd(&VIP_dhubHandle.dhub, chanId, |
| p_dma_cmd->addr0, |
| p_dma_cmd->size0, 0, 0, 0, 1, 0, |
| 0); |
| #else |
| chanId = avioDhubChMap_ag_MIC_W; |
| dhub_channel_write_cmd(&AG_dhubHandle.dhub, chanId, |
| p_dma_cmd->addr0, |
| p_dma_cmd->size0, 0, 0, 0, 1, 0, |
| 0); |
| #endif |
| } |
| AIPFifoKernelPreRdUpdate(p_aip_fifo, 1); |
| } |
| #endif /* (BERLIN_CHIP_VERSION != BERLIN_BG2CDP) */ |
| } |
| |
| static void aip_stop_cmd(void) |
| { |
| return; |
| } |
| |
| static void aip_resume_cmd() |
| { |
| AIP_DMA_CMD *p_dma_cmd; |
| unsigned int chanId; |
| int pair; |
| |
| #if (BERLIN_CHIP_VERSION != BERLIN_BG2CDP) |
| if (!p_aip_fifo->fifo_overflow) |
| AIPFifoKernelRdUpdate(p_aip_fifo, 1); |
| |
| if (AIPFifoCheckKernelFullness(p_aip_fifo)) { |
| p_aip_fifo->fifo_overflow = 0; |
| for (pair = 0; pair < aip_i2s_pair; pair++) { |
| p_dma_cmd = (AIP_DMA_CMD *)AIPFifoGetKernelPreRdDMAInfo(p_aip_fifo, pair); |
| #if (BERLIN_CHIP_VERSION >= BERLIN_BG2_A0) |
| chanId = avioDhubChMap_vip_MIC0_W + pair; |
| dhub_channel_write_cmd(&VIP_dhubHandle.dhub, chanId, |
| p_dma_cmd->addr0, |
| p_dma_cmd->size0, 0, 0, 0, |
| p_dma_cmd->addr1 ? 0 : 1, 0, 0); |
| if (p_dma_cmd->addr1) { |
| dhub_channel_write_cmd(&VIP_dhubHandle.dhub, |
| chanId, p_dma_cmd->addr1, |
| p_dma_cmd->size1, 0, 0, |
| 0, 1, 0, 0); |
| } |
| #else |
| chanId = avioDhubChMap_ag_MIC_W; |
| dhub_channel_write_cmd(&AG_dhubHandle.dhub, chanId, |
| p_dma_cmd->addr0, |
| p_dma_cmd->size0, 0, 0, 0, |
| p_dma_cmd->addr1 ? 0 : 1, 0, 0); |
| if (p_dma_cmd->addr1) { |
| dhub_channel_write_cmd(&AG_dhubHandle.dhub, |
| chanId, p_dma_cmd->addr1, |
| p_dma_cmd->size1, 0, 0, |
| 0, 1, 0, 0); |
| } |
| #endif |
| } |
| AIPFifoKernelPreRdUpdate(p_aip_fifo, 1); |
| } else { |
| p_aip_fifo->fifo_overflow = 1; |
| p_aip_fifo->fifo_overflow_cnt++; |
| for (pair = 0; pair < aip_i2s_pair; pair++) { |
| /* FIXME: |
| *chanid should be changed if 4 pair is supported |
| */ |
| #if (BERLIN_CHIP_VERSION >= BERLIN_BG2_A0) |
| chanId = avioDhubChMap_vip_MIC0_W + pair; |
| dhub_channel_write_cmd(&VIP_dhubHandle.dhub, chanId, |
| p_aip_fifo->overflow_buffer, |
| p_aip_fifo->overflow_buffer_size, |
| 0, 0, 0, 1, 0, 0); |
| #else |
| chanId = avioDhubChMap_ag_MIC_W; |
| dhub_channel_write_cmd(&AG_dhubHandle.dhub, chanId, |
| p_aip_fifo->overflow_buffer, |
| p_aip_fifo->overflow_buffer_size, |
| 0, 0, 0, 1, 0, 0); |
| #endif |
| } |
| } |
| #endif /* (BERLIN_CHIP_VERSION != BERLIN_BG2CDP) */ |
| } |
| |
| static int HwAPPFifoCheckKernelFullness(HWAPP_CMD_FIFO *p_app_cmd_fifo) |
| { |
| int full; |
| full = p_app_cmd_fifo->wr_offset - p_app_cmd_fifo->kernel_rd_offset; |
| if (full < 0) |
| full += p_app_cmd_fifo->size; |
| return full; |
| } |
| |
| static void *HwAPPFifoGetKernelCoefRdCmdBuf(HWAPP_CMD_FIFO *p_app_cmd_fifo) |
| { |
| void *pHandle; |
| pHandle = &(p_app_cmd_fifo->coef_cmd[p_app_cmd_fifo->kernel_rd_offset]); |
| return pHandle; |
| } |
| |
| static void *HwAPPFifoGetKernelDataRdCmdBuf(HWAPP_CMD_FIFO *p_app_cmd_fifo) |
| { |
| void *pHandle; |
| pHandle = &(p_app_cmd_fifo->data_cmd[p_app_cmd_fifo->kernel_rd_offset]); |
| return pHandle; |
| } |
| |
| static void HwAPPFifoUpdateIdleFlag(HWAPP_CMD_FIFO *p_app_cmd_fifo, int flag) |
| { |
| p_app_cmd_fifo->kernel_idle = flag; |
| } |
| |
| static void HwAPPFifoKernelRdUpdate(HWAPP_CMD_FIFO *p_app_cmd_fifo, int adv) |
| { |
| p_app_cmd_fifo->kernel_rd_offset += adv; |
| if (p_app_cmd_fifo->kernel_rd_offset >= p_app_cmd_fifo->size) |
| p_app_cmd_fifo->kernel_rd_offset -= p_app_cmd_fifo->size; |
| } |
| |
| static void app_start_cmd(HWAPP_CMD_FIFO *p_app_cmd_fifo) |
| { |
| APP_CMD_BUFFER *p_coef_cmd; |
| APP_CMD_BUFFER *p_data_cmd; |
| unsigned int chanId, PA, cmdSize; |
| |
| if (HwAPPFifoCheckKernelFullness(p_app_cmd_fifo)) { |
| HwAPPFifoUpdateIdleFlag(p_app_cmd_fifo, 0); |
| p_coef_cmd = |
| (APP_CMD_BUFFER *) |
| HwAPPFifoGetKernelCoefRdCmdBuf(p_app_cmd_fifo); |
| chanId = avioDhubChMap_ag_APPCMD_R; |
| if (p_coef_cmd->cmd_len) { |
| PA = p_coef_cmd->cmd_buffer_hw_base; |
| cmdSize = p_coef_cmd->cmd_len * sizeof(int); |
| dhub_channel_write_cmd(&AG_dhubHandle.dhub, chanId, PA, |
| cmdSize, 0, 0, 0, 0, 0, 0); |
| } |
| p_data_cmd = |
| (APP_CMD_BUFFER *) |
| HwAPPFifoGetKernelDataRdCmdBuf(p_app_cmd_fifo); |
| if (p_data_cmd->cmd_len) { |
| PA = p_data_cmd->cmd_buffer_hw_base; |
| cmdSize = p_data_cmd->cmd_len * sizeof(int); |
| dhub_channel_write_cmd(&AG_dhubHandle.dhub, chanId, PA, |
| cmdSize, 0, 0, 0, 0, 0, 0); |
| } |
| } else { |
| HwAPPFifoUpdateIdleFlag(p_app_cmd_fifo, 1); |
| } |
| } |
| |
| static void app_resume_cmd(HWAPP_CMD_FIFO *p_app_cmd_fifo) |
| { |
| HwAPPFifoKernelRdUpdate(p_app_cmd_fifo, 1); |
| app_start_cmd(p_app_cmd_fifo); |
| } |
| |
| static irqreturn_t pe_devices_aout_isr(int irq, void *dev_id) |
| { |
| int instat; |
| UNSG32 chanId; |
| HDL_semaphore *pSemHandle; |
| |
| pSemHandle = dhub_semaphore(&AG_dhubHandle.dhub); |
| instat = semaphore_chk_full(pSemHandle, -1); |
| |
| for (chanId = avioDhubChMap_ag_MA0_R; chanId <= avioDhubChMap_ag_MA3_R; |
| chanId++) { |
| if (bTST(instat, chanId)) { |
| semaphore_pop(pSemHandle, chanId, 1); |
| semaphore_clr_full(pSemHandle, chanId); |
| if (chanId == avioDhubChMap_ag_MA0_R) { |
| aout_resume_cmd(MULTI_PATH); |
| tasklet_hi_schedule(&pe_ma_tasklet); |
| } |
| } |
| } |
| |
| #if (BERLIN_CHIP_VERSION != BERLIN_BG2CD_A0 && BERLIN_CHIP_VERSION != BERLIN_BG2CDP) |
| chanId = avioDhubChMap_ag_SA_R; |
| if (bTST(instat, chanId)) { |
| semaphore_pop(pSemHandle, chanId, 1); |
| semaphore_clr_full(pSemHandle, chanId); |
| aout_resume_cmd(LoRo_PATH); |
| tasklet_hi_schedule(&pe_sa_tasklet); |
| } |
| #endif /* (BERLIN_CHIP_VERSION != BERLIN_BG2CD_A0) */ |
| |
| #if (BERLIN_CHIP_VERSION != BERLIN_BG2CD_A0 && BERLIN_CHIP_VERSION != BERLIN_BG2CDP) |
| chanId = avioDhubChMap_ag_SPDIF_R; |
| if (bTST(instat, chanId)) { |
| semaphore_pop(pSemHandle, chanId, 1); |
| semaphore_clr_full(pSemHandle, chanId); |
| aout_resume_cmd(SPDIF_PATH); |
| tasklet_hi_schedule(&pe_spdif_tasklet); |
| } |
| #endif /* (BERLIN_CHIP_VERSION != BERLIN_BG2CD_A0) */ |
| #if(BERLIN_CHIP_VERSION < BERLIN_BG2_A0) |
| chanId = avioDhubChMap_ag_MIC_W; |
| if (bTST(instat, chanId)) { |
| semaphore_pop(pSemHandle, chanId, 1); |
| semaphore_clr_full(pSemHandle, chanId); |
| aip_resume_cmd(); |
| tasklet_hi_schedule(&pe_aip_tasklet); |
| } |
| #endif |
| |
| #if (BERLIN_CHIP_VERSION >= BERLIN_BG2) |
| chanId = avioDhubSemMap_ag_app_intr2; |
| #else |
| chanId = avioDhubChMap_ag_APPDAT_W; |
| #endif |
| if (bTST(instat, chanId)) { |
| semaphore_pop(pSemHandle, chanId, 1); |
| semaphore_clr_full(pSemHandle, chanId); |
| app_resume_cmd(p_app_fifo); |
| tasklet_hi_schedule(&pe_app_tasklet); |
| } |
| |
| #if (BERLIN_CHIP_VERSION != BERLIN_BG2CDP) |
| #if (BERLIN_CHIP_VERSION != BERLIN_BG2CD_A0) |
| chanId = avioDhubChMap_ag_PG_ENG_W; |
| if (bTST(instat, chanId)) { |
| semaphore_pop(pSemHandle, chanId, 1); |
| semaphore_clr_full(pSemHandle, chanId); |
| tasklet_hi_schedule(&pe_pg_done_tasklet); |
| } |
| #endif /* (BERLIN_CHIP_VERSION != BERLIN_BG2CD_A0) */ |
| |
| chanId = avioDhubSemMap_ag_spu_intr0; |
| if (bTST(instat, chanId)) { |
| semaphore_pop(pSemHandle, chanId, 1); |
| semaphore_clr_full(pSemHandle, chanId); |
| tasklet_hi_schedule(&pe_rle_err_tasklet); |
| } |
| |
| chanId = avioDhubSemMap_ag_spu_intr1; |
| if (bTST(instat, chanId)) { |
| semaphore_pop(pSemHandle, chanId, 1); |
| semaphore_clr_full(pSemHandle, chanId); |
| tasklet_hi_schedule(&pe_rle_done_tasklet); |
| } |
| |
| #endif /* (BERLIN_CHIP_VERSION != BERLIN_BG2CDP) */ |
| return IRQ_HANDLED; |
| } |
| |
| static irqreturn_t pe_devices_zsp_isr(int irq, void *dev_id) |
| { |
| UNSG32 addr, v_id; |
| T32ZspInt2Soc_status reg; |
| |
| addr = MEMMAP_ZSP_REG_BASE + RA_ZspRegs_Int2Soc + RA_ZspInt2Soc_status; |
| GA_REG_WORD32_READ(addr, &(reg.u32)); |
| |
| addr = MEMMAP_ZSP_REG_BASE + RA_ZspRegs_Int2Soc + RA_ZspInt2Soc_clear; |
| v_id = ADSP_ZSPINT2Soc_IRQ0; |
| if ((reg.u32) & (1 << v_id)) { |
| GA_REG_WORD32_WRITE(addr, v_id); |
| } |
| |
| tasklet_hi_schedule(&pe_zsp_tasklet); // this is audio zsp, video zsp interrupt will use another tasklet to post msg. |
| |
| return IRQ_HANDLED; |
| } |
| |
| #if (BERLIN_CHIP_VERSION >= BERLIN_BG2_A0) |
| #define MEMMAP_VPP_REG_BASE 0xF7F60000 |
| #define RA_Vpp_HDMI_ctrl 0x100C0 |
| #define MSK32HDMI_ctrl_DAMP 0x7FF80000 |
| #define MSK32HDMI_ctrl_EAMP 0x00000FFF |
| |
| static void pe_power_off_hdmi(void) |
| { |
| UNSG32 addr, value; |
| HDL_semaphore *pSemHandle; |
| |
| addr = MEMMAP_VPP_REG_BASE + RA_Vpp_HDMI_ctrl; |
| GA_REG_WORD32_READ(addr, &value); |
| value &= (~MSK32HDMI_ctrl_DAMP); |
| GA_REG_WORD32_WRITE(addr, value); |
| addr = MEMMAP_VPP_REG_BASE + RA_Vpp_HDMI_ctrl+ 0x4; |
| GA_REG_WORD32_READ(addr, &value); |
| value &= (~MSK32HDMI_ctrl_EAMP); |
| GA_REG_WORD32_WRITE(addr, value); |
| /* disable CPCB0 interrupt */ |
| #ifdef CONFIG_BERLIN_FASTLOGO |
| if(dhub_init_flag) |
| #endif |
| { |
| pSemHandle = dhub_semaphore(&VPP_dhubHandle.dhub); |
| semaphore_intr_enable(pSemHandle, avioDhubSemMap_vpp_vppCPCB0_intr, |
| 0/*empty*/, 0/*full*/, 0/*almost empty*/, 0/*almost full*/, 0/*cpu id*/); |
| } |
| } |
| #endif |
| |
| static int pe_reboot_notify_sys(struct notifier_block *this, unsigned long code, |
| void *unused) |
| { |
| #if (BERLIN_CHIP_VERSION >= BERLIN_BG2_A0) |
| pe_power_off_hdmi(); |
| #endif |
| return NOTIFY_DONE; |
| } |
| |
| static struct notifier_block pe_reboot_notifier = { |
| .notifier_call = pe_reboot_notify_sys |
| }; |
| |
| |
| static int pe_device_init(unsigned int cpu_id, void *pHandle) |
| { |
| unsigned int vec_num; |
| int err = 0; |
| |
| vpp_cpcb0_vbi_int_cnt = 0; |
| vpp_hdmi_audio_int_cnt =0; |
| err = register_reboot_notifier(&pe_reboot_notifier); |
| if(err) return err; |
| tasklet_enable(&pe_vpp_tasklet); |
| tasklet_enable(&pe_vpp_cec_tasklet); |
| tasklet_enable(&pe_vdec_tasklet); |
| #if (BERLIN_CHIP_VERSION >= BERLIN_BG2) |
| tasklet_enable(&pe_vip_tasklet); |
| #endif |
| tasklet_enable(&pe_ma_tasklet); |
| tasklet_enable(&pe_sa_tasklet); |
| tasklet_enable(&pe_spdif_tasklet); |
| tasklet_enable(&pe_aip_tasklet); |
| tasklet_enable(&pe_hdmi_tasklet); |
| tasklet_enable(&pe_app_tasklet); |
| tasklet_enable(&pe_zsp_tasklet); |
| tasklet_enable(&pe_pg_done_tasklet); |
| tasklet_enable(&pe_rle_err_tasklet); |
| tasklet_enable(&pe_rle_done_tasklet); |
| |
| #ifdef CONFIG_BERLIN_FASTLOGO |
| /* defer the DhubInitialization to the pe_driver_open() after fastlogo_stop(); */ |
| pe_cpu_id = cpu_id; |
| #else |
| /* initialize dhub */ |
| DhubInitialization(cpu_id, VPP_DHUB_BASE, VPP_HBO_SRAM_BASE, |
| &VPP_dhubHandle, VPP_config, VPP_NUM_OF_CHANNELS); |
| DhubInitialization(cpu_id, AG_DHUB_BASE, AG_HBO_SRAM_BASE, |
| &AG_dhubHandle, AG_config, AG_NUM_OF_CHANNELS); |
| #if (BERLIN_CHIP_VERSION >= BERLIN_BG2) && (BERLIN_CHIP_VERSION != BERLIN_BG2CD_A0) && (BERLIN_CHIP_VERSION != BERLIN_BG2CDP) |
| DhubInitialization(cpu_id, VIP_DHUB_BASE, VIP_HBO_SRAM_BASE, |
| &VIP_dhubHandle, VIP_config, VIP_NUM_OF_CHANNELS); |
| #endif |
| #endif //CONFIG_BERLIN_FASTLOGO |
| |
| #if CONFIG_VPP_IOCTL_MSG |
| sema_init(&vpp_sem, 0); |
| #endif |
| |
| #if CONFIG_VPP_ISR_MSGQ |
| err = PEMsgQ_Init(&hPEMsgQ, VPP_ISR_MSGQ_SIZE); |
| if (unlikely(err != S_OK)) { |
| pe_trace("PEMsgQ_Init: falied, err:%8x\n", err); |
| unregister_reboot_notifier(&pe_reboot_notifier); |
| return err; |
| } |
| #endif |
| |
| #if (BERLIN_CHIP_VERSION >= BERLIN_BG2) |
| #if CONFIG_VIP_IOCTL_MSG |
| sema_init(&vip_sem, 0); |
| #endif |
| #if CONFIG_VIP_ISR_MSGQ |
| err = PEMsgQ_Init(&hPEVIPMsgQ, VIP_ISR_MSGQ_SIZE); |
| if (unlikely(err != S_OK)) { |
| pe_trace("PEVIPMsgQ_Init: falied, err:%8x\n", err); |
| unregister_reboot_notifier(&pe_reboot_notifier); |
| return err; |
| } |
| #endif |
| #endif |
| |
| return S_OK; |
| } |
| |
| static int pe_device_exit(unsigned int cpu_id, void *pHandle) |
| { |
| int err = 0; |
| unregister_reboot_notifier(&pe_reboot_notifier); |
| #if (BERLIN_CHIP_VERSION >= BERLIN_BG2) |
| #if CONFIG_VIP_ISR_MSGQ |
| err = PEMsgQ_Destroy(&hPEVIPMsgQ); |
| if (unlikely(err != S_OK)) { |
| pe_trace("vip MsgQ Destroy: falied, err:%8x\n",err); |
| return err; |
| } |
| #endif |
| #endif |
| #if CONFIG_VPP_ISR_MSGQ |
| err = PEMsgQ_Destroy(&hPEMsgQ); |
| if (unlikely(err != S_OK)) { |
| pe_trace("vpp MsgQ Destroy: falied, err:%8x\n", err); |
| return err; |
| } |
| #endif |
| |
| tasklet_disable(&pe_vpp_tasklet); |
| tasklet_disable(&pe_vpp_cec_tasklet); |
| tasklet_disable(&pe_vdec_tasklet); |
| #if (BERLIN_CHIP_VERSION >= BERLIN_BG2) |
| tasklet_disable(&pe_vip_tasklet); |
| #endif |
| tasklet_disable(&pe_ma_tasklet); |
| tasklet_disable(&pe_sa_tasklet); |
| tasklet_disable(&pe_spdif_tasklet); |
| tasklet_disable(&pe_aip_tasklet); |
| tasklet_disable(&pe_hdmi_tasklet); |
| tasklet_disable(&pe_app_tasklet); |
| tasklet_disable(&pe_zsp_tasklet); |
| tasklet_disable(&pe_pg_done_tasklet); |
| tasklet_disable(&pe_rle_err_tasklet); |
| tasklet_disable(&pe_rle_done_tasklet); |
| |
| return S_OK; |
| } |
| |
| /******************************************************************************* |
| Module API |
| */ |
| |
| static int pe_driver_open(struct inode *inode, struct file *filp) |
| { |
| unsigned int vec_num; |
| void *pHandle = &pe_dev; |
| int err = 0; |
| |
| #ifdef CONFIG_BERLIN_FASTLOGO |
| printk(KERN_NOTICE PE_DEVICE_TAG "drv stop fastlogo\n"); |
| fastlogo_stop(); |
| |
| /* initialize dhub */ |
| dhub_init_flag =1; |
| DhubInitialization(pe_cpu_id, VPP_DHUB_BASE, VPP_HBO_SRAM_BASE, |
| &VPP_dhubHandle, VPP_config, VPP_NUM_OF_CHANNELS); |
| DhubInitialization(pe_cpu_id, AG_DHUB_BASE, AG_HBO_SRAM_BASE, |
| &AG_dhubHandle, AG_config, AG_NUM_OF_CHANNELS); |
| #if (BERLIN_CHIP_VERSION >= BERLIN_BG2) && (BERLIN_CHIP_VERSION != BERLIN_BG2CD_A0) && (BERLIN_CHIP_VERSION != BERLIN_BG2CDP) |
| DhubInitialization(pe_cpu_id, VIP_DHUB_BASE, VIP_HBO_SRAM_BASE, |
| &VIP_dhubHandle, VIP_config, VIP_NUM_OF_CHANNELS); |
| #endif |
| |
| #endif |
| |
| #if (BERLIN_CHIP_VERSION >= BERLIN_BG2) |
| /* register and enable cec interrupt */ |
| #if (BERLIN_CHIP_VERSION >= BERLIN_BG2_A0) |
| vec_num = pe_irqs[IRQ_SM_CEC]; |
| err = |
| request_irq(vec_num, pe_devices_vpp_cec_isr, IRQF_DISABLED, |
| "pe_module_vpp_cec", pHandle); |
| if (unlikely(err < 0)) { |
| pe_trace("vec_num:%5d, err:%8x\n", vec_num, err); |
| return err; |
| } |
| #else |
| vec_num = IRQ_SM_GPIO0; |
| err = |
| request_irq(vec_num, pe_devices_vpp_cec_isr, |
| IRQF_DISABLED | IRQF_SHARED, "pe_module_vpp_cec", |
| pHandle); |
| if (unlikely(err < 0)) { |
| pe_trace("vec_num:%5d, err:%8x\n", vec_num, err); |
| return err; |
| } |
| #endif |
| #endif |
| |
| /* register and enable VPP ISR */ |
| vec_num = pe_irqs[IRQ_DHUBINTRAVIO0]; |
| err = request_irq(vec_num, pe_devices_vpp_isr, IRQF_DISABLED, "pe_module_vpp", pHandle); |
| if (unlikely(err < 0)) { |
| pe_trace("vec_num:%5d, err:%8x\n", vec_num, err); |
| return err; |
| } |
| #if (BERLIN_CHIP_VERSION >= BERLIN_BG2) |
| /* register and enable VIP ISR */ |
| vec_num = pe_irqs[IRQ_DHUBINTRAVIO2]; |
| err = request_irq(vec_num, pe_devices_vip_isr, IRQF_DISABLED, "pe_module_vip", pHandle); |
| if (unlikely(err < 0)) { |
| pe_trace("vec_num:%5d, err:%8x\n", vec_num, err); |
| return err; |
| } |
| #endif |
| |
| /* register and enable VDEC ISR */ |
| vec_num = pe_irqs[IRQ_DHUBINTRVPRO]; |
| err = request_irq(vec_num, pe_devices_vdec_isr, IRQF_DISABLED, "pe_module_vdec", pHandle); |
| if (unlikely(err < 0)) { |
| pe_trace("vec_num:%5d, err:%8x\n", vec_num, err); |
| return err; |
| } |
| |
| /* register and enable audio out ISR */ |
| vec_num = pe_irqs[IRQ_DHUBINTRAVIO1]; |
| err = request_irq(vec_num, pe_devices_aout_isr, IRQF_DISABLED, "pe_module_aout", pHandle); |
| if (unlikely(err < 0)) { |
| pe_trace("vec_num:%5d, err:%8x\n", vec_num, err); |
| return err; |
| } |
| |
| /* register and enable ZSP ISR */ |
| vec_num = pe_irqs[IRQ_ZSPINT]; |
| err = request_irq(vec_num, pe_devices_zsp_isr, IRQF_DISABLED, "pe_module_zsp", pHandle); |
| if (unlikely(err < 0)) |
| { |
| pe_trace("vec_num:%5d, err:%8x\n", vec_num, err); |
| return err; |
| } |
| |
| disable_irq(pe_irqs[IRQ_DHUBINTRVPRO]); |
| |
| pe_debug("pe_driver_open ok\n"); |
| |
| return 0; |
| } |
| |
| static int pe_driver_release(struct inode *inode, struct file *filp) |
| { |
| void *pHandle = &pe_dev; |
| unsigned int vec_num; |
| int err = 0; |
| /* unregister cec interrupt */ |
| #if (BERLIN_CHIP_VERSION >= BERLIN_BG2) |
| #if (BERLIN_CHIP_VERSION >= BERLIN_BG2_A0) |
| free_irq(pe_irqs[IRQ_SM_CEC], pHandle); |
| #else |
| free_irq(pe_irqs[IRQ_SM_GPIO0], pHandle); |
| #endif |
| #endif |
| |
| /* unregister VPP interrupt */ |
| free_irq(pe_irqs[IRQ_DHUBINTRAVIO0], pHandle); |
| /* unregister VIP interrupt */ |
| free_irq(pe_irqs[IRQ_DHUBINTRAVIO2], pHandle); |
| /* unregister VDEC interrupt */ |
| free_irq(pe_irqs[IRQ_DHUBINTRVPRO], pHandle); |
| /* unregister audio out interrupt */ |
| free_irq(pe_irqs[IRQ_DHUBINTRAVIO1], pHandle); |
| /* unregister ZSP interrupt */ |
| free_irq(pe_irqs[IRQ_ZSPINT], pHandle); |
| |
| pe_debug("pe_driver_release ok\n"); |
| |
| return 0; |
| } |
| |
| static long pe_driver_ioctl_unlocked(struct file *filp, unsigned int cmd, |
| unsigned long arg) |
| { |
| VPP_DMA_INFO user_dma_info; |
| int bcmbuf_info[2]; |
| int aout_info[2]; |
| int app_info[2]; |
| int aip_info[2]; |
| unsigned long irqstat, aoutirq, appirq, aipirq; |
| unsigned int bcm_sche_cmd_info[3], q_id; |
| |
| switch (cmd) { |
| case VPP_IOCTL_BCM_SCHE_CMD: |
| if (copy_from_user |
| (bcm_sche_cmd_info, (void __user *)arg, 3*sizeof(unsigned int))) |
| return -EFAULT; |
| q_id = bcm_sche_cmd_info[2]; |
| if (q_id > BCM_SCHED_Q5) { |
| pe_trace("error BCM queue ID = %d\n", q_id); |
| return -EFAULT; |
| } |
| bcm_sche_cmd[q_id][0] = bcm_sche_cmd_info[0]; |
| bcm_sche_cmd[q_id][1] = bcm_sche_cmd_info[1]; |
| break; |
| |
| case VPP_IOCTL_VBI_DMA_CFGQ: |
| if (copy_from_user |
| (&user_dma_info, (void __user *)arg, sizeof(VPP_DMA_INFO))) |
| return -EFAULT; |
| |
| dma_info[user_dma_info.cpcbID].DmaAddr = |
| (UINT32) MV_SHM_GetCacheVirtAddr(user_dma_info.DmaAddr); |
| dma_info[user_dma_info.cpcbID].DmaLen = user_dma_info.DmaLen; |
| break; |
| |
| case VPP_IOCTL_VBI_BCM_CFGQ: |
| if (copy_from_user |
| (&user_dma_info, (void __user *)arg, sizeof(VPP_DMA_INFO))) |
| return -EFAULT; |
| |
| vbi_bcm_info[user_dma_info.cpcbID].DmaAddr = |
| (UINT32) MV_SHM_GetCachePhysAddr(user_dma_info.DmaAddr); |
| vbi_bcm_info[user_dma_info.cpcbID].DmaLen = |
| user_dma_info.DmaLen; |
| break; |
| |
| case VPP_IOCTL_VDE_BCM_CFGQ: |
| if (copy_from_user |
| (&user_dma_info, (void __user *)arg, sizeof(VPP_DMA_INFO))) |
| return -EFAULT; |
| |
| vde_bcm_info[user_dma_info.cpcbID].DmaAddr = |
| (UINT32) MV_SHM_GetCachePhysAddr(user_dma_info.DmaAddr); |
| vde_bcm_info[user_dma_info.cpcbID].DmaLen = |
| user_dma_info.DmaLen; |
| break; |
| |
| case VPP_IOCTL_GET_MSG: |
| { |
| #if CONFIG_VPP_IOCTL_MSG |
| MV_CC_MSG_t msg = { 0 }; |
| HRESULT rc = S_OK; |
| |
| rc = down_interruptible(&vpp_sem); |
| if (rc < 0) |
| return rc; |
| |
| #ifdef CONFIG_IRQ_LATENCY_PROFILE |
| pe_irq_profiler.vpp_task_sched_last = |
| cpu_clock(smp_processor_id()); |
| #endif |
| #if CONFIG_VPP_ISR_MSGQ |
| |
| // check fullness, clear message queue once. |
| // only send latest message to task. |
| #if 1 |
| if (PEMsgQ_Fullness(&hPEMsgQ) <= 0) { |
| //pe_trace(" E/[vpp isr task] message queue empty\n"); |
| return -EFAULT; |
| } |
| |
| PEMsgQ_DequeueRead(&hPEMsgQ, &msg); |
| |
| if (atomic_read(&vpp_isr_msg_err_cnt)) { |
| // msgQ get full, if isr task can run here, reset msgQ |
| //fullness--; |
| //PEMsgQ_Dequeue(&hPEMsgQ, fullness); |
| atomic_set(&vpp_isr_msg_err_cnt, 0); |
| } |
| #else |
| rc = PEMsgQ_ReadTry(&hPEMsgQ, &msg); |
| if (unlikely(rc != S_OK)) { |
| pe_trace("read message queue failed\n"); |
| return -EFAULT; |
| } |
| PEMsgQ_ReadFinish(&hPEMsgQ); |
| #endif |
| #else |
| msg.m_MsgID = VPP_CC_MSG_TYPE_VPP; |
| msg.m_Param1 = vpp_instat; |
| msg.m_Param2 = vpp_intr_timestamp; |
| #endif |
| if (copy_to_user |
| ((void __user *)arg, &msg, sizeof(MV_CC_MSG_t))) |
| return -EFAULT; |
| break; |
| #else |
| return -EFAULT; |
| #endif |
| } |
| case CEC_IOCTL_RX_MSG_BUF_MSG:// copy cec rx message to user space buffer |
| if (copy_to_user |
| ((void __user *)arg, &rx_buf, sizeof(VPP_CEC_RX_MSG_BUF))) |
| return -EFAULT; |
| |
| return S_OK; |
| break; |
| case VPP_IOCTL_START_BCM_TRANSACTION: |
| if (copy_from_user |
| (bcmbuf_info, (void __user *)arg, 2 * sizeof(int))) |
| return -EFAULT; |
| spin_lock_irqsave(&bcm_spinlock, irqstat); |
| dhub_channel_write_cmd(&(VPP_dhubHandle.dhub), |
| avioDhubChMap_vpp_BCM_R, bcmbuf_info[0], |
| bcmbuf_info[1], 0, 0, 0, 1, 0, 0); |
| spin_unlock_irqrestore(&bcm_spinlock, irqstat); |
| break; |
| |
| case VPP_IOCTL_INTR_MSG: |
| //get VPP INTR MASK info |
| { |
| INTR_MSG vpp_intr_info = { 0, 0 }; |
| |
| if (copy_from_user |
| (&vpp_intr_info, (void __user *)arg, sizeof(INTR_MSG))) |
| return -EFAULT; |
| |
| if (vpp_intr_info.DhubSemMap < MAX_INTR_NUM) |
| vpp_intr_status[vpp_intr_info.DhubSemMap] = vpp_intr_info.Enable; |
| else |
| return -EFAULT; |
| |
| break; |
| } |
| |
| #if (BERLIN_CHIP_VERSION >= BERLIN_BG2) |
| /************************************** |
| * VIP IOCTL |
| **************************************/ |
| case VIP_IOCTL_GET_MSG: |
| { |
| #if CONFIG_VIP_IOCTL_MSG |
| MV_CC_MSG_t msg = { 0 }; |
| HRESULT rc = S_OK; |
| |
| rc = down_interruptible(&vip_sem); |
| if (rc < 0) |
| return rc; |
| |
| #if CONFIG_VIP_ISR_MSGQ |
| rc = PEMsgQ_ReadTry(&hPEVIPMsgQ, &msg); |
| if (unlikely(rc != S_OK)) { |
| pe_trace("VIP read message queue failed\n"); |
| return -EFAULT; |
| } |
| PEMsgQ_ReadFinish(&hPEVIPMsgQ); |
| #else |
| #if 0 |
| //msg.m_MsgID = VPP_CC_MSG_TYPE_VPP; |
| //msg.m_Param1 = MV_Time_GetTIMER7(); it's not in kernel symbol temp use others |
| msg.m_Param1 = vip_instat; |
| msg.m_Param2 = vip_intr_timestamp; |
| #endif |
| #endif |
| if (copy_to_user |
| ((void __user *)arg, &msg, sizeof(MV_CC_MSG_t))) |
| return -EFAULT; |
| break; |
| #else |
| return -EFAULT; |
| #endif |
| } |
| case VIP_IOCTL_VDE_BCM_CFGQ: |
| //TODO: get VBI data BCM CFGQ from user space |
| { |
| VIP_DMA_INFO user_vip_info; |
| |
| if (copy_from_user |
| (&user_vip_info, (void __user *)arg, |
| sizeof(VIP_DMA_INFO))) |
| return -EFAULT; |
| |
| vip_vbi_info.DmaAddr = |
| (UINT32) MV_SHM_GetCachePhysAddr(user_vip_info. |
| DmaAddr); |
| vip_vbi_info.DmaLen = user_vip_info.DmaLen; |
| |
| break; |
| } |
| case VIP_IOCTL_VBI_BCM_CFGQ: |
| //TODO: get BCM CFGQ from user space |
| { |
| VIP_DMA_INFO user_vip_info; |
| |
| if (copy_from_user |
| (&user_vip_info, (void __user *)arg, |
| sizeof(VIP_DMA_INFO))) |
| return -EFAULT; |
| |
| vip_dma_info.DmaAddr = |
| (UINT32) MV_SHM_GetCachePhysAddr(user_vip_info. |
| DmaAddr); |
| vip_dma_info.DmaLen = user_vip_info.DmaLen; |
| |
| break; |
| } |
| |
| case VIP_IOCTL_SD_WRE_CFGQ: |
| //TODO: get BCM CFGQ from user space |
| { |
| VIP_DMA_INFO user_vip_info; |
| |
| if (copy_from_user |
| (&user_vip_info, (void __user *)arg, |
| sizeof(VIP_DMA_INFO))) |
| return -EFAULT; |
| |
| vip_sd_wr_info.DmaAddr = |
| (UINT32) MV_SHM_GetCachePhysAddr(user_vip_info. |
| DmaAddr); |
| vip_sd_wr_info.DmaLen = user_vip_info.DmaLen; |
| |
| //setup WR DMA in advance! |
| start_vip_sd_wr_bcm(); |
| |
| break; |
| } |
| case VIP_IOCTL_SD_RDE_CFGQ: |
| //TODO: get BCM CFGQ from user space |
| { |
| VIP_DMA_INFO user_vip_info; |
| |
| if (copy_from_user |
| (&user_vip_info, (void __user *)arg, |
| sizeof(VIP_DMA_INFO))) |
| return -EFAULT; |
| |
| vip_sd_rd_info.DmaAddr = |
| (UINT32) MV_SHM_GetCachePhysAddr(user_vip_info. |
| DmaAddr); |
| vip_sd_rd_info.DmaLen = user_vip_info.DmaLen; |
| |
| //setup RD DMA in advance! |
| start_vip_sd_rd_bcm(); |
| |
| break; |
| } |
| |
| case VIP_IOCTL_SEND_MSG: |
| //get msg from VIP |
| { |
| int vip_msg = 0; |
| if (copy_from_user |
| (&vip_msg, (void __user *)arg, sizeof(int))) |
| return -EFAULT; |
| |
| if (vip_msg == VIP_MSG_DESTROY_ISR_TASK) { |
| //force one more INT to VIP to destroy ISR task |
| up(&vip_sem); |
| } |
| |
| break; |
| } |
| |
| case VIP_IOCTL_INTR_MSG: |
| //get VIP INTR MASK info |
| { |
| INTR_MSG vip_intr_info = { 0, 0 }; |
| |
| if (copy_from_user |
| (&vip_intr_info, (void __user *)arg, sizeof(INTR_MSG))) |
| return -EFAULT; |
| |
| if (vip_intr_info.DhubSemMap < MAX_INTR_NUM) |
| vip_intr_status[vip_intr_info.DhubSemMap] = vip_intr_info.Enable; |
| else |
| return -EFAULT; |
| |
| break; |
| } |
| #endif |
| |
| case VDEC_IOCTL_ENABLE_INT: |
| /* special handle for Vdec interrupt */ |
| #if CONFIG_VDEC_UNBLC_IRQ_FIX |
| if (vdec_enable_int_cnt - vdec_int_cnt == 0) { |
| enable_irq(pe_irqs[IRQ_DHUBINTRVPRO]); |
| vdec_enable_int_cnt++; |
| } |
| if (vdec_enable_int_cnt - vdec_int_cnt > 1) { |
| pe_trace("enable_irq vdec, vdec_int_depth:%d, %d\n", |
| vdec_int_cnt, vdec_enable_int_cnt); |
| } |
| #else |
| enable_irq(pe_irqs[IRQ_DHUBINTRVPRO]); |
| #endif |
| break; |
| |
| case VDEC_IOCTL_DISABLE_INT: |
| /* special handle for Vdec interrupt */ |
| #if CONFIG_VDEC_UNBLC_IRQ_FIX |
| if ((vdec_enable_int_cnt - vdec_int_cnt) > 0) { |
| disable_irq_nosync(pe_irqs[IRQ_DHUBINTRVPRO]); |
| vdec_int_cnt++; |
| } |
| if ((vdec_enable_int_cnt - vdec_int_cnt) != 0) { |
| pe_trace("enable_irq vdec, vdec_int_depth:%d, %d\n", |
| vdec_int_cnt, vdec_enable_int_cnt); |
| } |
| #else |
| disable_irq_nosync(pe_irqs[IRQ_DHUBINTRVPRO]); |
| #endif |
| break; |
| |
| case AOUT_IOCTL_DISABLE_INT_MSG: |
| if (copy_from_user |
| (aout_info, (void __user *)arg, 2 * sizeof(int))) |
| return -EFAULT; |
| spin_lock_irqsave(&aout_spinlock, aoutirq); |
| aout_disable_int_msg_update(aout_info); |
| spin_unlock_irqrestore(&aout_spinlock, aoutirq); |
| break; |
| |
| case AOUT_IOCTL_START_CMD: |
| if (copy_from_user |
| (aout_info, (void __user *)arg, 2 * sizeof(int))) |
| return -EFAULT; |
| spin_lock_irqsave(&aout_spinlock, aoutirq); |
| aout_start_cmd(aout_info); |
| spin_unlock_irqrestore(&aout_spinlock, aoutirq); |
| break; |
| |
| case AIP_IOCTL_START_CMD: |
| if (copy_from_user |
| (aip_info, (void __user *)arg, 2 * sizeof(int))) { |
| return -EFAULT; |
| } |
| spin_lock_irqsave(&aip_spinlock, aipirq); |
| aip_start_cmd(aip_info); |
| spin_unlock_irqrestore(&aip_spinlock, aipirq); |
| break; |
| |
| case AIP_IOCTL_STOP_CMD: |
| aip_stop_cmd(); |
| break; |
| |
| case APP_IOCTL_INIT_CMD: |
| if (copy_from_user(app_info, (void __user *)arg, sizeof(int))) |
| return -EFAULT; |
| p_app_fifo = |
| (HWAPP_CMD_FIFO *) MV_SHM_GetNonCacheVirtAddr(*app_info); |
| break; |
| |
| case APP_IOCTL_START_CMD: |
| spin_lock_irqsave(&app_spinlock, appirq); |
| app_start_cmd(p_app_fifo); |
| spin_unlock_irqrestore(&app_spinlock, appirq); |
| default: |
| break; |
| } |
| |
| return 0; |
| } |
| |
| static int read_proc_status(char *page, char **start, off_t offset, |
| int count, int *eof, void *data) |
| { |
| int len = 0; |
| int cnt; |
| int vpp_fatal_err = 0; |
| |
| if(atomic_read(&vpp_isr_msg_err_cnt)) |
| vpp_fatal_err = 1; |
| |
| len += snprintf(page + len, count, "PE_Module_IRQ_cnt: %d\n", vpp_cpcb0_vbi_int_cnt); |
| |
| len += snprintf(page + len, count, "VPP_MsgQ_full: %d\n", vpp_fatal_err); |
| |
| pe_debug("%s OK. (%d / %d)\n", __func__, len, count); |
| |
| *eof = 1; |
| |
| return ((count < len) ? count : len); |
| } |
| |
| static int read_proc_detail(char *page, char **start, off_t offset, |
| int count, int *eof, void *data) |
| { |
| int len = 0; |
| |
| len += |
| snprintf(page + len, count,"%-25s : %d aud %d \n", "PE Module IRQ cnt", |
| vpp_cpcb0_vbi_int_cnt, vpp_hdmi_audio_int_cnt); |
| |
| pe_debug("%s OK. (%d / %d)\n", __func__, len, count); |
| |
| *eof = 1; |
| |
| return ((count < len) ? count : len); |
| } |
| |
| /******************************************************************************* |
| Module Register API |
| */ |
| static int pe_driver_setup_cdev(struct cdev *dev, int major, int minor, |
| struct file_operations *fops) |
| { |
| cdev_init(dev, fops); |
| dev->owner = THIS_MODULE; |
| dev->ops = fops; |
| return cdev_add(dev, MKDEV(major, minor), 1); |
| } |
| |
| static int __init pe_driver_init(void) |
| { |
| int i, res; |
| struct device_node *np, *iter; |
| struct resource r; |
| |
| np = of_find_compatible_node(NULL, NULL, "mrvl,berlin-pe"); |
| if (!np) |
| return -ENODEV; |
| for (i = 0; i <= IRQ_DHUBINTRVPRO; i++) { |
| of_irq_to_resource(np, i, &r); |
| pe_irqs[i] = r.start; |
| } |
| for_each_child_of_node(np, iter) { |
| if (of_device_is_compatible(iter, "mrvl,berlin-cec")) { |
| of_irq_to_resource(iter, 0, &r); |
| pe_irqs[IRQ_SM_CEC] = r.start; |
| } |
| } |
| of_node_put(np); |
| |
| /* Figure out our device number. */ |
| res = |
| register_chrdev_region(MKDEV(GALOIS_PE_MAJOR, 0), GALOIS_PE_MINORS, |
| PE_DEVICE_NAME); |
| if (res < 0) { |
| pe_error("unable to get pe device major [%d]\n", |
| GALOIS_PE_MAJOR); |
| goto err_reg_device; |
| } |
| pe_debug("register cdev device major [%d]\n", GALOIS_PE_MAJOR); |
| |
| /* Now setup cdevs. */ |
| res = |
| pe_driver_setup_cdev(&pe_dev, GALOIS_PE_MAJOR, GALOIS_PE_MINOR, |
| &pe_ops); |
| if (res) { |
| pe_error("pe_driver_setup_cdev failed.\n"); |
| goto err_add_device; |
| } |
| pe_debug("setup cdevs device minor [%d]\n", GALOIS_PE_MINOR); |
| |
| /* add PE devices to sysfs */ |
| pe_dev_class = class_create(THIS_MODULE, PE_DEVICE_NAME); |
| if (IS_ERR(pe_dev_class)) { |
| pe_error("class_create failed.\n"); |
| res = -ENODEV; |
| goto err_add_device; |
| } |
| |
| device_create(pe_dev_class, NULL, |
| MKDEV(GALOIS_PE_MAJOR, GALOIS_PE_MINOR), |
| NULL, PE_DEVICE_NAME); |
| pe_debug("create device sysfs [%s]\n", PE_DEVICE_NAME); |
| |
| /* create PE device */ |
| res = pe_device_init(CPUINDEX, &pe_dev); |
| if (res != 0) |
| pe_error("pe_int_init failed !!! res = 0x%08X\n", res); |
| |
| /* create PE device proc file */ |
| pe_driver_procdir = proc_mkdir(PE_DEVICE_NAME, NULL); |
| //pe_driver_procdir->owner = THIS_MODULE; |
| create_proc_read_entry(PE_DEVICE_PROCFILE_STATUS, 0, pe_driver_procdir, |
| read_proc_status, NULL); |
| create_proc_read_entry(PE_DEVICE_PROCFILE_DETAIL, 0, pe_driver_procdir, |
| read_proc_detail, NULL); |
| |
| res = pe_agent_driver_init(); |
| if (res != 0) |
| pe_error("pe_agent_driver_init failed !!! res = 0x%08X\n", res); |
| |
| pe_trace("pe_driver_init OK\n"); |
| |
| return 0; |
| |
| err_add_device: |
| |
| cdev_del(&pe_dev); |
| |
| unregister_chrdev_region(MKDEV(GALOIS_PE_MAJOR, 0), GALOIS_PE_MINORS); |
| |
| err_reg_device: |
| |
| pe_trace("pe_driver_init failed !!! (%d)\n", res); |
| |
| return res; |
| } |
| |
| static void __exit pe_driver_exit(void) |
| { |
| int res; |
| |
| /* destroy PE kernel API */ |
| res = pe_device_exit(0, 0); |
| if (res != 0) |
| pe_error("pe_device_exit failed !!! res = 0x%08X\n", res); |
| |
| /* remove PE device proc file */ |
| remove_proc_entry(PE_DEVICE_PROCFILE_DETAIL, pe_driver_procdir); |
| remove_proc_entry(PE_DEVICE_PROCFILE_STATUS, pe_driver_procdir); |
| remove_proc_entry(PE_DEVICE_NAME, NULL); |
| |
| /* del sysfs entries */ |
| device_destroy(pe_dev_class, MKDEV(GALOIS_PE_MAJOR, GALOIS_PE_MINOR)); |
| pe_debug("delete device sysfs [%s]\n", PE_DEVICE_NAME); |
| |
| class_destroy(pe_dev_class); |
| |
| /* del cdev */ |
| cdev_del(&pe_dev); |
| |
| pe_agent_driver_exit(); |
| |
| unregister_chrdev_region(MKDEV(GALOIS_PE_MAJOR, 0), GALOIS_PE_MINORS); |
| pe_debug("unregister cdev device major [%d]\n", GALOIS_PE_MAJOR); |
| |
| pe_trace("pe_driver_exit OK\n"); |
| } |
| |
| module_init(pe_driver_init); |
| module_exit(pe_driver_exit); |
| |
| /******************************************************************************* |
| Module Descrption |
| */ |
| MODULE_AUTHOR("marvell"); |
| MODULE_LICENSE("GPL"); |
| MODULE_DESCRIPTION("pe module template"); |