diff options
author | Kevin | 2014-11-15 10:00:36 +0800 |
---|---|---|
committer | Kevin | 2014-11-15 10:00:36 +0800 |
commit | 9d40ac5867b9aefe0722bc1f110b965ff294d30d (patch) | |
tree | de942df665fac4bac0d9cb7ae86910fe937b0c1a /ANDROID_3.4.5/drivers/video/wmt/vout.c | |
parent | 392e8802486cb573b916e746010e141a75f507e6 (diff) | |
download | FOSSEE-netbook-kernel-source-9d40ac5867b9aefe0722bc1f110b965ff294d30d.tar.gz FOSSEE-netbook-kernel-source-9d40ac5867b9aefe0722bc1f110b965ff294d30d.tar.bz2 FOSSEE-netbook-kernel-source-9d40ac5867b9aefe0722bc1f110b965ff294d30d.zip |
add via modify part source code for wm8880 4.4 kitkat
Diffstat (limited to 'ANDROID_3.4.5/drivers/video/wmt/vout.c')
-rwxr-xr-x | ANDROID_3.4.5/drivers/video/wmt/vout.c | 941 |
1 files changed, 941 insertions, 0 deletions
diff --git a/ANDROID_3.4.5/drivers/video/wmt/vout.c b/ANDROID_3.4.5/drivers/video/wmt/vout.c new file mode 100755 index 00000000..9291ac55 --- /dev/null +++ b/ANDROID_3.4.5/drivers/video/wmt/vout.c @@ -0,0 +1,941 @@ +/*++ + * linux/drivers/video/wmt/vout.c + * WonderMedia video post processor (VPP) driver + * + * Copyright c 2014 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 + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * WonderMedia Technologies, Inc. + * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C +--*/ + +#define VOUT_C +#undef DEBUG +/* #define DEBUG */ +/* #define DEBUG_DETAIL */ +/*----------------------- DEPENDENCE -----------------------------------------*/ +#include "vout.h" + +/*----------------------- PRIVATE MACRO --------------------------------------*/ +/* #define VO_XXXX xxxx *//*Example*/ + +/*----------------------- PRIVATE CONSTANTS ----------------------------------*/ +/* #define VO_XXXX 1 *//*Example*/ + +/*----------------------- PRIVATE TYPE --------------------------------------*/ +/* typedef xxxx vo_xxx_t; *//*Example*/ + +/*----------EXPORTED PRIVATE VARIABLES are defined in vout.h -------------*/ +/*----------------------- INTERNAL PRIVATE VARIABLES - -----------------------*/ +/* int vo_xxx; *//*Example*/ +struct vout_t *vout_array[VPP_VOUT_NUM]; +struct vout_inf_t *vout_inf_array[VOUT_INF_MODE_MAX]; +struct vout_dev_t *vout_dev_list; + +/*--------------------- INTERNAL PRIVATE FUNCTIONS ---------------------------*/ +/* void vo_xxx(void); *//*Example*/ + +/*----------------------- Function Body --------------------------------------*/ +/*----------------------- vout API --------------------------------------*/ +void vout_register(int no, struct vout_t *vo) +{ + if (no >= VPP_VOUT_NUM) + return; + + vo->num = no; + vo->govr = (void *) p_govrh; + vo->status = VPP_VOUT_STS_REGISTER; + vo->info = 0; + vout_array[no] = vo; +} + +struct vout_t *vout_get_entry(int no) +{ + if (no >= VPP_VOUT_NUM) + return 0; + return vout_array[no]; +} +EXPORT_SYMBOL(vout_get_entry); + +struct vout_info_t *vout_get_info_entry(int no) +{ + struct vout_info_t *info; + struct vout_t *vout; + int i, j; + + if (no >= VPP_VOUT_NUM) + return 0; + + for (i = 0; i < VPP_VOUT_INFO_NUM; i++) { + info = vout_info[i]; + if (!info) + break; + for (j = 0; j < VPP_VOUT_NUM; j++) { + vout = info->vout[j]; + if (vout == 0) + break; + if (vout->num == no) + return info; + } + } + return 0; +} + +void vout_change_status(struct vout_t *vo, int mask, int sts) +{ + DBG_DETAIL("(0x%x,%d)\n", mask, sts); + if (sts) + vo->status |= mask; + else + vo->status &= ~mask; + + switch (mask) { + case VPP_VOUT_STS_PLUGIN: + if (sts == 0) { + vo->status &= ~(VPP_VOUT_STS_EDID + + VPP_VOUT_STS_CONTENT_PROTECT); + vo->edid_info.option = 0; +#ifdef __KERNEL__ + vpp_netlink_notify_cp(0); +#endif + } + break; + default: + break; + } +} + +int vout_query_inf_support(int no, enum vout_inf_mode_t mode) +{ + struct 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; +} + +/*----------------------- vout interface API --------------------------------*/ +int vout_inf_register(enum vout_inf_mode_t mode, struct vout_inf_t *inf) +{ + if (mode >= VOUT_INF_MODE_MAX) { + DBG_ERR("vout interface mode invalid %d\n", mode); + return -1; + } + + if (vout_inf_array[mode]) + DBG_ERR("vout interface register again %d\n", mode); + + vout_inf_array[mode] = inf; + return 0; +} /* End of vout_register */ + +struct vout_inf_t *vout_inf_get_entry(enum vout_inf_mode_t mode) +{ + if (mode >= VOUT_INF_MODE_MAX) { + DBG_ERR("vout interface mode invalid %d\n", mode); + return 0; + } + return vout_inf_array[mode]; +} + +/*----------------------- vout device API -----------------------------------*/ +int vout_device_register(struct vout_dev_t *ops) +{ + struct vout_dev_t *list; + + if (vout_dev_list == 0) { + vout_dev_list = ops; + list = ops; + } else { + list = vout_dev_list; + while (list->next != 0) + list = list->next; + list->next = ops; + } + ops->next = 0; + return 0; +} + +struct vout_dev_t *vout_get_device(struct vout_dev_t *ops) +{ + if (ops == 0) + return vout_dev_list; + return ops->next; +} + +struct vout_t *vout_get_entry_adapter(enum 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: + no = VPP_VOUT_NUM_HDMI; + break; + case VOUT_LVDS: + no = VPP_VOUT_NUM_LVDS; + break; + default: + no = VPP_VOUT_NUM; + break; + } + return vout_get_entry(no); +} + +struct vout_inf_t *vout_get_inf_entry_adapter(enum vout_mode_t mode) +{ + int no; + + switch (mode) { + case VOUT_SD_DIGITAL: + case VOUT_SD_ANALOG: + case VOUT_DVI: + case VOUT_LCD: + case VOUT_DVO2HDMI: + case VOUT_VGA: + no = VOUT_INF_DVI; + break; + case VOUT_HDMI: + no = VOUT_INF_HDMI; + break; + case VOUT_LVDS: + no = VOUT_INF_LVDS; + break; + default: + no = VOUT_INF_MODE_MAX; + return 0; + } + return vout_inf_get_entry(no); +} + +enum vpp_vout_s vout_get_mode_adapter(struct vout_t *vout) +{ + enum vpp_vout_s mode; + + switch (vout->inf->mode) { + case VOUT_INF_DVI: + mode = VPP_VOUT_DVI; + if (vout->dev && (strcmp("LCD", vout->dev->name) == 0)) + mode = VPP_VOUT_LCD; + break; + case VOUT_INF_HDMI: + mode = VPP_VOUT_HDMI; + break; + case VOUT_INF_LVDS: + mode = VPP_VOUT_LVDS; + break; + default: + mode = VPP_VOUT_NONE; + break; + } + return mode; +} + +int vout_info_add_entry(int no, struct vout_t *vo) +{ + struct vout_info_t *info; + int i = 0; + + if ((vo == 0) || (vo->info)) + return 0; + + info = vout_info[no]; + info->num = no; + if (vo->num < VPP_VOUT_NUM) { /* not virtual vout */ + for (i = 0; i < VPP_VOUT_NUM; i++) { + if (info->vout[i] == 0) { + info->vout[i] = vo; + vo->info = info; + break; + } else { + if (info->vout[i] == vo) /* exist */ + break; + } + } + } + + if (i == 0) { /* new */ + info->resx = vo->resx; + info->resy = vo->resy; + info->resx_virtual = vpp_calc_align(info->resx, 4); + info->resy_virtual = info->resy; + info->fps = (int) vo->fps; + DBG_MSG("new %dx%d@%d\n", info->resx, info->resy, info->fps); + } + + DBG_MSG("info %d,%dx%d@%d\n", no, info->resx, info->resy, info->fps); + return no; +} + +struct vout_info_t *vout_info_get_entry(int no) +{ + if (no >= VPP_VOUT_INFO_NUM) + return 0; + return vout_info[no]; +} + +void vout_info_set_fixed_timing(int no, struct fb_videomode *vmode) +{ + struct vout_info_t *info; + + DBG_MSG("(%d)\n", no); + + info = vout_info_get_entry(no); + if (!info->fixed_vmode) { + info->fixed_vmode = + kmalloc(sizeof(struct fb_videomode), GFP_KERNEL); + if (!info->fixed_vmode) + return; + } + memcpy(info->fixed_vmode, vmode, sizeof(struct fb_videomode)); +} + +struct govrh_mod_t *vout_info_get_govr(int no) +{ + struct vout_info_t *info; + struct govrh_mod_t *govr = 0; + int i; + + info = vout_info[no]; + if (!info) + return 0; + + for (i = 0; i < VPP_VOUT_NUM; i++) { + if (info->vout[i]) { + if (govr == 0) + govr = info->vout[i]->govr; + if (info->vout[i]->status & VPP_VOUT_STS_ACTIVE) { + govr = info->vout[i]->govr; + break; + } + } + } + return govr; +} + +int vout_check_ratio_16_9(unsigned int resx, unsigned int resy) +{ + int val; + + val = (resy) ? ((resx * 10) / resy) : 0; + return (val >= 15) ? 1 : 0; +} + +struct fb_videomode *vout_get_video_mode(int vout_num, + struct fb_videomode *vmode, int option) +{ + int i; + struct fb_videomode *p, *best = NULL; + unsigned int diff = -1, diff_refresh = -1; + int d; + int resx, resy, fps; + unsigned int pixel_clock, diff_pixel_clock = -1; + struct vout_t *vo = 0; + char *edid = 0; + + resx = vmode->xres; + resy = vmode->yres; + fps = vmode->refresh; +#ifdef DEBUG + pixel_clock = (vmode->pixclock) ? PICOS2KHZ(vmode->pixclock) * 1000 : 0; + DBG_MSG("%d,%dx%d@%d,%d,0x%x\n", vout_num, resx, resy, fps, + pixel_clock, option); +#endif + pixel_clock = vmode->pixclock; + + /* EDID detail timing */ + if (option & VOUT_MODE_OPTION_EDID) { + unsigned int opt; + struct fb_videomode *edid_vmode; + + vo = vout_get_entry(vout_num); + if (vo == 0) + return 0; + + edid = vout_get_edid(vout_num); + if (edid_parse(edid, &vo->edid_info)) { + opt = fps | ((option & + VOUT_MODE_OPTION_INTERLACE) ? + EDID_TMR_INTERLACE : 0); + if (edid_find_support(&vo->edid_info, + resx, resy, opt, &edid_vmode)) { + if (edid_vmode) { + DBG_MSG("EDID detail timing\n"); + return edid_vmode; + } + } + } + } + + /* video mode table */ + for (i = 0; ; i++) { + p = (struct fb_videomode *) &vpp_videomode[i]; + if (p->pixclock == 0) + break; + + if (option & VOUT_MODE_OPTION_LESS) { + if ((p->xres > resx) || (p->yres > resy)) + continue; + } + if (option & VOUT_MODE_OPTION_GREATER) { + if ((p->xres < resx) || (p->yres < resy)) + continue; + } + if (option & VOUT_MODE_OPTION_INTERLACE) { + if (!(p->vmode & FB_VMODE_INTERLACED)) + continue; + } + if (option & VOUT_MODE_OPTION_PROGRESS) { + if ((p->vmode & FB_VMODE_INTERLACED)) + continue; + } + if ((option & VOUT_MODE_OPTION_EDID) && + (edid_parse(edid, &vo->edid_info))) { + unsigned int opt; + struct fb_videomode *edid_vmode; + + opt = p->refresh | ((option & + VOUT_MODE_OPTION_INTERLACE) ? + EDID_TMR_INTERLACE : 0); + if (edid_find_support(&vo->edid_info, + p->xres, p->yres, opt, &edid_vmode)) { + if (edid_vmode) + p = edid_vmode; + } else { + continue; + } + } + d = abs(p->xres - resx) + abs(p->yres - resy); + d = abs(d); + if (diff > d) { + diff = d; + diff_refresh = abs(p->refresh - fps); + diff_pixel_clock = abs(p->pixclock - pixel_clock); + best = p; + } else if (diff == d) { + d = abs(p->refresh - fps); + if (diff_refresh > d) { + diff_refresh = d; + diff_pixel_clock = + abs(p->pixclock - pixel_clock); + best = p; + } else if (diff_refresh == d) { + d = abs(p->pixclock - pixel_clock); + if (diff_pixel_clock > d) { + diff_pixel_clock = d; + best = p; + } + } + } + } + if (best) + DBG_MSG("%dx%d@%d\n", best->xres, best->yres, best->refresh); + return best; +} + +int vout_get_width_height(int fbnum, int *width, int *height) +{ + struct vout_info_t *info; + int i; + + info = vout_info_get_entry(fbnum); + *width = 0; + *height = 0; + for (i = 0; i < VPP_VOUT_NUM; i++) { + struct vout_t *vout; + + vout = info->vout[i]; + if (vout) { + if ((vout->inf->mode == VOUT_INF_DVI) && p_lcd) { + if (info->fixed_width != 0 && info->fixed_height != 0) { + *width = info->fixed_width; + *height = info->fixed_height; + } else { + *width = p_lcd->width; + *height = p_lcd->height; + } + break; + } + if (vout_chkplug(vout->num)) { + if (vout_get_edid_option(vout->num) + & EDID_OPT_VALID) { + *width = vout->edid_info.width; + *height = vout->edid_info.height; + break; + } + } + } + } + return 0; +} + +#ifndef CONFIG_VPOST +int vout_find_match_mode(int fbnum, + struct fb_videomode *vmode, int match) +{ + struct vout_info_t *info; + struct fb_videomode *p; + int no = VPP_VOUT_NUM; + unsigned int option; + int i; + + DBG_DETAIL("(%d)\n", fbnum); + + info = vout_info_get_entry(fbnum); + if (vmode->refresh == 59) + vmode->refresh = 60; + + /* fixed timing */ + if (info->fixed_vmode) { + if (info->fixed_vmode->xres != vmode->xres) + return -1; + if (info->fixed_vmode->yres != vmode->yres) + return -1; + if (info->fixed_vmode->refresh != vmode->refresh) + return -1; + p = info->fixed_vmode; + goto label_find_match; + } + for (i = 0; i < VPP_VOUT_NUM; i++) { + if (info->vout[i]) { + int vout_no = info->vout[i]->num; + + if (no == VPP_VOUT_NUM) + no = vout_no; /* get first vo */ + if (vout_chkplug(vout_no)) { + no = vout_no; + break; + } + } + } + /* resolution match and interlace match */ + option = VOUT_MODE_OPTION_GREATER + VOUT_MODE_OPTION_LESS; + option |= (no == VPP_VOUT_NUM) ? 0 : VOUT_MODE_OPTION_EDID; + option |= (vmode->vmode & FB_VMODE_INTERLACED) ? + VOUT_MODE_OPTION_INTERLACE : VOUT_MODE_OPTION_PROGRESS; + p = vout_get_video_mode(no, vmode, option); + if (p) + goto label_find_match; + + /* resolution match but interlace not match */ + option = VOUT_MODE_OPTION_GREATER + VOUT_MODE_OPTION_LESS; + option |= (no == VPP_VOUT_NUM) ? 0 : VOUT_MODE_OPTION_EDID; + option |= (vmode->vmode & FB_VMODE_INTERLACED) ? + VOUT_MODE_OPTION_PROGRESS : VOUT_MODE_OPTION_INTERLACE; + p = vout_get_video_mode(no, vmode, option); + if (p) + goto label_find_match; + +/* if( !match ){ */ + /* resolution less best mode */ + option = VOUT_MODE_OPTION_LESS; + option |= (no == VPP_VOUT_NUM) ? 0 : VOUT_MODE_OPTION_EDID; + p = vout_get_video_mode(no, vmode, option); + if (p) + goto label_find_match; +/* } */ + DBG_ERR("no support mode\n"); + return -1; +label_find_match: + *vmode = *p; +#ifdef CONFIG_UBOOT + info->p_vmode = p; +#endif + return 0; +} +#endif + +int vout_find_edid_support_mode( + struct edid_info_t *info, + unsigned int *resx, + unsigned int *resy, + unsigned int *fps, + int r_16_9 +) +{ + /* check the EDID to find one that not large and same ratio mode*/ +#ifdef CONFIG_WMT_EDID + int i, cnt; + struct fb_videomode *p; + unsigned int w, h, f, option; + + if ((*resx == 720) && (*resy == 480) && (*fps == 50)) + *fps = 60; + + for (i = 0, cnt = 0; ; i++) { + if (vpp_videomode[i].pixclock == 0) + break; + cnt++; + } + + for (i = cnt - 1; i >= 0; i--) { + p = (struct fb_videomode *) &vpp_videomode[i]; + h = p->yres; + if (h > *resy) + continue; + + w = p->xres; + if (w > *resx) + continue; + + f = p->refresh; + if (f > *fps) + continue; + + if (r_16_9 != vout_check_ratio_16_9(w, h)) + continue; + + option = f & EDID_TMR_FREQ; + option |= (p->vmode & FB_VMODE_INTERLACED) ? + EDID_TMR_INTERLACE : 0; + + if (edid_find_support(info, w, h, option, &p)) { + *resx = w; + *resy = h; + *fps = f; + DBG_MSG("(%dx%d@%d)\n", w, h, f); + return 1; + } + } +#endif + return 0; +} + +/*----------------------- vout control API ----------------------------------*/ +void vout_set_framebuffer(struct vout_info_t *info, vdo_framebuf_t *fb) +{ + int i; + struct vout_t *vo; + + if (!info) + return; + + for (i = 0; i < VPP_VOUT_NUM; i++) { + vo = info->vout[i]; + if (vo == 0) + break; + if (vo->govr) + vo->govr->fb_p->set_framebuf(fb); + } +} + +int vout_set_blank(int no, enum vout_blank_t arg) +{ + struct vout_t *vo; + + DBG_DETAIL("(%d,%d)\n", no, arg); + + vo = vout_get_entry(no); + if (vo && (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 (vo->govr) + govrh_set_MIF_enable(vo->govr, (arg) ? 0 : 1); + } + return 0; +} + +int vout_set_mode(int no, enum vout_inf_mode_t mode) +{ + struct 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->inf->init(vo, 0); + vout_change_status(vo, VPP_VOUT_STS_ACTIVE, 1); + return 0; +} + +int vout_config(struct vout_info_t *info, struct fb_videomode *vmode, + vdo_framebuf_t *fb) +{ + struct vout_t *vo; + int i; + + DBG_DETAIL("\n"); + + if (!vmode && !fb) + return 0; + + if (vmode) { + /* option for interface & device config */ + info->resx = vmode->xres; + info->resy = vmode->yres; + info->fps = (vmode->refresh == 59) ? 60 : vmode->refresh; + info->option = (vmode->vmode & FB_VMODE_INTERLACED) ? + VPP_OPT_INTERLACE : 0; + info->option |= (vmode->sync & FB_SYNC_HOR_HIGH_ACT) ? + VPP_DVO_SYNC_POLAR_HI : 0; + info->option |= (vmode->sync & FB_SYNC_VERT_HIGH_ACT) ? + VPP_DVO_VSYNC_POLAR_HI : 0; + } + + for (i = 0; i < VPP_VOUT_NUM; i++) { + vo = info->vout[i]; + if (vo == 0) + break; + + if (vo->govr == 0) + continue; + + if (vmode) { + govrh_set_videomode(vo->govr, vmode); + + if (vo->inf) { + vo->inf->config(vo, (int)info); + if (vo->dev) + vo->dev->config(info); + } + } + + if (fb) + govrh_set_framebuffer(vo->govr, fb); + } + return 0; +} + +int vout_chkplug(int no) +{ + struct vout_t *vo; + struct vout_inf_t *inf; + int ret = 0; + + DBG_DETAIL("(%d)\n", no); + + vo = vout_get_entry(no); + if (vo == 0) + return 0; + + if (vo->inf == 0) + return 0; + + inf = vout_inf_get_entry(vo->inf->mode); + if (inf == 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_inf_chkplug(int no, enum vout_inf_mode_t mode) +{ + struct vout_t *vo; + struct 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); + inf = vout_inf_get_entry(mode); + if (inf) { + if (inf->chkplug) + plugin = inf->chkplug(vo, 0); + } + return plugin; +} + +char *vout_get_edid(int no) +{ + struct vout_t *vo; + int ret; + + DBG_DETAIL("(%d)\n", no); + + if (edid_disable) + return 0; + vo = vout_get_entry(no); + if (vo == 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) { + vo->edid = 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) { + DBG_DETAIL("edid read\n"); + vout_change_status(vo, VPP_VOUT_STS_EDID, 1); + return vo->edid; + } else { + DBG_MSG("read edid fail\n"); + } + +#ifdef CONFIG_VOUT_EDID_ALLOC + kfree(vo->edid); + vo->edid = 0; +#endif + return 0; +} + +int vout_get_edid_option(int no) +{ + struct vout_t *vo; + + DBG_DETAIL("(%d)\n", no); + + vo = vout_get_entry(no); + if (vo == 0) + return 0; + + if (vo->edid_info.option) + return vo->edid_info.option; + + if (vout_get_edid(no) == 0) { + if (no == VPP_VOUT_NUM_HDMI) { /* HDMI wo EDID still can work */ + vo->edid_info.option = (EDID_OPT_HDMI + EDID_OPT_AUDIO); + return vo->edid_info.option; + } + return 0; + } + + edid_parse(vo->edid, &vo->edid_info); + return vo->edid_info.option; +} + +unsigned int vout_get_mask(struct vout_info_t *vo_info) +{ + unsigned int mask; + int i; + + if (g_vpp.virtual_display) { + if (vo_info->num == 0) + return 0; + return VPP_VOUT_ALL; + } + + mask = 0; + for (i = 0; i <= VPP_VOUT_NUM; i++) { + if (vo_info->vout[i] == 0) + break; + mask |= (0x1 << vo_info->vout[i]->num); + } + return mask; +} + +int vout_check_plugin(int clr_sts) +{ + struct vout_t *vo; + int i; + int plugin = 0; + + for (i = 0; i <= VPP_VOUT_NUM; i++) { + vo = vout_get_entry(i); + if (vo == 0) + continue; + if (vo->inf == 0) + continue; + + if (vo->dev) { + if (!(vo->dev->capability & VOUT_DEV_CAP_FIX_PLUG)) { + if (vout_chkplug(i)) { + plugin = 1; + if (clr_sts) + vout_change_status(vo, + VPP_VOUT_STS_PLUGIN, 0); + DBG_MSG("[VPP] ext dev plugin\n"); + } + } + } else { + if (!(vo->inf->capability & VOUT_INF_CAP_FIX_PLUG)) { + if (vout_chkplug(i)) { + plugin = 1; + if (clr_sts) + vout_change_status(vo, + VPP_VOUT_STS_PLUGIN, 0); + DBG_MSG("[VPP] inf dev plugin\n"); + } + } + } + } + return plugin; +} + +enum vout_tvformat_t vout_get_tvformat(void) +{ + char buf[40] = {0}; + int varlen = 40; + enum vout_tvformat_t s_tvformat = TV_MAX; + + if (wmt_getsyspara("wmt.display.tvformat", buf, &varlen) == 0) { + if (!strnicmp(buf, "PAL", 3)) + s_tvformat = TV_PAL; + else if (!strnicmp(buf, "NTSC", 4)) + s_tvformat = TV_NTSC; + else + s_tvformat = TV_UNDEFINED; + } else + s_tvformat = TV_UNDEFINED; + + return s_tvformat; +} + +/*--------------------End of Function Body -----------------------------------*/ +#undef VOUT_C |