[v2,4/6] ASoC: sun4i-i2s: Add multi-lane functionality
diff mbox

Message ID 20180312155753.9478-5-codekipper@gmail.com
State New
Headers show

Commit Message

Code Kipper March 12, 2018, 3:57 p.m. UTC
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>
---
 .../devicetree/bindings/sound/sun4i-i2s.txt        |  3 ++
 sound/soc/sunxi/sun4i-i2s.c                        | 48 +++++++++++++++++-----
 2 files changed, 41 insertions(+), 10 deletions(-)

Comments

Maxime Ripard March 13, 2018, 8 a.m. UTC | #1
On Mon, Mar 12, 2018 at 04:57:51PM +0100, codekipper@gmail.com wrote:
> 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>
> ---
>  .../devicetree/bindings/sound/sun4i-i2s.txt        |  3 ++
>  sound/soc/sunxi/sun4i-i2s.c                        | 48 +++++++++++++++++-----
>  2 files changed, 41 insertions(+), 10 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/sound/sun4i-i2s.txt b/Documentation/devicetree/bindings/sound/sun4i-i2s.txt
> index 48addef65b8f..3f966ac61b9e 100644
> --- a/Documentation/devicetree/bindings/sound/sun4i-i2s.txt
> +++ b/Documentation/devicetree/bindings/sound/sun4i-i2s.txt
> @@ -33,6 +33,9 @@ Optional properties:
>  				configured to extend the slot width to the
>  				value specified. Min 8, Max 32.
>  
> +- allwinner,playback-channels:  if this property is present then the number
> +				of available channels is extended and the
> +				outputs enabled.

Isn't it something that is fixed for each generation of SoCs? Can't we
attach it to the compatible?

Maxime
Code Kipper March 13, 2018, 8:15 a.m. UTC | #2
On 13 March 2018 at 09:00, Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> On Mon, Mar 12, 2018 at 04:57:51PM +0100, codekipper@gmail.com wrote:
>> 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>
>> ---
>>  .../devicetree/bindings/sound/sun4i-i2s.txt        |  3 ++
>>  sound/soc/sunxi/sun4i-i2s.c                        | 48 +++++++++++++++++-----
>>  2 files changed, 41 insertions(+), 10 deletions(-)
>>
>> diff --git a/Documentation/devicetree/bindings/sound/sun4i-i2s.txt b/Documentation/devicetree/bindings/sound/sun4i-i2s.txt
>> index 48addef65b8f..3f966ac61b9e 100644
>> --- a/Documentation/devicetree/bindings/sound/sun4i-i2s.txt
>> +++ b/Documentation/devicetree/bindings/sound/sun4i-i2s.txt
>> @@ -33,6 +33,9 @@ Optional properties:
>>                               configured to extend the slot width to the
>>                               value specified. Min 8, Max 32.
>>
>> +- allwinner,playback-channels:  if this property is present then the number
>> +                             of available channels is extended and the
>> +                             outputs enabled.
>
> Isn't it something that is fixed for each generation of SoCs? Can't we
> attach it to the compatible?

I'm not sure as the documentation is pretty poor. It looks like it is
supported by all of the variations that we've seen but only exposed as
pins on A10 and A20. I'm also not sure who would ever use it with
external devices.
The reason why I've added it is that it is required by HDMI for
supporting surround sound on the newer SoCs.
CK

