All of lore.kernel.org
 help / color / mirror / Atom feed
From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
To: Algea Cao <algea.cao@rock-chips.com>
Cc: daniel@ffwll.ch, jernej.skrabec@siol.net,
	laurent.pinchart+renesas@ideasonboard.com, heiko@sntech.de,
	jonas@kwiboo.se, airlied@linux.ie, kuankuan.y@gmail.com,
	narmstrong@baylibre.com, maarten.lankhorst@linux.intel.com,
	hjc@rock-chips.com, dri-devel@lists.freedesktop.org,
	linux-kernel@vger.kernel.org, a.hajda@samsung.com,
	mripard@kernel.org, tzimmermann@suse.de, jbrunet@baylibre.com,
	linux-rockchip@lists.infradead.org, darekm@google.com,
	sam@ravnborg.org, linux-arm-kernel@lists.infradead.org,
	cychiang@chromium.org
Subject: Re: [PATCH 2/6] drm: bridge: dw-hdmi: Implement connector atomic_begin/atomic_flush
Date: Wed, 12 Aug 2020 12:22:17 +0300	[thread overview]
Message-ID: <20200812092217.GC6057@pendragon.ideasonboard.com> (raw)
In-Reply-To: <20200812083433.934-1-algea.cao@rock-chips.com>

Hi Algea,

Thank you for the patch.

