uboot 环境变量配置fb及双屏显示(vga、lcd)

上周公司终于拿到了freescale i.MX53的QSB板,经过一些折腾之后终于在上面把android跑起来了,按照所给的user guide测试了一下VGA、HDMI等,一切正常,但是都是单独显示的,和公司要开发的车载产品有很大距离,公司要开发的产品的大概要求是:
1、支持前后台显示(前台lcd显示由司机操作、后台TV输出供乘客观看电影及地图导航显示)
2、7.1声道,同时解码两路audio并能让两路声音分离
……………………
把相关的文档看了几遍,上面有介绍双屏显示的,但都是针对i.MX51的,53是刚出来不久的芯片,A8核心+硬解码器
通过参考51的双屏显示设置及uboot环境配置,终于在53的QSB板上作到了双屏显示(后台通过VGA输出、QSB板上的HDMI是接到了FB0上,占用了lcd的FB,所以还没用HDMI作为后台输出)
基本的过程如下:
1、把板子连接上串口和VGA,用电脑显示器作为输出

2、重启系统后在串口中出现如下提示的时候按回车进入uboot环境配置状态

U-Boot 2009.08-00246-gf56947c-dirty ( 6月 06 2011 - 23:02:35)

CPU:   Freescale i.MX53 family 2.0V at 1000 MHz
mx53 pll1: 1000MHz
mx53 pll2: 400MHz
mx53 pll3: 216MHz
mx53 pll4: 455MHz
ipg clock     : 66666666Hz
ipg per clock : 33333333Hz
uart clock    : 21600000Hz
cspi clock    : 54000000Hz
ahb clock     : 133333333Hz
axi_a clock   : 400000000Hz
axi_b clock   : 200000000Hz
emi_slow clock: 133333333Hz
ddr clock     : 400000000Hz
esdhc1 clock  : 80000000Hz
esdhc2 clock  : 80000000Hz
esdhc3 clock  : 80000000Hz
esdhc4 clock  : 80000000Hz
nfc clock     : 26666666Hz
Board: MX53-LOCO 1.0
Boot Reason: [WDOG]
Boot Device: SD
I2C:   ready
DRAM:   1 GB
MMC:   FSL_ESDHC: 0, FSL_ESDHC: 1
In:    serial
Out:   serial
Err:   serial
Checking for recovery command file...
Net:   got MAC address from IIM: 00:04:9f:01:a9:8a
FEC0 [PRIME]
Hit any key to stop autoboot:  0 
MX53-LOCO U-Boot > 

输入
MX53-LOCO U-Boot > printenv

可看到一些默认的环境设置如下:

bootdelay=3
baudrate=115200
loadaddr=0x70800000
netdev=eth0
ethprime=FEC0
bootdelay=3
uboot=u-boot.bin
kernel=uImage
loadaddr=0x70800000
rd_loadaddr=0x70C00000
nfsroot=/opt/eldk/arm
bootargs_base=setenv bootargs console=ttymxc0,115200
vga=setenv bootargs ${bootargs} init=/init androidboot.console=ttymxc0 di1_primary tve
lcd=setenv bootargs ${bootargs} init=/init androidboot.console=ttymxc0 di0_primary calibration
hdmi=setenv bootargs ${bootargs} init=/init androidboot.console=ttymxc0 video=mxcdi0fb:RGB24,1080P60 tve gpu_memory=256M
claa_lcd=setenv bootargs ${bootargs} init=/init androidboot.console=ttymxc0 video=mxcdi0fb:RGB565,CLAA-WVGA calibration
bootcmd_SD1=run bootargs_base bootargs_android
bootcmd_SD2=mmc read 0 ${loadaddr} 0x800 0x1800;mmc read 0 ${rd_loadaddr} 0x3000 0x300;bootm ${loadaddr} ${rd_loadaddr}
bootargs_nfs=setenv bootargs ${bootargs} root=/dev/nfs ip=dhcp nfsroot=${serverip}:${nfsroot},v3,tcp
bootcmd_net=run bootargs_base bootargs_nfs; tftpboot ${loadaddr} ${kernel}; bootm
bootcmd_android_recovery=run bootargs_base bootargs_android_recovery;mmc read 0 ${loadaddr} 0x800 0x1800;bootm
bootargs_android_recovery=setenv bootargs ${bootargs} init=/init root=/dev/mmcblk0p4 rootfs=ext4
ethact=FEC0

