#include "typesdef.h" #include "errno.h" #include "osal/irq.h" #include "devid.h" #include "dev/scale/hgscale.h" #include "osal/string.h" #include "osal/sleep.h" uint32_t in_disable_irq(void); struct hgscale1_hw { __IO uint32 SCALECON; //0x00 __IO uint32 SWINCON; //0x04 __IO uint32 SSTART; __IO uint32 TWINCON; //0x08 __IO uint32 SWIDTH_STEP; //0x0C __IO uint32 SHEIGH_STEP; //0x10 __IO uint32 INBUF_LINE_NUM; //0x14 __IO uint32 INYDMA_STADR; //0x18 __IO uint32 INUDMA_STADR; //0x1C __IO uint32 INVDMA_STADR; //0x20 __IO uint32 INBUFCON; //0x24 __IO uint32 SHEIGH_CNT; //0x28 __IO uint32 SCALESTA; //0x2C }; struct hgscale2_hw { __IO uint32 SCALECON; //0x00 __IO uint32 SWINCON; //0x04 __IO uint32 SSTART; //0x08 __IO uint32 TWINCON; //0x0C __IO uint32 SWIDTH_STEP; //0x10 __IO uint32 SHEIGH_STEP; //0x14 __IO uint32 YSRAMBUF_STADR; //0x18 __IO uint32 USRAMBUF_STADR; //0x18 __IO uint32 VSRAMBUF_STADR; //0x18 __IO uint32 INYDMA_STADR; //0x1C __IO uint32 INUDMA_STADR; //0x20 __IO uint32 INVDMA_STADR; //0x24 __IO uint32 OUTYDMA_STADR; //0x1C __IO uint32 OUTUDMA_STADR; //0x20 __IO uint32 OUTVDMA_STADR; //0x24 __IO uint32 SHEIGH_CNT; //0x28 __IO uint32 SCALESTA; //0x2C }; struct hgscale3_hw { __IO uint32 SCALECON; //0x00 __IO uint32 SWINCON; //0x04 __IO uint32 SSTART; //0x08 __IO uint32 TWINCON; //0x0C __IO uint32 SWIDTH_STEP; //0x10 __IO uint32 SHEIGH_STEP; //0x14 __IO uint32 INBUF_LINE_NUM; //0x18 __IO uint32 INYDMA_STADR; //0x1C __IO uint32 INUDMA_STADR; //0x20 __IO uint32 INVDMA_STADR; //0x24 __IO uint32 OUTYDMA_STADR; //0x28 __IO uint32 OUTUDMA_STADR; //0x2C __IO uint32 OUTVDMA_STADR; //0x30 __IO uint32 INBUFCON; //0x34 __IO uint32 SHEIGH_CNT; //0x38 __IO uint32 SCALESTA; //0x3C }; scale_irq_hdl scaleirq1_vector_table[SCALE_IRQ_NUM]; volatile uint32 scaleirq1_dev_table[SCALE_IRQ_NUM]; scale_irq_hdl scaleirq2_vector_table[SCALE_IRQ_NUM]; volatile uint32 scaleirq2_dev_table[SCALE_IRQ_NUM]; scale_irq_hdl scaleirq3_vector_table[SCALE_IRQ_NUM]; volatile uint32 scaleirq3_dev_table[SCALE_IRQ_NUM]; extern volatile uint8 isp_ov_err; extern volatile uint8 scaler3_lost; static int32 hgscale1_ioctl(struct scale_device *p_scale, enum scale_ioctl_cmd ioctl_cmd, uint32 param1, uint32 param2) { int32 ret_val = RET_OK; uint32 s_w,s_h,d_w,d_h; uint32 s_x,s_y; struct hgscale *scale_hw = (struct hgscale*)p_scale; struct hgscale1_hw *hw = (struct hgscale1_hw *)scale_hw->hw; if(scale_hw->clk_en == 0){ scale_hw->clk_en = 1; if((SYSCTRL->CLK_CON4 & BIT(29)) == 0){ //lcd clk not open SYSCTRL->CLK_CON4 |= BIT(29); //lcdc clk en SYSCTRL->CLK_CON4 &= ~BIT(30); SYSCTRL->CLK_CON4 |= BIT(30); //lcdc rest *(volatile uint32_t*)0x400070d4 |= BIT(1); //scale1 clk enable }else{ *(volatile uint32_t*)0x400070d4 |= BIT(1); //scale1 clk enable } } switch(ioctl_cmd){ case SCALE_IOCTL_CMD_SET_IN_OUT_SIZE: s_w = param1 & 0xffff; s_h = (param1>>16) & 0xffff; d_w = param2 & 0xffff; d_h = (param2>>16) & 0xffff; hw->SWINCON = (s_w-1)|((s_h-1)<<16); hw->TWINCON = (d_w-1)|((d_h-1)<<16); break; case SCALE_IOCTL_CMD_GET_INPUT_WIDTH: ret_val = (hw->SWINCON & 0xffff)+1; break; case SCALE_IOCTL_CMD_GET_INPUT_HIGH: ret_val = ((hw->SWINCON & 0xffff0000)>>16)+1; break; case SCALE_IOCTL_CMD_SET_STEP: s_w = param1 & 0xffff; s_h = (param1>>16) & 0xffff; d_w = param2 & 0xffff; d_h = (param2>>16) & 0xffff; hw->SWIDTH_STEP = 256*s_w/d_w; hw->SHEIGH_STEP = 256*s_h/d_h; break; case SCALE_IOCTL_CMD_SET_START_ADDR: s_x = param1 & 0xffff; s_y = (param1>>16) & 0xffff; hw->SSTART = (s_x) |(s_y<<16); break; case SCALE_IOCTL_CMD_SET_LINE_BUF_NUM: hw->INBUF_LINE_NUM = param1; break; case SCALE_IOCTL_CMD_SET_IN_Y_ADDR: hw->INYDMA_STADR = param1; break; case SCALE_IOCTL_CMD_SET_IN_U_ADDR: hw->INUDMA_STADR = param1; break; case SCALE_IOCTL_CMD_SET_IN_V_ADDR: hw->INVDMA_STADR = param1; break; case SCALE_IOCTL_CMD_SET_BOTH_MJPG_H264: if(param1) hw->SCALECON |= BIT(3); //both mjpg and h264 else hw->SCALECON &= ~BIT(3); // break; case SCALE_IOCTL_CMD_SET_DATA_FROM: if(param1) hw->SCALECON &=~BIT(2); //vpp else hw->SCALECON |= BIT(2); //soft break; case SCALE_IOCTL_CMD_GET_INBUF_NUM: ret_val = (hw->INBUFCON>>16)&0x3ff; break; case SCALE_IOCTL_CMD_SET_INBUF_NUM: hw->INBUFCON = ((param1)<<16)|(param2); break; case SCALE_IOCTL_CMD_SET_NEW_FRAME: hw->INBUFCON |= BIT(15); break; case SCALE_IOCTL_CMD_SET_END_FRAME: hw->INBUFCON |= BIT(31); break; case SCALE_IOCTL_CMD_GET_HEIGH_CNT: ret_val = hw->SHEIGH_CNT; break; case SCALE_IOCTL_CMD_GET_IS_OPEN: if(scale_hw->clk_en){ //判断scaler是否启动在运行 ret_val = 1; }else{ ret_val = 0; } break; default: os_printf("NO SCALE1 IOCTL:%d\r\n",ioctl_cmd); ret_val = -ENOTSUPP; break; } return ret_val; } static int32 hgscale2_ioctl(struct scale_device *p_scale, enum scale_ioctl_cmd ioctl_cmd, uint32 param1, uint32 param2) { int32 ret_val = RET_OK; uint32 s_w,s_h,d_w,d_h; uint32 s_x,s_y; uint32 *param_buf; struct hgscale *scale_hw = (struct hgscale*)p_scale; struct hgscale2_hw *hw = (struct hgscale2_hw *)scale_hw->hw; if(scale_hw->clk_en == 0){ scale_hw->clk_en = 1; if((SYSCTRL->CLK_CON4 & BIT(29)) == 0){ //lcd clk not open SYSCTRL->CLK_CON4 |= BIT(29); //lcdc clk en SYSCTRL->CLK_CON4 &= ~BIT(30); SYSCTRL->CLK_CON4 |= BIT(30); //lcdc rest *(volatile uint32_t*)0x400070d4 |= BIT(2); //scale2 clk enable }else{ *(volatile uint32_t*)0x400070d4 |= BIT(2); //scale2 clk enable } } switch(ioctl_cmd){ case SCALE_IOCTL_CMD_SET_IN_OUT_SIZE: s_w = param1 & 0xffff; s_h = (param1>>16) & 0xffff; d_w = param2 & 0xffff; d_h = (param2>>16) & 0xffff; hw->SWINCON = (s_w-1)|((s_h-1)<<16); hw->TWINCON = (d_w-1)|((d_h-1)<<16); break; case SCALE_IOCTL_CMD_GET_INPUT_WIDTH: ret_val = (hw->SWINCON & 0xffff)+1; break; case SCALE_IOCTL_CMD_GET_INPUT_HIGH: ret_val = ((hw->SWINCON & 0xffff0000)>>16)+1; break; case SCALE_IOCTL_CMD_SET_STEP: s_w = param1 & 0xffff; s_h = (param1>>16) & 0xffff; d_w = param2 & 0xffff; d_h = (param2>>16) & 0xffff; hw->SWIDTH_STEP = 256*s_w/d_w; hw->SHEIGH_STEP = 256*s_h/d_h; break; case SCALE_IOCTL_CMD_INPUT_STREAM: hw->SCALECON &= ~(7<<1); hw->SCALECON |= (param1<<1); //0:jpg decoder //1:h264 decoder //memory frame buf yuv420 //memory frame buf yuv422 //memory frame buf yuv444 //memory frame buf rgb888 break; case SCALE_IOCTL_CMD_SET_NEW_FRAME: hw->SCALECON |= BIT(15); break; case SCALE_IOCTL_CMD_SET_LINE_BUF_NUM: hw->SCALECON &= ~(BIT(7)|BIT(8)); //line 16 if(param1 == 32){ hw->SCALECON |= BIT(7); }else if(param1 == 64){ hw->SCALECON |= BIT(8); }else if(param1 == 128){ hw->SCALECON |= (BIT(7)|BIT(8)); } break; case SCALE_IOCTL_CMD_OUT2SRAM_FRAME: if(param1 == 1){ hw->SCALECON &= ~BIT(6); //line buf }else{ hw->SCALECON |= BIT(6); //frame } break; case SCALE_IOCTL_CMD_SRAM_ROTATE: hw->SCALECON &= ~(BIT(9)|BIT(10)); //rotate 0 if(param1 == 1){ hw->SCALECON |= BIT(9); //rotate 90 }else if(param1 == 2){ hw->SCALECON |= BIT(10); //rotate 180 }else if(param1 == 3){ hw->SCALECON |= (BIT(9)|BIT(10)); //rotate 270 } break; case SCALE_IOCTL_CMD_SRAM_MIRROR: if(param1 == 0){ hw->SCALECON &= ~BIT(11); //no mirror }else{ hw->SCALECON |= BIT(11); //mirror } break; case SCALE_IOCTL_CMD_PSRAM_BURST: hw->SCALECON &= ~(BIT(12)|BIT(13)); //8 word if(param1 == 16){ hw->SCALECON |= BIT(12); //16 word }else if(param1 == 32){ hw->SCALECON |= BIT(13); //32 word }else if(param1 == 64){ hw->SCALECON |= (BIT(12)|BIT(13));//64 word } break; case SCALE_IOCTL_CMD_SET_START_ADDR: s_x = param1 & 0xffff; s_y = (param1>>16) & 0xffff; hw->SSTART = (s_x) |(s_y<<16); break; case SCALE_IOCTL_CMD_SET_SRAMBUF_WLEN: hw->SCALECON &= ~(BIT(4)|BIT(5)); if(param1 == 64){ hw->SCALECON |= BIT(4); }else if(param1 == 256){ hw->SCALECON |= BIT(5); }else if(param1 == 512){ hw->SCALECON |= (BIT(4)|BIT(5)); } break; case SCALE_IOCTL_CMD_SET_IN_Y_ADDR: hw->INYDMA_STADR = param1; break; case SCALE_IOCTL_CMD_SET_IN_U_ADDR: hw->INUDMA_STADR = param1; break; case SCALE_IOCTL_CMD_SET_IN_V_ADDR: hw->INVDMA_STADR = param1; break; case SCALE_IOCTL_CMD_SET_OUT_Y_ADDR: hw->OUTYDMA_STADR = param1; break; case SCALE_IOCTL_CMD_SET_OUT_U_ADDR: hw->OUTUDMA_STADR = param1; break; case SCALE_IOCTL_CMD_SET_OUT_V_ADDR: hw->OUTVDMA_STADR = param1; break; case SCALE_IOCTL_CMD_SET_LINEBUF_YUV_ADDR: param_buf = (uint32*)param1; //printf("YUV:%08x %08x %08x\r\n",param_buf[0],param_buf[1],param_buf[2]); hw->YSRAMBUF_STADR = param_buf[0]; hw->USRAMBUF_STADR = param_buf[1]; hw->VSRAMBUF_STADR = param_buf[2]; break; case SCALE_IOCTL_CMD_SET_INBUF_YUV_ADDR: param_buf = (uint32*)param1; hw->INYDMA_STADR = param_buf[0]; hw->INUDMA_STADR = param_buf[1]; hw->INVDMA_STADR = param_buf[2]; break; case SCALE_IOCTL_CMD_GET_HEIGH_CNT: ret_val = hw->SHEIGH_CNT; break; case SCALE_IOCTL_CMD_GET_IS_OPEN: if(scale_hw->clk_en){ //判断scaler是否启动在运行 ret_val = 1; }else{ ret_val = 0; } break; default: os_printf("NO SCALE2 IOCTL:%d\r\n",ioctl_cmd); ret_val = -ENOTSUPP; break; } return ret_val; } static int32 hgscale3_ioctl(struct scale_device *p_scale, enum scale_ioctl_cmd ioctl_cmd, uint32 param1, uint32 param2) { int32 ret_val = RET_OK; uint32 s_w,s_h,d_w,d_h; uint32 s_x,s_y; // uint32 *size_array; struct hgscale *scale_hw = (struct hgscale*)p_scale; struct hgscale3_hw *hw = (struct hgscale3_hw *)scale_hw->hw; if(scale_hw->clk_en == 0){ scale_hw->clk_en = 1; if((SYSCTRL->CLK_CON4 & BIT(29)) == 0){ //lcd clk not open SYSCTRL->CLK_CON4 |= BIT(29); //lcdc clk en SYSCTRL->CLK_CON4 &= ~BIT(30); SYSCTRL->CLK_CON4 |= BIT(30); //lcdc rest *(volatile uint32_t*)0x400070d4 |= BIT(3); //scale3 clk enable }else{ *(volatile uint32_t*)0x400070d4 |= BIT(3); //scale3 clk enable } } switch(ioctl_cmd){ case SCALE_IOCTL_CMD_SET_IN_OUT_SIZE: s_w = param1 & 0xffff; s_h = (param1>>16) & 0xffff; d_w = param2 & 0xffff; d_h = (param2>>16) & 0xffff; hw->SWINCON = (s_w-1)|((s_h-1)<<16); hw->TWINCON = (d_w-1)|((d_h-1)<<16); break; case SCALE_IOCTL_CMD_GET_INPUT_WIDTH: ret_val = (hw->SWINCON & 0xffff)+1; break; case SCALE_IOCTL_CMD_GET_INPUT_HIGH: ret_val = ((hw->SWINCON & 0xffff0000)>>16)+1; break; case SCALE_IOCTL_CMD_SET_STEP: s_w = param1 & 0xffff; s_h = (param1>>16) & 0xffff; d_w = param2 & 0xffff; d_h = (param2>>16) & 0xffff; //printf("s:%d %d d:%d %d \r\n",s_w,s_h,d_w,d_h); hw->SWIDTH_STEP = 256*s_w/d_w; hw->SHEIGH_STEP = 256*s_h/d_h; break; case SCALE_IOCTL_CMD_SET_START_ADDR: s_x = param1 & 0xffff; s_y = (param1>>16) & 0xffff; hw->SSTART = (s_x) |(s_y<<16); break; case SCALE_IOCTL_CMD_SET_LINE_BUF_NUM: hw->INBUF_LINE_NUM = param1; break; case SCALE_IOCTL_CMD_SET_IN_Y_ADDR: hw->INYDMA_STADR = param1; break; case SCALE_IOCTL_CMD_SET_IN_U_ADDR: hw->INUDMA_STADR = param1; break; case SCALE_IOCTL_CMD_SET_IN_V_ADDR: hw->INVDMA_STADR = param1; break; case SCALE_IOCTL_CMD_SET_OUT_Y_ADDR: hw->OUTYDMA_STADR = param1; //printf("YO:%08x %08x\r\n",hw->OUTYDMA_STADR,param1); //if(param1 < 0x20000000){ // hw->SCALECON &= ~BIT(0); //disable // __BKPT(); //} break; case SCALE_IOCTL_CMD_SET_OUT_U_ADDR: hw->OUTUDMA_STADR = param1; //printf("UO:%08x %08x\r\n",hw->OUTYDMA_STADR,param1); break; case SCALE_IOCTL_CMD_SET_OUT_V_ADDR: hw->OUTVDMA_STADR = param1; //printf("VO:%08x %08x\r\n",hw->OUTYDMA_STADR,param1); break; case SCALE_IOCTL_CMD_SET_OUTPUT_FORMAT: if(param1 == 0){ hw->SCALECON &= ~BIT(5); //yuv420p }else{ hw->SCALECON |= BIT(5); //rgb888p } break; case SCALE_IOCTL_CMD_SET_INPUT_IS_FRAMEBUF: if(param1 == 0){ hw->SCALECON &= ~BIT(4); //line buf }else{ hw->SCALECON |= BIT(4); //all frame } break; case SCALE_IOCTL_CMD_SET_INPUT_FORMAT: if(param1 == 0){ hw->SCALECON &= ~BIT(3); //YUV420P }else{ hw->SCALECON |= BIT(3); //RGB888p } break; case SCALE_IOCTL_CMD_DMA_TO_MEMORY: if(param1){ hw->SCALECON |= BIT(1); }else{ hw->SCALECON &= ~BIT(1); } break; case SCALE_IOCTL_CMD_SET_DATA_FROM: if(param1) hw->SCALECON &=~BIT(2); //vpp else hw->SCALECON |= BIT(2); //soft break; case SCALE_IOCTL_CMD_GET_INBUF_NUM: ret_val = (hw->INBUFCON>>16)&0x3ff; break; case SCALE_IOCTL_CMD_SET_INBUF_NUM: //os_printf("set inbuf_num:%d %d\r\n",param1,param2); hw->INBUFCON = ((param1)<<16)|(param2); break; case SCALE_IOCTL_CMD_SET_NEW_FRAME: hw->INBUFCON |= BIT(15); break; case SCALE_IOCTL_CMD_SET_END_FRAME: hw->INBUFCON |= BIT(31); break; case SCALE_IOCTL_CMD_GET_HEIGH_CNT: ret_val = hw->SHEIGH_CNT; break; case SCALE_IOCTL_CMD_GET_IS_OPEN: if(scale_hw->clk_en){ //判断scaler是否启动在运行 ret_val = 1; }else{ ret_val = 0; } break; default: os_printf("NO SCALE3 IOCTL:%d\r\n",ioctl_cmd); ret_val = -ENOTSUPP; break; } return ret_val; } void irq_scale1_enable(struct scale_device *p_scale,uint8 mode,uint8 irq){ struct hgscale *scale_hw = (struct hgscale*)p_scale; struct hgscale1_hw *hw = (struct hgscale1_hw *)scale_hw->hw; if(mode){ hw->SCALECON |= BIT(irq+16); }else{ hw->SCALECON &= ~BIT(irq+16); } } void irq_scale2_enable(struct scale_device *p_scale,uint8 mode,uint8 irq){ struct hgscale *scale_hw = (struct hgscale*)p_scale; struct hgscale2_hw *hw = (struct hgscale2_hw *)scale_hw->hw; if(mode){ hw->SCALECON |= BIT(irq+16); }else{ hw->SCALECON &= ~BIT(irq+16); } } void irq_scale3_enable(struct scale_device *p_scale,uint8 mode,uint8 irq){ struct hgscale *scale_hw = (struct hgscale*)p_scale; struct hgscale3_hw *hw = (struct hgscale3_hw *)scale_hw->hw; if(mode){ hw->SCALECON |= BIT(irq+16); }else{ hw->SCALECON &= ~BIT(irq+16); } } void SCALE1_IRQHandler_action(void *p_scale) { uint32 sta = 0; uint8 loop; struct hgscale *scale_hw = (struct hgscale*)p_scale; struct hgscale1_hw *hw = (struct hgscale1_hw *)scale_hw->hw; sta = hw->SCALESTA; for(loop = 0;loop < SCALE_IRQ_NUM;loop++){ if(sta&BIT(loop)){ hw->SCALESTA = BIT(loop); if(scaleirq1_vector_table[loop] != NULL) scaleirq1_vector_table[loop] (loop,scaleirq1_dev_table[loop],0); } } if(scale_hw->need_close) { hw->SCALECON &= ~BIT(0); //disable scale_hw->need_close = 0; } } int32 scaleirq1_register(struct scale_device *p_scale,uint32 irq, scale_irq_hdl isr, uint32 dev_id){ struct hgscale *scale_hw = (struct hgscale*)p_scale; struct hgscale1_hw *hw = (struct hgscale1_hw *)scale_hw->hw; request_irq(scale_hw->irq_num, SCALE1_IRQHandler_action, p_scale); irq_scale1_enable(p_scale, 1, irq); scaleirq1_vector_table[irq] = isr; scaleirq1_dev_table[irq] = dev_id; hw->SCALESTA |= BIT(irq); os_printf("scaleirq1_register:%d %x %x\r\n",irq,(uint32)scaleirq1_vector_table[irq],(uint32)isr); return 0; } int32 scaleirq1_unregister(struct scale_device *p_scale,uint32 irq){ struct hgscale *scale_hw = (struct hgscale*)p_scale; struct hgscale1_hw *hw = (struct hgscale1_hw *)scale_hw->hw; irq_scale1_enable(p_scale, 0, irq); scaleirq1_vector_table[irq] = NULL; scaleirq1_dev_table[irq] = 0; hw->SCALESTA |= BIT(irq); return 0; } void SCALE2_IRQHandler_action(void *p_scale) { uint32 sta = 0; uint8 loop; struct hgscale *scale_hw = (struct hgscale*)p_scale; struct hgscale2_hw *hw = (struct hgscale2_hw *)scale_hw->hw; sta = hw->SCALESTA; for(loop = 0;loop < SCALE_IRQ_NUM;loop++){ if(sta&BIT(loop)){ hw->SCALESTA = BIT(loop); if(scaleirq2_vector_table[loop] != NULL) scaleirq2_vector_table[loop] (loop,scaleirq2_dev_table[loop],0); } } } int32 scaleirq2_register(struct scale_device *p_scale,uint32 irq, scale_irq_hdl isr, uint32 dev_id){ struct hgscale *scale_hw = (struct hgscale*)p_scale; struct hgscale2_hw *hw = (struct hgscale2_hw *)scale_hw->hw; request_irq(scale_hw->irq_num, SCALE2_IRQHandler_action, p_scale); irq_scale2_enable(p_scale, 1, irq); scaleirq2_vector_table[irq] = isr; scaleirq2_dev_table[irq] = dev_id; hw->SCALESTA |= BIT(irq); return 0; } int32 scaleirq2_unregister(struct scale_device *p_scale,uint32 irq){ struct hgscale *scale_hw = (struct hgscale*)p_scale; struct hgscale2_hw *hw = (struct hgscale2_hw *)scale_hw->hw; irq_scale2_enable(p_scale, 0, irq); scaleirq2_vector_table[irq] = NULL; scaleirq2_dev_table[irq] = 0; hw->SCALESTA |= BIT(irq); return 0; } void SCALE3_IRQHandler_action(void *p_scale) { uint32 sta = 0; uint8 loop; struct hgscale *scale_hw = (struct hgscale*)p_scale; struct hgscale3_hw *hw = (struct hgscale3_hw *)scale_hw->hw; sta = hw->SCALESTA; // printf("STA:%08x CNT:%08x\r\n",hw->SCALESTA,hw->SHEIGH_CNT); for(loop = 0;loop < SCALE_IRQ_NUM;loop++){ if(sta&BIT(loop)){ hw->SCALESTA = BIT(loop); if(scaleirq3_vector_table[loop] != NULL){ if(scaler3_lost){ os_printf("isp error,scaler3 drop\r\n"); scaler3_lost = 0; }else{ scaleirq3_vector_table[loop] (loop,scaleirq3_dev_table[loop],0); } } } } } int32 scaleirq3_register(struct scale_device *p_scale,uint32 irq, scale_irq_hdl isr, uint32 dev_id){ struct hgscale *scale_hw = (struct hgscale*)p_scale; struct hgscale3_hw *hw = (struct hgscale3_hw *)scale_hw->hw; request_irq(scale_hw->irq_num, SCALE3_IRQHandler_action, p_scale); irq_scale3_enable(p_scale, 1, irq); scaleirq3_vector_table[irq] = isr; scaleirq3_dev_table[irq] = dev_id; hw->SCALESTA |= BIT(irq); //os_printf("scaleirq3_register:%d %x %x\r\n",irq,(uint32)scaleirq3_vector_table[irq],(uint32)isr); return 0; } int32 scaleirq3_unregister(struct scale_device *p_scale,uint32 irq){ struct hgscale *scale_hw = (struct hgscale*)p_scale; struct hgscale3_hw *hw = (struct hgscale3_hw *)scale_hw->hw; irq_scale3_enable(p_scale, 0, irq); scaleirq3_vector_table[irq] = NULL; scaleirq3_dev_table[irq] = 0; hw->SCALESTA |= BIT(irq); return 0; } static int32 hgscale1_open(struct scale_device *p_scale){ struct hgscale *scale_hw = (struct hgscale*)p_scale; struct hgscale1_hw *hw = (struct hgscale1_hw *)scale_hw->hw; irq_enable(scale_hw->irq_num); hw->SCALECON |= BIT(0); //enable return 0; } static int32 hgscale1_close(struct scale_device *p_scale){ struct hgscale *scale_hw = (struct hgscale*)p_scale; struct hgscale1_hw *hw = (struct hgscale1_hw *)scale_hw->hw; //如果关闭中断或者在中断调用,就不再处理,并且是在vpp模式需要等待中断关闭 if((!(__in_interrupt() || in_disable_irq())) && hw->SCALECON & BIT(2)) { uint32_t timeout = 50; scale_hw->need_close = 1; while(scale_hw->need_close && --timeout) { os_sleep_ms(1); } scale_hw->need_close = 0; } hw->SCALECON &= ~BIT(0); //disable hw->SCALESTA = hw->SCALESTA; scale_hw->clk_en = 0; *(volatile uint32_t*)0x400070d4 &= ~BIT(1); //scale1 clk enable return 0; } static int32 hgscale2_open(struct scale_device *p_scale){ struct hgscale *scale_hw = (struct hgscale*)p_scale; struct hgscale2_hw *hw = (struct hgscale2_hw *)scale_hw->hw; irq_enable(scale_hw->irq_num); hw->SCALECON |= BIT(0); //enable return 0; } static int32 hgscale2_close(struct scale_device *p_scale){ struct hgscale *scale_hw = (struct hgscale*)p_scale; struct hgscale2_hw *hw = (struct hgscale2_hw *)scale_hw->hw; //如果关闭中断或者在中断调用,就不再处理 uint32_t in_disable_irq(void); if(!(__in_interrupt() || in_disable_irq())) { uint32_t timeout = 100; while((hw->SCALESTA &BIT(16)) && --timeout) { os_sleep_ms(1); } } else { while(hw->SCALESTA &BIT(16)); } hw->SCALECON &= ~BIT(0); //disable hw->SCALESTA = hw->SCALESTA; scale_hw->clk_en = 0; *(volatile uint32_t*)0x400070d4 &= ~BIT(2); //scale2 clk enable return 0; } static int32 hgscale3_open(struct scale_device *p_scale){ struct hgscale *scale_hw = (struct hgscale*)p_scale; struct hgscale3_hw *hw = (struct hgscale3_hw *)scale_hw->hw; irq_enable(scale_hw->irq_num); hw->SCALECON |= BIT(0); //enable return 0; } static int32 hgscale3_close(struct scale_device *p_scale){ struct hgscale *scale_hw = (struct hgscale*)p_scale; struct hgscale3_hw *hw = (struct hgscale3_hw *)scale_hw->hw; //如果关闭中断或者在中断调用,就不再处理 uint32_t in_disable_irq(void); if(!(__in_interrupt() || in_disable_irq())) { uint32_t timeout = 100; while((hw->SCALESTA &BIT(16)) && --timeout) { os_sleep_ms(1); } } else { while(hw->SCALESTA &BIT(16)); } hw->SCALECON &= ~BIT(0); //disable hw->SCALESTA = hw->SCALESTA; scale_hw->clk_en = 0; *(volatile uint32_t*)0x400070d4 &= ~BIT(3); //scale3 clk enable return 0; } int32 hgscale1_suspend(struct dev_obj *obj){ struct hgscale *scale_hw = (struct hgscale*)obj; struct hgscale1_hw *hw; struct hgscale1_hw *hw_cfg; if(!scale_hw->opened || scale_hw->dsleep) { return RET_OK; } scale_hw->dsleep = 1; scale_hw->cfg_backup = (uint32 *)os_malloc(sizeof(struct hgscale1_hw)); hw_cfg = (struct hgscale1_hw*)scale_hw->cfg_backup; hw = (struct hgscale1_hw*)scale_hw->hw; hw_cfg->SCALECON = hw->SCALECON; hw_cfg->SWINCON = hw->SWINCON; hw_cfg->SSTART = hw->SSTART; hw_cfg->TWINCON = hw->TWINCON; hw_cfg->SWIDTH_STEP = hw->SWIDTH_STEP; hw_cfg->SHEIGH_STEP = hw->SHEIGH_STEP; hw_cfg->INBUF_LINE_NUM = hw->INBUF_LINE_NUM; hw_cfg->INYDMA_STADR = hw->INYDMA_STADR; hw_cfg->INUDMA_STADR = hw->INUDMA_STADR; hw_cfg->INVDMA_STADR = hw->INVDMA_STADR; hw_cfg->INBUFCON = hw->INBUFCON; hw_cfg->SHEIGH_CNT = hw->SHEIGH_CNT; hw_cfg->SCALESTA = hw->SCALESTA; irq_disable(scale_hw->irq_num); return 0; } int32 hgscale1_resume(struct dev_obj *obj){ struct hgscale *scale_hw = (struct hgscale*)obj; struct hgscale1_hw *hw; struct hgscale1_hw *hw_cfg; if(!scale_hw->opened || !scale_hw->dsleep) { return RET_OK; } scale_hw->dsleep = 0; hw_cfg = (struct hgscale1_hw*)scale_hw->cfg_backup; hw = (struct hgscale1_hw*)scale_hw->hw; hw->SCALECON = hw_cfg->SCALECON; hw->SWINCON = hw_cfg->SWINCON; hw->SSTART = hw_cfg->SSTART; hw->TWINCON = hw_cfg->TWINCON; hw->SWIDTH_STEP = hw_cfg->SWIDTH_STEP; hw->SHEIGH_STEP = hw_cfg->SHEIGH_STEP; hw->INBUF_LINE_NUM = hw_cfg->INBUF_LINE_NUM; hw->INYDMA_STADR = hw_cfg->INYDMA_STADR; hw->INUDMA_STADR = hw_cfg->INUDMA_STADR; hw->INVDMA_STADR = hw_cfg->INVDMA_STADR; hw->INBUFCON = hw_cfg->INBUFCON; hw->SHEIGH_CNT = hw_cfg->SHEIGH_CNT; hw->SCALESTA = hw_cfg->SCALESTA; irq_enable(scale_hw->irq_num); os_free(scale_hw->cfg_backup); return 0; } int32 hgscale2_suspend(struct dev_obj *obj){ struct hgscale *scale_hw = (struct hgscale*)obj; struct hgscale2_hw *hw; struct hgscale2_hw *hw_cfg; if(!scale_hw->opened || scale_hw->dsleep) { return RET_OK; } scale_hw->dsleep = 1; scale_hw->cfg_backup = (uint32 *)os_malloc(sizeof(struct hgscale2_hw)); hw_cfg = (struct hgscale2_hw*)scale_hw->cfg_backup; hw = (struct hgscale2_hw*)scale_hw->hw; hw_cfg->SCALECON = hw->SCALECON; hw_cfg->SWINCON = hw->SWINCON; hw_cfg->SSTART = hw->SSTART; hw_cfg->TWINCON = hw->TWINCON; hw_cfg->SWIDTH_STEP = hw->SWIDTH_STEP; hw_cfg->SHEIGH_STEP = hw->SHEIGH_STEP; hw_cfg->YSRAMBUF_STADR = hw->YSRAMBUF_STADR; hw_cfg->USRAMBUF_STADR = hw->USRAMBUF_STADR; hw_cfg->VSRAMBUF_STADR = hw->VSRAMBUF_STADR; hw_cfg->INYDMA_STADR = hw->INYDMA_STADR; hw_cfg->INUDMA_STADR = hw->INUDMA_STADR; hw_cfg->INVDMA_STADR = hw->INVDMA_STADR; hw_cfg->OUTYDMA_STADR = hw->OUTYDMA_STADR; hw_cfg->OUTUDMA_STADR = hw->OUTUDMA_STADR; hw_cfg->OUTVDMA_STADR = hw->OUTVDMA_STADR; hw_cfg->SHEIGH_CNT = hw->SHEIGH_CNT; hw_cfg->SCALESTA = hw->SCALESTA; irq_disable(scale_hw->irq_num); return 0; } int32 hgscale2_resume(struct dev_obj *obj){ struct hgscale *scale_hw = (struct hgscale*)obj; struct hgscale2_hw *hw; struct hgscale2_hw *hw_cfg; if(!scale_hw->opened || !scale_hw->dsleep) { return RET_OK; } scale_hw->dsleep = 0; hw_cfg = (struct hgscale2_hw*)scale_hw->cfg_backup; hw = (struct hgscale2_hw*)scale_hw->hw; hw->SCALECON = hw_cfg->SCALECON; hw->SWINCON = hw_cfg->SWINCON; hw->SSTART = hw_cfg->SSTART; hw->TWINCON = hw_cfg->TWINCON; hw->SWIDTH_STEP = hw_cfg->SWIDTH_STEP; hw->SHEIGH_STEP = hw_cfg->SHEIGH_STEP; hw->YSRAMBUF_STADR = hw_cfg->YSRAMBUF_STADR; hw->USRAMBUF_STADR = hw_cfg->USRAMBUF_STADR; hw->VSRAMBUF_STADR = hw_cfg->VSRAMBUF_STADR; hw->INYDMA_STADR = hw_cfg->INYDMA_STADR; hw->INUDMA_STADR = hw_cfg->INUDMA_STADR; hw->INVDMA_STADR = hw_cfg->INVDMA_STADR; hw->OUTYDMA_STADR = hw_cfg->OUTYDMA_STADR; hw->OUTUDMA_STADR = hw_cfg->OUTUDMA_STADR; hw->OUTVDMA_STADR = hw_cfg->OUTVDMA_STADR; hw->SHEIGH_CNT = hw_cfg->SHEIGH_CNT; hw->SCALESTA = hw_cfg->SCALESTA; irq_enable(scale_hw->irq_num); os_free(scale_hw->cfg_backup); return 0; } int32 hgscale3_suspend(struct dev_obj *obj){ struct hgscale *scale_hw = (struct hgscale*)obj; struct hgscale3_hw *hw; struct hgscale3_hw *hw_cfg; if(!scale_hw->opened || scale_hw->dsleep) { return RET_OK; } scale_hw->dsleep = 1; scale_hw->cfg_backup = (uint32 *)os_malloc(sizeof(struct hgscale3_hw)); hw_cfg = (struct hgscale3_hw*)scale_hw->cfg_backup; hw = (struct hgscale3_hw*)scale_hw->hw; hw_cfg->SCALECON = hw->SCALECON; hw_cfg->SWINCON = hw->SWINCON; hw_cfg->SSTART = hw->SSTART; hw_cfg->TWINCON = hw->TWINCON; hw_cfg->SWIDTH_STEP = hw->SWIDTH_STEP; hw_cfg->SHEIGH_STEP = hw->SHEIGH_STEP; hw_cfg->INBUF_LINE_NUM = hw->INBUF_LINE_NUM; hw_cfg->INYDMA_STADR = hw->INYDMA_STADR; hw_cfg->INUDMA_STADR = hw->INUDMA_STADR; hw_cfg->INVDMA_STADR = hw->INVDMA_STADR; hw_cfg->OUTYDMA_STADR = hw->OUTYDMA_STADR; hw_cfg->OUTUDMA_STADR = hw->OUTUDMA_STADR; hw_cfg->OUTVDMA_STADR = hw->OUTVDMA_STADR; hw_cfg->INBUFCON = hw->INBUFCON; hw_cfg->SHEIGH_CNT = hw->SHEIGH_CNT; hw_cfg->SCALESTA = hw->SCALESTA; irq_disable(scale_hw->irq_num); return 0; } int32 hgscale3_resume(struct dev_obj *obj){ struct hgscale *scale_hw = (struct hgscale*)obj; struct hgscale3_hw *hw; struct hgscale3_hw *hw_cfg; if(!scale_hw->opened || !scale_hw->dsleep) { return RET_OK; } scale_hw->dsleep = 0; hw_cfg = (struct hgscale3_hw*)scale_hw->cfg_backup; hw = (struct hgscale3_hw*)scale_hw->hw; hw->SCALECON = hw_cfg->SCALECON; hw->SWINCON = hw_cfg->SWINCON; hw->SSTART = hw_cfg->SSTART; hw->TWINCON = hw_cfg->TWINCON; hw->SWIDTH_STEP = hw_cfg->SWIDTH_STEP; hw->SHEIGH_STEP = hw_cfg->SHEIGH_STEP; hw->INBUF_LINE_NUM = hw_cfg->INBUF_LINE_NUM; hw->INYDMA_STADR = hw_cfg->INYDMA_STADR; hw->INUDMA_STADR = hw_cfg->INUDMA_STADR; hw->INVDMA_STADR = hw_cfg->INVDMA_STADR; hw->OUTYDMA_STADR = hw_cfg->OUTYDMA_STADR; hw->OUTUDMA_STADR = hw_cfg->OUTUDMA_STADR; hw->OUTVDMA_STADR = hw_cfg->OUTVDMA_STADR; hw->INBUFCON = hw_cfg->INBUFCON; hw->SHEIGH_CNT = hw_cfg->SHEIGH_CNT; hw->SCALESTA = hw_cfg->SCALESTA; irq_enable(scale_hw->irq_num); os_free(scale_hw->cfg_backup); return 0; } static const struct scale_hal_ops dev1_ops = { .open = hgscale1_open, .close = hgscale1_close, .ioctl = hgscale1_ioctl, .request_irq = scaleirq1_register, .release_irq = scaleirq1_unregister, #ifdef CONFIG_SLEEP .ops.suspend = hgscale1_suspend, .ops.resume = hgscale1_resume, #endif }; static const struct scale_hal_ops dev2_ops = { .open = hgscale2_open, .close = hgscale2_close, .ioctl = hgscale2_ioctl, .request_irq = scaleirq2_register, .release_irq = scaleirq2_unregister, #ifdef CONFIG_SLEEP .ops.suspend = hgscale2_suspend, .ops.resume = hgscale2_resume, #endif }; static const struct scale_hal_ops dev3_ops = { .open = hgscale3_open, .close = hgscale3_close, .ioctl = hgscale3_ioctl, .request_irq = scaleirq3_register, .release_irq = scaleirq3_unregister, #ifdef CONFIG_SLEEP .ops.suspend = hgscale3_suspend, .ops.resume = hgscale3_resume, #endif }; int32 hgscale1_attach(uint32 dev_id, struct hgscale *scale){ scale->clk_en = 0; scale->opened = 0; scale->use_dma = 0; scale->irq_hdl = NULL; //memset(dvp->irq_hdl,0,sizeof(dvp->irq_hdl)); scale->irq_data = 0; //memset(dvp->irq_data,0,sizeof(dvp->irq_data)); scale->dev.dev.ops = (const struct devobj_ops *)&dev1_ops; irq_disable(scale->irq_num); dev_register(dev_id, (struct dev_obj *)scale); return 0; } int32 hgscale2_attach(uint32 dev_id, struct hgscale *scale){ scale->clk_en = 0; scale->opened = 0; scale->use_dma = 0; scale->irq_hdl = NULL; //memset(dvp->irq_hdl,0,sizeof(dvp->irq_hdl)); scale->irq_data = 0; //memset(dvp->irq_data,0,sizeof(dvp->irq_data)); scale->dev.dev.ops = (const struct devobj_ops *)&dev2_ops; irq_disable(scale->irq_num); dev_register(dev_id, (struct dev_obj *)scale); return 0; } int32 hgscale3_attach(uint32 dev_id, struct hgscale *scale){ scale->clk_en = 0; scale->opened = 0; scale->use_dma = 0; scale->irq_hdl = NULL; //memset(dvp->irq_hdl,0,sizeof(dvp->irq_hdl)); scale->irq_data = 0; //memset(dvp->irq_data,0,sizeof(dvp->irq_data)); scale->dev.dev.ops = (const struct devobj_ops *)&dev3_ops; irq_disable(scale->irq_num); dev_register(dev_id, (struct dev_obj *)scale); return 0; }