Skip to content

Commit 27b2871

Browse files
Zheng Yangrkhuangtao
authored andcommitted
drm: bridge: dw-hdmi: Implement connector atomic_begin
To avoid screen flash when updating CSC, we introduce connector atomic_begin. Before flush crtc and connector, it's need to send AVMUTE flag to make screen black, and clear flag after CSC updated. AVMUTE -> Update CRTC -> Update HDMI -> Clear AVMUTE Change-Id: Id47caac1e25fcce5a5aa7b879da4a6b9a9bab8a1 Signed-off-by: Zheng Yang <zhengyang@rock-chips.com>
1 parent 773d508 commit 27b2871

2 files changed

Lines changed: 58 additions & 19 deletions

File tree

drivers/gpu/drm/bridge/dw-hdmi.c

Lines changed: 54 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ struct hdmi_data_info {
162162
unsigned int enc_out_encoding;
163163
unsigned int pix_repet_factor;
164164
struct hdmi_vmode video_mode;
165+
bool update;
165166
};
166167

167168
struct dw_hdmi_i2c {
@@ -2152,6 +2153,7 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
21522153
{
21532154
int ret;
21542155
void *data = hdmi->plat_data->phy_data;
2156+
bool need_delay = false;
21552157

21562158
hdmi_disable_overflow_interrupts(hdmi);
21572159

@@ -2234,6 +2236,8 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
22342236
if (ret)
22352237
return ret;
22362238
hdmi->phy.enabled = true;
2239+
} else {
2240+
need_delay = true;
22372241
}
22382242
/* HDMI Initialization Step B.3 */
22392243
dw_hdmi_enable_video_path(hdmi);
@@ -2266,6 +2270,9 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
22662270
if (hdmi->cable_plugin && hdmi->sink_is_hdmi)
22672271
hdmi_enable_overflow_interrupts(hdmi);
22682272

2273+
/* XXX: Add delay to make csc work before unmute video. */
2274+
if (need_delay)
2275+
msleep(50);
22692276
return 0;
22702277
}
22712278

@@ -2519,13 +2526,12 @@ static void dw_hdmi_connector_destroy(struct drm_connector *connector)
25192526
}
25202527

25212528
static void
2522-
dw_hdmi_connector_atomic_flush(struct drm_connector *connector,
2529+
dw_hdmi_connector_atomic_begin(struct drm_connector *connector,
25232530
struct drm_connector_state *conn_state)
25242531
{
25252532
struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi,
2526-
connector);
2533+
connector);
25272534
void *data = hdmi->plat_data->phy_data;
2528-
struct drm_display_mode *mode = NULL;
25292535
unsigned int enc_in_bus_format;
25302536
unsigned int enc_out_bus_format;
25312537
unsigned int enc_in_encoding;
@@ -2534,21 +2540,8 @@ dw_hdmi_connector_atomic_flush(struct drm_connector *connector,
25342540
if (!hdmi->hpd_state || !conn_state->crtc)
25352541
return;
25362542

2537-
DRM_DEBUG("%s\n", __func__);
2538-
2539-
/*
2540-
* If HDMI is enabled in uboot, it's need to record
2541-
* drm_display_mode and set phy status to enabled.
2542-
*/
2543-
if (!hdmi->hdmi_data.video_mode.mpixelclock) {
2544-
mode = &conn_state->crtc->mode;
2545-
memcpy(&hdmi->previous_mode, mode, sizeof(hdmi->previous_mode));
2546-
hdmi->hdmi_data.video_mode.mpixelclock = mode->clock;
2547-
hdmi->hdmi_data.video_mode.previous_pixelclock = mode->clock;
2548-
hdmi->hdmi_data.video_mode.previous_tmdsclock = mode->clock;
2549-
hdmi->phy.enabled = true;
2543+
if (!hdmi->hdmi_data.video_mode.mpixelclock)
25502544
return;
2551-
}
25522545

25532546
if (hdmi->plat_data->get_enc_in_encoding)
25542547
enc_in_encoding = hdmi->plat_data->get_enc_in_encoding(data);
@@ -2572,10 +2565,51 @@ dw_hdmi_connector_atomic_flush(struct drm_connector *connector,
25722565
if (enc_in_encoding != hdmi->hdmi_data.enc_in_encoding ||
25732566
enc_out_encoding != hdmi->hdmi_data.enc_out_encoding ||
25742567
enc_in_bus_format != hdmi->hdmi_data.enc_in_bus_format ||
2575-
enc_out_bus_format != hdmi->hdmi_data.enc_out_bus_format)
2568+
enc_out_bus_format != hdmi->hdmi_data.enc_out_bus_format) {
2569+
hdmi->hdmi_data.update = true;
2570+
hdmi_writeb(hdmi, HDMI_FC_GCP_SET_AVMUTE, HDMI_FC_GCP);
2571+
/* XXX: Add delay to make av mute work on sink*/
2572+
msleep(50);
2573+
} else {
2574+
hdmi->hdmi_data.update = false;
2575+
}
2576+
}
2577+
2578+
static void
2579+
dw_hdmi_connector_atomic_flush(struct drm_connector *connector,
2580+
struct drm_connector_state *conn_state)
2581+
{
2582+
struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi,
2583+
connector);
2584+
struct drm_display_mode *mode = NULL;
2585+
2586+
if (!hdmi->hpd_state || !conn_state->crtc)
2587+
return;
2588+
2589+
DRM_DEBUG("%s\n", __func__);
2590+
2591+
/*
2592+
* If HDMI is enabled in uboot, it's need to record
2593+
* drm_display_mode and set phy status to enabled.
2594+
*/
2595+
if (!hdmi->hdmi_data.video_mode.mpixelclock) {
2596+
mode = &conn_state->crtc->mode;
2597+
memcpy(&hdmi->previous_mode, mode, sizeof(hdmi->previous_mode));
2598+
hdmi->hdmi_data.video_mode.mpixelclock = mode->clock;
2599+
hdmi->hdmi_data.video_mode.previous_pixelclock = mode->clock;
2600+
hdmi->hdmi_data.video_mode.previous_tmdsclock = mode->clock;
2601+
hdmi->phy.enabled = true;
2602+
return;
2603+
}
2604+
2605+
if (hdmi->hdmi_data.update) {
25762606
dw_hdmi_setup(hdmi, &hdmi->previous_mode);
2577-
else if (connector->state->hdr_metadata_changed && hdmi->sink_is_hdmi)
2607+
hdmi_writeb(hdmi, HDMI_FC_GCP_CLEAR_AVMUTE, HDMI_FC_GCP);
2608+
hdmi->hdmi_data.update = false;
2609+
} else if (connector->state->hdr_metadata_changed &&
2610+
hdmi->sink_is_hdmi) {
25782611
hdmi_config_hdr_infoframe(hdmi);
2612+
}
25792613
}
25802614

25812615
static int
@@ -2668,6 +2702,7 @@ static const struct drm_connector_helper_funcs dw_hdmi_connector_helper_funcs =
26682702
.get_modes = dw_hdmi_connector_get_modes,
26692703
.mode_valid = dw_hdmi_connector_mode_valid,
26702704
.best_encoder = dw_hdmi_connector_best_encoder,
2705+
.atomic_begin = dw_hdmi_connector_atomic_begin,
26712706
.atomic_flush = dw_hdmi_connector_atomic_flush,
26722707
};
26732708

drivers/gpu/drm/bridge/dw-hdmi.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -909,6 +909,10 @@ enum {
909909
HDMI_FC_AVICONF3_QUANT_RANGE_LIMITED = 0x00,
910910
HDMI_FC_AVICONF3_QUANT_RANGE_FULL = 0x04,
911911

912+
/* HDMI_FC_GCP */
913+
HDMI_FC_GCP_SET_AVMUTE = 0x2,
914+
HDMI_FC_GCP_CLEAR_AVMUTE = 0x1,
915+
912916
/* FC_DBGFORCE field values */
913917
HDMI_FC_DBGFORCE_FORCEAUDIO = 0x10,
914918
HDMI_FC_DBGFORCE_FORCEVIDEO = 0x1,

0 commit comments

Comments
 (0)