[PATCHv2,1/4] ASoC: simple-card: add asoc_simple_card_fmt_master() to simplify the code.
diff mbox

Message ID 1409649969-15759-2-git-send-email-Li.Xiubo@freescale.com
State New, archived
Headers show

Commit Message

Xiubo Li Sept. 2, 2014, 9:26 a.m. UTC
Signed-off-by: Xiubo Li <Li.Xiubo@freescale.com>
---
 sound/soc/generic/simple-card.c | 61 ++++++++++++++++++++---------------------
 1 file changed, 29 insertions(+), 32 deletions(-)

Comments

Varka Bhadram Sept. 2, 2014, 10:21 a.m. UTC | #1
On 09/02/2014 02:56 PM, Xiubo Li wrote:
> Signed-off-by: Xiubo Li <Li.Xiubo@freescale.com>
> ---
>   sound/soc/generic/simple-card.c | 61 ++++++++++++++++++++---------------------
>   1 file changed, 29 insertions(+), 32 deletions(-)
>
> diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c
> index 986d2c7..cad2b30 100644
> --- a/sound/soc/generic/simple-card.c
> +++ b/sound/soc/generic/simple-card.c
> @@ -163,6 +163,26 @@ asoc_simple_card_sub_parse_of(struct device_node *np,
>   	return 0;
>   }
>   
> +static inline unsigned int
> +asoc_simple_card_fmt_master(struct device_node *np,
> +			    struct device_node *bitclkmaster,
> +			    struct device_node *framemaster)
> +{
> +	switch (((np == bitclkmaster) << 4) | (np == framemaster)) {
> +	case 0x11:
> +		return SND_SOC_DAIFMT_CBS_CFS;
> +	case 0x10:
> +		return SND_SOC_DAIFMT_CBS_CFM;
> +	case 0x01:
> +		return SND_SOC_DAIFMT_CBM_CFS;
> +	default:
> +		return SND_SOC_DAIFMT_CBM_CFM;
> +	}
> +
> +	/* Shouldn't be here */
> +	return -EINVAL;
> +}

It will be nice if we declare the switch case numbers as macros (specific name)...
Jean-Francois Moine Sept. 2, 2014, 10:38 a.m. UTC | #2
On Tue, 02 Sep 2014 15:51:41 +0530
Varka Bhadram <varkabhadram@gmail.com> wrote:

> > +	switch (((np == bitclkmaster) << 4) | (np == framemaster)) {
> > +	case 0x11:
> > +		return SND_SOC_DAIFMT_CBS_CFS;
> > +	case 0x10:
> > +		return SND_SOC_DAIFMT_CBS_CFM;
> > +	case 0x01:
> > +		return SND_SOC_DAIFMT_CBM_CFS;
> > +	default:
> > +		return SND_SOC_DAIFMT_CBM_CFM;
> > +	}
> > +
> > +	/* Shouldn't be here */
> > +	return -EINVAL;
> > +}  
> 
> It will be nice if we declare the switch case numbers as macros (specific name)...

