lkml.org 
[lkml]   [2019]   [Aug]   [14]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    SubjectRe: [linux-sunxi] [PATCH v5 12/15] ASoC: sun4i-i2s: Add multi-lane functionality
    Date
    Hi!

    Dne sreda, 14. avgust 2019 ob 08:08:51 CEST je codekipper@gmail.com
    napisal(a):
    > From: Marcus Cooper <codekipper@gmail.com>
    >
    > The i2s block supports multi-lane i2s output however this functionality
    > is only possible in earlier SoCs where the pins are exposed and for
    > the i2s block used for HDMI audio on the later SoCs.
    >
    > To enable this functionality, an optional property has been added to
    > the bindings.
    >
    > Signed-off-by: Marcus Cooper <codekipper@gmail.com>
    > ---
    > sound/soc/sunxi/sun4i-i2s.c | 28 +++++++++++++++++++++++++---
    > 1 file changed, 25 insertions(+), 3 deletions(-)
    >
    > diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c
    > index a8d98696fe7c..a020c3b372a8 100644
    > --- a/sound/soc/sunxi/sun4i-i2s.c
    > +++ b/sound/soc/sunxi/sun4i-i2s.c
    > @@ -23,7 +23,7 @@
    >
    > #define SUN4I_I2S_CTRL_REG 0x00
    > #define SUN4I_I2S_CTRL_SDO_EN_MASK GENMASK(11, 8)
    > -#define SUN4I_I2S_CTRL_SDO_EN(sdo) BIT(8 +
    (sdo))
    > +#define SUN4I_I2S_CTRL_SDO_EN(lines) (((1 << lines) - 1)
    << 8)
    > #define SUN4I_I2S_CTRL_MODE_MASK BIT(5)
    > #define SUN4I_I2S_CTRL_MODE_SLAVE (1 << 5)
    > #define SUN4I_I2S_CTRL_MODE_MASTER (0 << 5)
    > @@ -614,6 +614,7 @@ static int sun4i_i2s_hw_params(struct snd_pcm_substream
    > *substream, struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai);
    > int sr, wss, channels;
    > u32 width;
    > + int lines;
    >
    > channels = params_channels(params);
    > if (channels != 2) {
    > @@ -622,6 +623,13 @@ static int sun4i_i2s_hw_params(struct snd_pcm_substream
    > *substream, return -EINVAL;
    > }
    >
    > + lines = (channels + 1) / 2;
    > +
    > + /* Enable the required output lines */
    > + regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG,
    > + SUN4I_I2S_CTRL_SDO_EN_MASK,
    > + SUN4I_I2S_CTRL_SDO_EN(lines));

    As Maxime said before, this doesn't work for TDM. Maybe we can skip this for
    now, until we agree on method how to describe channel allocation?

    > +
    > if (i2s->variant->has_chcfg) {
    > regmap_update_bits(i2s->regmap, SUN8I_I2S_CHAN_CFG_REG,
    >
    SUN8I_I2S_CHAN_CFG_TX_SLOT_NUM_MASK,
    > @@ -1389,9 +1397,10 @@ static int sun4i_i2s_init_regmap_fields(struct device
    > *dev, static int sun4i_i2s_probe(struct platform_device *pdev)
    > {
    > struct sun4i_i2s *i2s;
    > + struct snd_soc_dai_driver *soc_dai;
    > struct resource *res;
    > void __iomem *regs;
    > - int irq, ret;
    > + int irq, ret, val;
    >
    > i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL);
    > if (!i2s)
    > @@ -1456,6 +1465,19 @@ static int sun4i_i2s_probe(struct platform_device
    > *pdev) i2s->capture_dma_data.addr = res->start + SUN4I_I2S_FIFO_RX_REG;
    > i2s->capture_dma_data.maxburst = 8;
    >
    > + soc_dai = devm_kmemdup(&pdev->dev, &sun4i_i2s_dai,
    > + sizeof(*soc_dai), GFP_KERNEL);
    > + if (!soc_dai) {
    > + ret = -ENOMEM;
    > + goto err_pm_disable;
    > + }
    > +
    > + if (!of_property_read_u32(pdev->dev.of_node,
    > + "allwinner,playback-channels",
    &val)) {
    > + if (val >= 2 && val <= 8)
    > + soc_dai->playback.channels_max = val;
    > + }
    > +

    Rather than inventing new DT properties, I would rather have multiple
    snd_soc_dai_driver structures, depending on capabilities of that particular
    I2S block. That way we avoid some boilerplate code as can be seen here and
    it's IMO more transparent.

    In this case, I would make another snd_soc_dai_driver struct for H3, which has
    channel_max property set to 8 and from patch 14, additional supported formats.

    Best regards,
    Jernej

    > pm_runtime_enable(&pdev->dev);
    > if (!pm_runtime_enabled(&pdev->dev)) {
    > ret = sun4i_i2s_runtime_resume(&pdev->dev);
    > @@ -1465,7 +1487,7 @@ static int sun4i_i2s_probe(struct platform_device
    > *pdev)
    >
    > ret = devm_snd_soc_register_component(&pdev->dev,
    >
    &sun4i_i2s_component,
    > - &sun4i_i2s_dai,
    1);
    > + soc_dai, 1);
    > if (ret) {
    > dev_err(&pdev->dev, "Could not register DAI\n");
    > goto err_suspend;




    \
     
     \ /
      Last update: 2019-08-14 10:28    [W:6.586 / U:0.008 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site