295 lines
6.7 KiB
C
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;
|
|
}
|
|
|
|
|