#include "typesdef.h" #include "errno.h" #include "osal/irq.h" #include "devid.h" #include "dev/osd_enc/hgosd_enc.h" #include "osal/string.h" struct hgosdenc_hw { __IO uint32 OSD_ENC_CON; __IO uint32 OSD_ENC_STA; __IO uint32 OSD_ENC_SADR; __IO uint32 OSD_ENC_TADR; __IO uint32 OSD_ENC_RLEN; __IO uint32 OSD_ENC_DLEN; __IO uint32 OSD_ENC_IDENT0; __IO uint32 OSD_ENC_IDENT1; __IO uint32 OSD_ENC_TRANS0; __IO uint32 OSD_ENC_TRANS1; }; static int32 hgosd_ioctl(struct osdenc_device *p_osd, enum osdenc_ioctl_cmd ioctl_cmd, uint32 param1, uint32 param2) { int32 ret_val = RET_OK; struct hgosd *osd_hw = (struct hgosd*)p_osd; struct hgosdenc_hw *hw = (struct hgosdenc_hw *)osd_hw->hw; uint32_t *p32; switch(ioctl_cmd){ case OSD_IOCTL_TRAN_IDENT_TRANS: p32 = (uint32_t *)param1; hw->OSD_ENC_IDENT0 = p32[0]; hw->OSD_ENC_IDENT1 = p32[1]; hw->OSD_ENC_TRANS0 = p32[2]; hw->OSD_ENC_TRANS1 = p32[3]; break; case OSD_IOCTL_ENC_ADR: hw->OSD_ENC_SADR = param1; hw->OSD_ENC_TADR = param2; break; case OSD_IOCTL_SET_ENC_RLEN: hw->OSD_ENC_RLEN = ((param1/4 + 1)/2)*2 - 1; //word 偶对齐 -1 break; case OSD_IOCTL_SET_ENC_FORMAT: if(param1 == 1){ hw->OSD_ENC_CON &= ~BIT(1); //565 }else{ hw->OSD_ENC_CON |= BIT(1); //888 } break; case OSD_IOCTL_GET_ENC_DLEN: return hw->OSD_ENC_DLEN*4; break; case OSD_IOCTL_SET_ENC_RUN: hw->OSD_ENC_CON |= BIT(0); break; default: os_printf("NO OSD IOCTL:%d\r\n",ioctl_cmd); ret_val = -ENOTSUPP; break; } return ret_val; } osdenc_irq_hdl encirq_vector_table[ENC_IRQ_NUM]; void * encirq_dev_table[ENC_IRQ_NUM]; void irq_osdenc_enable(struct osdenc_device *p_osd,uint8 mode,uint8 irq){ struct hgosd *osd_hw = (struct hgosd*)p_osd; struct hgosdenc_hw *hw = (struct hgosdenc_hw *)osd_hw->hw; if(mode){ hw->OSD_ENC_CON |= BIT(irq+2); }else{ hw->OSD_ENC_CON &= ~BIT(irq+2); } } void OSD_ENC_IRQHandler_action(void *p_osd){ uint32 sta = 0; uint8 loop; struct hgosd *osd_hw = (struct hgosd*)p_osd; struct hgosdenc_hw *hw = (struct hgosdenc_hw *)osd_hw->hw; sta = hw->OSD_ENC_STA; for(loop = 0;loop < ENC_IRQ_NUM;loop++){ if(sta&BIT(loop)){ hw->OSD_ENC_STA = BIT(loop); if(encirq_vector_table[loop] != NULL) encirq_vector_table[loop] (loop,(uint32)encirq_dev_table[loop],0); } } } int32 osd_enc_irq_register(struct osdenc_device *p_osd,uint32 irq, osdenc_irq_hdl isr, uint32 dev_id){ struct hgosd *osd_hw = (struct hgosd*)p_osd; struct hgosdenc_hw *hw = (struct hgosdenc_hw *)osd_hw->hw; request_irq(osd_hw->irq_num, OSD_ENC_IRQHandler_action, p_osd); irq_osdenc_enable(p_osd, 1, irq); encirq_vector_table[irq] = isr; encirq_dev_table[irq] = (void*)dev_id; hw->OSD_ENC_STA |= BIT(irq); os_printf("osdencirq_register:%d %x %x\r\n",irq,(uint32)encirq_vector_table[irq],(uint32)isr); return 0; } int32 osd_enc_irq_unregister(struct osdenc_device *p_osd,uint32 irq){ struct hgosd *osd_hw = (struct hgosd*)p_osd; struct hgosdenc_hw *hw = (struct hgosdenc_hw *)osd_hw->hw; irq_osdenc_enable(p_osd, 0, irq); encirq_vector_table[irq] = NULL; encirq_dev_table[irq] = 0; hw->OSD_ENC_STA |= BIT(irq); return 0; } static int32 hgosdenc_open(struct osdenc_device *p_osd){ struct hgosd *osd_hw = (struct hgosd*)p_osd; //struct hgosdenc_hw *hw = (struct hgosdenc_hw *)osd_hw->hw; #ifdef FPGA_SUPPORT SYSCTRL->SYS_CON0 |= BIT(12); #else sysctrl_osd_enc_clk_open(); SYSCTRL->SYS_CON7 |= BIT(15); #endif irq_enable(osd_hw->irq_num); return 0; } static int32 hgosdenc_close(struct osdenc_device *p_osd){ struct hgosd *osd_hw = (struct hgosd*)p_osd; //struct hgosdenc_hw *hw = (struct hgosdenc_hw *)osd_hw->hw; sysctrl_osd_enc_clk_close(); irq_disable(osd_hw->irq_num); return 0; } int32 hgosdenc_suspend(struct dev_obj *obj){ struct hgosd *osd_hw = (struct hgosd*)obj; struct hgosdenc_hw *hw; struct hgosdenc_hw *hw_cfg; //确保已经被打开并且休眠过,直接返回 if(!osd_hw->opened || osd_hw->dsleep) { return RET_OK; } osd_hw->dsleep = 1; osd_hw->cfg_backup = (uint32 *)os_malloc(sizeof(struct hgosdenc_hw)); hw_cfg = (struct hgosdenc_hw*)osd_hw->cfg_backup; hw = (struct hgosdenc_hw*)osd_hw->hw; hw_cfg->OSD_ENC_CON=hw->OSD_ENC_CON; hw_cfg->OSD_ENC_STA=hw->OSD_ENC_STA; hw_cfg->OSD_ENC_SADR=hw->OSD_ENC_SADR; hw_cfg->OSD_ENC_TADR=hw->OSD_ENC_TADR; hw_cfg->OSD_ENC_RLEN=hw->OSD_ENC_RLEN; hw_cfg->OSD_ENC_DLEN=hw->OSD_ENC_DLEN; hw_cfg->OSD_ENC_IDENT0=hw->OSD_ENC_IDENT0; hw_cfg->OSD_ENC_IDENT1=hw->OSD_ENC_IDENT1; hw_cfg->OSD_ENC_TRANS0=hw->OSD_ENC_TRANS0; hw_cfg->OSD_ENC_TRANS1=hw->OSD_ENC_TRANS1; irq_disable(osd_hw->irq_num); return 0; } int32 hgosdenc_resume(struct dev_obj *obj){ struct hgosd *osd_hw = (struct hgosd*)obj; struct hgosdenc_hw *hw; struct hgosdenc_hw *hw_cfg; //如果已经被打开并且没有休眠过,直接返回 if(!osd_hw->opened || !osd_hw->dsleep) { return RET_OK; } osd_hw->dsleep = 0; hw_cfg = (struct hgosdenc_hw*)osd_hw->cfg_backup; hw = (struct hgosdenc_hw*)osd_hw->hw; hw->OSD_ENC_CON=hw_cfg->OSD_ENC_CON; hw->OSD_ENC_STA=hw_cfg->OSD_ENC_STA; hw->OSD_ENC_SADR=hw_cfg->OSD_ENC_SADR; hw->OSD_ENC_TADR=hw_cfg->OSD_ENC_TADR; hw->OSD_ENC_RLEN=hw_cfg->OSD_ENC_RLEN; hw->OSD_ENC_DLEN=hw_cfg->OSD_ENC_DLEN; hw->OSD_ENC_IDENT0=hw_cfg->OSD_ENC_IDENT0; hw->OSD_ENC_IDENT1=hw_cfg->OSD_ENC_IDENT1; hw->OSD_ENC_TRANS0=hw_cfg->OSD_ENC_TRANS0; hw->OSD_ENC_TRANS1=hw_cfg->OSD_ENC_TRANS1; irq_enable(osd_hw->irq_num); os_free(osd_hw->cfg_backup); return 0; } static const struct osdenc_hal_ops dev_ops = { .open = hgosdenc_open, .close = hgosdenc_close, .ioctl = hgosd_ioctl, .request_irq = osd_enc_irq_register, .release_irq = osd_enc_irq_unregister, #ifdef CONFIG_SLEEP .ops.suspend = hgosdenc_suspend, .ops.resume = hgosdenc_resume, #endif }; int32 hgosdenc_attach(uint32 dev_id, struct hgosd *hgosd){ hgosd->opened = 0; hgosd->use_dma = 0; hgosd->irq_hdl = NULL; hgosd->irq_data = 0; hgosd->dev.dev.ops = (const struct devobj_ops *)&dev_ops; irq_disable(hgosd->irq_num); dev_register(dev_id, (struct dev_obj *)hgosd); return 0; }