static int framerate_automation_process(int duration) { int policy=0, fr_vsource = 0, fr_target = 0; vmode_t mode_target = VMODE_INIT_NULL; const vinfo_t *pvinfo; printk("vout [%s] duration = %d\n", __FUNCTION__, duration); policy = fr_auto_policy; if( policy == 0 ) { printk("vout frame rate automation disabled!\n"); return 1; } fr_vsource = get_vsource_frame_rate(duration); fr_target = get_target_frame_rate(fr_vsource, policy); pvinfo = tv_get_current_info(); if( (pvinfo->sync_duration_num==fr_target) || (pvinfo->sync_duration_num==(fr_target/100)) ) return 0; mode_target = get_target_vmode(fr_target); framerate_automation_set_mode(mode_target); return 0; }
// return values: // 0: same vmode, need not change // 1: similar vmode, just change pll to add 0.1% clock // 0xff: similar vmode, just change pll to reduce 0.1% clock // 2: different vmode, need change mode static int get_exchange_mode(vmode_t mode_target) { const vinfo_t *pvinfo; vmode_t mode_current = VMODE_INIT_NULL; pvinfo = tv_get_current_info(); mode_current = pvinfo->mode; if ( mode_current == mode_target ) return 0; if ( ((mode_current == VMODE_480P) && (mode_target == VMODE_480P_59HZ)) || ((mode_current == VMODE_480P_59HZ) && (mode_target == VMODE_480P)) || ((mode_current == VMODE_720P) && (mode_target == VMODE_720P_59HZ)) || ((mode_current == VMODE_720P_59HZ) && (mode_target == VMODE_720P)) || ((mode_current == VMODE_1080I) && (mode_target == VMODE_1080I_59HZ)) || ((mode_current == VMODE_1080I_59HZ) && (mode_target == VMODE_1080I)) || ((mode_current == VMODE_1080P) && (mode_target == VMODE_1080P_59HZ)) || ((mode_current == VMODE_1080P_59HZ) && (mode_target == VMODE_1080P)) || ((mode_current == VMODE_1080P_24HZ) && (mode_target == VMODE_1080P_23HZ)) || ((mode_current == VMODE_1080P_23HZ) && (mode_target == VMODE_1080P_24HZ) ) || ((mode_current == VMODE_4K2K_30HZ) && (mode_target == VMODE_4K2K_29HZ)) || ((mode_current == VMODE_4K2K_29HZ) && (mode_target == VMODE_4K2K_30HZ)) || ((mode_current == VMODE_4K2K_24HZ) && (mode_target == VMODE_4K2K_23HZ)) || ((mode_current == VMODE_4K2K_23HZ) && (mode_target == VMODE_4K2K_24HZ)) ) return 0x1; return 2; }
static int get_target_vmode(int framerate_target) { // int is_receiver_supported = 0; const vinfo_t *pvinfo ; vmode_t mode_target = VMODE_INIT_NULL; printk("vout [%s] frame_rate_target = %d\n", __FUNCTION__, framerate_target); pvinfo = tv_get_current_info(); mode_target = pvinfo->mode; if ( (framerate_target == 2397) || (framerate_target == 2997) || (framerate_target == 5994) ) { switch ( mode_target ) { case VMODE_480P: mode_target = VMODE_480P_59HZ; break; case VMODE_720P: mode_target = VMODE_720P_59HZ; break; case VMODE_1080I: mode_target = VMODE_1080I_59HZ; break; case VMODE_1080P_24HZ: mode_target = VMODE_1080P_23HZ; break; case VMODE_1080P: mode_target = VMODE_1080P_59HZ; break; case VMODE_4K2K_24HZ: mode_target = VMODE_4K2K_23HZ; break; case VMODE_4K2K_30HZ: mode_target = VMODE_4K2K_29HZ; break; default: break; } } /* is_receiver_supported = hdmitx_is_vmode_supported(get_name_from_vmode(mode_target)); switch ( is_receiver_supported ) { case 0: // not supported in edid mode_target = pvinfo->mode; break; case 1: // supported in edid break; case 2: // no edid mode_target = pvinfo->mode; break; default: break; } */ return mode_target; }
static int get_target_frame_rate(int framerate_vsource, int policy) { const vinfo_t *pvinfo ; int framerate_target = 0; pvinfo = tv_get_current_info(); switch ( policy ) { case 0: // not change break; case 1: // change to the frame rate of video source if ( (framerate_vsource == 2397) || (framerate_vsource == 2997) || (framerate_vsource == 5994) ) { switch (pvinfo->sync_duration_num) { case 24: framerate_target=2397; break; case 30: framerate_target=2997; break; case 60: framerate_target=5994; break; default: framerate_target = ( pvinfo->sync_duration_num > 100 ? pvinfo->sync_duration_num : pvinfo->sync_duration_num*100 ); break; } } else framerate_target = framerate_vsource; break; case 2: // change to the frame rate of video source, but use 59.94 for 23.97/29.97 if ( (framerate_vsource == 2397) || (framerate_vsource == 2997) ) framerate_target = 5994; else framerate_target = framerate_vsource; break; default: break; } return framerate_target; }
static int tv_set_vframe_rate_hint(int duration) { #ifdef CONFIG_AML_VOUT_FRAMERATE_AUTOMATION const struct vinfo_s *pvinfo; vout_log_info("vout [%s] duration = %d, policy = %d!\n", __func__, duration, fr_auto_policy); pvinfo = tv_get_current_info(); if (!pvinfo) { vout_log_err("don't get vinfo!\n"); return 1; } /*if in CVBS mode, don't do frame rate automation*/ if (!want_hdmi_mode(pvinfo->mode)) { vout_log_info("not in valid HDMI mode!\n"); return 1; } framerate_automation_process(duration); #endif return 0; }
static int framerate_automation_set_mode( enum vmode_e mode_target, enum hint_mode_e hint_mode) { const struct vinfo_s *pvinfo; enum vmode_e mode_current = VMODE_INIT_NULL; if ((mode_target&VMODE_MODE_BIT_MASK) > VMODE_MAX) return 1; pvinfo = tv_get_current_info(); if (!pvinfo) { vout_log_err("don't get tv_info, mode is %d\n", mode_target); return 1; } mode_current = pvinfo->mode; if (!want_hdmi_mode(mode_current)) { vout_log_info("not in valid HDMI mode!\n"); return 1; } if (mode_current == mode_target) { if (fine_tune_mode == KEEP_HPLL) return 0; } vout_log_info("vout [%s] mode_target = %d\n", __func__, mode_target); if (START_HINT == hint_mode) { info->vinfo = update_tv_info_duration(mode_target, fine_tune_mode); } else if (END_HINT == hint_mode) { /*recovery tv_info array, e.g. 1080p59hz->1080p50hz or 1080p59hz->1080p60hz, recovery 1080p60hz vinfo*/ update_tv_info_duration(fps_target_mode, fine_tune_mode); /*get current vinfo, maybe change is 1080p->1080p50, then get info->vinfo for 1080p50hz*/ info->vinfo = get_tv_info(mode_target & VMODE_MODE_BIT_MASK); } update_vmode_status(get_name_from_vmode(mode_target)); vout_notifier_call_chain(VOUT_EVENT_MODE_CHANGE, &mode_target); return 0; }
// just to fine tune the 0.1% clock static int clock_fine_tune(void) { const vinfo_t *pvinfo ; pvinfo = tv_get_current_info(); #if (MESON_CPU_TYPE == MESON_CPU_TYPE_MESON8) || (MESON_CPU_TYPE == MESON_CPU_TYPE_MESON8B) switch ( pvinfo->mode ) { case VMODE_720P_59HZ: case VMODE_1080I_59HZ: case VMODE_1080P_23HZ: case VMODE_1080P_59HZ: if ( MESON_CPU_TYPE == MESON_CPU_TYPE_MESON8B ) aml_write_reg32(P_HHI_VID_PLL_CNTL2, 0x69c84cf8); else aml_write_reg32(P_HHI_VID_PLL_CNTL2, 0x69c84d04); break; case VMODE_4K2K_23HZ: case VMODE_4K2K_29HZ: if ( MESON_CPU_TYPE == MESON_CPU_TYPE_MESON8B ) aml_write_reg32(P_HHI_VID_PLL_CNTL2, 0x69d84cf8); else if (IS_MESON_M8_CPU && hdmitx_is_special_tv_process())//SAMSUNG future TV, M8, in 4K2K mode aml_write_reg32(P_HHI_VID_PLL_CNTL2, 0x59c84d04); else aml_write_reg32(P_HHI_VID_PLL_CNTL2, 0x69d84d04); break; case VMODE_720P: case VMODE_1080I: case VMODE_1080P: case VMODE_1080P_24HZ: aml_write_reg32(P_HHI_VID_PLL_CNTL2, 0x69c84e00); break; case VMODE_4K2K_24HZ: case VMODE_4K2K_30HZ: if (IS_MESON_M8_CPU && hdmitx_is_special_tv_process())//SAMSUNG future TV, M8, in 4K2K mode aml_write_reg32(P_HHI_VID_PLL_CNTL2, 0x59c84e00); else aml_write_reg32(P_HHI_VID_PLL_CNTL2, 0x69c84e00); break; case VMODE_480P_59HZ: if ( (MESON_CPU_TYPE == MESON_CPU_TYPE_MESON8B) || (IS_MESON_M8M2_CPU) ) { aml_write_reg32(P_HHI_VID_PLL_CNTL2, 0x69c84f48); aml_write_reg32(P_HHI_VID_PLL_CNTL, 0x400d042c); } else { aml_write_reg32(P_HHI_VID_PLL_CNTL2, 0x69c8cf48); aml_write_reg32(P_HHI_VID_PLL_CNTL, 0x4008042c); } break; case VMODE_480P: if ( (MESON_CPU_TYPE == MESON_CPU_TYPE_MESON8B) || (IS_MESON_M8M2_CPU) ) { aml_write_reg32(P_HHI_VID_PLL_CNTL2, 0x69c84000); aml_write_reg32(P_HHI_VID_PLL_CNTL, 0x400d042d); } else { aml_write_reg32(P_HHI_VID_PLL_CNTL2, 0x69c88000); aml_write_reg32(P_HHI_VID_PLL_CNTL, 0x4008042d); } break; default: break; } #endif return 0; }
static enum vmode_e get_target_vmode(int fr_vsource) { int is_receiver_supported = 0; const struct vinfo_s *pvinfo; enum vmode_e mode_target = VMODE_INIT_NULL; int i = 0, count = 0; struct fps_mode_conv *s = NULL; vout_log_info("fr_vsource = %d\n", fr_vsource); pvinfo = tv_get_current_info(); if (!pvinfo) { vout_log_info("don't get vinfo!\n"); return mode_target; } mode_target = pvinfo->mode; mode_by_user = mode_target; if (fr_auto_policy == 1) {/* for amlogic */ fine_tune_mode = get_fine_tune_mode(mode_target, fr_vsource); } else if (fr_auto_policy == 2) {/* for jiewei */ switch (fr_vsource) { case 2397: s = fps_mode_map_23; count = ARRAY_SIZE(fps_mode_map_23); break; case 2400: s = fps_mode_map_24; count = ARRAY_SIZE(fps_mode_map_24); break; case 2500: s = fps_mode_map_25; count = ARRAY_SIZE(fps_mode_map_25); break; case 2997: s = fps_mode_map_29; count = ARRAY_SIZE(fps_mode_map_29); break; case 3000: s = fps_mode_map_30; count = ARRAY_SIZE(fps_mode_map_30); break; case 5000: s = fps_mode_map_50; count = ARRAY_SIZE(fps_mode_map_50); break; case 5994: s = fps_mode_map_59; count = ARRAY_SIZE(fps_mode_map_59); break; case 6000: s = fps_mode_map_60; count = ARRAY_SIZE(fps_mode_map_60); break; default: break; } } for (i = 0; i < count; i++) { if (s[i].cur_mode == mode_target) break; } if (i < count) { mode_target = s[i].target_mode; /*for jiewei policy=2, if mode not support in edid, then will use Amloigc policy*/ fine_tune_mode = get_fine_tune_mode(mode_target, fr_vsource); } is_receiver_supported = hdmitx_is_vmode_supported_process( get_name_from_vmode(mode_target)); vout_log_info("mode_target=%d,is_receiver_supported=%d\n", mode_target, is_receiver_supported); switch (is_receiver_supported) { case 0: /* not supported in edid */ case 2: /* no edid */ mode_target = pvinfo->mode; break; case 1:/* supported in edid */ default: break; } fps_target_mode = mode_target; return mode_target; }