hdmitx: don't send emp packet [1/1]

PD#SWPL-209441

Problem:
send emp packet when TV not support qms vrr

Solution:
don't send emp packet when TV not support qms vrr

Verify:
s7d

Test:
DRM-TX-

Change-Id: I6f76ec092632c6958449d0a0bce070c188d59aa9
Signed-off-by: Wenjie Qiao <wenjie.qiao@amlogic.com>
This commit is contained in:
Wenjie Qiao
2025-05-16 06:40:22 +00:00
committed by gerrit autosubmit
parent 84e54f4772
commit cdf5fe98cc
7 changed files with 111 additions and 31 deletions
@@ -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;
@@ -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
@@ -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};
@@ -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 = &para->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 */
@@ -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;
@@ -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
@@ -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)