翼度科技»论坛 编程开发 .net 查看内容

全志G2D实现屏幕旋转,开机logo实现手动旋转。

3

主题

3

帖子

9

积分

新手上路

Rank: 1

积分
9
产品设计出来之后啊,大家使用的时候觉得反过来使用更加便捷。但是屏幕显示是反的。那怎么办那?????
修改硬件费时费工,那能否软件实现那?????
 如果纯软件使用那就太费系统资源了。于是就想到了使用全志R528 自带的G2D功能(硬件加速功能)。
使用它进行旋转,后又发现uboot阶段系统没有G2D导致开机logo不能自动旋转,内核启动后G2D 启动logo 又旋转了。
(好烦啊!!!!!!!!!!!!)
于是就需要把uboot 阶段手动把图片数据旋转过来。在G2D启动前把uboot 传递给内核的logo 图片数据也旋转过来。
下面具体步骤:
一、开启G2D功能。
1、由于此前公版默认在modules.mk屏蔽了屏旋转相关配置, 如果你的版本是禁用旋转的, 需要把相关配置去掉.
device/config/chips/r528/configs/evb1/linux-5.4/config-5.4
2759:# CONFIG_SUNXI_DISP2_FB_DISABLE_ROTATE is not set
以下3个相关选项
  1. CONFIG_DISP2_SUNXI=m \
  2. #CONFIG_SUNXI_DISP2_FB_DISABLE_ROTATE=y \
  3. #CONFIG_SUNXI_DISP2_FB_ROTATION_SUPPORT=n \
  4. #CONFIG_SUNXI_DISP2_FB_HW_ROTATION_SUPPORT=n \<br>修改为:
复制代码
  1. CONFIG_DISP2_SUNXI=m \
  2. #CONFIG_SUNXI_DISP2_FB_DISABLE_ROTATE=n \
  3. #CONFIG_SUNXI_DISP2_FB_ROTATION_SUPPORT=n \
  4. #CONFIG_SUNXI_DISP2_FB_HW_ROTATION_SUPPORT=y \
复制代码
 
2、硬件旋转需要确保G2D驱动已经使能
  1. make kernel_menuconfig
  2. Device Drivers --->
  3. <*> SUNXI G2D Driver
  4. [*] sunxi g2d mixer module
  5. [*] sunxi g2d rotate module
  6. [] sunxi sync fence implement for rotate jobs synchronous
复制代码
3.打开显示驱动旋转支持
  1. make kernel_menuconfig
  2. Device Drivers --->
  3. Graphics support --->
  4. Frame buffer Devices --->
  5. Video support for sunxi --->
  6. DISP2 Framebuffer rotation support (Disable rotation) --->
  7. ( ) Disable rotation
  8. ( ) Software rotation support (不要选这个,方案未支持)
  9. (X) Hardware(G2D) rotation support (选择G2D旋转)
复制代码
4.dts配置
 
board.dts 和 uboot-board.dts同步修改.
  1. &disp{
  2. .....
  3. disp_rotation_used = <1>;/* 使能旋转功能 */
  4. degree0 = <2>; /* X:screen index; 0:0 degree; 1:90 degree; 3:270 degree */
  5. fb0_width = <800>;/*fb 的长宽交换*/
  6. fb0_height = <480>;
  7. .....
  8. };
复制代码
 
5.旋转后framebuffer编程是需要注意,旋转后的buffer不会直接显示到屏幕上, 需要在应用刷屏的地方调用FBIOPAN_DISPLAY接口.同步旋转后的buffer到LCD上.
 
以修改公版旋转的GUI刷屏示例:
 
  1. 路径:package/gui/littlevgl-6/lv_drivers/display/fbdev.c
  2. void fbdev_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_p){
  3. ....
  4.     lv_disp_flush_ready(drv);
  5.     ioctl(fbfd, FBIOPAN_DISPLAY, &vinfo); /*函数最后,在刷屏函数后面,调用 FBIOPAN_DISPLAY 接口*/
  6. }
复制代码
 
