From 190492f6a9800dc99aa6ff8372202ec3bda78adc Mon Sep 17 00:00:00 2001 From: Brian Zhu Date: Thu, 12 Sep 2019 03:39:26 +0800 Subject: [PATCH] vpp: improve the csc and dv switch flow and policy [1/1] PD#SWPL-13990 Problem: There are some conflicts between csc and dv module switching. Can not switch to SDR->DV when HDR core is working on SDR->SDR mode. Solution: 1. Improve the switching policy. DV and csc will use same on. 2. add mute operation under dv mode. Verify: Verified on AC211 Change-Id: I4d59328fc34228a0ef5275d22643932c4dfe00b0 Signed-off-by: Brian Zhu --- .../enhancement/amdolby_vision/amdolby_vision.c | 686 ++++++++++++++------- drivers/amlogic/media/enhancement/amvecm/amcsc.c | 556 +++++++++++++---- drivers/amlogic/media/enhancement/amvecm/amcsc.h | 13 + .../amlogic/media/enhancement/amvecm/amcsc_pip.c | 336 ++++++++-- .../amlogic/media/enhancement/amvecm/set_hdr2_v0.c | 8 +- drivers/amlogic/media/video_sink/video.c | 132 +++- .../amlogic/media/amdolbyvision/dolby_vision.h | 13 +- include/linux/amlogic/media/video_sink/video.h | 7 + 8 files changed, 1311 insertions(+), 440 deletions(-) diff --git a/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c b/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c index d4715ff..8307e91 100644 --- a/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c +++ b/drivers/amlogic/media/enhancement/amdolby_vision/amdolby_vision.c @@ -218,13 +218,14 @@ static bool dolby_vision_el_disable; #define FLAG_DISABLE_DOVI_OUT 0x2000 #define FLAG_FORCE_DOVI_LL 0x4000 #define FLAG_FORCE_RGB_OUTPUT 0x8000 -/* #define FLAG_DOVI_LL_RGB_DESIRED 0x8000 */ -#define FLAG_DOVI2HDR10_NOMAPPING 0x100000 -#define FLAG_PRIORITY_GRAPHIC 0x200000 -#define FLAG_DISABLE_LOAD_VSVDB 0x400000 -#define FLAG_DISABLE_CRC 0x800000 -#define FLAG_ENABLE_EL 0x1000000 -#define FLAG_COPY_CORE1S0 0x2000000 +#define FLAG_DOVI2HDR10_NOMAPPING 0x100000 +#define FLAG_PRIORITY_GRAPHIC 0x200000 +#define FLAG_DISABLE_LOAD_VSVDB 0x400000 +#define FLAG_DISABLE_CRC 0x800000 +#define FLAG_ENABLE_EL 0x1000000 +#define FLAG_COPY_CORE1S0 0x2000000 +#define FLAG_MUTE 0x4000000 +#define FLAG_FORCE_HDMI_PKT 0x8000000 #define FLAG_TOGGLE_FRAME 0x80000000 #define FLAG_FRAME_DELAY_MASK 0xf @@ -276,7 +277,6 @@ static bool is_osd_off; static bool force_reset_core2; static int core1_switch; static int core3_switch; -static int video_enable; module_param(vtotal_add, uint, 0664); MODULE_PARM_DESC(vtotal_add, "\n vtotal_add\n"); @@ -2348,6 +2348,13 @@ static int dolby_core2_set( return 0; } +bool is_core3_mute_reg(int index) +{ + return (index == 12) || /* ipt_scale for ipt*/ + (index >= 16 && index <= 17) || /* rgb2yuv scale for yuv */ + (index >= 5 && index <= 9); /* lms2rgb coeff for rgb */ +} + static int dolby_core3_set( uint32_t dm_count, uint32_t md_count, @@ -2520,12 +2527,20 @@ static int dolby_core3_set( count = 26; else count = dm_count; - for (i = 0; i < count; i++) + for (i = 0; i < count; i++) { if (reset || (p_core3_dm_regs[i] != - last_dm[i])) + last_dm[i]) || is_core3_mute_reg(i)) { + if ((dolby_vision_flags & FLAG_MUTE) && + is_core3_mute_reg(i)) + VSYNC_WR_DV_REG( + DOLBY_CORE3_REG_START + 0x6 + i, + 0); + else VSYNC_WR_DV_REG( DOLBY_CORE3_REG_START + 0x6 + i, p_core3_dm_regs[i]); + } + } /* from addr 0x18 */ if (scramble_en) { @@ -2591,34 +2606,49 @@ static int is_graphic_changed(void) force_reset_core2 = true; pr_dolby_dbg("osd on\n"); is_osd_off = false; - ret |= 1; + ret |= 2; } + /* do not need to monitor osd change, */ + /* because scaler is after dolby core2 */ if ((osd_graphic_width != new_osd_graphic_width) || (osd_graphic_height != new_osd_graphic_height)) { - pr_dolby_dbg("osd changed %d %d-%d %d\n", - osd_graphic_width, - osd_graphic_height, - new_osd_graphic_width, - new_osd_graphic_height); - osd_graphic_width = new_osd_graphic_width; - osd_graphic_height = new_osd_graphic_height; - ret |= 2; + if (debug_dolby & 0x10) + pr_dolby_dbg("osd changed %d %d-%d %d\n", + osd_graphic_width, + osd_graphic_height, + new_osd_graphic_width, + new_osd_graphic_height); + /* ignore osd size change */ + /* osd scaler is after dobly core */ + /* osd_graphic_width = new_osd_graphic_width; */ + /* osd_graphic_height = new_osd_graphic_height; */ + /* ret |= 4; */ } return ret; } -static int is_video_turn_on(void) -{ - int ret = 0; - int new_video_enable = get_video_enabled(); +static int cur_mute_type; +static char mute_type_str[4][4] = { + "NON", + "YUV", + "RGB", + "IPT" +}; - if (video_enable != new_video_enable) { - pr_dolby_dbg("video_enable changed %d-%d\n", - video_enable, new_video_enable); - ret = new_video_enable ? 1 : -1; - } - video_enable = new_video_enable; - return ret; +int get_mute_type(void) +{ + if (dolby_vision_ll_policy == DOLBY_VISION_LL_RGB444) + return MUTE_TYPE_RGB; + else if ((dolby_vision_ll_policy == DOLBY_VISION_LL_YUV422) || + (dolby_vision_mode == DOLBY_VISION_OUTPUT_MODE_SDR8) || + (dolby_vision_mode == DOLBY_VISION_OUTPUT_MODE_SDR10) || + (dolby_vision_mode == DOLBY_VISION_OUTPUT_MODE_HDR10)) + return MUTE_TYPE_YUV; + else if ((dolby_vision_mode == DOLBY_VISION_OUTPUT_MODE_IPT) || + (dolby_vision_mode == DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL)) + return MUTE_TYPE_IPT; + else + return MUTE_TYPE_NONE; } static void adjust_vpotch(void) @@ -2700,6 +2730,12 @@ static void apply_stb_core_settings( #endif u32 graphics_w = osd_graphic_width; u32 graphics_h = osd_graphic_height; + int mute_type; + + if (h_size == 0xffff) + h_size = 0; + if (v_size == 0xffff) + v_size = 0; if (is_dolby_vision_stb_mode() && (dolby_vision_flags & FLAG_CERTIFICAION)) { @@ -2747,44 +2783,71 @@ static void apply_stb_core_settings( reset); } - if (stb_core_setting_update_flag != FLAG_CHANGE_ALL) { - /* when FLAG_CONST_TC2 is set, */ - /* set the stb_core_setting_update_flag */ - /* until only meeting the FLAG_CHANGE_TC2 */ - if (stb_core_setting_update_flag & FLAG_CONST_TC2) - stb_core2_const_flag = true; - else if (stb_core_setting_update_flag & FLAG_CHANGE_TC2) - stb_core2_const_flag = false; - } + if (mask & 2) { + if (stb_core_setting_update_flag != FLAG_CHANGE_ALL) { + /* when FLAG_CONST_TC2 is set, */ + /* set the stb_core_setting_update_flag */ + /* until only meeting the FLAG_CHANGE_TC2 */ + if (stb_core_setting_update_flag & FLAG_CONST_TC2) + stb_core2_const_flag = true; + else if (stb_core_setting_update_flag & FLAG_CHANGE_TC2) + stb_core2_const_flag = false; + } - /* revert the core2 lut as last corret one when const case */ - if (stb_core2_const_flag) - memcpy(&new_dovi_setting.dm_lut2, - &dovi_setting.dm_lut2, - sizeof(struct dm_lut_ipcore_s)); + /* revert the core2 lut as last corret one when const case */ + if (stb_core2_const_flag) + memcpy(&new_dovi_setting.dm_lut2, + &dovi_setting.dm_lut2, + sizeof(struct dm_lut_ipcore_s)); - if (mask & 2) dolby_core2_set( 24, 256 * 5, (uint32_t *)&new_dovi_setting.dm_reg2, (uint32_t *)&new_dovi_setting.dm_lut2, graphics_w, graphics_h, 1, 1); - v_size = vinfo->height; - if (((vinfo->width == 720) && - (vinfo->height == 480) && - (vinfo->height != vinfo->field_height)) || - ((vinfo->width == 720) && - (vinfo->height == 576) && - (vinfo->height != vinfo->field_height)) || - ((vinfo->width == 1920) && - (vinfo->height == 1080) && - (vinfo->height != vinfo->field_height)) || - ((vinfo->width == 1920) && - (vinfo->height == 1080) && - (vinfo->height != vinfo->field_height) && - (vinfo->sync_duration_num / vinfo->sync_duration_den == 50))) - v_size = v_size/2; - if (mask & 4) + } + + if (mask & 4) { + v_size = vinfo->height; + if (((vinfo->width == 720) && + (vinfo->height == 480) && + (vinfo->height != vinfo->field_height)) || + ((vinfo->width == 720) && + (vinfo->height == 576) && + (vinfo->height != vinfo->field_height)) || + ((vinfo->width == 1920) && + (vinfo->height == 1080) && + (vinfo->height != vinfo->field_height)) || + ((vinfo->width == 1920) && + (vinfo->height == 1080) && + (vinfo->height != vinfo->field_height) && + (vinfo->sync_duration_num + / vinfo->sync_duration_den == 50))) + v_size = v_size / 2; + mute_type = get_mute_type(); + if ((get_video_mute() == VIDEO_MUTE_ON_DV) && + (!(dolby_vision_flags & FLAG_MUTE) || + cur_mute_type != mute_type)) { + pr_dolby_dbg("mute %s\n", mute_type_str[mute_type]); + /* unmute vpp and mute by core3 */ + VSYNC_WR_MPEG_REG(VPP_CLIP_MISC0, + (0x3ff << 20) | + (0x3ff << 10) | + 0x3ff); + VSYNC_WR_MPEG_REG(VPP_CLIP_MISC1, + (0x0 << 20) | + (0x0 << 10) | 0x0); + cur_mute_type = mute_type; + dolby_vision_flags |= FLAG_MUTE; + } else if ((get_video_mute() == VIDEO_MUTE_OFF) && + (dolby_vision_flags & FLAG_MUTE)) { + /* vpp unmuted when dv mute */ + /* clean flag to unmute core3 here*/ + pr_dolby_dbg("unmute %s\n", + mute_type_str[cur_mute_type]); + cur_mute_type = MUTE_TYPE_NONE; + dolby_vision_flags &= ~FLAG_MUTE; + } dolby_core3_set( 26, new_dovi_setting.md_reg3.size, (uint32_t *)&new_dovi_setting.dm_reg3, @@ -2794,6 +2857,7 @@ static void apply_stb_core_settings( dolby_vision_mode == DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL, pps_state); + } } static void osd_bypass(int bypass) @@ -3380,7 +3444,10 @@ void enable_dolby_vision(int enable) last_dolby_vision_ll_policy = dolby_vision_ll_policy; #endif - pr_info("Dolby Vision G12a turn on\n"); + pr_dolby_dbg( + "Dolby Vision G12a turn on%s\n", + dolby_vision_core1_on ? + ", core1 on" : ""); } else { VSYNC_WR_DV_REG(VPP_DOLBY_CTRL, /* cm_datx4_mode */ @@ -3456,7 +3523,10 @@ void enable_dolby_vision(int enable) last_dolby_vision_ll_policy = dolby_vision_ll_policy; #endif - pr_info("Dolby Vision turn on\n"); + pr_dolby_dbg( + "Dolby Vision turn on%s\n", + dolby_vision_core1_on ? + ", core1 on" : ""); } } else { if (!dolby_vision_core1_on @@ -3473,7 +3543,7 @@ void enable_dolby_vision(int enable) 0, 16, 1); /* core1 */ dolby_vision_core1_on = true; - pr_dolby_dbg("dolby_vision_core1_on\n"); + pr_dolby_dbg("Dolby Vision core1 turn on\n"); } else if (dolby_vision_core1_on && (!(dolby_vision_mask & 1) || !dovi_setting_video_flag)) { @@ -3488,6 +3558,7 @@ void enable_dolby_vision(int enable) 1, 16, 1); /* core1 */ dolby_vision_core1_on = false; + pr_dolby_dbg("Dolby Vision core1 turn off\n"); } } dolby_vision_on = true; @@ -3683,8 +3754,12 @@ void enable_dolby_vision(int enable) dolby_vision_wait_init = false; dolby_vision_wait_count = 0; dolby_vision_status = BYPASS_PROCESS; + dolby_vision_mode = DOLBY_VISION_OUTPUT_MODE_BYPASS; + dolby_vision_src_format = 0; dolby_vision_on_count = 0; cur_csc_type[VD1_PATH] = VPP_MATRIX_NULL; + /* clean mute flag for next time dv on */ + dolby_vision_flags &= ~FLAG_MUTE; hdr_osd_off(); hdr_vd1_off(); } @@ -4088,52 +4163,8 @@ static int sink_support_hdr10_plus(const struct vinfo_s *vinfo) return 0; } -static bool is_vinfo_available(const struct vinfo_s *vinfo) -{ - return strcmp(vinfo->name, "invalid") && - strcmp(vinfo->name, "null") && - strcmp(vinfo->name, "576cvbs") && - strcmp(vinfo->name, "470cvbs"); -} - static int current_hdr_cap = -1; /* should set when probe */ static int current_sink_available; -static int is_sink_cap_changed(const struct vinfo_s *vinfo) -{ - int hdr_cap; - int sink_available; - int ret = 0; - - if (vinfo && is_vinfo_available(vinfo)) { - hdr_cap = (1 << 0) | - (sink_support_dolby_vision(vinfo) << 1) | - (sink_support_hdr10_plus(vinfo) << 2) | - (sink_support_hdr(vinfo) << 3); - sink_available = 1; - } else { - hdr_cap = 0; - current_hdr_cap = 0; - sink_available = 0; - } - if (current_hdr_cap == -1) { - current_hdr_cap = hdr_cap; - pr_dolby_dbg("hdr cap=%d, output=%s\n", - hdr_cap, vinfo->name); - ret |= 4; - } else if (current_hdr_cap != hdr_cap) { - pr_dolby_dbg("hdr cap changed %d->%d, video %s, output=%s\n", - current_hdr_cap, hdr_cap, - get_video_enabled() ? "on" : "off", vinfo->name); - current_hdr_cap = hdr_cap; - ret |= 2; - } - if (current_sink_available != sink_available) { - pr_dolby_dbg("sink available = %d\n", sink_available); - current_sink_available = sink_available; - ret |= 1; - } - return ret; -} static int is_policy_changed(void) { @@ -4147,15 +4178,15 @@ static int is_policy_changed(void) last_dolby_vision_policy = dolby_vision_policy; ret |= 1; } -#if 0 // do not need to monitor, since this is dynamic changing if (last_dolby_vision_ll_policy != dolby_vision_ll_policy) { - /* handle policy change */ - pr_dolby_dbg("ll policy changed %d->%d\n", - last_dolby_vision_ll_policy, - dolby_vision_ll_policy); - ret |= 2; + /* handle ll policy change when dolby on */ + if (dolby_vision_on) { + pr_dolby_dbg("ll policy changed %d->%d\n", + last_dolby_vision_ll_policy, + dolby_vision_ll_policy); + ret |= 2; + } } -#endif if (last_dolby_vision_hdr10_policy != dolby_vision_hdr10_policy) { /* handle policy change */ pr_dolby_dbg("hdr10 policy changed %d->%d\n", @@ -4198,16 +4229,16 @@ static void update_src_format( dolby_vision_src_format = 5; else dolby_vision_src_format = 6; - if (cur_format != dolby_vision_src_format) { - pr_dolby_dbg( - "dolby_vision_src_format changed: %s => %s, signal_type = 0x%x\n", - input_str[cur_format], - input_str[dolby_vision_src_format], - vf->signal_type); - cur_format = dolby_vision_src_format; - } } } + if (cur_format != dolby_vision_src_format) { + pr_dolby_dbg( + "dolby_vision_src_format changed: %s => %s, signal_type = 0x%x\n", + input_str[cur_format], + input_str[dolby_vision_src_format], + vf->signal_type); + cur_format = dolby_vision_src_format; + } } int get_dolby_vision_src_format(void) @@ -4330,9 +4361,7 @@ static int dolby_vision_policy_process( mode_change = 1; } } else if ((cur_csc_type[VD1_PATH] != 0xffff) && - (get_hdr_module_status(VD1_PATH) == HDR_MODULE_ON) && - (src_format != FORMAT_DOVI) && - (src_format != FORMAT_DOVI_LL)) { + (get_hdr_module_status(VD1_PATH) == HDR_MODULE_ON)) { /*if vpp is playing hlg/hdr10+*/ /*dolby need bypass at this time*/ if (dolby_vision_mode != @@ -4420,9 +4449,7 @@ static int dolby_vision_policy_process( return mode_change; } if ((cur_csc_type[VD1_PATH] != 0xffff) && - (get_hdr_module_status(VD1_PATH) == HDR_MODULE_ON) && - (src_format != FORMAT_DOVI) && - (src_format != FORMAT_DOVI_LL)) { + (get_hdr_module_status(VD1_PATH) == HDR_MODULE_ON)) { /* bypass dolby incase VPP is not in sdr mode */ if (dolby_vision_mode != DOLBY_VISION_OUTPUT_MODE_BYPASS) { @@ -4482,7 +4509,7 @@ static int dolby_vision_policy_process( } else if (dolby_vision_mode != DOLBY_VISION_OUTPUT_MODE_BYPASS) { /* HDR/SDR bypass */ - pr_dolby_dbg("sdr, dovi output -> DOLBY_VISION_OUTPUT_MODE_BYPASS"); + pr_dolby_dbg("sdr, dovi output -> DOLBY_VISION_OUTPUT_MODE_BYPASS\n"); *mode = DOLBY_VISION_OUTPUT_MODE_BYPASS; mode_change = 1; } @@ -4496,6 +4523,17 @@ static int dolby_vision_policy_process( return mode_change; } +static char dv_provider[32] = "dvbldec"; + +void dolby_vision_set_provider(char *prov_name) +{ + if (prov_name && strlen(prov_name) < 32) { + strcpy(dv_provider, prov_name); + pr_dolby_dbg("provider changed to %s\n", dv_provider); + } +} +EXPORT_SYMBOL(dolby_vision_set_provider); + bool is_dovi_frame(struct vframe_s *vf) { struct provider_aux_req_s req; @@ -4523,9 +4561,9 @@ bool is_dovi_frame(struct vframe_s *vf) else return 0; } else if (vf->source_type == VFRAME_SOURCE_TYPE_OTHERS) { - vf_notify_provider_by_name("dvbldec", - VFRAME_EVENT_RECEIVER_GET_AUX_DATA, - (void *)&req); + vf_notify_provider_by_name(dv_provider, + VFRAME_EVENT_RECEIVER_GET_AUX_DATA, + (void *)&req); if (req.dv_enhance_exist) return true; if (!req.aux_buf || !req.aux_size) @@ -5441,6 +5479,7 @@ static bool send_hdmi_pkt( (p_hdr->display_primaries_y_0_MSB << 8) | p_hdr->display_primaries_y_0_LSB; } + if (hdr10_data.white_point[0] != ((p_hdr->white_point_x_MSB << 8) | p_hdr->white_point_x_LSB)) @@ -5488,6 +5527,7 @@ static bool send_hdmi_pkt( hdr10_data.max_frame_average = (p_hdr->max_frame_average_light_level_MSB << 8) | p_hdr->max_frame_average_light_level_LSB; + if (vinfo && vinfo->vout_device && vinfo->vout_device->fresh_tx_hdr_pkt) vinfo->vout_device->fresh_tx_hdr_pkt(&hdr10_data); @@ -5496,10 +5536,12 @@ static bool send_hdmi_pkt( vinfo->vout_device->fresh_tx_vsif_pkt) vinfo->vout_device->fresh_tx_vsif_pkt(0, 0, NULL, true); #endif - if (last_dst_format != FORMAT_HDR10) - pr_info("send_hdmi_pkt: HDR10\n"); + if ((last_dst_format != FORMAT_HDR10) || + (dolby_vision_flags & FLAG_FORCE_HDMI_PKT)) + pr_dolby_dbg("send_hdmi_pkt: HDR10\n"); + last_dst_format = dst_format; - if (flag) { + if (flag && debug_dolby & 8) { pr_dolby_dbg("Info frame for hdr10 changed:\n"); for (i = 0; i < 3; i++) pr_dolby_dbg( @@ -5570,9 +5612,10 @@ static bool send_hdmi_pkt( ? RGB_8BIT : YUV422_BIT12, &vsif, false); } - if (last_dst_format != FORMAT_DOVI) - pr_info("send_hdmi_pkt: %s\n", - dovi_setting.dovi_ll_enable ? "LL" : "DV"); + if ((last_dst_format != FORMAT_DOVI) || + (dolby_vision_flags & FLAG_FORCE_HDMI_PKT)) + pr_dolby_dbg("send_hdmi_pkt: %s\n", + dovi_setting.dovi_ll_enable ? "LL" : "DV"); last_dst_format = dst_format; } else if (last_dst_format != dst_format) { if (last_dst_format == FORMAT_HDR10) { @@ -5611,21 +5654,21 @@ static bool send_hdmi_pkt( /* HLG/HDR10+ case: first switch to SDR * immediately. */ - pr_info("send_hdmi_pkt: HDR10+/HLG: signal SDR first\n"); + pr_dolby_dbg("send_hdmi_pkt: HDR10+/HLG: signal SDR first\n"); vinfo->vout_device->fresh_tx_vsif_pkt( 0, 0, NULL, true); last_dst_format = dst_format; sdr_transition_delay = 0; } else if (sdr_transition_delay >= MAX_TRANSITION_DELAY) { - pr_info("send_hdmi_pkt: VSIF disabled, signal SDR\n"); + pr_dolby_dbg("send_hdmi_pkt: VSIF disabled, signal SDR\n"); vinfo->vout_device->fresh_tx_vsif_pkt( 0, 0, NULL, true); last_dst_format = dst_format; sdr_transition_delay = 0; } else { if (sdr_transition_delay == 0) { - pr_info("send_hdmi_pkt: disable Dovi/H14b VSIF\n"); + pr_dolby_dbg("send_hdmi_pkt: disable Dovi/H14b VSIF\n"); vinfo->vout_device->fresh_tx_vsif_pkt( 0, 0, NULL, false); } @@ -5634,6 +5677,8 @@ static bool send_hdmi_pkt( } } } + if (dolby_vision_flags & FLAG_FORCE_HDMI_PKT) + dolby_vision_flags &= ~FLAG_FORCE_HDMI_PKT; return flag; } @@ -5732,8 +5777,8 @@ int dolby_vision_parse_metadata( int total_comp_size = 0; bool el_flag = 0; bool el_halfsize_flag = 1; - uint32_t w = 3840; - uint32_t h = 2160; + u32 w = 0xffff; + u32 h = 0xffff; int meta_flag_bl = 1; int meta_flag_el = 1; int src_chroma_format = 0; @@ -5859,9 +5904,9 @@ int dolby_vision_parse_metadata( req.aux_buf = NULL; req.aux_size = 0; req.dv_enhance_exist = 0; - vf_notify_provider_by_name("dvbldec", - VFRAME_EVENT_RECEIVER_GET_AUX_DATA, - (void *)&req); + vf_notify_provider_by_name(dv_provider, + VFRAME_EVENT_RECEIVER_GET_AUX_DATA, + (void *)&req); if (debug_dolby & 1 && req.aux_buf && req.aux_size) pr_dolby_dbg("dvbldec get aux data %p %x\n", req.aux_buf, req.aux_size); @@ -5876,14 +5921,14 @@ int dolby_vision_parse_metadata( &ret_flags, drop_flag); if (ret_flags && req.dv_enhance_exist && (frame_count == 0)) { - vf_notify_provider_by_name("dvbldec", + vf_notify_provider_by_name( + dv_provider, VFRAME_EVENT_RECEIVER_DOLBY_BYPASS_EL, (void *)&req); pr_info("bypass mel\n"); } - if (ret_flags == 1) { + if (ret_flags == 1) mel_flag = true; - } if (!is_dv_standard_es(req.dv_enhance_exist, ret_flags, w)) { src_format = FORMAT_SDR; @@ -5941,7 +5986,7 @@ int dolby_vision_parse_metadata( || (frame_count == 0)) && (toggle_mode == 1)) pr_info( - "frame %d pts %lld, src bdp: %d format: %s, aux_size:%d, enhance: %d\n", + "DOLBY: dolby_vision_parse_metadata frame %d pts %lld, src bdp: %d format: %s, aux_size:%d, enhance: %d\n", frame_count, vf->pts_us64, src_bdp, (src_format == FORMAT_HDR10) ? "HDR10" : (src_format == FORMAT_DOVI ? "DOVI" : @@ -6069,10 +6114,6 @@ int dolby_vision_parse_metadata( /* use old setting for this frame */ return -1; } - w = (vf->type & VIDTYPE_COMPRESS) ? - vf->compWidth : vf->width; - h = (vf->type & VIDTYPE_COMPRESS) ? - vf->compHeight : vf->height; } if ((src_format == FORMAT_DOVI) @@ -6490,12 +6531,11 @@ int dolby_vision_parse_metadata( } } -#if 0 /* check video/graphics priority on the fly */ + /* check video/graphics priority on the fly */ if (get_video_enabled() && is_graphics_output_off()) dolby_vision_graphics_priority = 0; else dolby_vision_graphics_priority = 1; -#endif if (dolby_vision_graphics_priority || (dolby_vision_flags & @@ -6611,20 +6651,28 @@ int dolby_vision_parse_metadata( osd_graphic_width, osd_graphic_height); if (el_flag) - pr_dolby_dbg("setting %d->%d(T:%d-%d): flag=%x, md=%d,comp=%d, frame:%d\n", - src_format, dst_format, - dolby_vision_target_min, - dolby_vision_target_max[src_format][dst_format], - flag, - total_md_size, total_comp_size, - frame_count); + pr_dolby_dbg("video %d:%dx%d setting %d->%d(T:%d-%d): flag=%x, md=%d,comp=%d, frame:%d\n", + dovi_setting_video_flag, + w == 0xffff ? 0 : w, + h == 0xffff ? 0 : h, + src_format, dst_format, + dolby_vision_target_min, + dolby_vision_target_max + [src_format][dst_format], + flag, + total_md_size, total_comp_size, + frame_count); else - pr_dolby_dbg("setting %d->%d(T:%d-%d): flag=%x, md=%d, frame:%d\n", - src_format, dst_format, - dolby_vision_target_min, - dolby_vision_target_max[src_format][dst_format], - flag, - total_md_size, frame_count); + pr_dolby_dbg("video %d:%dx%d setting %d->%d(T:%d-%d): flag=%x, md=%d, frame:%d\n", + dovi_setting_video_flag, + w == 0xffff ? 0 : w, + h == 0xffff ? 0 : h, + src_format, dst_format, + dolby_vision_target_min, + dolby_vision_target_max + [src_format][dst_format], + flag, + total_md_size, frame_count); } dump_setting(&new_dovi_setting, frame_count, debug_dolby); el_mode = el_flag; @@ -6681,7 +6729,8 @@ int dolby_vision_wait_metadata(struct vframe_s *vf) req.dv_enhance_exist = 0; if (vf->source_type == VFRAME_SOURCE_TYPE_OTHERS) - vf_notify_provider_by_name("dvbldec", + vf_notify_provider_by_name( + dv_provider, VFRAME_EVENT_RECEIVER_GET_AUX_DATA, (void *)&req); } @@ -6842,7 +6891,10 @@ static void bypass_pps_path(u8 pps_state) } } -int dolby_vision_process(struct vframe_s *vf, u32 display_size, +int dolby_vision_process( + struct vframe_s *rpt_vf, + struct vframe_s *vf, + u32 display_size, u8 pps_state) /* 0: no change, 1: pps enable, 2: pps disable */ { int src_chroma_format = 0; @@ -6853,6 +6905,12 @@ int dolby_vision_process(struct vframe_s *vf, u32 display_size, bool force_set = false; static int sdr_delay; unsigned int mode = dolby_vision_mode; + static bool video_turn_off = true; + static bool video_on[VD_PATH_MAX]; + int video_status = 0; + int graphic_status = 0; + int policy_changed = 0; + int sink_changed = 0; if (!is_meson_box() && !is_meson_txlx() && !is_meson_tm2()) return -1; @@ -6866,6 +6924,11 @@ int dolby_vision_process(struct vframe_s *vf, u32 display_size, vf->compWidth : vf->width; v_size = (vf->type & VIDTYPE_COMPRESS) ? vf->compHeight : vf->height; + } else if (rpt_vf) { + h_size = (rpt_vf->type & VIDTYPE_COMPRESS) ? + rpt_vf->compWidth : rpt_vf->width; + v_size = (rpt_vf->type & VIDTYPE_COMPRESS) ? + rpt_vf->compHeight : rpt_vf->height; } else { h_size = 0; v_size = 0; @@ -6874,9 +6937,58 @@ int dolby_vision_process(struct vframe_s *vf, u32 display_size, dolby_vision_run_mode_delay; } - if ((core1_disp_hsize != h_size) - || (core1_disp_vsize != v_size)) - force_set = true; + if (dolby_vision_flags & FLAG_TOGGLE_FRAME) { + h_size = (display_size >> 16) & 0xffff; + v_size = display_size & 0xffff; + if (new_dovi_setting.video_width & 0xffff && + new_dovi_setting.video_height & 0xffff) { + if (new_dovi_setting.video_width != h_size || + new_dovi_setting.video_height != v_size) { + if (debug_dolby & 8) + pr_dolby_dbg( + "update display size %d %d -> %d %d\n", + new_dovi_setting.video_width, + new_dovi_setting.video_height, + h_size, v_size); + } + if (h_size && v_size) { + new_dovi_setting.video_width = h_size; + new_dovi_setting.video_height = v_size; + } else { + new_dovi_setting.video_width = 0xffff; + new_dovi_setting.video_height = 0xffff; + } + + /* tvcore need a reset for resolution change */ + if (is_meson_tvmode() && + ((core1_disp_hsize != h_size) || + (core1_disp_vsize != v_size))) + force_set = true; + } else if (core1_disp_hsize != h_size || + core1_disp_vsize != v_size) { + if (debug_dolby & 8) + pr_dolby_dbg( + "vpp update display size %d %d -> %d %d\n", + core1_disp_hsize, + core1_disp_vsize, + h_size, v_size); + if (h_size && v_size) { + new_dovi_setting.video_width = h_size; + new_dovi_setting.video_height = v_size; + } else { + new_dovi_setting.video_width = 0xffff; + new_dovi_setting.video_height = 0xffff; + } + } + if (!vf && !sdr_delay) { + /* log to monitor if has dv toggles not needed */ + /* !sdr_delay: except in transition from DV to SDR */ + pr_dolby_dbg("NULL frame, hdr module %s, video %s\n", + get_hdr_module_status(VD1_PATH) + == HDR_MODULE_ON ? "on" : "off", + get_video_enabled() ? "on" : "off"); + } + } if ((dolby_vision_flags & FLAG_CERTIFICAION) && (setting_update_count > crc_count) @@ -6911,42 +7023,71 @@ int dolby_vision_process(struct vframe_s *vf, u32 display_size, } } - if (dolby_vision_on - && is_video_output_off(vf) - && !video_off_handled) { - dolby_vision_set_toggle_flag(1); - frame_count = 0; - video_off_handled = 1; - if (debug_dolby & 2) { - pr_dolby_dbg("video off\n"); - } - } + video_status = is_video_turn_on(video_on, VD1_PATH); + if (video_status == -1) + video_turn_off = true; + else if (video_status == 1) + video_turn_off = false; - if (is_sink_cap_changed(vinfo)) { - if (vf) - dolby_vision_parse_metadata(vf, 1, false, false); - dolby_vision_set_toggle_flag(1); - } - if (is_video_turn_on() == 1) { - if (vf && !dolby_vision_parse_metadata(vf, 0, false, false)) - dolby_vision_set_toggle_flag(1); + if (video_turn_off && + get_hdr_module_status(VD1_PATH) + != HDR_MODULE_ON) { + vf = NULL; + rpt_vf = NULL; } - /* only monitor dolby_vision_policy */ - /* other policy will be updated for video */ - if (is_policy_changed() & 1) + graphic_status = is_graphic_changed(); + + /* monitor policy changes */ + policy_changed = is_policy_changed(); + if (policy_changed) dolby_vision_set_toggle_flag(1); - if (is_graphic_changed()) + + if (graphic_status & 2) dolby_vision_set_toggle_flag(1); - if (!vf && !get_video_enabled()) { - if (dolby_vision_policy == DOLBY_VISION_FOLLOW_SINK - && !is_dolby_vision_video_on()) { - if (dolby_vision_policy_process( - &mode, FORMAT_SDR)) { + if (!is_dolby_vision_on()) + dolby_vision_flags &= ~FLAG_FORCE_HDMI_PKT; + + sink_changed = (is_sink_cap_changed(vinfo, + ¤t_hdr_cap, ¤t_sink_available) & 2) ? 1 : 0; + if (sink_changed || policy_changed || + (video_status == 1) || (graphic_status & 2) || + (dolby_vision_flags & FLAG_FORCE_HDMI_PKT)) { + u8 toggle_mode; + + pr_dolby_dbg("sink %s, cap 0x%x, video %s, osd %s, vf %p, rpt_vf %p\n", + current_sink_available ? "on" : "off", + current_hdr_cap, + video_turn_off ? "off" : "on", + is_graphics_output_off() ? "off" : "on", + vf, rpt_vf); + if (vf && (vf != rpt_vf)) + toggle_mode = 1; + else + toggle_mode = 0; + if ((vf || rpt_vf) && + !dolby_vision_parse_metadata( + vf ? vf : rpt_vf, toggle_mode, false, false)) { + h_size = (display_size >> 16) & 0xffff; + v_size = display_size & 0xffff; + new_dovi_setting.video_width = h_size; + new_dovi_setting.video_height = v_size; + dolby_vision_set_toggle_flag(1); + } + } + + if (!vf && video_turn_off) { + if (dolby_vision_policy_process(&mode, FORMAT_SDR)) { + pr_dolby_dbg("Fake SDR, mode->%d\n", mode); + if (dolby_vision_policy == DOLBY_VISION_FOLLOW_SOURCE && + mode == DOLBY_VISION_OUTPUT_MODE_BYPASS) { + dolby_vision_mode = + DOLBY_VISION_OUTPUT_MODE_BYPASS; + dolby_vision_set_toggle_flag(0); + dolby_vision_wait_on = false; + } else dolby_vision_set_toggle_flag(1); - pr_dolby_dbg("Fake SDR, mode->%d\n", mode); - } } if (dolby_vision_flags & FLAG_TOGGLE_FRAME) dolby_vision_parse_metadata( @@ -6954,8 +7095,6 @@ int dolby_vision_process(struct vframe_s *vf, u32 display_size, } if (dolby_vision_mode == DOLBY_VISION_OUTPUT_MODE_BYPASS) { - if (vinfo && sink_support_dolby_vision(vinfo)) - dolby_vision_set_toggle_flag(1); if (!is_meson_tvmode() || force_stb_mode) { if (vinfo && vinfo->vout_device && (!vinfo->vout_device->dv_info) @@ -6967,6 +7106,8 @@ int dolby_vision_process(struct vframe_s *vf, u32 display_size, if (dolby_vision_status != BYPASS_PROCESS) { if (vinfo && !is_meson_tvmode() && !force_stb_mode) { + if (!vf && rpt_vf) + rpt_vf = vf; if (vf && is_hdr10plus_frame(vf)) { /* disable dolby immediately */ pr_info("Dolby bypass: HDR10+: Switched to SDR first\n"); @@ -6980,28 +7121,51 @@ int dolby_vision_process(struct vframe_s *vf, u32 display_size, FORMAT_SDR, vinfo, vf); enable_dolby_vision(0); } else if (last_dst_format != FORMAT_DOVI) { - /* disable dolby immediately */ - pr_info("Dolby bypass: Switched %d to SDR\n", - last_dst_format); + /* disable dolby immediately: + * non-dovi alwyas hdr to adaptive + */ + pr_dolby_dbg("Dolby bypass: Switched %d to SDR\n", + last_dst_format); send_hdmi_pkt(dolby_vision_src_format, FORMAT_SDR, vinfo, vf); enable_dolby_vision(0); } else { + /* disable dolby after sdr delay: + * dovi alwyas hdr to adaptive or dovi + * playback exit in adaptive mode on + * a dovi tv + */ + if (sdr_delay == 0) { + pr_dolby_dbg("Dolby bypass: Start - Switched to SDR\n"); + dolby_vision_set_toggle_flag(1); + } + if ((get_video_mute() == + VIDEO_MUTE_ON_DV && + !(dolby_vision_flags & FLAG_MUTE)) || + (get_video_mute() == VIDEO_MUTE_OFF && + dolby_vision_flags & FLAG_MUTE)) + /* core 3 only */ + apply_stb_core_settings( + dovi_setting_video_flag, + 0x4, + 0, + (dovi_setting.video_width << 16) + | dovi_setting.video_height, + pps_state); send_hdmi_pkt(dolby_vision_src_format, FORMAT_SDR, vinfo, vf); if (sdr_delay >= MAX_TRANSITION_DELAY) { - pr_info("Dolby bypass: Done - Switched to SDR\n"); + pr_dolby_dbg("Dolby bypass: Done - Switched to SDR\n"); enable_dolby_vision(0); sdr_delay = 0; - } - sdr_delay++; + } else + sdr_delay++; } } else enable_dolby_vision(0); - - if (dolby_vision_flags & FLAG_TOGGLE_FRAME) - dolby_vision_flags &= ~FLAG_TOGGLE_FRAME; } + if (sdr_delay == 0) + dolby_vision_flags &= ~FLAG_TOGGLE_FRAME; return 0; } else if (sdr_delay != 0) { /* in case mode change to a mode requiring dolby block */ @@ -7072,6 +7236,10 @@ int dolby_vision_process(struct vframe_s *vf, u32 display_size, } else { if ((new_dovi_setting.video_width & 0xffff) && (new_dovi_setting.video_height & 0xffff)) { + if (new_dovi_setting.video_width == 0xffff) + new_dovi_setting.video_width = 0; + if (new_dovi_setting.video_height == 0xffff) + new_dovi_setting.video_height = 0; if (force_set && !(dolby_vision_flags & FLAG_CERTIFICAION)) @@ -7080,22 +7248,45 @@ int dolby_vision_process(struct vframe_s *vf, u32 display_size, dovi_setting_video_flag, dolby_vision_mask & 0x7, reset_flag, - (h_size << 16) | v_size, + (new_dovi_setting.video_width << 16) + | new_dovi_setting.video_height, pps_state); memcpy(&dovi_setting, &new_dovi_setting, sizeof(dovi_setting)); + if (core1_disp_hsize != + dovi_setting.video_width || + core1_disp_vsize != + dovi_setting.video_height) + if (core1_disp_hsize && + core1_disp_vsize) + pr_dolby_dbg( + "frame size %d %d->%d %d\n", + core1_disp_hsize, + core1_disp_vsize, + dovi_setting.video_width, + dovi_setting.video_height); new_dovi_setting.video_width = new_dovi_setting.video_height = 0; - if (!h_size || !v_size) + if (!dovi_setting.video_width || + !dovi_setting.video_height) dovi_setting_video_flag = false; if (dovi_setting_video_flag && (dolby_vision_on_count == 0)) pr_dolby_dbg("first frame reset %d\n", reset_flag); + /* clr hdr+ pkt when enable dv */ + if (!dolby_vision_on && + vinfo && vinfo->vout_device && + vinfo->vout_device->fresh_tx_hdr10plus_pkt) + vinfo->vout_device-> + fresh_tx_hdr10plus_pkt( + 0, NULL); enable_dolby_vision(1); bypass_pps_path(pps_state); - core1_disp_hsize = h_size; - core1_disp_vsize = v_size; + core1_disp_hsize = + dovi_setting.video_width; + core1_disp_vsize = + dovi_setting.video_height; /* send HDMI packet according to dst_format */ if (vinfo && !force_stb_mode) send_hdmi_pkt( @@ -7104,6 +7295,29 @@ int dolby_vision_process(struct vframe_s *vf, u32 display_size, vinfo, vf); update_dolby_vision_status( dovi_setting.src_format); + } else { + if ((get_video_mute() == VIDEO_MUTE_ON_DV && + !(dolby_vision_flags & FLAG_MUTE)) || + (get_video_mute() == VIDEO_MUTE_OFF && + dolby_vision_flags & FLAG_MUTE) || + (last_dolby_vision_ll_policy != + dolby_vision_ll_policy)) + /* core 3 only */ + apply_stb_core_settings( + dovi_setting_video_flag, + 0x4, + reset_flag, + (dovi_setting.video_width << 16) + | dovi_setting.video_height, + pps_state); + /* force send hdmi pkt */ + if (dolby_vision_flags & FLAG_FORCE_HDMI_PKT) { + if (vinfo && !force_stb_mode) + send_hdmi_pkt( + dovi_setting.src_format, + dovi_setting.dst_format, + vinfo, vf); + } } } dolby_vision_flags &= ~FLAG_TOGGLE_FRAME; @@ -7177,15 +7391,16 @@ int dolby_vision_process(struct vframe_s *vf, u32 display_size, /* core 1 only */ dolby_vision_mask & 0x1, reset_flag, - (h_size << 16) | v_size, + (core1_disp_hsize << 16) + | core1_disp_vsize, pps_state); - core1_disp_hsize = h_size; - core1_disp_vsize = v_size; if (dolby_vision_on_count < dolby_vision_run_mode_delay) - pr_dolby_dbg("fake frame %d reset %d\n", - dolby_vision_on_count, - reset_flag); + pr_dolby_dbg("fake frame (%d %d) %d reset %d\n", + core1_disp_hsize, + core1_disp_vsize, + dolby_vision_on_count, + reset_flag); } } } @@ -7227,10 +7442,13 @@ EXPORT_SYMBOL(for_dolby_vision_certification); void dolby_vision_set_toggle_flag(int flag) { - if (flag) + if (flag) { dolby_vision_flags |= FLAG_TOGGLE_FRAME; - else + if (flag & 2) + dolby_vision_flags |= FLAG_FORCE_HDMI_PKT; + } else { dolby_vision_flags &= ~FLAG_TOGGLE_FRAME; + } } EXPORT_SYMBOL(dolby_vision_set_toggle_flag); @@ -7281,6 +7499,12 @@ bool is_dolby_vision_el_disable(void) } EXPORT_SYMBOL(is_dolby_vision_el_disable); +void set_dolby_vision_policy(int policy) +{ + dolby_vision_policy = policy; +} +EXPORT_SYMBOL(set_dolby_vision_policy); + int get_dolby_vision_policy(void) { return dolby_vision_policy; @@ -7299,9 +7523,11 @@ int register_dv_functions(const struct dolby_vision_func_s *func) *otherwise it will effect hdr module */ if (dolby_vision_on_in_uboot) { - if (is_vinfo_available(vinfo)) { - is_sink_cap_changed(vinfo); - } else + if (is_vinfo_available(vinfo)) + is_sink_cap_changed(vinfo, + ¤t_hdr_cap, + ¤t_sink_available); + else pr_info("sink not available\n"); dolby_vision_on = true; dolby_vision_wait_on = false; diff --git a/drivers/amlogic/media/enhancement/amvecm/amcsc.c b/drivers/amlogic/media/enhancement/amvecm/amcsc.c index 7aa379e..ac17546 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amcsc.c +++ b/drivers/amlogic/media/enhancement/amvecm/amcsc.c @@ -127,7 +127,7 @@ static ssize_t write_file_hdr_cfgosd( hdr_set_cfg_osd_100(val); - pr_info("en_osd_lut_100: %d\n", phdr->hdr_cfg.en_osd_lut_100); + pr_info("HDR: en_osd_lut_100: %d\n", phdr->hdr_cfg.en_osd_lut_100); return count; } @@ -337,12 +337,56 @@ static uint hdmi_csc_type = 0xffff; module_param(hdmi_csc_type, uint, 0444); MODULE_PARM_DESC(hdmi_csc_type, "\n current color space convert type\n"); +/* 0: follow sink, 1: follow source, 2: debug, 0xff: bootup default value */ +/* by default follow source to match default sdr_mode*/ +static uint hdr_policy = 1; +static uint cur_hdr_policy = 0xff; +module_param(hdr_policy, uint, 0664); +MODULE_PARM_DESC(hdr_policy, "\n current hdr_policy\n"); + +/* when cur_hdr_policy == 2 && dovi disable */ +/* enum output_format_e */ +/* BT709 = 1, */ +/* BT2020 = 2, */ +/* BT2020_PQ = 3, */ +/* BT2020_PQ_DYNAMIC = 4, */ +/* BT2020_HLG = 5, */ +/* BT2100_IPT = 6 */ +/* BT2020 = 2: 2020 + gamma not support in hdmi now */ +static uint force_output = 1; /* BT709 */ +module_param(force_output, uint, 0664); +MODULE_PARM_DESC(force_output, "\n current force_output\n"); + +int get_hdr_policy(void) +{ + int dv_policy = 0; + int dv_mode = 0; + + if (is_dolby_vision_enable()) { + /* sync hdr_policy with dolby_vision_policy */ + /* get current dolby_vision_mode */ + dv_policy = get_dolby_vision_policy(); + dv_mode = get_dolby_vision_mode(); + if ((dv_policy != DOLBY_VISION_FORCE_OUTPUT_MODE) || + (dv_mode != DOLBY_VISION_OUTPUT_MODE_BYPASS)) { + /* use dv policy when not force bypass */ + return dv_policy; + } + } + return hdr_policy; +} +EXPORT_SYMBOL(get_hdr_policy); + +enum output_format_e get_force_output(void) +{ + return force_output; +} +EXPORT_SYMBOL(get_force_output); + static uint hdr_mode = 2; /* 0: hdr->hdr, 1:hdr->sdr, 2:auto */ module_param(hdr_mode, uint, 0664); MODULE_PARM_DESC(hdr_mode, "\n set hdr_mode\n"); -static uint cur_hdr_mode; - /* 0: hdr->hdr, 1:hdr->sdr, 2:hdr->hlg */ uint hdr_process_mode[VD_PATH_MAX]; uint cur_hdr_process_mode[VD_PATH_MAX] = {PROC_OFF, PROC_OFF}; @@ -418,18 +462,15 @@ module_param(hdr_flag, uint, 0664); MODULE_PARM_DESC(hdr_flag, "\n set hdr_flag\n"); /* 0: off, 1: normal, 2: bypass */ -static int video_process_status[VD_PATH_MAX]; +static int video_process_status[VD_PATH_MAX] = {2, 2}; module_param_array(video_process_status, uint, &vd_path_max, 0664); MODULE_PARM_DESC(video_process_status, "\n video_process_status\n"); -int get_hdr_module_status(enum vd_path_e vd_path) -{ - return video_process_status[vd_path]; -} -EXPORT_SYMBOL(get_hdr_module_status); void set_hdr_module_status(enum vd_path_e vd_path, int status) { video_process_status[vd_path] = status; + pr_csc(4, "video_process_status[VD%d] = %d", + vd_path + 1, status); } EXPORT_SYMBOL(set_hdr_module_status); @@ -3714,8 +3755,8 @@ int signal_type_changed(struct vframe_s *vf, u32 default_signal_type; int change_flag = 0; int i, j; - struct vframe_master_display_colour_s *p_cur; - struct vframe_master_display_colour_s *p_new; + struct vframe_master_display_colour_s *p_cur = NULL; + struct vframe_master_display_colour_s *p_new = NULL; struct vframe_master_display_colour_s cus; int ret; @@ -3820,9 +3861,11 @@ int signal_type_changed(struct vframe_s *vf, /*vf->signal_type, signal_type);*/ } - ret = hdr10_primaries_changed(p_new, p_cur); - if (ret) - change_flag |= SIG_PRI_INFO; + if (p_new && p_cur) { + ret = hdr10_primaries_changed(p_new, p_cur); + if (ret) + change_flag |= SIG_PRI_INFO; + } if (change_flag & SIG_PRI_INFO) { pr_csc(1, "vd%d Master_display_colour changed %x.\n", vd_path + 1, ret); @@ -6264,23 +6307,100 @@ static void hdr_support_process(struct vinfo_s *vinfo, enum vd_path_e vd_path) sdr_process_mode[vd_path] = sdr_mode; } +static int sink_support_dolby_vision(const struct vinfo_s *vinfo) +{ + if (!vinfo || !vinfo->vout_device || !vinfo->vout_device->dv_info) + return 0; + if (vinfo->vout_device->dv_info->ieeeoui != 0x00d046) + return 0; + if (vinfo->vout_device->dv_info->block_flag != CORRECT) + return 0; + if (strstr(vinfo->name, "2160p60hz") || + strstr(vinfo->name, "2160p50hz")) { + if (!vinfo->vout_device->dv_info->sup_2160p60hz) + return 0; + } + return 1; +} + +static int sink_support_hdr(const struct vinfo_s *vinfo) +{ + if (!vinfo) + return 0; + if (vinfo->hdr_info.hdr_support & HDR_SUPPORT) + return 1; + return 0; +} + +static int sink_support_hlg(const struct vinfo_s *vinfo) +{ + if (!vinfo) + return 0; + if (vinfo->hdr_info.hdr_support & HLG_SUPPORT) + return 1; + return 0; +} + +static int sink_support_hdr10_plus(const struct vinfo_s *vinfo) +{ + if ((vinfo->hdr_info.hdr10plus_info.ieeeoui + == 0x90848B) && + (vinfo->hdr_info.hdr10plus_info.application_version + == 1)) + return 1; + + return 0; +} + +bool is_vinfo_available(const struct vinfo_s *vinfo) +{ + return strcmp(vinfo->name, "invalid") && + strcmp(vinfo->name, "null") && + strcmp(vinfo->name, "576cvbs") && + strcmp(vinfo->name, "470cvbs"); +} +EXPORT_SYMBOL(is_vinfo_available); + static enum hdr_type_e get_source_type(enum vd_path_e vd_path) { get_cur_vd_signal_type(vd_path); + if (vd_path == VD1_PATH && + is_dolby_vision_enable() && + get_dolby_vision_src_format() + == HDRTYPE_DOVI) + return HDRTYPE_DOVI; if (((signal_transfer_characteristic == 14) || - (signal_transfer_characteristic == 18)) && - (signal_color_primaries == 9)) + (signal_transfer_characteristic == 18)) && + (signal_color_primaries == 9)) return HDRTYPE_HLG; - else if ((signal_transfer_characteristic == 0x30) - && (signal_color_primaries == 9)) - return HDRTYPE_HDR10PLUS; - else if ((signal_transfer_characteristic == 16) - || (signal_color_primaries == 9)) + else if ((signal_transfer_characteristic == 0x30) && + (signal_color_primaries == 9)) { + if (sink_support_hdr10_plus(get_current_vinfo())) + return HDRTYPE_HDR10PLUS; + else + return HDRTYPE_HDR10; + } else if ((signal_transfer_characteristic == 16) || + (signal_color_primaries == 9)) return HDRTYPE_HDR10; else return HDRTYPE_SDR; } +int get_hdr_module_status(enum vd_path_e vd_path) +{ + if (vd_path == VD1_PATH && + is_dolby_vision_enable() && + get_dolby_vision_policy() + == DOLBY_VISION_FOLLOW_SOURCE && + get_source_type(VD1_PATH) + == HDRTYPE_SDR && + sdr_process_mode[VD1_PATH] + == PROC_BYPASS) + return HDR_MODULE_BYPASS; + return video_process_status[vd_path]; +} +EXPORT_SYMBOL(get_hdr_module_status); + static bool video_layer_wait_on[VD_PATH_MAX]; bool is_video_layer_on(enum vd_path_e vd_path) { @@ -6346,6 +6466,7 @@ static void hdr10_plus_metadata_update(struct vframe_s *vf, static struct hdr10plus_para hdmitx_hdr10plus_params[VD_PATH_MAX]; static int hdr10_plus_pkt_update; static bool hdr10_plus_pkt_on; +/* 0: no delay, 1:delay one frame, >1:delay one frame and repeat */ static uint hdr10_plus_pkt_delay = 1; static struct hdr10plus_para cur_hdr10plus_params; static struct master_display_info_s cur_send_info; @@ -6418,8 +6539,8 @@ void send_hdr10_plus_pkt(enum vd_path_e vd_path) else hdr10_plus_pkt_update = HDRPLUS_PKT_IDLE; pr_csc(2, "send_hdr10_plus_pkt update\n"); - } else if ((hdr10_plus_pkt_update == HDRPLUS_PKT_REPEAT) - && (get_hdr10_plus_pkt_delay() > 1)) { + } else if ((hdr10_plus_pkt_update == HDRPLUS_PKT_REPEAT) && + (get_hdr10_plus_pkt_delay() > 1)) { vdev->fresh_tx_hdr_pkt( &cur_send_info); vdev->fresh_tx_hdr10plus_pkt( @@ -6918,6 +7039,59 @@ static void video_process( } } +static int current_hdr_cap[VD_PATH_MAX] = {-1, -1}; /* should set when probe */ +static int current_sink_available[VD_PATH_MAX] = {-1, -1}; + +int is_sink_cap_changed( + const struct vinfo_s *vinfo, + int *p_current_hdr_cap, + int *p_current_sink_available) +{ + int hdr_cap; + int sink_available; + int ret = 0; + + if (is_vinfo_available(vinfo)) { + hdr_cap = (1 << 0) | + (sink_support_dolby_vision(vinfo) << 1) | + (sink_support_hdr10_plus(vinfo) << 2) | + (sink_support_hdr(vinfo) << 3) | + (sink_support_hlg(vinfo) << 3); + sink_available = 1; + } else { + hdr_cap = 0; + *p_current_hdr_cap = 0; + sink_available = 0; + } + + if (*p_current_hdr_cap == -1) { + *p_current_hdr_cap = hdr_cap; + ret |= 4; + } else if (*p_current_hdr_cap != hdr_cap) { + *p_current_hdr_cap = hdr_cap; + ret |= 2; + } + if (*p_current_sink_available != sink_available) { + *p_current_sink_available = sink_available; + ret |= 1; + } + return ret; +} +EXPORT_SYMBOL(is_sink_cap_changed); + +static bool video_on[VD_PATH_MAX]; +int is_video_turn_on(bool *vd_on, enum vd_path_e vd_path) +{ + int ret = 0; + + if (vd_on[vd_path] != is_video_layer_on(vd_path)) { + vd_on[vd_path] = is_video_layer_on(vd_path); + ret = vd_on[vd_path] ? 1 : -1; + } + return ret; +} +EXPORT_SYMBOL(is_video_turn_on); + static int vpp_matrix_update( struct vframe_s *vf, struct vinfo_s *vinfo, int flags, enum vd_path_e vd_path) @@ -6951,13 +7125,19 @@ static int vpp_matrix_update( else csc_type = get_csc_type(); - - if (video_process_status[vd_path] == HDR_MODULE_BYPASS) { - if (is_video_layer_on(vd_path) && - (!is_dolby_vision_on() || (vd_path == VD2_PATH))) + if ((video_process_status[vd_path] == HDR_MODULE_BYPASS) && + !(video_process_flags[vd_path] & PROC_FLAG_FORCE_PROCESS)) { + if ((is_video_layer_on(vd_path) || + video_layer_wait_on[vd_path]) && + (!is_dolby_vision_on() || + (vd_path == VD2_PATH))) { video_process_status[vd_path] = HDR_MODULE_ON; - else + pr_csc(4, + "video_process_status[%s] = HDR_MODULE_ON\n", + vd_path == VD1_PATH ? "VD1" : "VD2"); + } else { return 2; + } } if (is_dolby_vision_on() && (vd_path == VD1_PATH)) @@ -6969,6 +7149,12 @@ static int vpp_matrix_update( enum vd_path_e oth_path = (vd_path == VD1_PATH) ? VD2_PATH : VD1_PATH; + if (get_hdr_policy() != cur_hdr_policy) { + pr_csc(4, "policy changed from %d to %d.\n", + cur_hdr_policy, + get_hdr_policy()); + signal_change_flag |= SIG_HDR_MODE; + } source_format[VD1_PATH] = get_source_type(VD1_PATH); source_format[VD2_PATH] = get_source_type(VD2_PATH); get_cur_vd_signal_type(vd_path); @@ -7026,11 +7212,13 @@ static int vpp_matrix_update( SIG_SRC_OUTPUT_CHG | SIG_HDR10_PLUS_MODE | SIG_SRC_CHG | SIG_HDR_OOTF_CHG))) { if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A) && - (get_cpu_type() != MESON_CPU_MAJOR_ID_TL1)) + (get_cpu_type() != MESON_CPU_MAJOR_ID_TL1)) { video_post_process(csc_type, vinfo, vd_path); - else + cur_hdr_policy = get_hdr_policy(); + } else { video_process(vf, csc_type, signal_change_flag, vinfo, p, vd_path); + } } /* eye protection mode */ @@ -7040,11 +7228,12 @@ static int vpp_matrix_update( return 0; } +static struct vframe_s last_vf_backup[VD_PATH_MAX]; static struct vframe_s *last_vf[VD_PATH_MAX]; static int last_vf_signal_type[VD_PATH_MAX]; -static int null_vf_cnt[VD_PATH_MAX]; -static int prev_hdr_support; +static int null_vf_cnt[VD_PATH_MAX] = {2, 2}; static int prev_color_fmt; +static bool dovi_on; static unsigned int fg_vf_sw_dbg; unsigned int null_vf_max = 2; @@ -7057,9 +7246,12 @@ int amvecm_matrix_process( { struct vframe_s fake_vframe; struct vinfo_s *vinfo = get_current_vinfo(); - int toggle_frame; + int toggle_frame = 0; int i; int ret; + int sink_changed = 0; + bool cap_changed = false; + bool send_fake_frame = false; if ((get_cpu_type() < MESON_CPU_MAJOR_ID_GXTVBB) || is_meson_gxl_package_905M2() || (csc_en == 0) || @@ -7083,15 +7275,43 @@ int amvecm_matrix_process( CSC_ON); } - if (is_dolby_vision_on() && vd_path == VD1_PATH) { - if ((video_process_status[vd_path] == HDR_MODULE_BYPASS) - && (vf || vf_rpt)) - return vpp_matrix_update( - vf ? vf : vf_rpt, vinfo, flags, vd_path); - else - return 0; + if (vd_path == VD1_PATH) { + if (is_dolby_vision_on()) { + dovi_on = true; + if ((video_process_status[vd_path] + == HDR_MODULE_BYPASS) && + (vf || vf_rpt)) + return vpp_matrix_update( + vf ? vf : vf_rpt, + vinfo, flags, vd_path); + else + return 0; + } else { + /* dv from on to off */ + if (dovi_on) { + cap_changed = true; + dovi_on = false; + } + } } + sink_changed = is_sink_cap_changed(vinfo, + ¤t_hdr_cap[vd_path], + ¤t_sink_available[vd_path]); + if (sink_changed) { + cap_changed = sink_changed & 0x02; + pr_csc(4, "sink %s, cap%s 0x%x, vd%d %s %p %p\n", + current_sink_available[vd_path] ? "on" : "off", + cap_changed ? " changed" : "", + current_hdr_cap[vd_path], + vd_path + 1, + is_video_layer_on(vd_path) ? "on" : "off", + vf, vf_rpt); + } + + if (is_video_turn_on(video_on, vd_path) == 1) + cap_changed = true; + if ((vf != NULL) && (flags & CSC_FLAG_CHECK_OUTPUT)) { ret = vpp_matrix_update(vf, vinfo, flags, vd_path); if (ret == 1) { @@ -7105,12 +7325,20 @@ int amvecm_matrix_process( } } else if ((vf != NULL) && (flags & CSC_FLAG_TOGGLE_FRAME)) { if (is_video_layer_on(vd_path) || + video_layer_wait_on[vd_path] || video_process_flags[vd_path] & PROC_FLAG_FORCE_PROCESS) { - video_process_status[vd_path] = HDR_MODULE_ON; + if (video_process_status[vd_path] != HDR_MODULE_ON) { + video_process_status[vd_path] = HDR_MODULE_ON; + pr_csc(4, + "video_process_status[%s] = HDR_MODULE_ON\n", + vd_path == VD1_PATH ? "VD1" : "VD2"); + } vpp_matrix_update(vf, vinfo, flags, vd_path); video_process_flags[vd_path] &= ~PROC_FLAG_FORCE_PROCESS; - last_vf[vd_path] = vf; + memcpy(&last_vf_backup[vd_path], vf, + sizeof(struct vframe_s)); + last_vf[vd_path] = &last_vf_backup[vd_path]; last_vf_signal_type[vd_path] = vf->signal_type; null_vf_cnt[vd_path] = 0; pr_csc(2, "vd%d: process toggle frame(%p) %x\n", @@ -7123,100 +7351,180 @@ int amvecm_matrix_process( fg_vf_sw_dbg = 1; /* debug vframe info backup */ dbg_vf = vf; - } else if ((vf_rpt != NULL) && is_video_layer_on(vd_path)) { - if (video_process_flags[vd_path] & PROC_FLAG_FORCE_PROCESS) { + } else if (vf_rpt && + (is_video_layer_on(vd_path) || + video_layer_wait_on[vd_path])) { + if ((video_process_flags[vd_path] & PROC_FLAG_FORCE_PROCESS) || + cap_changed) { + if (video_process_status[vd_path] != HDR_MODULE_ON) { + video_process_status[vd_path] = HDR_MODULE_ON; + pr_csc(4, + "video_process_status[%s] = HDR_MODULE_ON\n", + vd_path == VD1_PATH ? "VD1" : "VD2"); + } vpp_matrix_update(vf_rpt, vinfo, flags, vd_path); video_process_flags[vd_path] &= ~PROC_FLAG_FORCE_PROCESS; - pr_csc(2, "vd%d: rpt and process frame(%p)\n", - vd_path + 1, vf_rpt); - } else + pr_csc(4, "vd%d: rpt and process frame(%p)\n", + vd_path + 1, vf_rpt); + } else { pr_csc(2, "vd%d: rpt frame(%p)\n", vd_path + 1, vf_rpt); + } null_vf_cnt[vd_path] = 0; fg_vf_sw_dbg = 2; - } else if ((last_vf[vd_path] != NULL) && is_video_layer_on(vd_path)) { - pr_csc(2, "vd%d: rpt frame local\n", - vd_path + 1); + } else if (last_vf[vd_path] && + (is_video_layer_on(vd_path) || + video_layer_wait_on[vd_path])) { + if (video_process_flags[vd_path] & PROC_FLAG_FORCE_PROCESS || + cap_changed) { + vpp_matrix_update( + last_vf[vd_path], vinfo, flags, vd_path); + video_process_flags[vd_path] &= + ~PROC_FLAG_FORCE_PROCESS; + pr_csc(4, "vd%d: rpt and process frame local(%p)\n", + vd_path + 1, last_vf[vd_path]); + } else { + pr_csc(2, "vd%d: rpt frame local\n", + vd_path + 1); + } null_vf_cnt[vd_path] = 0; fg_vf_sw_dbg = 3; } else { + last_vf[vd_path] = NULL; + + if (null_vf_cnt[vd_path] <= null_vf_max) + null_vf_cnt[vd_path]++; + /* handle change between TV support/not support HDR */ - if (prev_hdr_support != vinfo->hdr_info.hdr_support) { - if ((vd_path == VD1_PATH) || - ((vd_path == VD2_PATH) && - is_video_layer_on(VD2_PATH))) + if (cap_changed) { + if (is_video_layer_on(vd_path)) null_vf_cnt[vd_path] = 0; - prev_hdr_support = vinfo->hdr_info.hdr_support; - pr_csc(2, "vd%d: hdr_support changed\n", - vd_path + 1); + pr_csc(4, "vd%d: sink cap changed when idle\n", + vd_path + 1); } + /* handle change between output mode*/ if (prev_color_fmt != vinfo->viu_color_fmt) { - if ((vd_path == VD1_PATH) || - ((vd_path == VD2_PATH) && - is_video_layer_on(VD2_PATH))) + if (is_video_layer_on(vd_path)) null_vf_cnt[vd_path] = 0; prev_color_fmt = vinfo->viu_color_fmt; - pr_csc(2, "vd%d: output color format changed\n", - vd_path + 1); + pr_csc(4, "vd%d: output color format changed\n", + vd_path + 1); } + /* handle eye protect mode */ - if ((cur_eye_protect_mode != wb_val[0]) - && (vd_path == VD1_PATH)) { + if ((cur_eye_protect_mode != wb_val[0]) && + (vd_path == VD1_PATH) && + is_video_layer_on(vd_path)) { null_vf_cnt[vd_path] = 0; - pr_csc(2, "vd%d: eye_protect_mode changed\n", - vd_path + 1); + pr_csc(4, "vd%d: eye_protect_mode changed\n", + vd_path + 1); } - if (!is_video_layer_on(vd_path) - && (video_process_status[vd_path] == HDR_MODULE_ON)) - null_vf_cnt[vd_path] = toggle_frame = 1; - else if (csc_en & 0x10) - toggle_frame = null_vf_max; - else - toggle_frame = 0; - /* handle sdr_mode change */ - if ((vinfo->hdr_info.hdr_support & 0xc) && - ((cpu_after_eq(MESON_CPU_MAJOR_ID_GXL)) && - (vinfo->viu_color_fmt != COLOR_FMT_RGB444))) { + if (is_video_layer_on(vd_path) && + (vinfo->hdr_info.hdr_support & 0x4) && + ((cpu_after_eq(MESON_CPU_MAJOR_ID_GXL)) && + (vinfo->viu_color_fmt != COLOR_FMT_RGB444))) { if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) { - if (hdr_mode != cur_hdr_mode) { - null_vf_cnt[vd_path] = toggle_frame; - cur_hdr_mode = hdr_mode; - pr_csc(2, "vd%d: hdr_mode changed\n", - vd_path + 1); - } if (sdr_mode != cur_sdr_mode) { - null_vf_cnt[vd_path] = toggle_frame; + null_vf_cnt[vd_path] = 0; cur_sdr_mode = sdr_mode; - pr_csc(2, "vd%d: sdr_mode changed\n", - vd_path + 1); + pr_csc(4, "vd%d: sdr_mode changed\n", + vd_path + 1); } - } else if (((sdr_process_mode[vd_path] != - PROC_SDR_TO_HDR) - && (sdr_mode > 0)) - || ((sdr_process_mode[vd_path] > PROC_BYPASS) && - (sdr_process_mode[vd_path] != PROC_OFF) && - (sdr_mode == 0))) - null_vf_cnt[vd_path] = toggle_frame; + } else { + if (((sdr_process_mode[vd_path] != + PROC_SDR_TO_HDR) && + (sdr_mode > 0)) || + ((sdr_process_mode[vd_path] + > PROC_BYPASS) && + (sdr_process_mode[vd_path] + != PROC_OFF) && + (sdr_mode == 0))) { + null_vf_cnt[vd_path] = 0; + pr_csc(4, "vd%d: sdr_mode changed\n", + vd_path + 1); + } + } + } + if (!is_dolby_vision_enable() && + get_hdr_policy() != cur_hdr_policy) { + null_vf_cnt[vd_path] = 1; + toggle_frame = 1; + } else if (!is_video_layer_on(vd_path) && + (video_process_status[vd_path] + == HDR_MODULE_ON)) { + null_vf_cnt[vd_path] = 1; + toggle_frame = 1; + } else if (csc_en & 0x10) { + toggle_frame = null_vf_max; + } else { + toggle_frame = 0; } - if (null_vf_cnt[vd_path] == toggle_frame) { - pr_csc(8, - "vd%d: %d %d Fake SDR frame%s, dolby on=%d, dolby policy =%d\n", - vd_path + 1, - null_vf_cnt[vd_path], - toggle_frame, - is_video_layer_on(vd_path) ? - " " : ", video off", - is_dolby_vision_on(), - get_dolby_vision_policy()); - video_process_status[vd_path] = HDR_MODULE_OFF; - if ((get_dolby_vision_policy() != 0) || - (!is_dolby_vision_on())) { - /*send a faked vframe to switch matrix*/ - /*from 2020 to 601 when video disabled */ + if (null_vf_cnt[vd_path] == 0) { + /* video on */ + video_process_flags[vd_path] |= + PROC_FLAG_FORCE_PROCESS; + return 0; + } + /* video off */ + if (is_dolby_vision_enable()) { + /* dolby enable */ + pr_csc(8, + "vd%d: %d %d Fake SDR frame%s, dolby on=%d, dolby policy =%d\n", + vd_path + 1, + null_vf_cnt[vd_path], + toggle_frame, + is_video_layer_on(vd_path) ? + " " : ", video off", + is_dolby_vision_on(), + get_dolby_vision_policy()); + if (vd_path == VD2_PATH || + (vd_path == VD1_PATH && + (get_dolby_vision_policy() != + DOLBY_VISION_FOLLOW_SINK || + get_source_type(VD1_PATH) == + HDRTYPE_HDR10PLUS || + get_source_type(VD1_PATH) + == HDRTYPE_HLG))) { + /* and VD1 adaptive or VD2 */ + /* or always hdr hdr+/hlg bypass */ + /* faked vframe to switch matrix */ + /* 2020 to 601 when video disabled */ + /* and bypass hdr module for dv core*/ + send_fake_frame = true; + video_process_status[vd_path] = + HDR_MODULE_OFF; + } + } else { + /* dolby disable */ + pr_csc(8, + "vd%d: %d %d Fake SDR frame%s, policy =%d\n", + vd_path + 1, + null_vf_cnt[vd_path], + toggle_frame, + is_video_layer_on(vd_path) ? + " " : ", video off", + get_hdr_policy()); + send_fake_frame = true; + if (get_hdr_policy() == 1) { + /* adaptive hdr */ + /* faked vframe to switch matrix */ + /* turn off hdr module */ + video_process_status[vd_path] = + HDR_MODULE_OFF; + } else { + /* always hdr */ + /* faked vframe to switch matrix */ + /* hdr module to handle osd */ + video_process_status[vd_path] = + HDR_MODULE_ON; + } + } + + if (send_fake_frame) { fake_vframe.source_type = VFRAME_SOURCE_TYPE_OTHERS; fake_vframe.signal_type = 0; @@ -7225,23 +7533,25 @@ int amvecm_matrix_process( fake_vframe.prop. master_display_colour.present_flag = 0x80000000; - if (null_vf_cnt[vd_path] == toggle_frame) - vpp_matrix_update( - &fake_vframe, vinfo, - CSC_FLAG_TOGGLE_FRAME, vd_path); - else if (null_vf_cnt[vd_path] == 0) - vpp_matrix_update( - &fake_vframe, vinfo, - CSC_FLAG_CHECK_OUTPUT, vd_path); + vpp_matrix_update( + &fake_vframe, vinfo, + CSC_FLAG_TOGGLE_FRAME, vd_path); + last_vf[vd_path] = NULL; + null_vf_cnt[vd_path] = null_vf_max + 1; + fg_vf_sw_dbg = 4; + dbg_vf = NULL; + video_process_status[vd_path] = + HDR_MODULE_BYPASS; + pr_csc(4, + "video_process_status[%s] = HDR_MODULE_BYPASS\n", + vd_path == VD1_PATH ? "VD1" : "VD2"); + if ((vd_path == VD2_PATH) && + (is_video_layer_on(VD1_PATH) || + video_layer_wait_on[VD1_PATH])) + video_process_flags[VD1_PATH] |= + PROC_FLAG_FORCE_PROCESS; } - last_vf[vd_path] = NULL; - null_vf_cnt[vd_path] = null_vf_max; - fg_vf_sw_dbg = 4; - dbg_vf = NULL; - video_process_status[vd_path] = HDR_MODULE_BYPASS; } - if (null_vf_cnt[vd_path] <= null_vf_max) - null_vf_cnt[vd_path]++; } return 0; } diff --git a/drivers/amlogic/media/enhancement/amvecm/amcsc.h b/drivers/amlogic/media/enhancement/amvecm/amcsc.h index 3dd6a85..b63ed64 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amcsc.h +++ b/drivers/amlogic/media/enhancement/amvecm/amcsc.h @@ -101,6 +101,12 @@ enum output_format_e { #define HDR_SUPPORT (1 << 2) #define HLG_SUPPORT (1 << 3) +bool is_vinfo_available(const struct vinfo_s *vinfo); +int is_sink_cap_changed(const struct vinfo_s *vinfo, + int *p_current_hdr_cap, + int *p_current_sink_available); +int is_video_turn_on(bool *vd_on, enum vd_path_e vd_path); + #define SIG_CS_CHG 0x01 #define SIG_SRC_CHG 0x02 #define SIG_PRI_INFO 0x04 @@ -132,6 +138,9 @@ extern int video_rgb_ogo_xvy_mtx; extern int tx_op_color_primary; extern uint cur_csc_type[VD_PATH_MAX]; +int get_hdr_policy(void); +enum output_format_e get_force_output(void); + /* 0: hdr->hdr, 1:hdr->sdr, 2:hdr->hlg */ extern uint hdr_process_mode[VD_PATH_MAX]; extern uint cur_hdr_process_mode[VD_PATH_MAX]; @@ -158,6 +167,10 @@ extern int amvecm_hdr_dbg(u32 sel); extern u32 get_video_enabled(void); extern u32 get_videopip_enabled(void); + +void set_video_mute(bool on); +int get_video_mute(void); + extern void get_hdr_source_type(void); extern void get_cur_vd_signal_type(enum vd_path_e vd_path); extern enum color_primary_e get_color_primary(void); diff --git a/drivers/amlogic/media/enhancement/amvecm/amcsc_pip.c b/drivers/amlogic/media/enhancement/amvecm/amcsc_pip.c index ff5f23b..17a907b 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amcsc_pip.c +++ b/drivers/amlogic/media/enhancement/amvecm/amcsc_pip.c @@ -23,12 +23,6 @@ #include "set_hdr2_v0.h" #include "hdr/am_hdr10_plus.h" -/* 0: follow sink, 1: follow source */ -static uint hdr_policy = 1; -module_param(hdr_policy, uint, 0664); -MODULE_PARM_DESC(hdr_policy, "\n hdr policy\n"); - -static uint cur_hdr_policy; static enum output_format_e target_format[VD_PATH_MAX]; static enum hdr_type_e cur_source_format[VD_PATH_MAX]; static enum output_format_e output_format; @@ -125,8 +119,10 @@ int hdr_policy_process( int change_flag = 0; enum vd_path_e oth_path = (vd_path == VD1_PATH) ? VD2_PATH : VD1_PATH; + int cur_hdr_policy; int dv_policy = 0; int dv_mode = 0; + int dv_format = 0; bool hdr10_plus_support = (vinfo->hdr_info.hdr10plus_info.ieeeoui == HDR_PLUS_IEEE_OUI) && @@ -135,37 +131,53 @@ int hdr_policy_process( tx_hdr10_plus_support = hdr10_plus_support; - cur_hdr_policy = hdr_policy; + cur_hdr_policy = get_hdr_policy(); if (is_dolby_vision_enable()) { /* sync hdr_policy with dolby_vision_policy */ /* get current dolby_vision_mode */ dv_policy = get_dolby_vision_policy(); dv_mode = get_dolby_vision_mode(); - if ((dv_policy != DOLBY_VISION_FORCE_OUTPUT_MODE) - || (dv_mode != DOLBY_VISION_OUTPUT_MODE_BYPASS)) { - /* use dv policy when not force bypass */ - cur_hdr_policy = dv_policy; - } + dv_format = get_dolby_vision_src_format(); } - if ((get_hdr_module_status(vd_path) != HDR_MODULE_ON) - && is_dolby_vision_enable()) { + if (get_hdr_module_status(vd_path) != HDR_MODULE_ON) { + /* hdr module off or bypass */ sdr_process_mode[vd_path] = PROC_BYPASS; hdr_process_mode[vd_path] = PROC_BYPASS; hlg_process_mode[vd_path] = PROC_BYPASS; hdr10_plus_process_mode[vd_path] = PROC_BYPASS; target_format[vd_path] = BT709; } else if (cur_hdr_policy == 0) { - if ((vd_path == VD1_PATH) - && (source_format[vd_path] == HDRTYPE_HLG) - && (vinfo->hdr_info.hdr_support & HLG_SUPPORT)) { + if (vd_path == VD1_PATH && + is_dolby_vision_enable() && + !is_dolby_vision_on() && + (source_format[vd_path] + == HDRTYPE_DOVI || + source_format[vd_path] + == HDRTYPE_HDR10 || + source_format[vd_path] + == HDRTYPE_SDR)) { + /* vd1 follow sink: dv handle sdr/hdr/dovi */ + sdr_process_mode[vd_path] = PROC_BYPASS; + hdr_process_mode[vd_path] = PROC_BYPASS; + hlg_process_mode[vd_path] = PROC_BYPASS; + hdr10_plus_process_mode[vd_path] = PROC_BYPASS; + target_format[vd_path] = BT709; + set_hdr_module_status(vd_path, HDR_MODULE_OFF); + dolby_vision_set_toggle_flag(1); + } else if ((vd_path == VD1_PATH) && + (source_format[vd_path] + == HDRTYPE_HLG) && + (vinfo->hdr_info.hdr_support + & HLG_SUPPORT)) { /* vd1 bypass hlg */ hlg_process_mode[vd_path] = PROC_BYPASS; target_format[vd_path] = BT2020_HLG; - } else if ((vd_path == VD1_PATH) - && (!is_video_layer_on(VD2_PATH)) - && (source_format[vd_path] == HDRTYPE_HDR10PLUS) - && hdr10_plus_support) { + } else if ((vd_path == VD1_PATH) && + (!is_video_layer_on(VD2_PATH)) && + (source_format[vd_path] + == HDRTYPE_HDR10PLUS) && + hdr10_plus_support) { /* vd1 bypass hdr+ when vd2 off */ hdr10_plus_process_mode[vd_path] = PROC_BYPASS; target_format[vd_path] = BT2020_PQ_DYNAMIC; @@ -176,8 +188,8 @@ int hdr_policy_process( sdr_process_mode[vd_path] = PROC_MATCH; hdr10_plus_process_mode[vd_path] = PROC_MATCH; target_format[vd_path] = BT2100_IPT; - } else if ((vd_path == VD2_PATH) - && is_video_layer_on(VD1_PATH)) { + } else if ((vd_path == VD2_PATH) && + is_video_layer_on(VD1_PATH)) { /* vd1 on and vd2 follow vd1 output */ if (target_format[VD1_PATH] == BT2020_HLG) { /* vd2 *->hlg when vd1 output hlg */ @@ -188,7 +200,8 @@ int hdr_policy_process( PROC_HDRP_TO_HLG; target_format[vd_path] = BT2020_HLG; } else if ((target_format[VD1_PATH] == BT2020_PQ) || - (target_format[VD1_PATH] == BT2020_PQ_DYNAMIC)) { + (target_format[VD1_PATH] + == BT2020_PQ_DYNAMIC)) { /* vd2 *->hdr when vd1 output hdr/hdr+ */ sdr_process_mode[vd_path] = PROC_SDR_TO_HDR; hdr_process_mode[vd_path] = PROC_BYPASS; @@ -209,10 +222,10 @@ int hdr_policy_process( else target_format[vd_path] = BT709; } - } else if ((vinfo->hdr_info.hdr_support & HDR_SUPPORT) - && ((source_format[vd_path] != HDRTYPE_HLG) - || ((source_format[vd_path] == HDRTYPE_HLG) - && (hdr_flag & 0x10)))) { + } else if ((vinfo->hdr_info.hdr_support & HDR_SUPPORT) && + ((source_format[vd_path] != HDRTYPE_HLG) || + ((source_format[vd_path] == HDRTYPE_HLG) && + (hdr_flag & 0x10)))) { /* *->hdr */ sdr_process_mode[vd_path] = PROC_SDR_TO_HDR; hdr_process_mode[vd_path] = PROC_BYPASS; @@ -227,10 +240,11 @@ int hdr_policy_process( hlg_process_mode[vd_path] = PROC_HLG_TO_SDR; hdr10_plus_process_mode[vd_path] = PROC_HDRP_TO_SDR; -#if 0 +#ifdef AMCSC_DEBUG_TEST if ((vinfo->hdr_info.colorimetry_support & SINK_SUPPORTS_BT2020) && - (source_format[vd_path] == HDRTYPE_HLG) && + ((source_format[vd_path] == HDRTYPE_HLG) || + (source_format[vd_path] == HDRTYPE_HDR10)) && !is_video_layer_on(oth_path)) target_format[vd_path] = BT2020; else @@ -240,14 +254,28 @@ int hdr_policy_process( #endif } } else if (cur_hdr_policy == 1) { - if ((vd_path == VD2_PATH) && is_dolby_vision_on()) { + if (vd_path == VD1_PATH && + is_dolby_vision_enable() && + !is_dolby_vision_on() && + source_format[vd_path] + == HDRTYPE_DOVI) { + /* vd1 follow source: dv handle dovi */ + sdr_process_mode[vd_path] = PROC_BYPASS; + hdr_process_mode[vd_path] = PROC_BYPASS; + hlg_process_mode[vd_path] = PROC_BYPASS; + hdr10_plus_process_mode[vd_path] = PROC_BYPASS; + target_format[vd_path] = BT709; + set_hdr_module_status(vd_path, HDR_MODULE_OFF); + dolby_vision_set_toggle_flag(1); + } else if ((vd_path == VD2_PATH) && is_dolby_vision_on()) { /* VD2 with VD1 in DV mode */ hdr_process_mode[vd_path] = PROC_MATCH; hlg_process_mode[vd_path] = PROC_MATCH; sdr_process_mode[vd_path] = PROC_MATCH; /* *->ipt */ target_format[vd_path] = BT2100_IPT; - } else if ((vd_path == VD1_PATH) - || ((vd_path == VD2_PATH) && !is_video_layer_on(VD1_PATH))) { + } else if ((vd_path == VD1_PATH) || + ((vd_path == VD2_PATH) && + !is_video_layer_on(VD1_PATH))) { /* VD1(with/without VD2) */ /* or VD2(without VD1) <= should switch to VD1 */ switch (source_format[vd_path]) { @@ -314,7 +342,7 @@ int hdr_policy_process( /* hlg->sdr */ hlg_process_mode[vd_path] = PROC_HLG_TO_SDR; -#if 0 +#ifdef AMCSC_DEBUG_TEST if ((vinfo->hdr_info.colorimetry_support & SINK_SUPPORTS_BT2020) && !is_video_layer_on(oth_path)) @@ -347,8 +375,17 @@ int hdr_policy_process( /* hdr ->sdr */ hdr_process_mode[vd_path] = PROC_HDR_TO_SDR; +#ifdef AMCSC_DEBUG_TEST + if ((vinfo->hdr_info.colorimetry_support + & SINK_SUPPORTS_BT2020) && + !is_video_layer_on(oth_path)) + target_format[vd_path] = + BT2020; + else +#else target_format[vd_path] = BT709; +#endif } break; case HDRTYPE_HDR10PLUS: @@ -376,7 +413,17 @@ int hdr_policy_process( /* hdr+ *->sdr */ hdr10_plus_process_mode[vd_path] = PROC_HDRP_TO_SDR; - target_format[vd_path] = BT709; +#ifdef AMCSC_DEBUG_TEST + if ((vinfo->hdr_info.colorimetry_support + & SINK_SUPPORTS_BT2020) && + !is_video_layer_on(oth_path)) + target_format[vd_path] = + BT2020; + else +#else + target_format[vd_path] = + BT709; +#endif } break; default: @@ -501,12 +548,182 @@ int hdr_policy_process( } } } - } else if (cur_hdr_policy == 2) { - /* *->ipt */ - hdr_process_mode[vd_path] = PROC_MATCH; - hlg_process_mode[vd_path] = PROC_MATCH; - sdr_process_mode[vd_path] = PROC_MATCH; - target_format[vd_path] = BT2100_IPT; + } else if (cur_hdr_policy == 2 && + !is_dolby_vision_enable()) { + /* dv off, and policy == debug */ + /* *->force_output */ + if ((vd_path == VD1_PATH) || + ((vd_path == VD2_PATH) && + !is_video_layer_on(VD1_PATH))) { + /* VD1 or VD2 without VD1 */ + target_format[vd_path] = get_force_output(); + switch (target_format[vd_path]) { + case BT709: + sdr_process_mode[vd_path] = + PROC_BYPASS; + hlg_process_mode[vd_path] = + PROC_HLG_TO_SDR; + hdr_process_mode[vd_path] = + PROC_HDR_TO_SDR; + hdr10_plus_process_mode[vd_path] + = PROC_HDRP_TO_SDR; + break; + case BT2020: + break; + case BT2020_PQ: + sdr_process_mode[vd_path] = + PROC_SDR_TO_HDR; + hlg_process_mode[vd_path] = + PROC_HLG_TO_HDR; + hdr_process_mode[vd_path] = + PROC_BYPASS; + hdr10_plus_process_mode[vd_path] + = PROC_HDRP_TO_HDR; + break; + case BT2020_PQ_DYNAMIC: + sdr_process_mode[vd_path] = + PROC_SDR_TO_HDR; + hlg_process_mode[vd_path] = + PROC_HLG_TO_HDR; + hdr_process_mode[vd_path] = + PROC_BYPASS; + hdr10_plus_process_mode[vd_path] = + PROC_BYPASS; + break; + case BT2020_HLG: + sdr_process_mode[vd_path] = + PROC_SDR_TO_HLG; + hlg_process_mode[vd_path] = + PROC_BYPASS; + hdr_process_mode[vd_path] = + PROC_HDR_TO_HLG; + hdr10_plus_process_mode[vd_path] + = PROC_HDRP_TO_HLG; + break; + case BT2100_IPT: + /* hdr module not handle dv output */ + default: + break; + } + } else { + /* VD2 with VD1 on */ + if (is_dolby_vision_on()) { + /* VD1 is dolby vision */ + hdr_process_mode[vd_path] = PROC_MATCH; + hlg_process_mode[vd_path] = PROC_MATCH; + sdr_process_mode[vd_path] = PROC_MATCH; + target_format[vd_path] = BT2100_IPT; + } else { + oth_path = VD1_PATH; + switch (source_format[vd_path]) { + case HDRTYPE_SDR: + /* VD2 source SDR */ + if ((target_format[oth_path] == + BT2020_PQ) || + (target_format[oth_path] == + BT2020_PQ_DYNAMIC)) { + /* other layer output HDR */ + /* sdr *->hdr */ + sdr_process_mode[vd_path] = + PROC_SDR_TO_HDR; + target_format[vd_path] = + BT2020_PQ; + } else if (target_format[oth_path] == + BT2020_HLG) { + /* other layer on and not sdr */ + /* sdr *->hlg */ + sdr_process_mode[vd_path] = + PROC_SDR_TO_HLG; + target_format[vd_path] = + BT2020_HLG; + } else { + /* sdr->sdr */ + sdr_process_mode[vd_path] = + PROC_BYPASS; + target_format[vd_path] = BT709; + } + break; + case HDRTYPE_HLG: + /* VD2 source HLG */ + if (target_format[oth_path] + == BT2020_HLG) { + /* hlg->hlg */ + hlg_process_mode[vd_path] = + PROC_BYPASS; + target_format[vd_path] = + BT2020_HLG; + } else if ((target_format[oth_path] == + BT2020_PQ) || + (target_format[oth_path] == + BT2020_PQ_DYNAMIC)) { + /* hlg->hdr */ + hlg_process_mode[vd_path] = + PROC_HLG_TO_HDR; + target_format[vd_path] = + BT2020_PQ; + } else if (target_format[oth_path] == + BT709) { + /* hlg->sdr */ + hlg_process_mode[vd_path] = + PROC_HLG_TO_SDR; + target_format[vd_path] = BT709; + } + break; + case HDRTYPE_HDR10: + /* VD2 source HDR10 */ + if ((target_format[oth_path] == + BT2020_PQ) || + (target_format[oth_path] == + BT2020_PQ_DYNAMIC)) { + /* hdr->hdr */ + hdr_process_mode[vd_path] = + PROC_BYPASS; + target_format[vd_path] = + BT2020_PQ; + } else if (target_format[oth_path] + == BT2020_HLG) { + /* hdr->hlg */ + hdr_process_mode[vd_path] = + PROC_HDR_TO_HLG; + target_format[vd_path] = + BT2020_HLG; + } else { + /* hdr->sdr */ + hdr_process_mode[vd_path] = + PROC_HDR_TO_SDR; + target_format[vd_path] = BT709; + } + break; + case HDRTYPE_HDR10PLUS: + /* VD2 source HDR10+ */ + if ((target_format[oth_path] == + BT2020_PQ) || + (target_format[oth_path] == + BT2020_PQ_DYNAMIC)) { + /* hdr->hdr */ + hdr10_plus_process_mode[vd_path] + = PROC_HDRP_TO_HDR; + target_format[vd_path] = + BT2020_PQ; + } else if (target_format[oth_path] + == BT2020_HLG) { + /* hdr->hlg */ + hdr_process_mode[vd_path] = + PROC_HDR_TO_HLG; + target_format[vd_path] = + BT2020_HLG; + } else { + /* hdr->sdr */ + hdr10_plus_process_mode[vd_path] + = PROC_HDRP_TO_SDR; + target_format[vd_path] = BT709; + } + break; + default: + break; + } + } + } } /* update change flags */ @@ -515,7 +732,7 @@ int hdr_policy_process( pr_csc(4, "am_vecm: vd%d: (%s) %s->%s.\n", vd_path + 1, policy_str[dv_policy], - input_str[get_dolby_vision_src_format()], + input_str[dv_format], dv_output_str[dv_mode]); } else { if (cur_hdr10_plus_process_mode[vd_path] @@ -545,19 +762,19 @@ int hdr_policy_process( } cur_source_format[vd_path] = source_format[vd_path]; - if (is_dolby_vision_on() - && (vd_path == VD2_PATH) - && is_video_layer_on(VD2_PATH) - && (target_format[vd_path] != BT2100_IPT)) { + if (is_dolby_vision_on() && + (vd_path == VD2_PATH) && + is_video_layer_on(VD2_PATH) && + (target_format[vd_path] != BT2100_IPT)) { pr_csc(4, "am_vecm: vd%d output mode not match to dolby %s.\n", vd_path + 1, output_str[target_format[vd_path]]); change_flag |= SIG_OUTPUT_MODE_CHG; - } else if (!is_dolby_vision_on() - && is_video_layer_on(VD1_PATH) - && is_video_layer_on(VD2_PATH) - && (target_format[vd_path] - != target_format[oth_path])) { + } else if (!is_dolby_vision_on() && + is_video_layer_on(VD1_PATH) && + is_video_layer_on(VD2_PATH) && + (target_format[vd_path] + != target_format[oth_path])) { pr_csc(4, "am_vecm: vd%d output mode not match %s %s.\n", vd_path + 1, output_str[target_format[vd_path]], @@ -767,7 +984,22 @@ void video_post_process( struct vinfo_s *vinfo, enum vd_path_e vd_path) { - switch (cur_source_format[vd_path]) { + enum hdr_type_e src_format = cur_source_format[vd_path]; + + if (get_hdr_module_status(vd_path) == HDR_MODULE_OFF) { + if (vd_path == VD1_PATH) + hdr_proc(VD1_HDR, HDR_BYPASS, vinfo); + else + hdr_proc(VD2_HDR, HDR_BYPASS, vinfo); + if (((vd_path == VD1_PATH) && + !is_video_layer_on(VD2_PATH)) || + ((vd_path == VD2_PATH) && + !is_video_layer_on(VD1_PATH))) + hdr_proc(OSD1_HDR, HDR_BYPASS, vinfo); + src_format = HDRTYPE_NONE; + } + + switch (src_format) { case HDRTYPE_SDR: if (vd_path == VD2_PATH && is_dolby_vision_on()) { hdr_proc(VD2_HDR, SDR_IPT, vinfo); diff --git a/drivers/amlogic/media/enhancement/amvecm/set_hdr2_v0.c b/drivers/amlogic/media/enhancement/amvecm/set_hdr2_v0.c index 88f788a..de9f77e 100644 --- a/drivers/amlogic/media/enhancement/amvecm/set_hdr2_v0.c +++ b/drivers/amlogic/media/enhancement/amvecm/set_hdr2_v0.c @@ -2015,7 +2015,7 @@ enum hdr_process_sel hdr_func(enum hdr_module_sel module_sel, hdr_lut_param.eotf_lut[i] = eo_y_lut_sdr[i]; if (i < HDR2_CGAIN_LUT_SIZE) hdr_lut_param.cgain_lut[i] = - cgain_lut_bypass[i] - 1; + cgain_lut0[i] - 1; } hdr_lut_param.bitdepth = bit_depth; hdr_lut_param.lut_on = LUT_ON; @@ -2068,11 +2068,11 @@ enum hdr_process_sel hdr_func(enum hdr_module_sel module_sel, hdr_lut_param.eotf_lut[i] = eo_y_lut_sdr[i]; if (i < HDR2_CGAIN_LUT_SIZE) hdr_lut_param.cgain_lut[i] = - cgain_lut_bypass[i] - 1; + cgain_lut0[i] - 1; } hdr_lut_param.lut_on = LUT_ON; hdr_lut_param.bitdepth = bit_depth; - hdr_lut_param.cgain_en = LUT_OFF; + hdr_lut_param.cgain_en = LUT_ON; } else if (hdr_process_select == HLG_SDR) { for (i = 0; i < HDR2_OETF_LUT_SIZE; i++) { hdr_lut_param.oetf_lut[i] = oe_y_lut_sdr[i]; @@ -2183,7 +2183,7 @@ enum hdr_process_sel hdr_func(enum hdr_module_sel module_sel, hdr_lut_param.eotf_lut[i] = eo_y_lut_pq[i]; if (i < HDR2_CGAIN_LUT_SIZE) hdr_lut_param.cgain_lut[i] = - cgain_lut1[i] - 1; + cgain_lut0[i] - 1; } //pr_info("\t oo_gain = %lld of 512\n", // hdr_lut_param.ogain_lut[0]); diff --git a/drivers/amlogic/media/video_sink/video.c b/drivers/amlogic/media/video_sink/video.c index 506f604..eaa494a 100644 --- a/drivers/amlogic/media/video_sink/video.c +++ b/drivers/amlogic/media/video_sink/video.c @@ -6122,13 +6122,6 @@ struct vframe_s *dolby_vision_toggle_frame(struct vframe_s *vf) height_el - 1; } - if (!get_video_enabled()) { - /* when video layer off */ - /* not need to update setting */ - dolby_vision_set_toggle_flag(0); - return NULL; - }; - if (ret == 0) { /* setting generated for this frame */ /* or DOVI in bypass mode */ @@ -6181,6 +6174,74 @@ static int dolby_vision_drop_frame(void) return 0; } #endif + +static bool video_mute_on; +MODULE_PARM_DESC(video_mute_on, "\n video_mute_on\n"); +module_param(video_mute_on, bool, 0664); + +/* 0: off, 1: vpp mute 2:dv mute */ +static int video_mute_status; + +void set_video_mute(bool on) +{ + video_mute_on = on; +} +EXPORT_SYMBOL(set_video_mute); + +int get_video_mute(void) +{ + return video_mute_status; +} +EXPORT_SYMBOL(get_video_mute); + +static void check_video_mute(void) +{ + if (video_mute_on) { + if (is_dolby_vision_on()) { + /* core 3 black */ + if (video_mute_status != VIDEO_MUTE_ON_DV) { + dolby_vision_set_toggle_flag(1); + pr_info("DOLBY: check_video_mute: VIDEO_MUTE_ON_DV\n"); + } + video_mute_status = VIDEO_MUTE_ON_DV; + } else { + if (video_mute_status != VIDEO_MUTE_ON_VPP) { + /* vpp black */ + VSYNC_WR_MPEG_REG(VPP_CLIP_MISC0, + (0x0 << 20) | + (0x200 << 10) | + 0x200); + VSYNC_WR_MPEG_REG(VPP_CLIP_MISC1, + (0x0 << 20) | + (0x200 << 10) | + 0x200); + pr_info("DOLBY: check_video_mute: VIDEO_MUTE_ON_VPP\n"); + } + video_mute_status = VIDEO_MUTE_ON_VPP; + } + } else { + if (is_dolby_vision_on()) { + if (video_mute_status != VIDEO_MUTE_OFF) { + dolby_vision_set_toggle_flag(2); + pr_info("DOLBY: check_video_mute: VIDEO_MUTE_OFF dv on\n"); + } + video_mute_status = VIDEO_MUTE_OFF; + } else { + if (video_mute_status != VIDEO_MUTE_OFF) { + VSYNC_WR_MPEG_REG(VPP_CLIP_MISC0, + (0x3ff << 20) | + (0x3ff << 10) | + 0x3ff); + VSYNC_WR_MPEG_REG(VPP_CLIP_MISC1, + (0x0 << 20) | + (0x0 << 10) | 0x0); + pr_info("DOLBY: check_video_mute: VIDEO_MUTE_OFF dv off\n"); + } + video_mute_status = VIDEO_MUTE_OFF; + } + } +} + /* patch for 4k2k bandwidth issue, skiw mali and vpu mif */ static void dmc_adjust_for_mali_vpu(unsigned int width, unsigned int height, bool force_adjust) @@ -7491,8 +7552,9 @@ static irqreturn_t vsync_isr_in(int irq, void *dev_id) } else vsync_toggle_frame(cur_dispbuf, __LINE__); - if (is_dolby_vision_enable() - && is_dolby_vision_video_on()) { + if (is_dolby_vision_enable() && + is_dolby_vision_on() && + get_video_enabled()) { pause_vf = cur_dispbuf; video_pause_global = 1; } else { @@ -7653,6 +7715,8 @@ SET_FILTER: if (is_dolby_vision_enable()) { u32 frame_size = 0, h_size, v_size; u8 pps_state = 0; /* pps no change */ + static struct vframe_s *cur_dv_vf; + static u32 cur_frame_size; /* force toggle when keeping frame after playing */ if ((cur_dispbuf == &vf_local) @@ -7663,22 +7727,8 @@ SET_FILTER: dolby_vision_parse_metadata( toggle_vf, 2, false, false); dolby_vision_set_toggle_flag(1); - //pr_info("DOLBY: keep frame %p", toggle_vf); + /* pr_info("DOLBY: keep frame %p", toggle_vf); */ } -/* pause mode was moved to video display property */ -#if 0 - /* force toggle in pause mode */ - if (cur_dispbuf - && (cur_dispbuf != &vf_local) - && !toggle_vf - && is_dolby_vision_on() - && !for_dolby_vision_certification()) { - toggle_vf = cur_dispbuf; - dolby_vision_parse_metadata( - cur_dispbuf, 0, false, false); - dolby_vision_set_toggle_flag(1); - } -#endif if (cur_frame_par) { if (frame_par_ready_to_set || frame_par_force_to_set) { struct vppfilter_mode_s *vpp_filter = @@ -7720,8 +7770,28 @@ SET_FILTER: toggle_vf->compHeight : toggle_vf->height; frame_size = (h_size << 16) | v_size; } - dolby_vision_process((cur_dispbuf != &vf_local) - ? cur_dispbuf : toggle_vf, frame_size, pps_state); + + if (cur_dispbuf == &vf_local) { + if (get_video_enabled()) + toggle_vf = cur_dispbuf; + else + toggle_vf = NULL; + } + /* trigger dv process once when stop playing */ + /* because toggle_vf is not sync with video off */ + if (cur_dv_vf && !toggle_vf) + dolby_vision_set_toggle_flag(1); + + if (cur_frame_size != frame_size) { + cur_frame_size = frame_size; + if (!toggle_vf && get_video_enabled()) + toggle_vf = cur_dispbuf; + dolby_vision_set_toggle_flag(1); + } + cur_dv_vf = toggle_vf; + dolby_vision_process( + cur_dispbuf, toggle_vf, + frame_size, pps_state); dolby_vision_update_setting(); } #endif @@ -8309,6 +8379,9 @@ SET_FILTER: #if defined(PTS_LOGGING) || defined(PTS_TRACE_DEBUG) pts_trace++; #endif + + check_video_mute(); + vpp_misc_save = READ_VCBUS_REG(VPP_MISC + cur_dev->vpp_off); vpp_misc_set = vpp_misc_save; #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_VECM @@ -13339,10 +13412,11 @@ int vout_notify_callback(struct notifier_block *block, unsigned long cmd, spin_unlock_irqrestore(&lock, flags); new_vmode = vinfo->mode; #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION - pr_info("vout_notify_callback: VOUT_EVENT_MODE_CHANGE"); - /* make sure dolby policy process runs atleast once */ + pr_info("DOLBY: vout_notify_callback: VOUT_EVENT_MODE_CHANGE\n"); + /* force send hdmi pkt in dv code */ + /* to workaround pkt cleaned during hotplug */ if (is_dolby_vision_enable()) - dolby_vision_set_toggle_flag(1); + dolby_vision_set_toggle_flag(2); #endif break; case VOUT_EVENT_OSD_PREBLEND_ENABLE: diff --git a/include/linux/amlogic/media/amdolbyvision/dolby_vision.h b/include/linux/amlogic/media/amdolbyvision/dolby_vision.h index ea8fbe2..d3c4849c 100644 --- a/include/linux/amlogic/media/amdolbyvision/dolby_vision.h +++ b/include/linux/amlogic/media/amdolbyvision/dolby_vision.h @@ -22,6 +22,7 @@ #define V2_4 #include +#include #define DOLBY_VISION_OUTPUT_MODE_IPT 0 #define DOLBY_VISION_OUTPUT_MODE_IPT_TUNNEL 1 @@ -47,6 +48,11 @@ /* else bypass Dolby Vision */ #define DOLBY_VISION_FORCE_OUTPUT_MODE 2 +#define MUTE_TYPE_NONE 0 +#define MUTE_TYPE_YUV 1 +#define MUTE_TYPE_RGB 2 +#define MUTE_TYPE_IPT 3 + extern void enable_dolby_vision(int enable); extern bool is_dolby_vision_enable(void); extern bool is_dolby_vision_on(void); @@ -58,8 +64,9 @@ extern void dolby_vision_set_toggle_flag(int flag); extern int dolby_vision_wait_metadata(struct vframe_s *vf); extern int dolby_vision_pop_metadata(void); int dolby_vision_update_metadata(struct vframe_s *vf, bool drop_flag); -extern int dolby_vision_process(struct vframe_s *vf, u32 display_size, - u8 pps_state); +int dolby_vision_process( + struct vframe_s *rpt_vf, struct vframe_s *vf, + u32 display_size, u8 pps_state); extern void dolby_vision_init_receiver(void *pdev); extern void dolby_vision_vf_put(struct vframe_s *vf); extern struct vframe_s *dolby_vision_vf_peek_el(struct vframe_s *vf); @@ -104,7 +111,9 @@ extern bool is_dovi_frame(struct vframe_s *vf); extern void update_graphic_width_height(unsigned int width, unsigned int height); extern int get_dolby_vision_policy(void); +void set_dolby_vision_policy(int policy); extern int get_dolby_vision_src_format(void); extern bool is_dolby_vision_el_disable(void); extern bool is_dovi_dual_layer_frame(struct vframe_s *vf); +void dolby_vision_set_provider(char *prov_name); #endif diff --git a/include/linux/amlogic/media/video_sink/video.h b/include/linux/amlogic/media/video_sink/video.h index 640271b..eb67cde 100644 --- a/include/linux/amlogic/media/video_sink/video.h +++ b/include/linux/amlogic/media/video_sink/video.h @@ -238,6 +238,13 @@ static inline int amvideo_notifier_call_chain(unsigned long val, void *v) } #endif +/* 0: off, 1: vpp mute 2:dv mute */ +#define VIDEO_MUTE_OFF 0 +#define VIDEO_MUTE_ON_VPP 1 +#define VIDEO_MUTE_ON_DV 2 +void set_video_mute(bool on); +int get_video_mute(void); + int query_video_status(int type, int *value); u32 set_blackout_policy(int policy); u32 get_blackout_policy(void); -- 2.7.4