I don't see which macros: the values are just 2 booleans.
Varka Bhadram Sept. 2, 2014, 10:42 a.m. UTC | #3
On 09/02/2014 04:08 PM, Jean-Francois Moine wrote:
> On Tue, 02 Sep 2014 15:51:41 +0530
> Varka Bhadram <varkabhadram@gmail.com> wrote:
>
>>> +	switch (((np == bitclkmaster) << 4) | (np == framemaster)) {
>>> +	case 0x11:
>>> +		return SND_SOC_DAIFMT_CBS_CFS;
>>> +	case 0x10:
>>> +		return SND_SOC_DAIFMT_CBS_CFM;
>>> +	case 0x01:
>>> +		return SND_SOC_DAIFMT_CBM_CFS;
>>> +	default:
>>> +		return SND_SOC_DAIFMT_CBM_CFM;
>>> +	}
>>> +
>>> +	/* Shouldn't be here */
>>> +	return -EINVAL;
>>> +}
>> It will be nice if we declare the switch case numbers as macros (specific name)...
> I don't see which macros: the values are just 2 booleans.
>
I am talking about 0x11, 0x10, 0x01 values.. We can give any understandable
names to those...?
Takashi Iwai Sept. 2, 2014, 11:04 a.m. UTC | #4
At Tue, 02 Sep 2014 16:12:40 +0530,
Varka Bhadram wrote:
> 
> On 09/02/2014 04:08 PM, Jean-Francois Moine wrote:
> > On Tue, 02 Sep 2014 15:51:41 +0530
> > Varka Bhadram <varkabhadram@gmail.com> wrote:
> >
> >>> +	switch (((np == bitclkmaster) << 4) | (np == framemaster)) {
> >>> +	case 0x11:
> >>> +		return SND_SOC_DAIFMT_CBS_CFS;
> >>> +	case 0x10:
> >>> +		return SND_SOC_DAIFMT_CBS_CFM;
> >>> +	case 0x01:
> >>> +		return SND_SOC_DAIFMT_CBM_CFS;
> >>> +	default:
> >>> +		return SND_SOC_DAIFMT_CBM_CFM;
> >>> +	}
> >>> +
> >>> +	/* Shouldn't be here */
> >>> +	return -EINVAL;
> >>> +}
> >> It will be nice if we declare the switch case numbers as macros (specific name)...
> > I don't see which macros: the values are just 2 booleans.
> >
> I am talking about 0x11, 0x10, 0x01 values.. We can give any understandable
> names to those...?

The whole switch block is too hackish, makes unnecessarily complex.
It can be more strightforwardly like:

	if (np == bitclkmaster)
		return np == framemater ?
			SND_SOC_DAIFMT_CBS_CFS : SND_SOC_DAIFMT_CBS_CFM;
	else
		return np == framemaster ?
			SND_SOC_DAIFMT_CBM_CFS : SND_SOC_DAIFMT_CBM_CFM;

Or, if you love efficiency and complexity, something like:

#define SND_SOC_DAIFMT(_np, _clk, _frame) \
	((((_np) != (_clk)) | (((_np) != (_frame)) << 1) << 12) + (1 << 12)

Then
	return SND_SOC_DAIFMT(np, blkclkmaster, framemaster);

Takashi
Jean-Francois Moine Sept. 2, 2014, 11:09 a.m. UTC | #5
On Tue, 02 Sep 2014 16:12:40 +0530
Varka Bhadram <varkabhadram@gmail.com> wrote:

> >>> +	switch (((np == bitclkmaster) << 4) | (np == framemaster)) {
> >>> +	case 0x11:
> >>> +		return SND_SOC_DAIFMT_CBS_CFS;
> >>> +	case 0x10:
> >>> +		return SND_SOC_DAIFMT_CBS_CFM;
> >>> +	case 0x01:
> >>> +		return SND_SOC_DAIFMT_CBM_CFS;
> >>> +	default:
> >>> +		return SND_SOC_DAIFMT_CBM_CFM;
> >>> +	}
> >>> +
> >>> +	/* Shouldn't be here */
> >>> +	return -EINVAL;
> >>> +}  
> >> It will be nice if we declare the switch case numbers as macros (specific name)...  
> > I don't see which macros: the values are just 2 booleans.
> >  
> I am talking about 0x11, 0x10, 0x01 values.. We can give any understandable
> names to those...?

#define TRUE_TRUE 0x11
#define TRUE_FALSE 0x10
#define FALSE_TRUE 0x01