我们系统时自己的UI系统。是在重绘回调函数中,增加FBIOPAN_DISPLAY
 
 
  1. main()<br>{
  2.   int fp=0;
  3. struct fb_var_screeninfo vinfo;
  4. struct fb_fix_screeninfo finfo;
  5. fp = open("/dev/fb0", O_RDWR);
  6. if(fp < 0) {
  7. printf("Error : Can not open framebuffer device/n");
  8. exit(1);
  9. }
  10. if(ioctl(fp, FBIOGET_VSCREENINFO, &vinfo)){
  11. printf("Error reading variable information/n");
  12. exit(3);
  13. }
  14. vinfo.xoffset = 0;
  15. vinfo.yoffset = 0;  <br>}
  16. void sys_paint(void) // 每次重绘调用一次
  17. {
  18.   ioctl(fbfd, FBIOPAN_DISPLAY, &vinfo); /*函数最后,在刷屏函数后面,调用 FBIOPAN_DISPLAY 接口*/
  19. }
复制代码
二、uboot阶段手动修改旋转图片数据
  追踪uboot  logo 执行过程
  1. static int run_main_loop(void)
  2. {
  3. ....
  4.     #ifdef CONFIG_ARCH_SUNXI
  5.         initr_sunxi_plat,
  6.     #endif
  7. ....
  8. }
  9. initr_sunxi_plat
  10. {
  11. ....
  12.               #ifdef CONFIG_BOOT_GUI
  13.                 void board_bootlogo_display(void);
  14.                 board_bootlogo_display();
  15.         #else
  16. ....
  17. }
  18. void board_bootlogo_display(void)
  19. {
  20. ....
  21. #if defined(CONFIG_CMD_SUNXI_BMP)
  22.     sunxi_bmp_display("bootlogo.bmp"); //指定bootlogo的名字。通过修改这个地方可以修改指定logo的名称
  23.    
  24. #elif defined(CONFIG_CMD_SUNXI_JPEG)
  25.     sunxi_jpeg_display("bootlogo.jpg");
  26. #endif   
  27. ....
  28. }
  29. int sunxi_bmp_display(char *name)
  30. {
  31.     int ret = -1;
  32.     char *argv[6];
  33.     char bmp_head[32];273
  34.     char bmp_name[32];
  35.     char part_info[16] = {0};
  36.     char size[32] = {0};
  37.     int partno = -1;
  38.     unsigned long file_size = 0;
  39.     char *bmp_head_addr;
  40.     struct bmp_image *bmp;
  41.     bmp = memalign(CONFIG_SYS_CACHELINE_SIZE,  ALIGN(sizeof(struct bmp_header), CONFIG_SYS_CACHELINE_SIZE));
  42.     if (bmp) {
  43.         sprintf(bmp_head, "%lx", (ulong)bmp);
  44.     } else {
  45.         pr_error("sunxi bmp: alloc buffer for %s fail\n", name);
  46.         goto out;
  47.     }
  48.     partno = sunxi_partition_get_partno_byname("bootloader"); /*android*/
  49.     if (partno < 0) {
  50.         partno = sunxi_partition_get_partno_byname(
  51.             "boot-resource"); /*linux*/
  52.         if (partno < 0) {
  53.             pr_error("Get bootloader and boot-resource partition number fail!\n");
  54.             goto free1;
  55.         }
  56.     }
  57.     snprintf(part_info, 16, "0:%x", partno);
  58.     strncpy(bmp_name, name, sizeof(bmp_name));
  59.     snprintf(size, 16, "%lx", (ulong)sizeof(struct bmp_header));
  60.     argv[0] = "fatload";
  61.     argv[1] = "sunxi_flash";
  62.     argv[2] = part_info;
  63.     argv[3] = bmp_head;
  64.     argv[4] = bmp_name;
  65.     argv[5] = size;
  66.     if (do_fat_fsload(0, 0, 6, argv)) {
  67.         pr_error("sunxi bmp info error : unable to open logo file %s\n",
  68.                argv[4]);
  69.         goto free1;
  70.     }
  71.     if ((bmp->header.signature[0] != 'B') ||
  72.         (bmp->header.signature[1] != 'M')) {
  73.         pr_error("this is not a bmp picture\n");
  74.         goto free1;
  75.     }
  76.     file_size = bmp->header.file_size;
  77.     bmp_head_addr = memalign(CONFIG_SYS_CACHELINE_SIZE,  ALIGN(file_size, CONFIG_SYS_CACHELINE_SIZE));
  78.     if (bmp_head_addr) {
  79.         sprintf(bmp_head, "%lx", (ulong)bmp_head_addr);
  80.     } else {
  81.         pr_error("sunxi bmp: alloc buffer for %s fail\n", name);
  82.         goto free1;
  83.     }
  84.     snprintf(size, 16, "%lx", (ulong)file_size);
  85.     tick_printf("bmp_name=%s size %ld\n", bmp_name, file_size);
  86.     if (do_fat_fsload(0, 0, 6, argv)) {
  87.         pr_error("sunxi bmp info error : unable to open logo file %s\n",
  88.                argv[4]);
  89.         goto free2;
  90.     }
  91. //在调用show_bmp_on_fb 之前将bmp_head_addr中的图片数据进行旋转
复制代码
  // 调用旋转函数
          rotateBMP180(bmp_head_addr);
  1.     ret = show_bmp_on_fb(bmp_head_addr, FB_ID_0);
  2.     if (ret != 0)
  3.         pr_error("show bmp on fb failed !%d\n", ret);
  4. free2:
  5.     free(bmp_head_addr);
  6. free1:
  7.     free(bmp);
  8. out:
  9.     return ret;
  10. }
  11.         
