mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH 0/2] Add HDMI audio support to the LT8912B bridge
@ 2025-02-03 19:23 rafael
  2025-02-03 19:23 ` [PATCH 1/2] dt-bindings: display: bridge: lt8912b: Add I2S audio input port rafael
  2025-02-03 19:23 ` [PATCH 2/2] drm/bridge: lt8912b: Add support for audio rafael
  0 siblings, 2 replies; 6+ messages in thread
From: rafael @ 2025-02-03 19:23 UTC (permalink / raw)
  To: Adrien Grassein, Andrzej Hajda, Neil Armstrong, Robert Foss,
	Laurent Pinchart, Jonas Karlman, Jernej Skrabec,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
	David Airlie, Simona Vetter, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Joao Paulo Goncalves
  Cc: Rafael Beims, dri-devel, devicetree, linux-kernel

From: Rafael Beims <rafael.beims@toradex.com>

This patch series adds HDMI audio support to the Lontium LT8912B bridge driver using the I2S input. The audio output was tested using a Verdin iMX8MM + DSI to HDMI adapter connected to different monitors.

Rafael Beims (2):
  dt-bindings: display: bridge: lt8912b: Add I2S audio input port
  drm/bridge: lt8912b: Add support for audio

 .../display/bridge/lontium,lt8912b.yaml       |   8 ++
 drivers/gpu/drm/bridge/Kconfig                |   1 +
 drivers/gpu/drm/bridge/lontium-lt8912b.c      | 107 +++++++++++++++++-
 3 files changed, 115 insertions(+), 1 deletion(-)

-- 
2.47.2


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 1/2] dt-bindings: display: bridge: lt8912b: Add I2S audio input port
  2025-02-03 19:23 [PATCH 0/2] Add HDMI audio support to the LT8912B bridge rafael
@ 2025-02-03 19:23 ` rafael
  2025-02-03 23:06   ` Rob Herring (Arm)
  2025-02-03 19:23 ` [PATCH 2/2] drm/bridge: lt8912b: Add support for audio rafael
  1 sibling, 1 reply; 6+ messages in thread
From: rafael @ 2025-02-03 19:23 UTC (permalink / raw)
  To: Adrien Grassein, Andrzej Hajda, Neil Armstrong, Robert Foss,
	Laurent Pinchart, Jonas Karlman, Jernej Skrabec,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
	David Airlie, Simona Vetter, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Joao Paulo Goncalves
  Cc: Rafael Beims, dri-devel, devicetree, linux-kernel

From: Rafael Beims <rafael.beims@toradex.com>

Add the I2S audio input port for audio over HDMI support.

Signed-off-by: Rafael Beims <rafael.beims@toradex.com>
---
 .../bindings/display/bridge/lontium,lt8912b.yaml          | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/bridge/lontium,lt8912b.yaml b/Documentation/devicetree/bindings/display/bridge/lontium,lt8912b.yaml
index 2cef25215798..ce555f52beb8 100644
--- a/Documentation/devicetree/bindings/display/bridge/lontium,lt8912b.yaml
+++ b/Documentation/devicetree/bindings/display/bridge/lontium,lt8912b.yaml
@@ -51,6 +51,11 @@ properties:
           HDMI port, should be connected to a node compatible with the
           hdmi-connector binding.
 
+      port@2:
+        $ref: /schemas/graph.yaml#/properties/port
+        description:
+          I2S Audio input port
+
     required:
       - port@0
       - port@1
@@ -76,6 +81,9 @@ properties:
   vdd-supply:
     description: A 1.8V supply that powers the digital part.
 
+  "#sound-dai-cells":
+    const: 0
+
 required:
   - compatible
   - reg
-- 
2.47.2


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 2/2] drm/bridge: lt8912b: Add support for audio
  2025-02-03 19:23 [PATCH 0/2] Add HDMI audio support to the LT8912B bridge rafael
  2025-02-03 19:23 ` [PATCH 1/2] dt-bindings: display: bridge: lt8912b: Add I2S audio input port rafael