其中

vga=setenv bootargs ${bootargs} init=/init androidboot.console=ttymxc0 di1_primary tve
lcd=setenv bootargs ${bootargs} init=/init androidboot.console=ttymxc0 di0_primary calibration
hdmi=setenv bootargs ${bootargs} init=/init androidboot.console=ttymxc0 video=mxcdi0fb:RGB24,1080P60 tve gpu_memory=256M

代表的是分别用vga、lcd、hdmi作为输出的一些配置

要想做到双屏显示就得重新配置一下uboot的环境,我现在的配置参数如下:

setenv bootargs_android 'setenv bootargs ${bootargs} init=/init androidboot.console=ttymxc0 di0_primary calibration video=mxcdi1fb:RGB565,720P60 tve'

几点说明:
1、init=/init表示的是android启动的init.rc文件的位置
2、androidboot.console=ttymxc0表示的是系统debug时所使用的串口为tty0
3、di0_primary 表示的是把lcd挂到fb0上作为主显示,而calibration则是触摸屏
4、video=mxcdi1fb:RGB565,720P60 tve 表示的是把video输出挂到fb1上,输出的数据格式为RGB565,720P60
设置好上面这些环境变量之后,然后输入
MX53-LOCO U-Boot > saveenv
Saving Environment to MMC...
Writing to MMC(0)... done
MX53-LOCO U-Boot > boot
系统将会重新启动
等系统启动完成后在串中输入
#echo U:1280x1024p-60 > /sys/class/graphics/fb1/mode 
#echo 1 >/sys/class/graphics/fb1/blank               
#echo 0 >/sys/class/graphics/fb1/blank
#setprop rw.SECOND_DISPLAY_CONNECTED 1
#setprop sys.SECOND_DISPLAY_ENABLED 1
关于上面设置参数的几点说明:
1、echo U:1280x1024p-60 > /sys/class/graphics/fb1/mode 是设置TV输出的显示模式,在uboot的源码
Videomodes.c文件中有如下19种输出模式
const struct ctfb_vesa_modes vesa_modes[VESA_MODES_COUNT] = {
    {0x301, RES_MODE_640x480, 8},
    {0x310, RES_MODE_640x480, 15},
    {0x311, RES_MODE_640x480, 16},
    {0x312, RES_MODE_640x480, 24},
    {0x303, RES_MODE_800x600, 8},
    {0x313, RES_MODE_800x600, 15},
    {0x314, RES_MODE_800x600, 16},
    {0x315, RES_MODE_800x600, 24},
    {0x305, RES_MODE_1024x768, 8},
    {0x316, RES_MODE_1024x768, 15},
    {0x317, RES_MODE_1024x768, 16},
    {0x318, RES_MODE_1024x768, 24},
    {0x161, RES_MODE_1152x864, 8},
    {0x162, RES_MODE_1152x864, 15},
    {0x163, RES_MODE_1152x864, 16},
    {0x307, RES_MODE_1280x1024, 8},
    {0x319, RES_MODE_1280x1024, 15},
    {0x31A, RES_MODE_1280x1024, 16},
    {0x31B, RES_MODE_1280x1024, 24},
};

但是代码里真正实现的只有如下12种

RES_MODE_640x480 bpp8
RES_MODE_640x480 bpp16
RES_MODE_640x480 bpp24
RES_MODE_800x600 bpp8
RES_MODE_800x600 bpp16
RES_MODE_800x600 bpp24
RES_MODE_1024x768 bpp8
RES_MODE_1024x768 bpp16
RES_MODE_1024x768 bpp24
RES_MODE_1280x1024 bpp8
RES_MODE_1280x1024 bpp16
RES_MODE_1280x1024 bpp24
具体实现的代码在Ati_radeon_fb.c文件中
代码如下:

