char *vout_get_edid(int no) { vout_t *vo; int ret; DBG_DETAIL("(%d)\n",no); if( (vo = vout_get_entry(no)) == 0 ){ return 0; } if( vo->status & VPP_VOUT_STS_EDID ){ DBG_MSG("edid exist\n"); return vo->edid; } vout_change_status(vo,VPP_VOUT_STS_EDID,0); #ifdef CONFIG_VOUT_EDID_ALLOC if( vo->edid == 0 ){ // DBG_MSG("edid buf alloc\n"); vo->edid = (char *) kmalloc(128*EDID_BLOCK_MAX,GFP_KERNEL); if( !vo->edid ){ DBG_ERR("edid buf alloc\n"); return 0; } } #endif ret = 1; if( vo->dev && vo->dev->get_edid ){ ret = vo->dev->get_edid(vo->edid); } else { if( vo->inf->get_edid ){ ret = vo->inf->get_edid(vo,(int)vo->edid); } } if( ret == 0 ){ vout_info_t *info; DBG_DETAIL("edid read\n"); vout_change_status(vo,VPP_VOUT_STS_EDID,1); if( (info = vout_get_info_entry((g_vpp.virtual_display)?1:no)) ){ info->force_config = 1; } return vo->edid; } else { DBG_ERR("read edid fail\n"); } #ifdef CONFIG_VOUT_EDID_ALLOC if( vo->edid ){ kfree(vo->edid); vo->edid = 0; } #endif return 0; }
int vout_chkplug(int no) { vout_t *vo; vout_inf_t *inf; int ret = 0; DBG_DETAIL("(%d)\n",no); if( (vo = vout_get_entry(no)) == 0 ){ return 0; } if( vo->inf == 0 ){ return 0; } if( (inf = vout_inf_get_entry(vo->inf->mode)) == 0 ){ return 0; } if( vo->dev && vo->dev->check_plugin ){ ret = vo->dev->check_plugin(0); } else { ret = inf->chkplug(vo,0); } vout_change_status(vo,VPP_VOUT_STS_PLUGIN,ret); return ret; }
int vout_set_mode(int no,vout_inf_mode_t mode) { vout_t *vo; DBG_DETAIL("(%d,%d)\n",no,mode); if( vout_query_inf_support(no,mode)==0 ){ DBG_ERR("not support this interface(%d,%d)\n",no,mode); return -1; } vo = vout_get_entry(no); if( vo->inf ){ if( vo->inf->mode == mode ) return 0; vo->inf->uninit(vo,0); vout_change_status(vo,VPP_VOUT_STS_ACTIVE,0); if( vo->dev ) vo->dev->set_power_down(1); } vo->inf = vout_inf_get_entry(mode); vo->dev = ( vo->ext_dev && (vo->ext_dev->mode == mode) )? vo->ext_dev:0; vo->inf->init(vo,0); vout_change_status(vo,VPP_VOUT_STS_ACTIVE,1); return 0; }
static void vo_do_plug ( void *ptr /*!<; // work input data */ ) #endif { vout_t *vo; int plugin; if( vo_plug_func == 0 ) return; 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); vout_change_status(vo,VPP_VOUT_STS_PLUGIN,plugin); vo_plug_flag = 0; DBG_DETAIL("vo_do_plug %d\n",plugin); vppif_reg32_write(GPIO_BASE_ADDR+0x300+VPP_VOINT_NO,0x80,7,1); // GPIO irq enable vppif_reg32_write(GPIO_BASE_ADDR+0x80,0x1<<VPP_VOINT_NO,VPP_VOINT_NO,0x0); // GPIO input mode #ifdef __KERNEL__ vpp_netlink_notify(USER_PID,DEVICE_PLUG_IN,plugin); vpp_netlink_notify(WP_PID,DEVICE_PLUG_IN,plugin); #endif return; }
int vout_set_blank(unsigned int mask,vout_blank_t arg) { int i; vout_t *vo; DBG_DETAIL("(0x%x,%d)\n",mask,arg); if( mask == 0 ) return 0; for(i=0;i<VPP_VOUT_NUM;i++){ if( (mask & (0x1 << i)) == 0 ) continue; if( (vo = vout_get_entry(i)) ){ if( vo->inf ){ vout_change_status(vo,VPP_VOUT_STS_BLANK,arg); vo->inf->blank(vo,arg); if( vo->dev && vo->dev->set_power_down ){ vo->dev->set_power_down((arg==VOUT_BLANK_POWERDOWN)?1:0); } } } } if(1){ int govr_enable_mask,govr_mask; govrh_mod_t *govr; govr_enable_mask = 0; for(i=0;i<VPP_VOUT_NUM;i++){ if( (vo = vout_get_entry(i)) ){ if( vo->govr ){ govr_mask = (vo->govr->mod == VPP_MOD_GOVRH)? 0x1:0x2; govr_enable_mask |= (vo->status & VPP_VOUT_STS_BLANK)? 0:govr_mask; } } } for(i=0;i<VPP_VOUT_INFO_NUM;i++){ govr = (i==0)? p_govrh:p_govrh2; govr_mask = 0x1 << i; govrh_set_MIF_enable(govr,(govr_enable_mask & govr_mask)? 1:0); } } return 0; }
int vout_config(unsigned int mask,vout_info_t *info) { vout_t *vo; vpp_timing_t *p_timing; int no = VPP_VOUT_NUM; int i; unsigned int govr_mask = 0; DBG_DETAIL("(0x%x)\n",mask); if( mask == 0 ) return 0; for(i=0;i<VPP_VOUT_NUM;i++){ if( (mask & (0x1 << i)) == 0 ) continue; if( no == VPP_VOUT_NUM ){ no = i; // get first vo } if( vout_chkplug(i) ){ no = i; break; } } if( (p_timing = vout_find_video_mode(no,info)) == 0 ){ return -1; } info->option = p_timing->option; for(i=0;i<VPP_VOUT_NUM;i++){ if( (mask & (0x1 << i)) == 0 ) continue; if( (vo = vout_get_entry(i)) == 0 ) continue; if( vo->govr == 0 ) continue; if( (govr_mask & (0x1 << vo->govr->mod)) == 0 ){ govrh_set_timing(vo->govr,p_timing); govr_mask |= (0x1 << vo->govr->mod); } if( vo->inf ){ vo->inf->config(vo,(int)info); if( vo->dev ) vo->dev->config(info); } } return 0; }
int vout_query_inf_support(int no,vout_inf_mode_t mode) { vout_t *vo; if( no >= VPP_VOUT_NUM ) return 0; if( mode >= VOUT_INF_MODE_MAX ){ return 0; } vo = vout_get_entry(no); return (vo->fix_cap & BIT(mode))? 1:0; }
int vout_inf_chkplug(int no,vout_inf_mode_t mode) { vout_t *vo; vout_inf_t *inf; int plugin = 0; DBG_MSG("(%d,%d)\n",no,mode); if( vout_query_inf_support(no,mode) == 0 ) return 0; vo = vout_get_entry(no); if( (inf = vout_inf_get_entry(mode)) ){ if( inf->chkplug ){ plugin = inf->chkplug(vo,0); } } return plugin; }
void vout_set_tg_enable(unsigned int mask,int enable) { int i; vout_t *vo; if( mask == 0 ) return; for(i=0;i<VPP_VOUT_NUM;i++){ if( (mask & (0x1 << i)) == 0 ) continue; if( (vo = vout_get_entry(i)) ){ if( vo->govr ){ govrh_set_tg_enable(vo->govr,enable); } } } }
/*----------------------- vout control API --------------------------------------*/ void vout_set_framebuffer(unsigned int mask,vdo_framebuf_t *fb) { int i; vout_t *vo; if( mask == 0 ) return; for(i=0;i<VPP_VOUT_NUM;i++){ if( (mask & (0x1 << i)) == 0 ) continue; if( (vo = vout_get_entry(i)) ){ if( vo->govr ){ vo->govr->fb_p->set_framebuf(fb); } } } }
int vout_get_edid_option(int no) { vout_t *vo; DBG_DETAIL("(%d)\n",no); if( (vo = vout_get_entry(no)) == 0 ){ return 0; } if( vo->edid_info.option ){ return vo->edid_info.option; } if( vout_get_edid(no) == 0 ){ return 0; } edid_parse(vo->edid,&vo->edid_info); return vo->edid_info.option; }
vout_t *vout_get_entry_adapter(vout_mode_t mode) { int no; switch(mode){ case VOUT_SD_DIGITAL: case VOUT_DVI: case VOUT_LCD: case VOUT_DVO2HDMI: case VOUT_SD_ANALOG: case VOUT_VGA: no = VPP_VOUT_NUM_DVI; break; case VOUT_HDMI: case VOUT_LVDS: no = VPP_VOUT_NUM_HDMI; break; default: no = VPP_VOUT_NUM; break; } return vout_get_entry(no); }
vpp_timing_t *vout_find_video_mode(int no,vout_info_t *info) { vout_t *vo; char *edid = 0; unsigned int vo_option; vpp_timing_t *p_timing = 0; unsigned int opt = 0; int index = 0; vpp_timing_t *edid_timing = 0; if( (vo = vout_get_entry(no)) == 0 ) return 0; // if( vo->num != VPP_VOUT_NUM_HDMI ) // wm3445 simulate dual display { if( info->fixed_timing ){ p_timing = info->fixed_timing; DBG_MSG("%d(fixed timer)\n",no); goto find_video_mode; } } vo_option = vo->option[1]; DBG_MSG("(%d,%dx%d@%d,%d),%s\n",no,info->resx,info->resy,info->pixclk,info->fps,(vo_option & VOUT_OPT_INTERLACE)?"i":"p"); if( vo->status & VPP_VOUT_STS_PLUGIN ){ if( (edid = vout_get_edid(no)) ){ if( edid_parse(edid,&vo->edid_info) == 0 ){ edid = 0; } else { opt = info->fps | ((vo_option & VOUT_OPT_INTERLACE)? EDID_TMR_INTERLACE:0); if( edid_find_support(&vo->edid_info,info->resx,info->resy,opt,&edid_timing) ){ if( edid_timing ){ p_timing = edid_timing; DBG_MSG("Use EDID detail timing\n"); goto find_video_mode; } } } } } do { p_timing = vpp_get_video_mode(info->resx,info->resy,info->pixclk,&index); DBG_MSG("find(%dx%d@%d) -> %dx%d\n",info->resx,info->resy,info->pixclk,p_timing->hpixel,p_timing->vpixel); info->resx = p_timing->hpixel; info->resy = p_timing->vpixel; if( p_timing->option & VPP_OPT_INTERLACE ){ info->resy *= 2; } info->fps = VPP_GET_OPT_FPS(p_timing->option); opt = info->fps | ((vo_option & VOUT_OPT_INTERLACE)? EDID_TMR_INTERLACE:0); if( edid == 0 ) break; DBG_MSG("find edid %dx%d@%d%s\n",info->resx,info->resy,info->fps,(opt & EDID_TMR_INTERLACE)?"i":"p"); if( edid_find_support(&vo->edid_info,info->resx,info->resy,opt,&edid_timing) ){ break; } opt = info->fps | ((vo_option & VOUT_OPT_INTERLACE)? 0:EDID_TMR_INTERLACE); DBG_MSG("find edid %dx%d@%d%s\n",info->resx,info->resy,info->fps,(opt & EDID_TMR_INTERLACE)?"i":"p"); if( edid_find_support(&vo->edid_info,info->resx,info->resy,opt,&edid_timing) ){ break; } if( (info->resx <= vpp_video_mode_table[0].hpixel) || (index <=1) ){ info->resx = vpp_video_mode_table[0].hpixel; info->resy = vpp_video_mode_table[0].vpixel; break; } do { index--; p_timing = (vpp_timing_t *) &vpp_video_mode_table[index]; if( info->resx == p_timing->hpixel ){ int vpixel; vpixel = p_timing->vpixel; if( p_timing->option & VPP_OPT_INTERLACE ){ vpixel *= 2; index--; } if( info->resy == vpixel ){ continue; } } break; } while(1); info->resx = vpp_video_mode_table[index].hpixel; info->resy = vpp_video_mode_table[index].vpixel; if(vpp_video_mode_table[index].option & VPP_OPT_INTERLACE){ info->resy *= 2; } } while(1); if( edid_timing ){ p_timing = edid_timing; DBG_MSG("Use EDID detail timing\n"); } else { if( opt & EDID_TMR_INTERLACE ) vo_option |= VOUT_OPT_INTERLACE; else vo_option &= ~VOUT_OPT_INTERLACE; p_timing = vpp_get_video_mode_ext(info->resx,info->resy,info->fps,vo_option); } find_video_mode: { int hpixel,vpixel; info->resx = p_timing->hpixel; info->resy = p_timing->vpixel; hpixel = p_timing->hpixel + p_timing->hsync + p_timing->hfp + p_timing->hbp; vpixel = p_timing->vpixel + p_timing->vsync + p_timing->vfp + p_timing->vbp; if( p_timing->option & VPP_OPT_INTERLACE ) { info->resy *= 2; // vpixel *= 2; } info->pixclk = p_timing->pixel_clock; info->fps = info->pixclk / (hpixel * vpixel); info->resx_virtual = vpp_calc_fb_width(g_vpp.mb_colfmt,info->resx); info->resy_virtual = info->resy; } DBG_MSG("Leave (%dx%d@%d,%d)\n",p_timing->hpixel,p_timing->vpixel,p_timing->pixel_clock,info->fps); return p_timing; }