Reachy 发表于 2017-12-27 11:55:58

CubieAIO-S500 linux系统的异显设置

本帖最后由 Reachy 于 2017-12-28 18:06 编辑

CubieAIO-S500的显示可以支持异屏同显,异屏异显

一,异屏同显
CubieAIO-S500 Linux系统默认工作在该模式,LCD作为主设备,HDMI 作为从设备;LCD 输出 1024*600 图像,且主设备的显示图像镜像到 HDMI时,将会进行 scale 处理,导致 HDMI 上显示的画面模糊,没有达到显示器1080p和720p的效果,不过显示还可以。
二,异屏异显
系统默认工作在异屏同显模式,可通过如下命令切换到异屏异显:# echo 0 > /sys/class/graphics/fb0/mirror_to_hdmi在异屏异显模式,LCD 作为主设备(/dev/fb0),HDMI 作为从设备(/dev/fb1);用户可通过/dev/fb1接口往从设备的 framebuffer 中写入显示内容,最终写入的内容将显示在 HDMI 上,可参考下面的测试程序:#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <termios.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/msg.h>
#include <sys/sem.h>
#include <sys/mman.h>
#include <linux/fb.h>
#define DEV_FB         "/dev/fb1"

#define PRINT_INT(e) printf("%s = %d\n", #e, e)
#define PRINT_STR(e) printf("%s = %s\n", #e, e)
#define PRINT_P(e) printf("%s %d %s = %p\n", __func__, __LINE__, #e, e);
#define NUM_OF_COLORS 8
#define COLOR_BAR_BORDER_WIDTH 32

// Arguments r,g,b range from 0x00 - 0xFF
#define MAKE_565_PIXEL(r,g,b)                     \
(((r & 0xF8) << 8) |                                  \
((g & 0xFC) << 3) |                                  \
((b & 0xF8) >> 3))

#define RED_565_PIXEL                   MAKE_565_PIXEL(255,0,0)
#define GREEN_565_PIXEL               MAKE_565_PIXEL(0,255,0)
#define BLUE_565_PIXEL                  MAKE_565_PIXEL(0,0,255)
#define WHITE_565_PIXEL               MAKE_565_PIXEL(255,255,255)
#define BLACK_565_PIXEL               MAKE_565_PIXEL(0,0,0)
#define CYAN_565_PIXEL                  MAKE_565_PIXEL(0,255,255)
#define MAGENTA_565_PIXEL               MAKE_565_PIXEL(255,0,255)
#define YELLOW_565_PIXEL                MAKE_565_PIXEL(255,255,0)

// Arguments t,r,g,b range from 0x00 - 0xFF
#define MAKE_8888_PIXEL(t,r,g,b)             \
(((t & 0xFF) << 24) |                                  \
((r & 0xFF) << 16) |                                  \
((g & 0xFF) << 8)|                                  \
((b & 0xFF) << 0))

#define RED_8888_PIXEL                               MAKE_8888_PIXEL(0xFF,255,0,0)
#define GREEN_8888_PIXEL                MAKE_8888_PIXEL(0xFF,0,255,0)
#define BLUE_8888_PIXEL               MAKE_8888_PIXEL(0xFF,0,0,255)
#define WHITE_8888_PIXEL                MAKE_8888_PIXEL(0xFF,255,255,255)
#define BLACK_8888_PIXEL                MAKE_8888_PIXEL(0xFF,0,0,0)
#define CYAN_8888_PIXEL               MAKE_8888_PIXEL(0xFF,0,255,255)
#define MAGENTA_8888_PIXEL            MAKE_8888_PIXEL(0xFF,255,0,255)
#define YELLOW_8888_PIXEL               MAKE_8888_PIXEL(0xFF,255,255,0)

struct fb_fix_screeninfo fbx;
struct fb_var_screeninfo fbv;
int *fbp, fd;
long int screensize = 0;

static short color565Array[] =
{
    RED_565_PIXEL,
    GREEN_565_PIXEL,
    BLUE_565_PIXEL,
    CYAN_565_PIXEL,
    MAGENTA_565_PIXEL,
    YELLOW_565_PIXEL,
    BLACK_565_PIXEL,
    WHITE_565_PIXEL,
};

static int color8888Array[] =
{
    RED_8888_PIXEL,
    GREEN_8888_PIXEL,
    BLUE_8888_PIXEL,
    BLACK_8888_PIXEL,
    WHITE_8888_PIXEL,
    CYAN_8888_PIXEL,
    MAGENTA_8888_PIXEL,
    YELLOW_8888_PIXEL,
};

