On Sun, 29 Sep 2024 23:06:02 +1300
Ryan Walklin <ryan@xxxxxxxxxxxxx> wrote:
Hi,
> From: Marcus Cooper <codekipper@xxxxxxxxx>
>
> The Allwinner H616 SoC uses a different register address to control the
> output FIFO.
>
> Allow this to be specified separately from the ADC FIFO control
> register.
That looks good to me, it follows the existing regmap_field pattern for the
input FIFO, and I can confirm it changes every user of the DAC register.
> Signed-off-by: Marcus Cooper <codekipper@xxxxxxxxx>
> Signed-off-by: Ryan Walklin <ryan@xxxxxxxxxxxxx>
Reviewed-by: Andre Przywara <andre.przywara@xxxxxxx>
Cheers,
Andre
> ---
> sound/soc/sunxi/sun4i-codec.c | 83 +++++++++++++++++++++--------------
> 1 file changed, 51 insertions(+), 32 deletions(-)
>
> diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c
> index 330bc0c09f56b..37f5678b55291 100644
> --- a/sound/soc/sunxi/sun4i-codec.c
> +++ b/sound/soc/sunxi/sun4i-codec.c
> @@ -238,6 +238,8 @@ struct sun4i_codec {
>
> /* ADC_FIFOC register is at different offset on different SoCs */
> struct regmap_field *reg_adc_fifoc;
> + /* DAC_FIFOC register is at different offset on different SoCs */
> + struct regmap_field *reg_dac_fifoc;
>
> struct snd_dmaengine_dai_dma_data capture_dma_data;
> struct snd_dmaengine_dai_dma_data playback_dma_data;
> @@ -246,19 +248,19 @@ struct sun4i_codec {
> static void sun4i_codec_start_playback(struct sun4i_codec *scodec)
> {
> /* Flush TX FIFO */
> - regmap_set_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
> - BIT(SUN4I_CODEC_DAC_FIFOC_FIFO_FLUSH));
> + regmap_field_set_bits(scodec->reg_dac_fifoc,
> + BIT(SUN4I_CODEC_DAC_FIFOC_FIFO_FLUSH));
>
> /* Enable DAC DRQ */
> - regmap_set_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
> - BIT(SUN4I_CODEC_DAC_FIFOC_DAC_DRQ_EN));
> + regmap_field_set_bits(scodec->reg_dac_fifoc,
> + BIT(SUN4I_CODEC_DAC_FIFOC_DAC_DRQ_EN));
> }
>
> static void sun4i_codec_stop_playback(struct sun4i_codec *scodec)
> {
> /* Disable DAC DRQ */
> - regmap_clear_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
> - BIT(SUN4I_CODEC_DAC_FIFOC_DAC_DRQ_EN));
> + regmap_field_clear_bits(scodec->reg_dac_fifoc,
> + BIT(SUN4I_CODEC_DAC_FIFOC_DAC_DRQ_EN));
> }
>
> static void sun4i_codec_start_capture(struct sun4i_codec *scodec)
> @@ -356,13 +358,13 @@ static int sun4i_codec_prepare_playback(struct snd_pcm_substream *substream,
> u32 val;
>
> /* Flush the TX FIFO */
> - regmap_set_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
> - BIT(SUN4I_CODEC_DAC_FIFOC_FIFO_FLUSH));
> + regmap_field_set_bits(scodec->reg_dac_fifoc,
> + BIT(SUN4I_CODEC_DAC_FIFOC_FIFO_FLUSH));
>
> /* Set TX FIFO Empty Trigger Level */
> - regmap_update_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
> - 0x3f << SUN4I_CODEC_DAC_FIFOC_TX_TRIG_LEVEL,
> - 0xf << SUN4I_CODEC_DAC_FIFOC_TX_TRIG_LEVEL);
> + regmap_field_update_bits(scodec->reg_dac_fifoc,
> + 0x3f << SUN4I_CODEC_DAC_FIFOC_TX_TRIG_LEVEL,
> + 0xf << SUN4I_CODEC_DAC_FIFOC_TX_TRIG_LEVEL);
>
> if (substream->runtime->rate > 32000)
> /* Use 64 bits FIR filter */
> @@ -371,13 +373,13 @@ static int sun4i_codec_prepare_playback(struct snd_pcm_substream *substream,
> /* Use 32 bits FIR filter */
> val = BIT(SUN4I_CODEC_DAC_FIFOC_FIR_VERSION);
>
> - regmap_update_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
> - BIT(SUN4I_CODEC_DAC_FIFOC_FIR_VERSION),
> - val);
> + regmap_field_update_bits(scodec->reg_dac_fifoc,
> + BIT(SUN4I_CODEC_DAC_FIFOC_FIR_VERSION),
> + val);
>
> /* Send zeros when we have an underrun */
> - regmap_clear_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
> - BIT(SUN4I_CODEC_DAC_FIFOC_SEND_LASAT));
> + regmap_field_clear_bits(scodec->reg_dac_fifoc,
> + BIT(SUN4I_CODEC_DAC_FIFOC_SEND_LASAT));
>
> return 0;
> };
> @@ -510,9 +512,9 @@ static int sun4i_codec_hw_params_playback(struct sun4i_codec *scodec,
> u32 val;
>
> /* Set DAC sample rate */
> - regmap_update_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
> - 7 << SUN4I_CODEC_DAC_FIFOC_DAC_FS,
> - hwrate << SUN4I_CODEC_DAC_FIFOC_DAC_FS);
> + regmap_field_update_bits(scodec->reg_dac_fifoc,
> + 7 << SUN4I_CODEC_DAC_FIFOC_DAC_FS,
> + hwrate << SUN4I_CODEC_DAC_FIFOC_DAC_FS);
>
> /* Set the number of channels we want to use */
> if (params_channels(params) == 1)
> @@ -520,27 +522,27 @@ static int sun4i_codec_hw_params_playback(struct sun4i_codec *scodec,
> else
> val = 0;
>
> - regmap_update_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
> - BIT(SUN4I_CODEC_DAC_FIFOC_MONO_EN),
> - val);
> + regmap_field_update_bits(scodec->reg_dac_fifoc,
> + BIT(SUN4I_CODEC_DAC_FIFOC_MONO_EN),
> + val);
>
> /* Set the number of sample bits to either 16 or 24 bits */
> if (hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS)->min == 32) {
> - regmap_set_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
> - BIT(SUN4I_CODEC_DAC_FIFOC_TX_SAMPLE_BITS));
> + regmap_field_set_bits(scodec->reg_dac_fifoc,
> + BIT(SUN4I_CODEC_DAC_FIFOC_TX_SAMPLE_BITS));
>
> /* Set TX FIFO mode to padding the LSBs with 0 */
> - regmap_clear_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
> - BIT(SUN4I_CODEC_DAC_FIFOC_TX_FIFO_MODE));
> + regmap_field_clear_bits(scodec->reg_dac_fifoc,
> + BIT(SUN4I_CODEC_DAC_FIFOC_TX_FIFO_MODE));
>
> scodec->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
> } else {
> - regmap_clear_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
> - BIT(SUN4I_CODEC_DAC_FIFOC_TX_SAMPLE_BITS));
> + regmap_field_clear_bits(scodec->reg_dac_fifoc,
> + BIT(SUN4I_CODEC_DAC_FIFOC_TX_SAMPLE_BITS));
>
> /* Set TX FIFO mode to repeat the MSB */
> - regmap_set_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
> - BIT(SUN4I_CODEC_DAC_FIFOC_TX_FIFO_MODE));
> + regmap_field_set_bits(scodec->reg_dac_fifoc,
> + BIT(SUN4I_CODEC_DAC_FIFOC_TX_FIFO_MODE));
>
> scodec->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
> }
> @@ -587,8 +589,8 @@ static int sun4i_codec_startup(struct snd_pcm_substream *substream,
> * Stop issuing DRQ when we have room for less than 16 samples
> * in our TX FIFO
> */
> - regmap_set_bits(scodec->regmap, SUN4I_CODEC_DAC_FIFOC,
> - 3 << SUN4I_CODEC_DAC_FIFOC_DRQ_CLR_CNT);
> + regmap_field_set_bits(scodec->reg_dac_fifoc,
> + 3 << SUN4I_CODEC_DAC_FIFOC_DRQ_CLR_CNT);
>
> return clk_prepare_enable(scodec->clk_module);
> }
> @@ -1565,6 +1567,7 @@ struct sun4i_codec_quirks {
> const struct snd_soc_component_driver *codec;
> struct snd_soc_card * (*create_card)(struct device *dev);
> struct reg_field reg_adc_fifoc; /* used for regmap_field */
> + struct reg_field reg_dac_fifoc; /* used for regmap_field */
> unsigned int reg_dac_txdata; /* TX FIFO offset for DMA config */
> unsigned int reg_adc_rxdata; /* RX FIFO offset for DMA config */
> bool has_reset;
> @@ -1575,6 +1578,7 @@ static const struct sun4i_codec_quirks sun4i_codec_quirks = {
> .codec = &sun4i_codec_codec,
> .create_card = sun4i_codec_create_card,
> .reg_adc_fifoc = REG_FIELD(SUN4I_CODEC_ADC_FIFOC, 0, 31),
> + .reg_dac_fifoc = REG_FIELD(SUN4I_CODEC_DAC_FIFOC, 0, 31),
> .reg_dac_txdata = SUN4I_CODEC_DAC_TXDATA,
> .reg_adc_rxdata = SUN4I_CODEC_ADC_RXDATA,
> };
> @@ -1584,6 +1588,7 @@ static const struct sun4i_codec_quirks sun6i_a31_codec_quirks = {
> .codec = &sun6i_codec_codec,
> .create_card = sun6i_codec_create_card,
> .reg_adc_fifoc = REG_FIELD(SUN6I_CODEC_ADC_FIFOC, 0, 31),
> + .reg_dac_fifoc = REG_FIELD(SUN4I_CODEC_DAC_FIFOC, 0, 31),
> .reg_dac_txdata = SUN4I_CODEC_DAC_TXDATA,
> .reg_adc_rxdata = SUN6I_CODEC_ADC_RXDATA,
> .has_reset = true,
> @@ -1594,6 +1599,7 @@ static const struct sun4i_codec_quirks sun7i_codec_quirks = {
> .codec = &sun7i_codec_codec,
> .create_card = sun4i_codec_create_card,
> .reg_adc_fifoc = REG_FIELD(SUN4I_CODEC_ADC_FIFOC, 0, 31),
> + .reg_dac_fifoc = REG_FIELD(SUN4I_CODEC_DAC_FIFOC, 0, 31),
> .reg_dac_txdata = SUN4I_CODEC_DAC_TXDATA,
> .reg_adc_rxdata = SUN4I_CODEC_ADC_RXDATA,
> };
> @@ -1603,6 +1609,7 @@ static const struct sun4i_codec_quirks sun8i_a23_codec_quirks = {
> .codec = &sun8i_a23_codec_codec,
> .create_card = sun8i_a23_codec_create_card,
> .reg_adc_fifoc = REG_FIELD(SUN6I_CODEC_ADC_FIFOC, 0, 31),
> + .reg_dac_fifoc = REG_FIELD(SUN4I_CODEC_DAC_FIFOC, 0, 31),
> .reg_dac_txdata = SUN4I_CODEC_DAC_TXDATA,
> .reg_adc_rxdata = SUN6I_CODEC_ADC_RXDATA,
> .has_reset = true,
> @@ -1618,6 +1625,7 @@ static const struct sun4i_codec_quirks sun8i_h3_codec_quirks = {
> .codec = &sun8i_a23_codec_codec,
> .create_card = sun8i_h3_codec_create_card,
> .reg_adc_fifoc = REG_FIELD(SUN6I_CODEC_ADC_FIFOC, 0, 31),
> + .reg_dac_fifoc = REG_FIELD(SUN4I_CODEC_DAC_FIFOC, 0, 31),
> .reg_dac_txdata = SUN8I_H3_CODEC_DAC_TXDATA,
> .reg_adc_rxdata = SUN6I_CODEC_ADC_RXDATA,
> .has_reset = true,
> @@ -1632,6 +1640,7 @@ static const struct sun4i_codec_quirks sun8i_v3s_codec_quirks = {
> .codec = &sun8i_a23_codec_codec,
> .create_card = sun8i_v3s_codec_create_card,
> .reg_adc_fifoc = REG_FIELD(SUN6I_CODEC_ADC_FIFOC, 0, 31),
> + .reg_dac_fifoc = REG_FIELD(SUN4I_CODEC_DAC_FIFOC, 0, 31),
> .reg_dac_txdata = SUN8I_H3_CODEC_DAC_TXDATA,
> .reg_adc_rxdata = SUN6I_CODEC_ADC_RXDATA,
> .has_reset = true,
> @@ -1739,6 +1748,16 @@ static int sun4i_codec_probe(struct platform_device *pdev)
> return ret;
> }
>
> + scodec->reg_dac_fifoc = devm_regmap_field_alloc(&pdev->dev,
> + scodec->regmap,
> + quirks->reg_dac_fifoc);
> + if (IS_ERR(scodec->reg_dac_fifoc)) {
> + ret = PTR_ERR(scodec->reg_dac_fifoc);
> + dev_err(&pdev->dev, "Failed to create regmap fields: %d\n",
> + ret);
> + return ret;
> + }
> +
> /* Enable the bus clock */
> if (clk_prepare_enable(scodec->clk_apb)) {
> dev_err(&pdev->dev, "Failed to enable the APB clock\n");
[Index of Archives]
[Pulseaudio]
[Linux Audio Users]
[ALSA Devel]
[Fedora Desktop]
[Fedora SELinux]
[Big List of Linux Books]
[Yosemite News]
[KDE Users]