📄 ipu.c
字号:
width_up = rsize_w >= img->in_width; height_up = rsize_h >= img->in_height; REG32(ipu_vbase + REG_CTRL) |= (height_up << V_SCALE_SHIFT) | (width_up << H_SCALE_SHIFT);// set IPU_INDEX register Width_lut_max = width_up ? ipu_ratio_table[Wsel].m : ipu_ratio_table[Wsel].n; Height_lut_max = height_up ? ipu_ratio_table[Hsel].m : ipu_ratio_table[Hsel].n; REG32(ipu_vbase + REG_RSZ_COEF_INDEX) = ((Height_lut_max - 1) << VE_IDX_SFT) | ((Width_lut_max - 1) << HE_IDX_SFT);// calculate out W/H and LUT srcN = ipu_ratio_table[Wsel].n; dstM = ipu_ratio_table[Wsel].m; *outWp = resize_out_cal ( img->in_width, rsize_w, srcN, dstM, width_up, Wdiff); resize_lut_cal (srcN, dstM, width_up, h_lut); srcN = ipu_ratio_table[Hsel].n; dstM = ipu_ratio_table[Hsel].m; *outHp = resize_out_cal ( img->in_height, rsize_h, srcN, dstM, height_up, Hdiff); resize_lut_cal (srcN, dstM, height_up, v_lut);// set IPU LUT register for (i = 0; i < Height_lut_max; i++) REG32(ipu_vbase + VRSZ_LUT_BASE + i * 4) = (v_lut[i].coef << W_COEF_SFT) | (v_lut[i].in_n << IN_N_SFT) | (v_lut[i].out_n << OUT_N_SFT); for (i = 0; i < Width_lut_max; i++) REG32(ipu_vbase + HRSZ_LUT_BASE + i * 4) = (h_lut[i].coef << W_COEF_SFT) | (h_lut[i].in_n << IN_N_SFT) | (h_lut[i].out_n << OUT_N_SFT); return 0;}int resize_out_cal (int insize, int outsize, int srcN, int dstM, int upScale, int *diff){ int calsize, delta; float tmp, tmp2; delta = 1; do { tmp = (int)((insize - delta) * dstM / (float)srcN); tmp2 = tmp * srcN / dstM; if (upScale) { if (tmp2 == insize - delta) calsize = tmp + 1; else calsize = tmp + 2; } else // down Scale { if (tmp2 == insize - delta) calsize = tmp; else calsize = tmp + 1; } delta++; } while (calsize > outsize); *diff = delta - 2; return calsize;}int resize_lut_cal (int srcN, int dstM, int upScale, rsz_lut lut[]){ int i, t, x; float w_coef, factor, factor2; if (upScale) { for (i = 0, t=0; i < dstM; i++) { factor = (float) (i * srcN) / (float)dstM; factor2 = factor - (int)factor; w_coef = 1.0 - factor2; lut[i].coef = (unsigned int)(128.0 * w_coef);// calculate in & out lut[i].out_n = 1; if (t <= factor) { lut[i].in_n = 1; t++; } else lut[i].in_n = 0; } // end for } else { for (i = 0, t = 0, x = 0; i < srcN; i++) { factor = (float) (t * srcN + 1) / (float)dstM; if (dstM == 1) {// calculate in & out lut[i].coef = (i == 0) ? 64 : 0; lut[i].out_n = (i == 0) ? 1 : 0; } else if (((t * srcN + 1) / dstM - i) >= 1) lut[i].coef = 0; else if (factor - i == 0) { lut[i].coef = 128; t++; } else { factor2 = (float) (t * srcN) / (float)dstM; factor = factor - (int)factor2; w_coef = 1.0 - factor; lut[i].coef = (unsigned int)(128.0*w_coef); t++; }// calculate in & out lut[i].in_n = 1; if (dstM != 1) { if (((x * srcN + 1) / dstM - i) >= 1) lut[i].out_n = 0; else { lut[i].out_n = 1; x++; } } } /* for end down Scale*/ } /* else upScale */ return 0;}int jz47_ipu_init (img_param_t *img){ int ret; int outW, outH, Wdiff, Hdiff; outW = img->out_width; outH = img->out_height; if (!ipu_inited) {//init screen_offset = (fb_h-outH)/2*fb_line_len + (fb_w-outW)*fb_bpp/16; stop_ipu (ipu_vbase); reset_ipu (ipu_vbase); clear_end_flag (ipu_vbase);//disable irq disable_irq(ipu_vbase);// set IPU resize field jz47_set_ipu_resize (img, &outW, &outH, &Wdiff, &Hdiff);// set CSC parameter and format ret = jz47_set_ipu_csc_cfg(img, outW, outH, Wdiff, Hdiff); if (ret) return ret;// set out frame buffer REG32(ipu_vbase + REG_OUT_ADDR) = phy_fb + screen_offset; REG32(IPU_VBASE + REG_OUT_STRIDE) = fb_line_len;// ipu_inited = 1; ipu_size_cfg = 0; } else if (ipu_size_cfg) {// set IPU resize field screen_offset = (fb_h-outH)/2*fb_line_len + (fb_w-outW)*fb_bpp/16; REG32(ipu_vbase + REG_OUT_ADDR) = phy_fb + screen_offset; jz47_set_ipu_resize (img, &outW, &outH, &Wdiff, &Hdiff);// set CSC parameter and format ret = jz47_set_ipu_csc_cfg(img, outW, outH, Wdiff, Hdiff); if (ret) return ret; ipu_size_cfg = 0; } return 0; }void ipu_image_start(){ ipu_inited = 0; ipu_image_completed = 0; rsize_w = 0; rsize_h = 0;}void ipu_outsize_changed(int x,int y,int w, int h){ //int offset_x =x; //int offset_y =y; if ((w==0) && (h==0)) { if ((rsize_w == 0) && ( rsize_h == 0)) return; rsize_w = 0; rsize_h = 0; ipu_size_cfg = 1; } else { if (rsize_w != w || rsize_h != h) { rsize_w = w; rsize_h = h; ipu_size_cfg = 1; } }}int jz47_put_image_with_ipu (img_param_t *img){ int ret; unsigned int paddr; ipu_vbase = (volatile unsigned char *)IPU_VBASE; if (!get_fbinfo_already) { get_fbaddr_info(); get_fbinfo_already = 1; } ret = jz47_ipu_init (img); while ((!polling_end_flag(ipu_vbase)) && ipu_is_enable(ipu_vbase)) ; stop_ipu(ipu_vbase); clear_end_flag(ipu_vbase); paddr = PHYS ((unsigned int)img->y_buf); if (paddr == 0) { printf ("++ Can not found Y buffer(0x%x) physical addr since addr errors +++\n", (unsigned int)img->y_buf); return -1; } REG32(ipu_vbase + REG_Y_ADDR) = paddr;// set U addr register (mpi->planes[1]) paddr = PHYS ((unsigned int)img->u_buf); if (paddr == 0) { printf ("++ Can not found U buffer(0x%x) physical addr since addr errors +++\n", (unsigned int)img->u_buf); return -1; } REG32(ipu_vbase + REG_U_ADDR) = paddr;// set V addr register (mpi->planes[2]) paddr = PHYS ((unsigned int)img->v_buf); if (paddr == 0) { printf ("++ Can not found V buffer(0x%x) physical addr since addr errors +++\n", (unsigned int)img->v_buf); return -1; } REG32(ipu_vbase + REG_V_ADDR) = paddr;// set Y(mpi->stride[0]) U(mpi->stride[1]) V(mpi->stride[2]) stride REG32(ipu_vbase + REG_Y_STRIDE) = img->in_width; switch(img->in_fmt) { case INFMT_YCbCr420: case INFMT_YCbCr422: case INFMT_YUV420: case INFMT_YUV422: REG32(ipu_vbase + REG_UV_STRIDE) = U_STRIDE(img->in_width/2 ) | V_STRIDE(img->in_width/2); break; case INFMT_YCbCr444: case INFMT_YUV444: REG32(ipu_vbase + REG_UV_STRIDE) = U_STRIDE(img->in_width ) | V_STRIDE(img->in_width); break; case INFMT_YCbCr411: case INFMT_YUV411: REG32(ipu_vbase + REG_UV_STRIDE) = U_STRIDE(img->in_width/4) | V_STRIDE(img->in_width/4); break; default: printf("Error: Input data format isn't support\n"); return -1; } // flush the dcache __dcache_writeback_all();// start ipu run_ipu(ipu_vbase); ipu_image_completed = 1; jz47_dump_ipu_regs(-1); return 0;}void ipu_data_transer(void) { phy_fb= lcd_get_change_phyframe(); REG32(ipu_vbase + REG_OUT_ADDR) = phy_fb + screen_offset; run_ipu(ipu_vbase);}void ipu_wait_end(void){ while ((!polling_end_flag(IPU_VBASE)) && ipu_is_enable(IPU_VBASE)); stop_ipu(ipu_vbase); clear_end_flag(ipu_vbase);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -