📄 ipu.c
字号:
#include <stdio.h>#include <stdlib.h>#include <fcntl.h>#include <assert.h>#include <time.h>#include <string.h>#include <ctype.h>#include <termios.h>#include <unistd.h>#include "camera.h"#include "jz4740_ipu.h"#ifdef JZ4740_IPU#define IPU_LUT_LEN 20#define FB_LCD_WIDTH lcd_get_width()#define FB_LCD_HEIGHT lcd_get_height()#define LCD_BPP lcd_get_bpp()#define LCD_BPP_BYTE (LCD_BPP / 8)#define IPU_VBASE (IPU__OFFSET | 0xa0000000)#define PAGE_SIZE (4096)#define MEM_ALLOC_DEV_NUM 2struct mem_dev { unsigned int vaddr; unsigned int paddr; unsigned int totalsize; unsigned int usedsize;} memdev[MEM_ALLOC_DEV_NUM]; static int ipu_inited = 0, ipu_size_cfg = 0, get_fbinfo_already = 0;static int ipu_rtable_init = 0, ipu_rtable_len;static int screen_offset;int ipu_image_completed = 0;static volatile unsigned char *ipu_vbase=NULL, *frame_buffer=NULL;unsigned int fb_w, fb_h, fb_bpp, phy_fb, fbmemlen, fb_line_len;unsigned int rsize_w = 0, rsize_h = 0;unsigned int out_width, out_height;#define IPU_LUT_LEN 20//struct Ration2m ipu_ratio_table[(IPU_LUT_LEN) * (IPU_LUT_LEN)];static struct Ration2m *ipu_ratio_table;rsz_lut h_lut[IPU_LUT_LEN];rsz_lut v_lut[IPU_LUT_LEN];typedef void ( *CvGETIPURATIOTABLE )( void **, int );static CvGETIPURATIOTABLE get_ipu_ratio_table = NULL;void CvCMallocIpuRatioTable( CvGETIPURATIOTABLE func ){ get_ipu_ratio_table = func;}void get_fbaddr_info (){ fb_w = FB_LCD_WIDTH; fb_h = FB_LCD_HEIGHT; fb_bpp = LCD_BPP;// phy_fb= (lcd_get_current_cframe() & 0x1fffffff); phy_fb= lcd_get_change_phyframe();// phy_fb= (lcd_get_change_cframe() & 0x1fffffff); fb_line_len = FB_LCD_WIDTH * LCD_BPP_BYTE; fbmemlen = FB_LCD_WIDTH * LCD_BPP_BYTE *FB_LCD_HEIGHT; printf ("fb_w=%d, fb_h=%d, phy_fb=0x%x, fbmemlen=%d, fb_line_len=%d\n", fb_w, fb_h, phy_fb, fbmemlen, fb_line_len);}/*----------------------------------------------------------------------------------*/char *ipu_regs_name[] = { "REG_CTRL", /* 0x0 */ "REG_STATUS", /* 0x4 */ "REG_D_FMT", /* 0x8 */ "REG_Y_ADDR", /* 0xc */ "REG_U_ADDR", /* 0x10 */ "REG_V_ADDR", /* 0x14 */ "REG_IN_FM_GS", /* 0x18 */ "REG_Y_STRIDE", /* 0x1c */ "REG_UV_STRIDE", /* 0x20 */ "REG_OUT_ADDR", /* 0x24 */ "REG_OUT_GS", /* 0x28 */ "REG_OUT_STRIDE", /* 0x2c */ "RSZ_COEF_INDEX", /* 0x30 */ "REG_CSC_C0_COEF", /* 0x34 */ "REG_CSC_C1_COEF", /* 0x38 */ "REG_CSC_C2_COEF", /* 0x3c */ "REG_CSC_C3_COEF", /* 0x40 */ "REG_CSC_C4_COEF", /* 0x44 */ };int jz47_dump_ipu_regs(int num){ int i, total; if (num >= 0) { //printf ("ipu_reg: %s: 0x%x\n", ipu_regs_name[num >> 2], REG32(ipu_vbase + num)); return 1; } if (num == -1) { total = sizeof (ipu_regs_name) / sizeof (char *); for (i = 0; i < total; i++) printf ("ipu_reg: %s: 0x%x\n", ipu_regs_name[i], REG32(ipu_vbase + (i << 2))); } if (num == -2) { for (i = 0; i < IPU_LUT_LEN; i++) printf ("ipu_H_LUT(%d): 0x%x\n", i, REG32(ipu_vbase + HRSZ_LUT_BASE + i * 4)); for (i = 0; i < IPU_LUT_LEN; i++) printf ("ipu_V_LUT(%d): 0x%x\n", i, REG32(ipu_vbase + VRSZ_LUT_BASE + i * 4)); } return 1;}/* set ipu data format. */int jz47_set_ipu_csc_cfg (img_param_t *img, int outW, int outH, int Wdiff, int Hdiff){ unsigned int in_fmt = 0, out_fmt = 0; printf("img->in_width\t= %d\n", img->in_width); printf("img->in_height\t= %d\n", img->in_height); printf("img->in_bpp \t=%d\n", img->in_bpp); printf("img->out_width\t= %d\n", img->out_width); printf("img->out_height\t= %d\n", img->out_height); printf("img->y_buf \t= 0x%08x\n", (unsigned int)img->y_buf); printf("img->u_buf \t= 0x%08x\n", (unsigned int)img->u_buf); printf("img->v_buf \t= 0x%08x\n", (unsigned int)img->v_buf); in_fmt = img->in_fmt; switch (in_fmt) { case INFMT_YCbCr420: case INFMT_YUV420: Hdiff = (Hdiff + 1) & ~1; Wdiff = (Wdiff + 1) & ~1; break; case INFMT_YCbCr422: case INFMT_YUV422: Wdiff = (Wdiff + 1) & ~1; break; case INFMT_YCbCr444: case INFMT_YCbCr411: case INFMT_YUV444: case INFMT_YUV411: break; default: printf("Error: Input data format isn't support\n"); return -1; } out_width =outW; out_height=outH; printf ("++ out_width = %d, out_heigth = %d ++\n", out_width, out_height); switch (fb_bpp) { case 16: out_fmt = OUTFMT_RGB565; outW = outW << 1; break; default: out_fmt = OUTFMT_RGB888; outW = outW << 2; break; }// Set GS register REG32(ipu_vbase + REG_IN_FM_GS) = IN_FM_W((img->in_width - Wdiff) & ~0x1) | IN_FM_H((img->in_height - Hdiff) & ~0x1); REG32(ipu_vbase + REG_OUT_GS) = OUT_FM_W(outW) | OUT_FM_H(outH);// set Format REG32(ipu_vbase + REG_D_FMT) = in_fmt | out_fmt;// set parameter REG32(ipu_vbase + REG_CSC_C0_COEF) = YUV_CSC_C0; REG32(ipu_vbase + REG_CSC_C1_COEF) = YUV_CSC_C1; REG32(ipu_vbase + REG_CSC_C2_COEF) = YUV_CSC_C2; REG32(ipu_vbase + REG_CSC_C3_COEF) = YUV_CSC_C3; REG32(ipu_vbase + REG_CSC_C4_COEF) = YUV_CSC_C4; return 0;}int init_ipu_ratio_table (){ int i, j, cnt; float r, min, diff; get_ipu_ratio_table( (void **)&ipu_ratio_table, (IPU_LUT_LEN) * (IPU_LUT_LEN)*sizeof(struct Ration2m) ); // orig table, first calculate for (i = 1; i <= (IPU_LUT_LEN); i++) for (j = 1; j <= (IPU_LUT_LEN); j++) { ipu_ratio_table [(i - 1) * 20 + j - 1].ratio = i / (float)j; ipu_ratio_table [(i - 1) * 20 + j - 1].n = i; ipu_ratio_table [(i - 1) * 20 + j - 1].m = j; }// Eliminate the ratio greater than 1:2 for (i = 0; i < (IPU_LUT_LEN) * (IPU_LUT_LEN); i++) if (ipu_ratio_table[i].ratio < 0.4999) ipu_ratio_table[i].n = ipu_ratio_table[i].m = -1;// eliminate the same ratio for (i = 0; i < (IPU_LUT_LEN) * (IPU_LUT_LEN); i++) for (j = i + 1; j < (IPU_LUT_LEN) * (IPU_LUT_LEN); j++) { diff = ipu_ratio_table[i].ratio - ipu_ratio_table[j].ratio; if (diff > -0.001 && diff < 0.001) { ipu_ratio_table[j].n = -1; ipu_ratio_table[j].m = -1; } }// reorder ipu_ratio_tablecnt = 0; for (i = 0; i < (IPU_LUT_LEN) * (IPU_LUT_LEN); i++) if (ipu_ratio_table[i].n != -1) { if (cnt != i) ipu_ratio_table[cnt] = ipu_ratio_table[i]; cnt++; } ipu_rtable_len = cnt; //printf ("ipu_rtable_len = %d\n", ipu_rtable_len); return 0;}int find_ipu_ratio_factor (float ratio){ int i, sel; float diff, min=100; sel = ipu_rtable_len; for (i = 0; i < ipu_rtable_len; i++) { if (ratio > ipu_ratio_table[i].ratio) diff = ratio - ipu_ratio_table[i].ratio; else diff = ipu_ratio_table[i].ratio - ratio; if (diff < min || i == 0) { min = diff; sel = i; } } printf ("resize: sel = %d, n=%d, m=%d\n", sel, ipu_ratio_table[sel].n, ipu_ratio_table[sel].m); return sel;}int resize_lut_cal (int srcN, int dstM, int upScale, rsz_lut lut[]);int resize_out_cal (int insize, int outsize, int srcN, int dstM, int upScale, int *diff);int jz47_set_ipu_resize (img_param_t *img, int *outWp, int *outHp, int *Wdiff, int *Hdiff){ static int W = 0, H = 0, Hsel = 0, Wsel = 0; int srcN, dstM, width_up, height_up; int Height_lut_max, Width_lut_max; int i; rsize_w = (rsize_w == 0) ? img->out_width : rsize_w; rsize_h = (rsize_h == 0) ? img->out_height : rsize_h; rsize_w = (rsize_w > fb_w) ? fb_w : rsize_w; rsize_h = (rsize_h > fb_h) ? fb_h : rsize_h; *outWp = rsize_w; *outHp = rsize_h; *Wdiff = *Hdiff = 0;// Don't need do resize ? if (((img->in_width == rsize_w) && (img->in_height == rsize_h)) || (rsize_w > 2 * img->in_width) || (rsize_h > 2 * img->in_height)) { disable_rsize (ipu_vbase); return 0; }// init the resize factor table if (!ipu_rtable_init) { init_ipu_ratio_table (); ipu_rtable_init = 1; }// enable resize enable_rsize (ipu_vbase);// get the resize factor if (W != rsize_w) { Wsel = find_ipu_ratio_factor(((float) img->in_width)/rsize_w); W = rsize_w; } if (H != rsize_h) { Hsel = find_ipu_ratio_factor(((float) img->in_height)/rsize_h); H = rsize_h; }// set IPU_CTRL register
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -