diff --git a/drivers/media/vout/meson_tx_connector/hdmitx/tx21/hdmitx_hw.c b/drivers/media/vout/meson_tx_connector/hdmitx/tx21/hdmitx_hw.c index 225eddb15..4f6327fe1 100644 --- a/drivers/media/vout/meson_tx_connector/hdmitx/tx21/hdmitx_hw.c +++ b/drivers/media/vout/meson_tx_connector/hdmitx/tx21/hdmitx_hw.c @@ -2311,7 +2311,7 @@ static int hdmitx_set_dispmode(struct hdmitx_hw_common *tx_hw, struct hdmi_forma static enum hdmi_tf_type hdmitx21_get_cur_hdr_st(void) { int ret; - u8 body[31] = {0}; + u8 body[32] = {0}; enum hdmi_tf_type tf_type = HDMI_NONE; enum hdmi_eotf type = HDMI_EOTF_TRADITIONAL_GAMMA_SDR; union hdmi_infoframe info; @@ -2364,7 +2364,7 @@ static bool hdmitx_vsif_en(u8 *body) static enum hdmi_tf_type hdmitx21_get_cur_dv_st(void) { int ret; - u8 body[31] = {0}; + u8 body[32] = {0}; enum hdmi_tf_type type = HDMI_NONE; union hdmi_infoframe info; /* struct hdmi_vendor_infoframe *vend = (struct hdmi_vendor_infoframe *)&info; */ @@ -2421,7 +2421,7 @@ static enum hdmi_tf_type hdmitx21_get_cur_hdr10p_st(void) { /* int ret; */ unsigned int ieee_code = 0; - u8 body[31] = {0}; + u8 body[32] = {0}; enum hdmi_tf_type type = HDMI_NONE; /* union hdmi_infoframe info; */ /* struct hdmi_vendor_infoframe *vend = (struct hdmi_vendor_infoframe *)&info; */ @@ -2449,7 +2449,7 @@ static enum hdmi_tf_type hdmitx21_get_cur_cuva_st(void) { /* int ret; */ unsigned int ieee_code = 0; - u8 body[31] = {0}; + u8 body[32] = {0}; enum hdmi_tf_type type = HDMI_NONE; int val; @@ -2478,7 +2478,7 @@ static enum hdmi_tf_type hdmitx21_get_cur_cuva_st(void) unsigned int hdmitx21_get_vendor_infoframe_ieee(void) { unsigned int ieee_code = 0; - u8 body[31] = {0}; + u8 body[32] = {0}; if (!hdmitx_vsif_en(body)) return 0; @@ -3952,22 +3952,42 @@ static enum hdmi_color_depth get_cd_from_pkt(void) return cd; } -static unsigned short get_qms_en_from_pkt(void) +static unsigned short get_vrr_en_from_pkt(enum emp_type type) { int ret; - u8 body[31]; + u8 body[32] = {0}; unsigned int next_tfr = 0; unsigned int qms_en = 0; + unsigned int game_en = 0; + unsigned int emp_en = 0; memset(body, 0, sizeof(body)); + /* game and qms use the same buff */ ret = hdmi_emp_infoframe_get(EMP_TYPE_VRR_QMS, body); if (ret <= 0) return 0; - qms_en = !!(body[10] & BIT(2)); - if (qms_en) - next_tfr = (body[12] >> 3) & 0xf; - if (qms_en && next_tfr) - return 1; + + switch (type) { + case EMP_TYPE_NONE: + /* emp enable and emp head */ + if (body[31] == 0xe0 && + body[0] == HDMI_INFOFRAME_TYPE_EMP) + emp_en = 1; + return emp_en; + case EMP_TYPE_VRR_QMS: + qms_en = !!(body[10] & BIT(2)); + if (qms_en) + next_tfr = (body[12] >> 3) & 0xf; + if (qms_en && next_tfr) + return 1; + break; + case EMP_TYPE_VRR_GAME: + game_en = !!(body[10] & BIT(0)); + return game_en; + default: + break; + } + return 0; } @@ -4278,6 +4298,8 @@ static int hdmitx21_hw_cntl_pkt(struct hdmitx_hw_common *tx_hw, u32 cmd, u8 *pkt_byte = NULL; struct emp_packet_st sbtm_emp; struct vtem_sbtm_st *sbtm_para; + struct emp_packet_st *qms_emp = NULL; + struct emp_packet_st *game_emp = NULL; if ((cmd & CMD_TYPE_MASK) != CMD_AUX_PKT_OFFSET) { HDMITX_ERROR("%s cmd[0x%x] wrong cmd type\n", __func__, cmd); @@ -4544,6 +4566,22 @@ static int hdmitx21_hw_cntl_pkt(struct hdmitx_hw_common *tx_hw, u32 cmd, sbtm_para->frmpblimitint); hdmi_emp_infoframe_set(EMP_TYPE_SBTM, &sbtm_emp); break; + case AUX_PKT_CONF_EMP_VRR_QMS: + if (!input_argv) { + hdmi_emp_infoframe_set(EMP_TYPE_VRR_QMS, NULL); + break; + } + qms_emp = (struct emp_packet_st *)(input_argv); + hdmi_emp_infoframe_set(EMP_TYPE_VRR_QMS, qms_emp); + break; + case AUX_PKT_CONF_EMP_VRR_GAME: + if (!input_argv) { + hdmi_emp_infoframe_set(EMP_TYPE_VRR_GAME, NULL); + break; + } + game_emp = (struct emp_packet_st *)(input_argv); + hdmi_emp_infoframe_set(EMP_TYPE_VRR_GAME, game_emp); + break; case AUX_PKT_AVI_CONSTRUCT: hdmitx_construct_avi_packet(hdev); break; @@ -4686,7 +4724,9 @@ static int hdmitx21_hw_cntl_vrr(struct hdmitx_hw_common *tx_hw, u32 cmd, { struct hdmitx21_dev *hdev = container_of(tx_hw, struct hdmitx21_dev, hw_comm); struct hdmitx_common *tx_comm = &hdev->tx_comm; - unsigned short tfr_en; + unsigned short qms_en; + unsigned short game_en; + unsigned short emp_en; unsigned short value_brr; u32 arg; int ret = 0; @@ -4711,8 +4751,14 @@ static int hdmitx21_hw_cntl_vrr(struct hdmitx_hw_common *tx_hw, u32 cmd, break; case QMS_GET_INFO: value_brr = (unsigned short)get_vic_from_pkt(); - tfr_en = (unsigned short)get_qms_en_from_pkt(); - return (tfr_en << 16) | value_brr; + qms_en = (unsigned short)get_vrr_en_from_pkt(EMP_TYPE_VRR_QMS); + return (qms_en << 16) | value_brr; + case GAME_GET_INFO: + game_en = (unsigned short)get_vrr_en_from_pkt(EMP_TYPE_VRR_GAME); + return game_en; + case EMP_GET_INFO: + emp_en = (unsigned short)get_vrr_en_from_pkt(EMP_TYPE_NONE); + return emp_en; default: break; } @@ -6622,7 +6668,7 @@ void hdmitx21_sw_debug_func(struct hdmitx_common *tx_comm, const char *buf) HDMITX_INFO("hdcp_delay :%d\n", value); p_hdcp->hdcp_debug_delay = value; } else if (strncmp(tmpbuf, "vrr_mode", 8) == 0) { - switch (hdev->vrr_mode) { + switch (tx_comm->vrr_mode) { case T_VRR_GAME: HDMITX_INFO("%s\n", "game-vrr"); break; diff --git a/drivers/media/vout/meson_tx_connector/hdmitx/tx21/hdmitx_hw_platform.h b/drivers/media/vout/meson_tx_connector/hdmitx/tx21/hdmitx_hw_platform.h index e5a05e92e..bd02131a1 100644 --- a/drivers/media/vout/meson_tx_connector/hdmitx/tx21/hdmitx_hw_platform.h +++ b/drivers/media/vout/meson_tx_connector/hdmitx/tx21/hdmitx_hw_platform.h @@ -79,7 +79,6 @@ struct hdmitx21_dev { /* 0: RGB444 1: Y444 2: Y422 3: Y420 */ /* 4: 24bit 5: 30bit 6: 36bit 7: 48bit */ /* if equals to 1, means current video & audio output are blank */ - enum vrr_type vrr_mode; /* 1: GAME-VRR, 2: QMS-VRR, 0: default no-VRR */ /* * debug only, should be positive value. if it is N, then vysnc_handler diff --git a/drivers/media/vout/meson_tx_connector/hdmitx/tx21/hdmitx_pktmgmt.c b/drivers/media/vout/meson_tx_connector/hdmitx/tx21/hdmitx_pktmgmt.c index 000d3f9d4..a2af32f87 100644 --- a/drivers/media/vout/meson_tx_connector/hdmitx/tx21/hdmitx_pktmgmt.c +++ b/drivers/media/vout/meson_tx_connector/hdmitx/tx21/hdmitx_pktmgmt.c @@ -107,8 +107,9 @@ static int tpi_info_get(u8 sel, u8 *data) } for (i = 0; i < 31; i++) data[i] = hdmitx21_rd_reg(TPI_INFO_B0_IVCTX + i); + data[31] = hdmitx21_rd_reg(TPI_INFO_EN_IVCTX); spin_unlock_irqrestore(&tpi_lock, flags); - return 31; /* fixed value */ + return 32; /* fixed value */ } void hdmitx_dump_infoframe_packets(struct seq_file *s) @@ -777,6 +778,7 @@ int hdmi_emp_infoframe_get(enum emp_type type, u8 *body) * EMP packets is different as other packets * no checksum, the successive packets in a video frame... */ +/* only use hw cmd send emp packet */ void hdmi_emp_infoframe_set(enum emp_type type, struct emp_packet_st *info) { u8 body[31] = {0}; diff --git a/drivers/media/vout/meson_tx_connector/hdmitx/tx21/hdmitx_vrr.c b/drivers/media/vout/meson_tx_connector/hdmitx/tx21/hdmitx_vrr.c index 2a328e9ff..b86f5fb87 100644 --- a/drivers/media/vout/meson_tx_connector/hdmitx/tx21/hdmitx_vrr.c +++ b/drivers/media/vout/meson_tx_connector/hdmitx/tx21/hdmitx_vrr.c @@ -988,13 +988,38 @@ static void vrr_init_qms_para(struct hdmitx_common *tx_comm, struct tx_vrr_param } /* when exit game-vrr or qms-vrr, the MD of EMP will be set as 0 */ -static void hdmi_vrr_disable_emp_packet(struct tx_vrr_params *para, enum vrr_type vrr_mode) +static void hdmi_vrr_disable_emp_packet(struct tx_vrr_params *para, struct hdmitx_common *tx_comm) { struct emp_packet_st *vrr_pkt; + int value; + bool emp_en; + bool qms_en; + bool game_en; + int pkt_type = 0; if (!para) return; + /* judgement the emp packet sned or not */ + emp_en = hdmitx_hw_cntl(tx_comm->tx_hw, EMP_GET_INFO, NULL, NULL); + if (!emp_en) + return; + + /* judgement the qms enable or not */ + value = hdmitx_hw_cntl(tx_comm->tx_hw, QMS_GET_INFO, NULL, NULL); + qms_en = value >> 16; + if (qms_en) { + pkt_type = AUX_PKT_CONF_EMP_VRR_QMS; + } else { + /* judgement the game enable or not */ + game_en = hdmitx_hw_cntl(tx_comm->tx_hw, GAME_GET_INFO, NULL, NULL); + if (game_en) + pkt_type = AUX_PKT_CONF_EMP_VRR_GAME; + } + /* already send emp 0 packet, do nothing */ + if (pkt_type == 0) + return; + vrr_pkt = ¶->emp_vrr_pkt; memset(vrr_pkt, 0, sizeof(*vrr_pkt)); hdmi_emp_frame_set_member(vrr_pkt, CONF_HEADER_INIT, HDMI_INFOFRAME_TYPE_EMP); @@ -1002,9 +1027,9 @@ static void hdmi_vrr_disable_emp_packet(struct tx_vrr_params *para, enum vrr_typ hdmi_emp_frame_set_member(vrr_pkt, CONF_HEADER_LAST, 1); hdmi_emp_frame_set_member(vrr_pkt, CONF_HEADER_SEQ_INDEX, 0); hdmi_emp_frame_set_member(vrr_pkt, CONF_DS_TYPE, 0); - if (vrr_mode == T_VRR_GAME) + if (tx_comm->vrr_mode == T_VRR_GAME) hdmi_emp_frame_set_member(vrr_pkt, CONF_SYNC, 0); - else if (vrr_mode == T_VRR_QMS) + else if (tx_comm->vrr_mode == T_VRR_QMS) hdmi_emp_frame_set_member(vrr_pkt, CONF_SYNC, 1); hdmi_emp_frame_set_member(vrr_pkt, CONF_VFR, 1); hdmi_emp_frame_set_member(vrr_pkt, CONF_AFR, 0); @@ -1013,7 +1038,7 @@ static void hdmi_vrr_disable_emp_packet(struct tx_vrr_params *para, enum vrr_typ hdmi_emp_frame_set_member(vrr_pkt, CONF_ORG_ID, 1); hdmi_emp_frame_set_member(vrr_pkt, CONF_DATA_SET_TAG, 1); hdmi_emp_frame_set_member(vrr_pkt, CONF_DATA_SET_LENGTH, 0); - hdmi_emp_infoframe_set(EMP_TYPE_VRR_GAME, vrr_pkt); + hdmitx_hw_cntl(tx_comm->tx_hw, pkt_type, vrr_pkt, NULL); } static void vrr_init_para(struct hdmitx_common *tx_comm, struct tx_vrr_params *para) @@ -1245,7 +1270,7 @@ int hdmitx_set_vrr_rate(struct hdmitx_hw_common *tx_hw, int _rate, void *data) return -1; } fmt_para->frac_mode = vrr_info->frac_mode; - hdev->vrr_mode = vrr_info ? vrr_info->type : T_VRR_QMS; + tx_comm->vrr_mode = vrr_info ? vrr_info->type : T_VRR_QMS; /* check current rate, should less or equal than current rate of BRR */ tmp_rate = fmt_para->timing.v_freq / 10; /* TODO, BRR mode should have frac_rate_policy as 0 */ @@ -1262,15 +1287,15 @@ int hdmitx_set_vrr_rate(struct hdmitx_hw_common *tx_hw, int _rate, void *data) */ tx_comm->hdmitx_vinfo.brr_duration = 0; memset(&vrr_para.vrr_para_tmp, 0, sizeof(vrr_para.vrr_para_tmp)); - hdmi_vrr_disable_emp_packet(&vrr_para, hdev->vrr_mode); - hdev->vrr_mode = T_VRR_NONE; + hdmi_vrr_disable_emp_packet(&vrr_para, tx_comm); + tx_comm->vrr_mode = T_VRR_NONE; hdmitx_vrr_set_maxlncnt(fmt_para->timing.v_total); HDMITX_INFO("qms: disable EMP packet\n"); return 0; } - if (hdev->vrr_mode == T_VRR_GAME || hdev->vrr_mode == T_VRR_QMS) { - para.type = hdev->vrr_mode; + if (tx_comm->vrr_mode == T_VRR_GAME || tx_comm->vrr_mode == T_VRR_QMS) { + para.type = tx_comm->vrr_mode; } else { para.vrr_enabled = 0; return 0; @@ -1329,7 +1354,7 @@ int hdmitx_set_vrr_rate(struct hdmitx_hw_common *tx_hw, int _rate, void *data) para.duration = rate; } updata_vinfo_sync_duration(&tx_comm->hdmitx_vinfo, rate, - hdev->vrr_mode == T_VRR_GAME ? 0 : fmt_para->frac_mode, + tx_comm->vrr_mode == T_VRR_GAME ? 0 : fmt_para->frac_mode, (fmt_para->timing.v_freq + 999) / 1000); para.vrr_enabled = 1; @@ -1414,7 +1439,7 @@ static void hdmitx_vrr_game_handler(struct hdmitx21_dev *hdev) vrr->game_val.vtotal_fixed = vtotal_tmp; HDMITX_DEBUG_QMS("game-vrr vtotal = %d\n", vrr->game_val.vtotal_fixed); - hdmi_emp_infoframe_set(EMP_TYPE_VRR_GAME, &vrr->emp_vrr_pkt); + hdmitx_hw_cntl(hdev->tx_comm.tx_hw, AUX_PKT_CONF_EMP_VRR_GAME, &vrr->emp_vrr_pkt, NULL); if (vrr->game_val.vtotal_fixed) hdmitx_vrr_set_maxlncnt(vrr->game_val.vtotal_fixed); vrr_cur_vtotal_debug(vrr->frame_cnt, m_const, vrr->game_val.vtotal_fixed); @@ -1455,7 +1480,7 @@ irqreturn_t hdmitx_vrr_vsync_handler(struct hdmitx21_dev *hdev) m_const = 0; hdmi_emp_frame_set_member(&vrr->emp_vrr_pkt, CONF_M_CONST, m_const); - hdmi_emp_infoframe_set(EMP_TYPE_VRR_QMS, &vrr->emp_vrr_pkt); + hdmitx_hw_cntl(tx_comm->tx_hw, AUX_PKT_CONF_EMP_VRR_QMS, &vrr->emp_vrr_pkt, NULL); vrr_cur_vtotal_debug(vrr->frame_cnt, m_const, vrr->mconst_val->vtotal_fixed); return IRQ_HANDLED; } @@ -1474,7 +1499,7 @@ irqreturn_t hdmitx_vrr_vsync_handler(struct hdmitx21_dev *hdev) m_const = 1; hdmi_emp_frame_set_member(&vrr->emp_vrr_pkt, CONF_M_CONST, m_const); - hdmi_emp_infoframe_set(EMP_TYPE_VRR_GAME, &vrr->emp_vrr_pkt); + hdmitx_hw_cntl(tx_comm->tx_hw, AUX_PKT_CONF_EMP_VRR_GAME, &vrr->emp_vrr_pkt, NULL); hdmitx_vrr_set_maxlncnt(vtotal_tmp); vrr_cur_vtotal_debug(vrr->frame_cnt, m_const, vrr->mconst_val->vtotal_fixed); /* the frame count will add 1 at end */ diff --git a/drivers/media/vout/meson_tx_connector/hdmitx_hdr.c b/drivers/media/vout/meson_tx_connector/hdmitx_hdr.c index d46ec73f2..25c3d7c8b 100644 --- a/drivers/media/vout/meson_tx_connector/hdmitx_hdr.c +++ b/drivers/media/vout/meson_tx_connector/hdmitx_hdr.c @@ -1226,6 +1226,7 @@ void hdmitx_clear_all_infoframe_pkt(struct hdmitx_common *tx_comm) arg = CLR_AVI_BT2020; hdmitx_hw_cntl(tx_hw, AUX_PKT_CONF_AVI_BT2020, (void *)&arg, NULL); hdmitx_hw_cntl(tx_hw, AUX_PKT_CLR_AVI, NULL, NULL); + hdmitx_hw_cntl(tx_hw, AUX_PKT_CONF_EMP_VRR_QMS, NULL, NULL); /* step2 SW: reset para */ tx_comm->hdr_transfer_feature = T_UNKNOWN; tx_comm->hdr_color_feature = C_UNKNOWN; @@ -1233,6 +1234,7 @@ void hdmitx_clear_all_infoframe_pkt(struct hdmitx_common *tx_comm) tx_comm->hdmi_current_hdr_mode = 0; tx_comm->hdmi_last_hdr_mode = 0; tx_comm->hdr10plus_feature = 0; + tx_comm->vrr_mode = T_VRR_NONE; /* reset hdmitx csc para */ tx_comm->in_colorimetry = 0xff; tx_comm->out_colorimetry = 0xff; diff --git a/include/linux/amlogic/media/vout/hdmitx_common/hdmitx_common.h b/include/linux/amlogic/media/vout/hdmitx_common/hdmitx_common.h index d230c2312..d09390a83 100644 --- a/include/linux/amlogic/media/vout/hdmitx_common/hdmitx_common.h +++ b/include/linux/amlogic/media/vout/hdmitx_common/hdmitx_common.h @@ -344,6 +344,8 @@ struct hdmitx_common { /* 11. vrr related*/ struct vrr_device_s hdmitx_vrr_dev; + /* 1: GAME-VRR, 2: QMS-VRR, 0: default no-VRR */ + enum vrr_type vrr_mode; /* * the qms_log_id is referred from hw_sequence_id * if value is not changed, the skip massive qms log diff --git a/include/linux/amlogic/media/vout/hdmitx_common/hdmitx_hw_common.h b/include/linux/amlogic/media/vout/hdmitx_common/hdmitx_hw_common.h index 32b75f4b6..9144e1309 100644 --- a/include/linux/amlogic/media/vout/hdmitx_common/hdmitx_hw_common.h +++ b/include/linux/amlogic/media/vout/hdmitx_common/hdmitx_hw_common.h @@ -156,6 +156,8 @@ #define AUX_PKT_GET_VSIF_ALLM (CMD_AUX_PKT_OFFSET + 0x3f) #define AUX_PKT_GET_VSIF_AMDV_SIGNAL (CMD_AUX_PKT_OFFSET + 0x40) #define AUX_PKT_GET_VSIF_AMDV_LOW_LATENCY (CMD_AUX_PKT_OFFSET + 0x41) +#define AUX_PKT_CONF_EMP_VRR_QMS (CMD_AUX_PKT_OFFSET + 0x42) +#define AUX_PKT_CONF_EMP_VRR_GAME (CMD_AUX_PKT_OFFSET + 0x43) /* Aux special for DPTX */ #define DP_AUX_CMD (CMD_AUX_PKT_OFFSET + CMD_DPTX_OFFSET + 0x0) @@ -193,6 +195,8 @@ /* 0x17 VRR */ #define VRR_REGISTER (CMD_VRR_OFFSET + 0x00) #define QMS_GET_INFO (CMD_VRR_OFFSET + 0x01) +#define GAME_GET_INFO (CMD_VRR_OFFSET + 0x02) +#define EMP_GET_INFO (CMD_VRR_OFFSET + 0x03) /* 0x18 core misc */ #define CORE_MISC_SUSPEND_RESUME_CNTL (CMD_CORE_MISC_OFFSET + 0x0)