2024-06-11 16:02:41

by Jonas Karlman

[permalink] [raw]
Subject: [PATCH 0/8] drm: bridge: dw_hdmi: Misc enable/disable, CEC and EDID cleanup

This series ensure poweron/poweroff and CEC phys addr invalidation is
happening under drm mode_config mutex lock, and also ensure EDID is
updated (when the dw-hdmi connector is used) after a hotplug pulse.

These changes has mainly been tested on Rockchip devices together with a
forthcoming series that add HDMI 2.0 4K@60Hz support to RK3228, RK3328,
RK3399 and RK3568.

Rockchip use the dw-hdmi connector so this should also be validated with
a driver that use the bridge connector.

Jonas Karlman (8):
drm: bridge: dw_hdmi: Call poweron/poweroff from atomic enable/disable
drm: bridge: dw_hdmi: Use passed mode instead of stored previous_mode
drm: bridge: dw_hdmi: Fold poweron and setup functions
drm: bridge: dw_hdmi: Remove previous_mode and mode_set
drm: bridge: dw_hdmi: Invalidate CEC phys addr from connector detect
drm: bridge: dw_hdmi: Remove cec_notifier_mutex
drm: bridge: dw_hdmi: Update EDID during hotplug processing
drm: bridge: dw_hdmi: Use display_info is_hdmi and has_audio

drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 145 ++++++----------------
1 file changed, 39 insertions(+), 106 deletions(-)

--
2.45.2



2024-06-11 16:04:05

by Jonas Karlman

[permalink] [raw]
Subject: [PATCH 2/8] drm: bridge: dw_hdmi: Use passed mode instead of stored previous_mode

Use the passed mode instead of mixing use of passed mode and the stored
previous_mode. The passed mode is currenly always the previous_mode.

Also fix a small type and add a variable to help shorten a code line.