void radeon_setmode_9200(int vesa_idx, int bpp)
void radeon_setmode_9200(int vesa_idx, int bpp)
{
    struct radeon_regs *mode = malloc(sizeof(struct radeon_regs));


    mode->crtc_gen_cntl = CRTC_EN | CRTC_EXT_DISP_EN;
    mode->crtc_ext_cntl = VGA_ATI_LINEAR | XCRT_CNT_EN | CRTC_CRT_ON;
    mode->dac_cntl = DAC_MASK_ALL | DAC_VGA_ADR_EN | DAC_8BIT_EN;
    mode->crtc_offset_cntl = CRTC_OFFSET_CNTL__CRTC_TILE_EN;


    switch (bpp) {
    case 24:
        mode->crtc_gen_cntl |= 0x6 << 8; /* x888 */
#if defined(__BIG_ENDIAN)
        mode->surface_cntl = NONSURF_AP0_SWP_32BPP | NONSURF_AP1_SWP_32BPP;
        mode->surf_info[0] = NONSURF_AP0_SWP_32BPP | NONSURF_AP1_SWP_32BPP;
#endif
        break;
    case 16:
        mode->crtc_gen_cntl |= 0x4 << 8; /* 565 */
#if defined(__BIG_ENDIAN)
        mode->surface_cntl = NONSURF_AP0_SWP_16BPP | NONSURF_AP1_SWP_16BPP;
        mode->surf_info[0] = NONSURF_AP0_SWP_16BPP | NONSURF_AP1_SWP_16BPP;
#endif
        break;
    default:
        mode->crtc_gen_cntl |= 0x2 << 8; /* palette */
        mode->surface_cntl = 0x00000000;
        break;
    }


    switch (vesa_idx) {
    case RES_MODE_1280x1024:
        mode->crtc_h_total_disp = CRTC_H_TOTAL_DISP_VAL(1688,1280);
        mode->crtc_v_total_disp = CRTC_V_TOTAL_DISP_VAL(1066,1024);
        mode->crtc_v_sync_strt_wid = CRTC_VSYNC_STRT_WID_VAL(1025,3);
#if defined(CONFIG_RADEON_VREFRESH_75HZ)
        mode->crtc_h_sync_strt_wid = CRTC_HSYNC_STRT_WID_VAL(1288,18);
        mode->ppll_div_3 = 0x00010078;
#else /* default @ 60 Hz */
        mode->crtc_h_sync_strt_wid = CRTC_HSYNC_STRT_WID_VAL(1320,14);
        mode->ppll_div_3 = 0x00010060;
#endif
        /*
         * for this mode pitch expands to the same value for 32, 16 and 8 bpp,
         * so we set it here once only.
         */
        mode->crtc_pitch = RADEON_CRT_PITCH(1280,32);
        switch (bpp) {
        case 24:
            mode->surf_info[0] |= R200_SURF_TILE_COLOR_MACRO | (1280 * 4 / 16);
            mode->surf_upper_bound[0] = SURF_UPPER_BOUND(1280,1024,32);
            break;
        case 16:
            mode->surf_info[0] |= R200_SURF_TILE_COLOR_MACRO | (1280 * 2 / 16);
            mode->surf_upper_bound[0] = SURF_UPPER_BOUND(1280,1024,16);
            break;
        default: /* 8 bpp */
            mode->surf_info[0] = R200_SURF_TILE_COLOR_MACRO | (1280 * 1 / 16);
            mode->surf_upper_bound[0] = SURF_UPPER_BOUND(1280,1024,8);
            break;
        }
        break;
    case RES_MODE_1024x768:
#if defined(CONFIG_RADEON_VREFRESH_75HZ)
        mode->crtc_h_total_disp = CRTC_H_TOTAL_DISP_VAL(1312,1024);
        mode->crtc_h_sync_strt_wid = CRTC_HSYNC_STRT_WID_VAL(1032,12);
        mode->crtc_v_total_disp = CRTC_V_TOTAL_DISP_VAL(800,768);
        mode->crtc_v_sync_strt_wid = CRTC_VSYNC_STRT_WID_VAL(769,3);
        mode->ppll_div_3 = 0x0002008c;
#else /* @ 60 Hz */
        mode->crtc_h_total_disp = CRTC_H_TOTAL_DISP_VAL(1344,1024);
        mode->crtc_h_sync_strt_wid = CRTC_HSYNC_STRT_WID_VAL(1040,17) | CRTC_H_SYNC_POL;
        mode->crtc_v_total_disp = CRTC_V_TOTAL_DISP_VAL(806,768);
        mode->crtc_v_sync_strt_wid = CRTC_VSYNC_STRT_WID_VAL(771,6) | CRTC_V_SYNC_POL;
        mode->ppll_div_3 = 0x00020074;
#endif
        /* also same pitch value for 32, 16 and 8 bpp */
        mode->crtc_pitch = RADEON_CRT_PITCH(1024,32);
        switch (bpp) {
        case 24:
            mode->surf_info[0] |= R200_SURF_TILE_COLOR_MACRO | (1024 * 4 / 16);
            mode->surf_upper_bound[0] = SURF_UPPER_BOUND(1024,768,32);
            break;
        case 16:
            mode->surf_info[0] |= R200_SURF_TILE_COLOR_MACRO | (1024 * 2 / 16);
            mode->surf_upper_bound[0] = SURF_UPPER_BOUND(1024,768,16);
            break;
        default: /* 8 bpp */
            mode->surf_info[0] = R200_SURF_TILE_COLOR_MACRO | (1024 * 1 / 16);
            mode->surf_upper_bound[0] = SURF_UPPER_BOUND(1024,768,8);
            break;
        }
        break;
    case RES_MODE_800x600:
        mode->crtc_h_total_disp = CRTC_H_TOTAL_DISP_VAL(1056,800);
#if defined(CONFIG_RADEON_VREFRESH_75HZ)
        mode->crtc_h_sync_strt_wid = CRTC_HSYNC_STRT_WID_VAL(808,10);
        mode->crtc_v_total_disp = CRTC_V_TOTAL_DISP_VAL(625,600);
        mode->crtc_v_sync_strt_wid = CRTC_VSYNC_STRT_WID_VAL(601,3);
        mode->ppll_div_3 = 0x000300b0;
#else /* @ 60 Hz */
        mode->crtc_h_sync_strt_wid = CRTC_HSYNC_STRT_WID_VAL(832,16);
        mode->crtc_v_total_disp = CRTC_V_TOTAL_DISP_VAL(628,600);
        mode->crtc_v_sync_strt_wid = CRTC_VSYNC_STRT_WID_VAL(601,4);
        mode->ppll_div_3 = 0x0003008e;
#endif
        switch (bpp) {
        case 24:
            mode->crtc_pitch = RADEON_CRT_PITCH(832,32);
            mode->surf_info[0] |= R200_SURF_TILE_COLOR_MACRO | (832 * 4 / 16);
            mode->surf_upper_bound[0] = SURF_UPPER_BOUND(832,600,32);
            break;
        case 16:
            mode->crtc_pitch = RADEON_CRT_PITCH(896,16);
            mode->surf_info[0] |= R200_SURF_TILE_COLOR_MACRO | (896 * 2 / 16);
            mode->surf_upper_bound[0] = SURF_UPPER_BOUND(896,600,16);
            break;
        default: /* 8 bpp */
            mode->crtc_pitch = RADEON_CRT_PITCH(1024,8);
            mode->surf_info[0] = R200_SURF_TILE_COLOR_MACRO | (1024 * 1 / 16);
            mode->surf_upper_bound[0] = SURF_UPPER_BOUND(1024,600,8);
            break;
        }
        break;
    default: /* RES_MODE_640x480 */
#if defined(CONFIG_RADEON_VREFRESH_75HZ)
        mode->crtc_h_total_disp = CRTC_H_TOTAL_DISP_VAL(840,640);
        mode->crtc_h_sync_strt_wid = CRTC_HSYNC_STRT_WID_VAL(648,8) | CRTC_H_SYNC_POL;
        mode->crtc_v_total_disp = CRTC_V_TOTAL_DISP_VAL(500,480);
        mode->crtc_v_sync_strt_wid = CRTC_VSYNC_STRT_WID_VAL(481,3) | CRTC_V_SYNC_POL;
        mode->ppll_div_3 = 0x00030070;
#else /* @ 60 Hz */
        mode->crtc_h_total_disp = CRTC_H_TOTAL_DISP_VAL(800,640);
        mode->crtc_h_sync_strt_wid = CRTC_HSYNC_STRT_WID_VAL(674,12) | CRTC_H_SYNC_POL;
        mode->crtc_v_total_disp = CRTC_V_TOTAL_DISP_VAL(525,480);
        mode->crtc_v_sync_strt_wid = CRTC_VSYNC_STRT_WID_VAL(491,2) | CRTC_V_SYNC_POL;
        mode->ppll_div_3 = 0x00030059;
#endif
        /* also same pitch value for 32, 16 and 8 bpp */
        mode->crtc_pitch = RADEON_CRT_PITCH(640,32);
        switch (bpp) {
        case 24:
            mode->surf_info[0] |= R200_SURF_TILE_COLOR_MACRO | (640 * 4 / 16);
            mode->surf_upper_bound[0] = SURF_UPPER_BOUND(640,480,32);
            break;
        case 16:
            mode->surf_info[0] |= R200_SURF_TILE_COLOR_MACRO | (640 * 2 / 16);
            mode->surf_upper_bound[0] = SURF_UPPER_BOUND(640,480,16);
            break;
        default: /* 8 bpp */
            mode->crtc_offset_cntl = 0x00000000;
            break;
        }
        break;
    }


    OUTREG(CRTC_GEN_CNTL, mode->crtc_gen_cntl | CRTC_DISP_REQ_EN_B);
    OUTREGP(CRTC_EXT_CNTL, mode->crtc_ext_cntl,
        (CRTC_HSYNC_DIS | CRTC_VSYNC_DIS | CRTC_DISPLAY_DIS));
    OUTREGP(DAC_CNTL, mode->dac_cntl, DAC_RANGE_CNTL | DAC_BLANKING);
    OUTREG(CRTC_H_TOTAL_DISP, mode->crtc_h_total_disp);
    OUTREG(CRTC_H_SYNC_STRT_WID, mode->crtc_h_sync_strt_wid);
    OUTREG(CRTC_V_TOTAL_DISP, mode->crtc_v_total_disp);
    OUTREG(CRTC_V_SYNC_STRT_WID, mode->crtc_v_sync_strt_wid);
    OUTREG(CRTC_OFFSET, 0);
    OUTREG(CRTC_OFFSET_CNTL, mode->crtc_offset_cntl);
    OUTREG(CRTC_PITCH, mode->crtc_pitch);
    OUTREG(CRTC_GEN_CNTL, mode->crtc_gen_cntl);


    mode->clk_cntl_index = 0x300;
    mode->ppll_ref_div = 0xc;


    radeon_write_pll_regs(rinfo, mode);


    OUTREGP(CRTC_EXT_CNTL, mode->crtc_ext_cntl,
        ~(CRTC_HSYNC_DIS | CRTC_VSYNC_DIS | CRTC_DISPLAY_DIS));
    OUTREG(SURFACE0_INFO, mode->surf_info[0]);
    OUTREG(SURFACE0_LOWER_BOUND, 0);
    OUTREG(SURFACE0_UPPER_BOUND, mode->surf_upper_bound[0]);
    OUTREG(SURFACE_CNTL, mode->surface_cntl);


    if (bpp > 8)
        set_pal();


    free(mode);
}