>
> Maxime
>
> --
> Maxime Ripard, Bootlin (formerly Free Electrons)
> Embedded Linux and Kernel engineering
> https://bootlin.com
Maxime Ripard March 13, 2018, 8:23 a.m. UTC | #3
On Tue, Mar 13, 2018 at 09:15:49AM +0100, Code Kipper wrote:
> On 13 March 2018 at 09:00, Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> > On Mon, Mar 12, 2018 at 04:57:51PM +0100, codekipper@gmail.com wrote:
> >> 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>
> >> ---
> >>  .../devicetree/bindings/sound/sun4i-i2s.txt        |  3 ++
> >>  sound/soc/sunxi/sun4i-i2s.c                        | 48 +++++++++++++++++-----
> >>  2 files changed, 41 insertions(+), 10 deletions(-)
> >>
> >> diff --git a/Documentation/devicetree/bindings/sound/sun4i-i2s.txt b/Documentation/devicetree/bindings/sound/sun4i-i2s.txt
> >> index 48addef65b8f..3f966ac61b9e 100644
> >> --- a/Documentation/devicetree/bindings/sound/sun4i-i2s.txt
> >> +++ b/Documentation/devicetree/bindings/sound/sun4i-i2s.txt
> >> @@ -33,6 +33,9 @@ Optional properties:
> >>                               configured to extend the slot width to the
> >>                               value specified. Min 8, Max 32.
> >>
> >> +- allwinner,playback-channels:  if this property is present then the number
> >> +                             of available channels is extended and the
> >> +                             outputs enabled.
> >
> > Isn't it something that is fixed for each generation of SoCs? Can't we
> > attach it to the compatible?
> 
> I'm not sure as the documentation is pretty poor. It looks like it is
> supported by all of the variations that we've seen but only exposed as
> pins on A10 and A20. I'm also not sure who would ever use it with
> external devices.

Well, you were saying that it was the case on the older SoCs in your
commit log, so this needs to be figured out.

> The reason why I've added it is that it is required by HDMI for
> supporting surround sound on the newer SoCs.

Why isn't that mentionned in your commit log?

Can you post the whole set of changes needed for HDMI audio? this
would make things much easier to see where you're going.

Maxime
Code Kipper March 13, 2018, 8:59 a.m. UTC | #4
On 13 March 2018 at 09:23, Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> On Tue, Mar 13, 2018 at 09:15:49AM +0100, Code Kipper wrote:
>> On 13 March 2018 at 09:00, Maxime Ripard <maxime.ripard@bootlin.com> wrote:
>> > On Mon, Mar 12, 2018 at 04:57:51PM +0100, codekipper@gmail.com wrote:
>> >> 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>
>> >> ---
>> >>  .../devicetree/bindings/sound/sun4i-i2s.txt        |  3 ++
>> >>  sound/soc/sunxi/sun4i-i2s.c                        | 48 +++++++++++++++++-----
>> >>  2 files changed, 41 insertions(+), 10 deletions(-)
>> >>
>> >> diff --git a/Documentation/devicetree/bindings/sound/sun4i-i2s.txt b/Documentation/devicetree/bindings/sound/sun4i-i2s.txt
>> >> index 48addef65b8f..3f966ac61b9e 100644
>> >> --- a/Documentation/devicetree/bindings/sound/sun4i-i2s.txt
>> >> +++ b/Documentation/devicetree/bindings/sound/sun4i-i2s.txt
>> >> @@ -33,6 +33,9 @@ Optional properties:
>> >>                               configured to extend the slot width to the
>> >>                               value specified. Min 8, Max 32.
>> >>
>> >> +- allwinner,playback-channels:  if this property is present then the number
>> >> +                             of available channels is extended and the
>> >> +                             outputs enabled.
>> >
>> > Isn't it something that is fixed for each generation of SoCs? Can't we
>> > attach it to the compatible?
>>
>> I'm not sure as the documentation is pretty poor. It looks like it is
>> supported by all of the variations that we've seen but only exposed as
>> pins on A10 and A20. I'm also not sure who would ever use it with
>> external devices.
>
> Well, you were saying that it was the case on the older SoCs in your
> commit log, so this needs to be figured out.
>
>> The reason why I've added it is that it is required by HDMI for
>> supporting surround sound on the newer SoCs.
>
> Why isn't that mentionned in your commit log?
>
> Can you post the whole set of changes needed for HDMI audio? this
> would make things much easier to see where you're going.

Maybe we should drop this change for now as basic HDMI audio for two
channels doesn't require it. I've also not tested multi-channel audio
yet.

