Files
2025-08-27 09:51:58 +01:00

212 lines
4.7 KiB
C

#include "typesdef.h"
#include "errno.h"
#include "osal/irq.h"
#include "devid.h"
#include "dev/prc/hgprc.h"
#include "osal/string.h"
struct hgprc_hw
{
__IO uint32 CON;
__IO uint32 STA;
__IO uint32 SADR;
__IO uint32 YADR;
__IO uint32 UADR;
__IO uint32 VADR;
};
prc_irq_hdl prcirq_vector_table[PRC_IRQ_NUM];
volatile uint32 prcirq_dev_table[PRC_IRQ_NUM];
static int32 hgprc_ioctl(struct prc_device *p_prc, enum prc_ioctl_cmd ioctl_cmd, uint32 param1, uint32 param2){
int32 ret_val = RET_OK;
struct hgprc *prc_hw = (struct hgprc*)p_prc;
struct hgprc_hw *hw = (struct hgprc_hw *)prc_hw->hw;
switch(ioctl_cmd){
case PRC_IOCTL_CMD_SET_WIDTH:
hw->CON &= ~((0x7ff)<<16);
hw->CON |= ((param1)<<16);
break;
case PRC_IOCTL_CMD_SET_YUV_MODE:
hw->CON &= ~((0x3)<<2);
hw->CON |= ((param1)<<2);
break;
case PRC_IOCTL_CMD_SET_Y_ADDR:
hw->YADR = param1;
break;
case PRC_IOCTL_CMD_SET_U_ADDR:
hw->UADR = param1;
break;
case PRC_IOCTL_CMD_SET_V_ADDR:
hw->VADR = param1;
break;
case PRC_IOCTL_CMD_SET_SRC_ADDR:
hw->SADR = param1;
break;
case PRC_IOCTL_CMD_KICK:
hw->CON |= BIT(1); //enable prc
hw->CON |= BIT(0);
break;
default:
os_printf("NO PRC IOCTL:%d\r\n",ioctl_cmd);
ret_val = -ENOTSUPP;
break;
}
return ret_val;
}
void PRC_IRQHandler_action(void *p_prc)
{
uint32 sta = 0;
uint8 loop;
struct hgprc *prc_hw = (struct hgprc*)p_prc;
struct hgprc_hw *hw = (struct hgprc_hw *)prc_hw->hw;
sta = hw->STA;
for(loop = 0;loop < PRC_IRQ_NUM;loop++){
if(sta&BIT(loop)){
hw->STA = BIT(loop);
if(prcirq_vector_table[loop] != NULL)
prcirq_vector_table[loop] (loop,prcirq_dev_table[loop],0);
}
}
}
void irq_prc_enable(struct prc_device *p_prc,uint8 mode,uint8 irq){
struct hgprc *prc_hw = (struct hgprc*)p_prc;
struct hgprc_hw *hw = (struct hgprc_hw *)prc_hw->hw;
if(mode){
hw->CON |= BIT(irq+8);
}else{
hw->CON &= ~BIT(irq+8);
}
}
int32 prcirq_register(struct prc_device *p_prc,uint32 irq, prc_irq_hdl isr, uint32 dev_id){
struct hgprc *prc_hw = (struct hgprc*)p_prc;
struct hgprc_hw *hw = (struct hgprc_hw *)prc_hw->hw;
request_irq(prc_hw->irq_num, PRC_IRQHandler_action, p_prc);
irq_prc_enable(p_prc, 1, irq);
irq_enable(prc_hw->irq_num);
prcirq_vector_table[irq] = isr;
prcirq_dev_table[irq] = dev_id;
hw->STA |= BIT(irq);
return 0;
}
int32 prcirq_unregister(struct prc_device *p_prc,uint32 irq){
struct hgprc *prc_hw = (struct hgprc*)p_prc;
struct hgprc_hw *hw = (struct hgprc_hw *)prc_hw->hw;
irq_prc_enable(p_prc, 0, irq);
prcirq_vector_table[irq] = NULL;
prcirq_dev_table[irq] = 0;
hw->STA |= BIT(irq);
return 0;
}
static int32 hgprc_init(struct prc_device *p_prc){
int32 ret_val = RET_OK;
struct hgprc *prc_hw = (struct hgprc*)p_prc;
struct hgprc_hw *hw = (struct hgprc_hw *)prc_hw->hw;
prc_hw->opened = 1;
prc_hw->dsleep = 0;
hw->CON = 0;
hw->SADR = 0;
hw->YADR = 0;
hw->UADR = 0;
hw->VADR = 0;
return ret_val;
}
int32 hgprc_suspend(struct dev_obj *obj){
struct hgprc *prc_hw = (struct hgprc*)obj;
struct hgprc_hw *hw;
struct hgprc_hw *hw_cfg;
//确保已经被打开并且休眠过,直接返回
if(!prc_hw->opened || prc_hw->dsleep)
{
return RET_OK;
}
prc_hw->dsleep = 1;
prc_hw->cfg_backup = (uint32 *)os_malloc(sizeof(struct hgprc_hw));
hw_cfg = (struct hgprc_hw*)prc_hw->cfg_backup;
hw = (struct hgprc_hw*)prc_hw->hw;
hw_cfg->CON = hw->CON;
hw_cfg->STA = hw->STA;
hw_cfg->SADR = hw->SADR;
hw_cfg->YADR = hw->YADR;
hw_cfg->UADR = hw->UADR;
hw_cfg->VADR = hw->VADR;
irq_disable(prc_hw->irq_num);
return 0;
}
int32 hgprc_resume(struct dev_obj *obj){
struct hgprc *prc_hw = (struct hgprc*)obj;
struct hgprc_hw *hw;
struct hgprc_hw *hw_cfg;
//如果已经被打开并且没有休眠过,直接返回
if(!prc_hw->opened || !prc_hw->dsleep)
{
return RET_OK;
}
prc_hw->dsleep = 0;
hw_cfg = (struct hgprc_hw*)prc_hw->cfg_backup;
hw = (struct hgprc_hw*)prc_hw->hw;
//hw->CSR0 = hw_cfg->CSR0;
hw->CON = hw_cfg->CON;
hw->STA = hw_cfg->STA;
hw->SADR = hw_cfg->SADR;
hw->YADR = hw_cfg->YADR;
hw->UADR = hw_cfg->UADR;
hw->VADR = hw_cfg->VADR;
irq_enable(prc_hw->irq_num);
os_free(prc_hw->cfg_backup);
return 0;
}
static const struct prc_hal_ops dev_ops = {
.init = hgprc_init,
.ioctl = hgprc_ioctl,
.request_irq = prcirq_register,
.release_irq = prcirq_unregister,
#ifdef CONFIG_SLEEP
.ops.suspend = hgprc_suspend,
.ops.resume = hgprc_resume,
#endif
};
void hgprc_attach(uint32 dev_id, struct hgprc *prc)
{
prc->dev.dev.ops = (const struct devobj_ops *)&dev_ops;
irq_disable(prc->irq_num);
dev_register(dev_id, (struct dev_obj *)prc);
}