@ 2025-02-03 19:23 ` rafael
  2025-02-03 21:05   ` Rafael Beims
  2025-02-04  0:53   ` Dmitry Baryshkov
  1 sibling, 2 replies; 6+ messages in thread
From: rafael @ 2025-02-03 19:23 UTC (permalink / raw)
  To: Adrien Grassein, Andrzej Hajda, Neil Armstrong, Robert Foss,
	Laurent Pinchart, Jonas Karlman, Jernej Skrabec,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
	David Airlie, Simona Vetter, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Joao Paulo Goncalves
  Cc: Rafael Beims, dri-devel, devicetree, linux-kernel

From: Rafael Beims <rafael.beims@toradex.com>

Add support for HDMI codec with audio coming from the I2S input.
Support 48kHz and 96kHz sample rate, with 16 bits word size.

Co-developed-by: João Paulo Gonçalves <joao.goncalves@toradex.com>
Signed-off-by: João Paulo Gonçalves <joao.goncalves@toradex.com>
Signed-off-by: Rafael Beims <rafael.beims@toradex.com>
---
 drivers/gpu/drm/bridge/Kconfig           |   1 +
 drivers/gpu/drm/bridge/lontium-lt8912b.c | 107 ++++++++++++++++++++++-
 2 files changed, 107 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index 6b4664d91faa..489ce1041203 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -117,6 +117,7 @@ config DRM_ITE_IT6505
 
 config DRM_LONTIUM_LT8912B
 	tristate "Lontium LT8912B DSI/HDMI bridge"
+	select SND_SOC_HDMI_CODEC if SND_SOC
 	depends on OF
 	select DRM_PANEL_BRIDGE
 	select DRM_KMS_HELPER
diff --git a/drivers/gpu/drm/bridge/lontium-lt8912b.c b/drivers/gpu/drm/bridge/lontium-lt8912b.c
index 52da204f5740..2100b41e5f61 100644
--- a/drivers/gpu/drm/bridge/lontium-lt8912b.c
+++ b/drivers/gpu/drm/bridge/lontium-lt8912b.c
@@ -8,6 +8,8 @@
 #include <linux/gpio/consumer.h>
 #include <linux/i2c.h>
 #include <linux/media-bus-format.h>
+#include <linux/of_graph.h>
+#include <linux/platform_device.h>
 #include <linux/regmap.h>
 
 #include <drm/drm_probe_helper.h>
@@ -16,6 +18,8 @@
 #include <drm/drm_mipi_dsi.h>
 #include <drm/drm_of.h>
 
+#include <sound/hdmi-codec.h>
+
 #include <video/videomode.h>
 
 #define I2C_MAIN 0
@@ -24,7 +28,10 @@
 #define I2C_CEC_DSI 1
 #define I2C_ADDR_CEC_DSI 0x49
 
-#define I2C_MAX_IDX 2
+#define I2C_AUDIO 2
+#define I2C_ADDR_AUDIO 0x4a
+
+#define I2C_MAX_IDX 3
 
 struct lt8912 {
 	struct device *dev;
@@ -38,6 +45,7 @@ struct lt8912 {
 	struct drm_bridge *hdmi_port;
 
 	struct mipi_dsi_device *dsi;
+	struct platform_device *audio_pdev;
 
 	struct gpio_desc *gp_reset;
 
@@ -226,6 +234,7 @@ static int lt8912_init_i2c(struct lt8912 *lt, struct i2c_client *client)
 	struct i2c_board_info info[] = {
 		{ I2C_BOARD_INFO("lt8912p0", I2C_ADDR_MAIN), },
 		{ I2C_BOARD_INFO("lt8912p1", I2C_ADDR_CEC_DSI), },
+		{ I2C_BOARD_INFO("lt8912p2", I2C_ADDR_AUDIO), },
 	};
 
 	if (!lt)
@@ -754,6 +763,97 @@ static int lt8912_put_dt(struct lt8912 *lt)
 	return 0;
 }
 
+static int lt8912_hdmi_hw_params(struct device *dev, void *data,
+				 struct hdmi_codec_daifmt *fmt,
+				 struct hdmi_codec_params *hparms)
+{
+	struct lt8912 *lt = data;
+	unsigned int audio_params = 0x08; /* 16 bit word size */
+
+	if (hparms->sample_width != 16)
+		return -EINVAL;
+
+	if (hparms->sample_rate == 48000)
+		audio_params |= 0x20;
+	else if (hparms->sample_rate == 96000)
+		audio_params |= 0xa0;
+	else
+		return -EINVAL;
+
+	regmap_write(lt->regmap[I2C_AUDIO], 0x0f, audio_params);
+	regmap_write(lt->regmap[I2C_AUDIO], 0x35, 0x00);
+	regmap_write(lt->regmap[I2C_AUDIO], 0x36, 0x18);
+	regmap_write(lt->regmap[I2C_AUDIO], 0x37, 0x00);
+
+	return 0;
+}
+
+static int lt8912_audio_startup(struct device *dev, void *data)
+{
+	struct lt8912 *lt = data;
+
+	regmap_write(lt->regmap[I2C_AUDIO], 0x34, 0xe2);
+	regmap_write(lt->regmap[I2C_AUDIO], 0x3c, 0x60);
+	regmap_write(lt->regmap[I2C_AUDIO], 0x07, 0xf0);
+	regmap_write(lt->regmap[I2C_AUDIO], 0x06, 0x08);
+
+	return 0;
+}
+
+static void lt8912_audio_shutdown(struct device *dev, void *data)
+{
+	struct lt8912 *lt = data;
+
+	regmap_write(lt->regmap[I2C_AUDIO], 0x06, 0x00);
+	regmap_write(lt->regmap[I2C_AUDIO], 0x07, 0x00);
+	regmap_write(lt->regmap[I2C_AUDIO], 0x34, 0x52);
+	regmap_write(lt->regmap[I2C_AUDIO], 0x3c, 0x40);
+}
+
+static int lt8912_hdmi_i2s_get_dai_id(struct snd_soc_component *component,
+				      struct device_node *endpoint)
+{
+	struct of_endpoint of_ep;
+	int ret;
+
+	ret = of_graph_parse_endpoint(endpoint, &of_ep);
+	if (ret < 0)
+		return ret;
+
+	if (of_ep.port != 2)
+		return -EINVAL;
+
+	return 0;
+}
+
+static const struct hdmi_codec_ops lt8912_codec_ops = {
+	.hw_params = lt8912_hdmi_hw_params,
+	.audio_shutdown = lt8912_audio_shutdown,
+	.audio_startup = lt8912_audio_startup,
+	.get_dai_id = lt8912_hdmi_i2s_get_dai_id,
+};
+
+static int lt8912_audio_init(struct device *dev, struct lt8912 *lt)
+{
+	struct hdmi_codec_pdata codec_data = {
+		.ops = &lt8912_codec_ops,
+		.max_i2s_channels = 2,
+		.i2s = 1,
+		.data = lt,
+	};
+
+	lt->audio_pdev = platform_device_register_data(dev, HDMI_CODEC_DRV_NAME,
+						       PLATFORM_DEVID_AUTO,
+						       &codec_data, sizeof(codec_data));
+
+	return PTR_ERR_OR_ZERO(lt->audio_pdev);
+}
+
+static void lt8912_audio_exit(struct lt8912 *lt)
+{
+	platform_device_unregister(lt->audio_pdev);
+}
+
 static int lt8912_probe(struct i2c_client *client)
 {
 	static struct lt8912 *lt;
@@ -788,6 +888,10 @@ static int lt8912_probe(struct i2c_client *client)
 	if (ret)
 		goto err_attach;
 
+	ret = lt8912_audio_init(dev, lt);
+	if (ret)
+		goto err_attach;
+
 	return 0;
 
 err_attach:
@@ -803,6 +907,7 @@ static void lt8912_remove(struct i2c_client *client)
 {
 	struct lt8912 *lt = i2c_get_clientdata(client);
 
+	lt8912_audio_exit(lt);
 	drm_bridge_remove(&lt->bridge);
 	lt8912_free_i2c(lt);
 	lt8912_put_dt(lt);
-- 
2.47.2


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 2/2] drm/bridge: lt8912b: Add support for audio
  2025-02-03 19:23 ` [PATCH 2/2] drm/bridge: lt8912b: Add support for audio rafael