复制代码
旋转函数:
主要发现uboot 阶段malloc不能申请太大的内存空间,所以代码中申请的行的大小。
  1. #pragma pack(push, 1)
  2. typedef struct {
  3.     uint16_t type;
  4.     uint32_t size;
  5.     uint16_t reserved1;
  6.     uint16_t reserved2;
  7.     uint32_t offset;
  8. } BMPFileHeader;
  9. #pragma pack(pop)
  10. // 定义BMP图像信息头结构体
  11. #pragma pack(push, 1)
  12. typedef struct {
  13.     uint32_t header_size;
  14.     int32_t width;
  15.     int32_t height;
  16.     uint16_t planes;
  17.     uint16_t bit_count;
  18.     uint32_t compression;
  19.     uint32_t image_size;
  20.     int32_t x_pixels_per_meter;
  21.     int32_t y_pixels_per_meter;
  22.     uint32_t colors_used;
  23.     uint32_t colors_important;
  24. } BMPInfoHeader;
  25. #pragma pack(pop)
  26. // 旋转BMP图像180度
  27. void rotateBMP180(char * bmp_head_add) {
  28.     // 读取文件头
  29.     BMPFileHeader* file_header = (BMPFileHeader*)bmp_head_add;
  30.     // 读取图像信息头
  31.     BMPInfoHeader* info_header = (BMPInfoHeader*)(bmp_head_add + sizeof(BMPFileHeader));
  32.     // 获取图像宽度、高度和每行像素所占字节数
  33.     int32_t width = info_header->width;
  34.     int32_t height = info_header->height;
  35.     uint32_t row_size = (info_header->bit_count * width + 31) / 32 * 4;
  36.     // 创建临时缓冲区存储旋转后的图像数据
  37.     uint8_t* temp_data = (uint8_t*)malloc(row_size);
  38.     if (temp_data == NULL) {
  39.         printf("Failed to allocate memory for temporary data.\n");
  40.         return;
  41.     }
  42.     // 旋转图像
  43.     for (int32_t row = 0; row < height / 2; ++row) {
  44.         for (int32_t col = 0; col < width; ++col) {
  45.             // 计算当前像素位置和对应的对称像素位置
  46.             int32_t original_index = row * row_size + col * 3;
  47.             int32_t symmetric_index = (height - 1 - row) * row_size + (width - 1 - col) * 3;
  48.             // 交换像素颜色值
  49.             uint8_t temp_red = bmp_head_add[file_header->offset + original_index];
  50.             uint8_t temp_green = bmp_head_add[file_header->offset + original_index + 1];
  51.             uint8_t temp_blue = bmp_head_add[file_header->offset + original_index + 2];
  52.             bmp_head_add[file_header->offset + original_index] = bmp_head_add[file_header->offset + symmetric_index];
  53.             bmp_head_add[file_header->offset + original_index + 1] = bmp_head_add[file_header->offset + symmetric_index + 1];
  54.             bmp_head_add[file_header->offset + original_index + 2] = bmp_head_add[file_header->offset + symmetric_index + 2];
  55.             bmp_head_add[file_header->offset + symmetric_index] = temp_red;
  56.             bmp_head_add[file_header->offset + symmetric_index + 1] = temp_green;
  57.             bmp_head_add[file_header->offset + symmetric_index + 2] = temp_blue;
  58.         }
  59.     }
  60.     // 释放临时缓冲区内存
  61.     free(temp_data);
  62. }
复制代码
 