To get HDMI audio working the following patches are required for the dts
https://github.com/codekipper/linux-sunxi/commit/997c622ae10ef136bae0a35a0e9bf9c6dd27910a
and
https://github.com/codekipper/linux-sunxi/commit/4a81676d30a0262c57ffc0827e46c7934fb3b358

they don't need this patch but do need the slot-width-override patch.

CK
>
> Maxime
>
> --
> Maxime Ripard, Bootlin (formerly Free Electrons)
> Embedded Linux and Kernel engineering
> https://bootlin.com

Patch
diff mbox

diff --git a/Documentation/devicetree/bindings/sound/sun4i-i2s.txt b/Documentation/devicetree/bindings/sound/sun4i-i2s.txt
index 48addef65b8f..3f966ac61b9e 100644
--- a/Documentation/devicetree/bindings/sound/sun4i-i2s.txt
+++ b/Documentation/devicetree/bindings/sound/sun4i-i2s.txt
@@ -33,6 +33,9 @@  Optional properties:
 				configured to extend the slot width to the
 				value specified. Min 8, Max 32.
 
+- allwinner,playback-channels:  if this property is present then the number
+				of available channels is extended and the
+				outputs enabled.
 Example:
 
 i2s0: i2s@1c22400 {
diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c
index 2bd0befa02a8..436480df1844 100644
--- a/sound/soc/sunxi/sun4i-i2s.c
+++ b/sound/soc/sunxi/sun4i-i2s.c
@@ -27,7 +27,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)
@@ -394,14 +394,23 @@  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) {
+	if ((channels > dai->driver->playback.channels_max) ||
+		(channels < dai->driver->playback.channels_min)) {
 		dev_err(dai->dev, "Unsupported number of channels: %d\n",
 			channels);
 		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));
+
 	if (i2s->variant->has_chcfg) {
 		regmap_update_bits(i2s->regmap, SUN8I_I2S_CHAN_CFG_REG,
 				   SUN8I_I2S_CHAN_CFG_TX_SLOT_NUM_MASK,
@@ -412,8 +421,19 @@  static int sun4i_i2s_hw_params(struct snd_pcm_substream *substream,
 	}
 
 	/* Map the channels for playback and capture */
-	regmap_field_write(i2s->field_txchanmap, 0x76543210);
 	regmap_field_write(i2s->field_rxchanmap, 0x00003210);
+	regmap_field_write(i2s->field_txchanmap, 0x10);
+	if (i2s->variant->has_chsel_tx_chen) {
+		if (channels > 2)
+			regmap_write(i2s->regmap,
+				     SUN8I_I2S_TX_CHAN_MAP_REG+4, 0x32);
+		if (channels > 4)
+			regmap_write(i2s->regmap,
+				     SUN8I_I2S_TX_CHAN_MAP_REG+8, 0x54);
+		if (channels > 6)
+			regmap_write(i2s->regmap,
+				     SUN8I_I2S_TX_CHAN_MAP_REG+12, 0x76);
+	}
 
 	/* Configure the channels */
 	regmap_field_write(i2s->field_txchansel,
@@ -692,12 +712,6 @@  static int sun4i_i2s_startup(struct snd_pcm_substream *substream,
 	regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG,
 			   SUN4I_I2S_CTRL_GL_EN, SUN4I_I2S_CTRL_GL_EN);
 
-	/* Enable the first output line */
-	regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG,
-			   SUN4I_I2S_CTRL_SDO_EN_MASK,
-			   SUN4I_I2S_CTRL_SDO_EN(0));
-
-
 	return clk_prepare_enable(i2s->mod_clk);
 }
 
@@ -1073,6 +1087,7 @@  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, val;
@@ -1148,6 +1163,19 @@  static int sun4i_i2s_probe(struct platform_device *pdev)
 			i2s->slot_width = val;
 	}
 
+	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;
+	}
+
 	pm_runtime_enable(&pdev->dev);
 	if (!pm_runtime_enabled(&pdev->dev)) {
 		ret = sun4i_i2s_runtime_resume(&pdev->dev);
@@ -1157,7 +1185,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;