2015年3月9日 星期一

隨手筆記-5-panel 設定

HW:
  • Board:imx6 - mx6q_sabresd (FreeScale)
  • Panel: HSD101PWW1 (HannStar)
環境: Android 4.4 + Kernel 3.0.35

uboot-imx/include/lcd.h
typedef struct vidinfo {
 ushort vl_col;  /* Number of columns (i.e. 640) */
 ushort vl_row;  /* Number of rows (i.e. 480) */
 ushort vl_width; /* Width of display area in millimeters */
 ushort vl_height; /* Height of display area in millimeters */

 /* LCD configuration register */
 u_char vl_clkp; /* Clock polarity */
 u_char vl_oep;  /* Output Enable polarity */
 u_char vl_hsp;  /* Horizontal Sync polarity */
 u_char vl_vsp;  /* Vertical Sync polarity */
 u_char vl_dp;  /* Data polarity */
 u_char vl_bpix; /* Bits per pixel, 0 = 1, 1 = 2, 2 = 4, 3 = 8 */
 u_char vl_lbw;  /* LCD Bus width, 0 = 4, 1 = 8 */
 u_char vl_splt; /* Split display, 0 = single-scan, 1 = dual-scan */
 u_char vl_clor; /* Color, 0 = mono, 1 = color */
 u_char vl_tft;  /* 0 = passive, 1 = TFT */

 /* Horizontal control register. Timing from data sheet */
 ushort vl_wbl;  /* Wait between lines */

 /* Vertical control register */
 u_char vl_vpw;  /* Vertical sync pulse width */
 u_char vl_lcdac; /* LCD AC timing */
 u_char vl_wbf;  /* Wait between frames */
} vidinfo_t;

uboot-imx/board/freescale/mx6q_sabresd/mx6q_sabresd.c
static struct fb_videomode lvds_xga = {
 "XGA", 60, 1280, 800, 14493, 40, 40, 10, 3, 80, 10, 
  FB_SYNC_EXT,  
  FB_VMODE_NONINTERLACED, 
  1, 
    };
vidinfo_t panel_info;  <-記得改
...
...
vidinfo_t panel_info = {
 .vl_refresh = 60,
 .vl_col = 1280,
 .vl_row = 800,
 .vl_pixclock = 14066666,
 .vl_left_margin = 40,
 .vl_right_margin = 40,
 .vl_upper_margin = 10,
 .vl_lower_margin = 3,
 .vl_hsync = 80,
 .vl_vsync = 10,
 .vl_sync = 0,
 .vl_mode = 0,
 .vl_flag = 0,
 .vl_bpix = 3,
 .cmap:0,
};

kernel_imx/drivers/video/mxc/ldb.c
kernel_imx/include/linux/fb.h
static struct fb_videomode ldb_modedb[] = { 
    {
     "LDB-WXGA",     //name
     60,     //refresh
     1280,   //xres
     800,     //yres
     14065,    //pixelcolock
     40,    //left_margin  = HBPD(horizontal back porch)
     40,    //right_margin = HFPD(horizontal front porth)
     10,    //upper_margin = VBPD(vertical back porch)
     3,      //lower_margin = VFBD(vertical front porch)
     80,    //hsync_len = HSPW(horizontal sync pulse width)
    10,     //vsync_len = VSPW(vertical sync pulse width
     0,      //sync
     FB_VMODE_NONINTERLACED,   //vmode
     FB_MODE_IS_DETAILED,}, //flag
    {   
     "LDB-XGA", 60, 1024, 768, 15385,
     220, 40, 
     21, 7,
     60, 10, 
     0,  
     FB_VMODE_NONINTERLACED,
     FB_MODE_IS_DETAILED,},
    {   
     "LDB-1080P60", 60, 1920, 1080, 7692,
     100, 40, 
     30, 3,
     10, 2,
     0,  
     FB_VMODE_NONINTERLACED,
     FB_MODE_IS_DETAILED,},
};

kernel_imx/arch/arm/mach-mx6/board-mx6q_sabresd.c
static struct fsl_mxc_ldb_platform_data ldb_data = {
    .ipu_id = 0, 
    .disp_id = 1, 
    .ext_ref = 1, 
    .mode = LDB_SEP1,   <--Defaule為LVDS1開機
    .sec_ipu_id = 0, 
    .sec_disp_id = 0, 
};