三、kernel阶段手动修改旋转logo图片数据
  追踪内核执行过程
  1. disp_module_init{
  2. ........
  3.     platform_driver_unregister(&disp_driver);
  4. #ifndef CONFIG_OF
  5.     platform_device_unregister(&disp_device);
  6. #endif
  7. ........
  8. }
  9. static int disp_probe(struct platform_device *pdev){
  10. ........
  11.         bsp_disp_init(para);
  12. ........
  13. }
  14. static s32 disp_init(struct platform_device *pdev)   
  15. {
  16. ........
  17.     lcd_init();
  18.     bsp_disp_open();
  19.     fb_init(pdev);
  20. ........
  21. }
  22. s32 fb_init(struct platform_device *pdev)
  23. {
  24. ........
  25.     ret = display_fb_request(i, &fb_para);
  26. ........
  27. }
  28. static s32 display_fb_request(u32 fb_id, struct disp_fb_create_info *fb_para)
  29. {
  30. ........
  31.     Fb_map_kernel_logo(sel, info);
  32. ........
  33. }
  34. static int Fb_map_kernel_logo(u32 sel, struct fb_info *info)
  35. {
  36. ........
  37.     paddr = bootlogo_addr;
  38.     if (paddr == 0) {
  39.         __inf("Fb_map_kernel_logo failed!");
  40.         return Fb_copy_boot_fb(sel, info);
  41.     }
  42. ........
  43. }
  44. static int Fb_copy_boot_fb(u32 sel, struct fb_info *info)
  45. {
  46.     enum {
  47.         BOOT_FB_ADDR = 0,
  48.         BOOT_FB_WIDTH,
  49.         BOOT_FB_HEIGHT,
  50.         BOOT_FB_BPP,
  51.         BOOT_FB_STRIDE,
  52.         BOOT_FB_CROP_L,
  53.         BOOT_FB_CROP_T,
  54.         BOOT_FB_CROP_R,
  55.         BOOT_FB_CROP_B,
  56.     };
  57.     char *boot_fb_str = NULL;
  58.     char *src_phy_addr = NULL;
  59.     char *src_addr = NULL;
  60.     char *src_addr_b = NULL;
  61.     char *src_addr_e = NULL;
  62.     int src_width = 0;
  63.     int src_height = 0;
  64.     int fb_height = 0;
  65.     int src_bpp = 0;
  66.     int src_stride = 0;
  67.     int src_cp_btyes = 0;
  68.     int src_crop_l = 0;
  69.     int src_crop_t = 0;
  70.     int src_crop_r = 0;
  71.     int src_crop_b = 0;
  72.     char *dst_addr = NULL;
  73.     int dst_width = 0;
  74.     int dst_height = 0;
  75.     int dst_bpp = 0;
  76.     int dst_stride = 0;
  77.     int ret;
  78.     unsigned long map_offset;
  79.     if (info == NULL) {
  80.         __wrn("%s,%d: null pointer\n", __func__, __LINE__);
  81.         return -1;
  82.     }
  83.     boot_fb_str = (char *)disp_boot_para_parse_str("boot_fb0");
  84.     if (boot_fb_str != NULL) {
  85.         int i = 0;
  86.         char boot_fb[128] = { 0 };
  87.         int len = strlen(boot_fb_str);
  88.         if (sizeof(boot_fb) - 1 < len) {
  89.             __wrn("need bigger array size[%d] for boot_fb\n", len);
  90.             return -1;
  91.         }
  92.         memcpy((void *)boot_fb, (void *)boot_fb_str, len);
  93.         boot_fb[len] = '\0';
  94.         boot_fb_str = boot_fb;
  95.         for (i = 0;; ++i) {
  96.             char *p = strstr(boot_fb_str, ",");
  97.             if (p != NULL)
  98.                 *p = '\0';
  99.             if (i == BOOT_FB_ADDR) {
  100.                 ret = kstrtoul(boot_fb_str, 16,
  101.                     (unsigned long *)&src_phy_addr);
  102.                 if (ret)
  103.                     pr_warn("parse src_phy_addr fail!\n");
  104.             } else if (i == BOOT_FB_WIDTH) {
  105.                 ret = kstrtou32(boot_fb_str, 16, &src_width);
  106.                 if (ret)
  107.                     pr_warn("parse src_width fail!\n");
  108.             } else if (i == BOOT_FB_HEIGHT) {
  109.                 ret = kstrtou32(boot_fb_str, 16, &src_height);
  110.                 fb_height = src_height;
  111.                 if (ret)
  112.                     pr_warn("parse src_height fail!\n");
  113.             } else if (i == BOOT_FB_BPP) {
  114.                 ret = kstrtou32(boot_fb_str, 16, &src_bpp);
  115.                 if (ret)
  116.                     pr_warn("parse src_bpp fail!\n");
  117.             } else if (i == BOOT_FB_STRIDE) {
  118.                 ret = kstrtou32(boot_fb_str, 16, &src_stride);
  119.                 if (ret)
  120.                     pr_warn("parse src_stride fail!\n");
  121.             } else if (i == BOOT_FB_CROP_L) {
  122.                 ret = kstrtou32(boot_fb_str, 16, &src_crop_l);
  123.                 if (ret)
  124.                     pr_warn("parse src_crop_l fail!\n");
  125.             } else if (i == BOOT_FB_CROP_T) {
  126.                 ret = kstrtou32(boot_fb_str, 16, &src_crop_t);
  127.                 if (ret)
  128.                     pr_warn("parse src_crop_t fail!\n");
  129.             } else if (i == BOOT_FB_CROP_R) {
  130.                 ret = kstrtou32(boot_fb_str, 16, &src_crop_r);
  131.                 if (ret)
  132.                     pr_warn("parse src_crop_r fail!\n");
  133.             } else if (i == BOOT_FB_CROP_B) {
  134.                 ret = kstrtou32(boot_fb_str, 16, &src_crop_b);
  135.                 if (ret)
  136.                     pr_warn("parse src_crop_b fail!\n");
  137.             } else {
  138.                 break;
  139.             }
  140.             if (p == NULL)
  141.                 break;
  142.             boot_fb_str = p + 1;
  143.         }
  144.     } else {
  145.         __wrn("no boot_fb0\n");
  146.         return -1;
  147.     }
  148.     dst_addr = (char *)(info->screen_base);
  149.     dst_width = info->var.xres;
  150.     dst_height = info->var.yres;
  151.     dst_bpp = info->var.bits_per_pixel;
  152.     dst_stride = info->fix.line_length;
  153.     if ((src_phy_addr == NULL)
  154.         || (src_width <= 0)
  155.         || (src_height <= 0)
  156.         || (src_stride <= 0)
  157.         || (src_bpp <= 0)
  158.         || (dst_addr == NULL)
  159.         || (dst_width <= 0)
  160.         || (dst_height <= 0)
  161.         || (dst_stride <= 0)
  162.         || (dst_bpp <= 0)
  163.         || (src_bpp != dst_bpp)) {
  164.         __wrn
  165.             ("wrong para: src[phy_addr=%p,w=%d,h=%d,bpp=%d,stride=%d], dst[addr=%p,w=%d,h=%d,bpp=%d,stride=%d]\n",
  166.              src_phy_addr,
  167.              src_width, src_height, src_bpp, src_stride, dst_addr,
  168.              dst_width, dst_height, dst_bpp, dst_stride);
  169.         return -1;
  170.     }
  171.     map_offset = (unsigned long)src_phy_addr + PAGE_SIZE
  172.         - PAGE_ALIGN((unsigned long)src_phy_addr + 1);
  173.     src_addr = (char *)Fb_map_kernel_cache((unsigned long)src_phy_addr -
  174.                            map_offset,
  175.                            src_stride * src_height +
  176.                            map_offset);
  177.     if (src_addr == NULL) {
  178.         __wrn("Fb_map_kernel_cache for src_addr failed\n");
  179.         return -1;
  180.     }
  181.     src_addr_b = src_addr + map_offset;
  182.     if ((src_crop_b > src_crop_t) &&
  183.         (src_height > src_crop_b - src_crop_t) &&
  184.         (src_crop_t >= 0) &&
  185.         (src_height >= src_crop_b)) {
  186.         src_height = src_crop_b - src_crop_t;
  187.         src_addr_b += (src_stride * src_crop_t);
  188.     }
  189.     if ((src_crop_r > src_crop_l)
  190.         && (src_width > src_crop_r - src_crop_l)
  191.         && (src_crop_l >= 0)
  192.         && (src_width >= src_crop_r)) {
  193.         src_width = src_crop_r - src_crop_l;
  194.         src_addr_b += (src_crop_l * src_bpp >> 3);
  195.     }
  196.     // 旋转图片数据
  197.    // rotateImage180(src_addr_b, src_width, src_height, src_bpp, src_stride);
  198.         
  199.     if (src_height < dst_height) {
  200.         int dst_crop_t = (dst_height - src_height) >> 1;
  201.         dst_addr += (dst_stride * dst_crop_t);
  202.     } else if (src_height > dst_height) {
  203.         __wrn("src_height(%d) > dst_height(%d),please cut the height\n",
  204.               src_height,
  205.               dst_height);
  206.         Fb_unmap_kernel(src_addr);
  207.         return -1;
  208.     }
  209.     if (src_width < dst_width) {
  210.         int dst_crop_l = (dst_width - src_width) >> 1;
  211.         dst_addr += (dst_crop_l * dst_bpp >> 3);
  212.     } else if (src_width > dst_width) {
  213.         __wrn("src_width(%d) > dst_width(%d),please cut the width!\n",
  214.               src_width,
  215.               dst_width);
  216.         Fb_unmap_kernel(src_addr);
  217.         return -1;
  218.     }
  219.     src_cp_btyes = src_width * src_bpp >> 3;
  220.     src_addr_e = src_addr_b + src_stride * src_height;
  221.     for (; src_addr_b != src_addr_e; src_addr_b += src_stride) {
  222.         memcpy((void *)dst_addr, (void *)src_addr_b, src_cp_btyes);
  223.         dst_addr += dst_stride;
  224.     }
  225.        //再此地方旋转修改
  226.     dst_addr = (char *)(info->screen_base);
  227.     rotateImage180(dst_addr, dst_width, dst_height, dst_bpp, dst_stride);
  228.     Fb_unmap_kernel(src_addr);
  229.     memblock_free((unsigned long)src_phy_addr, src_stride * fb_height);
  230.     free_reserved_area(__va(src_phy_addr), __va(src_phy_addr + PAGE_ALIGN(src_stride * fb_height)), 0x00, "logo buffer");
  231.     return 0;
  232. }
  233.    
