Re: [PATCH v2] drm/bridge: it6505: support hdmi_codec_ops for audio stream setup

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, Feb 03, 2025 at 02:04:30PM +0800, Hermes Wu via B4 Relay wrote:
> From: Hermes Wu <Hermes.wu@xxxxxxxxxx>
> 
> For supporting audio form I2S to DP audio data sub stream.
> Add hdmi_audio callbacks to drm_bridge_funcs for the
> HDMI codec framework. The DRM_BRIDGE_OP_HDMI flag in bridge.ops
> must be set, and hdmi_write_infoframe and hdmi_clear_infoframe
> are necessary for the drm_bridge_connector to enable the HDMI codec.

Please split this into two commits: one adding OP_HDMI, second one
adding audio support.

> 
> Signed-off-by: Hermes Wu <Hermes.wu@xxxxxxxxxx>
> ---
> Changes in v2:
> - Use DRM HDMI codec framewrok for audio stream setup.
> - Link to v1: https://lore.kernel.org/r/20250121-add-audio-codec-v1-1-e3ff71b3c819@xxxxxxxxxx
> ---
>  drivers/gpu/drm/bridge/ite-it6505.c | 151 +++++++++++++++++++++++++++++++-----
>  1 file changed, 132 insertions(+), 19 deletions(-)
> 
> diff --git a/drivers/gpu/drm/bridge/ite-it6505.c b/drivers/gpu/drm/bridge/ite-it6505.c
> index 88ef76a37fe6accacdd343839ff2569b31b18ceb..361e2412b8e8f040cf4254479b60588d99e8c99a 100644
> --- a/drivers/gpu/drm/bridge/ite-it6505.c
> +++ b/drivers/gpu/drm/bridge/ite-it6505.c
> @@ -1414,32 +1414,43 @@ static void it6505_variable_config(struct it6505 *it6505)
>  	memset(it6505->bksvs, 0, sizeof(it6505->bksvs));
>  }
>  
> +static int it6505_write_avi_infoframe(struct it6505 *it6505,
> +				      const u8 *buffer, size_t len)
> +{
> +	struct device *dev = it6505->dev;
> +
> +	if (len - HDMI_INFOFRAME_HEADER_SIZE > 13) {
> +		DRM_DEV_DEBUG_DRIVER(dev, "AVI size fail %d", len);
> +		return -EINVAL;
> +	}
> +
> +	it6505_set_bits(it6505, REG_INFOFRAME_CTRL, EN_AVI_PKT, 0);
> +	regmap_bulk_write(it6505->regmap, REG_AVI_INFO_DB1,
> +			  buffer + HDMI_INFOFRAME_HEADER_SIZE,
> +			  len - HDMI_INFOFRAME_HEADER_SIZE);
> +
> +	it6505_write(it6505, REG_AVI_INFO_SUM, buffer[3]);
> +	it6505_set_bits(it6505, REG_INFOFRAME_CTRL, EN_AVI_PKT,
> +			EN_AVI_PKT);
> +
> +	return 0;
> +}
> +
>  static int it6505_send_video_infoframe(struct it6505 *it6505,
>  				       struct hdmi_avi_infoframe *frame)
>  {
>  	u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE];
> -	int err;
> +	int err, length;
>  	struct device *dev = it6505->dev;
>  
> -	err = hdmi_avi_infoframe_pack(frame, buffer, sizeof(buffer));
> -	if (err < 0) {
> -		dev_err(dev, "Failed to pack AVI infoframe: %d", err);
> -		return err;
> +	length = hdmi_avi_infoframe_pack(frame, buffer, sizeof(buffer));
> +	if (length < 0) {
> +		dev_err(dev, "Failed to pack AVI infoframe: %d", length);
> +		return length;
>  	}
>  
> -	err = it6505_set_bits(it6505, REG_INFOFRAME_CTRL, EN_AVI_PKT, 0x00);
> -	if (err)
> -		return err;
> -
> -	err = regmap_bulk_write(it6505->regmap, REG_AVI_INFO_DB1,
> -				buffer + HDMI_INFOFRAME_HEADER_SIZE,
> -				frame->length);
> -	if (err)
> -		return err;
> -
> -	err = it6505_set_bits(it6505, REG_INFOFRAME_CTRL, EN_AVI_PKT,
> -			      EN_AVI_PKT);
> -	if (err)
> +	err = it6505_write_avi_infoframe(it6505, buffer, length);

You mustn't to do this. Please instead call
drm_atomic_helper_connector_hdmi_update_infoframes() from your
.atomic_enable instead.

> +	if (err < 0)
>  		return err;
>  
>  	return 0;
> @@ -1625,6 +1636,18 @@ static void it6505_enable_audio_infoframe(struct it6505 *it6505)
>  			EN_AUD_CTRL_PKT);
>  }
>  
> +static void it6505_write_audio_infoframe(struct it6505 *it6505,
> +					 const u8 *buffer, size_t len)
> +{
> +	it6505_set_bits(it6505, REG_INFOFRAME_CTRL, EN_AUD_PKT, 0);
> +	regmap_bulk_write(it6505->regmap, REG_AUD_INFOFRAM_DB1,
> +			  buffer + HDMI_INFOFRAME_HEADER_SIZE,
> +			  4);
> +	it6505_write(it6505, REG_AUD_INFOFRAM_SUM, buffer[3]);
> +	it6505_set_bits(it6505, REG_INFOFRAME_CTRL, EN_AUD_PKT,
> +			EN_AUD_PKT);
> +}
> +
>  static void it6505_disable_audio(struct it6505 *it6505)
>  {
>  	it6505_set_bits(it6505, REG_DATA_MUTE_CTRL, EN_AUD_MUTE, EN_AUD_MUTE);
> @@ -3302,6 +3325,85 @@ static const struct drm_edid *it6505_bridge_edid_read(struct drm_bridge *bridge,
>  	return drm_edid_dup(it6505->cached_edid);
>  }
>  
> +static int it6505_bridge_hdmi_audio_startup(struct drm_connector *connector,
> +					    struct drm_bridge *bridge)
> +{
> +	struct it6505 *it6505 = bridge_to_it6505(bridge);
> +	struct device *dev = it6505->dev;
> +
> +	if (!it6505->powered || it6505->enable_drv_hold)
> +		return -EIO;
> +
> +	DRM_DEV_DEBUG_DRIVER(dev, "Audio enable");
> +	it6505_enable_audio(it6505);
> +
> +	return 0;
> +}
> +
> +static int it6505_bridge_hdmi_audio_prepare(struct drm_connector *connector,
> +					    struct drm_bridge *bridge,
> +					    struct hdmi_codec_daifmt *fmt,
> +					    struct hdmi_codec_params *hparms)
> +{
> +	struct it6505 *it6505 = bridge_to_it6505(bridge);
> +
> +	return it6505_audio_setup_hw_params(it6505, hparms);
> +}
> +
> +static void it6505_bridge_hdmi_audio_shutdown(struct drm_connector *connector,
> +					      struct drm_bridge *bridge)
> +{
> +	struct it6505 *it6505 = bridge_to_it6505(bridge);
> +
> +	if (it6505->powered && !it6505->enable_drv_hold)
> +		it6505_disable_audio(it6505);
> +}
> +
> +static int it6505_bridge_hdmi_clear_infoframe(struct drm_bridge *bridge,
> +					      enum hdmi_infoframe_type type)
> +{
> +	struct it6505 *it6505 = bridge_to_it6505(bridge);
> +	struct device *dev = it6505->dev;
> +
> +	switch (type) {
> +	case HDMI_INFOFRAME_TYPE_AUDIO:
> +		it6505_set_bits(it6505, REG_INFOFRAME_CTRL, EN_AUD_PKT, 0);
> +		break;
> +
> +	case HDMI_INFOFRAME_TYPE_AVI:
> +		it6505_set_bits(it6505, REG_INFOFRAME_CTRL, EN_AVI_PKT, 0);
> +		break;

Are SPD / Vendor InfoFrames not supported by the HW?

> +	default:
> +		dev_dbg(dev, "unsupported HDMI infoframe 0x%x\n", type);
> +		break;
> +	}
> +
> +	return 0;
> +}
> +
> +static int it6505_bridge_hdmi_write_infoframe(struct drm_bridge *bridge,
> +					      enum hdmi_infoframe_type type,
> +					      const u8 *buffer, size_t len)
> +{
> +	struct it6505 *it6505 = bridge_to_it6505(bridge);
> +	struct device *dev = it6505->dev;
> +
> +	switch (type) {
> +	case HDMI_INFOFRAME_TYPE_AUDIO:
> +		it6505_write_audio_infoframe(it6505, buffer, len);
> +		break;
> +
> +	case HDMI_INFOFRAME_TYPE_AVI:
> +		it6505_write_avi_infoframe(it6505, buffer, len);
> +		break;
> +	default:
> +		dev_dbg(dev, "unsupported HDMI infoframe 0x%x\n", type);
> +		break;
> +	}
> +
> +	return 0;
> +}

Please group functions logically, by having all InfoFrame functions next
to each other.

> +
>  static const struct drm_bridge_funcs it6505_bridge_funcs = {
>  	.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
>  	.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
> @@ -3315,6 +3417,12 @@ static const struct drm_bridge_funcs it6505_bridge_funcs = {
>  	.atomic_post_disable = it6505_bridge_atomic_post_disable,
>  	.detect = it6505_bridge_detect,
>  	.edid_read = it6505_bridge_edid_read,
> +	.hdmi_audio_startup = it6505_bridge_hdmi_audio_startup,
> +	.hdmi_audio_prepare = it6505_bridge_hdmi_audio_prepare,
> +	.hdmi_audio_shutdown = it6505_bridge_hdmi_audio_shutdown,
> +	.hdmi_clear_infoframe = it6505_bridge_hdmi_clear_infoframe,
> +	.hdmi_write_infoframe = it6505_bridge_hdmi_write_infoframe,

No .hdmi_tmds_char_rate_valid?

> +
>  };
>  
>  static __maybe_unused int it6505_bridge_resume(struct device *dev)
> @@ -3700,7 +3808,12 @@ static int it6505_i2c_probe(struct i2c_client *client)
>  	it6505->bridge.funcs = &it6505_bridge_funcs;
>  	it6505->bridge.type = DRM_MODE_CONNECTOR_DisplayPort;
>  	it6505->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID |
> -			     DRM_BRIDGE_OP_HPD;
> +			     DRM_BRIDGE_OP_HPD | DRM_BRIDGE_OP_HDMI;
> +	it6505->bridge.vendor = "iTE";
> +	it6505->bridge.product = "IT6505";
> +	it6505->bridge.hdmi_audio_dev = dev;
> +	it6505->bridge.hdmi_audio_max_i2s_playback_channels = 2;
> +	it6505->bridge.hdmi_audio_dai_port = 1;
>  	drm_bridge_add(&it6505->bridge);
>  
>  	return 0;
> 
> ---
> base-commit: fe003bcb69f7bff9ff2b30b659b004dbafe52907
> change-id: 20250114-add-audio-codec-8c9d47062a6c
> 
> Best regards,
> -- 
> Hermes Wu <Hermes.wu@xxxxxxxxxx>
> 
> 

-- 
With best wishes
Dmitry



[Index of Archives]     [Linux DRI Users]     [Linux Intel Graphics]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux