mirror of
https://github.com/torvalds/linux.git
synced 2026-09-24 06:24:02 +02:00
ASoC: meson: aiu: use aiu-formatter-i2s to format I2S output data
Create a new DAPM widget for "I2S formatter" and place it on the path between FIFO and output DAI interface. Remove I2S output formatting code from aiu-encoder-i2s since it's now implemented from aiu-formatter-i2s. Signed-off-by: Valerio Setti <vsetti@baylibre.com> Reviewed-by: Jerome Brunet <jbrunet@baylibre.com> Link: https://patch.msgid.link/20260610-reshape-aiu-as-axg-v2-4-cac3663a8b51@baylibre.com Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
2cbb32d8dc
commit
83b83024cd
|
|
@ -13,13 +13,8 @@
|
|||
#include "gx-formatter.h"
|
||||
#include "gx-interface.h"
|
||||
|
||||
#define AIU_I2S_SOURCE_DESC_MODE_8CH BIT(0)
|
||||
#define AIU_I2S_SOURCE_DESC_MODE_24BIT BIT(5)
|
||||
#define AIU_I2S_SOURCE_DESC_MODE_32BIT BIT(9)
|
||||
#define AIU_I2S_SOURCE_DESC_MODE_SPLIT BIT(11)
|
||||
#define AIU_RST_SOFT_I2S_FAST BIT(0)
|
||||
|
||||
#define AIU_I2S_DAC_CFG_MSB_FIRST BIT(2)
|
||||
#define AIU_CLK_CTRL_I2S_DIV_EN BIT(0)
|
||||
#define AIU_CLK_CTRL_I2S_DIV GENMASK(3, 2)
|
||||
#define AIU_CLK_CTRL_AOCLK_INVERT BIT(6)
|
||||
|
|
@ -37,49 +32,6 @@ static void aiu_encoder_i2s_divider_enable(struct snd_soc_component *component,
|
|||
enable ? AIU_CLK_CTRL_I2S_DIV_EN : 0);
|
||||
}
|
||||
|
||||
static int aiu_encoder_i2s_setup_desc(struct snd_soc_component *component,
|
||||
struct snd_pcm_hw_params *params)
|
||||
{
|
||||
/* Always operate in split (classic interleaved) mode */
|
||||
unsigned int desc = AIU_I2S_SOURCE_DESC_MODE_SPLIT;
|
||||
|
||||
/* Reset required to update the pipeline */
|
||||
snd_soc_component_write(component, AIU_RST_SOFT, AIU_RST_SOFT_I2S_FAST);
|
||||
snd_soc_component_read(component, AIU_I2S_SYNC);
|
||||
|
||||
switch (params_physical_width(params)) {
|
||||
case 16: /* Nothing to do */
|
||||
break;
|
||||
|
||||
case 32:
|
||||
desc |= (AIU_I2S_SOURCE_DESC_MODE_24BIT |
|
||||
AIU_I2S_SOURCE_DESC_MODE_32BIT);
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (params_channels(params)) {
|
||||
case 2: /* Nothing to do */
|
||||
break;
|
||||
case 8:
|
||||
desc |= AIU_I2S_SOURCE_DESC_MODE_8CH;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
snd_soc_component_update_bits(component, AIU_I2S_SOURCE_DESC,
|
||||
AIU_I2S_SOURCE_DESC_MODE_8CH |
|
||||
AIU_I2S_SOURCE_DESC_MODE_24BIT |
|
||||
AIU_I2S_SOURCE_DESC_MODE_32BIT |
|
||||
AIU_I2S_SOURCE_DESC_MODE_SPLIT,
|
||||
desc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int aiu_encoder_i2s_set_legacy_div(struct snd_soc_component *component,
|
||||
struct snd_pcm_hw_params *params,
|
||||
unsigned int bs)
|
||||
|
|
@ -173,11 +125,6 @@ static int aiu_encoder_i2s_set_clocks(struct snd_soc_component *component,
|
|||
if ((fs % 64) || (fs == 0))
|
||||
return -EINVAL;
|
||||
|
||||
/* Send data MSB first */
|
||||
snd_soc_component_update_bits(component, AIU_I2S_DAC_CFG,
|
||||
AIU_I2S_DAC_CFG_MSB_FIRST,
|
||||
AIU_I2S_DAC_CFG_MSB_FIRST);
|
||||
|
||||
/* Set bclk to lrlck ratio */
|
||||
snd_soc_component_update_bits(component, AIU_CODEC_DAC_LRCLK_CTRL,
|
||||
AIU_CODEC_DAC_LRCLK_CTRL_DIV,
|
||||
|
|
@ -223,12 +170,6 @@ static int aiu_encoder_i2s_hw_params(struct snd_pcm_substream *substream,
|
|||
}
|
||||
}
|
||||
|
||||
ret = aiu_encoder_i2s_setup_desc(component, params);
|
||||
if (ret) {
|
||||
dev_err(dai->dev, "setting i2s desc failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = aiu_encoder_i2s_set_clocks(component, params);
|
||||
if (ret) {
|
||||
dev_err(dai->dev, "setting i2s clocks failed: %d\n", ret);
|
||||
|
|
@ -411,6 +352,25 @@ static int aiu_encoder_i2s_startup(struct snd_pcm_substream *substream,
|
|||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* We're always operating in split mode for the playback stream.
|
||||
*
|
||||
* This setting arguably belong to the 'aiu-formatter', but it's kept
|
||||
* here for backward compatibility reason. At reset the I2S encoder
|
||||
* operates in normal mode which would only support 8ch, but by default
|
||||
* only 2ch are enabled. If a playback stream is started without
|
||||
* changing to split mode, then the I2S encoder doesn't consume audio
|
||||
* samples and the playback fails.
|
||||
* Moving this to 'aiu-formatter' would cause the split mode to be set
|
||||
* only when the formatter is enabled, which doesn't happen at boot as
|
||||
* the default value for "HDMI CTRL SRC" is "DISABLED".
|
||||
*/
|
||||
ret = snd_soc_component_update_bits(dai->component, AIU_I2S_SOURCE_DESC,
|
||||
AIU_I2S_SOURCE_DESC_MODE_SPLIT,
|
||||
AIU_I2S_SOURCE_DESC_MODE_SPLIT);
|
||||
if (ret < 0)
|
||||
dev_err(dai->dev, "failed to update AIU_I2S_SOURCE_DESC: %d", ret);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,13 +29,22 @@ static SOC_ENUM_SINGLE_DECL(aiu_spdif_encode_sel_enum, AIU_I2S_MISC,
|
|||
static const struct snd_kcontrol_new aiu_spdif_encode_mux =
|
||||
SOC_DAPM_ENUM("SPDIF Buffer Src", aiu_spdif_encode_sel_enum);
|
||||
|
||||
static const struct snd_soc_dapm_widget aiu_cpu_dapm_widgets[] = {
|
||||
SND_SOC_DAPM_MUX("SPDIF SRC SEL", SND_SOC_NOPM, 0, 0,
|
||||
&aiu_spdif_encode_mux),
|
||||
#define AIU_WIDGET_SPDIF_SRC_SEL 0
|
||||
#define AIU_WIDGET_I2S_FORMATTER 1
|
||||
|
||||
static struct snd_soc_dapm_widget aiu_cpu_dapm_widgets[] = {
|
||||
[AIU_WIDGET_SPDIF_SRC_SEL] =
|
||||
SND_SOC_DAPM_MUX("SPDIF SRC SEL", SND_SOC_NOPM, 0, 0,
|
||||
&aiu_spdif_encode_mux),
|
||||
[AIU_WIDGET_I2S_FORMATTER] =
|
||||
SND_SOC_DAPM_PGA_E("I2S Formatter", SND_SOC_NOPM, 0, 0, NULL, 0,
|
||||
gx_formatter_event,
|
||||
(SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD)),
|
||||
};
|
||||
|
||||
static const struct snd_soc_dapm_route aiu_cpu_dapm_routes[] = {
|
||||
{ "I2S Encoder Playback", NULL, "I2S FIFO Playback" },
|
||||
{ "I2S Formatter", NULL, "I2S FIFO Playback" },
|
||||
{ "I2S Encoder Playback", NULL, "I2S Formatter" },
|
||||
{ "SPDIF SRC SEL", "SPDIF", "SPDIF FIFO Playback" },
|
||||
{ "SPDIF SRC SEL", "I2S", "I2S FIFO Playback" },
|
||||
{ "SPDIF Encoder Playback", NULL, "SPDIF SRC SEL" },
|
||||
|
|
@ -172,6 +181,11 @@ static const struct regmap_config aiu_regmap_cfg = {
|
|||
.max_register = 0x2ac,
|
||||
};
|
||||
|
||||
const struct gx_formatter_driver aiu_formatter_i2s_drv = {
|
||||
.regmap_cfg = &aiu_regmap_cfg,
|
||||
.ops = &aiu_formatter_i2s_ops,
|
||||
};
|
||||
|
||||
static int aiu_clk_bulk_get(struct device *dev,
|
||||
const char * const *ids,
|
||||
unsigned int num,
|
||||
|
|
@ -282,6 +296,14 @@ static int aiu_probe(struct platform_device *pdev)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Allocate the aiu-formatter into its widget */
|
||||
ret = gx_formatter_create(dev, &aiu_cpu_dapm_widgets[AIU_WIDGET_I2S_FORMATTER],
|
||||
&aiu_formatter_i2s_drv, map);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to allocate aiu formatter\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Register the cpu component of the aiu */
|
||||
ret = snd_soc_register_component(dev, &aiu_cpu_component,
|
||||
aiu_cpu_dai_drv,
|
||||
|
|
@ -310,12 +332,14 @@ static int aiu_probe(struct platform_device *pdev)
|
|||
|
||||
return 0;
|
||||
err:
|
||||
gx_formatter_free(&aiu_cpu_dapm_widgets[AIU_WIDGET_I2S_FORMATTER]);
|
||||
snd_soc_unregister_component(dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void aiu_remove(struct platform_device *pdev)
|
||||
{
|
||||
gx_formatter_free(&aiu_cpu_dapm_widgets[AIU_WIDGET_I2S_FORMATTER]);
|
||||
snd_soc_unregister_component(&pdev->dev);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ extern const struct snd_soc_dai_ops aiu_fifo_i2s_dai_ops;
|
|||
extern const struct snd_soc_dai_ops aiu_fifo_spdif_dai_ops;
|
||||
extern const struct snd_soc_dai_ops aiu_encoder_i2s_dai_ops;
|
||||
extern const struct snd_soc_dai_ops aiu_encoder_spdif_dai_ops;
|
||||
extern const struct gx_formatter_ops aiu_formatter_i2s_ops;
|
||||
|
||||
#define AIU_IEC958_BPF 0x000
|
||||
#define AIU_958_MISC 0x010
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user