Commit 7fa72cca authored by Kuninori Morimoto's avatar Kuninori Morimoto Committed by Mark Brown
Browse files

ASoC: rsnd: add HDMI output support



Renesas R-Car Gen3 can output HDMI sound if SSIU/SSI are connected to
R-Car built-in HDMI device (R-Car Gen3 built-in HDMI device will be
controlled by DRM/KMS driver).
If SSIx was connected to HDMI0/1 on DT, SSI driver will detect it
automatically by this patch.
Note is that now Renesas R-Car sound driver is assuming that it is
using OF-graph base simple card for HDMI sound.

Signed-off-by: default avatarKuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 4d4b334b
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -38,7 +38,7 @@ config SND_SOC_RCAR
	tristate "R-Car series SRU/SCU/SSIU/SSI support"
	depends on COMMON_CLK
	depends on OF || COMPILE_TEST
	select SND_SIMPLE_CARD
	select SND_SIMPLE_CARD_UTILS
	select REGMAP_MMIO
	help
	  This option enables R-Car SRU/SCU/SSIU/SSI sound support
+5 −2
Original line number Diff line number Diff line
@@ -909,8 +909,11 @@ static int rsnd_dai_probe(struct rsnd_priv *priv)
	 */
	dai_i = 0;
	if (is_graph) {
		for_each_endpoint_of_node(dai_node, dai_np)
			__rsnd_dai_probe(priv, dai_np, dai_i++, is_graph);
		for_each_endpoint_of_node(dai_node, dai_np) {
			__rsnd_dai_probe(priv, dai_np, dai_i, is_graph);
			rsnd_ssi_parse_hdmi_connection(priv, dai_np, dai_i);
			dai_i++;
		}
	} else {
		for_each_child_of_node(dai_node, dai_np)
			__rsnd_dai_probe(priv, dai_np, dai_i++, is_graph);
+2 −0
Original line number Diff line number Diff line
@@ -219,6 +219,8 @@ static int rsnd_gen2_probe(struct rsnd_priv *priv)
		RSND_GEN_S_REG(SSI_SYS_STATUS5,	0x884),
		RSND_GEN_S_REG(SSI_SYS_STATUS6,	0x888),
		RSND_GEN_S_REG(SSI_SYS_STATUS7,	0x88c),
		RSND_GEN_S_REG(HDMI0_SEL,	0x9e0),
		RSND_GEN_S_REG(HDMI1_SEL,	0x9e4),

		/* FIXME: it needs SSI_MODE2/3 in the future */
		RSND_GEN_M_REG(SSI_BUSIF_MODE,	0x0,	0x80),
+9 −0
Original line number Diff line number Diff line
@@ -170,6 +170,8 @@ enum rsnd_reg {
	RSND_REG_SSI_SYS_STATUS5,
	RSND_REG_SSI_SYS_STATUS6,
	RSND_REG_SSI_SYS_STATUS7,
	RSND_REG_HDMI0_SEL,
	RSND_REG_HDMI1_SEL,

	/* SSI */
	RSND_REG_SSICR,
@@ -646,6 +648,13 @@ int rsnd_ssi_is_dma_mode(struct rsnd_mod *mod);
int rsnd_ssi_use_busif(struct rsnd_dai_stream *io);
u32 rsnd_ssi_multi_slaves_runtime(struct rsnd_dai_stream *io);

#define RSND_SSI_HDMI_PORT0	0xf0
#define RSND_SSI_HDMI_PORT1	0xf1
int rsnd_ssi_hdmi_port(struct rsnd_dai_stream *io);
void rsnd_ssi_parse_hdmi_connection(struct rsnd_priv *priv,
				    struct device_node *endpoint,
				    int dai_i);

#define rsnd_ssi_is_pin_sharing(io)	\
	__rsnd_ssi_is_pin_sharing(rsnd_io_to_mod_ssi(io))
int __rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod);
+58 −0
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */
#include <sound/simple_card_utils.h>
#include <linux/delay.h>
#include "rsnd.h"
#define RSND_SSI_NAME_SIZE 16
@@ -81,6 +82,8 @@ struct rsnd_ssi {
/* flags */
#define RSND_SSI_CLK_PIN_SHARE		(1 << 0)
#define RSND_SSI_NO_BUSIF		(1 << 1) /* SSI+DMA without BUSIF */
#define RSND_SSI_HDMI0			(1 << 2) /* for HDMI0 */
#define RSND_SSI_HDMI1			(1 << 3) /* for HDMI1 */

#define for_each_rsnd_ssi(pos, priv, i)					\
	for (i = 0;							\
@@ -99,6 +102,20 @@ struct rsnd_ssi {
#define rsnd_ssi_is_run_mods(mod, io) \
	(rsnd_ssi_run_mods(io) & (1 << rsnd_mod_id(mod)))

int rsnd_ssi_hdmi_port(struct rsnd_dai_stream *io)
{
	struct rsnd_mod *mod = rsnd_io_to_mod_ssi(io);
	struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);

	if (rsnd_ssi_mode_flags(ssi) & RSND_SSI_HDMI0)
		return RSND_SSI_HDMI_PORT0;

	if (rsnd_ssi_mode_flags(ssi) & RSND_SSI_HDMI1)
		return RSND_SSI_HDMI_PORT1;

	return 0;
}

int rsnd_ssi_use_busif(struct rsnd_dai_stream *io)
{
	struct rsnd_mod *mod = rsnd_io_to_mod_ssi(io);
@@ -835,6 +852,47 @@ void rsnd_parse_connect_ssi(struct rsnd_dai *rdai,
	of_node_put(node);
}

static void __rsnd_ssi_parse_hdmi_connection(struct rsnd_priv *priv,
					     struct rsnd_dai_stream *io,
					     struct device_node *remote_ep)
{
	struct device *dev = rsnd_priv_to_dev(priv);
	struct rsnd_mod *mod = rsnd_io_to_mod_ssi(io);
	struct rsnd_ssi *ssi;

	if (!mod)
		return;

	ssi  = rsnd_mod_to_ssi(mod);

	if (strstr(remote_ep->full_name, "hdmi0")) {
		ssi->flags |= RSND_SSI_HDMI0;
		dev_dbg(dev, "%s[%d] connected to HDMI0\n",
			 rsnd_mod_name(mod), rsnd_mod_id(mod));
	}

	if (strstr(remote_ep->full_name, "hdmi1")) {
		ssi->flags |= RSND_SSI_HDMI1;
		dev_dbg(dev, "%s[%d] connected to HDMI1\n",
			rsnd_mod_name(mod), rsnd_mod_id(mod));
	}
}

void rsnd_ssi_parse_hdmi_connection(struct rsnd_priv *priv,
				    struct device_node *endpoint,
				    int dai_i)
{
	struct rsnd_dai *rdai = rsnd_rdai_get(priv, dai_i);
	struct device_node *remote_ep;

	remote_ep = of_graph_get_remote_endpoint(endpoint);
	if (!remote_ep)
		return;

	__rsnd_ssi_parse_hdmi_connection(priv, &rdai->playback, remote_ep);
	__rsnd_ssi_parse_hdmi_connection(priv, &rdai->capture,  remote_ep);
}

struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id)
{
	if (WARN_ON(id < 0 || id >= rsnd_ssi_nr(priv)))
Loading