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

295 lines
6.7 KiB
C

#include "typesdef.h"
#include "errno.h"
#include "osal/irq.h"
#include "devid.h"
#include "dev/csi/hgdvp.h"
#include "osal/string.h"
struct hgdvp_hw
{
__IO uint32 CON;
__IO uint32 STA;
};
dvp_irq_hdl dvpirq_vector_table[DVP_IRQ_NUM];
volatile uint32 dvpirq_dev_table[DVP_IRQ_NUM];
static int32 hgdvp_ioctl(struct dvp_device *p_dvp, enum dvp_ioctl_cmd ioctl_cmd, uint32 param1, uint32 param2)
{
int32 ret_val = RET_OK;
//uint32 x_s,y_s,x_e,y_e;
//uint32 *size_array;
struct hgdvp *dvp_hw = (struct hgdvp*)p_dvp;
struct hgdvp_hw *hw = (struct hgdvp_hw *)dvp_hw->hw;
switch(ioctl_cmd){
case DVP_IOCTL_CMD_SET_FORMAT:
hw->CON &= ~(BIT(1));
if(param1 > 1){
os_printf("set FORMAT mode err\r\n");
return RET_ERR;
}
hw->CON |= param1<<1;
break;
case DVP_IOCTL_CMD_SET_HSYNC_VAILD:
if(param1)
hw->CON &= ~BIT(2);
else
hw->CON |= BIT(2);
break;
case DVP_IOCTL_CMD_SET_VSYNC_VAILD:
if(param1)
hw->CON &= ~BIT(3);
else
hw->CON |= BIT(3);
break;
case DVP_IOCTL_CMD_SET_DEBOUNCE:
if(param1){
hw->CON |= BIT(24);
hw->CON &=~(BIT(25)|BIT(26));
hw->CON |=(param2<<25);
}
else
hw->CON &= ~BIT(29);
break;
case DVP_IOCTL_CMD_EX_D5_D6:
if(param1 == 0)
hw->CON &= ~BIT(16);
else
hw->CON |= BIT(16);
break;
case DVP_IOCTL_CMD_SET_SCEN:
if(param1 == 0)
hw->CON &= ~BIT(4);
else
hw->CON |= BIT(4);
break;
default:
os_printf("NO DVP IOCTL:%d\r\n",ioctl_cmd);
ret_val = -ENOTSUPP;
break;
}
return ret_val;
}
void DVP_IRQHandler_action(void *p_dvp)
{
uint32 sta = 0;
uint8 loop;
struct hgdvp *dvp_hw = (struct hgdvp*)p_dvp;
struct hgdvp_hw *hw = (struct hgdvp_hw *)dvp_hw->hw;
sta = hw->STA;
for(loop = 0;loop < DVP_IRQ_NUM;loop++){
if(sta&BIT(loop)){
hw->STA = BIT(loop);
if(dvpirq_vector_table[loop] != NULL)
dvpirq_vector_table[loop] (loop,dvpirq_dev_table[loop],0);
}
}
}
void irq_dvp_enable(struct dvp_device *p_dvp,uint8 mode,uint8 irq){
struct hgdvp *dvp_hw = (struct hgdvp*)p_dvp;
struct hgdvp_hw *hw = (struct hgdvp_hw *)dvp_hw->hw;
if(mode){
hw->CON |= BIT(irq+8);
}else{
hw->CON &= ~BIT(irq+8);
}
}
int32 dvpirq_register(struct dvp_device *p_dvp,uint32 irq, dvp_irq_hdl isr, uint32 dev_id){
struct hgdvp *dvp_hw = (struct hgdvp*)p_dvp;
struct hgdvp_hw *hw = (struct hgdvp_hw *)dvp_hw->hw;
request_irq(dvp_hw->irq_num, DVP_IRQHandler_action, p_dvp);
irq_dvp_enable(p_dvp, 1, irq);
dvpirq_vector_table[irq] = isr;
dvpirq_dev_table[irq] = dev_id;
hw->STA |= BIT(irq);
os_printf("dvpirq_register:%d %x %x\r\n",irq,(uint32)dvpirq_vector_table[irq],(uint32)isr);
return 0;
}
int32 dvpirq_unregister(struct dvp_device *p_dvp,uint32 irq){
struct hgdvp *dvp_hw = (struct hgdvp*)p_dvp;
struct hgdvp_hw *hw = (struct hgdvp_hw *)dvp_hw->hw;
irq_dvp_enable(p_dvp, 0, irq);
dvpirq_vector_table[irq] = NULL;
dvpirq_dev_table[irq] = 0;
hw->STA |= BIT(irq);
return 0;
}
static int32 hgdvp_open(struct dvp_device *p_dvp){
struct hgdvp *dvp_hw = (struct hgdvp*)p_dvp;
struct hgdvp_hw *hw = (struct hgdvp_hw *)dvp_hw->hw;
hw->CON |= BIT(0);
dvp_hw->opened = 1;
dvp_hw->dsleep = 0;
irq_enable(dvp_hw->irq_num);
return 0;
}
static int32 hgdvp_close(struct dvp_device *p_dvp){
struct hgdvp *dvp_hw = (struct hgdvp*)p_dvp;
struct hgdvp_hw *hw = (struct hgdvp_hw *)dvp_hw->hw;
hw->CON &= ~BIT(0);
dvp_hw->opened = 0;
dvp_hw->dsleep = 0;
irq_disable(dvp_hw->irq_num);
_os_printf("hgdvp_close...............................................................\r\n");
return 0;
}
int32 hgdvp_suspend(struct dev_obj *obj){
struct hgdvp *dvp_hw = (struct hgdvp*)obj;
struct hgdvp_hw *hw;
struct hgdvp_hw *hw_cfg;
//确保已经被打开并且休眠过,直接返回
if(!dvp_hw->opened || dvp_hw->dsleep)
{
return RET_OK;
}
dvp_hw->dsleep = 1;
dvp_hw->cfg_backup = (uint32 *)os_malloc(sizeof(struct hgdvp_hw));
//memcpy((uint8 *)p_jpg->cfg_backup,(uint8 *)jpg_hw->hw,sizeof(struct hgjpg_hw));
hw_cfg = (struct hgdvp_hw*)dvp_hw->cfg_backup;
hw = (struct hgdvp_hw*)dvp_hw->hw;
//hw_cfg->CSR0 = hw->CSR0;
hw_cfg->CON = hw->CON;
hw_cfg->STA = hw->STA;
irq_disable(dvp_hw->irq_num);
return 0;
}
int32 hgdvp_resume(struct dev_obj *obj){
struct hgdvp *dvp_hw = (struct hgdvp*)obj;
struct hgdvp_hw *hw;
struct hgdvp_hw *hw_cfg;
//如果已经被打开并且没有休眠过,直接返回
if(!dvp_hw->opened || !dvp_hw->dsleep)
{
return RET_OK;
}
dvp_hw->dsleep = 0;
hw_cfg = (struct hgdvp_hw*)dvp_hw->cfg_backup;
hw = (struct hgdvp_hw*)dvp_hw->hw;
//hw->CSR0 = hw_cfg->CSR0;
hw->CON = hw_cfg->CON;
hw->STA = hw_cfg->STA;
irq_enable(dvp_hw->irq_num);
os_free(dvp_hw->cfg_backup);
return 0;
}
static int32 hgdvp_init(struct dvp_device *p_dvp){
// struct hgdvp *dvp_hw = (struct hgdvp*)p_dvp;
#ifdef FPGA_SUPPORT
SYSCTRL->CLK_CON2 |= BIT(31);
SYSCTRL->SYS_CON1 |= BIT(28);
SYSCTRL->CLK_CON1 &= ~(BIT(27)|BIT(28));
SYSCTRL->CLK_CON1 |= BIT(28);
#else
SYSCTRL->CLK_CON2 |= BIT(31);
SYSCTRL->SYS_CON1 |= BIT(28);
SYSCTRL->CLK_CON1 &= ~(BIT(27)|BIT(28));
SYSCTRL->CLK_CON1 |= BIT(28);
#endif
pin_func(HG_DVP_DEVID,1);
return 0;
}
static int32 hgdvp_set_baudrate(struct dvp_device *p_dvp,uint32 baudrate){
//struct hgdvp_hw *hw = (struct hgdvp_hw *)dvp_hw->hw;
uint8 m_cfg = 0;
#if defined(FPGA_SUPPORT)
m_cfg = 240000000/baudrate - 1;
#else
if(baudrate != 0)
m_cfg = (peripheral_clock_get(HG_APB0_PT_DVP))/baudrate - 1;
else
m_cfg = 0x3f;
#endif
_os_printf("%s:clock:%d\n",__FUNCTION__,peripheral_clock_get(HG_APB0_PT_DVP));
SYSCTRL->SYS_KEY = 0x3fac87e4;
SYSCTRL->CLK_CON3 &= ~(0x3f<<26);
SYSCTRL->CLK_CON3 |= ((m_cfg&0x3f)<<26);
if(m_cfg&0x40){
SYSCTRL->SYS_CON3 |= BIT(26);
}else
{
SYSCTRL->SYS_CON3 &= ~BIT(26);
}
if(m_cfg&0x80){
SYSCTRL->SYS_CON3 |= BIT(2);
}else
{
SYSCTRL->SYS_CON3 &= ~BIT(2);
}
SYSCTRL->SYS_KEY = 0;
//vsync低有效 hsync高有效
//hw->CON = BIT(11); //
return 0;
}
static const struct dvp_hal_ops dev_ops = {
.init = hgdvp_init,
.baudrate = hgdvp_set_baudrate,
.open = hgdvp_open,
.close = hgdvp_close,
.ioctl = hgdvp_ioctl,
.request_irq = dvpirq_register,
.release_irq = dvpirq_unregister,
#ifdef CONFIG_SLEEP
.ops.suspend = hgdvp_suspend,
.ops.resume = hgdvp_resume,
#endif
};
int32 hgdvp_attach(uint32 dev_id, struct hgdvp *dvp){
dvp->opened = 0;
dvp->use_dma = 0;
dvp->irq_hdl = NULL;
//memset(dvp->irq_hdl,0,sizeof(dvp->irq_hdl));
dvp->irq_data = 0;
//memset(dvp->irq_data,0,sizeof(dvp->irq_data));
dvp->dev.dev.ops = (const struct devobj_ops *)&dev_ops;
irq_disable(dvp->irq_num);
dev_register(dev_id, (struct dev_obj *)dvp);
return 0;
}