/** * @file fbdev.c * */ /********************* * INCLUDES *********************/ #include "fbdev.h" #include "hd_gfx.h" #include "vendor_gfx.h" #include "hd_common.h" #include #include #if defined(_UI_STYLE_LVGL_) #include "PrjInc.h" #endif #if USE_FBDEV || USE_BSD_FBDEV #include #include #include #include #include #if !defined(__FREERTOS) #include #include #endif #if USE_BSD_FBDEV #include #include #include #include #else /* USE_BSD_FBDEV */ #if !defined(__FREERTOS) #include #endif #endif /* USE_BSD_FBDEV */ /********************* * DEFINES *********************/ #ifndef FBDEV_PATH #define FBDEV_PATH "/dev/fb0" #endif //#define FBDEV_DBG #ifdef FBDEV_DBG #define fbdev_msg printf #else #define fbdev_msg(...) #endif //#define FBDEV_PERF #ifdef FBDEV_PERF #define fbdev_perf printf #else #define fbdev_perf(...) #endif /********************** * TYPEDEFS **********************/ /********************** * STRUCTURES **********************/ #if (USE_BSD_FBDEV || defined(__FREERTOS)) struct bsd_fb_var_info{ int32_t xoffset; int32_t yoffset; int32_t xres; int32_t yres; int bits_per_pixel; }; struct bsd_fb_fix_info{ long int line_length; long int smem_len; }; #endif /********************** * Function Declaration **********************/ HD_RESULT LVGL_rotate_fb(UINT32 dst_pa, UINT32 src_pa,lv_disp_drv_t * disp_drv,UINT32 fmt); /********************** * STATIC VARIABLES **********************/ #if USE_BSD_FBDEV static struct bsd_fb_var_info vinfo; static struct bsd_fb_fix_info finfo; #else #if !defined(__FREERTOS) static struct fb_var_screeninfo vinfo; static struct fb_fix_screeninfo finfo; #else #include "sys_mempool.h" #include "vendor_videoout.h" static struct bsd_fb_var_info vinfo; //static struct bsd_fb_fix_info finfo; #define FBIOPAN_DISPLAY (0x1) #endif #endif /* USE_BSD_FBDEV */ #if LV_COLOR_DEPTH == 24 HD_RESULT disp_gfx_copy_8565(UINT32 dst_pa, UINT32 src_pa,lv_disp_drv_t * disp_drv); HD_RESULT disp_gfx_rotate_8565(UINT32 dst_pa, UINT32 src_pa,lv_disp_drv_t * disp_drv); void lv_gpu_nvt_dma2d_rotate_8565(lv_color_t * buf, lv_coord_t buf_w, const lv_color_t * map, lv_coord_t map_w, lv_area_t area, UINT32 dir); #endif void lv_gpu_nvt_dma2d_rotate(lv_color_t * buf, lv_coord_t buf_w, const lv_color_t * map, lv_coord_t map_w, lv_area_t area, UINT32 dir, bool flush); char *fbp = 0; long int screensize = 0; static UINT32 buf1_pa; #if LV_USE_GPU_NVT_DMA2D #include "lvgl/src/lv_gpu/lv_gpu_nvt_dma2d.h" static UINT32 hdal_fmt=DISPLAY_HDAL_OSD_FMT; //for gfx need hdal fmt #endif static int fbfd = 0; /********************** * MACROS **********************/ /********************** * GLOBAL FUNCTIONS **********************/ /********************************************* * IMPORTANT! * * Do not edit lv_user_rounder_callback * *********************************************/ void lv_user_rounder_callback( lv_disp_drv_t* disp_drv, lv_area_t* area) { #if LV_USE_GPU_NVT_DMA2D == 1 #if LV_COLOR_DEPTH != 8 #if LV_USER_CFG_USE_ROTATE_BUFFER uint8_t alignment = 16; #else uint8_t alignment = 4; #endif area->x1 = ALIGN_FLOOR(area->x1, alignment); area->y1 = ALIGN_FLOOR(area->y1, alignment); lv_coord_t copy_w = (area->x2 - area->x1) + 1; lv_coord_t copy_h = (area->y2 - area->y1) + 1; uint8_t remainder_copy_w = copy_w % alignment; uint8_t remainder_copy_h = copy_h % alignment; if(area->x1 == area->x2){ area->x2 += (alignment - 1); } else if(remainder_copy_w){ area->x2 += (alignment - remainder_copy_w); } if( (area->y1 == area->y2)){ area->y2 += (alignment - 1); } else if(remainder_copy_h){ area->y2 += (alignment - remainder_copy_h); } /* check out of area, LV_MAX_RES_HOR & LV_MAX_RES_VER should be aligned too. */ if(area->x2 > (disp_drv->hor_res - 1)) area->x2 = disp_drv->hor_res - 1; if(area->y2 > (disp_drv->ver_res - 1)) area->y2 = disp_drv->ver_res - 1; #else /******************************************************************* * invalidate area update still has issues for LV_COLOR_DEPTH = 8, * keep fully update. ******************************************************************/ area->x1 = 0; area->y1 = 0; area->x2 = disp_drv->hor_res - 1; area->y2 = disp_drv->ver_res - 1; #endif #endif } /** * Flush a buffer to the marked area * @param x1 left coordinate * @param y1 top coordinate * @param x2 right coordinate * @param y2 bottom coordinate * @param color_p an array of colors */ void fbdev_flush(int32_t x1, int32_t y1, int32_t x2, int32_t y2, const lv_color_t * color_p) { if(fbp == NULL) return; fbdev_msg("fbdev_flush : %d,%d,%d,%d {%lu, %lu, %lu, %lu}\r\n",x1,y1,x2,y2, vinfo.xres, vinfo.xoffset, vinfo.yres, vinfo.yoffset); /*Return if the area is out the screen*/ if(x2 < 0) return; if(y2 < 0) return; if(x1 > (int32_t)(vinfo.xres) - 1) return; if(y1 > (int32_t)(vinfo.yres) - 1) return; /*Truncate the area to the screen*/ int32_t act_x1 = x1 < 0 ? 0 : x1; int32_t act_y1 = y1 < 0 ? 0 : y1; int32_t act_x2 = x2 > (int32_t)(vinfo.xres) - 1 ? (int32_t)(vinfo.xres) - 1 : x2; int32_t act_y2 = y2 > (int32_t)(vinfo.yres) - 1 ? (int32_t)(vinfo.yres) - 1 : y2; long int location = 0; /*32 or 24 bit per pixel*/ if(vinfo.bits_per_pixel == 32) { uint32_t *fbp32 = (uint32_t*)fbp; for(int32_t y = act_y1; y <= act_y2; y++) { for(int32_t x = act_x1; x <= act_x2; x++) { location = x + y * vinfo.xres; fbp32[location] = lv_color_to32(*color_p); color_p++; } color_p += x2 - act_x2; } } /*16 bit per pixel*/ else if(vinfo.bits_per_pixel == 16) { uint16_t *fbp16 = (uint16_t*)fbp; for(int32_t y = act_y1; y <= act_y2; y++) { for(int32_t x = act_x1; x <= act_x2; x++) { location = x + y * vinfo.xres; fbp16[location] = color_p->full; color_p++; } color_p += x2 - act_x2; } } /********************************************************************************** * 24 bit per pixel * * IMPORTANT!! * * set_px_cb is set in LV_COLOR_DEPTH = 24, color_p is already a two plane buffer, * do not get pixel data by accessing member of lv_color_t * **********************************************************************************/ else if(vinfo.bits_per_pixel == 24) { /* RGB plane*/ uint16_t *fbp16 = (uint16_t*)fbp; uint16_t *color_p16 = (uint16_t*)color_p; /* Alpha plane, 565 = 2 bytes, shift to alpha address */ uint8_t *fbp8 = (uint8_t*)fbp; uint8_t *color_p8 = (uint8_t*)color_p; fbp8 += (vinfo.yres * vinfo.xres * sizeof(color_p->full)); color_p8 += (vinfo.yres * vinfo.xres * sizeof(color_p->full)); for(int32_t y = act_y1 ; y <= act_y2 ; y++) { for( int32_t x = act_x1 ; x <= act_x2 ; x++) { location = x + y * vinfo.xres; fbp16[location] = color_p16[location]; fbp8[location] = color_p8[location]; } } } /*8 bit per pixel*/ else if(vinfo.bits_per_pixel == 8) { uint8_t *fbp8 = (uint8_t*)fbp; for(int32_t y = act_y1 ; y <= act_y2 ; y++) { for(int32_t x = act_x1 ; x <= act_x2 ; x++) { location = x + y * vinfo.xres; fbp8[location] = color_p->full; color_p++; } color_p += x2 - act_x2; } } else { LV_LOG_ERROR("current vinfo.bits_per_pixel(%d) is not supported!", vinfo.bits_per_pixel); } } #if !defined(__FREERTOS) void fbdev_init(void) { // Open the file for reading and writing int count =1000; HD_COMMON_MEM_VIRT_INFO vir_meminfo = {0}; int ERcode; while(count){ fbfd = open(FBDEV_PATH, O_RDWR); if (fbfd<0) { usleep(10); count--; } else { break; } } if(fbfd == -1) { perror("Error: cannot open framebuffer device"); return; } fbdev_msg("The framebuffer device was opened successfully.~~~~\n"); // Get fixed screen information if(ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo) == -1) { perror("Error reading fixed information"); return; } // Get variable screen information if(ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo) == -1) { perror("Error reading variable information"); return; } vinfo.xres_virtual = vinfo.xres; #if LV_USER_CFG_USE_TWO_BUFFER vinfo.yres_virtual = vinfo.yres * 2; #else vinfo.yres_virtual = vinfo.yres; #endif if (ioctl(fbfd, FBIOPUT_VSCREENINFO, &vinfo) == -1) { perror("Could not set variable screen info!\n"); return; } fbdev_msg("The mem is :%d\n",finfo.smem_len); fbdev_msg("The line_length is :%d\n",finfo.line_length); fbdev_msg("The xres is :%d\n",vinfo.xres); fbdev_msg("The yres is :%d\n",vinfo.yres); fbdev_msg("bits_per_pixel is :%d\n",vinfo.bits_per_pixel); fbdev_msg("The yres_virtual is :%d\n",vinfo.yres_virtual); // Figure out the size of the screen in bytes screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8; fbdev_msg("screen size = %u xres = %u yres = %u bpp = %u\r\n", screensize, vinfo.xres , vinfo.yres , vinfo.bits_per_pixel); // Map the device to memory fbp = (char *)mmap(0, finfo.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0); if((intptr_t)fbp == -1) { perror("Error: failed to map framebuffer device to memory"); return; } memset(fbp, 0, screensize); fbdev_msg("The framebuffer device was mapped to memory successfully.\n"); vir_meminfo.va = (void *)(fbp); ERcode = hd_common_mem_get(HD_COMMON_MEM_PARAM_VIRT_INFO, &vir_meminfo); if ( ERcode != HD_OK) { fbdev_msg("_DC_bltDestOffset map fail %d\n",ERcode); return; } buf1_pa = vir_meminfo.pa; } void fbdev_exit(void) { close(fbfd); } #else // __FREERTOS #define ioctl fbdev_ioctl int fbdev_ioctl(int f, unsigned int cmd, void *arg) { int ret = 0; switch(cmd){ case FBIOPAN_DISPLAY : { VENDOR_FB_INIT fb_init; struct bsd_fb_var_info *my_vinfo =arg; //assign bf buffer to FB_INIT fb_init.fb_id = HD_FB0; fb_init.pa_addr = (int) fbp + (my_vinfo->xres * my_vinfo->yoffset * (my_vinfo->bits_per_pixel / 8)); fb_init.buf_len = (my_vinfo->xres * my_vinfo->yres * (my_vinfo->bits_per_pixel / 8)); fbdev_msg("pa_addr 0x%x buf_len 0x%x \r\n",fb_init.pa_addr,fb_init.buf_len); ret = vendor_videoout_set(VENDOR_VIDEOOUT_ID0, VENDOR_VIDEOOUT_ITEM_FB_INIT, &fb_init); return ret; }; break; default : printf("unsupport cmd = %d\r\n", cmd); break; }; return ret; } void fbdev_init(void) { screensize = OSD_SCREEN_SIZE; fbp = (char *)mempool_disp_osd1_pa; buf1_pa = mempool_disp_osd1_pa; memset(fbp,0,POOL_SIZE_OSD); memset((void *)&vinfo,0,sizeof(struct bsd_fb_var_info)); vinfo.xoffset = 0; vinfo.yoffset = 0; vinfo.xres = DISPLAY_OSD_W; vinfo.yres = DISPLAY_OSD_H; vinfo.bits_per_pixel = LV_COLOR_DEPTH; fbfd =1; fbdev_msg("The xres is :%d\n",vinfo.xres); fbdev_msg("The yres is :%d\n",vinfo.yres); fbdev_msg("bits_per_pixel is :%d\n",vinfo.bits_per_pixel); } void fbdev_exit(void) { fbfd =0; } #endif #include "kwrap/debug.h" #if LV_USE_GPU_NVT_DMA2D static UINT32 disp_get_dst_va(lv_disp_drv_t * disp_drv) { UINT32 dst_va; #if LV_USER_CFG_USE_TWO_BUFFER if(vinfo.yoffset == 0){ dst_va = (UINT32)fbp + screensize; } else{ dst_va = (UINT32)fbp; } #else dst_va = (UINT32)fbp; #endif return dst_va; } static void disp_set_pan_display(lv_disp_drv_t * disp_drv) { #if LV_USER_CFG_USE_TWO_BUFFER UINT32 fpb_scr, fpb_dst; const lv_area_t area = {0, 0, disp_drv->hor_res - 1, disp_drv->ver_res - 1}; /* check is last chunk */ if(disp_drv->buffer->flushing_last){ if(vinfo.yoffset == 0){ vinfo.yoffset = vinfo.yres; fpb_scr = (UINT32)fbp + screensize; fpb_dst = (UINT32)fbp; } else{ vinfo.yoffset = 0; fpb_scr = (UINT32)fbp; fpb_dst = (UINT32)fbp + screensize; } if (ioctl(fbfd, FBIOPAN_DISPLAY, &vinfo)) { fbdev_msg("Error to do pan display. %s\n",strerror(errno)); } lv_gpu_nvt_dma2d_copy( (lv_color_t *) fpb_scr, disp_drv->hor_res, disp_drv->ver_res, (lv_color_t *) fpb_dst, disp_drv->hor_res, disp_drv->ver_res, &area, true ); } #endif } /* Flush the content of the internal buffer the specific area on the display * You can use DMA or any hardware acceleration to do this operation in the background but * 'lv_disp_flush_ready()' has to be called when finished. */ #if (LV_COLOR_DEPTH == 24) #if LV_USER_CFG_USE_ROTATE_BUFFER void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p) { UINT32 dst_va = disp_get_dst_va(disp_drv); lv_gpu_nvt_dma2d_rotate_8565( (lv_color_t *)dst_va, disp_drv->hor_res, (lv_color_t *)color_p, disp_drv->hor_res, *area, VDO_ROTATE_DIR); disp_set_pan_display(disp_drv); lv_disp_flush_ready(disp_drv); } #else void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p) { UINT32 dst_va = disp_get_dst_va(disp_drv); #if 1 lv_gpu_nvt_dma2d_copy( color_p, disp_drv->hor_res, disp_drv->ver_res, (lv_color_t *)dst_va, disp_drv->hor_res, disp_drv->ver_res, area, true ); #else /* CPU flush for debugging */ uint32_t location, location2; const uint32_t alpha_offset = LV_HOR_RES_MAX * LV_VER_RES_MAX * 2; for(int i=area->x1 ; i<=area->x2 ; i++) { for(int j=area->y1 ; j<=area->y2 ; j++) { location = i + j * disp_drv->hor_res; location2 = (i-area->x1) + (j-area->y1) * disp_drv->hor_res; *(((uint16_t*)dst_va) + location ) = *((uint16_t*)(vir_meminfo.va) + location2); *((uint8_t*)(dst_va + alpha_offset + location)) = *((uint8_t*)(vir_meminfo.va) + location2 + alpha_offset); } } hd_common_mem_flush_cache(color_p, disp_drv->hor_res * disp_drv->ver_res * sizeof(lv_color_t)); #endif disp_set_pan_display(disp_drv); lv_disp_flush_ready(disp_drv); } #endif #else /* 32 & 8 */ #if LV_USER_CFG_USE_ROTATE_BUFFER void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p) { UINT32 dst_va = disp_get_dst_va(disp_drv); lv_gpu_nvt_dma2d_rotate( (lv_color_t *)dst_va, disp_drv->hor_res, (lv_color_t *)color_p, disp_drv->hor_res, *area, VDO_ROTATE_DIR, true); disp_set_pan_display(disp_drv); lv_disp_flush_ready(disp_drv); } #else void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p) { UINT32 dst_va = disp_get_dst_va(disp_drv); lv_gpu_nvt_dma2d_copy( color_p, lv_area_get_width(area), lv_area_get_height(area), (lv_color_t *)dst_va, disp_drv->hor_res, disp_drv->ver_res, area, true ); disp_set_pan_display(disp_drv); lv_disp_flush_ready(disp_drv); } #endif #endif #else /* Flush the content of the internal buffer the specific area on the display * You can use DMA or any hardware acceleration to do this operation in the background but * 'lv_disp_flush_ready()' has to be called when finished. */ void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p) { fbdev_flush(area->x1,area->y1,area->x2,area->y2,color_p); lv_disp_flush_ready(disp_drv); } #endif #if LV_USE_GPU_NVT_DMA2D #if LV_COLOR_DEPTH == 24 void set_px_cb_8565( struct _disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y, lv_color_t color, lv_opa_t opa) { /* buf should be disp_drv->buffer->buf_act */ if(buf == disp_drv->buffer->buf_act){ static const uint32_t px_size_rgb = sizeof(color.full); static const uint32_t offset = LV_HOR_RES_MAX * LV_VER_RES_MAX * px_size_rgb; uint32_t location = x + y * vinfo.xres; lv_color_t color_buf; lv_color_t color_mix; color_buf.full = *(((uint16_t*)buf) + location); color_buf.ext_ch.alpha = *(buf + offset + location); lv_color_mix_with_alpha( color_buf, (lv_opa_t) color_buf.ext_ch.alpha, color, opa, &color_mix, (lv_opa_t*)&color_mix.ext_ch.alpha); /* RGB plane*/ *(((uint16_t*)buf) + location) = color_mix.full; /* Alpha plane, 565 = 2 bytes, shift to alpha address */ *(buf + offset + location) = color_mix.ext_ch.alpha; } else{ LV_LOG_WARN("buf != disp_drv->buffer->buf_act"); } } void lv_gpu_nvt_dma2d_rotate_8565(lv_color_t * buf, lv_coord_t buf_w, const lv_color_t * map, lv_coord_t map_w, lv_area_t area, UINT32 dir) { UINT32 dst_pa = 0; UINT32 src_pa = 0; HD_GFX_ROTATE param = {0}; HD_RESULT ret = HD_OK; HD_COMMON_MEM_VIRT_INFO vir_meminfo = {0}; lv_coord_t copy_w = (area.x2 - area.x1) + 1; lv_coord_t copy_h = (area.y2 - area.y1) + 1; bool swap_xy = false; HD_IPOINT dst_pos = {-1, -1}; const uint8_t pixel_size_rgb = sizeof(LV_COLOR_BLACK.full); const uint8_t pixel_size_alpha = sizeof(LV_COLOR_BLACK.ext_ch.alpha); const uint32_t alpha_offset = LV_VER_RES_MAX * LV_HOR_RES_MAX * pixel_size_rgb; /* convert va to pa */ vir_meminfo.va = (void *)(map); if ( hd_common_mem_get(HD_COMMON_MEM_PARAM_VIRT_INFO, &vir_meminfo) != HD_OK) { fbdev_msg("convert map failed!\n"); return; } src_pa = vir_meminfo.pa; vir_meminfo.va = (void *)(buf); if ( hd_common_mem_get(HD_COMMON_MEM_PARAM_VIRT_INFO, &vir_meminfo) != HD_OK) { fbdev_msg("convert buf failed!\n"); return; } dst_pa = vir_meminfo.pa; memset(¶m, 0, sizeof(HD_GFX_ROTATE)); /* check dir */ switch(dir) { case HD_VIDEO_DIR_ROTATE_90: dst_pos = (HD_IPOINT){LV_VER_RES_MAX - area.y1 - copy_h, area.x1}; swap_xy = true; break; case HD_VIDEO_DIR_ROTATE_270: dst_pos = (HD_IPOINT){area.y1, LV_HOR_RES_MAX - area.x1 - copy_w}; swap_xy = true; break; case HD_VIDEO_DIR_ROTATE_180: dst_pos = (HD_IPOINT){LV_HOR_RES_MAX - area.x1 - copy_w, LV_VER_RES_MAX - area.y1 - copy_h}; swap_xy = false; break; default: LV_LOG_ERROR("dir(%lx) is currently not supported", dir); return; } /* rotate rgb channels */ param.src_img.dim.w = LV_HOR_RES_MAX; param.src_img.dim.h = LV_VER_RES_MAX; param.src_img.p_phy_addr[0] = src_pa; param.src_img.lineoffset[0] = LV_HOR_RES_MAX * pixel_size_rgb; param.src_img.format = HD_VIDEO_PXLFMT_RGB565; param.src_region.x = 0; param.src_region.y = 0; param.src_region.w = copy_w; param.src_region.h = copy_h; param.dst_img.format = HD_VIDEO_PXLFMT_RGB565; param.dst_img.dim.w = swap_xy ? LV_VER_RES_MAX : LV_HOR_RES_MAX; param.dst_img.dim.h = swap_xy ? LV_HOR_RES_MAX : LV_VER_RES_MAX; param.dst_img.p_phy_addr[0] = dst_pa; param.dst_img.lineoffset[0] = (swap_xy ? LV_VER_RES_MAX : LV_HOR_RES_MAX) * pixel_size_rgb; param.dst_pos = dst_pos; param.angle = dir; ret = hd_gfx_rotate(¶m); if(ret != HD_OK){ fbdev_msg("ret = %d\n", ret); } /* rotate alpha channel */ param.src_img.dim.w = LV_HOR_RES_MAX; param.src_img.dim.h = LV_VER_RES_MAX; param.src_img.p_phy_addr[0] = src_pa + alpha_offset; param.src_img.lineoffset[0] = LV_HOR_RES_MAX * pixel_size_alpha; param.src_img.format = HD_VIDEO_PXLFMT_I8; param.src_region.x = 0; param.src_region.y = 0; param.src_region.w = copy_w; param.src_region.h = copy_h; param.dst_img.format = HD_VIDEO_PXLFMT_I8; param.dst_img.dim.w = swap_xy ? LV_VER_RES_MAX : LV_HOR_RES_MAX; param.dst_img.dim.h = swap_xy ? LV_HOR_RES_MAX : LV_VER_RES_MAX; param.dst_img.p_phy_addr[0] = dst_pa + alpha_offset; param.dst_img.lineoffset[0] = (swap_xy ? LV_VER_RES_MAX : LV_HOR_RES_MAX) * pixel_size_alpha; param.dst_pos = dst_pos; param.angle = dir; ret = hd_gfx_rotate(¶m); if(ret != HD_OK){ fbdev_msg("ret = %d\n", ret); } } #endif #include "kwrap/debug.h" #include "FileSysTsk.h" void lv_gpu_nvt_dma2d_rotate(lv_color_t * buf, lv_coord_t buf_w, const lv_color_t * map, lv_coord_t map_w, lv_area_t area, UINT32 dir, bool flush) { UINT32 dst_pa = 0; UINT32 src_pa = 0; HD_GFX_ROTATE param = {0}; HD_RESULT ret = HD_OK; HD_COMMON_MEM_VIRT_INFO vir_meminfo = {0}; lv_coord_t copy_w = lv_area_get_width(&area); lv_coord_t copy_h = lv_area_get_height(&area); bool swap_xy = false; HD_IPOINT dst_pos = {-1, -1}; /* convert va to pa */ vir_meminfo.va = (void *)(map); if ( hd_common_mem_get(HD_COMMON_MEM_PARAM_VIRT_INFO, &vir_meminfo) != HD_OK) { fbdev_msg("convert map failed!\n"); return; } src_pa = vir_meminfo.pa; vir_meminfo.va = (void *)(buf); if ( hd_common_mem_get(HD_COMMON_MEM_PARAM_VIRT_INFO, &vir_meminfo) != HD_OK) { fbdev_msg("convert buf failed!\n"); return; } dst_pa = vir_meminfo.pa; memset(¶m, 0, sizeof(HD_GFX_ROTATE)); /* check dir */ switch(dir) { case HD_VIDEO_DIR_ROTATE_90: dst_pos = (HD_IPOINT){LV_VER_RES_MAX - area.y1 - copy_h, area.x1}; swap_xy = true; break; case HD_VIDEO_DIR_ROTATE_270: dst_pos = (HD_IPOINT){area.y1, LV_HOR_RES_MAX - area.x1 - copy_w}; swap_xy = true; break; case HD_VIDEO_DIR_ROTATE_180: dst_pos = (HD_IPOINT){LV_HOR_RES_MAX - area.x1 - copy_w, LV_VER_RES_MAX - area.y1 - copy_h}; swap_xy = false; break; default: LV_LOG_ERROR("dir(%lx) is currently not supported", dir); return; } /* rotate rgb channels */ param.src_img.dim.w = copy_w; param.src_img.dim.h = copy_h; param.src_img.p_phy_addr[0] = src_pa; param.src_img.lineoffset[0] = copy_w * sizeof(lv_color_t); param.src_img.format = hdal_fmt; param.src_region.x = 0; param.src_region.y = 0; param.src_region.w = copy_w; param.src_region.h = copy_h; param.dst_img.format = hdal_fmt; param.dst_img.dim.w = swap_xy ? LV_VER_RES_MAX : LV_HOR_RES_MAX; param.dst_img.dim.h = swap_xy ? LV_HOR_RES_MAX : LV_VER_RES_MAX; param.dst_img.p_phy_addr[0] = dst_pa; param.dst_img.lineoffset[0] = (swap_xy ? LV_VER_RES_MAX : LV_HOR_RES_MAX) * sizeof(lv_color_t); param.dst_pos = dst_pos; param.angle = dir; if(flush){ ret = hd_gfx_rotate(¶m); } else{ ret = vendor_gfx_rotate_no_flush(¶m); } if(ret != HD_OK){ fbdev_msg("ret = %d\n", ret); } } #endif /********************** * Local Functions **********************/ #if LV_COLOR_DEPTH == 24 HD_RESULT disp_gfx_rotate_8565(UINT32 dst_pa, UINT32 src_pa, lv_disp_drv_t * disp_drv) { HD_GFX_ROTATE param; HD_RESULT ret; HD_VIDEO_PXLFMT fmt; fmt = HD_VIDEO_PXLFMT_RGB565; fbdev_msg("disp_gfx_rotate: dst_pa = 0x%x,src_pa = 0x%x fmt 0x%x\n", dst_pa,src_pa,fmt); memset(¶m, 0, sizeof(HD_GFX_ROTATE)); param.src_img.dim.w = disp_drv->hor_res; param.src_img.dim.h = disp_drv->ver_res; param.src_img.p_phy_addr[0] = src_pa; param.src_img.lineoffset[0] = disp_drv->hor_res * 2; param.src_img.format = fmt; param.dst_img.dim.w = disp_drv->ver_res; param.dst_img.dim.h = disp_drv->hor_res; param.dst_img.p_phy_addr[0] = dst_pa; param.dst_img.lineoffset[0] = disp_drv->ver_res * 2; param.dst_img.format = fmt; param.src_region.x = 0; param.src_region.y = 0; param.src_region.w = disp_drv->hor_res; param.src_region.h = disp_drv->ver_res; param.dst_pos.x = 0; param.dst_pos.y = 0; param.angle = VDO_ROTATE_DIR; ret = hd_gfx_rotate(¶m); fmt = HD_VIDEO_PXLFMT_I8; memset(¶m, 0, sizeof(HD_GFX_ROTATE)); param.src_img.dim.w = disp_drv->hor_res; param.src_img.dim.h = disp_drv->ver_res; param.src_img.p_phy_addr[0] = src_pa + disp_drv->hor_res * disp_drv->ver_res * 2; param.src_img.lineoffset[0] = disp_drv->hor_res; param.src_img.format = fmt; param.dst_img.dim.w = disp_drv->ver_res; param.dst_img.dim.h = disp_drv->hor_res; param.dst_img.p_phy_addr[0] = dst_pa + disp_drv->hor_res * disp_drv->ver_res * 2; param.dst_img.lineoffset[0] = disp_drv->ver_res; param.dst_img.format = fmt; param.src_region.x = 0; param.src_region.y = 0; param.src_region.w = disp_drv->hor_res; param.src_region.h = disp_drv->ver_res; param.dst_pos.x = 0; param.dst_pos.y = 0; param.angle = VDO_ROTATE_DIR; ret = hd_gfx_rotate(¶m); return ret; } #endif #endif /* USE_FBDEV || USE_BSD_FBDEV */