On Wed, Aug 12, 2020 at 04:34:33PM +0800, Algea Cao wrote:
> Introduce dw_hdmi_connector_atomic_begin() and
> dw_hdmi_connector_atomic_flush() to implement connector
> atomic_begin/atomic_flush. When enc_out_bus_format or
> enc_in_bus_format changed, dw_hdmi_setup is called.
> 
> To avoid screen flash when updating bus format, it's need
> to send AVMUTE flag to make screen black, and clear flag
> after bus format updated.
> 
> Signed-off-by: Algea Cao <algea.cao@rock-chips.com>
> ---
> 
>  drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 65 +++++++++++++++++++++++
>  drivers/gpu/drm/bridge/synopsys/dw-hdmi.h |  4 ++
>  2 files changed, 69 insertions(+)
> 
> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> index 6148a022569a..a1a81fc768c2 100644
> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> @@ -108,6 +108,8 @@ struct hdmi_vmode {
>  };
>  
>  struct hdmi_data_info {
> +	unsigned int prev_enc_in_bus_format;
> +	unsigned int prev_enc_out_bus_format;
>  	unsigned int enc_in_bus_format;
>  	unsigned int enc_out_bus_format;
>  	unsigned int enc_in_encoding;
> @@ -116,6 +118,7 @@ struct hdmi_data_info {
>  	unsigned int hdcp_enable;
>  	struct hdmi_vmode video_mode;
>  	bool rgb_limited_range;
> +	bool update;
>  };
>  
>  struct dw_hdmi_i2c {
> @@ -2401,6 +2404,60 @@ static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
>  	return ret;
>  }
>  
> +static void
> +dw_hdmi_connector_atomic_begin(struct drm_connector *connector,
> +			       struct drm_connector_state *conn_state)
> +{
> +	struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi,
> +					    connector);
> +	unsigned int enc_in_bus_fmt = hdmi->hdmi_data.enc_in_bus_format;
> +	unsigned int enc_out_bus_fmt = hdmi->hdmi_data.enc_out_bus_format;
> +	unsigned int prev_enc_in_bus_fmt =
> +		hdmi->hdmi_data.prev_enc_in_bus_format;
> +	unsigned int prev_enc_out_bus_fmt =
> +		hdmi->hdmi_data.prev_enc_out_bus_format;
> +
> +	if (!conn_state->crtc)
> +		return;
> +
> +	if (!hdmi->hdmi_data.video_mode.mpixelclock)
> +		return;
> +
> +	if (enc_in_bus_fmt != prev_enc_in_bus_fmt ||
> +	    enc_out_bus_fmt != prev_enc_out_bus_fmt) {
> +		hdmi->hdmi_data.update = true;
> +		hdmi_writeb(hdmi, HDMI_FC_GCP_SET_AVMUTE, HDMI_FC_GCP);
> +		/* Add delay to make av mute work on sink*/
> +		msleep(50);
> +	} else {
> +		hdmi->hdmi_data.update = false;
> +	}
> +}
> +
> +static void
> +dw_hdmi_connector_atomic_flush(struct drm_connector *connector,
> +			       struct drm_connector_state *conn_state)
> +{
> +	struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi,
> +					     connector);
> +
> +	if (!conn_state->crtc)
> +		return;
> +
> +	DRM_DEBUG("%s\n", __func__);
> +
> +	if (hdmi->hdmi_data.update) {
> +		dw_hdmi_setup(hdmi, hdmi->curr_conn, &hdmi->previous_mode);
> +		/*
> +		 * Before clear AVMUTE, delay is needed to
> +		 * prevent display flash.
> +		 */
> +		msleep(50);
> +		hdmi_writeb(hdmi, HDMI_FC_GCP_CLEAR_AVMUTE, HDMI_FC_GCP);
> +		hdmi->hdmi_data.update = false;
> +	}
> +}
> +
>  static bool hdr_metadata_equal(const struct drm_connector_state *old_state,
>  			       const struct drm_connector_state *new_state)
>  {
> @@ -2465,6 +2522,8 @@ static const struct drm_connector_funcs dw_hdmi_connector_funcs = {
>  static const struct drm_connector_helper_funcs dw_hdmi_connector_helper_funcs = {
>  	.get_modes = dw_hdmi_connector_get_modes,
>  	.atomic_check = dw_hdmi_connector_atomic_check,
> +	.atomic_begin = dw_hdmi_connector_atomic_begin,
> +	.atomic_flush = dw_hdmi_connector_atomic_flush,
>  };
>  
>  static int dw_hdmi_connector_create(struct dw_hdmi *hdmi)
> @@ -2778,6 +2837,12 @@ static int dw_hdmi_bridge_atomic_check(struct drm_bridge *bridge,
>  {
>  	struct dw_hdmi *hdmi = bridge->driver_private;
>  
> +	hdmi->hdmi_data.prev_enc_out_bus_format =
> +			hdmi->hdmi_data.enc_out_bus_format;
> +
> +	hdmi->hdmi_data.prev_enc_in_bus_format =
> +			hdmi->hdmi_data.enc_in_bus_format;
> +
>  	hdmi->hdmi_data.enc_out_bus_format =
>  			bridge_state->output_bus_cfg.format;
>  

.atomic_check() isn't allowed to change the device state, neither the
hardware state, nor the software state stored in struct dw_hdmi. You
essentially need to treat the drm_bridge and dw_hdmi as const in the
.atomic_check() operation.

> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
> index 1999db05bc3b..05182418efbb 100644
> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
> @@ -842,6 +842,10 @@ enum {
>  	HDMI_FC_AVICONF3_QUANT_RANGE_LIMITED = 0x00,
>  	HDMI_FC_AVICONF3_QUANT_RANGE_FULL = 0x04,
>  
> +/* HDMI_FC_GCP */
> +	HDMI_FC_GCP_SET_AVMUTE = 0x2,
> +	HDMI_FC_GCP_CLEAR_AVMUTE = 0x1,
> +
>  /* FC_DBGFORCE field values */
>  	HDMI_FC_DBGFORCE_FORCEAUDIO = 0x10,
>  	HDMI_FC_DBGFORCE_FORCEVIDEO = 0x1,

-- 
Regards,

Laurent Pinchart

_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip

WARNING: multiple messages have this Message-ID (diff)
From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
To: Algea Cao <algea.cao@rock-chips.com>
Cc: daniel@ffwll.ch, jernej.skrabec@siol.net,
	laurent.pinchart+renesas@ideasonboard.com, heiko@sntech.de,
	jonas@kwiboo.se, airlied@linux.ie, kuankuan.y@gmail.com,
	narmstrong@baylibre.com, maarten.lankhorst@linux.intel.com,
	hjc@rock-chips.com, dri-devel@lists.freedesktop.org,
	linux-kernel@vger.kernel.org, a.hajda@samsung.com,
	mripard@kernel.org, tzimmermann@suse.de, jbrunet@baylibre.com,
	linux-rockchip@lists.infradead.org, darekm@google.com,
	sam@ravnborg.org, linux-arm-kernel@lists.infradead.org,
	cychiang@chromium.org
Subject: Re: [PATCH 2/6] drm: bridge: dw-hdmi: Implement connector atomic_begin/atomic_flush
Date: Wed, 12 Aug 2020 12:22:17 +0300	[thread overview]
Message-ID: <20200812092217.GC6057@pendragon.ideasonboard.com> (raw)
In-Reply-To: <20200812083433.934-1-algea.cao@rock-chips.com>

Hi Algea,

Thank you for the patch.

On Wed, Aug 12, 2020 at 04:34:33PM +0800, Algea Cao wrote:
> Introduce dw_hdmi_connector_atomic_begin() and
> dw_hdmi_connector_atomic_flush() to implement connector
> atomic_begin/atomic_flush. When enc_out_bus_format or
> enc_in_bus_format changed, dw_hdmi_setup is called.
> 
> To avoid screen flash when updating bus format, it's need
> to send AVMUTE flag to make screen black, and clear flag
> after bus format updated.
> 
> Signed-off-by: Algea Cao <algea.cao@rock-chips.com>
> ---
> 
>  drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 65 +++++++++++++++++++++++
>  drivers/gpu/drm/bridge/synopsys/dw-hdmi.h |  4 ++
>  2 files changed, 69 insertions(+)
> 
> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> index 6148a022569a..a1a81fc768c2 100644
> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> @@ -108,6 +108,8 @@ struct hdmi_vmode {
>  };
>  
>  struct hdmi_data_info {
> +	unsigned int prev_enc_in_bus_format;
> +	unsigned int prev_enc_out_bus_format;
>  	unsigned int enc_in_bus_format;
>  	unsigned int enc_out_bus_format;
>  	unsigned int enc_in_encoding;
> @@ -116,6 +118,7 @@ struct hdmi_data_info {
>  	unsigned int hdcp_enable;
>  	struct hdmi_vmode video_mode;
>  	bool rgb_limited_range;
> +	bool update;
>  };
>  
>  struct dw_hdmi_i2c {
> @@ -2401,6 +2404,60 @@ static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
>  	return ret;
>  }
>  
> +static void
> +dw_hdmi_connector_atomic_begin(struct drm_connector *connector,
> +			       struct drm_connector_state *conn_state)
> +{
> +	struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi,
> +					    connector);
> +	unsigned int enc_in_bus_fmt = hdmi->hdmi_data.enc_in_bus_format;
> +	unsigned int enc_out_bus_fmt = hdmi->hdmi_data.enc_out_bus_format;
> +	unsigned int prev_enc_in_bus_fmt =
> +		hdmi->hdmi_data.prev_enc_in_bus_format;
> +	unsigned int prev_enc_out_bus_fmt =
> +		hdmi->hdmi_data.prev_enc_out_bus_format;
> +
> +	if (!conn_state->crtc)
> +		return;
> +
> +	if (!hdmi->hdmi_data.video_mode.mpixelclock)
> +		return;
> +
> +	if (enc_in_bus_fmt != prev_enc_in_bus_fmt ||
> +	    enc_out_bus_fmt != prev_enc_out_bus_fmt) {
> +		hdmi->hdmi_data.update = true;
> +		hdmi_writeb(hdmi, HDMI_FC_GCP_SET_AVMUTE, HDMI_FC_GCP);
> +		/* Add delay to make av mute work on sink*/
> +		msleep(50);
> +	} else {
> +		hdmi->hdmi_data.update = false;
> +	}
> +}
> +
> +static void
> +dw_hdmi_connector_atomic_flush(struct drm_connector *connector,
> +			       struct drm_connector_state *conn_state)
> +{
> +	struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi,
> +					     connector);
> +
> +	if (!conn_state->crtc)
> +		return;
> +
> +	DRM_DEBUG("%s\n", __func__);
> +
> +	if (hdmi->hdmi_data.update) {
> +		dw_hdmi_setup(hdmi, hdmi->curr_conn, &hdmi->previous_mode);
> +		/*
> +		 * Before clear AVMUTE, delay is needed to
> +		 * prevent display flash.
> +		 */
> +		msleep(50);
> +		hdmi_writeb(hdmi, HDMI_FC_GCP_CLEAR_AVMUTE, HDMI_FC_GCP);
> +		hdmi->hdmi_data.update = false;
> +	}
> +}
> +
>  static bool hdr_metadata_equal(const struct drm_connector_state *old_state,
>  			       const struct drm_connector_state *new_state)
>  {
> @@ -2465,6 +2522,8 @@ static const struct drm_connector_funcs dw_hdmi_connector_funcs = {
>  static const struct drm_connector_helper_funcs dw_hdmi_connector_helper_funcs = {
>  	.get_modes = dw_hdmi_connector_get_modes,
>  	.atomic_check = dw_hdmi_connector_atomic_check,
> +	.atomic_begin = dw_hdmi_connector_atomic_begin,
> +	.atomic_flush = dw_hdmi_connector_atomic_flush,
>  };
>  
>  static int dw_hdmi_connector_create(struct dw_hdmi *hdmi)
> @@ -2778,6 +2837,12 @@ static int dw_hdmi_bridge_atomic_check(struct drm_bridge *bridge,
>  {
>  	struct dw_hdmi *hdmi = bridge->driver_private;
>  
> +	hdmi->hdmi_data.prev_enc_out_bus_format =
> +			hdmi->hdmi_data.enc_out_bus_format;
> +
> +	hdmi->hdmi_data.prev_enc_in_bus_format =
> +			hdmi->hdmi_data.enc_in_bus_format;
> +
>  	hdmi->hdmi_data.enc_out_bus_format =
>  			bridge_state->output_bus_cfg.format;
>  

.atomic_check() isn't allowed to change the device state, neither the
hardware state, nor the software state stored in struct dw_hdmi. You
essentially need to treat the drm_bridge and dw_hdmi as const in the
.atomic_check() operation.

> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
> index 1999db05bc3b..05182418efbb 100644
> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
> @@ -842,6 +842,10 @@ enum {
>  	HDMI_FC_AVICONF3_QUANT_RANGE_LIMITED = 0x00,
>  	HDMI_FC_AVICONF3_QUANT_RANGE_FULL = 0x04,
>  
> +/* HDMI_FC_GCP */
> +	HDMI_FC_GCP_SET_AVMUTE = 0x2,
> +	HDMI_FC_GCP_CLEAR_AVMUTE = 0x1,
> +
>  /* FC_DBGFORCE field values */
>  	HDMI_FC_DBGFORCE_FORCEAUDIO = 0x10,
>  	HDMI_FC_DBGFORCE_FORCEVIDEO = 0x1,

-- 
Regards,

Laurent Pinchart

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

WARNING: multiple messages have this Message-ID (diff)
From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
To: Algea Cao <algea.cao@rock-chips.com>
Cc: jernej.skrabec@siol.net,
	laurent.pinchart+renesas@ideasonboard.com, jonas@kwiboo.se,
	airlied@linux.ie, kuankuan.y@gmail.com, narmstrong@baylibre.com,
	hjc@rock-chips.com, dri-devel@lists.freedesktop.org,
	linux-kernel@vger.kernel.org, a.hajda@samsung.com,
	tzimmermann@suse.de, jbrunet@baylibre.com,
	linux-rockchip@lists.infradead.org, darekm@google.com,
	sam@ravnborg.org, linux-arm-kernel@lists.infradead.org,
	cychiang@chromium.org
Subject: Re: [PATCH 2/6] drm: bridge: dw-hdmi: Implement connector atomic_begin/atomic_flush
Date: Wed, 12 Aug 2020 12:22:17 +0300	[thread overview]
Message-ID: <20200812092217.GC6057@pendragon.ideasonboard.com> (raw)
In-Reply-To: <20200812083433.934-1-algea.cao@rock-chips.com>

Hi Algea,

Thank you for the patch.

On Wed, Aug 12, 2020 at 04:34:33PM +0800, Algea Cao wrote:
> Introduce dw_hdmi_connector_atomic_begin() and
> dw_hdmi_connector_atomic_flush() to implement connector
> atomic_begin/atomic_flush. When enc_out_bus_format or
> enc_in_bus_format changed, dw_hdmi_setup is called.
> 
> To avoid screen flash when updating bus format, it's need
> to send AVMUTE flag to make screen black, and clear flag
> after bus format updated.
> 
> Signed-off-by: Algea Cao <algea.cao@rock-chips.com>
> ---
> 
>  drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 65 +++++++++++++++++++++++
>  drivers/gpu/drm/bridge/synopsys/dw-hdmi.h |  4 ++
>  2 files changed, 69 insertions(+)
> 
> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> index 6148a022569a..a1a81fc768c2 100644
> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> @@ -108,6 +108,8 @@ struct hdmi_vmode {
>  };
>  
>  struct hdmi_data_info {
> +	unsigned int prev_enc_in_bus_format;
> +	unsigned int prev_enc_out_bus_format;
>  	unsigned int enc_in_bus_format;
>  	unsigned int enc_out_bus_format;
>  	unsigned int enc_in_encoding;
> @@ -116,6 +118,7 @@ struct hdmi_data_info {
>  	unsigned int hdcp_enable;
>  	struct hdmi_vmode video_mode;
>  	bool rgb_limited_range;
> +	bool update;
>  };
>  
>  struct dw_hdmi_i2c {
> @@ -2401,6 +2404,60 @@ static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
>  	return ret;
>  }
>  
> +static void
> +dw_hdmi_connector_atomic_begin(struct drm_connector *connector,
> +			       struct drm_connector_state *conn_state)
> +{
> +	struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi,
> +					    connector);
> +	unsigned int enc_in_bus_fmt = hdmi->hdmi_data.enc_in_bus_format;
> +	unsigned int enc_out_bus_fmt = hdmi->hdmi_data.enc_out_bus_format;
> +	unsigned int prev_enc_in_bus_fmt =
> +		hdmi->hdmi_data.prev_enc_in_bus_format;
> +	unsigned int prev_enc_out_bus_fmt =
> +		hdmi->hdmi_data.prev_enc_out_bus_format;
> +
> +	if (!conn_state->crtc)
> +		return;
> +
> +	if (!hdmi->hdmi_data.video_mode.mpixelclock)
> +		return;
> +
> +	if (enc_in_bus_fmt != prev_enc_in_bus_fmt ||
> +	    enc_out_bus_fmt != prev_enc_out_bus_fmt) {
> +		hdmi->hdmi_data.update = true;
> +		hdmi_writeb(hdmi, HDMI_FC_GCP_SET_AVMUTE, HDMI_FC_GCP);
> +		/* Add delay to make av mute work on sink*/
> +		msleep(50);
> +	} else {
> +		hdmi->hdmi_data.update = false;
> +	}
> +}
> +
> +static void
> +dw_hdmi_connector_atomic_flush(struct drm_connector *connector,
> +			       struct drm_connector_state *conn_state)
> +{
> +	struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi,
> +					     connector);
> +
> +	if (!conn_state->crtc)
> +		return;
> +
> +	DRM_DEBUG("%s\n", __func__);
> +
> +	if (hdmi->hdmi_data.update) {
> +		dw_hdmi_setup(hdmi, hdmi->curr_conn, &hdmi->previous_mode);
> +		/*
> +		 * Before clear AVMUTE, delay is needed to
> +		 * prevent display flash.
> +		 */
> +		msleep(50);
> +		hdmi_writeb(hdmi, HDMI_FC_GCP_CLEAR_AVMUTE, HDMI_FC_GCP);
> +		hdmi->hdmi_data.update = false;
> +	}
> +}
> +
>  static bool hdr_metadata_equal(const struct drm_connector_state *old_state,
>  			       const struct drm_connector_state *new_state)
>  {
> @@ -2465,6 +2522,8 @@ static const struct drm_connector_funcs dw_hdmi_connector_funcs = {
>  static const struct drm_connector_helper_funcs dw_hdmi_connector_helper_funcs = {
>  	.get_modes = dw_hdmi_connector_get_modes,
>  	.atomic_check = dw_hdmi_connector_atomic_check,
> +	.atomic_begin = dw_hdmi_connector_atomic_begin,
> +	.atomic_flush = dw_hdmi_connector_atomic_flush,
>  };
>  
>  static int dw_hdmi_connector_create(struct dw_hdmi *hdmi)
> @@ -2778,6 +2837,12 @@ static int dw_hdmi_bridge_atomic_check(struct drm_bridge *bridge,
>  {
>  	struct dw_hdmi *hdmi = bridge->driver_private;
>  
> +	hdmi->hdmi_data.prev_enc_out_bus_format =
> +			hdmi->hdmi_data.enc_out_bus_format;
> +
> +	hdmi->hdmi_data.prev_enc_in_bus_format =
> +			hdmi->hdmi_data.enc_in_bus_format;
> +
>  	hdmi->hdmi_data.enc_out_bus_format =
>  			bridge_state->output_bus_cfg.format;
>  

.atomic_check() isn't allowed to change the device state, neither the
hardware state, nor the software state stored in struct dw_hdmi. You
essentially need to treat the drm_bridge and dw_hdmi as const in the
.atomic_check() operation.

> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
> index 1999db05bc3b..05182418efbb 100644
> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
> @@ -842,6 +842,10 @@ enum {
>  	HDMI_FC_AVICONF3_QUANT_RANGE_LIMITED = 0x00,
>  	HDMI_FC_AVICONF3_QUANT_RANGE_FULL = 0x04,
>  
> +/* HDMI_FC_GCP */
> +	HDMI_FC_GCP_SET_AVMUTE = 0x2,
> +	HDMI_FC_GCP_CLEAR_AVMUTE = 0x1,
> +
>  /* FC_DBGFORCE field values */
>  	HDMI_FC_DBGFORCE_FORCEAUDIO = 0x10,
>  	HDMI_FC_DBGFORCE_FORCEVIDEO = 0x1,

-- 
Regards,

Laurent Pinchart
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

WARNING: multiple messages have this Message-ID (diff)
From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
To: Algea Cao <algea.cao@rock-chips.com>
Cc: a.hajda@samsung.com, kuankuan.y@gmail.com, hjc@rock-chips.com,
	tzimmermann@suse.de, dri-devel@lists.freedesktop.org,
	sam@ravnborg.org, airlied@linux.ie, heiko@sntech.de,
	jernej.skrabec@siol.net,
	laurent.pinchart+renesas@ideasonboard.com, jonas@kwiboo.se,
	mripard@kernel.org, darekm@google.com,
	linux-rockchip@lists.infradead.org,
	linux-arm-kernel@lists.infradead.org, cychiang@chromium.org,
	linux-kernel@vger.kernel.org, narmstrong@baylibre.com,
	jbrunet@baylibre.com, maarten.lankhorst@linux.intel.com,
	daniel@ffwll.ch
Subject: Re: [PATCH 2/6] drm: bridge: dw-hdmi: Implement connector atomic_begin/atomic_flush
Date: Wed, 12 Aug 2020 12:22:17 +0300	[thread overview]
Message-ID: <20200812092217.GC6057@pendragon.ideasonboard.com> (raw)
In-Reply-To: <20200812083433.934-1-algea.cao@rock-chips.com>

Hi Algea,

Thank you for the patch.

On Wed, Aug 12, 2020 at 04:34:33PM +0800, Algea Cao wrote:
> Introduce dw_hdmi_connector_atomic_begin() and
> dw_hdmi_connector_atomic_flush() to implement connector
> atomic_begin/atomic_flush. When enc_out_bus_format or
> enc_in_bus_format changed, dw_hdmi_setup is called.
> 
> To avoid screen flash when updating bus format, it's need
> to send AVMUTE flag to make screen black, and clear flag
> after bus format updated.
> 
> Signed-off-by: Algea Cao <algea.cao@rock-chips.com>
> ---
> 
>  drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 65 +++++++++++++++++++++++
>  drivers/gpu/drm/bridge/synopsys/dw-hdmi.h |  4 ++
>  2 files changed, 69 insertions(+)
> 
> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> index 6148a022569a..a1a81fc768c2 100644
> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
> @@ -108,6 +108,8 @@ struct hdmi_vmode {
>  };
>  
>  struct hdmi_data_info {
> +	unsigned int prev_enc_in_bus_format;
> +	unsigned int prev_enc_out_bus_format;
>  	unsigned int enc_in_bus_format;
>  	unsigned int enc_out_bus_format;
>  	unsigned int enc_in_encoding;
> @@ -116,6 +118,7 @@ struct hdmi_data_info {
>  	unsigned int hdcp_enable;
>  	struct hdmi_vmode video_mode;
>  	bool rgb_limited_range;
> +	bool update;
>  };
>  
>  struct dw_hdmi_i2c {
> @@ -2401,6 +2404,60 @@ static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
>  	return ret;
>  }
>  
> +static void
> +dw_hdmi_connector_atomic_begin(struct drm_connector *connector,
> +			       struct drm_connector_state *conn_state)
> +{
> +	struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi,
> +					    connector);
> +	unsigned int enc_in_bus_fmt = hdmi->hdmi_data.enc_in_bus_format;
> +	unsigned int enc_out_bus_fmt = hdmi->hdmi_data.enc_out_bus_format;
> +	unsigned int prev_enc_in_bus_fmt =
> +		hdmi->hdmi_data.prev_enc_in_bus_format;
> +	unsigned int prev_enc_out_bus_fmt =
> +		hdmi->hdmi_data.prev_enc_out_bus_format;
> +
> +	if (!conn_state->crtc)
> +		return;
> +
> +	if (!hdmi->hdmi_data.video_mode.mpixelclock)
> +		return;
> +
> +	if (enc_in_bus_fmt != prev_enc_in_bus_fmt ||
> +	    enc_out_bus_fmt != prev_enc_out_bus_fmt) {
> +		hdmi->hdmi_data.update = true;
> +		hdmi_writeb(hdmi, HDMI_FC_GCP_SET_AVMUTE, HDMI_FC_GCP);
> +		/* Add delay to make av mute work on sink*/
> +		msleep(50);
> +	} else {
> +		hdmi->hdmi_data.update = false;
> +	}
> +}
> +
> +static void
> +dw_hdmi_connector_atomic_flush(struct drm_connector *connector,
> +			       struct drm_connector_state *conn_state)
> +{
> +	struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi,
> +					     connector);
> +
> +	if (!conn_state->crtc)
> +		return;
> +
> +	DRM_DEBUG("%s\n", __func__);
> +
> +	if (hdmi->hdmi_data.update) {
> +		dw_hdmi_setup(hdmi, hdmi->curr_conn, &hdmi->previous_mode);
> +		/*
> +		 * Before clear AVMUTE, delay is needed to
> +		 * prevent display flash.
> +		 */
> +		msleep(50);
> +		hdmi_writeb(hdmi, HDMI_FC_GCP_CLEAR_AVMUTE, HDMI_FC_GCP);
> +		hdmi->hdmi_data.update = false;
> +	}
> +}
> +
>  static bool hdr_metadata_equal(const struct drm_connector_state *old_state,
>  			       const struct drm_connector_state *new_state)
>  {
> @@ -2465,6 +2522,8 @@ static const struct drm_connector_funcs dw_hdmi_connector_funcs = {
>  static const struct drm_connector_helper_funcs dw_hdmi_connector_helper_funcs = {
>  	.get_modes = dw_hdmi_connector_get_modes,
>  	.atomic_check = dw_hdmi_connector_atomic_check,
> +	.atomic_begin = dw_hdmi_connector_atomic_begin,
> +	.atomic_flush = dw_hdmi_connector_atomic_flush,
>  };
>  
>  static int dw_hdmi_connector_create(struct dw_hdmi *hdmi)
> @@ -2778,6 +2837,12 @@ static int dw_hdmi_bridge_atomic_check(struct drm_bridge *bridge,
>  {
>  	struct dw_hdmi *hdmi = bridge->driver_private;
>  
> +	hdmi->hdmi_data.prev_enc_out_bus_format =
> +			hdmi->hdmi_data.enc_out_bus_format;
> +
> +	hdmi->hdmi_data.prev_enc_in_bus_format =
> +			hdmi->hdmi_data.enc_in_bus_format;
> +
>  	hdmi->hdmi_data.enc_out_bus_format =
>  			bridge_state->output_bus_cfg.format;
>  

.atomic_check() isn't allowed to change the device state, neither the
hardware state, nor the software state stored in struct dw_hdmi. You
essentially need to treat the drm_bridge and dw_hdmi as const in the
.atomic_check() operation.

> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
> index 1999db05bc3b..05182418efbb 100644
> --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
> +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h
> @@ -842,6 +842,10 @@ enum {
>  	HDMI_FC_AVICONF3_QUANT_RANGE_LIMITED = 0x00,
>  	HDMI_FC_AVICONF3_QUANT_RANGE_FULL = 0x04,
>  
> +/* HDMI_FC_GCP */
> +	HDMI_FC_GCP_SET_AVMUTE = 0x2,
> +	HDMI_FC_GCP_CLEAR_AVMUTE = 0x1,
> +
>  /* FC_DBGFORCE field values */
>  	HDMI_FC_DBGFORCE_FORCEAUDIO = 0x10,
>  	HDMI_FC_DBGFORCE_FORCEVIDEO = 0x1,

-- 
Regards,

Laurent Pinchart

  reply	other threads:[~2020-08-12  9:22 UTC|newest]

Thread overview: 67+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-08-12  8:31 [PATCH 0/6] Support change dw-hdmi output color Algea Cao
2020-08-12  8:31 ` Algea Cao
2020-08-12  8:31 ` Algea Cao
2020-08-12  8:31 ` Algea Cao
2020-08-12  8:34 ` [PATCH 1/6] drm: Add connector atomic_begin/atomic_flush Algea Cao
2020-08-12  8:34   ` Algea Cao
2020-08-12  8:34   ` Algea Cao
2020-08-12  8:34   ` Algea Cao
2020-08-12  9:26   ` Laurent Pinchart
2020-08-12  9:26     ` Laurent Pinchart
2020-08-12  9:26     ` Laurent Pinchart
2020-08-12  9:26     ` Laurent Pinchart
2020-08-12 10:16   ` kernel test robot
2020-08-12 10:16     ` kernel test robot
2020-08-12  8:34 ` [PATCH 2/6] drm: bridge: dw-hdmi: Implement " Algea Cao
2020-08-12  8:34   ` Algea Cao
2020-08-12  8:34   ` Algea Cao
2020-08-12  8:34   ` Algea Cao
2020-08-12  9:22   ` Laurent Pinchart [this message]
2020-08-12  9:22     ` Laurent Pinchart
2020-08-12  9:22     ` Laurent Pinchart
2020-08-12  9:22     ` Laurent Pinchart
2020-08-12  8:34 ` [PATCH 3/6] drm: bridge: dw-hdmi: Introduce previous_pixelclock/previous_tmdsclock Algea Cao
2020-08-12  8:34   ` Algea Cao
2020-08-12  8:34   ` Algea Cao
2020-08-12  8:34   ` Algea Cao
2020-08-24  9:53   ` Neil Armstrong
2020-08-24  9:53     ` Neil Armstrong
2020-08-24  9:53     ` Neil Armstrong
2020-08-24  9:53     ` Neil Armstrong
2020-08-12  8:35 ` [PATCH 4/6] drm/rockchip: dw_hdmi: Add vendor hdmi properties Algea Cao
2020-08-12  8:35   ` Algea Cao
2020-08-12  8:35   ` Algea Cao
2020-08-12  8:35   ` Algea Cao
2020-08-12  9:33   ` Laurent Pinchart
2020-08-12  9:33     ` Laurent Pinchart
2020-08-12  9:33     ` Laurent Pinchart
2020-08-12  9:33     ` Laurent Pinchart
2020-08-12 11:08     ` crj
2020-08-12 13:30       ` Laurent Pinchart
2020-08-12 13:30         ` Laurent Pinchart
2020-08-12 13:30         ` Laurent Pinchart
2020-08-12 13:30         ` Laurent Pinchart
2020-08-13  7:42         ` Pekka Paalanen
2020-08-13  7:42           ` Pekka Paalanen
2020-08-13  7:42           ` Pekka Paalanen
2020-08-13  7:42           ` Pekka Paalanen
2020-08-13 10:45           ` Laurent Pinchart
2020-08-13 10:45             ` Laurent Pinchart
2020-08-13 10:45             ` Laurent Pinchart
2020-08-13 10:45             ` Laurent Pinchart
2020-08-14  8:23             ` Pekka Paalanen
2020-08-14  8:23               ` Pekka Paalanen
2020-08-14  8:23               ` Pekka Paalanen
2020-08-14  8:23               ` Pekka Paalanen
2020-08-12  8:36 ` [PATCH 5/6] drm/rockchip: dw_hdmi: Add get_output_bus_format Algea Cao
2020-08-12  8:36   ` Algea Cao
2020-08-12  8:36   ` Algea Cao
2020-08-12  8:36   ` Algea Cao
2020-08-12  8:36 ` [PATCH 6/6] drm: bridge: dw-hdmi: Get output bus format when dw-hdmi is the only bridge Algea Cao
2020-08-12  8:36   ` Algea Cao
2020-08-12  8:36   ` Algea Cao
2020-08-12  8:36   ` Algea Cao
2020-08-24  9:50   ` Neil Armstrong
2020-08-24  9:50     ` Neil Armstrong
2020-08-24  9:50     ` Neil Armstrong
2020-08-24  9:50     ` Neil Armstrong

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200812092217.GC6057@pendragon.ideasonboard.com \
    --to=laurent.pinchart@ideasonboard.com \
    --cc=a.hajda@samsung.com \
    --cc=airlied@linux.ie \
    --cc=algea.cao@rock-chips.com \
    --cc=cychiang@chromium.org \
    --cc=daniel@ffwll.ch \
    --cc=darekm@google.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=heiko@sntech.de \
    --cc=hjc@rock-chips.com \
    --cc=jbrunet@baylibre.com \
    --cc=jernej.skrabec@siol.net \
    --cc=jonas@kwiboo.se \
    --cc=kuankuan.y@gmail.com \
    --cc=laurent.pinchart+renesas@ideasonboard.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-rockchip@lists.infradead.org \
    --cc=maarten.lankhorst@linux.intel.com \
    --cc=mripard@kernel.org \
    --cc=narmstrong@baylibre.com \
    --cc=sam@ravnborg.org \
    --cc=tzimmermann@suse.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.