diff options
-rw-r--r-- | Documentation/devicetree/bindings/sound/renesas,rsnd.txt | 34 | ||||
-rw-r--r-- | sound/soc/generic/simple-card.c | 6 | ||||
-rw-r--r-- | sound/soc/generic/simple-scu-card.c | 6 | ||||
-rw-r--r-- | sound/soc/sh/Kconfig | 2 | ||||
-rw-r--r-- | sound/soc/sh/rcar/adg.c | 8 | ||||
-rw-r--r-- | sound/soc/sh/rcar/cmd.c | 3 | ||||
-rw-r--r-- | sound/soc/sh/rcar/core.c | 204 | ||||
-rw-r--r-- | sound/soc/sh/rcar/gen.c | 2 | ||||
-rw-r--r-- | sound/soc/sh/rcar/rsnd.h | 11 | ||||
-rw-r--r-- | sound/soc/sh/rcar/src.c | 18 | ||||
-rw-r--r-- | sound/soc/sh/rcar/ssi.c | 58 | ||||
-rw-r--r-- | sound/soc/sh/rcar/ssiu.c | 37 |
12 files changed, 270 insertions, 119 deletions
diff --git a/Documentation/devicetree/bindings/sound/renesas,rsnd.txt b/Documentation/devicetree/bindings/sound/renesas,rsnd.txt index 15a7316e4c91..13cb21d53b8b 100644 --- a/Documentation/devicetree/bindings/sound/renesas,rsnd.txt +++ b/Documentation/devicetree/bindings/sound/renesas,rsnd.txt @@ -83,11 +83,11 @@ SRC can convert [xx]Hz to [yy]Hz. Then, it has below 2 modes ** Asynchronous mode ------------------ -You need to use "renesas,rsrc-card" sound card for it. +You need to use "simple-scu-audio-card" sound card for it. example) sound { - compatible = "renesas,rsrc-card"; + compatible = "simple-scu-audio-card"; ... /* * SRC Asynchronous mode setting @@ -97,12 +97,12 @@ example) * Inputed 48kHz data will be converted to * system specified Hz */ - convert-rate = <48000>; + simple-audio-card,convert-rate = <48000>; ... - cpu { + simple-audio-card,cpu { sound-dai = <&rcar_sound>; }; - codec { + simple-audio-card,codec { ... }; }; @@ -141,23 +141,23 @@ For more detail information, see below ${LINUX}/sound/soc/sh/rcar/ctu.c - comment of header -You need to use "renesas,rsrc-card" sound card for it. +You need to use "simple-scu-audio-card" sound card for it. example) sound { - compatible = "renesas,rsrc-card"; + compatible = "simple-scu-audio-card"; ... /* * CTU setting * All input data will be converted to 2ch * as output data */ - convert-channels = <2>; + simple-audio-card,convert-channels = <2>; ... - cpu { + simple-audio-card,cpu { sound-dai = <&rcar_sound>; }; - codec { + simple-audio-card,codec { ... }; }; @@ -190,22 +190,22 @@ and these sounds will be merged by MIX. aplay -D plughw:0,0 xxxx.wav & aplay -D plughw:0,1 yyyy.wav -You need to use "renesas,rsrc-card" sound card for it. +You need to use "simple-scu-audio-card" sound card for it. Ex) [MEM] -> [SRC1] -> [CTU02] -+-> [MIX0] -> [DVC0] -> [SSI0] | [MEM] -> [SRC2] -> [CTU03] -+ sound { - compatible = "renesas,rsrc-card"; + compatible = "simple-scu-audio-card"; ... - cpu@0 { + simple-audio-card,cpu@0 { sound-dai = <&rcar_sound 0>; }; - cpu@1 { + simple-audio-card,cpu@1 { sound-dai = <&rcar_sound 1>; }; - codec { + simple-audio-card,codec { ... }; }; @@ -368,6 +368,10 @@ Required properties: see below for detail. - #sound-dai-cells : it must be 0 if your system is using single DAI it must be 1 if your system is using multi DAI +- clocks : References to SSI/SRC/MIX/CTU/DVC/AUDIO_CLK clocks. +- clock-names : List of necessary clock names. + "ssi-all", "ssi.X", "src.X", "mix.X", "ctu.X", + "dvc.X", "clk_a", "clk_b", "clk_c", "clk_i" Optional properties: - #clock-cells : it must be 0 if your system has audio_clkout diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 2c9dedab5184..4dacaf78a0de 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -497,8 +497,10 @@ static int asoc_simple_card_probe(struct platform_device *pdev) snd_soc_card_set_drvdata(card, priv); ret = devm_snd_soc_register_card(dev, card); - if (ret >= 0) - return ret; + if (ret < 0) + goto err; + + return 0; err: asoc_simple_card_clean_reference(card); diff --git a/sound/soc/generic/simple-scu-card.c b/sound/soc/generic/simple-scu-card.c index dcbcab230d1b..9b9b01e12149 100644 --- a/sound/soc/generic/simple-scu-card.c +++ b/sound/soc/generic/simple-scu-card.c @@ -298,8 +298,10 @@ static int asoc_simple_card_probe(struct platform_device *pdev) snd_soc_card_set_drvdata(card, priv); ret = devm_snd_soc_register_card(dev, card); - if (ret >= 0) - return ret; + if (ret < 0) + goto err; + + return 0; err: asoc_simple_card_clean_reference(card); diff --git a/sound/soc/sh/Kconfig b/sound/soc/sh/Kconfig index 147ebecfed94..1aa5cd77ca24 100644 --- a/sound/soc/sh/Kconfig +++ b/sound/soc/sh/Kconfig @@ -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 diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index 66203d107a11..36bece8621b7 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c @@ -480,6 +480,9 @@ static void rsnd_adg_get_clkout(struct rsnd_priv *priv, if (req_rate[0] % 48000 == 0) adg->flags = AUDIO_OUT_48; + if (of_get_property(np, "clkout-lr-asynchronous", NULL)) + adg->flags = LRCLK_ASYNC; + /* * This driver is assuming that AUDIO_CLKA/AUDIO_CLKB/AUDIO_CLKC * have 44.1kHz or 48kHz base clocks for now. @@ -553,7 +556,6 @@ static void rsnd_adg_get_clkout(struct rsnd_priv *priv, clk = clk_register_fixed_rate(dev, clkout_name[i], parent_clk_name, 0, req_rate[0]); - adg->clkout[i] = ERR_PTR(-ENOENT); if (!IS_ERR(clk)) adg->clkout[i] = clk; } @@ -578,7 +580,6 @@ int rsnd_adg_probe(struct rsnd_priv *priv) { struct rsnd_adg *adg; struct device *dev = rsnd_priv_to_dev(priv); - struct device_node *np = dev->of_node; int ret; adg = devm_kzalloc(dev, sizeof(*adg), GFP_KERNEL); @@ -595,9 +596,6 @@ int rsnd_adg_probe(struct rsnd_priv *priv) rsnd_adg_get_clkin(priv, adg); rsnd_adg_get_clkout(priv, adg); - if (of_get_property(np, "clkout-lr-asynchronous", NULL)) - adg->flags = LRCLK_ASYNC; - priv->adg = adg; rsnd_adg_clk_enable(priv); diff --git a/sound/soc/sh/rcar/cmd.c b/sound/soc/sh/rcar/cmd.c index 7d92a24b7cfa..98835e9d1d7d 100644 --- a/sound/soc/sh/rcar/cmd.c +++ b/sound/soc/sh/rcar/cmd.c @@ -82,6 +82,9 @@ static int rsnd_cmd_init(struct rsnd_mod *mod, [9] = 0x2, }; + if (unlikely(!src)) + return -EIO; + data = path[rsnd_mod_id(src)] | cmd_case[rsnd_mod_id(src)] << 16; } diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 1744015408c3..080431543141 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -715,11 +715,16 @@ static int rsnd_soc_dai_startup(struct snd_pcm_substream *substream, { struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai); struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream); + int ret; /* * call rsnd_dai_call without spinlock */ - return rsnd_dai_call(nolock_start, io, priv); + ret = rsnd_dai_call(nolock_start, io, priv); + if (ret < 0) + rsnd_dai_call(nolock_stop, io, priv); + + return ret; } static void rsnd_soc_dai_shutdown(struct snd_pcm_substream *substream, @@ -769,32 +774,131 @@ void rsnd_parse_connect_common(struct rsnd_dai *rdai, of_node_put(node); } -static int rsnd_dai_probe(struct rsnd_priv *priv) +static struct device_node *rsnd_dai_of_node(struct rsnd_priv *priv, + int *is_graph) { + struct device *dev = rsnd_priv_to_dev(priv); + struct device_node *np = dev->of_node; struct device_node *dai_node; - struct device_node *dai_np; + struct device_node *ret; + + *is_graph = 0; + + /* + * parse both previous dai (= rcar_sound,dai), and + * graph dai (= ports/port) + */ + dai_node = of_get_child_by_name(np, RSND_NODE_DAI); + if (dai_node) { + ret = dai_node; + goto of_node_compatible; + } + + ret = np; + + dai_node = of_graph_get_next_endpoint(np, NULL); + if (dai_node) + goto of_node_graph; + + return NULL; + +of_node_graph: + *is_graph = 1; +of_node_compatible: + of_node_put(dai_node); + + return ret; +} + +static void __rsnd_dai_probe(struct rsnd_priv *priv, + struct device_node *dai_np, + int dai_i, int is_graph) +{ struct device_node *playback, *capture; struct rsnd_dai_stream *io_playback; struct rsnd_dai_stream *io_capture; - struct snd_soc_dai_driver *rdrv, *drv; + struct snd_soc_dai_driver *drv; struct rsnd_dai *rdai; struct device *dev = rsnd_priv_to_dev(priv); - int nr, dai_i, io_i; - int ret; - - dai_node = rsnd_dai_of_node(priv); - nr = of_get_child_count(dai_node); - if (!nr) { - ret = -EINVAL; - goto rsnd_dai_probe_done; + int io_i; + + rdai = rsnd_rdai_get(priv, dai_i); + drv = priv->daidrv + dai_i; + io_playback = &rdai->playback; + io_capture = &rdai->capture; + + snprintf(rdai->name, RSND_DAI_NAME_SIZE, "rsnd-dai.%d", dai_i); + + rdai->priv = priv; + drv->name = rdai->name; + drv->ops = &rsnd_soc_dai_ops; + + snprintf(rdai->playback.name, RSND_DAI_NAME_SIZE, + "DAI%d Playback", dai_i); + drv->playback.rates = RSND_RATES; + drv->playback.formats = RSND_FMTS; + drv->playback.channels_min = 2; + drv->playback.channels_max = 6; + drv->playback.stream_name = rdai->playback.name; + + snprintf(rdai->capture.name, RSND_DAI_NAME_SIZE, + "DAI%d Capture", dai_i); + drv->capture.rates = RSND_RATES; + drv->capture.formats = RSND_FMTS; + drv->capture.channels_min = 2; + drv->capture.channels_max = 6; + drv->capture.stream_name = rdai->capture.name; + + rdai->playback.rdai = rdai; + rdai->capture.rdai = rdai; + rsnd_set_slot(rdai, 2, 1); /* default */ + + for (io_i = 0;; io_i++) { + playback = of_parse_phandle(dai_np, "playback", io_i); + capture = of_parse_phandle(dai_np, "capture", io_i); + + if (!playback && !capture) + break; + + rsnd_parse_connect_ssi(rdai, playback, capture); + rsnd_parse_connect_src(rdai, playback, capture); + rsnd_parse_connect_ctu(rdai, playback, capture); + rsnd_parse_connect_mix(rdai, playback, capture); + rsnd_parse_connect_dvc(rdai, playback, capture); + + of_node_put(playback); + of_node_put(capture); } + dev_dbg(dev, "%s (%s/%s)\n", rdai->name, + rsnd_io_to_mod_ssi(io_playback) ? "play" : " -- ", + rsnd_io_to_mod_ssi(io_capture) ? "capture" : " -- "); +} + +static int rsnd_dai_probe(struct rsnd_priv *priv) +{ + struct device_node *dai_node; + struct device_node *dai_np; + struct snd_soc_dai_driver *rdrv; + struct device *dev = rsnd_priv_to_dev(priv); + struct rsnd_dai *rdai; + int nr; + int is_graph; + int dai_i; + + dai_node = rsnd_dai_of_node(priv, &is_graph); + if (is_graph) + nr = of_graph_get_endpoint_count(dai_node); + else + nr = of_get_child_count(dai_node); + + if (!nr) + return -EINVAL; + rdrv = devm_kzalloc(dev, sizeof(*rdrv) * nr, GFP_KERNEL); rdai = devm_kzalloc(dev, sizeof(*rdai) * nr, GFP_KERNEL); - if (!rdrv || !rdai) { - ret = -ENOMEM; - goto rsnd_dai_probe_done; - } + if (!rdrv || !rdai) + return -ENOMEM; priv->rdai_nr = nr; priv->daidrv = rdrv; @@ -804,68 +908,18 @@ static int rsnd_dai_probe(struct rsnd_priv *priv) * parse all dai */ dai_i = 0; - for_each_child_of_node(dai_node, dai_np) { - rdai = rsnd_rdai_get(priv, dai_i); - drv = rdrv + dai_i; - io_playback = &rdai->playback; - io_capture = &rdai->capture; - - snprintf(rdai->name, RSND_DAI_NAME_SIZE, "rsnd-dai.%d", dai_i); - - rdai->priv = priv; - drv->name = rdai->name; - drv->ops = &rsnd_soc_dai_ops; - - snprintf(rdai->playback.name, RSND_DAI_NAME_SIZE, - "DAI%d Playback", dai_i); - drv->playback.rates = RSND_RATES; - drv->playback.formats = RSND_FMTS; - drv->playback.channels_min = 2; - drv->playback.channels_max = 6; - drv->playback.stream_name = rdai->playback.name; - - snprintf(rdai->capture.name, RSND_DAI_NAME_SIZE, - "DAI%d Capture", dai_i); - drv->capture.rates = RSND_RATES; - drv->capture.formats = RSND_FMTS; - drv->capture.channels_min = 2; - drv->capture.channels_max = 6; - drv->capture.stream_name = rdai->capture.name; - - rdai->playback.rdai = rdai; - rdai->capture.rdai = rdai; - rsnd_set_slot(rdai, 2, 1); /* default */ - - for (io_i = 0;; io_i++) { - playback = of_parse_phandle(dai_np, "playback", io_i); - capture = of_parse_phandle(dai_np, "capture", io_i); - - if (!playback && !capture) - break; - - rsnd_parse_connect_ssi(rdai, playback, capture); - rsnd_parse_connect_src(rdai, playback, capture); - rsnd_parse_connect_ctu(rdai, playback, capture); - rsnd_parse_connect_mix(rdai, playback, capture); - rsnd_parse_connect_dvc(rdai, playback, capture); - - of_node_put(playback); - of_node_put(capture); + if (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++; } - - dai_i++; - - dev_dbg(dev, "%s (%s/%s)\n", rdai->name, - rsnd_io_to_mod_ssi(io_playback) ? "play" : " -- ", - rsnd_io_to_mod_ssi(io_capture) ? "capture" : " -- "); + } else { + for_each_child_of_node(dai_node, dai_np) + __rsnd_dai_probe(priv, dai_np, dai_i++, is_graph); } - ret = 0; - -rsnd_dai_probe_done: - of_node_put(dai_node); - - return ret; + return 0; } /* diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index 63b6d3c28021..99f93a17511e 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c @@ -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), diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index dbf4163427e8..037e33ffa69d 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -18,6 +18,7 @@ #include <linux/list.h> #include <linux/module.h> #include <linux/of_device.h> +#include <linux/of_graph.h> #include <linux/of_irq.h> #include <linux/sh_dma.h> #include <linux/workqueue.h> @@ -169,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, @@ -475,7 +478,6 @@ int rsnd_dai_pointer_offset(struct rsnd_dai_stream *io, int additional); int rsnd_dai_connect(struct rsnd_mod *mod, struct rsnd_dai_stream *io, enum rsnd_mod_type type); -#define rsnd_dai_of_node(priv) rsnd_parse_of_node(priv, RSND_NODE_DAI) /* * R-Car Gen1/Gen2 @@ -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); diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c index 20b5b2ec625e..e4bde0c8d93a 100644 --- a/sound/soc/sh/rcar/src.c +++ b/sound/soc/sh/rcar/src.c @@ -12,10 +12,6 @@ #define SRC_NAME "src" -/* SRCx_STATUS */ -#define OUF_SRCO ((1 << 12) | (1 << 13)) -#define OUF_SRCI ((1 << 9) | (1 << 8)) - /* SCU_SYSTEM_STATUS0/1 */ #define OUF_SRC(id) ((1 << (id + 16)) | (1 << id)) @@ -55,20 +51,6 @@ struct rsnd_src { * */ -/* - * src.c is caring... - * - * Gen1 - * - * [mem] -> [SRU] -> [SSI] - * |--------| - * - * Gen2 - * - * [mem] -> [SRC] -> [SSIU] -> [SSI] - * |-----------------| - */ - static void rsnd_src_activation(struct rsnd_mod *mod) { rsnd_mod_write(mod, SRC_SWRSR, 0); diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 135c5669f796..d0602c189736 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -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))) diff --git a/sound/soc/sh/rcar/ssiu.c b/sound/soc/sh/rcar/ssiu.c index 14fafdaf1395..13d648ef1ed6 100644 --- a/sound/soc/sh/rcar/ssiu.c +++ b/sound/soc/sh/rcar/ssiu.c @@ -123,6 +123,7 @@ static int rsnd_ssiu_init_gen2(struct rsnd_mod *mod, struct rsnd_dai_stream *io, struct rsnd_priv *priv) { + int hdmi = rsnd_ssi_hdmi_port(io); int ret; ret = rsnd_ssiu_init(mod, io, priv); @@ -149,6 +150,42 @@ static int rsnd_ssiu_init_gen2(struct rsnd_mod *mod, rsnd_get_dalign(mod, io)); } + if (hdmi) { + enum rsnd_mod_type rsnd_ssi_array[] = { + RSND_MOD_SSIM1, + RSND_MOD_SSIM2, + RSND_MOD_SSIM3, + }; + struct rsnd_mod *ssi_mod = rsnd_io_to_mod_ssi(io); + struct rsnd_mod *pos; + u32 val; + int i, shift; + + i = rsnd_mod_id(ssi_mod); + + /* output all same SSI as default */ + val = i << 16 | + i << 20 | + i << 24 | + i << 28 | + i; + + for_each_rsnd_mod_array(i, pos, io, rsnd_ssi_array) { + shift = (i * 4) + 16; + val = (val & ~(0xF << shift)) | + rsnd_mod_id(pos) << shift; + } + + switch (hdmi) { + case RSND_SSI_HDMI_PORT0: + rsnd_mod_write(mod, HDMI0_SEL, val); + break; + case RSND_SSI_HDMI_PORT1: + rsnd_mod_write(mod, HDMI1_SEL, val); + break; + } + } + return 0; } |