2、echo 1 >/sys/class/graphics/fb1/blank 是关闭fb1
而echo 0 >/sys/class/graphics/fb1/blank 则是打开fb1
3、setprop rw.SECOND_DISPLAY_CONNECTED 1 我理解的是允许TV输出连接至fb
而setprop sys.SECOND_DISPLAY_ENABLED 1则是开启fb的数据输出  
(不知道是否有哪位对这些参数有更具体的了解和说明)
设置为上面这些之后,把显示器的VGA线接到板子的VGA上就可以看到在显示器显示的内容是和lcd的显示同步的
目前有几个疑点,希望看到的同行指点:
1、如何做到只让显示器输出的图像是板子上播放的视频内容,而UI部分不会显示
2、我找了个可以支持后台播放的视频播放器,开始播放视频后,我设置播放器“play in background”让其在后台播放,这时就会退出到UI显示状态,而工具栏上显示播放已经在后台播放视频了,lcd上显示正常,而显示器上则显示为:黑色的底图已经变成了当前正在后台播放的视频,运用程序的小图标则浮在了视频上面
3、在网上下了个RockPlay播放器,打开视频的时候会提示用哪种解码方式,我先选择了硬解码方式,这时播放的视频内容可以在显示器上正常显示,而lcd上则为黑色的,只有播放器的UI可以显示;然后我又选择了软解码方式,这时播放的视频内容在显示器上和lcd上都可以显示!!!由于视频的片源为720P的,软解码的效果比硬解码要差很多,而且软解码为会做到自动适应显示器的宽度!!!!

你可能感兴趣的:(uboot 环境变量配置fb及双屏显示(vga、lcd))