diff options
Diffstat (limited to 'drivers/video/wmt/vout-wmt.c')
-rw-r--r--[-rwxr-xr-x] | drivers/video/wmt/vout-wmt.c | 1083 |
1 files changed, 631 insertions, 452 deletions
diff --git a/drivers/video/wmt/vout-wmt.c b/drivers/video/wmt/vout-wmt.c index b7ff0bf4..323f9278 100755..100644 --- a/drivers/video/wmt/vout-wmt.c +++ b/drivers/video/wmt/vout-wmt.c @@ -2,7 +2,7 @@ * linux/drivers/video/wmt/vout-wmt.c * WonderMedia video post processor (VPP) driver * - * Copyright c 2014 WonderMedia Technologies, Inc. + * Copyright c 2013 WonderMedia Technologies, Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -31,13 +31,14 @@ static int vo_plug_flag; #endif int vo_plug_vout; int (*vo_plug_func)(int hotplug); -enum vout_mode_t dvo_vout_mode; -enum vout_mode_t int_vout_mode; +vout_mode_t dvo_vout_mode; +vout_mode_t int_vout_mode; +struct fb_videomode vo_oem_vmode; int hdmi_cur_plugin; -struct vout_t *vo_poll_vout; +vout_t *vo_poll_vout; /* GPIO 10 & 11 */ -struct swi2c_reg_s vo_gpio_scl = { +swi2c_reg_t vo_gpio_scl = { .bit_mask = BIT10, .gpio_en = (__GPIO_BASE + 0x40), .out_en = (__GPIO_BASE + 0x80), @@ -47,7 +48,7 @@ struct swi2c_reg_s vo_gpio_scl = { .pull_en_bit_mask = BIT10, }; -struct swi2c_reg_s vo_gpio_sda = { +swi2c_reg_t vo_gpio_sda = { .bit_mask = BIT11, .gpio_en = (__GPIO_BASE + 0x40), .out_en = (__GPIO_BASE + 0x80), @@ -57,66 +58,30 @@ struct swi2c_reg_s vo_gpio_sda = { .pull_en_bit_mask = BIT11, }; -struct swi2c_handle_s vo_swi2c_dvi = { +swi2c_handle_t vo_swi2c_dvi = { .scl_reg = &vo_gpio_scl, .sda_reg = &vo_gpio_sda, }; -#define DVI_POLL_TIME_MS 1000 - -extern void hdmi_config_audio(struct vout_audio_t *info); - -/*---------------------------------- API ------------------------------------*/ -#ifdef DEBUG -void vout_print_entry(struct vout_t *vo) -{ - if (vo == 0) - return; +struct vout_init_parm_t { + unsigned int virtual_display; + unsigned int def_resx; + unsigned int def_resy; + unsigned int def_fps; + unsigned int ub_resx; + unsigned int ub_resy; +}; - MSG(" =============== vout %d ===============\n", vo->num); - MSG("fix 0x%x", vo->fix_cap); - MSG("(inf %d,bus %d,govr %d,ext dev %d,fix plug %d,aud %d,edid %d)\n", - (vo->fix_cap & VOUT_CAP_INTERFACE), - (vo->fix_cap & VOUT_CAP_BUS) >> 8, - (vo->fix_cap & VOUT_CAP_GOVR) >> 12, - (vo->fix_cap & VOUT_CAP_EXT_DEV) ? 1 : 0, - (vo->fix_cap & VOUT_CAP_FIX_PLUG) ? 1 : 0, - (vo->fix_cap & VOUT_CAP_AUDIO) ? 1 : 0, - (vo->fix_cap & VOUT_CAP_EDID) ? 1 : 0); - MSG("info %d,%s\n", vo->info->num, vpp_mod_str[vo->govr->mod]); - MSG("inf 0x%x,dev 0x%x\n", (int)vo->inf, (int)vo->dev); - MSG("resx %d,resy %d,fps %d\n", vo->resx, vo->resy, vo->fps); - MSG("pixclk %d,option %d,%d,%d,disable %d\n", vo->pixclk, - vo->option[0], vo->option[1], vo->option[2], vo->disable); - MSG("sts(reg %d,act %d,plug %d,edid %d,blank %d,pwrdn %d,cp %d)\n", - (vo->status & VPP_VOUT_STS_REGISTER) ? 1 : 0, - (vo->status & VPP_VOUT_STS_ACTIVE) ? 1 : 0, - (vo->status & VPP_VOUT_STS_PLUGIN) ? 1 : 0, - (vo->status & VPP_VOUT_STS_EDID) ? 1 : 0, - (vo->status & VPP_VOUT_STS_BLANK) ? 1 : 0, - (vo->status & VPP_VOUT_STS_POWERDN) ? 1 : 0, - (vo->status & VPP_VOUT_STS_CONTENT_PROTECT) ? 1 : 0); - - if (vo->inf) { - MSG(" ===== inf entry =====\n"); - MSG("mode %d, %s\n", - vo->inf->mode, vout_inf_str[vo->inf->mode]); - } +#define DVI_POLL_TIME_MS 100 - if (vo->dev) { - MSG(" ===== dev entry =====\n"); - MSG("name %s,inf %d,%s\n", vo->dev->name, - vo->dev->mode, vout_inf_str[vo->dev->mode]); - MSG("vout 0x%x,capability 0x%x\n", - (int)vo->dev->vout, vo->dev->capability); - } -} -#endif +extern void hdmi_config_audio(vout_audio_t *info); +extern vout_dev_t *lcd_get_dev(void); +/*---------------------------------- API ------------------------------------*/ int vo_i2c_proc(int id, unsigned int addr, unsigned int index, char *pdata, int len) { - struct swi2c_handle_s *handle = 0; + swi2c_handle_t *handle = 0; int ret = 0; switch (id) { @@ -150,7 +115,7 @@ int vo_i2c_proc(int id, unsigned int addr, unsigned int index, #ifndef CONFIG_UBOOT static void vo_do_plug(struct work_struct *ptr) { - struct vout_t *vo; + vout_t *vo; int plugin; if (vo_plug_func == 0) @@ -159,7 +124,7 @@ static void vo_do_plug(struct work_struct *ptr) vo = vout_get_entry(vo_plug_vout); govrh_set_dvo_enable(vo->govr, 1); plugin = vo_plug_func(1); -/* govrh_set_dvo_enable(vo->govr, plugin); */ + govrh_set_dvo_enable(vo->govr, plugin); vout_change_status(vo, VPP_VOUT_STS_PLUGIN, plugin); vo_plug_flag = 0; DBG_DETAIL("vo_do_plug %d\n", plugin); @@ -183,12 +148,12 @@ static irqreturn_t vo_plug_interrupt_routine ) { DBG_DETAIL("Enter\n"); - if ((inb(GPIO_BASE_ADDR + 0x360) & + if ((vppif_reg8_in(GPIO_BASE_ADDR + 0x360) & (0x1 << VPP_VOINT_NO)) == 0) return IRQ_NONE; /* clear int status */ - outb(0x1 << VPP_VOINT_NO, GPIO_BASE_ADDR + 0x360); + vppif_reg8_out(GPIO_BASE_ADDR + 0x360, 0x1 << VPP_VOINT_NO); #ifdef __KERNEL__ /* if (vo_plug_flag == 0) { */ /* GPIO irq disable */ @@ -208,7 +173,7 @@ struct timer_list vo_poll_timer; #ifdef CONFIG_VO_POLL_WORKQUEUE static void vo_do_poll(struct work_struct *ptr) { - struct vout_t *vo; + vout_t *vo; vo = vo_poll_vout; if (vo) { @@ -228,7 +193,7 @@ static void vo_do_poll_tasklet unsigned long data /*!<; // tasklet input data */ ) { - struct vout_t *vo; + vout_t *vo; vpp_lock(); vo = vo_poll_vout; @@ -251,10 +216,8 @@ void vo_do_poll_tmr(int ms) #endif } -static void vo_set_poll(struct vout_t *vo, int on, int ms) +static void vo_set_poll(vout_t *vo, int on, int ms) { - DMSG("%d\n", on); - if (on) { vo_poll_vout = vo; if (vo_poll_timer.function) { @@ -286,7 +249,7 @@ void vout_set_int_type(int type) { unsigned char reg; - reg = inb(GPIO_BASE_ADDR + 0x300 + VPP_VOINT_NO); + reg = vppif_reg8_in(GPIO_BASE_ADDR+0x300 + VPP_VOINT_NO); reg &= ~0x7; switch (type) { case 0: /* low level */ @@ -299,7 +262,7 @@ void vout_set_int_type(int type) default: break; } - outb(reg, GPIO_BASE_ADDR + 0x300 + VPP_VOINT_NO); + vppif_reg8_out(GPIO_BASE_ADDR + 0x300 + VPP_VOINT_NO, reg); } EXPORT_SYMBOL(vout_set_int_type); @@ -312,18 +275,18 @@ EXPORT_SYMBOL(vout_set_int_enable); int vout_get_clr_int(void) { - if ((inb(GPIO_BASE_ADDR + 0x360) & + if ((vppif_reg8_in(GPIO_BASE_ADDR + 0x360) & (0x1 << VPP_VOINT_NO)) == 0) return 1; /* clear int status */ - outb(0x1 << VPP_VOINT_NO, GPIO_BASE_ADDR + 0x360); + vppif_reg8_out(GPIO_BASE_ADDR + 0x360, 0x1 << VPP_VOINT_NO); return 0; } EXPORT_SYMBOL(vout_get_clr_int); static void vo_plug_enable(int enable, void *func, int no) { - struct vout_t *vo; + vout_t *vo; DBG_DETAIL("%d\n", enable); vo_plug_vout = no; @@ -362,77 +325,78 @@ static void vo_plug_enable(int enable, void *func, int no) /*--------------------------------- DVI ------------------------------------*/ #ifdef WMT_FTBLK_VOUT_DVI -static int vo_dvi_blank(struct vout_t *vo, enum vout_blank_t arg) +static int vo_dvi_blank(vout_t *vo, vout_blank_t arg) { - DMSG("(%d, %d)\n", vo->pre_blank, arg); - if(vo->pre_blank == arg) - return 0; - - if (vo->pre_blank == VOUT_BLANK_POWERDOWN) { - if (vo->dev) { + DBG_DETAIL("(%d)\n", arg); + if (vo->pre_blank == VOUT_BLANK_POWERDOWN) { + if (vo->dev) { + vo->dev->init(vo); #ifdef __KERNEL__ - if (!g_vpp.dvi_int_disable && vo->dev->interrupt) - vo_plug_enable(VPP_FLAG_ENABLE, - vo->dev->interrupt, vo->num); - else if (vo->dev->poll) - vo_set_poll(vo, (vo->dev->poll) ? 1 : 0, - DVI_POLL_TIME_MS); + if (vo->dev->poll) + vo_set_poll(vo, (vo->dev->poll) ? 1 : 0, + DVI_POLL_TIME_MS); #endif - } - } + } + } #ifdef __KERNEL__ - if (arg == VOUT_BLANK_POWERDOWN) - vo_set_poll(vo, 0, 0); + if (arg == VOUT_BLANK_POWERDOWN) + vo_set_poll(vo, 0, 0); + + /* patch for virtual fb,if HDMI plugin then DVI blank */ + if (g_vpp.virtual_display || (g_vpp.dual_display == 0)) { + if (vout_chkplug(VPP_VOUT_NUM_HDMI)) { + arg = VOUT_BLANK_NORMAL; + vout_change_status(vo, VPP_VOUT_STS_BLANK, arg); + } + } #endif - if (!lcd_get_dev()) /* enable DVO not contain LCD */ - govrh_set_dvo_enable(vo->govr, - (arg == VOUT_BLANK_UNBLANK) ? 1 : 0); - vo->pre_blank = arg; - return 0; + if (!lcd_get_dev()) /* enable DVO not contain LCD */ + govrh_set_dvo_enable(vo->govr, + (arg == VOUT_BLANK_UNBLANK) ? 1 : 0); + vo->pre_blank = arg; + return 0; } -static int vo_dvi_config(struct vout_t *vo, int arg) +static int vo_dvi_config(vout_t *vo, int arg) { - struct vout_info_t *vo_info; + vout_info_t *vo_info; DBG_DETAIL("Enter\n"); - vo_info = (struct vout_info_t *) arg; + vo_info = (vout_info_t *) arg; govrh_set_dvo_sync_polar(vo->govr, - (vo_info->option & VPP_DVO_SYNC_POLAR_HI) ? 0 : 1, - (vo_info->option & VPP_DVO_VSYNC_POLAR_HI) ? 0 : 1); + (vo_info->option & VPP_DVO_SYNC_POLAR_HI) ? 0 : 1, + (vo_info->option & VPP_DVO_VSYNC_POLAR_HI) ? 0 : 1); return 0; } -static int vo_dvi_init(struct vout_t *vo, int arg) +static int vo_dvi_init(vout_t *vo, int arg) { unsigned int clk_delay; DBG_DETAIL("(%d)\n", arg); - vo->pre_blank = VOUT_BLANK_POWERDOWN; - lvds_set_enable(0); govrh_set_dvo_color_format(vo->govr, vo->option[0]); - govrh_set_dvo_outdatw(vo->govr, vo->option[1] & WMT_DISP_FB_DVI_24BIT); - govrh_IGS_set_mode(vo->govr, 0, WMT_DISP_FB_GET_RGB_MODE(vo->option[1]), - (vo->option[1] & WMT_DISP_FB_MSB) ? 1 : 0); - govrh_IGS_set_RGB_swap(vo->govr, WMT_DISP_FB_RGB_SWAP(vo->option[1])); - clk_delay = (vo->option[1] & WMT_DISP_FB_DVI_24BIT) ? + /* bit0:0-12 bit,1-24bit */ + govrh_set_dvo_outdatw(vo->govr, vo->option[1] & BIT0); + govrh_IGS_set_mode(vo->govr, 0, (vo->option[1] & 0x600) >> 9, + (vo->option[1] & 0x800) >> 11); + govrh_IGS_set_RGB_swap(vo->govr, (vo->option[1] & 0x3000) >> 12); + clk_delay = (vo->option[1] & BIT0) ? VPP_GOVR_DVO_DELAY_24 : VPP_GOVR_DVO_DELAY_12; govrh_set_dvo_clock_delay(vo->govr, ((clk_delay & BIT14) != 0x0), clk_delay & 0x3FFF); if (vo->dev) { vo->dev->set_mode(&vo->option[0]); vo->dev->set_power_down(VPP_FLAG_DISABLE); - if (!g_vpp.dvi_int_disable && vo->dev->interrupt) + if (vo->dev->interrupt) vo_plug_enable(VPP_FLAG_ENABLE, vo->dev->interrupt, vo->num); #ifdef __KERNEL__ - else if (vo->dev->poll) { + if (vo->dev->poll) vo_set_poll(vo, (vo->dev->poll) ? 1 : 0, DVI_POLL_TIME_MS); - } #endif vout_change_status(vo, VPP_VOUT_STS_PLUGIN, vo->dev->check_plugin(0)); @@ -445,7 +409,7 @@ static int vo_dvi_init(struct vout_t *vo, int arg) return 0; } -static int vo_dvi_uninit(struct vout_t *vo, int arg) +static int vo_dvi_uninit(vout_t *vo, int arg) { DBG_DETAIL("(%d)\n", arg); @@ -457,7 +421,7 @@ static int vo_dvi_uninit(struct vout_t *vo, int arg) return 0; } -static int vo_dvi_chkplug(struct vout_t *vo, int arg) +static int vo_dvi_chkplug(vout_t *vo, int arg) { int plugin = 1; @@ -465,7 +429,7 @@ static int vo_dvi_chkplug(struct vout_t *vo, int arg) return plugin; } -static int vo_dvi_get_edid(struct vout_t *vo, int arg) +static int vo_dvi_get_edid(vout_t *vo, int arg) { char *buf; int i, cnt; @@ -494,7 +458,7 @@ static int vo_dvi_get_edid(struct vout_t *vo, int arg) return 0; } -struct vout_inf_t vo_dvi_inf = { +vout_inf_t vo_dvi_inf = { .mode = VOUT_INF_DVI, .init = vo_dvi_init, .uninit = vo_dvi_uninit, @@ -532,9 +496,7 @@ static struct timer_list hdmi_plug_timer; void vo_hdmi_cp_set_enable_tmr(int sec) { -#ifdef __KERNEL__ int ms = sec * 1000; -#endif DBG_MSG("[HDMI] set enable tmr %d sec\n", sec); @@ -554,9 +516,8 @@ void vo_hdmi_cp_set_enable_tmr(int sec) hdmi_set_cp_enable(VPP_FLAG_ENABLE); #endif } -EXPORT_SYMBOL(vo_hdmi_cp_set_enable_tmr); -static int vo_hdmi_blank(struct vout_t *vo, enum vout_blank_t arg) +static int vo_hdmi_blank(vout_t *vo, vout_blank_t arg) { int enable; @@ -579,7 +540,7 @@ static irqreturn_t vo_hdmi_cp_interrupt void *dev_id /*!<; // device id */ ) { - struct vout_t *vo; + vout_t *vo; DBG_DETAIL("%d\n", irq); vo = vout_get_entry(VPP_VOUT_NUM_HDMI); @@ -610,7 +571,7 @@ static void vo_hdmi_do_plug(struct work_struct *ptr) static void vo_hdmi_do_plug(void) #endif { - struct vout_t *vo; + vout_t *vo; int plugin; int option = 0; @@ -636,14 +597,14 @@ DECLARE_WORK(vo_hdmi_plug_work, vo_hdmi_do_plug); static void hdmi_handle_plug(vpp_flag_t enable) { - schedule_work(&vo_hdmi_plug_work); + schedule_work(&vo_hdmi_plug_work); } static void vo_hdmi_handle_plug_tmr(int ms) { static int timer_init; - if (timer_init == 0) { + if(timer_init == 0) { init_timer(&hdmi_plug_timer); hdmi_plug_timer.data = VPP_FLAG_ENABLE; hdmi_plug_timer.function = (void *) hdmi_handle_plug; @@ -663,13 +624,13 @@ static irqreturn_t vo_hdmi_plug_interrupt hdmi_clear_plug_status(); if (g_vpp.hdmi_certify_flag) vo_hdmi_do_plug(0); - else + else vo_hdmi_handle_plug_tmr(HDMI_PLUG_DELAY); return IRQ_HANDLED; } #endif -static int vo_hdmi_init(struct vout_t *vo, int arg) +static int vo_hdmi_init(vout_t *vo, int arg) { DBG_DETAIL("(%d)\n", arg); @@ -679,7 +640,7 @@ static int vo_hdmi_init(struct vout_t *vo, int arg) hdmi_enable_plugin(1); if (g_vpp.hdmi_disable) - return 0; + return 0; #ifndef CONFIG_UBOOT if (vpp_request_irq(VPP_IRQ_HDMI_CP, vo_hdmi_cp_interrupt, SA_INTERRUPT, "hdmi cp", (void *) 0)) { @@ -699,7 +660,7 @@ static int vo_hdmi_init(struct vout_t *vo, int arg) return 0; } -static int vo_hdmi_uninit(struct vout_t *vo, int arg) +static int vo_hdmi_uninit(vout_t *vo, int arg) { DBG_DETAIL("(%d)\n", arg); hdmi_enable_plugin(0); @@ -714,15 +675,16 @@ static int vo_hdmi_uninit(struct vout_t *vo, int arg) return 0; } -static int vo_hdmi_config(struct vout_t *vo, int arg) +static int vo_hdmi_config(vout_t *vo, int arg) { - struct vout_info_t *vo_info; + vout_info_t *vo_info; vdo_color_fmt colfmt; hdmi_set_enable(0); - vo_info = (struct vout_info_t *) arg; + vo_info = (vout_info_t *) arg; DBG_DETAIL("(%dx%d@%d)\n", vo_info->resx, vo_info->resy, vo_info->fps); + DPRINT("hdmi config (%dx%d@%d)\n", vo_info->resx, vo_info->resy, vo_info->fps); /* 1280x720@60, HDMI pixel clock 74250060 not 74500000 */ if ((vo_info->resx == 1280) @@ -750,18 +712,18 @@ static int vo_hdmi_config(struct vout_t *vo, int arg) return 0; } -static int vo_hdmi_chkplug(struct vout_t *vo, int arg) +static int vo_hdmi_chkplug(vout_t *vo, int arg) { int plugin; if (g_vpp.hdmi_disable) - return 0; + return 0; plugin = hdmi_get_plugin(); DBG_DETAIL("%d\n", plugin); return plugin; } -static int vo_hdmi_get_edid(struct vout_t *vo, int arg) +static int vo_hdmi_get_edid(vout_t *vo, int arg) { char *buf; #ifdef CONFIG_WMT_EDID @@ -794,7 +756,7 @@ static int vo_hdmi_get_edid(struct vout_t *vo, int arg) return 0; } -struct vout_inf_t vo_hdmi_inf = { +vout_inf_t vo_hdmi_inf = { .mode = VOUT_INF_HDMI, .init = vo_hdmi_init, .uninit = vo_hdmi_uninit, @@ -816,11 +778,11 @@ module_init(vo_hdmi_initial); /*--------------------------------- LVDS ------------------------------------*/ #ifdef WMT_FTBLK_VOUT_LVDS int vo_lvds_init_flag; -static int vo_lvds_blank(struct vout_t *vo, enum vout_blank_t arg) +static int vo_lvds_blank(vout_t *vo, vout_blank_t arg) { DBG_DETAIL("(%d)\n", arg); if (arg == VOUT_BLANK_POWERDOWN) { - lvds_regs->test.b.tre_en = 0; + vppif_reg32_write(LVDS_TRE_EN, 0); } else { /* avoid suspend signal not clear */ lvds_set_enable((arg == VOUT_BLANK_UNBLANK) ? 1 : 0); } @@ -830,7 +792,7 @@ static int vo_lvds_blank(struct vout_t *vo, enum vout_blank_t arg) return 0; } -static int vo_lvds_config(struct vout_t *vo, int arg) +static int vo_lvds_config(vout_t *vo, int arg) { DBG_DETAIL("(%d)\n", arg); lvds_set_power_down(VPP_FLAG_DISABLE); @@ -838,7 +800,7 @@ static int vo_lvds_config(struct vout_t *vo, int arg) return 0; } -static int vo_lvds_init(struct vout_t *vo, int arg) +static int vo_lvds_init(vout_t *vo, int arg) { DBG_DETAIL("(%d)\n", arg); @@ -852,7 +814,7 @@ static int vo_lvds_init(struct vout_t *vo, int arg) return 0; } -static int vo_lvds_uninit(struct vout_t *vo, int arg) +static int vo_lvds_uninit(vout_t *vo, int arg) { DBG_DETAIL("(%d)\n", arg); lvds_set_enable(VPP_FLAG_DISABLE); @@ -864,7 +826,7 @@ static int vo_lvds_uninit(struct vout_t *vo, int arg) return 0; } -static int vo_lvds_chkplug(struct vout_t *vo, int arg) +static int vo_lvds_chkplug(vout_t *vo, int arg) { DBG_DETAIL("\n"); #if 0 @@ -875,7 +837,7 @@ static int vo_lvds_chkplug(struct vout_t *vo, int arg) return 1; } -struct vout_inf_t vo_lvds_inf = { +vout_inf_t vo_lvds_inf = { .mode = VOUT_INF_LVDS, .capability = VOUT_INF_CAP_FIX_PLUG, .init = vo_lvds_init, @@ -898,9 +860,9 @@ module_init(vo_lvds_initial); #endif /* WMT_FTBLK_VOUT_LVDS */ /*---------------------------------- API ------------------------------------*/ #ifndef CFG_LOADER -int vout_set_audio(struct vout_audio_t *arg) +int vout_set_audio(vout_audio_t *arg) { - struct vout_t *vout; + vout_t *vout; int ret = 0; #if 0 @@ -914,9 +876,7 @@ int vout_set_audio(struct vout_audio_t *arg) #ifdef WMT_FTBLK_VOUT_HDMI vout = vout_get_entry(VPP_VOUT_NUM_HDMI); if (vout) { - g_vpp.hdmi_ch_change = 1; hdmi_config_audio(arg); - g_vpp.hdmi_ch_change = 0; ret = 1; } #endif @@ -927,14 +887,14 @@ int vout_set_audio(struct vout_audio_t *arg) /* 3445 port1 : DVI/SDD, port2 : VGA/SDA, port3 : HDMI/LVDS */ /* 3481 port1 : HDMI/LVDS, port2 : DVI */ /* 3498 port1 : HDMI, port2 : DVI/LVDS */ -struct vout_t vout_entry_0 = { +vout_t vout_entry_0 = { .fix_cap = BIT(VOUT_INF_HDMI), .option[0] = VDO_COL_FMT_ARGB, .option[1] = VPP_DATAWIDHT_24, .option[2] = 0, }; -struct vout_t vout_entry_1 = { +vout_t vout_entry_1 = { .fix_cap = BIT(VOUT_INF_DVI) + BIT(VOUT_INF_LVDS) + VOUT_CAP_EXT_DEV + 0x100, /* i2c bus 1,ext dev */ .option[0] = VDO_COL_FMT_ARGB, @@ -942,256 +902,366 @@ struct vout_t vout_entry_1 = { .option[2] = 0, }; -int vout_add_display(int fb_no, unsigned int *parm) +void vout_init_param(struct vout_init_parm_t *init_parm) { - struct vout_info_t *info; - struct vout_t *vout; - int ret = 0; + char buf[100]; + int varlen = 100; + unsigned int parm[10]; - info = vout_info[fb_no]; - if (!info) { - info = kmalloc(sizeof(struct vout_info_t), GFP_KERNEL); - if (!info) - return 1; - memset(info, 0, sizeof(struct vout_info_t)); - vout_info[fb_no] = info; - DBG_MSG("malloc vout_info %d,0x%x\n", fb_no, (int) info); -#ifdef CONFIG_KERNEL - sema_init(&info->sem, 1); -#endif + memset(init_parm, 0, sizeof(struct vout_init_parm_t)); + + /* register vout & set default */ + vout_register(0, &vout_entry_0); + vout_entry_0.inf = vout_inf_get_entry(VOUT_INF_HDMI); + vout_register(1, &vout_entry_1); + vout_entry_1.inf = vout_inf_get_entry(VOUT_INF_DVI); + + /* [uboot parameter] up bound : resx:resy */ + if (wmt_getsyspara("wmt.display.upbound", buf, &varlen) == 0) { + vpp_parse_param(buf, parm, 2, 0); + init_parm->ub_resx = parm[0]; + init_parm->ub_resy = parm[1]; + MSG("up bound(%d,%d)\n", init_parm->ub_resx, + init_parm->ub_resy); } - if (parm[0] == VOUT_BOOT) { - struct vout_t *vo_boot; + /* [uboot parameter] default resolution : resx:resy:fps */ + init_parm->def_resx = VOUT_INFO_DEFAULT_RESX; + init_parm->def_resy = VOUT_INFO_DEFAULT_RESY; + init_parm->def_fps = VOUT_INFO_DEFAULT_FPS; + if (wmt_getsyspara("wmt.display.default.res", buf, &varlen) == 0) { + vpp_parse_param(buf, parm, 3, 0); + init_parm->def_resx = parm[0]; + init_parm->def_resy = parm[1]; + init_parm->def_fps = parm[2]; + MSG("default res(%d,%d,%d)\n", init_parm->def_resx, + init_parm->def_resy, init_parm->def_fps); + } else if (wmt_getsyspara("wmt.display.param", buf, &varlen) == 0) { + vpp_parse_param(buf, parm, 6, 0); + init_parm->def_resx = parm[3]; + init_parm->def_resy = parm[4]; + init_parm->def_fps = parm[5]; + MSG("param2 res(%d,%d,%d)\n", init_parm->def_resx, + init_parm->def_resy, init_parm->def_fps); + } +} - MSG("[VOUT] %s (%d:%d:%d)\n", - (fb_no == 0) ? "tvbox" : "virtual display", - parm[0], parm[1], parm[2]); - if (fb_no == 0) { +const char *vout_sys_parm_str[] = {"wmt.display.param", "wmt.display.param2"}; +int vout_check_display_info(struct vout_init_parm_t *init_parm) +{ + char buf[100]; + const char *display_param[] = { "2:0:24:1024:600:60", "4:0:24:1024:600:60" }; + int varlen = 100; + unsigned int parm[10]; + vout_t *vo = 0; + int ret = 1; + int i; + int info_no; + + DBG_DETAIL("Enter\n"); + + /* [uboot parameter] display param : type:op1:op2:resx:resy:fps */ + for (i = 0; i < 2; i++) { + strncpy(buf, display_param[i], 19); + DBG_MSG("display param %d : %s\n", i, buf); + vpp_parse_param(buf, (unsigned int *)parm, 6, 0); + MSG("boot parm vo %d opt %d,%d, %dx%d@%d\n", parm[0], + parm[1], parm[2], parm[3], parm[4], parm[5]); + vo = vout_get_entry_adapter(parm[0]); + if (vo == 0) { + vout_t *vo_boot; + + if (parm[0] != VOUT_BOOT) { + ret = 1; + DBG_ERR("uboot param invalid\n"); + break; + } + + g_vpp.virtual_display_mode = parm[1]; + if (parm[1] == 1) { + init_parm->def_resx = parm[3]; + init_parm->def_resy = parm[4]; + init_parm->def_fps = parm[5]; + parm[3] = 1920; + parm[4] = 1080; + parm[5] = 60; + } else if (parm[1] == 2) { + init_parm->def_resx = parm[3]; + init_parm->def_resy = parm[4]; + init_parm->def_fps = parm[5]; + g_vpp.dual_display = 0; + break; + } + + MSG("[VOUT] virtual display\n"); + init_parm->virtual_display = 1; g_vpp.virtual_display = 1; g_vpp.fb0_bitblit = 1; + vo_boot = kmalloc(sizeof(vout_t), GFP_KERNEL); + if (vo_boot == 0) { + ret = 1; + break; + } + vo_boot->resx = parm[3]; + vo_boot->resy = parm[4]; + vo_boot->pixclk = parm[5]; + vo_boot->inf = 0; + vo_boot->num = VPP_VOUT_INFO_NUM; + vo_boot->govr = 0; + info_no = vout_info_add_entry(vo_boot); + kfree(vo_boot); } else { - g_vpp.stream_fb = fb_no; + vo->inf = vout_get_inf_entry_adapter(parm[0]); + vo->option[0] = parm[1]; + vo->option[1] = parm[2]; + vo->resx = parm[3]; + vo->resy = parm[4]; + vo->pixclk = parm[5]; + vout_change_status(vo, VPP_VOUT_STS_BLANK, + (parm[2] & VOUT_OPT_BLANK) ? + VOUT_BLANK_NORMAL : VOUT_BLANK_UNBLANK); + info_no = vout_info_add_entry(vo); } - vo_boot = kmalloc(sizeof(struct vout_t), GFP_KERNEL); - if (vo_boot == 0) - return 1; - memset(vo_boot, 0, sizeof(struct vout_t)); - vo_boot->resx = parm[3]; - vo_boot->resy = parm[4]; - vo_boot->fps = parm[5]; - vo_boot->num = VPP_VOUT_NUM; - vout_info_add_entry(fb_no, vo_boot); - kfree(vo_boot); - return 0; - } - vout = vout_get_entry_adapter(parm[0]); - vout->inf = vout_get_inf_entry_adapter(parm[0]); - vout->option[0] = parm[1]; - vout->option[1] = parm[2]; - vout->resx = parm[3]; - vout->resy = parm[4]; - vout->fps = parm[5]; - vout->disable = (parm[2] & VOUT_OPT_BLANK) ? 1 : 0; - switch (parm[0]) { - case VOUT_LVDS: - { - struct fb_videomode *vmode = 0; - - /* lvds auto detect edid */ - if ((parm[1] == 0) && (parm[3] == 0) && (parm[4] == 0)) { - if (vout_get_edid_option(vout->num)) { - vmode = &vout->edid_info.detail_timing[0]; - if (vmode->pixclock == 0) { - vmode = 0; - DBG_ERR("LVDS timing\n"); + switch (parm[0]) { + case VOUT_LVDS: + { + struct fb_videomode *vmode; + vout_info_t *info; + + info = vout_info_get_entry(info_no); + vmode = 0; + if ((parm[1] == 0) && (parm[3] == 0) && + (parm[4] == 0)) { /* auto detect */ + if (vout_get_edid_option(vo->num)) { + vmode = &vo->edid_info.detail_timing[0]; + if (vmode->pixclock == 0) { + vmode = 0; + DBG_ERR("LVDS timing\n"); + } + } + + if (vo->inf->get_edid(vo, + (int)vo->edid) == 0) { + if (edid_parse(vo->edid, + &vo->edid_info) == 0) + DBG_ERR("LVDS edid parse\n"); + } else { + DBG_ERR("LVDS edid read\n"); } } - if (vout->inf->get_edid(vout, (int)vout->edid) == 0) { - if (edid_parse(vout->edid, - &vout->edid_info) == 0) - DBG_ERR("LVDS edid parse\n"); - } else { - DBG_ERR("LVDS edid read\n"); + if (vmode == 0) { /* use internal timing */ + lcd_parm_t *p = 0; + + if (parm[1]) { + p = lcd_get_parm(parm[1], parm[2]); + if (p) + lcd_set_lvds_id(parm[1]); + } + + if (p == 0) + p = lcd_get_oem_parm(parm[3], parm[4]); + vmode = &p->vmode; + } + memcpy(&vo_oem_vmode, vmode, + sizeof(struct fb_videomode)); + vo->option[2] = vmode->vmode; + info->resx = vmode->xres; + info->resy = vmode->yres; + info->fps = vmode->refresh; + vout_info_set_fixed_timing(info_no, &vo_oem_vmode); + lcd_set_type(1); } + case VOUT_LCD: + { + vout_dev_t *dev; + + lcd_set_parm(parm[1], parm[2] & 0xFF); + dev = lcd_get_dev(); + vo->ext_dev = dev; + vo->dev = dev; + dev->vout = vo; + vo->option[0] = VDO_COL_FMT_ARGB; + vo->option[1] &= ~0xFF; + vo->option[1] |= VPP_DATAWIDHT_24; + } + break; + case VOUT_DVI: + case VOUT_HDMI: + vout_info[info_no].option = (parm[2] & 0x2) ? + VPP_OPT_INTERLACE : 0; + break; + default: + break; } + ret = 0; + } - if (vmode == 0) { /* use internal timing */ - struct lcd_parm_t *p = 0; + if (g_vpp.virtual_display) + ret = 1; - if (parm[1]) { - p = lcd_get_parm(parm[1], parm[2]); - if (p) - lcd_set_lvds_id(parm[1]); + /* add vout entry to info */ + for (i = 0; i < VPP_VOUT_NUM; i++) { + vo = vout_get_entry(i); + if (vo) { + if (vo->resx == 0) { + vo->resx = init_parm->def_resx; + vo->resy = init_parm->def_resy; + vo->pixclk = init_parm->def_fps; } - - if (p == 0) - p = lcd_get_oem_parm(parm[3], parm[4]); - vmode = &p->vmode; - } - vout->option[2] = vmode->vmode; - info->resx = vmode->xres; - info->resy = vmode->yres; - info->fps = vmode->refresh; - vout_info_set_fixed_timing(fb_no, vmode); - lcd_set_type(1); + vout_info_add_entry(vo); } - case VOUT_LCD: - { - struct vout_dev_t *dev; - - lcd_set_parm(parm[1], parm[2] & 0xFF); - dev = lcd_get_dev(); - vout->dev = dev; - dev->vout = vout; - vout->option[0] = VDO_COL_FMT_ARGB; - vout->option[1] &= ~0xFF; - vout->option[1] |= VPP_DATAWIDHT_24; - vout->dev->init(vout); - vout_info_set_fixed_timing(fb_no, &p_lcd->vmode); + } + DBG_DETAIL("Leave\n"); + return ret; +} + +void vout_check_ext_device(void) +{ + char buf[100]; + int varlen = 100; + vout_t *vo = 0; + vout_dev_t *dev = 0; + int i; + vout_info_t *info; + + DBG_DETAIL("Enter\n"); + vpp_i2c_init(1, 0xA0); + + /* [uboot parameter] reg operation : addr op val */ + if (wmt_getsyspara("wmt.display.regop", buf, &varlen) == 0) { + unsigned int addr; + unsigned int val; + char op; + char *p, *endp; + + p = buf; + while (1) { + addr = simple_strtoul(p, &endp, 16); + if (*endp == '\0') + break; + + op = *endp; + if (endp[1] == '~') { + val = simple_strtoul(endp + 2, &endp, 16); + val = ~val; + } else { + val = simple_strtoul(endp + 1, &endp, 16); + } + + DBG_DETAIL(" reg op: 0x%X %c 0x%X\n", addr, op, val); + switch (op) { + case '|': + REG32_VAL(addr) |= val; + break; + case '=': + REG32_VAL(addr) = val; + break; + case '&': + REG32_VAL(addr) &= val; + break; + default: + DBG_ERR("Error, Unknown operator %c\n", op); + } + + if (*endp == '\0') + break; + p = endp + 1; } - break; - case VOUT_DVI: - { - struct vout_dev_t *dev = 0; - - g_vpp.dvi_int_disable = - (parm[2] & WMT_DISP_FB_DISBALE_DVI_INT) ? 1 : 0; - g_vpp.dvi_int_no = (parm[2] & WMT_DISP_FB_DVI_INT) ? - ((parm[1] & 0xF000) >> 12) : VPP_DVI_INT_DEFAULT; - g_vpp.dvi_i2c_no = (parm[2] & WMT_DISP_FB_DVI_I2C) ? - ((parm[1] & 0xF00) >> 8) : VPP_DVI_I2C_DEFAULT; - g_vpp.dvi_i2c_no &= VPP_DVI_I2C_ID_MASK; - - if (parm[2] & WMT_DISP_FB_DISABLE_EXTDEV) - vout->dev = 0; - else { - vpp_i2c_init(VPP_DVI_I2C_ID, 0xA0); + } + + /* [uboot parameter] dvi device : name:i2c id */ + vo = vout_get_entry(VPP_VOUT_NUM_DVI); + info = vout_get_info_entry(VPP_VOUT_NUM_DVI); + if (lcd_get_dev()) { + vo->dev->init(vo); + vout_info_set_fixed_timing(info->num, &p_lcd->vmode); + } else if (vo->ext_dev == 0) { + if (wmt_getsyspara("wmt.display.dvi.dev", buf, &varlen) == 0) { + unsigned int param[1]; + char *p; + + p = strchr(buf, ':'); + *p = 0; + vpp_parse_param(p + 1, param, 1, 0x1); + vpp_i2c_release(); + vpp_i2c_init(param[0], 0xA0); + MSG("dvi dev %s : %x\n", buf, param[0]); do { dev = vout_get_device(dev); if (dev == 0) break; - if (vout->fix_cap & BIT(dev->mode)) { - vout->inf = - vout_inf_get_entry(dev->mode); - if (dev->init(vout) == 0) { - vout->dev = dev; - dev->vout = vout; + if (strcmp(buf, dev->name) == 0) { + vo->ext_dev = dev; + vo->dev = dev; + dev->vout = vo; + + /* probe & init external device */ + if (dev->init(vo)) { + DBG_ERR("%s not exist\n", + dev->name); + vo->dev = vo->ext_dev = 0; break; + } else { + MSG("[VOUT] dvi dev %s\n", buf); } + + /* if LCD then set fixed timing */ + if (vo->dev == lcd_get_dev()) + vout_info_set_fixed_timing( + info->num, &p_lcd->vmode); } } while (1); } - - DBG_MSG("DVI ext dev : %s\n", - (vout->dev) ? vout->dev->name : "NO"); - } - info->option = (parm[2] & WMT_DISP_FB_INTERLACE) ? - VPP_OPT_INTERLACE : 0; - break; - case VOUT_HDMI: - info->option = (parm[2] & WMT_DISP_FB_INTERLACE) ? - VPP_OPT_INTERLACE : 0; -#if 0 /* use old uboot param and wait next chip */ - g_vpp.hdmi_disable = - (parm[2] & WMT_DISP_FB_HDMI_DISABLE) ? 1 : 0; - - g_vpp.hdmi_sp_mode = - (parm[2] & WMT_DISP_FB_HDMI_SP_MODE) ? 1 : 0; -#endif - break; - default: - break; } - if (ret == 0) - vout_info_add_entry(fb_no, vout); - return ret; -} + for (i = 0; i < VPP_VOUT_NUM; i++) { + vo = vout_get_entry(i); + if (vo == 0) + continue; -int vout_check_display(void) -{ - #define BUF_LEN 100 - char buf[BUF_LEN]; - int varlen = BUF_LEN; - unsigned int parm[32]; - int i, idx; - - if (wmt_getsyspara("wmt.display.fb0", buf, &varlen)) { - /* default for no uboot parameter */ - parm[0] = VOUT_HDMI; - parm[1] = VDO_COL_FMT_ARGB; - parm[2] = VPP_DATAWIDHT_24; - parm[3] = 1280; - parm[4] = 720; - parm[5] = 60; - vout_add_display(0, &parm[0]); - parm[0] = VOUT_DVI; - parm[1] = VDO_COL_FMT_ARGB; - parm[2] = VPP_DATAWIDHT_24; - parm[3] = 1024; - parm[4] = 768; - parm[5] = 60; - vout_add_display(0, &parm[0]); - return 1; - } else { - int fb_no = 0; - int num; - - while (fb_no < VPP_VOUT_INFO_NUM) { - sprintf(buf, "wmt.display.fb%d", fb_no); - varlen = BUF_LEN; - if (wmt_getsyspara(buf, buf, &varlen)) - break; - - DBG_DETAIL("fb%d : %s\n", fb_no, buf); - varlen = vpp_parse_param(buf, - (unsigned int *)parm, 32, 0x1C1C1C1D); - DBG_DETAIL("op 0x%x\n", parm[0]); - num = (varlen - 1) / 7; - for (i = 0; i < num; i++) { - idx = 1 + 8 * i; /* [ + 6 + ] = 8 */ - DBG_DETAIL("%d : %x, %x, %x (%dx%d@%d)\n", i, - parm[idx + 1], parm[idx + 2], - parm[idx + 3], parm[idx + 4], - parm[idx + 5], parm[idx + 6]); - vout_add_display(fb_no, &parm[idx + 1]); - } - - vout_info[fb_no]->multi = - (parm[0] & WMT_DISP_FB_MULTI) ? 1 : 0; - vout_info[fb_no]->alloc_mode = (parm[0] & 0xF); - vout_info[fb_no]->hwc_mode = (parm[0] & 0xF0) >> 4; - if (parm[0] & WMT_DISP_FB_COLFMT) - vout_info[fb_no]->fb.col_fmt = ((parm[0] & - WMT_DISP_FB_COLFMT_MASK) >> 16); - fb_no++; + if ((vo->fix_cap & VOUT_CAP_EXT_DEV) && !(vo->ext_dev)) { + dev = 0; + do { + dev = vout_get_device(dev); + if (dev == 0) + break; + if (vo->fix_cap & BIT(dev->mode)) { + vo->inf = vout_inf_get_entry(dev->mode); + if (dev->init(vo) == 0) { + vo->ext_dev = dev; + vo->dev = dev; + dev->vout = vo; + break; + } + } + } while (1); } + DBG_MSG("vout %d ext dev : %s\n", i, + (vo->dev) ? vo->dev->name : "NO"); } /* [uboot parameter] oem timing : pixclk:option:hsync:hbp:hpixel:hfp:vsync:vbp:vpixel:vfp */ - varlen = BUF_LEN; if (wmt_getsyspara("wmt.display.tmr", buf, &varlen) == 0) { + unsigned int param[10]; struct fb_videomode *p; int xres, yres; - struct fb_videomode vo_oem_vmode; p = &vo_oem_vmode; DBG_MSG("tmr %s\n", buf); - vpp_parse_param(buf, parm, 12, 0); - p->pixclock = parm[0]; - p->vmode = parm[1]; - p->hsync_len = parm[2]; - p->left_margin = parm[3]; - p->xres = parm[4]; - p->right_margin = parm[5]; - p->vsync_len = parm[6]; - p->upper_margin = parm[7]; - p->yres = parm[8]; - p->lower_margin = parm[9]; + vpp_parse_param(buf, param, 10, 0); + p->pixclock = param[0]; + p->vmode = param[1]; + p->hsync_len = param[2]; + p->left_margin = param[3]; + p->xres = param[4]; + p->right_margin = param[5]; + p->vsync_len = param[6]; + p->upper_margin = param[7]; + p->yres = param[8]; + p->lower_margin = param[9]; p->pixclock *= 1000; xres = p->hsync_len + p->left_margin + p->xres + p->right_margin; @@ -1200,9 +1270,6 @@ int vout_check_display(void) p->refresh = vpp_calc_refresh(p->pixclock, xres, yres); if (p->refresh == 59) p->refresh = 60; - p->vmode = (parm[1] & VPP_OPT_INTERLACE) ? FB_VMODE_INTERLACED : 0; - p->sync = (parm[1] & VPP_DVO_SYNC_POLAR_HI) ? FB_SYNC_HOR_HIGH_ACT : 0; - p->sync |= (parm[1] & VPP_DVO_VSYNC_POLAR_HI) ? FB_SYNC_VERT_HIGH_ACT : 0; DBG_MSG("tmr pixclk %d,option 0x%x\n", p->pixclock, p->vmode); DBG_MSG("H sync %d,bp %d,pixel %d,fp %d\n", p->hsync_len, @@ -1211,129 +1278,241 @@ int vout_check_display(void) p->upper_margin, p->yres, p->lower_margin); p->pixclock = KHZ2PICOS(p->pixclock / 1000); vout_info_set_fixed_timing(0, &vo_oem_vmode); - vout_info[0]->fixed_width = parm[10]; - vout_info[0]->fixed_height = parm[11]; - vout_info[0]->resx = p->xres; - vout_info[0]->resy = p->yres; - vout_info[0]->fps = p->refresh; - vout_info[0]->vout[0]->resx = p->xres; - vout_info[0]->vout[0]->resy = p->yres; - vout_info[0]->vout[0]->fps = p->refresh; + vout_info[0].resx = p->xres; + vout_info[0].resy = p->yres; + vout_info[0].fps = p->refresh; } - return 0; + DBG_DETAIL("Leave\n"); } -int vout_init(void) +void vout_check_monitor_resolution(struct vout_init_parm_t *init_parm) { - struct vout_info_t *info; - struct vout_t *vout; - int i, j; - - DBG_DETAIL("Enter\n"); + vout_info_t *p; + vout_t *vo; + int i; + + DBG_DETAIL("Check monitor support\n"); + + if (g_vpp.virtual_display) { + p = &vout_info[0]; + if ((p->resx == 0) || (p->resy == 0)) { + struct fb_videomode vmode; + int edid_option; + + for (i = 0; i < VPP_VOUT_NUM; i++) { + if (vout_chkplug(i) == 0) { + DBG_MSG("no plugin %d\n", i); + continue; + } - for(i = 0; i < VPP_VOUT_INFO_NUM; i++) { - if(vout_info[i] != NULL) { - kfree(vout_info[i]); - vout_info[i] = NULL; + edid_option = vout_get_edid_option(i); + if ((edid_option & EDID_OPT_VALID) == 0) { + DBG_MSG("no EDID %d\n", i); + continue; + } + break; + } + vmode.xres = (i == VPP_VOUT_NUM) ? 1280 : 1920; + vmode.yres = (i == VPP_VOUT_NUM) ? 720 : 1080; + vmode.refresh = 60; + vmode.vmode = 0; + vout_find_match_mode(1, &vmode, 1); + init_parm->def_resx = vmode.xres; + init_parm->def_resy = vmode.yres; + init_parm->def_fps = vmode.refresh; + + for (i = 0; i < VPP_VOUT_INFO_NUM; i++) { + p = &vout_info[i]; + p->resx = init_parm->def_resx; + p->resy = init_parm->def_resy; + p->fps = init_parm->def_fps; + } + DBG_MSG("virtual display %dx%d@%d\n", + vmode.xres, vmode.yres, vmode.refresh); } } - /* register vout & set default */ - vout_register(0, &vout_entry_0); - vout_entry_0.inf = vout_inf_get_entry(VOUT_INF_HDMI); - vout_entry_0.govr = p_govrh; - vout_register(1, &vout_entry_1); - vout_entry_1.inf = vout_inf_get_entry(VOUT_INF_DVI); - vout_entry_1.govr = p_govrh2; + for (i = 0; i < VPP_VOUT_INFO_NUM; i++) { + int support; + int vo_num; - /* check vout info */ - DBG_DETAIL("check display\n"); - vout_check_display(); + p = &vout_info[i]; - /* initial vout */ - DBG_DETAIL("init display\n"); - for (i = 0; i < VPP_VOUT_INFO_NUM; i++) { - info = vout_info[i]; - if (!info) + DBG_MSG("info %d (%d,%d,%d)\n", i, p->resx, p->resy, p->fps); + + if (p->vo_mask == 0) break; - for (j = 0; ; j++) { - vout = info->vout[j]; - if (vout == 0) - break; - if (vout->inf) - vout->inf->init(vout, 0); - } - } + if (p->govr == 0) + continue; + if (p->fixed_vmode) + continue; + if (init_parm->ub_resx) + p->resx = init_parm->ub_resx; + if (init_parm->ub_resy) + p->resy = init_parm->ub_resy; + if (!p->resx) + p->resx = init_parm->def_resx; + if (!p->resy) + p->resy = init_parm->def_resy; + if (!p->fps) + p->fps = init_parm->def_fps; + + DBG_DETAIL("info %d (%d,%d,%d)\n", i, p->resx, p->resy, p->fps); + + support = 0; + for (vo_num = 0; vo_num < VPP_VOUT_NUM; vo_num++) { + int edid_option; + + if ((p->vo_mask & (0x1 << vo_num)) == 0) + continue; + vo = vout_get_entry(vo_num); + if (vo == 0) + continue; +#ifdef CONFIG_WMT_EDID + if (vout_chkplug(vo_num) == 0) { + DBG_MSG("no plugin %d\n", vo_num); + continue; + } - /* check monitor resolution */ - DBG_DETAIL("check resolution\n"); - for (i = 0; i < VPP_VOUT_INFO_NUM; i++) { - struct vout_t *vout_first = 0; - struct vout_t *vout_plug = 0; + vout_change_status(vo, VPP_VOUT_STS_BLANK, 0); + edid_option = vout_get_edid_option(vo_num); + if (edid_option & EDID_OPT_VALID) { + struct fb_videomode *vmode; - info = vout_info[i]; - if (!info) + if (edid_find_support(&vo->edid_info, p->resx, + p->resy, p->fps, &vmode)) { + support = 1; + break; + } else { + if (vout_find_edid_support_mode( + &vo->edid_info, + (unsigned int *)&p->resx, + (unsigned int *)&p->resy, + (unsigned int *)&p->fps, + (edid_option & EDID_OPT_16_9) ? + 1 : 0)) { + support = 1; + break; + } + } + } +#else break; - for (j = 0; ; j++) { - vout = info->vout[j]; - if (vout == 0) - break; +#endif + } - if (vout_first == 0) /* first priority */ - vout_first = vout; - - if (vout_chkplug(vout->num)) { - struct fb_videomode vmode; - - vmode.xres = vout->resx; - vmode.yres = vout->resy; - vmode.refresh = vout->fps; - vmode.vmode = 0; - vout_find_match_mode(i, &vmode, 1); - vout->resx = vmode.xres; - vout->resy = vmode.yres; - vout->fps = vmode.refresh; - if (vout_plug == 0) /* first plugin */ - vout_plug = vout; + if (support == 0) { + if (vout_chkplug(VPP_VOUT_NUM_HDMI)) { + init_parm->def_resx = 1280; + init_parm->def_resy = 720; + init_parm->def_fps = 60; + } else { + char buf[40]; + int varlen = 40; + + if (wmt_getsyspara("wmt.display.tvformat", + buf, &varlen) == 0) { + if (strnicmp(buf, "PAL", 3) == 0) { + init_parm->def_resx = 720; + init_parm->def_resy = 576; + init_parm->def_fps = 50; + } else if (strnicmp(buf,"NTSC",4) == 0) { + init_parm->def_resx = 720; + init_parm->def_resy = 480; + init_parm->def_fps = 60; + } + } else { + init_parm->def_resx = 1024; + init_parm->def_resy = 768; + init_parm->def_fps = 60; + } } - - if (info->multi) - vout_change_status(vout, - VPP_VOUT_STS_ACTIVE, 1); + p->resx = init_parm->def_resx; + p->resy = init_parm->def_resy; + p->fps = init_parm->def_fps; + DBG_MSG("use default(%dx%d@%d)\n", p->resx, + p->resy, p->fps); } + DBG_MSG("fb%d(%dx%d@%d)\n", i, p->resx, p->resy, p->fps); + } + DBG_DETAIL("Leave\n"); +} - vout = (vout_plug) ? vout_plug : vout_first; - if (vout) { - vout_change_status(vout, VPP_VOUT_STS_ACTIVE, 1); - info->resx = vout->resx; - info->resy = vout->resy; - info->fps = vout->fps; +int vout_init(void) +{ + vout_t *vo; + int flag; + int i; + struct vout_init_parm_t init_parm; + + DBG_DETAIL("Enter\n"); + + vout_init_param(&init_parm); + + /* check vout info */ + memset(vout_info, 0, sizeof(vout_info_t) * VPP_VOUT_INFO_NUM); + flag = vout_check_display_info(&init_parm); + + /* probe external device */ + vout_check_ext_device(); + + /* check plug & EDID for resolution */ + if (flag) + vout_check_monitor_resolution(&init_parm); + + if ((init_parm.virtual_display) || (g_vpp.dual_display == 0)) { + int plugin; + + plugin = vout_chkplug(VPP_VOUT_NUM_HDMI); + vout_change_status(vout_get_entry(VPP_VOUT_NUM_HDMI), + VPP_VOUT_STS_BLANK, (plugin) ? 0 : 1); + vout_change_status(vout_get_entry(VPP_VOUT_NUM_DVI), + VPP_VOUT_STS_BLANK, (plugin) ? 1 : 0); + } + + DBG_DETAIL("Set mode\n"); + for (i = 0; i < VPP_VOUT_NUM; i++) { + vo = vout_get_entry(i); + if (vo && (vo->inf)) { + vout_inf_mode_t mode; + + mode = vo->inf->mode; + vo->inf = 0; /* force interface init */ + vout_set_mode(i, mode); + DBG_DETAIL("vout %d : inf %s, ext dev %s,status 0x%x\n", + i, + (vo->inf) ? vout_inf_str[vo->inf->mode] : "No", + (vo->dev) ? vo->dev->name : "No", vo->status); } } -#ifdef DEBUG - /* show display info */ +#ifndef CONFIG_UBOOT + for (i = 0; i < VPP_VOUT_NUM; i++) { + vo = vout_get_entry(i); + if (vo) + vout_set_blank((0x1 << i), + (vo->status & VPP_VOUT_STS_BLANK) ? 1 : 0); + } +#endif + + /* show vout info */ for (i = 0; i < VPP_VOUT_INFO_NUM; i++) { - info = vout_info[i]; - if (!info) + vout_info_t *info; + + info = &vout_info[i]; + if (info->vo_mask == 0) break; - MSG("-----------------------------------------------------\n"); - MSG("fb%d, resx %d,resy %d,fps %d\n", i, - info->resx, info->resy, info->fps); - MSG("resx_vir %d,resy_vir %d,pixclk %d\n", info->resx_virtual, - info->resy_virtual, info->pixclk); - MSG("multi %d,alloc %d,option 0x%x\n", info->multi, - info->alloc_mode, info->option); - - for (j = 0; ; j++) { - vout = info->vout[j]; - if (vout == 0) - break; - vout_print_entry(vout); + if (i == 0) { + if (info->govr) { +#ifdef WMT_FTBLK_GOVRH_CURSOR + p_cursor->mmio = info->govr->mmio; +#endif + } } + MSG("[VOUT] info %d,mask 0x%x,%s,%dx%d@%d\n", i, info->vo_mask, + (info->govr) ? vpp_mod_str[info->govr_mod] : "VIR", + info->resx, info->resy, info->fps); } - MSG("-----------------------------------------------------\n"); -#endif DBG_DETAIL("Leave\n"); return 0; } |