[alsa-devel] [PATCH 0/4] ASoC: meson: axg-fifo: fix depth handling
This patchset improves the handling the depth of the different fifos found in amlogic audio subsystems derived from the axg family.
Initially, it was reported that, when the period is less than 8kB on sm1 and with TODDR A, several period are coming at once. This is because the field related to the fifo request threshold changed on the sm1 SoC and also because TODDR A instance is significantly larger compared to the other instances.
With this initial issue fixed, I used the opportunity to improve the driver and properly deal with the different fifo depth found in these SoCs.
Jerome Brunet (4): ASoC: meson: axg-fifo: fix fifo threshold setup ASoC: meson: axg-fifo: add fifo depth to the bindings documentation ASoC: meson: axg-fifo: improve depth handling ASoC: meson: axg-fifo: relax period size constraints
.../bindings/sound/amlogic,axg-fifo.txt | 4 ++ sound/soc/meson/axg-fifo.c | 50 ++++++++++++++++--- sound/soc/meson/axg-fifo.h | 9 ++-- sound/soc/meson/axg-frddr.c | 33 ++++++------ sound/soc/meson/axg-toddr.c | 21 ++++---- 5 files changed, 76 insertions(+), 41 deletions(-)
On TODDR sm1, the fifo threshold register field is slightly different compared to the other SoCs. This leads to the fifo A being flushed to memory every 8kB. If the period is smaller than that, several periods are pushed to memory and notified at once. This is not ideal.
Fix the register field update. With this, the fifos are flushed every 128B. We could still do better, like adapt the threshold depending on the period size, but at least it consistent across the different SoC/fifos
Fixes: 5ac825c3d85e ("ASoC: meson: axg-toddr: add sm1 support") Reported-by: Alden DSouza aldend@google.com Signed-off-by: Jerome Brunet jbrunet@baylibre.com --- sound/soc/meson/axg-fifo.c | 27 +++++++++++++++++++++++++-- sound/soc/meson/axg-fifo.h | 6 ++++-- sound/soc/meson/axg-frddr.c | 24 ++++++++++++------------ sound/soc/meson/axg-toddr.c | 21 +++++++++------------ 4 files changed, 50 insertions(+), 28 deletions(-)
diff --git a/sound/soc/meson/axg-fifo.c b/sound/soc/meson/axg-fifo.c index 772eda857019..4365086c9a31 100644 --- a/sound/soc/meson/axg-fifo.c +++ b/sound/soc/meson/axg-fifo.c @@ -113,8 +113,10 @@ int axg_fifo_pcm_hw_params(struct snd_soc_component *component, { struct snd_pcm_runtime *runtime = ss->runtime; struct axg_fifo *fifo = axg_fifo_data(ss); + unsigned int burst_num, period, threshold; dma_addr_t end_ptr; - unsigned int burst_num; + + period = params_period_bytes(params);
/* Setup dma memory pointers */ end_ptr = runtime->dma_addr + runtime->dma_bytes - AXG_FIFO_BURST; @@ -122,9 +124,25 @@ int axg_fifo_pcm_hw_params(struct snd_soc_component *component, regmap_write(fifo->map, FIFO_FINISH_ADDR, end_ptr);
/* Setup interrupt periodicity */ - burst_num = params_period_bytes(params) / AXG_FIFO_BURST; + burst_num = period / AXG_FIFO_BURST; regmap_write(fifo->map, FIFO_INT_ADDR, burst_num);
+ /* + * Start the fifo request on the smallest of the following: + * - Half the fifo size + * - Half the period size + */ + threshold = min(period / 2, + (unsigned int)AXG_FIFO_MIN_DEPTH / 2); + + /* + * With the threshold in bytes, register value is: + * V = (threshold / burst) - 1 + */ + threshold /= AXG_FIFO_BURST; + regmap_field_write(fifo->field_threshold, + threshold ? threshold - 1 : 0); + /* Enable block count irq */ regmap_update_bits(fifo->map, FIFO_CTRL0, CTRL0_INT_EN(FIFO_INT_COUNT_REPEAT), @@ -347,6 +365,11 @@ int axg_fifo_probe(struct platform_device *pdev) return fifo->irq; }
+ fifo->field_threshold = + devm_regmap_field_alloc(dev, fifo->map, data->field_threshold); + if (IS_ERR(fifo->field_threshold)) + return PTR_ERR(fifo->field_threshold); + return devm_snd_soc_register_component(dev, data->component_drv, data->dai_drv, 1); } diff --git a/sound/soc/meson/axg-fifo.h b/sound/soc/meson/axg-fifo.h index cf928d43b558..c442195ba191 100644 --- a/sound/soc/meson/axg-fifo.h +++ b/sound/soc/meson/axg-fifo.h @@ -9,7 +9,9 @@
struct clk; struct platform_device; +struct reg_field; struct regmap; +struct regmap_field; struct reset_control;
struct snd_soc_component_driver; @@ -50,8 +52,6 @@ struct snd_soc_pcm_runtime; #define CTRL1_STATUS2_SEL_MASK GENMASK(11, 8) #define CTRL1_STATUS2_SEL(x) ((x) << 8) #define STATUS2_SEL_DDR_READ 0 -#define CTRL1_THRESHOLD_MASK GENMASK(23, 16) -#define CTRL1_THRESHOLD(x) ((x) << 16) #define CTRL1_FRDDR_DEPTH_MASK GENMASK(31, 24) #define CTRL1_FRDDR_DEPTH(x) ((x) << 24) #define FIFO_START_ADDR 0x08 @@ -67,12 +67,14 @@ struct axg_fifo { struct regmap *map; struct clk *pclk; struct reset_control *arb; + struct regmap_field *field_threshold; int irq; };
struct axg_fifo_match_data { const struct snd_soc_component_driver *component_drv; struct snd_soc_dai_driver *dai_drv; + struct reg_field field_threshold; };
int axg_fifo_pcm_open(struct snd_soc_component *component, diff --git a/sound/soc/meson/axg-frddr.c b/sound/soc/meson/axg-frddr.c index 0a7d41257a38..df104303351f 100644 --- a/sound/soc/meson/axg-frddr.c +++ b/sound/soc/meson/axg-frddr.c @@ -50,7 +50,7 @@ static int axg_frddr_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct axg_fifo *fifo = snd_soc_dai_get_drvdata(dai); - unsigned int fifo_depth, fifo_threshold; + unsigned int fifo_depth; int ret;
/* Enable pclk to access registers and clock the fifo ip */ @@ -68,11 +68,8 @@ static int axg_frddr_dai_startup(struct snd_pcm_substream *substream, * Depth and threshold are zero based. */ fifo_depth = AXG_FIFO_MIN_CNT - 1; - fifo_threshold = (AXG_FIFO_MIN_CNT / 2) - 1; - regmap_update_bits(fifo->map, FIFO_CTRL1, - CTRL1_FRDDR_DEPTH_MASK | CTRL1_THRESHOLD_MASK, - CTRL1_FRDDR_DEPTH(fifo_depth) | - CTRL1_THRESHOLD(fifo_threshold)); + regmap_update_bits(fifo->map, FIFO_CTRL1, CTRL1_FRDDR_DEPTH_MASK, + CTRL1_FRDDR_DEPTH(fifo_depth));
return 0; } @@ -158,8 +155,9 @@ static const struct snd_soc_component_driver axg_frddr_component_drv = { };
static const struct axg_fifo_match_data axg_frddr_match_data = { - .component_drv = &axg_frddr_component_drv, - .dai_drv = &axg_frddr_dai_drv + .field_threshold = REG_FIELD(FIFO_CTRL1, 16, 23), + .component_drv = &axg_frddr_component_drv, + .dai_drv = &axg_frddr_dai_drv };
static const struct snd_soc_dai_ops g12a_frddr_ops = { @@ -281,8 +279,9 @@ static const struct snd_soc_component_driver g12a_frddr_component_drv = { };
static const struct axg_fifo_match_data g12a_frddr_match_data = { - .component_drv = &g12a_frddr_component_drv, - .dai_drv = &g12a_frddr_dai_drv + .field_threshold = REG_FIELD(FIFO_CTRL1, 16, 23), + .component_drv = &g12a_frddr_component_drv, + .dai_drv = &g12a_frddr_dai_drv };
/* On SM1, the output selection in on CTRL2 */ @@ -350,8 +349,9 @@ static const struct snd_soc_component_driver sm1_frddr_component_drv = { };
static const struct axg_fifo_match_data sm1_frddr_match_data = { - .component_drv = &sm1_frddr_component_drv, - .dai_drv = &g12a_frddr_dai_drv + .field_threshold = REG_FIELD(FIFO_CTRL1, 16, 23), + .component_drv = &sm1_frddr_component_drv, + .dai_drv = &g12a_frddr_dai_drv };
static const struct of_device_id axg_frddr_of_match[] = { diff --git a/sound/soc/meson/axg-toddr.c b/sound/soc/meson/axg-toddr.c index f6023397c8fe..e711abcf8c12 100644 --- a/sound/soc/meson/axg-toddr.c +++ b/sound/soc/meson/axg-toddr.c @@ -89,7 +89,6 @@ static int axg_toddr_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct axg_fifo *fifo = snd_soc_dai_get_drvdata(dai); - unsigned int fifo_threshold; int ret;
/* Enable pclk to access registers and clock the fifo ip */ @@ -107,11 +106,6 @@ static int axg_toddr_dai_startup(struct snd_pcm_substream *substream, /* Apply single buffer mode to the interface */ regmap_update_bits(fifo->map, FIFO_CTRL0, CTRL0_TODDR_PP_MODE, 0);
- /* TODDR does not have a configurable fifo depth */ - fifo_threshold = AXG_FIFO_MIN_CNT - 1; - regmap_update_bits(fifo->map, FIFO_CTRL1, CTRL1_THRESHOLD_MASK, - CTRL1_THRESHOLD(fifo_threshold)); - return 0; }
@@ -190,8 +184,9 @@ static const struct snd_soc_component_driver axg_toddr_component_drv = { };
static const struct axg_fifo_match_data axg_toddr_match_data = { - .component_drv = &axg_toddr_component_drv, - .dai_drv = &axg_toddr_dai_drv + .field_threshold = REG_FIELD(FIFO_CTRL1, 16, 23), + .component_drv = &axg_toddr_component_drv, + .dai_drv = &axg_toddr_dai_drv };
static const struct snd_soc_dai_ops g12a_toddr_ops = { @@ -228,8 +223,9 @@ static const struct snd_soc_component_driver g12a_toddr_component_drv = { };
static const struct axg_fifo_match_data g12a_toddr_match_data = { - .component_drv = &g12a_toddr_component_drv, - .dai_drv = &g12a_toddr_dai_drv + .field_threshold = REG_FIELD(FIFO_CTRL1, 16, 23), + .component_drv = &g12a_toddr_component_drv, + .dai_drv = &g12a_toddr_dai_drv };
static const char * const sm1_toddr_sel_texts[] = { @@ -297,8 +293,9 @@ static const struct snd_soc_component_driver sm1_toddr_component_drv = { };
static const struct axg_fifo_match_data sm1_toddr_match_data = { - .component_drv = &sm1_toddr_component_drv, - .dai_drv = &g12a_toddr_dai_drv + .field_threshold = REG_FIELD(FIFO_CTRL1, 12, 23), + .component_drv = &sm1_toddr_component_drv, + .dai_drv = &g12a_toddr_dai_drv };
static const struct of_device_id axg_toddr_of_match[] = {
The patch
ASoC: meson: axg-fifo: fix fifo threshold setup
has been applied to the asoc tree at
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-5.6
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
From 864cee90d4bd870e5d5e5a0b1a6f055f4f951350 Mon Sep 17 00:00:00 2001
From: Jerome Brunet jbrunet@baylibre.com Date: Wed, 18 Dec 2019 18:24:17 +0100 Subject: [PATCH] ASoC: meson: axg-fifo: fix fifo threshold setup
On TODDR sm1, the fifo threshold register field is slightly different compared to the other SoCs. This leads to the fifo A being flushed to memory every 8kB. If the period is smaller than that, several periods are pushed to memory and notified at once. This is not ideal.
Fix the register field update. With this, the fifos are flushed every 128B. We could still do better, like adapt the threshold depending on the period size, but at least it consistent across the different SoC/fifos
Fixes: 5ac825c3d85e ("ASoC: meson: axg-toddr: add sm1 support") Reported-by: Alden DSouza aldend@google.com Signed-off-by: Jerome Brunet jbrunet@baylibre.com Link: https://lore.kernel.org/r/20191218172420.1199117-2-jbrunet@baylibre.com Signed-off-by: Mark Brown broonie@kernel.org --- sound/soc/meson/axg-fifo.c | 27 +++++++++++++++++++++++++-- sound/soc/meson/axg-fifo.h | 6 ++++-- sound/soc/meson/axg-frddr.c | 24 ++++++++++++------------ sound/soc/meson/axg-toddr.c | 21 +++++++++------------ 4 files changed, 50 insertions(+), 28 deletions(-)
diff --git a/sound/soc/meson/axg-fifo.c b/sound/soc/meson/axg-fifo.c index 772eda857019..4365086c9a31 100644 --- a/sound/soc/meson/axg-fifo.c +++ b/sound/soc/meson/axg-fifo.c @@ -113,8 +113,10 @@ int axg_fifo_pcm_hw_params(struct snd_soc_component *component, { struct snd_pcm_runtime *runtime = ss->runtime; struct axg_fifo *fifo = axg_fifo_data(ss); + unsigned int burst_num, period, threshold; dma_addr_t end_ptr; - unsigned int burst_num; + + period = params_period_bytes(params);
/* Setup dma memory pointers */ end_ptr = runtime->dma_addr + runtime->dma_bytes - AXG_FIFO_BURST; @@ -122,9 +124,25 @@ int axg_fifo_pcm_hw_params(struct snd_soc_component *component, regmap_write(fifo->map, FIFO_FINISH_ADDR, end_ptr);
/* Setup interrupt periodicity */ - burst_num = params_period_bytes(params) / AXG_FIFO_BURST; + burst_num = period / AXG_FIFO_BURST; regmap_write(fifo->map, FIFO_INT_ADDR, burst_num);
+ /* + * Start the fifo request on the smallest of the following: + * - Half the fifo size + * - Half the period size + */ + threshold = min(period / 2, + (unsigned int)AXG_FIFO_MIN_DEPTH / 2); + + /* + * With the threshold in bytes, register value is: + * V = (threshold / burst) - 1 + */ + threshold /= AXG_FIFO_BURST; + regmap_field_write(fifo->field_threshold, + threshold ? threshold - 1 : 0); + /* Enable block count irq */ regmap_update_bits(fifo->map, FIFO_CTRL0, CTRL0_INT_EN(FIFO_INT_COUNT_REPEAT), @@ -347,6 +365,11 @@ int axg_fifo_probe(struct platform_device *pdev) return fifo->irq; }
+ fifo->field_threshold = + devm_regmap_field_alloc(dev, fifo->map, data->field_threshold); + if (IS_ERR(fifo->field_threshold)) + return PTR_ERR(fifo->field_threshold); + return devm_snd_soc_register_component(dev, data->component_drv, data->dai_drv, 1); } diff --git a/sound/soc/meson/axg-fifo.h b/sound/soc/meson/axg-fifo.h index cf928d43b558..c442195ba191 100644 --- a/sound/soc/meson/axg-fifo.h +++ b/sound/soc/meson/axg-fifo.h @@ -9,7 +9,9 @@
struct clk; struct platform_device; +struct reg_field; struct regmap; +struct regmap_field; struct reset_control;
struct snd_soc_component_driver; @@ -50,8 +52,6 @@ struct snd_soc_pcm_runtime; #define CTRL1_STATUS2_SEL_MASK GENMASK(11, 8) #define CTRL1_STATUS2_SEL(x) ((x) << 8) #define STATUS2_SEL_DDR_READ 0 -#define CTRL1_THRESHOLD_MASK GENMASK(23, 16) -#define CTRL1_THRESHOLD(x) ((x) << 16) #define CTRL1_FRDDR_DEPTH_MASK GENMASK(31, 24) #define CTRL1_FRDDR_DEPTH(x) ((x) << 24) #define FIFO_START_ADDR 0x08 @@ -67,12 +67,14 @@ struct axg_fifo { struct regmap *map; struct clk *pclk; struct reset_control *arb; + struct regmap_field *field_threshold; int irq; };
struct axg_fifo_match_data { const struct snd_soc_component_driver *component_drv; struct snd_soc_dai_driver *dai_drv; + struct reg_field field_threshold; };
int axg_fifo_pcm_open(struct snd_soc_component *component, diff --git a/sound/soc/meson/axg-frddr.c b/sound/soc/meson/axg-frddr.c index 0a7d41257a38..df104303351f 100644 --- a/sound/soc/meson/axg-frddr.c +++ b/sound/soc/meson/axg-frddr.c @@ -50,7 +50,7 @@ static int axg_frddr_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct axg_fifo *fifo = snd_soc_dai_get_drvdata(dai); - unsigned int fifo_depth, fifo_threshold; + unsigned int fifo_depth; int ret;
/* Enable pclk to access registers and clock the fifo ip */ @@ -68,11 +68,8 @@ static int axg_frddr_dai_startup(struct snd_pcm_substream *substream, * Depth and threshold are zero based. */ fifo_depth = AXG_FIFO_MIN_CNT - 1; - fifo_threshold = (AXG_FIFO_MIN_CNT / 2) - 1; - regmap_update_bits(fifo->map, FIFO_CTRL1, - CTRL1_FRDDR_DEPTH_MASK | CTRL1_THRESHOLD_MASK, - CTRL1_FRDDR_DEPTH(fifo_depth) | - CTRL1_THRESHOLD(fifo_threshold)); + regmap_update_bits(fifo->map, FIFO_CTRL1, CTRL1_FRDDR_DEPTH_MASK, + CTRL1_FRDDR_DEPTH(fifo_depth));
return 0; } @@ -158,8 +155,9 @@ static const struct snd_soc_component_driver axg_frddr_component_drv = { };
static const struct axg_fifo_match_data axg_frddr_match_data = { - .component_drv = &axg_frddr_component_drv, - .dai_drv = &axg_frddr_dai_drv + .field_threshold = REG_FIELD(FIFO_CTRL1, 16, 23), + .component_drv = &axg_frddr_component_drv, + .dai_drv = &axg_frddr_dai_drv };
static const struct snd_soc_dai_ops g12a_frddr_ops = { @@ -281,8 +279,9 @@ static const struct snd_soc_component_driver g12a_frddr_component_drv = { };
static const struct axg_fifo_match_data g12a_frddr_match_data = { - .component_drv = &g12a_frddr_component_drv, - .dai_drv = &g12a_frddr_dai_drv + .field_threshold = REG_FIELD(FIFO_CTRL1, 16, 23), + .component_drv = &g12a_frddr_component_drv, + .dai_drv = &g12a_frddr_dai_drv };
/* On SM1, the output selection in on CTRL2 */ @@ -350,8 +349,9 @@ static const struct snd_soc_component_driver sm1_frddr_component_drv = { };
static const struct axg_fifo_match_data sm1_frddr_match_data = { - .component_drv = &sm1_frddr_component_drv, - .dai_drv = &g12a_frddr_dai_drv + .field_threshold = REG_FIELD(FIFO_CTRL1, 16, 23), + .component_drv = &sm1_frddr_component_drv, + .dai_drv = &g12a_frddr_dai_drv };
static const struct of_device_id axg_frddr_of_match[] = { diff --git a/sound/soc/meson/axg-toddr.c b/sound/soc/meson/axg-toddr.c index f6023397c8fe..e711abcf8c12 100644 --- a/sound/soc/meson/axg-toddr.c +++ b/sound/soc/meson/axg-toddr.c @@ -89,7 +89,6 @@ static int axg_toddr_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct axg_fifo *fifo = snd_soc_dai_get_drvdata(dai); - unsigned int fifo_threshold; int ret;
/* Enable pclk to access registers and clock the fifo ip */ @@ -107,11 +106,6 @@ static int axg_toddr_dai_startup(struct snd_pcm_substream *substream, /* Apply single buffer mode to the interface */ regmap_update_bits(fifo->map, FIFO_CTRL0, CTRL0_TODDR_PP_MODE, 0);
- /* TODDR does not have a configurable fifo depth */ - fifo_threshold = AXG_FIFO_MIN_CNT - 1; - regmap_update_bits(fifo->map, FIFO_CTRL1, CTRL1_THRESHOLD_MASK, - CTRL1_THRESHOLD(fifo_threshold)); - return 0; }
@@ -190,8 +184,9 @@ static const struct snd_soc_component_driver axg_toddr_component_drv = { };
static const struct axg_fifo_match_data axg_toddr_match_data = { - .component_drv = &axg_toddr_component_drv, - .dai_drv = &axg_toddr_dai_drv + .field_threshold = REG_FIELD(FIFO_CTRL1, 16, 23), + .component_drv = &axg_toddr_component_drv, + .dai_drv = &axg_toddr_dai_drv };
static const struct snd_soc_dai_ops g12a_toddr_ops = { @@ -228,8 +223,9 @@ static const struct snd_soc_component_driver g12a_toddr_component_drv = { };
static const struct axg_fifo_match_data g12a_toddr_match_data = { - .component_drv = &g12a_toddr_component_drv, - .dai_drv = &g12a_toddr_dai_drv + .field_threshold = REG_FIELD(FIFO_CTRL1, 16, 23), + .component_drv = &g12a_toddr_component_drv, + .dai_drv = &g12a_toddr_dai_drv };
static const char * const sm1_toddr_sel_texts[] = { @@ -297,8 +293,9 @@ static const struct snd_soc_component_driver sm1_toddr_component_drv = { };
static const struct axg_fifo_match_data sm1_toddr_match_data = { - .component_drv = &sm1_toddr_component_drv, - .dai_drv = &g12a_toddr_dai_drv + .field_threshold = REG_FIELD(FIFO_CTRL1, 12, 23), + .component_drv = &sm1_toddr_component_drv, + .dai_drv = &g12a_toddr_dai_drv };
static const struct of_device_id axg_toddr_of_match[] = {
Add a new property with the depth of the fifo in bytes. This is useful since some instance of the fifo, even on the same SoC, may have different depth. The depth is useful is set some parameters of the fifo.
Signed-off-by: Jerome Brunet jbrunet@baylibre.com --- Documentation/devicetree/bindings/sound/amlogic,axg-fifo.txt | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/Documentation/devicetree/bindings/sound/amlogic,axg-fifo.txt b/Documentation/devicetree/bindings/sound/amlogic,axg-fifo.txt index 3080979350a0..fa4545ed81ca 100644 --- a/Documentation/devicetree/bindings/sound/amlogic,axg-fifo.txt +++ b/Documentation/devicetree/bindings/sound/amlogic,axg-fifo.txt @@ -17,6 +17,9 @@ Required properties: * "arb" : memory ARB line (required) * "rst" : dedicated device reset line (optional) - #sound-dai-cells: must be 0. +- amlogic,fifo-depth: The size of the controller's fifo in bytes. This + is useful for determining certain configuration such + as the flush threshold of the fifo
Example of FRDDR A on the A113 SoC:
@@ -27,4 +30,5 @@ frddr_a: audio-controller@1c0 { interrupts = <GIC_SPI 88 IRQ_TYPE_EDGE_RISING>; clocks = <&clkc_audio AUD_CLKID_FRDDR_A>; resets = <&arb AXG_ARB_FRDDR_A>; + fifo-depth = <512>; };
On Wed, Dec 18, 2019 at 06:24:18PM +0100, Jerome Brunet wrote:
Add a new property with the depth of the fifo in bytes. This is useful since some instance of the fifo, even on the same SoC, may have different depth. The depth is useful is set some parameters of the fifo.
Can't we figure this out from the compatible strings? They look SoC specific (which is good). That means we don't need to add new properties for each quirk that separates the variants.
On Wed 18 Dec 2019 at 18:50, Mark Brown broonie@kernel.org wrote:
On Wed, Dec 18, 2019 at 06:24:18PM +0100, Jerome Brunet wrote:
Add a new property with the depth of the fifo in bytes. This is useful since some instance of the fifo, even on the same SoC, may have different depth. The depth is useful is set some parameters of the fifo.
Can't we figure this out from the compatible strings? They look SoC specific (which is good). That means we don't need to add new properties for each quirk that separates the variants.
I don't think it would be appropriate in this case:
If I take the example of TODDR fifos on the SM1 SoC; All the TODDR fifo on this SoC are compatible with the same driver and use:
compatible = "amlogic,sm1-toddr", "amlogic,axg-toddr";
However instance A on this SoC has a 8192B fifo while instance B, C and D have 256B fifo. Same goes for the other SoC and also FRDDR fifos.
To store this difference using compatible I would have to add 1 compatible string for each "A" instance of each FRDDR and TODDR of each SoC. At the moment this would be 6 more compatible string for something that is really a parameter ... This also shows that fifo depth is something the HW manufacturer can tweak easily for each instances.
It would not scale which is why I went for a property.
The patch
ASoC: meson: axg-fifo: add fifo depth to the bindings documentation
has been applied to the asoc tree at
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-5.6
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
From fb522dbb4531c14193115a09905c6c31b37dbfc5 Mon Sep 17 00:00:00 2001
From: Jerome Brunet jbrunet@baylibre.com Date: Wed, 18 Dec 2019 18:24:18 +0100 Subject: [PATCH] ASoC: meson: axg-fifo: add fifo depth to the bindings documentation
Add a new property with the depth of the fifo in bytes. This is useful since some instance of the fifo, even on the same SoC, may have different depth. The depth is useful is set some parameters of the fifo.
Signed-off-by: Jerome Brunet jbrunet@baylibre.com Link: https://lore.kernel.org/r/20191218172420.1199117-3-jbrunet@baylibre.com Signed-off-by: Mark Brown broonie@kernel.org --- Documentation/devicetree/bindings/sound/amlogic,axg-fifo.txt | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/Documentation/devicetree/bindings/sound/amlogic,axg-fifo.txt b/Documentation/devicetree/bindings/sound/amlogic,axg-fifo.txt index 3080979350a0..fa4545ed81ca 100644 --- a/Documentation/devicetree/bindings/sound/amlogic,axg-fifo.txt +++ b/Documentation/devicetree/bindings/sound/amlogic,axg-fifo.txt @@ -17,6 +17,9 @@ Required properties: * "arb" : memory ARB line (required) * "rst" : dedicated device reset line (optional) - #sound-dai-cells: must be 0. +- amlogic,fifo-depth: The size of the controller's fifo in bytes. This + is useful for determining certain configuration such + as the flush threshold of the fifo
Example of FRDDR A on the A113 SoC:
@@ -27,4 +30,5 @@ frddr_a: audio-controller@1c0 { interrupts = <GIC_SPI 88 IRQ_TYPE_EDGE_RISING>; clocks = <&clkc_audio AUD_CLKID_FRDDR_A>; resets = <&arb AXG_ARB_FRDDR_A>; + fifo-depth = <512>; };
Let the fifo driver parse the fifo depth from DT. Eventually all DT should have this property. Until it is actually the case, default to 256 bytes if the property is missing. 256 bytes is the size of the smallest fifo on the supported SoCs.
On the supported SoC, fifo A is usually bigger than the other ones. With depth known, we can improve the usage of the fifo and adapt the setup of request threshold.
Signed-off-by: Jerome Brunet jbrunet@baylibre.com --- sound/soc/meson/axg-fifo.c | 19 +++++++++++++++++-- sound/soc/meson/axg-fifo.h | 1 + sound/soc/meson/axg-frddr.c | 13 ++++--------- 3 files changed, 22 insertions(+), 11 deletions(-)
diff --git a/sound/soc/meson/axg-fifo.c b/sound/soc/meson/axg-fifo.c index 4365086c9a31..c2742a02d866 100644 --- a/sound/soc/meson/axg-fifo.c +++ b/sound/soc/meson/axg-fifo.c @@ -132,8 +132,7 @@ int axg_fifo_pcm_hw_params(struct snd_soc_component *component, * - Half the fifo size * - Half the period size */ - threshold = min(period / 2, - (unsigned int)AXG_FIFO_MIN_DEPTH / 2); + threshold = min(period / 2, fifo->depth / 2);
/* * With the threshold in bytes, register value is: @@ -320,6 +319,7 @@ int axg_fifo_probe(struct platform_device *pdev) const struct axg_fifo_match_data *data; struct axg_fifo *fifo; void __iomem *regs; + int ret;
data = of_device_get_match_data(dev); if (!data) { @@ -370,6 +370,21 @@ int axg_fifo_probe(struct platform_device *pdev) if (IS_ERR(fifo->field_threshold)) return PTR_ERR(fifo->field_threshold);
+ ret = of_property_read_u32(dev->of_node, "amlogic,fifo-depth", + &fifo->depth); + if (ret) { + /* Error out for anything but a missing property */ + if (ret != -EINVAL) + return ret; + /* + * If the property is missing, it might be because of an old + * DT. In such case, assume the smallest known fifo depth + */ + fifo->depth = 256; + dev_warn(dev, "fifo depth not found, assume %u bytes\n", + fifo->depth); + } + return devm_snd_soc_register_component(dev, data->component_drv, data->dai_drv, 1); } diff --git a/sound/soc/meson/axg-fifo.h b/sound/soc/meson/axg-fifo.h index c442195ba191..521b54e98fd3 100644 --- a/sound/soc/meson/axg-fifo.h +++ b/sound/soc/meson/axg-fifo.h @@ -68,6 +68,7 @@ struct axg_fifo { struct clk *pclk; struct reset_control *arb; struct regmap_field *field_threshold; + unsigned int depth; int irq; };
diff --git a/sound/soc/meson/axg-frddr.c b/sound/soc/meson/axg-frddr.c index df104303351f..c3ae8ac30745 100644 --- a/sound/soc/meson/axg-frddr.c +++ b/sound/soc/meson/axg-frddr.c @@ -50,7 +50,7 @@ static int axg_frddr_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct axg_fifo *fifo = snd_soc_dai_get_drvdata(dai); - unsigned int fifo_depth; + unsigned int val; int ret;
/* Enable pclk to access registers and clock the fifo ip */ @@ -61,15 +61,10 @@ static int axg_frddr_dai_startup(struct snd_pcm_substream *substream, /* Apply single buffer mode to the interface */ regmap_update_bits(fifo->map, FIFO_CTRL0, CTRL0_FRDDR_PP_MODE, 0);
- /* - * TODO: We could adapt the fifo depth and the fifo threshold - * depending on the expected memory throughput and lantencies - * For now, we'll just use the same values as the vendor kernel - * Depth and threshold are zero based. - */ - fifo_depth = AXG_FIFO_MIN_CNT - 1; + /* Use all fifo depth */ + val = (fifo->depth / AXG_FIFO_BURST) - 1; regmap_update_bits(fifo->map, FIFO_CTRL1, CTRL1_FRDDR_DEPTH_MASK, - CTRL1_FRDDR_DEPTH(fifo_depth)); + CTRL1_FRDDR_DEPTH(val));
return 0; }
The patch
ASoC: meson: axg-fifo: improve depth handling
has been applied to the asoc tree at
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-5.6
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
From 23b89e1d62c75f2c1985449e968886e8a97860c0 Mon Sep 17 00:00:00 2001
From: Jerome Brunet jbrunet@baylibre.com Date: Wed, 18 Dec 2019 18:24:19 +0100 Subject: [PATCH] ASoC: meson: axg-fifo: improve depth handling
Let the fifo driver parse the fifo depth from DT. Eventually all DT should have this property. Until it is actually the case, default to 256 bytes if the property is missing. 256 bytes is the size of the smallest fifo on the supported SoCs.
On the supported SoC, fifo A is usually bigger than the other ones. With depth known, we can improve the usage of the fifo and adapt the setup of request threshold.
Signed-off-by: Jerome Brunet jbrunet@baylibre.com Link: https://lore.kernel.org/r/20191218172420.1199117-4-jbrunet@baylibre.com Signed-off-by: Mark Brown broonie@kernel.org --- sound/soc/meson/axg-fifo.c | 19 +++++++++++++++++-- sound/soc/meson/axg-fifo.h | 1 + sound/soc/meson/axg-frddr.c | 13 ++++--------- 3 files changed, 22 insertions(+), 11 deletions(-)
diff --git a/sound/soc/meson/axg-fifo.c b/sound/soc/meson/axg-fifo.c index 4365086c9a31..c2742a02d866 100644 --- a/sound/soc/meson/axg-fifo.c +++ b/sound/soc/meson/axg-fifo.c @@ -132,8 +132,7 @@ int axg_fifo_pcm_hw_params(struct snd_soc_component *component, * - Half the fifo size * - Half the period size */ - threshold = min(period / 2, - (unsigned int)AXG_FIFO_MIN_DEPTH / 2); + threshold = min(period / 2, fifo->depth / 2);
/* * With the threshold in bytes, register value is: @@ -320,6 +319,7 @@ int axg_fifo_probe(struct platform_device *pdev) const struct axg_fifo_match_data *data; struct axg_fifo *fifo; void __iomem *regs; + int ret;
data = of_device_get_match_data(dev); if (!data) { @@ -370,6 +370,21 @@ int axg_fifo_probe(struct platform_device *pdev) if (IS_ERR(fifo->field_threshold)) return PTR_ERR(fifo->field_threshold);
+ ret = of_property_read_u32(dev->of_node, "amlogic,fifo-depth", + &fifo->depth); + if (ret) { + /* Error out for anything but a missing property */ + if (ret != -EINVAL) + return ret; + /* + * If the property is missing, it might be because of an old + * DT. In such case, assume the smallest known fifo depth + */ + fifo->depth = 256; + dev_warn(dev, "fifo depth not found, assume %u bytes\n", + fifo->depth); + } + return devm_snd_soc_register_component(dev, data->component_drv, data->dai_drv, 1); } diff --git a/sound/soc/meson/axg-fifo.h b/sound/soc/meson/axg-fifo.h index c442195ba191..521b54e98fd3 100644 --- a/sound/soc/meson/axg-fifo.h +++ b/sound/soc/meson/axg-fifo.h @@ -68,6 +68,7 @@ struct axg_fifo { struct clk *pclk; struct reset_control *arb; struct regmap_field *field_threshold; + unsigned int depth; int irq; };
diff --git a/sound/soc/meson/axg-frddr.c b/sound/soc/meson/axg-frddr.c index df104303351f..c3ae8ac30745 100644 --- a/sound/soc/meson/axg-frddr.c +++ b/sound/soc/meson/axg-frddr.c @@ -50,7 +50,7 @@ static int axg_frddr_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct axg_fifo *fifo = snd_soc_dai_get_drvdata(dai); - unsigned int fifo_depth; + unsigned int val; int ret;
/* Enable pclk to access registers and clock the fifo ip */ @@ -61,15 +61,10 @@ static int axg_frddr_dai_startup(struct snd_pcm_substream *substream, /* Apply single buffer mode to the interface */ regmap_update_bits(fifo->map, FIFO_CTRL0, CTRL0_FRDDR_PP_MODE, 0);
- /* - * TODO: We could adapt the fifo depth and the fifo threshold - * depending on the expected memory throughput and lantencies - * For now, we'll just use the same values as the vendor kernel - * Depth and threshold are zero based. - */ - fifo_depth = AXG_FIFO_MIN_CNT - 1; + /* Use all fifo depth */ + val = (fifo->depth / AXG_FIFO_BURST) - 1; regmap_update_bits(fifo->map, FIFO_CTRL1, CTRL1_FRDDR_DEPTH_MASK, - CTRL1_FRDDR_DEPTH(fifo_depth)); + CTRL1_FRDDR_DEPTH(val));
return 0; }
Now that the fifo depths and thresholds are properly in the axg-fifo driver, we can relax the constraints on period. As long as the period is a multiple of the fifo burst size (8 bytes) things should be OK.
Signed-off-by: Jerome Brunet jbrunet@baylibre.com --- sound/soc/meson/axg-fifo.c | 8 ++++---- sound/soc/meson/axg-fifo.h | 2 -- 2 files changed, 4 insertions(+), 6 deletions(-)
diff --git a/sound/soc/meson/axg-fifo.c b/sound/soc/meson/axg-fifo.c index c2742a02d866..c12b0d5e8ebf 100644 --- a/sound/soc/meson/axg-fifo.c +++ b/sound/soc/meson/axg-fifo.c @@ -34,7 +34,7 @@ static struct snd_pcm_hardware axg_fifo_hw = { .rate_max = 192000, .channels_min = 1, .channels_max = AXG_FIFO_CH_MAX, - .period_bytes_min = AXG_FIFO_MIN_DEPTH, + .period_bytes_min = AXG_FIFO_BURST, .period_bytes_max = UINT_MAX, .periods_min = 2, .periods_max = UINT_MAX, @@ -227,17 +227,17 @@ int axg_fifo_pcm_open(struct snd_soc_component *component,
/* * Make sure the buffer and period size are multiple of the FIFO - * minimum depth size + * burst */ ret = snd_pcm_hw_constraint_step(ss->runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, - AXG_FIFO_MIN_DEPTH); + AXG_FIFO_BURST); if (ret) return ret;
ret = snd_pcm_hw_constraint_step(ss->runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, - AXG_FIFO_MIN_DEPTH); + AXG_FIFO_BURST); if (ret) return ret;
diff --git a/sound/soc/meson/axg-fifo.h b/sound/soc/meson/axg-fifo.h index 521b54e98fd3..b63acd723c87 100644 --- a/sound/soc/meson/axg-fifo.h +++ b/sound/soc/meson/axg-fifo.h @@ -31,8 +31,6 @@ struct snd_soc_pcm_runtime; SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE)
#define AXG_FIFO_BURST 8 -#define AXG_FIFO_MIN_CNT 64 -#define AXG_FIFO_MIN_DEPTH (AXG_FIFO_BURST * AXG_FIFO_MIN_CNT)
#define FIFO_INT_ADDR_FINISH BIT(0) #define FIFO_INT_ADDR_INT BIT(1)
The patch
ASoC: meson: axg-fifo: relax period size constraints
has been applied to the asoc tree at
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-5.6
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
From 42b5ac832b0c3bf5b0bf98ea6d99efa5fb5d5075 Mon Sep 17 00:00:00 2001
From: Jerome Brunet jbrunet@baylibre.com Date: Wed, 18 Dec 2019 18:24:20 +0100 Subject: [PATCH] ASoC: meson: axg-fifo: relax period size constraints
Now that the fifo depths and thresholds are properly in the axg-fifo driver, we can relax the constraints on period. As long as the period is a multiple of the fifo burst size (8 bytes) things should be OK.
Signed-off-by: Jerome Brunet jbrunet@baylibre.com Link: https://lore.kernel.org/r/20191218172420.1199117-5-jbrunet@baylibre.com Signed-off-by: Mark Brown broonie@kernel.org --- sound/soc/meson/axg-fifo.c | 8 ++++---- sound/soc/meson/axg-fifo.h | 2 -- 2 files changed, 4 insertions(+), 6 deletions(-)
diff --git a/sound/soc/meson/axg-fifo.c b/sound/soc/meson/axg-fifo.c index c2742a02d866..c12b0d5e8ebf 100644 --- a/sound/soc/meson/axg-fifo.c +++ b/sound/soc/meson/axg-fifo.c @@ -34,7 +34,7 @@ static struct snd_pcm_hardware axg_fifo_hw = { .rate_max = 192000, .channels_min = 1, .channels_max = AXG_FIFO_CH_MAX, - .period_bytes_min = AXG_FIFO_MIN_DEPTH, + .period_bytes_min = AXG_FIFO_BURST, .period_bytes_max = UINT_MAX, .periods_min = 2, .periods_max = UINT_MAX, @@ -227,17 +227,17 @@ int axg_fifo_pcm_open(struct snd_soc_component *component,
/* * Make sure the buffer and period size are multiple of the FIFO - * minimum depth size + * burst */ ret = snd_pcm_hw_constraint_step(ss->runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, - AXG_FIFO_MIN_DEPTH); + AXG_FIFO_BURST); if (ret) return ret;
ret = snd_pcm_hw_constraint_step(ss->runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, - AXG_FIFO_MIN_DEPTH); + AXG_FIFO_BURST); if (ret) return ret;
diff --git a/sound/soc/meson/axg-fifo.h b/sound/soc/meson/axg-fifo.h index 521b54e98fd3..b63acd723c87 100644 --- a/sound/soc/meson/axg-fifo.h +++ b/sound/soc/meson/axg-fifo.h @@ -31,8 +31,6 @@ struct snd_soc_pcm_runtime; SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE)
#define AXG_FIFO_BURST 8 -#define AXG_FIFO_MIN_CNT 64 -#define AXG_FIFO_MIN_DEPTH (AXG_FIFO_BURST * AXG_FIFO_MIN_CNT)
#define FIFO_INT_ADDR_FINISH BIT(0) #define FIFO_INT_ADDR_INT BIT(1)
participants (2)
-
Jerome Brunet
-
Mark Brown