diff options
Diffstat (limited to 'sound/soc/sh/rcar/core.c')
-rw-r--r-- | sound/soc/sh/rcar/core.c | 73 |
1 files changed, 52 insertions, 21 deletions
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 2d269ac8c137..cb17f7d0cf0c 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -102,6 +102,7 @@ static const struct of_device_id rsnd_of_match[] = { { .compatible = "renesas,rcar_sound-gen1", .data = (void *)RSND_GEN1 }, { .compatible = "renesas,rcar_sound-gen2", .data = (void *)RSND_GEN2 }, { .compatible = "renesas,rcar_sound-gen3", .data = (void *)RSND_GEN3 }, + { .compatible = "renesas,rcar_sound-gen4", .data = (void *)RSND_GEN4 }, /* Special Handling */ { .compatible = "renesas,rcar_sound-r8a77990", .data = (void *)(RSND_GEN3 | RSND_SOC_E) }, {}, @@ -827,6 +828,13 @@ static int rsnd_soc_set_dai_tdm_slot(struct snd_soc_dai *dai, break; default: /* use default */ + /* + * Indicate warning if DT has "dai-tdm-slot-width" + * but the value was not expected. + */ + if (slot_width) + dev_warn(dev, "unsupported TDM slot width (%d), force to use default 32\n", + slot_width); slot_width = 32; } @@ -869,7 +877,8 @@ static unsigned int rsnd_soc_hw_rate_list[] = { static int rsnd_soc_hw_rule(struct rsnd_dai *rdai, unsigned int *list, int list_num, - struct snd_interval *baseline, struct snd_interval *iv) + struct snd_interval *baseline, struct snd_interval *iv, + struct rsnd_dai_stream *io, char *unit) { struct snd_interval p; unsigned int rate; @@ -899,6 +908,16 @@ static int rsnd_soc_hw_rule(struct rsnd_dai *rdai, } } + /* Indicate error once if it can't handle */ + if (!rsnd_flags_has(io, RSND_HW_RULE_ERR) && (p.min > p.max)) { + struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai); + struct device *dev = rsnd_priv_to_dev(priv); + + dev_warn(dev, "It can't handle %d %s <-> %d %s\n", + baseline->min, unit, baseline->max, unit); + rsnd_flags_set(io, RSND_HW_RULE_ERR); + } + return snd_interval_refine(iv, &p); } @@ -922,7 +941,7 @@ static int rsnd_soc_hw_rule_rate(struct snd_pcm_hw_params *params, return rsnd_soc_hw_rule(rdai, rsnd_soc_hw_rate_list, ARRAY_SIZE(rsnd_soc_hw_rate_list), - &ic, ir); + &ic, ir, io, "ch"); } static int rsnd_soc_hw_rule_channels(struct snd_pcm_hw_params *params, @@ -945,7 +964,7 @@ static int rsnd_soc_hw_rule_channels(struct snd_pcm_hw_params *params, return rsnd_soc_hw_rule(rdai, rsnd_soc_hw_channels_list, ARRAY_SIZE(rsnd_soc_hw_channels_list), - ir, &ic); + ir, &ic, io, "Hz"); } static const struct snd_pcm_hardware rsnd_pcm_hardware = { @@ -970,6 +989,8 @@ static int rsnd_soc_dai_startup(struct snd_pcm_substream *substream, unsigned int max_channels = rsnd_rdai_channels_get(rdai); int i; + rsnd_flags_del(io, RSND_HW_RULE_ERR); + rsnd_dai_stream_init(io, substream); /* @@ -1343,6 +1364,7 @@ static void __rsnd_dai_probe(struct rsnd_priv *priv, struct snd_soc_dai_driver *drv; struct rsnd_dai *rdai; struct device *dev = rsnd_priv_to_dev(priv); + int playback_exist = 0, capture_exist = 0; int io_i; rdai = rsnd_rdai_get(priv, dai_i); @@ -1357,22 +1379,6 @@ static void __rsnd_dai_probe(struct rsnd_priv *priv, drv->ops = &rsnd_soc_dai_ops; drv->pcm_new = rsnd_pcm_new; - snprintf(io_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 = 8; - drv->playback.stream_name = io_playback->name; - - snprintf(io_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 = 8; - drv->capture.stream_name = io_capture->name; - io_playback->rdai = rdai; io_capture->rdai = rdai; rsnd_rdai_channels_set(rdai, 2); /* default 2ch */ @@ -1386,6 +1392,14 @@ static void __rsnd_dai_probe(struct rsnd_priv *priv, if (!playback && !capture) break; + if (io_i == 0) { + /* check whether playback/capture property exists */ + if (playback) + playback_exist = 1; + if (capture) + capture_exist = 1; + } + rsnd_parse_connect_ssi(rdai, playback, capture); rsnd_parse_connect_ssiu(rdai, playback, capture); rsnd_parse_connect_src(rdai, playback, capture); @@ -1397,6 +1411,23 @@ static void __rsnd_dai_probe(struct rsnd_priv *priv, of_node_put(capture); } + if (playback_exist) { + snprintf(io_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 = 8; + drv->playback.stream_name = io_playback->name; + } + if (capture_exist) { + snprintf(io_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 = 8; + drv->capture.stream_name = io_capture->name; + } + if (rsnd_ssi_is_pin_sharing(io_capture) || rsnd_ssi_is_pin_sharing(io_playback)) { /* should have symmetric_rate if pin sharing */ @@ -1444,7 +1475,7 @@ static int rsnd_dai_probe(struct rsnd_priv *priv) if (is_graph) { for_each_endpoint_of_node(dai_node, dai_np) { __rsnd_dai_probe(priv, dai_np, dai_i); - if (rsnd_is_gen3(priv)) { + if (rsnd_is_gen3(priv) || rsnd_is_gen4(priv)) { rdai = rsnd_rdai_get(priv, dai_i); rsnd_parse_connect_graph(priv, &rdai->playback, dai_np); @@ -1455,7 +1486,7 @@ static int rsnd_dai_probe(struct rsnd_priv *priv) } else { for_each_child_of_node(dai_node, dai_np) { __rsnd_dai_probe(priv, dai_np, dai_i); - if (rsnd_is_gen3(priv)) { + if (rsnd_is_gen3(priv) || rsnd_is_gen4(priv)) { rdai = rsnd_rdai_get(priv, dai_i); rsnd_parse_connect_simple(priv, &rdai->playback, dai_np); |