static struct ipuv3_fb_platform_data sabresd_fb_data[] = {
    { /*fb0*/
    .disp_dev = "ldb",
    .interface_pix_fmt = IPU_PIX_FMT_RGB666,
    .mode_str = "LDB-XGA",   <--對應ldb.c的內容
    .default_bpp = 16,
    .int_clk = false,
    .late_init = false,
    }, { 
    .disp_dev = "hdmi",
    .interface_pix_fmt = IPU_PIX_FMT_RGB24,
    .mode_str = "1920x1080M@60",
    .default_bpp = 32,
    .int_clk = false,
    .late_init = false,
    }, { 
    .disp_dev = "ldb",
    .interface_pix_fmt = IPU_PIX_FMT_RGB666,
    .mode_str = "LDB-XGA",
    .default_bpp = 16,
    .int_clk = false,
    .late_init = false,
    },   
};

kernel_imx/drivers/video/mxc/ldb.c

/*
 *    "ldb=spl0/1"       --      split mode on DI0/1
 *    "ldb=dul0/1"       --      dual mode on DI0/1
 *    "ldb=sin0/1"       --      single mode on LVDS0/1
 *    "ldb=sep0/1"   --      separate mode begin from LVDS0/1 
 *
 *    there are two LVDS channels(LVDS0 and LVDS1) which can transfer video
 *    datas, there two channels can be used as split/dual/single/separate mode.
 *
 *    split mode means display data from DI0 or DI1 will send to both channels
 *    LVDS0+LVDS1.
 *    dual mode means display data from DI0 or DI1 will be duplicated on LVDS0
 *    and LVDS1, it said, LVDS0 and LVDS1 has the same content.
 *    single mode means only work for DI0/DI1->LVDS0 or DI0/DI1->LVDS1.
 *    separate mode means you can make DI0/DI1->LVDS0 and DI0/DI1->LVDS1 work
 *    at the same time.
 */
static int __init ldb_setup(char *options)
{
    if (!strcmp(options, "spl0"))
        g_ldb_mode = LDB_SPL_DI0;
    else if (!strcmp(options, "spl1"))
        g_ldb_mode = LDB_SPL_DI1;
    else if (!strcmp(options, "dul0"))
        g_ldb_mode = LDB_DUL_DI0;
    else if (!strcmp(options, "dul1"))
        g_ldb_mode = LDB_DUL_DI1;
    else if (!strcmp(options, "sin0"))
        g_ldb_mode = LDB_SIN0;
    else if (!strcmp(options, "sin1"))
        g_ldb_mode = LDB_SIN1;
    else if (!strcmp(options, "sep0"))
        g_ldb_mode = LDB_SEP0;
    else if (!strcmp(options, "sep1"))
        g_ldb_mode = LDB_SEP1;

    return 1;
}
__setup("ldb=", ldb_setup);

目前使用的參數為:
setenv bootargs console=ttymxc0,115200 androidboot.console=ttymxc0 vmalloc=400M 
init=/init video=mxcfb0:dev=ldb,LDB-XGA,if=RGB666,bpp=16 ldb=sin1 
video=mxcfb1:off video=mxcfb2:off fbmem=16M androidboot.hardware=freescale
--------------------------------------------------------------------------------------------------------------
drivers/video/fbmem.c
__setup("video=", video_setup);
static int __init video_setup(char *options) //把video的参数放到options中

static int mxcfb_option_setup(struct platform_device *pdev, struct fb_info *fbi) 解析字串
video=mxcfb0:dev=hdmi,1920x1080M@60
把 1920x1080M 放到pdata->mode_str

如果在uboot中没用到vidoe=参数
arch/arm/mach-mx6q/board-mx6_sabresd.c中有預設值
static struct ipuv3_fb_platform_data board_fb_data[] = {
    { /*fb0*/
  .disp_dev = "hdmi",
  .interface_pix_fmt = IPU_PIX_FMT_RGB24,.mode_str = "1920x1080M@60",
  .default_bpp = 32,
  .int_clk = false,
  .late_init = false,
  }
}
 static void __init fixup_mxc_board(struct machine_desc *desc, struct tag *tags,
   char **cmdline, struct meminfo *mi)
{
  char *str;
  struct tag *t;
  int i = 0;
  struct ipuv3_fb_platform_data *pdata_fb = board_fb_data;
}
ref: Here
--------------------------------------------------------------------------------------------------------------
IPU: Image Processing Unit
DI : Display Interface

There are 2 IPUs in i.mX6Q(IPU0 and IPU1),
and every IPU has 2 display interface(IPU0_DI0/IPU0_DI1; IPU1_DI0/IPU1_DI1)
It means IPU0 has disp_id=0 and disp_id=1 ,
               IPU1 has disp_id=0 and disp_id=1.

For example
(1)IPU1_DI1------>HDMI
(2)IPU0_DI0------>DISP0--->ADV7125
(3)LVDS datastructure It means LVDS0 uses IPU1_DI0 and LVDS1 uses IPU0_DI1.

ref : 1. Here 2. Magnum Programm Life

沒有留言:

張貼留言