hongyin 发表于 2016-6-17 17:17:48

【技术分享】Lubuntu分辨率自适应

本帖最后由 hongyin 于 2016-6-17 17:20 编辑

好久没发帖了,近期工作太忙,所以自适应(基于VGA)的整理迟迟没有更新,今天先来无事,所以把之前的研究成果拿出来供大家参考,如有问题,可以发我邮箱(iamphy@qq.com)进行交流,废话少说,谈正事。

首先,请先下载附件,该文件并非压缩包,下载后直接将后缀名改成.c即可,并将该文件cp到相应目录:kernel/drivers/video/rockchip/lcdc下,该文件修复了1440x900和1366x768两种分辨率的异常(兼容性有待考证),还有就是RGB颜色问题;准备工作做好之后,自行编译内核进行烧写;

然后,下面的代码便是自动适配分辨率的,这是一个单独的程序,需要各位网友自行cp进行编译,编译完成之后,只需要将执行路径添加到/etc/rc.local文件即可;若网友发现有问题,请邮件相互交流。

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/fb.h>

#define NUM_BUFFERS               2
#define RK_FBIOSET_CLEAR_FB         0x4633

#if 0
#define DEBUG_P(format, ...) printf(format, ##__VA_ARGS__)
#else
#define DEBUG_P(format, ...)
#endif

int main(int argc, char *argv[])
{
      FILE *fp = fopen("/sys/class/graphics/fb0/screen_info", "r");
      if(fp == NULL)
      {
                perror("fopen err:");
                return -1;
      }

      int xres = 0;
      int yres = 0;

      char line1 = {0};
      char line2 = {0};
      fgets(line1, sizeof(line1), fp);
      fgets(line2, sizeof(line2), fp);
      sscanf(line1, "xres:%d\n", &xres);
      sscanf(line2, "yres:%d\n", &yres);
      fclose(fp);
      DEBUG_P("read x:%d, y:%d\n", xres, yres);

      int fd = open("/dev/fb0", O_RDWR, 0);
      if (fd < 0)
      {
                fprintf(stderr, "No fb devices found!\n");
                return -errno;
      }

      struct fb_fix_screeninfo finfo;
      if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1)
      {
                close(fd);
                return -errno;
      }

      struct fb_var_screeninfo info;
      if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1)
      {
                close(fd);
                return -errno;
      }

      info.reserved = 0;
      info.reserved = 0;
      info.reserved = 0;
      info.xoffset = 0;
      info.yoffset = 0;
      info.width = xres;
      info.height = yres;
      info.xres = xres;
      info.yres = yres;
      info.xres_virtual = info.xres;
      info.yres_virtual = info.yres * NUM_BUFFERS;
      info.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE;

      info.bits_per_pixel = 32;
      info.red.offset   = 16;
      info.red.length   = 8;
      info.green.offset   = 8;
      info.green.length   = 8;
      info.blue.offset    = 0;
      info.blue.length    = 8;
      info.transp.offset= 0;
      info.transp.length= 0;
      info.grayscale            &= 0xff;
      info.grayscale            |= (info.xres<<8) + (info.yres<<20);
      info.nonstd             &= 0xffffff00;
      info.nonstd             |= 2;//HAL_PIXEL_FORMAT_RGBX_8888;

      ioctl(fd, RK_FBIOSET_CLEAR_FB, NULL);

      if (ioctl(fd, FBIOPUT_VSCREENINFO, &info) == -1)
      {
                perror("FBIOPUT_VSCREENINFO failed");
                close(fd);
                return -errno;
      }

      if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1)
      {
                fprintf(stderr, "FBIOGET_VSCREENINFO failed.\n");
                close(fd);
                return -errno;
      }

      int refreshRate = 0;
      if ( info.pixclock > 0 )
      {
                refreshRate = 1000000000000000LLU / ((uint64_t)
                        (info.upper_margin + info.lower_margin + info.yres + info.hsync_len ) *
                        (info.left_margin+ info.right_margin + info.xres + info.vsync_len ) *
                        info.pixclock);

                if (refreshRate == 0)
                {
                        refreshRate = 60*1000;// 60 Hz
                }
      }

      if ((int)(info.width) <= 0 || (int)(info.height) <= 0)
      {
                // the driver doesn't return that information
                // default to 160 dpi
                info.width= ((info.xres * 25.4f)/160.0f + 0.5f);
                info.height = ((info.yres * 25.4f)/160.0f + 0.5f);
      }

      float xdpi = (info.xres * 25.4f) / info.width;
      float ydpi = (info.yres * 25.4f) / info.height;
      float fps= refreshRate / 1000.0f;

      DEBUG_P("using (fd=%d)\n"
             "id         = %s\n"
             "xres         = %d px\n"
             "yres         = %d px\n"
             "xres_virtual = %d px\n"
             "yres_virtual = %d px\n"
             "bpp          = %d\n"
             "r            = %2u:%u\n"
             "g            = %2u:%u\n"
             "b            = %2u:%u\n"
             "format       = %d\n",
             fd,
             finfo.id,
             info.xres,
             info.yres,
             info.xres_virtual,
             info.yres_virtual,
             info.bits_per_pixel,
             info.red.offset, info.red.length,
             info.green.offset, info.green.length,
             info.blue.offset, info.blue.length,
             info.nonstd);

      DEBUG_P("width      = %d mm (%f dpi)\n"
             "height       = %d mm (%f dpi)\n"
             "refresh rate = %.2f Hz\n",
             info.width,xdpi,
             info.height, ydpi,
             fps);

      int videodata;
      videodata = videodata = finfo.smem_start;
      ioctl(fd, 0x5002, videodata);

      close(fd);
      return 0;
}


blackholeII 发表于 2016-6-21 10:37:13

文件已经损坏了,可以重新上传吗,谢谢

phoenix 发表于 2016-6-22 10:53:34

牛人,赞一个

hongyin 发表于 2016-6-22 15:09:40

blackholeII 发表于 2016-6-21 10:37
文件已经损坏了,可以重新上传吗,谢谢

附件并非压缩包,你下载后将后缀名改成.c就可以直接使用了

暴走的阿Sai 发表于 2016-6-22 22:59:22

好贴,已设置精华

mlt911213 发表于 2016-9-22 15:08:47

只能基于VGA?

mlt911213 发表于 2016-9-22 15:38:42

这个显示的问题可以帮忙看一下吗?
http://developer.t-firefly.com/thread-10933-1-1.html

东曦曦 发表于 2016-10-13 19:44:11

顶大神!!!!11

kcl21 发表于 2016-12-13 21:03:07

这个帖子真是精华

kgp00213 发表于 2017-7-19 22:50:51

强烈的感谢楼主!这个帖子真是精华
页: [1] 2
查看完整版本: 【技术分享】Lubuntu分辨率自适应