@ 2025-02-03 21:05   ` Rafael Beims
  2025-02-04  0:53   ` Dmitry Baryshkov
  1 sibling, 0 replies; 6+ messages in thread
From: Rafael Beims @ 2025-02-03 21:05 UTC (permalink / raw)
  To: Adrien Grassein, Andrzej Hajda, Neil Armstrong, Robert Foss,
	Laurent Pinchart, Jonas Karlman, Jernej Skrabec,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
	David Airlie, Simona Vetter, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Joao Paulo Goncalves
  Cc: Rafael Beims, dri-devel, devicetree, linux-kernel

On 03/02/2025 16:23, rafael@beims.me wrote:
> From: Rafael Beims <rafael.beims@toradex.com>
>
> Add support for HDMI codec with audio coming from the I2S input.
> Support 48kHz and 96kHz sample rate, with 16 bits word size.
>
> Co-developed-by: João Paulo Gonçalves <joao.goncalves@toradex.com>
> Signed-off-by: João Paulo Gonçalves <joao.goncalves@toradex.com>
> Signed-off-by: Rafael Beims <rafael.beims@toradex.com>
> ---
>   drivers/gpu/drm/bridge/Kconfig           |   1 +
>   drivers/gpu/drm/bridge/lontium-lt8912b.c | 107 ++++++++++++++++++++++-
>   2 files changed, 107 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
> index 6b4664d91faa..489ce1041203 100644
> --- a/drivers/gpu/drm/bridge/Kconfig
> +++ b/drivers/gpu/drm/bridge/Kconfig
> @@ -117,6 +117,7 @@ config DRM_ITE_IT6505
>   
>   config DRM_LONTIUM_LT8912B
>   	tristate "Lontium LT8912B DSI/HDMI bridge"
> +	select SND_SOC_HDMI_CODEC if SND_SOC
>   	depends on OF
>   	select DRM_PANEL_BRIDGE
>   	select DRM_KMS_HELPER
> diff --git a/drivers/gpu/drm/bridge/lontium-lt8912b.c b/drivers/gpu/drm/bridge/lontium-lt8912b.c
> index 52da204f5740..2100b41e5f61 100644
> --- a/drivers/gpu/drm/bridge/lontium-lt8912b.c
> +++ b/drivers/gpu/drm/bridge/lontium-lt8912b.c
> @@ -8,6 +8,8 @@
>   #include <linux/gpio/consumer.h>
>   #include <linux/i2c.h>
>   #include <linux/media-bus-format.h>
> +#include <linux/of_graph.h>
> +#include <linux/platform_device.h>
>   #include <linux/regmap.h>
>   
>   #include <drm/drm_probe_helper.h>
> @@ -16,6 +18,8 @@
>   #include <drm/drm_mipi_dsi.h>
>   #include <drm/drm_of.h>
>   
> +#include <sound/hdmi-codec.h>
> +
>   #include <video/videomode.h>
>   
>   #define I2C_MAIN 0
> @@ -24,7 +28,10 @@
>   #define I2C_CEC_DSI 1
>   #define I2C_ADDR_CEC_DSI 0x49
>   
> -#define I2C_MAX_IDX 2
> +#define I2C_AUDIO 2
> +#define I2C_ADDR_AUDIO 0x4a
> +
> +#define I2C_MAX_IDX 3
>   
>   struct lt8912 {
>   	struct device *dev;
> @@ -38,6 +45,7 @@ struct lt8912 {
>   	struct drm_bridge *hdmi_port;
>   
>   	struct mipi_dsi_device *dsi;
> +	struct platform_device *audio_pdev;
>   
>   	struct gpio_desc *gp_reset;
>   
> @@ -226,6 +234,7 @@ static int lt8912_init_i2c(struct lt8912 *lt, struct i2c_client *client)
>   	struct i2c_board_info info[] = {
>   		{ I2C_BOARD_INFO("lt8912p0", I2C_ADDR_MAIN), },
>   		{ I2C_BOARD_INFO("lt8912p1", I2C_ADDR_CEC_DSI), },
> +		{ I2C_BOARD_INFO("lt8912p2", I2C_ADDR_AUDIO), },
>   	};
>   
>   	if (!lt)
> @@ -754,6 +763,97 @@ static int lt8912_put_dt(struct lt8912 *lt)
>   	return 0;
>   }
>   
> +static int lt8912_hdmi_hw_params(struct device *dev, void *data,
> +				 struct hdmi_codec_daifmt *fmt,
> +				 struct hdmi_codec_params *hparms)
> +{
> +	struct lt8912 *lt = data;
> +	unsigned int audio_params = 0x08; /* 16 bit word size */
> +
> +	if (hparms->sample_width != 16)
> +		return -EINVAL;
> +
> +	if (hparms->sample_rate == 48000)
> +		audio_params |= 0x20;
> +	else if (hparms->sample_rate == 96000)
> +		audio_params |= 0xa0;
> +	else
> +		return -EINVAL;
> +
> +	regmap_write(lt->regmap[I2C_AUDIO], 0x0f, audio_params);
> +	regmap_write(lt->regmap[I2C_AUDIO], 0x35, 0x00);
> +	regmap_write(lt->regmap[I2C_AUDIO], 0x36, 0x18);
> +	regmap_write(lt->regmap[I2C_AUDIO], 0x37, 0x00);
> +
> +	return 0;
> +}
> +
> +static int lt8912_audio_startup(struct device *dev, void *data)
> +{
> +	struct lt8912 *lt = data;
> +
> +	regmap_write(lt->regmap[I2C_AUDIO], 0x34, 0xe2);
> +	regmap_write(lt->regmap[I2C_AUDIO], 0x3c, 0x60);
> +	regmap_write(lt->regmap[I2C_AUDIO], 0x07, 0xf0);
> +	regmap_write(lt->regmap[I2C_AUDIO], 0x06, 0x08);
> +
> +	return 0;
> +}
> +
> +static void lt8912_audio_shutdown(struct device *dev, void *data)
> +{
> +	struct lt8912 *lt = data;
> +
> +	regmap_write(lt->regmap[I2C_AUDIO], 0x06, 0x00);
> +	regmap_write(lt->regmap[I2C_AUDIO], 0x07, 0x00);
> +	regmap_write(lt->regmap[I2C_AUDIO], 0x34, 0x52);
> +	regmap_write(lt->regmap[I2C_AUDIO], 0x3c, 0x40);
> +}
> +
> +static int lt8912_hdmi_i2s_get_dai_id(struct snd_soc_component *component,
> +				      struct device_node *endpoint)
> +{
> +	struct of_endpoint of_ep;
> +	int ret;
> +
> +	ret = of_graph_parse_endpoint(endpoint, &of_ep);
> +	if (ret < 0)
> +		return ret;
> +
> +	if (of_ep.port != 2)
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
> +static const struct hdmi_codec_ops lt8912_codec_ops = {
> +	.hw_params = lt8912_hdmi_hw_params,
> +	.audio_shutdown = lt8912_audio_shutdown,
> +	.audio_startup = lt8912_audio_startup,
> +	.get_dai_id = lt8912_hdmi_i2s_get_dai_id,
> +};
> +
> +static int lt8912_audio_init(struct device *dev, struct lt8912 *lt)
> +{
> +	struct hdmi_codec_pdata codec_data = {
> +		.ops = &lt8912_codec_ops,
> +		.max_i2s_channels = 2,
> +		.i2s = 1,
> +		.data = lt,
> +	};
> +
> +	lt->audio_pdev = platform_device_register_data(dev, HDMI_CODEC_DRV_NAME,
> +						       PLATFORM_DEVID_AUTO,
> +						       &codec_data, sizeof(codec_data));
> +
> +	return PTR_ERR_OR_ZERO(lt->audio_pdev);
> +}
> +
> +static void lt8912_audio_exit(struct lt8912 *lt)
> +{
> +	platform_device_unregister(lt->audio_pdev);
> +}
> +
>   static int lt8912_probe(struct i2c_client *client)
>   {
>   	static struct lt8912 *lt;
> @@ -788,6 +888,10 @@ static int lt8912_probe(struct i2c_client *client)
>   	if (ret)
>   		goto err_attach;
>   
> +	ret = lt8912_audio_init(dev, lt);
> +	if (ret)
> +		goto err_attach;
> +
>   	return 0;
>   
>   err_attach:
> @@ -803,6 +907,7 @@ static void lt8912_remove(struct i2c_client *client)
>   {
>   	struct lt8912 *lt = i2c_get_clientdata(client);
>   
> +	lt8912_audio_exit(lt);
>   	drm_bridge_remove(&lt->bridge);
>   	lt8912_free_i2c(lt);
>   	lt8912_put_dt(lt);

This patch contains an error, v2 with the fix will follow shortly.

Rafael


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 1/2] dt-bindings: display: bridge: lt8912b: Add I2S audio input port
  2025-02-03 19:23 ` [PATCH 1/2] dt-bindings: display: bridge: lt8912b: Add I2S audio input port rafael
@ 2025-02-03 23:06   ` Rob Herring (Arm)
  0 siblings, 0 replies; 6+ messages in thread
From: Rob Herring (Arm) @ 2025-02-03 23:06 UTC (permalink / raw)
  To: rafael
  Cc: Simona Vetter, Rafael Beims, Robert Foss, Joao Paulo Goncalves,
	Jonas Karlman, Neil Armstrong, Maxime Ripard, Thomas Zimmermann,
	Andrzej Hajda, dri-devel, Adrien Grassein, Jernej Skrabec,
	Laurent Pinchart, Conor Dooley, linux-kernel, devicetree,
	Maarten Lankhorst, David Airlie, Krzysztof Kozlowski


On Mon, 03 Feb 2025 16:23:55 -0300, rafael@beims.me wrote:
> From: Rafael Beims <rafael.beims@toradex.com>
> 
> Add the I2S audio input port for audio over HDMI support.
> 
> Signed-off-by: Rafael Beims <rafael.beims@toradex.com>
> ---
>  .../bindings/display/bridge/lontium,lt8912b.yaml          | 8 ++++++++
>  1 file changed, 8 insertions(+)
> 

Reviewed-by: Rob Herring (Arm) <robh@kernel.org>


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH 2/2] drm/bridge: lt8912b: Add support for audio
  2025-02-03 19:23 ` [PATCH 2/2] drm/bridge: lt8912b: Add support for audio rafael
  2025-02-03 21:05   ` Rafael Beims
@ 2025-02-04  0:53   ` Dmitry Baryshkov
  1 sibling, 0 replies; 6+ messages in thread
From: Dmitry Baryshkov @ 2025-02-04  0:53 UTC (permalink / raw)
  To: rafael
  Cc: Adrien Grassein, Andrzej Hajda, Neil Armstrong, Robert Foss,
	Laurent Pinchart, Jonas Karlman, Jernej Skrabec,
	Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
	David Airlie, Simona Vetter, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Joao Paulo Goncalves, Rafael Beims, dri-devel,
	devicetree, linux-kernel

On Mon, Feb 03, 2025 at 04:23:56PM -0300, rafael@beims.me wrote:
> From: Rafael Beims <rafael.beims@toradex.com>
> 
> Add support for HDMI codec with audio coming from the I2S input.
> Support 48kHz and 96kHz sample rate, with 16 bits word size.
> 
> Co-developed-by: João Paulo Gonçalves <joao.goncalves@toradex.com>
> Signed-off-by: João Paulo Gonçalves <joao.goncalves@toradex.com>
> Signed-off-by: Rafael Beims <rafael.beims@toradex.com>

Please turn the bridge to support DRM_BRIDGE_OP_HDMI and then use
drm_hdmi_audio_helper features to provide audio support. Your
implementations misses ELD, plugged callback, etc.

> ---
>  drivers/gpu/drm/bridge/Kconfig           |   1 +
>  drivers/gpu/drm/bridge/lontium-lt8912b.c | 107 ++++++++++++++++++++++-
>  2 files changed, 107 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
> index 6b4664d91faa..489ce1041203 100644
> --- a/drivers/gpu/drm/bridge/Kconfig
> +++ b/drivers/gpu/drm/bridge/Kconfig
> @@ -117,6 +117,7 @@ config DRM_ITE_IT6505
>  
>  config DRM_LONTIUM_LT8912B
>  	tristate "Lontium LT8912B DSI/HDMI bridge"
> +	select SND_SOC_HDMI_CODEC if SND_SOC
>  	depends on OF
>  	select DRM_PANEL_BRIDGE
>  	select DRM_KMS_HELPER
> diff --git a/drivers/gpu/drm/bridge/lontium-lt8912b.c b/drivers/gpu/drm/bridge/lontium-lt8912b.c
> index 52da204f5740..2100b41e5f61 100644
> --- a/drivers/gpu/drm/bridge/lontium-lt8912b.c
> +++ b/drivers/gpu/drm/bridge/lontium-lt8912b.c
> @@ -8,6 +8,8 @@
>  #include <linux/gpio/consumer.h>
>  #include <linux/i2c.h>
>  #include <linux/media-bus-format.h>
> +#include <linux/of_graph.h>
> +#include <linux/platform_device.h>
>  #include <linux/regmap.h>
>  
>  #include <drm/drm_probe_helper.h>
> @@ -16,6 +18,8 @@
>  #include <drm/drm_mipi_dsi.h>
>  #include <drm/drm_of.h>
>  
> +#include <sound/hdmi-codec.h>
> +
>  #include <video/videomode.h>
>  
>  #define I2C_MAIN 0
> @@ -24,7 +28,10 @@
>  #define I2C_CEC_DSI 1
>  #define I2C_ADDR_CEC_DSI 0x49
>  
> -#define I2C_MAX_IDX 2
> +#define I2C_AUDIO 2
> +#define I2C_ADDR_AUDIO 0x4a
> +
> +#define I2C_MAX_IDX 3
>  
>  struct lt8912 {
>  	struct device *dev;
> @@ -38,6 +45,7 @@ struct lt8912 {
>  	struct drm_bridge *hdmi_port;
>  
>  	struct mipi_dsi_device *dsi;
> +	struct platform_device *audio_pdev;
>  
>  	struct gpio_desc *gp_reset;
>  
> @@ -226,6 +234,7 @@ static int lt8912_init_i2c(struct lt8912 *lt, struct i2c_client *client)
>  	struct i2c_board_info info[] = {
>  		{ I2C_BOARD_INFO("lt8912p0", I2C_ADDR_MAIN), },
>  		{ I2C_BOARD_INFO("lt8912p1", I2C_ADDR_CEC_DSI), },
> +		{ I2C_BOARD_INFO("lt8912p2", I2C_ADDR_AUDIO), },
>  	};
>  
>  	if (!lt)
> @@ -754,6 +763,97 @@ static int lt8912_put_dt(struct lt8912 *lt)
>  	return 0;
>  }
>  
> +static int lt8912_hdmi_hw_params(struct device *dev, void *data,
> +				 struct hdmi_codec_daifmt *fmt,
> +				 struct hdmi_codec_params *hparms)
> +{
> +	struct lt8912 *lt = data;
> +	unsigned int audio_params = 0x08; /* 16 bit word size */
> +
> +	if (hparms->sample_width != 16)
> +		return -EINVAL;
> +
> +	if (hparms->sample_rate == 48000)
> +		audio_params |= 0x20;
> +	else if (hparms->sample_rate == 96000)
> +		audio_params |= 0xa0;
> +	else
> +		return -EINVAL;
> +
> +	regmap_write(lt->regmap[I2C_AUDIO], 0x0f, audio_params);
> +	regmap_write(lt->regmap[I2C_AUDIO], 0x35, 0x00);
> +	regmap_write(lt->regmap[I2C_AUDIO], 0x36, 0x18);
> +	regmap_write(lt->regmap[I2C_AUDIO], 0x37, 0x00);
> +
> +	return 0;
> +}
> +
> +static int lt8912_audio_startup(struct device *dev, void *data)
> +{
> +	struct lt8912 *lt = data;
> +
> +	regmap_write(lt->regmap[I2C_AUDIO], 0x34, 0xe2);
> +	regmap_write(lt->regmap[I2C_AUDIO], 0x3c, 0x60);
> +	regmap_write(lt->regmap[I2C_AUDIO], 0x07, 0xf0);
> +	regmap_write(lt->regmap[I2C_AUDIO], 0x06, 0x08);
> +
> +	return 0;
> +}
> +
> +static void lt8912_audio_shutdown(struct device *dev, void *data)
> +{
> +	struct lt8912 *lt = data;
> +
> +	regmap_write(lt->regmap[I2C_AUDIO], 0x06, 0x00);
> +	regmap_write(lt->regmap[I2C_AUDIO], 0x07, 0x00);
> +	regmap_write(lt->regmap[I2C_AUDIO], 0x34, 0x52);
> +	regmap_write(lt->regmap[I2C_AUDIO], 0x3c, 0x40);
> +}
> +
> +static int lt8912_hdmi_i2s_get_dai_id(struct snd_soc_component *component,
> +				      struct device_node *endpoint)
> +{
> +	struct of_endpoint of_ep;
> +	int ret;
> +
> +	ret = of_graph_parse_endpoint(endpoint, &of_ep);
> +	if (ret < 0)
> +		return ret;
> +
> +	if (of_ep.port != 2)
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
> +static const struct hdmi_codec_ops lt8912_codec_ops = {
> +	.hw_params = lt8912_hdmi_hw_params,
> +	.audio_shutdown = lt8912_audio_shutdown,
> +	.audio_startup = lt8912_audio_startup,
> +	.get_dai_id = lt8912_hdmi_i2s_get_dai_id,
> +};
> +
> +static int lt8912_audio_init(struct device *dev, struct lt8912 *lt)
> +{
> +	struct hdmi_codec_pdata codec_data = {
> +		.ops = &lt8912_codec_ops,
> +		.max_i2s_channels = 2,
> +		.i2s = 1,
> +		.data = lt,
> +	};
> +
> +	lt->audio_pdev = platform_device_register_data(dev, HDMI_CODEC_DRV_NAME,
> +						       PLATFORM_DEVID_AUTO,
> +						       &codec_data, sizeof(codec_data));
> +
> +	return PTR_ERR_OR_ZERO(lt->audio_pdev);
> +}
> +
> +static void lt8912_audio_exit(struct lt8912 *lt)
> +{
> +	platform_device_unregister(lt->audio_pdev);
> +}
> +
>  static int lt8912_probe(struct i2c_client *client)
>  {
>  	static struct lt8912 *lt;
> @@ -788,6 +888,10 @@ static int lt8912_probe(struct i2c_client *client)
>  	if (ret)
>  		goto err_attach;
>  
> +	ret = lt8912_audio_init(dev, lt);
> +	if (ret)
> +		goto err_attach;
> +
>  	return 0;
>  
>  err_attach:
> @@ -803,6 +907,7 @@ static void lt8912_remove(struct i2c_client *client)
>  {
>  	struct lt8912 *lt = i2c_get_clientdata(client);
>  
> +	lt8912_audio_exit(lt);
>  	drm_bridge_remove(&lt->bridge);
>  	lt8912_free_i2c(lt);
>  	lt8912_put_dt(lt);
> -- 
> 2.47.2
> 

-- 
With best wishes
Dmitry

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2025-02-04  0:53 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-02-03 19:23 [PATCH 0/2] Add HDMI audio support to the LT8912B bridge rafael
2025-02-03 19:23 ` [PATCH 1/2] dt-bindings: display: bridge: lt8912b: Add I2S audio input port rafael
2025-02-03 23:06   ` Rob Herring (Arm)
2025-02-03 19:23 ` [PATCH 2/2] drm/bridge: lt8912b: Add support for audio rafael
2025-02-03 21:05   ` Rafael Beims
2025-02-04  0:53   ` Dmitry Baryshkov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®