复制代码
旋转180函数:
放在 tina-r528\lichee\linux-5.4\drivers\video\fbdev\sunxi\disp2\disp\dev_fb.c
注意此处由于申请的内存空间比较大,所以用的是vmalloc
  1. void rotateImage180(char* src_addr, int width, int height, int bpp, int stride) {
  2.                     // 计算每行像素数据的字节数
  3.     int row_bytes = width * (bpp / 8);
  4.         char * src_addr_e = src_addr + stride* height; //最后的地址位置
  5.     // 创建临时缓冲区用于保存旋转后的图像数据
  6.     char* temp_data = vmalloc(row_bytes * height);
  7.         int y=0,x=0;
  8.     // 复制旋转后的图像数据到临时缓冲区
  9.     for (y = 0; y < height; y++) {
  10.         char* src_row_start = src_addr + (y * stride);
  11.         char* dest_row_start = temp_data + ((height - 1 - y) * row_bytes);
  12.                 // 复制像素数据并进行左右翻转
  13.                         for ( x = 0; x < width; x++) {
  14.                                 char* src_pixel = src_row_start + (x * (bpp / 8));
  15.                                 char* dest_pixel = dest_row_start + ((width - 1 - x) * (bpp / 8));
  16.                                 // 复制像素值
  17.                                 memcpy(dest_pixel, src_pixel, (bpp / 8));
  18.                         }
  19.     }       //printk("----%s--%d\n",__func__,__LINE__);
  20.         // 将旋转后的图像数据写回原始内存地址
  21.         for (; src_addr != src_addr_e; src_addr += stride) {  //循环复制每一行
  22.                 memcpy((void *)src_addr, (void *)temp_data, row_bytes);
  23.                 temp_data += row_bytes;  //地址是增加地址宽度
  24.         }
  25.         //printk("----%s--%d\n",__func__,__LINE__);
  26.     // 释放临时缓冲区
  27.     vfree(temp_data);
  28. }
复制代码
 
 
 参考资料:
(67条消息) uboot修改启动logo-sunxi_u-boot启动时改横屏_Chasing_Chasing的博客-CSDN博客
【FAQ】全志F133(D1s)芯片 如何在Tina下进行显示旋转? | 全志在线开发者论坛 (aw-ol.com)
 

来源:https://www.cnblogs.com/hylife/p/17496308.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

举报 回复 使用道具