/*
*void writecolor8888bars(int fd, int width, int height)
*{
*    int x, y, count, i, j;
*    x = width * 2;
*    //y = height / NUM_OF_COLORS;
*    y = height;
*    printf("x : %d, y %d\n", x, y);
*    for(count = 0; count < NUM_OF_COLORS; count++)
*    {
*      for(i = 0; i < y; i++)
*      {
*            for(j = 0; j < x; j++)
*            {      
*                write(fd, &color8888Array, 4);               
*            }
*      }
*    }
*}
*/
void writeColor8888Bars(int stride, int width, int height)
{
    int row,col;
    int *framePtr = fbp;
    int colorIndex;

    printf("writeColor8888Bars:\n");
    for (row = 0; row < 8; row++) printf("color[%d]: %x\n",row,color8888Array);

    for (row = 0; row < height; row++)
    {
      framePtr = (int *) (*fbp + (row * stride));

      for (col = 0; col < width; col++, framePtr++)
      {
            if (row < COLOR_BAR_BORDER_WIDTH)
            {
                colorIndex = 0;         // red top border
            }
            else if (row >= (height - COLOR_BAR_BORDER_WIDTH))
            {
                colorIndex = 7;         // yellow bottom border
            }
            else
            {
                colorIndex = (col * NUM_OF_COLORS) / width;
            }
            *framePtr = color8888Array;
            //*((unsigned int*)(fbp + 300)) = color8888Array;
      }
    }
}

int main(int argc, char **argv)
{
int x, y;
    fd = open(DEV_FB, O_RDWR);
printf("open %sfd = %d\n", DEV_FB);      
      ioctl(fd, FBIOGET_VSCREENINFO, &fbv);
      
      ioctl(fd, FBIOGET_FSCREENINFO, &fbx);

      printf("smem_len : %u \n", fbx.smem_len);
      printf("line_length : %u \n", fbx.line_length);

      printf("xres : %u \n", fbv.xres);
      printf("yres : %u \n", fbv.yres);
      printf("bits_per_pixel : %u \n", fbv.bits_per_pixel);
    // Map the device to memory
    screensize = fbx.line_length * fbv.yres_virtual;
    printf("screensize=%d\n", (int)screensize);
    fbp = (int *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED,
            fd, 0);
    if ((int)fbp == -1)
    {
      printf("Error: failed to map framebuffer device to memory.\n");
      exit(4);
    }
    printf("The framebuffer device was mapped to memory successfully at %x.\n",(unsigned int)fbp);
    // blank screen
    printf("Blanking screen\n");
    memset (fbp, 0x00, screensize);

      int i, j, count, m, n;
//      int num = 0;
      int num = 0xffffffff;
    unsigned char t = 0xff;
      unsigned char r = 0xff;
      unsigned char g = 0x0;
      unsigned char b = 0x0;
      num = (t << 24) | (r << 16) | (g << 8) | b;
    /*
   *for(i = 0; i < y; i++)
   *{
   *    for(j = 0; j < x; j++)
   *    {      
   *      write(fd, &num, 4);               
   *    }
   *}
   */
    m = fbv.yres / NUM_OF_COLORS;
    y = 0;
    count = 1;
    for(count = 0; count < NUM_OF_COLORS; count++)
    {
      for(; y < m * (count + 1); y++)
      {
            for(x = 0; x < fbv.xres; x++)
            {
                write(fd, &color8888Array, 4);               
            }
      }
    }
    //*((unsigned int*)(fbp + x + 30)) = color8888Array;

    munmap(fbp, screensize);
      close(fd);

      return 0;
}显示效果如下:


三,主从显示设备设置
系统默认情况下, LCD 做为主显示设备; 可通过下面的方法, 将 HDMI设置为主显示设备, LCD设置为从显示设备。但是 uboot 和 kernel 的 dts相关配置需要同步修改,否则出现花屏。
需要修改dts
uboot dts 文件存放位置: u-boot/arch/arm/dts/cubieaio_s500.dts
kernel dts 文件存放位置:kernel/arch/arm/boot/dts/cubieaio_s500_linux.dts
将 LCD 设置为主显示设备,如下所示:framebuffer {
    compatible = "actions,framebuffer";
    def_display = "<span style="background-color: Red;">HDMI</span>";
};注意要同步修改uboot和kernel的相关配置:

然后编译所需文件
$ sudo make u-boot
$ sudo make kernel
编译后文件:
u-boot-dtb.img: u-boot/arch/arm/dts/cubieaio_s500.dts
kernel.dtb: kernel/arch/arm/boot/dts/cubieaio_s500_linux.dts
将编译生成的u-boot-dtb.img和kernel.dtb复制到CubieAIO-S500的/home/linaro目录下,通过以下命令更新://更新uboot镜像:
# sudo dd if=/home/linaro/u-boot-dtb.img of=/dev/mmcblk0 bs=512 seek=6144
//更新kernel的dtb文件
# sudo cp -f /home/linaro/kernel.dtb /media/linaro/misc
//同步文件并重启系统
# sudo sync && reboot如果不在乎编译时间,也可以直接重新编译成固件,然后烧入板子上
$ sudo make firmware
固件烧入参考固件烧入文档

HDMI设置为主显,LCD为副显,异屏同显OK,异屏异显,暂时还没有实现,后续再补上......


Reachy 发表于 2017-12-27 11:57:45

占楼先:)

ahha007 发表于 2018-1-5 04:28:00

有图有真相,有干货,顶一下!
页: [1]
查看完整版本: CubieAIO-S500 linux系统的异显设置