or

	case ((TRUE << 4) | TRUE:
		...
	case ((TRUE << 4) | FALSE:
		...
	case ((FALSE << 4) | TRUE:
		...

??
Jyri Sarha Sept. 2, 2014, 11:10 a.m. UTC | #6
On 09/02/2014 12:26 PM, Xiubo Li wrote:
> Signed-off-by: Xiubo Li <Li.Xiubo@freescale.com>
> ---
>   sound/soc/generic/simple-card.c | 61 ++++++++++++++++++++---------------------
>   1 file changed, 29 insertions(+), 32 deletions(-)
>
> diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c
> index 986d2c7..cad2b30 100644
> --- a/sound/soc/generic/simple-card.c
> +++ b/sound/soc/generic/simple-card.c
> @@ -163,6 +163,26 @@ asoc_simple_card_sub_parse_of(struct device_node *np,
>   	return 0;
>   }
>
> +static inline unsigned int
> +asoc_simple_card_fmt_master(struct device_node *np,
> +			    struct device_node *bitclkmaster,
> +			    struct device_node *framemaster)
> +{
> +	switch (((np == bitclkmaster) << 4) | (np == framemaster)) {
> +	case 0x11:
> +		return SND_SOC_DAIFMT_CBS_CFS;
> +	case 0x10:
> +		return SND_SOC_DAIFMT_CBS_CFM;
> +	case 0x01:
> +		return SND_SOC_DAIFMT_CBM_CFS;
> +	default:
> +		return SND_SOC_DAIFMT_CBM_CFM;
> +	}
> +
> +	/* Shouldn't be here */
> +	return -EINVAL;
> +}
> +
....
> +	fmt = asoc_simple_card_fmt_master(np, bitclkmaster, framemaster);
> +	dai_props->cpu_dai.fmt = daifmt | fmt;
...
> +		fmt = asoc_simple_card_fmt_master(np, bitclkmaster,
> +						  framemaster);
> +		dai_props->codec_dai.fmt = daifmt | fmt;

This won't work. The logic for cpu node needs to be negated for codec node.

Best regards,
Jyri
Jyri Sarha Sept. 2, 2014, 11:32 a.m. UTC | #7
On 09/02/2014 02:09 PM, Jean-Francois Moine wrote:
> On Tue, 02 Sep 2014 16:12:40 +0530
> Varka Bhadram <varkabhadram@gmail.com> wrote:
>
>>>>> +	switch (((np == bitclkmaster) << 4) | (np == framemaster)) {
>>>>> +	case 0x11:
>>>>> +		return SND_SOC_DAIFMT_CBS_CFS;
>>>>> +	case 0x10:
>>>>> +		return SND_SOC_DAIFMT_CBS_CFM;
>>>>> +	case 0x01:
>>>>> +		return SND_SOC_DAIFMT_CBM_CFS;
>>>>> +	default:
>>>>> +		return SND_SOC_DAIFMT_CBM_CFM;
>>>>> +	}
>>>>> +
>>>>> +	/* Shouldn't be here */
>>>>> +	return -EINVAL;
>>>>> +}
>>>> It will be nice if we declare the switch case numbers as macros (specific name)...
>>> I don't see which macros: the values are just 2 booleans.
>>>
>> I am talking about 0x11, 0x10, 0x01 values.. We can give any understandable
>> names to those...?
>
> #define TRUE_TRUE 0x11
> #define TRUE_FALSE 0x10
> #define FALSE_TRUE 0x01
>
> or
>
> 	case ((TRUE << 4) | TRUE:
> 		...
> 	case ((TRUE << 4) | FALSE:
> 		...
> 	case ((FALSE << 4) | TRUE:
> 		...
>

I would vote for this. Even over the options suggested by Takashi, but 
then again this really a matter of taste.

The fact that frame and bit-clock master boolean values are bundled into 
a single "enum" field, instead of two dedicated bits, makes all options 
bit inconvenient.

Best regards,
Jyri
Xiubo Li Sept. 3, 2014, 2:37 a.m. UTC | #8
> Subject: Re: [PATCHv2 1/4] ASoC: simple-card: add asoc_simple_card_fmt_master()
> to simplify the code.
> 
> On 09/02/2014 12:26 PM, Xiubo Li wrote:
> > Signed-off-by: Xiubo Li <Li.Xiubo@freescale.com>
> > ---
> >   sound/soc/generic/simple-card.c | 61 ++++++++++++++++++++-----------------
> ----
> >   1 file changed, 29 insertions(+), 32 deletions(-)
> >
> > diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-
> card.c
> > index 986d2c7..cad2b30 100644
> > --- a/sound/soc/generic/simple-card.c
> > +++ b/sound/soc/generic/simple-card.c
> > @@ -163,6 +163,26 @@ asoc_simple_card_sub_parse_of(struct device_node *np,
> >   	return 0;
> >   }
> >
> > +static inline unsigned int
> > +asoc_simple_card_fmt_master(struct device_node *np,
> > +			    struct device_node *bitclkmaster,
> > +			    struct device_node *framemaster)
> > +{
> > +	switch (((np == bitclkmaster) << 4) | (np == framemaster)) {
> > +	case 0x11:
> > +		return SND_SOC_DAIFMT_CBS_CFS;
> > +	case 0x10:
> > +		return SND_SOC_DAIFMT_CBS_CFM;
> > +	case 0x01:
> > +		return SND_SOC_DAIFMT_CBM_CFS;
> > +	default:
> > +		return SND_SOC_DAIFMT_CBM_CFM;
> > +	}
> > +
> > +	/* Shouldn't be here */
> > +	return -EINVAL;
> > +}
> > +
> ....
> > +	fmt = asoc_simple_card_fmt_master(np, bitclkmaster, framemaster);
> > +	dai_props->cpu_dai.fmt = daifmt | fmt;
> ...
> > +		fmt = asoc_simple_card_fmt_master(np, bitclkmaster,
> > +						  framemaster);
> > +		dai_props->codec_dai.fmt = daifmt | fmt;
> 
> This won't work. The logic for cpu node needs to be negated for codec node.
> 

Yes, actually it should be.

As my previous patches about this:
----
Since from the DAI format micro SND_SOC_DAIFMT_CBx_CFx, the 'CBx'
mean Codec's bit clock is as master/slave and the 'CFx' mean Codec's
frame clock is as master/slave.

So these same DAI formats should be informed to CPU and CODE DAIs at
the same time. For the Codec driver will set the bit clock and frame
clock as the DAI formats said, but for the CPU driver, if the the
bit clock or frame clock is as Codec master, so it should be set CPU
DAI device as bit clock or frame clock as slave, and vice versa.

The old code will cause confusion, and we should be clear that the
letter 'C' here mean to Codec.
----

For the master format, no matter for CPU or CODEC, it always means Codec
is master or slave for bit/frame clock, not means the local DAI device's
bit/frame clock as master or slave.

So your CPU DAI device driver should negate this locally as the existed
Ones do.

Thanks,

BRs
Xiubo
Jyri Sarha Sept. 3, 2014, 8:36 a.m. UTC | #9
On 09/03/2014 05:37 AM, Li.Xiubo@freescale.com wrote:
>> Subject: Re: [PATCHv2 1/4] ASoC: simple-card: add asoc_simple_card_fmt_master()
...
>>
>> This won't work. The logic for cpu node needs to be negated for codec node.
>>
>
> Yes, actually it should be.
>
> As my previous patches about this:
> ----
> Since from the DAI format micro SND_SOC_DAIFMT_CBx_CFx, the 'CBx'
> mean Codec's bit clock is as master/slave and the 'CFx' mean Codec's
> frame clock is as master/slave.
>
> So these same DAI formats should be informed to CPU and CODE DAIs at
> the same time. For the Codec driver will set the bit clock and frame
> clock as the DAI formats said, but for the CPU driver, if the the
> bit clock or frame clock is as Codec master, so it should be set CPU
> DAI device as bit clock or frame clock as slave, and vice versa.
>
> The old code will cause confusion, and we should be clear that the
> letter 'C' here mean to Codec.
> ----
>
> For the master format, no matter for CPU or CODEC, it always means Codec
> is master or slave for bit/frame clock, not means the local DAI device's
> bit/frame clock as master or slave.
>
> So your CPU DAI device driver should negate this locally as the existed
> Ones do.
>


Yes, but there is double negation in this patch. The switch-case
assignments depend on whether the bitclkmaster and framemaster
DT-node pointers are compared to a cpu-dai-node or
codec-dai-node. When your patch compares the codec-node, it does
the decisions like it was a cpu-node, which produces inverted CBM
and CFM setting.

However, Kurinori-san's patch fixes this problem because it just
uses the daifmt generated by comparing to codec node for both cpu
and codec nodes.

The reason why I did the comparison per node basis, was to make
the code more ready for tdm setups with multiple codecs on a same
wire. But writing code for something that is not really needed
yet is usually a bad idea, like it was this time too.

Kurinori-san's version of the fix should be fine and it cleans up
the code quite nicely.

Best regards,
Jyri
Xiubo Li Sept. 3, 2014, 8:39 a.m. UTC | #10
> Subject: Re: [PATCHv2 1/4] ASoC: simple-card: add asoc_simple_card_fmt_master()
> to simplify the code.
> 
> On 09/03/2014 05:37 AM, Li.Xiubo@freescale.com wrote:
> >> Subject: Re: [PATCHv2 1/4] ASoC: simple-card: add
> asoc_simple_card_fmt_master()
> ...
> >>
> >> This won't work. The logic for cpu node needs to be negated for codec node.
> >>
> >
> > Yes, actually it should be.
> >
> > As my previous patches about this:
> > ----
> > Since from the DAI format micro SND_SOC_DAIFMT_CBx_CFx, the 'CBx'
> > mean Codec's bit clock is as master/slave and the 'CFx' mean Codec's
> > frame clock is as master/slave.
> >
> > So these same DAI formats should be informed to CPU and CODE DAIs at
> > the same time. For the Codec driver will set the bit clock and frame
> > clock as the DAI formats said, but for the CPU driver, if the the
> > bit clock or frame clock is as Codec master, so it should be set CPU
> > DAI device as bit clock or frame clock as slave, and vice versa.
> >
> > The old code will cause confusion, and we should be clear that the
> > letter 'C' here mean to Codec.
> > ----
> >
> > For the master format, no matter for CPU or CODEC, it always means Codec
> > is master or slave for bit/frame clock, not means the local DAI device's
> > bit/frame clock as master or slave.
> >
> > So your CPU DAI device driver should negate this locally as the existed
> > Ones do.
> >
> 
> 
> Yes, but there is double negation in this patch. The switch-case
> assignments depend on whether the bitclkmaster and framemaster
> DT-node pointers are compared to a cpu-dai-node or
> codec-dai-node. When your patch compares the codec-node, it does
> the decisions like it was a cpu-node, which produces inverted CBM
> and CFM setting.
> 
> However, Kurinori-san's patch fixes this problem because it just
> uses the daifmt generated by comparing to codec node for both cpu
> and codec nodes.
> 
> The reason why I did the comparison per node basis, was to make
> the code more ready for tdm setups with multiple codecs on a same
> wire. But writing code for something that is not really needed
> yet is usually a bad idea, like it was this time too.
> 
> Kurinori-san's version of the fix should be fine and it cleans up
> the code quite nicely.
> 

Yes, agree.

So I just removed this patch from my patch series list.

Kuninori-san will post his local patch about this later.

Thanks,

BRs
Xiubo

Patch
diff mbox

diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c
index 986d2c7..cad2b30 100644
--- a/sound/soc/generic/simple-card.c
+++ b/sound/soc/generic/simple-card.c
@@ -163,6 +163,26 @@  asoc_simple_card_sub_parse_of(struct device_node *np,
 	return 0;
 }
 
+static inline unsigned int
+asoc_simple_card_fmt_master(struct device_node *np,
+			    struct device_node *bitclkmaster,
+			    struct device_node *framemaster)
+{
+	switch (((np == bitclkmaster) << 4) | (np == framemaster)) {
+	case 0x11:
+		return SND_SOC_DAIFMT_CBS_CFS;
+	case 0x10:
+		return SND_SOC_DAIFMT_CBS_CFM;
+	case 0x01:
+		return SND_SOC_DAIFMT_CBM_CFS;
+	default:
+		return SND_SOC_DAIFMT_CBM_CFM;
+	}
+
+	/* Shouldn't be here */
+	return -EINVAL;
+}
+
 static int asoc_simple_card_dai_link_of(struct device_node *node,
 					struct device *dev,
 					struct snd_soc_dai_link *dai_link,
@@ -172,7 +192,7 @@  static int asoc_simple_card_dai_link_of(struct device_node *node,
 	struct device_node *np = NULL;
 	struct device_node *bitclkmaster = NULL;
 	struct device_node *framemaster = NULL;
-	unsigned int daifmt;
+	unsigned int daifmt, fmt;
 	char *name;
 	char prop[128];
 	char *prefix = "";
@@ -185,6 +205,7 @@  static int asoc_simple_card_dai_link_of(struct device_node *node,
 					 &bitclkmaster, &framemaster);
 	daifmt &= ~SND_SOC_DAIFMT_MASTER_MASK;
 
+	/* Parse CPU DAI sub-node */
 	snprintf(prop, sizeof(prop), "%scpu", prefix);
 	np = of_get_child_by_name(node, prop);
 	if (!np) {
@@ -199,23 +220,11 @@  static int asoc_simple_card_dai_link_of(struct device_node *node,
 	if (ret < 0)
 		goto dai_link_of_err;
 
-	dai_props->cpu_dai.fmt = daifmt;
-	switch (((np == bitclkmaster) << 4) | (np == framemaster)) {
-	case 0x11:
-		dai_props->cpu_dai.fmt |= SND_SOC_DAIFMT_CBS_CFS;
-		break;
-	case 0x10:
-		dai_props->cpu_dai.fmt |= SND_SOC_DAIFMT_CBS_CFM;
-		break;
-	case 0x01:
-		dai_props->cpu_dai.fmt |= SND_SOC_DAIFMT_CBM_CFS;
-		break;
-	default:
-		dai_props->cpu_dai.fmt |= SND_SOC_DAIFMT_CBM_CFM;
-		break;
-	}
-
+	fmt = asoc_simple_card_fmt_master(np, bitclkmaster, framemaster);
+	dai_props->cpu_dai.fmt = daifmt | fmt;
 	of_node_put(np);
+
+	/* Parse CODEC DAI sub-node */
 	snprintf(prop, sizeof(prop), "%scodec", prefix);
 	np = of_get_child_by_name(node, prop);
 	if (!np) {
@@ -240,21 +249,9 @@  static int asoc_simple_card_dai_link_of(struct device_node *node,
 			snd_soc_of_parse_daifmt(np, NULL, NULL, NULL) |
 			(daifmt & ~SND_SOC_DAIFMT_CLOCK_MASK);
 	} else {
-		dai_props->codec_dai.fmt = daifmt;
-		switch (((np == bitclkmaster) << 4) | (np == framemaster)) {
-		case 0x11:
-			dai_props->codec_dai.fmt |= SND_SOC_DAIFMT_CBM_CFM;
-			break;
-		case 0x10:
-			dai_props->codec_dai.fmt |= SND_SOC_DAIFMT_CBM_CFS;
-			break;
-		case 0x01:
-			dai_props->codec_dai.fmt |= SND_SOC_DAIFMT_CBS_CFM;
-			break;
-		default:
-			dai_props->codec_dai.fmt |= SND_SOC_DAIFMT_CBS_CFS;
-			break;
-		}
+		fmt = asoc_simple_card_fmt_master(np, bitclkmaster,
+						  framemaster);
+		dai_props->codec_dai.fmt = daifmt | fmt;
 	}
 
 	if (!dai_link->cpu_dai_name || !dai_link->codec_dai_name) {