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
要想做到双屏显示就得重新配置一下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的,软解码的效果比硬解码要差很多,而且软解码为会做到自动适应显示器的宽度!!!!