#include "FreeRTOS.h" #include "board.h" #include "chip.h" #ifdef REVERSE_TRACK #include "vg_driver.h" #endif #define ITU_CTL (0x00) #define ITU_IMAGE_WIDTH (0x04) #define ITU_YFRAM0_ADDR_START (0x08) #define ITU_YFRAM1_ADDR_START (0x0C) #define ITU_YFRAM2_ADDR_START (0x10) #define ITU_YFRAM3_ADDR_START (0x14) #define ITU_YFRAM0_ADDR_FLIP (0x18) #define ITU_YFRAM1_ADDR_FLIP (0x1C) #define ITU_YFRAM2_ADDR_FLIP (0x20) #define ITU_YFRAM3_ADDR_FLIP (0x24) #define ITU_CFRAM0_ADDR_START (0x28) #define ITU_CFRAM1_ADDR_START (0x2c) #define ITU_CFRAM2_ADDR_START (0x30) #define ITU_CFRAM3_ADDR_START (0x34) #define ITU_CFRAM0_ADDR_FLIP (0x38) #define ITU_CFRAM1_ADDR_FLIP (0x3C) #define ITU_CFRAM2_ADDR_FLIP (0x40) #define ITU_CFRAM3_ADDR_FLIP (0x44) #define ITU_REC_HST_REC_HSP (0x48)// #define ITU_REC_VST_REC_VSP (0x4C)//开窗口大小,目的窗口 #define ITU_WIN_HST_WIN_HSP (0x50)//黑色位置 #define ITU_WIN_VST_WIN_VSP (0x54) #define ITU_EN_REG (0x58) #define ITU_ITU_HSTART_HSTOP (0x5C) #define ITU_ITU_VSTART_VSTOP (0x60) #define ITU_GLOBAL_ALPHA (0x64) #define ITU_WR_STATUS (0x6C) #define ITU_SCAL_CLK_RST (0x70) #define ITU_VGATE_START1_STOP1 (0x80) #define ITU_SCALE_CTRL_REG (0x84) #define ITU_VSYN_DEL_HFZ (0x88) #define ITU_VFZ_RHLEN_REG (0x8C) #define ITU_HSYN_START_STOP (0x90) #define ITU_HGATE_START_STOP (0x94) #define ITU_VSYN_START_STOP (0x98) #define ITU_VGATE_START_STOP (0x9C) #define ITU_IMG_CUT_REG (0xA0) #define ITU_DOWN_BLACK_NUM_HV_DELAY_COS_l (0xA4) #define ITU_COS_H_VXMOD_ODDF_INI_TVLEN_l (0xA8) #define ITU_TVLEN_H_SCAL_CTL (0xAC) #define ITU_SCALE_STATUS (0xB0) #define ITU_VFILT_COEF0_3 (0xB4) #define ITU_VFILT_COEF4_6_VFILT_CTL (0xB8) #define ITU_SRC_WIDE_HIGHT (0xBC) #define ITU_SRC_WIDE_FILTER (0xC0) #define ITU_DET_REG0 (0xC8) #define ITU_DET_REG1 (0xCC) #define ITU_DET_REG2 (0xD0) #define ITU_DET_REG3 (0xD4) #define ITU_INT_EN (0xD8) #define ITU_INT_STATUS (0xDC) #define ITU656IN_BUF_NUM 4 #define ITUFRAME_MAX_WIDTH VIN_WIDTH #define ITUFRAME_MAX_HEIGHT VIN_HEIGHT typedef struct { uint32_t yaddr; uint32_t uvaddr; int status; } ItuBufInfo; static uint32_t itubase = REGS_ITU_BASE; //static ItuBufInfo itubuf_info[ITU656IN_BUF_NUM] = {0}; static ItuConfigPara itu_para; static TaskHandle_t itu_task; static SemaphoreHandle_t itu_mutex = NULL; static void *itu_buf = NULL; static int itu_enable = 0; static int itu_take_video = 0; static unsigned int itu_get_frame_yadde(unsigned int itu_id) { if(itu_id == 0) return readl(itubase + ITU_YFRAM0_ADDR_START); else if(itu_id == 1) return readl(itubase + ITU_YFRAM1_ADDR_START); else if(itu_id == 2) return readl(itubase + ITU_YFRAM2_ADDR_START); else return readl(itubase + ITU_YFRAM3_ADDR_START); } static unsigned int itu_get_frame_uvadde(unsigned int itu_id) { if(itu_id == 0) return readl(itubase + ITU_CFRAM0_ADDR_START); else if(itu_id == 1) return readl(itubase + ITU_CFRAM1_ADDR_START); else if(itu_id == 2) return readl(itubase + ITU_CFRAM2_ADDR_START); else return readl(itubase + ITU_CFRAM3_ADDR_START); } static void itu_interupt_handler(void *param) { unsigned int status = readl(itubase + ITU_INT_STATUS); unsigned int height = 0,wide = 0; unsigned int totheight = 0,totwide = 0; unsigned int curr_handle_frame_id=0; //clear inter writel(status & 0xf0, itubase + ITU_INT_STATUS); if(status >>4 & 0x1) { unsigned int val; val = readl(itubase + ITU_DET_REG3) ; height = (val>>12)&0xFFF; wide = val&0xFFF; val = readl(itubase + ITU_DET_REG2) ; totheight = (val>>12)&0xFFF; totwide = val&0xFFF; printf(">>>>height = %d,wide= %d,totheight = %d,totwide= %d\n",height ,wide,totheight ,totwide); } if(status >> 6 & 0x1) { unsigned int itu_dis_id = 1; curr_handle_frame_id = readl(itubase + ITU_WR_STATUS) &0x3; if(curr_handle_frame_id != 0) itu_dis_id = curr_handle_frame_id - 1; else itu_dis_id = 3; // if (last_frame_id == itu_dis_id) // printf("itu_dis_id:%d \n", itu_dis_id); // last_frame_id = itu_dis_id; xTaskNotifyFromISR(itu_task, itu_dis_id, eSetValueWithOverwrite, 0); } } void itu_clear_addr_for_hwuse(void) { unsigned int regval = 0; unsigned int current_id = readl(itubase + ITU_WR_STATUS); if(current_id == ITU656IN_BUF_NUM - 1) regval = 1; else regval = 1<<(current_id + 1); writel(regval, itubase + ITU_INT_STATUS); } void itu_clk_cofig(void) { //select mfc clk 250M/5 unsigned int reg = readl(REGS_SYSCTL_BASE + 0x7c); reg &=~(0x1<<8); reg |=(0x1<<8); writel(reg , REGS_SYSCTL_BASE + 0x7c); reg = readl(itubase + ITU_SCAL_CLK_RST); reg &=~(0x3f<<20); //reg |=(0x5<<20); reg |=(0x7<<20); writel(reg , itubase + ITU_SCAL_CLK_RST); } int itu_config(ItuConfigPara *para) { uint32_t val; int ret = 0; int i; unsigned int Total_line_num = 0;//585; //thl (输入clk/2)/(总行数*总点数) = (scaler_clk)/(thlen*总点数) unsigned int Total_pixs_num = 2400;//2224(50M);//2661;//3333;//3232;//1716;//4608; configASSERT(para->in_width <= ITUFRAME_MAX_WIDTH && para->in_height <= ITUFRAME_MAX_HEIGHT); xSemaphoreTake(itu_mutex, portMAX_DELAY); para->win_hst = 0; para->win_hsp = para->out_width; para->win_vst = 0; para->win_vsp = para->out_height -1; para->rec_vsp = para->out_height; para->rec_vst = 0; para->rec_hsp = para->out_width; para->rec_hst = 0; para->itu_vstop = 0;//height; para->itu_vstart = 0; para->itu_hstop = 0;//wide; para->itu_hstart = 0; para->hsyn_start = 3; para->hsyn_stop = para->hsyn_start + 5;//wide; para->vsyn_start = 3; para->vsyn_stop = para->vsyn_start + 3; para->hgate_start = para->hsyn_stop + 20; para->hgate_stop = para->hgate_start +para->scale_out_width; if(para->Input_DataMode == ITU_MIPI) para->vgate_start = para->vsyn_stop + 0; else para->vgate_start = para->vsyn_stop + 18; para->vgate_stop = para->vgate_start + para->scale_out_height; para->vgate_start1= para->vgate_start; para->vgate_stop1 = para->vgate_stop + 0x10 ; Total_line_num = para->vgate_stop + 50; itu_clk_cofig(); writel((uint32_t)itu_buf, itubase + ITU_YFRAM0_ADDR_START); writel((uint32_t)itu_buf + para->out_width*para->out_height, itubase + ITU_CFRAM0_ADDR_START); writel((uint32_t)itu_buf + (para->out_height -1)*para->out_width, itubase + ITU_YFRAM0_ADDR_FLIP); if(para->out_format == ITU_Y_UV420) writel(readl(itubase + ITU_CFRAM0_ADDR_START) + ((para->out_height/2 -1)*para->out_width), itubase + ITU_CFRAM0_ADDR_FLIP); else if(para->out_format == ITU_Y_UV422) writel(readl(itubase + ITU_CFRAM0_ADDR_START) + ((para->out_height -1)*para->out_width), itubase + ITU_CFRAM0_ADDR_FLIP); writel((uint32_t)itu_buf + para->out_width*para->out_height*2, itubase + ITU_YFRAM1_ADDR_START); writel(readl(itubase + ITU_YFRAM1_ADDR_START) + para->out_width*para->out_height, itubase + ITU_CFRAM1_ADDR_START); writel(readl(itubase + ITU_YFRAM1_ADDR_START) + (para->out_height -1)*para->out_width, itubase + ITU_YFRAM1_ADDR_FLIP) ; if(para->out_format == ITU_Y_UV420) writel(readl(itubase + ITU_CFRAM1_ADDR_START) + ((para->out_height/2 -1)*para->out_width), itubase + ITU_CFRAM1_ADDR_FLIP); else if(para->out_format == ITU_Y_UV422) writel(readl(itubase + ITU_CFRAM1_ADDR_START) + ((para->out_height -1)*para->out_width), itubase + ITU_CFRAM1_ADDR_FLIP); writel((uint32_t)itu_buf + para->out_width*para->out_height*4, itubase + ITU_YFRAM2_ADDR_START); writel(readl(itubase + ITU_YFRAM2_ADDR_START) + para->out_width*para->out_height, itubase + ITU_CFRAM2_ADDR_START); writel(readl(itubase + ITU_YFRAM2_ADDR_START) + (para->out_height -1)*para->out_width, itubase + ITU_YFRAM2_ADDR_FLIP); if(para->out_format == ITU_Y_UV420) writel(readl(itubase + ITU_CFRAM2_ADDR_START)+ ((para->out_height/2 -1)*para->out_width), itubase + ITU_CFRAM2_ADDR_FLIP); else if(para->out_format == ITU_Y_UV422) writel(readl(itubase + ITU_CFRAM2_ADDR_START) + ((para->out_height -1)*para->out_width), itubase + ITU_CFRAM2_ADDR_FLIP); writel((uint32_t)itu_buf + para->out_width*para->out_height*6, itubase + ITU_YFRAM3_ADDR_START); writel(readl(itubase + ITU_YFRAM3_ADDR_START) + para->out_width*para->out_height, itubase + ITU_CFRAM3_ADDR_START); writel(readl(itubase + ITU_YFRAM3_ADDR_START) + (para->out_height -1)*para->out_width, itubase + ITU_YFRAM3_ADDR_FLIP); if(para->out_format == ITU_Y_UV420) writel(readl(itubase + ITU_CFRAM3_ADDR_START) + ((para->out_height/2 -1)*para->out_width), itubase + ITU_CFRAM3_ADDR_FLIP); else if(para->out_format == ITU_Y_UV422) writel(readl(itubase + ITU_CFRAM3_ADDR_START) + ((para->out_height -1)*para->out_width), itubase + ITU_CFRAM3_ADDR_FLIP); writel(para->rec_hsp << 12 | para->rec_hst << 0, itubase + ITU_REC_HST_REC_HSP); writel(para->rec_vsp << 12 | para->rec_vst << 0, itubase + ITU_REC_VST_REC_VSP); writel(para->win_hsp << 12 | para->win_hst << 0, itubase + ITU_WIN_HST_WIN_HSP); writel(para->win_vsp << 12 | para->win_hst << 0, itubase + ITU_WIN_VST_WIN_VSP); writel(para->vgate_stop1 << 16 | para->vgate_start1<< 0, itubase + ITU_VGATE_START1_STOP1); writel(para->hgate_stop << 16 | para->hgate_start << 0, itubase + ITU_HGATE_START_STOP); writel(para->hsyn_stop << 16 | para->hsyn_start << 0, itubase + ITU_HSYN_START_STOP); writel(para->vsyn_stop << 16 | para->vsyn_start << 0, itubase + ITU_VSYN_START_STOP); writel(para->vgate_stop << 16 | para->vgate_start << 0, itubase + ITU_VGATE_START_STOP); writel(para->itu_hstop << 12 | para->itu_hstart << 0, itubase + ITU_ITU_HSTART_HSTOP); writel(para->itu_vstop << 12 | para->itu_vstart << 0, itubase + ITU_ITU_VSTART_VSTOP); writel(2 | 0xc <<24 , itubase + ITU_SCALE_CTRL_REG); writel((para->in_width * 1024 / (para->scale_out_width + 0x17/*para.left_cut_num*/))<<16, itubase + ITU_VSYN_DEL_HFZ); writel((para->in_height * 1024)/(para->scale_out_height + para->up_black_num) | Total_pixs_num<<16, itubase + ITU_VFZ_RHLEN_REG); writel( 0x14 << 8, itubase + ITU_DOWN_BLACK_NUM_HV_DELAY_COS_l); writel((Total_line_num & 0xff)<<24, itubase + ITU_COS_H_VXMOD_ODDF_INI_TVLEN_l); writel(0x0<<16 | 0x1<<11 | (Total_line_num>>8 & 0xff), itubase + ITU_TVLEN_H_SCAL_CTL); writel(0, itubase + ITU_VFILT_COEF0_3); writel(4<<24, itubase + ITU_VFILT_COEF4_6_VFILT_CTL); writel(para->in_width | para->in_height<< 16, itubase + ITU_SRC_WIDE_HIGHT); writel(para->in_width, itubase + ITU_SRC_WIDE_FILTER); writel(para->out_width | para->out_width <<16, itubase + ITU_IMAGE_WIDTH); writel(para->in_height << 12 | para->in_width, itubase + ITU_DET_REG1); writel(1<<9 | 1<<8 |3<<2 | 1<<1, itubase + ITU_EN_REG); writel(readl(itubase + ITU_CTL)|(1<<6), itubase + ITU_CTL);//bit[3:2]fnum_sel/bit6 mode_en/bit7 yuv420 writel(readl(itubase + ITU_CTL)|2<<2 | 1<<1, itubase + ITU_CTL);//bit17 cbcr_inv bit5 hmirror bit4 vflip if(para->out_format == ITU_Y_UV420) { val = readl(itubase + ITU_CTL); val &=~(1<<26 | 1<<7); val |= 0<<26 | 1<<7 ; writel(val,itubase + ITU_CTL); } else if(para->out_format == ITU_Y_UV422) { val = readl(itubase + ITU_CTL); val &=~(1<<26 | 1<<7); writel(val,itubase + ITU_CTL); } else if(para->out_format == ITU_RGB_MODE) { val = readl(itubase + ITU_CTL); val &=~(1<<26); val |=(1<<26); writel(val, itubase + ITU_CTL); } if(para->itu601 == ITU_601) { val = readl(itubase + ITU_EN_REG); val &=~(3<<4); val |= 2 << 4 ; writel(val,itubase + ITU_EN_REG); } if(para->scale_bypass == 0) { val =readl(itubase + ITU_CTL); val &=~(1<<19); //ITU_CTL = val;//19bit scaler open writel(val, itubase + ITU_CTL); val =readl(itubase + ITU_TVLEN_H_SCAL_CTL); val |=(1<<8); writel(val, itubase + ITU_TVLEN_H_SCAL_CTL); } else writel(readl(itubase + ITU_CTL) | 1<<19 , itubase + ITU_CTL); //open mirror if(para->hmirror == 1) { val =readl(itubase + ITU_CTL); val &=~(1<<5 | 0x3ff<<8); val |=(1<<5)| ((para->out_width/8)-1) << 8; writel(val,itubase + ITU_CTL); val = readl(itubase + ITU_EN_REG); val &=~(1<<1); writel(val,itubase + ITU_EN_REG); } //open flip if(para->vflip== 1) { val = readl(itubase + ITU_CTL); val &=~(1<<4); val |= (1<<4); writel(val,itubase + ITU_CTL); } if(para->Input_DataMode == ITU_MIPI) { val = readl(itubase + ITU_CTL); val &=~((1<<24)); val |=((1<<24)); writel(val, itubase + ITU_CTL); val = readl(itubase + ITU_SCAL_CLK_RST); val &=~((1<<11)); val |=((1<<11)); writel(val, itubase + ITU_SCAL_CLK_RST); val = readl(itubase + ITU_CTL); val &=~((1<<22)|(1<<1)); writel(val, itubase + ITU_CTL); val = readl(itubase + ITU_SCALE_CTRL_REG); val &=~((1<<30)); val |=((1<<30)); writel(val, itubase + ITU_SCALE_CTRL_REG); } else if(para->Input_DataMode == ITU_ITU656_601) { val = readl(itubase + ITU_CTL); val &=~((1<<24)); writel(val, itubase + ITU_CTL); } if(para->in_height == 1080) { val = readl(itubase + ITU_EN_REG); val &=~((1<<1) | (1<<2)); writel(val, itubase + ITU_EN_REG); } val = readl(itubase + ITU_CTL); val &=~((1<<28) | (1<<29) | (1<<0)); writel(val, itubase + ITU_CTL); val = readl(itubase + ITU_DET_REG0); val &=~((7<<0)); val |=((7<<0)); writel(val, itubase + ITU_DET_REG0); // writel(0x05380400, itubase + ITU_VFZ_RHLEN_REG); memcpy(&itu_para, para, sizeof(itu_para)); end: xSemaphoreGive(itu_mutex); return ret; } void itu_start(void) { uint32_t val; //enable write data xSemaphoreTake(itu_mutex, portMAX_DELAY); val = readl(itubase + ITU_EN_REG); val |= (1<<0); writel(val, itubase + ITU_EN_REG); val = readl(itubase + ITU_CTL); val |= (1<<0); writel(val, itubase + ITU_CTL); itu_enable = 1; xSemaphoreGive(itu_mutex); } void itu_stop(void) { uint32_t val; //disable write data xSemaphoreTake(itu_mutex, portMAX_DELAY); val = readl(itubase + ITU_EN_REG); val &=~(1<<0); writel(val, itubase + ITU_EN_REG); val = readl(itubase + ITU_CTL); val &=~(1<<0); writel(val, itubase + ITU_CTL); itu_enable = 0; #ifndef REVERSE_UI ark_lcd_osd_enable(LCD_VIDEO_LAYER, 0); ark_lcd_set_osd_sync(LCD_VIDEO_LAYER); ark_lcd_osd_enable(LCD_OSD1, 1); ark_lcd_set_osd_sync(LCD_OSD1); #endif xTaskNotify(itu_task, 0, eSetValueWithOverwrite); xSemaphoreGive(itu_mutex); } void itu_display_thread(void *param) { uint32_t ulNotifiedValue; uint32_t yaddr, uvaddr, dstaddr; for (;;) { xTaskNotifyWait( 0x00, /* Don't clear any notification bits on entry. */ 0xffffffff, /* Reset the notification value to 0 on exit. */ &ulNotifiedValue, /* Notified value pass out in ulNotifiedValue. */ portMAX_DELAY); // printf("received address id 0x%x.\n", ulNotifiedValue); xSemaphoreTake(itu_mutex, portMAX_DELAY); if (!itu_enable) { xSemaphoreGive(itu_mutex); vVideoDisplayBufFree(dstaddr); /* 倒车显示优先级高,等倒车结束之后才释放视频显示资源 */ if (itu_take_video) { vVideoDisplayBufGive(); itu_take_video = 0; } continue; } /* 获取视频显示资源 */ if (!itu_take_video) { xVideoDisplayBufTake(portMAX_DELAY); itu_take_video = 1; } if (!ark_lcd_get_osd_info_atomic_isactive(LCD_VIDEO_LAYER)) { ark_lcd_wait_for_vsync(); } /* 通过该接口获取视频显示共用的缓存可以避免切换过程中的黑屏、 花屏等问题 */ dstaddr = ulVideoDisplayBufGet(); yaddr = itu_get_frame_yadde(ulNotifiedValue);//ulNotifiedValue; uvaddr = itu_get_frame_uvadde(ulNotifiedValue);//yaddr + itu_para.in_width * itu_para.in_height; #ifdef REVERSE_TRACK extern int get_reverse_track_index(void); static int index = 58; index = get_reverse_track_index(); xm_vg_set_gpu_fb_addr(dstaddr); xm_vg_draw_prepare(&index); xm_vg_draw_start(); #endif LcdOsdInfo info = {0}; info.x = itu_para.out_x; info.y = itu_para.out_y; info.width = itu_para.out_width; info.height = itu_para.out_height; if (itu_para.out_format == ITU_Y_UV422) info.format = LCD_OSD_FORAMT_Y_UV422; else if (itu_para.out_format == ITU_Y_UV420) info.format = LCD_OSD_FORAMT_Y_UV420; info.yaddr = yaddr; info.uaddr = uvaddr; ark_lcd_set_osd_info_atomic(LCD_VIDEO_LAYER, &info); ark_lcd_osd_enable(LCD_VIDEO_LAYER, 1); ark_lcd_set_osd_sync(LCD_VIDEO_LAYER); #ifndef REVERSE_UI ark_lcd_osd_enable(LCD_OSD1, 0); ark_lcd_set_osd_sync(LCD_OSD1); #endif itu_clear_addr_for_hwuse(); vVideoDisplayBufRender(dstaddr); xSemaphoreGive(itu_mutex); } } int itu_init(void) { sys_soft_reset(softreset_itu); itu_mutex = xSemaphoreCreateMutex(); itu_buf = pvPortMalloc(ITUFRAME_MAX_WIDTH * ITUFRAME_MAX_HEIGHT * 3 * ITU656IN_BUF_NUM); if (!itu_buf) { printf("Itu malloc memory fail.\n"); return -ENOMEM; } if (xTaskCreate(itu_display_thread, "itudis", configMINIMAL_STACK_SIZE, NULL, configMAX_PRIORITIES - 2, &itu_task) != pdPASS) { printf("create itu display task fail.\n"); return -1; } request_irq(ITU_IRQn, 0, itu_interupt_handler, NULL); return 0; }