[PATCH v7] drm/rockchip: rk3066_hdmi: add sound support

Andy Yan andyshrk at 163.com
Fri Jun 28 06:08:55 PDT 2024


Hi Johan,

At 2024-06-28 17:23:39, "Johan Jonker" <jbx6244 at gmail.com> wrote:
>Add sound support to the RK3066 HDMI driver.
>The HDMI TX audio source is connected to I2S_8CH.
>
>Signed-off-by: Zheng Yang <zhengyang at rock-chips.com>
>Signed-off-by: Johan Jonker <jbx6244 at gmail.com>
>---
>
>Changed V7:
>  rebase
>---
> drivers/gpu/drm/rockchip/Kconfig       |   2 +
> drivers/gpu/drm/rockchip/rk3066_hdmi.c | 274 ++++++++++++++++++++++++-
> 2 files changed, 275 insertions(+), 1 deletion(-)
>
>diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig
>index 1bf3e2829cd0..a32ee558408c 100644
>--- a/drivers/gpu/drm/rockchip/Kconfig
>+++ b/drivers/gpu/drm/rockchip/Kconfig
>@@ -102,6 +102,8 @@ config ROCKCHIP_RGB
> config ROCKCHIP_RK3066_HDMI
> 	bool "Rockchip specific extensions for RK3066 HDMI"
> 	depends on DRM_ROCKCHIP
>+	select SND_SOC_HDMI_CODEC if SND_SOC
>+	select SND_SOC_ROCKCHIP_I2S if SND_SOC
> 	help
> 	  This selects support for Rockchip SoC specific extensions
> 	  for the RK3066 HDMI driver. If you want to enable
>diff --git a/drivers/gpu/drm/rockchip/rk3066_hdmi.c b/drivers/gpu/drm/rockchip/rk3066_hdmi.c
>index 784de990da1b..d3128b787629 100644
>--- a/drivers/gpu/drm/rockchip/rk3066_hdmi.c
>+++ b/drivers/gpu/drm/rockchip/rk3066_hdmi.c
>@@ -15,12 +15,20 @@
> #include <linux/platform_device.h>
> #include <linux/regmap.h>
>
>+#include <sound/hdmi-codec.h>
>+
> #include "rk3066_hdmi.h"
>
> #include "rockchip_drm_drv.h"
>
> #define DEFAULT_PLLA_RATE 30000000
>
>+struct audio_info {
>+	int channels;
>+	int sample_rate;
>+	int sample_width;
>+};
>+
> struct hdmi_data_info {
> 	int vic; /* The CEA Video ID (VIC) of the current drm display mode. */
> 	unsigned int enc_out_format;
>@@ -54,9 +62,16 @@ struct rk3066_hdmi {
>
> 	unsigned int tmdsclk;
>
>+	struct platform_device *audio_pdev;
>+	stru

......

>+
>+	return ret;
>+}
>+
>+static const struct hdmi_codec_ops audio_codec_ops = {
>+	.hw_params = rk3066_hdmi_audio_hw_params,
>+	.audio_shutdown = rk3066_hdmi_audio_shutdown,
>+	.mute_stream = rk3066_hdmi_audio_mute_stream,
>+	.get_eld = rk3066_hdmi_audio_get_eld,
>+	.no_capture_mute = 1,
>+};
>+
>+static int rk3066_hdmi_audio_codec_init(struct rk3066_hdmi *hdmi,
>+					struct device *dev)
>+{
>+	struct hdmi_codec_pdata codec_data = {
>+		.i2s = 1,
>+		.ops = &audio_codec_ops,
>+		.max_i2s_channels = 8,
>+	};
>+
>+	hdmi->audio.channels = 2;
>+	hdmi->audio.sample_rate = 48000;
>+	hdmi->audio.sample_width = 16;
>+	hdmi->audio_enable = false;
>+	hdmi->audio_pdev =
>+		platform_device_register_data(dev,
>+					      HDMI_CODEC_DRV_NAME,
>+					      PLATFORM_DEVID_NONE,
>+					      &codec_data,
>+					      sizeof(codec_data));
>+
>+	return PTR_ERR_OR_ZERO(hdmi->audio_pdev);
>+}
>+
> static int
> rk3066_hdmi_register(struct drm_device *drm, struct rk3066_hdmi *hdmi)
> {
>@@ -566,6 +834,8 @@ rk3066_hdmi_register(struct drm_device *drm, struct rk3066_hdmi *hdmi)
>
> 	drm_connector_attach_encoder(&hdmi->connector, encoder);
>
>+	rk3066_hdmi_audio_codec_init(hdmi, dev);


According to Documentation/driver-api/driver-model/driver.rst,

It is best not to register at the bind callback:

.. warning::
      -EPROBE_DEFER must not be returned if probe() has already created
      child devices, even if those child devices are removed again
      in a cleanup path. If -EPROBE_DEFER is returned after a child
      device has been registered, it may result in an infinite loop of
      .probe() calls to the same driver.

For example:
vop_probe --》component_add--》rk3066_hdmi_bind--》rk3066_hdmi_audio_codec_init--》hdmi_codec_probe--》rockchip_rgb_init(DEFER when panel not ready)

This  may result in an infinite loop of probe


>+
> 	return 0;
> }
>
>@@ -813,6 +1083,7 @@ static int rk3066_hdmi_bind(struct device *dev, struct device *master,
> 	return 0;
>
> err_cleanup_hdmi:
>+	platform_device_unregister(hdmi->audio_pdev);
> 	hdmi->connector.funcs->destroy(&hdmi->connector);
> 	hdmi->encoder.encoder.funcs->destroy(&hdmi->encoder.encoder);
> err_disable_i2c:
>@@ -828,6 +1099,7 @@ static void rk3066_hdmi_unbind(struct device *dev, struct device *master,
> {
> 	struct rk3066_hdmi *hdmi = dev_get_drvdata(dev);
>
>+	platform_device_unregister(hdmi->audio_pdev);
> 	hdmi->connector.funcs->destroy(&hdmi->connector);
> 	hdmi->encoder.encoder.funcs->destroy(&hdmi->encoder.encoder);
>
>--
>2.39.2
>


More information about the Linux-rockchip mailing list