Signed-off-by: Jonas Karlman <[email protected]>
---
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index 34bc6f4754b8..ce4d4d06f758 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -2241,6 +2241,7 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi,
const struct drm_connector *connector,
const struct drm_display_mode *mode)
{
+ const struct drm_display_info *display = &connector->display_info;
int ret;

hdmi_disable_overflow_interrupts(hdmi);
@@ -2286,12 +2287,10 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi,
hdmi->hdmi_data.video_mode.mdataenablepolarity = true;

/* HDMI Initialization Step B.1 */
- hdmi_av_composer(hdmi, &connector->display_info, mode);
+ hdmi_av_composer(hdmi, display, mode);

- /* HDMI Initializateion Step B.2 */
- ret = hdmi->phy.ops->init(hdmi, hdmi->phy.data,
- &connector->display_info,
- &hdmi->previous_mode);
+ /* HDMI Initialization Step B.2 */
+ ret = hdmi->phy.ops->init(hdmi, hdmi->phy.data, display, mode);
if (ret)
return ret;
hdmi->phy.enabled = true;
--
2.45.2


2024-06-11 16:04:45

by Jonas Karlman

[permalink] [raw]
Subject: [PATCH 1/8] drm: bridge: dw_hdmi: Call poweron/poweroff from atomic enable/disable

Change to only call poweron/poweroff from atomic_enable/atomic_disable
ops instead of trying to keep a bridge_is_on state and poweron/off in
the hotplug irq handler.

A benefit of this is that drm mode_config mutex is always held at
poweron/off, something that may reduce the need for our own mutex.

Signed-off-by: Jonas Karlman <[email protected]>
---
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 33 ++---------------------
1 file changed, 2 insertions(+), 31 deletions(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index 9f2bc932c371..34bc6f4754b8 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -172,7 +172,6 @@ struct dw_hdmi {
enum drm_connector_force force; /* mutex-protected force state */
struct drm_connector *curr_conn;/* current connector (only valid when !disabled) */
bool disabled; /* DRM has disabled our bridge */
- bool bridge_is_on; /* indicates the bridge is on */
bool rxsense; /* rxsense state */
u8 phy_mask; /* desired phy int mask settings */
u8 mc_clkdis; /* clock disable register */
@@ -2383,8 +2382,6 @@ static void initialize_hdmi_ih_mutes(struct dw_hdmi *hdmi)

static void dw_hdmi_poweron(struct dw_hdmi *hdmi)
{
- hdmi->bridge_is_on = true;
-
/*
* The curr_conn field is guaranteed to be valid here, as this function
* is only be called when !hdmi->disabled.
@@ -2398,30 +2395,6 @@ static void dw_hdmi_poweroff(struct dw_hdmi *hdmi)
hdmi->phy.ops->disable(hdmi, hdmi->phy.data);
hdmi->phy.enabled = false;
}
-
- hdmi->bridge_is_on = false;
-}
-
-static void dw_hdmi_update_power(struct dw_hdmi *hdmi)
-{
- int force = hdmi->force;
-
- if (hdmi->disabled) {
- force = DRM_FORCE_OFF;
- } else if (force == DRM_FORCE_UNSPECIFIED) {
- if (hdmi->rxsense)
- force = DRM_FORCE_ON;
- else
- force = DRM_FORCE_OFF;
- }
-
- if (force == DRM_FORCE_OFF) {
- if (hdmi->bridge_is_on)
- dw_hdmi_poweroff(hdmi);
- } else {
- if (!hdmi->bridge_is_on)
- dw_hdmi_poweron(hdmi);
- }
}

/*
@@ -2546,7 +2519,6 @@ static void dw_hdmi_connector_force(struct drm_connector *connector)

mutex_lock(&hdmi->mutex);
hdmi->force = connector->force;
- dw_hdmi_update_power(hdmi);
dw_hdmi_update_phy_mask(hdmi);
mutex_unlock(&hdmi->mutex);
}
@@ -2955,7 +2927,7 @@ static void dw_hdmi_bridge_atomic_disable(struct drm_bridge *bridge,
mutex_lock(&hdmi->mutex);
hdmi->disabled = true;
hdmi->curr_conn = NULL;
- dw_hdmi_update_power(hdmi);
+ dw_hdmi_poweroff(hdmi);
dw_hdmi_update_phy_mask(hdmi);
handle_plugged_change(hdmi, false);
mutex_unlock(&hdmi->mutex);
@@ -2974,7 +2946,7 @@ static void dw_hdmi_bridge_atomic_enable(struct drm_bridge *bridge,
mutex_lock(&hdmi->mutex);
hdmi->disabled = false;
hdmi->curr_conn = connector;
- dw_hdmi_update_power(hdmi);
+ dw_hdmi_poweron(hdmi);
dw_hdmi_update_phy_mask(hdmi);
handle_plugged_change(hdmi, true);
mutex_unlock(&hdmi->mutex);
@@ -3073,7 +3045,6 @@ void dw_hdmi_setup_rx_sense(struct dw_hdmi *hdmi, bool hpd, bool rx_sense)
if (hpd)
hdmi->rxsense = true;

- dw_hdmi_update_power(hdmi);
dw_hdmi_update_phy_mask(hdmi);
}
mutex_unlock(&hdmi->mutex);
--
2.45.2


2024-06-11 16:08:04

by Jonas Karlman

[permalink] [raw]
Subject: [PATCH 3/8] drm: bridge: dw_hdmi: Fold poweron and setup functions

Fold the poweron and setup functions into one function and use the
adjusted_mode directly from the new crtc_state to remove the need of
storing previous_mode.

Signed-off-by: Jonas Karlman <[email protected]>
---
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 21 ++++++++-------------
1 file changed, 8 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index ce4d4d06f758..76048fc9fd14 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -2237,9 +2237,9 @@ static void hdmi_disable_overflow_interrupts(struct dw_hdmi *hdmi)
HDMI_IH_MUTE_FC_STAT2);
}

-static int dw_hdmi_setup(struct dw_hdmi *hdmi,
- const struct drm_connector *connector,
- const struct drm_display_mode *mode)
+static int dw_hdmi_poweron(struct dw_hdmi *hdmi,
+ const struct drm_connector *connector,
+ const struct drm_display_mode *mode)
{
const struct drm_display_info *display = &connector->display_info;
int ret;
@@ -2379,15 +2379,6 @@ static void initialize_hdmi_ih_mutes(struct dw_hdmi *hdmi)
hdmi_writeb(hdmi, ih_mute, HDMI_IH_MUTE);
}

-static void dw_hdmi_poweron(struct dw_hdmi *hdmi)
-{
- /*
- * The curr_conn field is guaranteed to be valid here, as this function
- * is only be called when !hdmi->disabled.
- */
- dw_hdmi_setup(hdmi, hdmi->curr_conn, &hdmi->previous_mode);
-}
-
static void dw_hdmi_poweroff(struct dw_hdmi *hdmi)
{
if (hdmi->phy.enabled) {
@@ -2937,15 +2928,19 @@ static void dw_hdmi_bridge_atomic_enable(struct drm_bridge *bridge,
{
struct dw_hdmi *hdmi = bridge->driver_private;
struct drm_atomic_state *state = old_state->base.state;
+ const struct drm_display_mode *mode;
struct drm_connector *connector;
+ struct drm_crtc *crtc;

connector = drm_atomic_get_new_connector_for_encoder(state,
bridge->encoder);
+ crtc = drm_atomic_get_new_connector_state(state, connector)->crtc;
+ mode = &drm_atomic_get_new_crtc_state(state, crtc)->adjusted_mode;

mutex_lock(&hdmi->mutex);
hdmi->disabled = false;
hdmi->curr_conn = connector;
- dw_hdmi_poweron(hdmi);
+ dw_hdmi_poweron(hdmi, connector, mode);
dw_hdmi_update_phy_mask(hdmi);
handle_plugged_change(hdmi, true);
mutex_unlock(&hdmi->mutex);
--
2.45.2