Re: [PATCH 1/2] ASoC: atmel-classd: add the Audio Class D Amplifier code

2015-09-14 Thread Wu, Songjun



On 9/11/2015 18:34, Mark Brown wrote:

On Thu, Sep 10, 2015 at 10:31:04AM +0800, Wu, Songjun wrote:

On 9/9/2015 17:52, Mark Brown wrote:



Yes, that's what's going to end up happening but it's not how controls
are expected to behave - applications will expect changing one control
to leave others unaffected so it's better to return an error rather than
change the other control.



If application change non EQ controls, the others will be unaffected. But
the classD IP can only supports one EQ control at once, these three EQ
controls point to the same register field, if application set a different EQ
control, the error occurs, there will be many errors, it's not very
reasonable to application. The best way I think is if application set one EQ
control, the other EQ controls will change to 0dB, it's also consistent with
fact.


There's no really good solutions here - this is why my initial
suggestion was to have a single enumerated control.

You are right, your suggestion is reasonable, to have a single 
enumerated control. The second version will be made and sent soon.

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/2] ASoC: atmel-classd: add the Audio Class D Amplifier code

2015-09-14 Thread Wu, Songjun



On 9/11/2015 18:34, Mark Brown wrote:

On Thu, Sep 10, 2015 at 10:31:04AM +0800, Wu, Songjun wrote:

On 9/9/2015 17:52, Mark Brown wrote:



Yes, that's what's going to end up happening but it's not how controls
are expected to behave - applications will expect changing one control
to leave others unaffected so it's better to return an error rather than
change the other control.



If application change non EQ controls, the others will be unaffected. But
the classD IP can only supports one EQ control at once, these three EQ
controls point to the same register field, if application set a different EQ
control, the error occurs, there will be many errors, it's not very
reasonable to application. The best way I think is if application set one EQ
control, the other EQ controls will change to 0dB, it's also consistent with
fact.


There's no really good solutions here - this is why my initial
suggestion was to have a single enumerated control.

You are right, your suggestion is reasonable, to have a single 
enumerated control. The second version will be made and sent soon.

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/2] ASoC: atmel-classd: add the Audio Class D Amplifier code

2015-09-11 Thread Mark Brown
On Thu, Sep 10, 2015 at 10:31:04AM +0800, Wu, Songjun wrote:
> On 9/9/2015 17:52, Mark Brown wrote:

> >Yes, that's what's going to end up happening but it's not how controls
> >are expected to behave - applications will expect changing one control
> >to leave others unaffected so it's better to return an error rather than
> >change the other control.

> If application change non EQ controls, the others will be unaffected. But
> the classD IP can only supports one EQ control at once, these three EQ
> controls point to the same register field, if application set a different EQ
> control, the error occurs, there will be many errors, it's not very
> reasonable to application. The best way I think is if application set one EQ
> control, the other EQ controls will change to 0dB, it's also consistent with
> fact.

There's no really good solutions here - this is why my initial
suggestion was to have a single enumerated control.


signature.asc
Description: Digital signature


Re: [PATCH 1/2] ASoC: atmel-classd: add the Audio Class D Amplifier code

2015-09-11 Thread Mark Brown
On Thu, Sep 10, 2015 at 10:31:04AM +0800, Wu, Songjun wrote:
> On 9/9/2015 17:52, Mark Brown wrote:

> >Yes, that's what's going to end up happening but it's not how controls
> >are expected to behave - applications will expect changing one control
> >to leave others unaffected so it's better to return an error rather than
> >change the other control.

> If application change non EQ controls, the others will be unaffected. But
> the classD IP can only supports one EQ control at once, these three EQ
> controls point to the same register field, if application set a different EQ
> control, the error occurs, there will be many errors, it's not very
> reasonable to application. The best way I think is if application set one EQ
> control, the other EQ controls will change to 0dB, it's also consistent with
> fact.

There's no really good solutions here - this is why my initial
suggestion was to have a single enumerated control.


signature.asc
Description: Digital signature


Re: [PATCH 1/2] ASoC: atmel-classd: add the Audio Class D Amplifier code

2015-09-09 Thread Wu, Songjun



On 9/9/2015 17:52, Mark Brown wrote:

On Wed, Sep 09, 2015 at 11:16:08AM +0800, Wu, Songjun wrote:

On 9/8/2015 20:23, Mark Brown wrote:



If you want to have three controls you need to write code so that the
user can only change one of them from 0dB at once, returning an error
otherwise.  That was why it looked like they were three separate
controls.



If user operates two or tree controls at the same time, for my
understanding, these operations are serial actually in kernel, not parallel,
and the last operation will be effective. I only write the function
'classd_get_eq_enum' to get the enumeration value, if user changes one of
controls, the other controls will get 0dB. Is my understanding correct?


Yes, that's what's going to end up happening but it's not how controls
are expected to behave - applications will expect changing one control
to leave others unaffected so it's better to return an error rather than
change the other control.

If application change non EQ controls, the others will be unaffected. 
But the classD IP can only supports one EQ control at once, these three 
EQ controls point to the same register field, if application set a 
different EQ control, the error occurs, there will be many errors, it's 
not very reasonable to application. The best way I think is if 
application set one EQ control, the other EQ controls will change to 
0dB, it's also consistent with fact.

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/2] ASoC: atmel-classd: add the Audio Class D Amplifier code

2015-09-09 Thread Mark Brown
On Wed, Sep 09, 2015 at 11:16:08AM +0800, Wu, Songjun wrote:
> On 9/8/2015 20:23, Mark Brown wrote:

> >If you want to have three controls you need to write code so that the
> >user can only change one of them from 0dB at once, returning an error
> >otherwise.  That was why it looked like they were three separate
> >controls.

> If user operates two or tree controls at the same time, for my
> understanding, these operations are serial actually in kernel, not parallel,
> and the last operation will be effective. I only write the function
> 'classd_get_eq_enum' to get the enumeration value, if user changes one of
> controls, the other controls will get 0dB. Is my understanding correct?

Yes, that's what's going to end up happening but it's not how controls
are expected to behave - applications will expect changing one control
to leave others unaffected so it's better to return an error rather than
change the other control.


signature.asc
Description: Digital signature


Re: [PATCH 1/2] ASoC: atmel-classd: add the Audio Class D Amplifier code

2015-09-09 Thread Mark Brown
On Wed, Sep 09, 2015 at 11:16:08AM +0800, Wu, Songjun wrote:
> On 9/8/2015 20:23, Mark Brown wrote:

> >If you want to have three controls you need to write code so that the
> >user can only change one of them from 0dB at once, returning an error
> >otherwise.  That was why it looked like they were three separate
> >controls.

> If user operates two or tree controls at the same time, for my
> understanding, these operations are serial actually in kernel, not parallel,
> and the last operation will be effective. I only write the function
> 'classd_get_eq_enum' to get the enumeration value, if user changes one of
> controls, the other controls will get 0dB. Is my understanding correct?

Yes, that's what's going to end up happening but it's not how controls
are expected to behave - applications will expect changing one control
to leave others unaffected so it's better to return an error rather than
change the other control.


signature.asc
Description: Digital signature


Re: [PATCH 1/2] ASoC: atmel-classd: add the Audio Class D Amplifier code

2015-09-09 Thread Wu, Songjun



On 9/9/2015 17:52, Mark Brown wrote:

On Wed, Sep 09, 2015 at 11:16:08AM +0800, Wu, Songjun wrote:

On 9/8/2015 20:23, Mark Brown wrote:



If you want to have three controls you need to write code so that the
user can only change one of them from 0dB at once, returning an error
otherwise.  That was why it looked like they were three separate
controls.



If user operates two or tree controls at the same time, for my
understanding, these operations are serial actually in kernel, not parallel,
and the last operation will be effective. I only write the function
'classd_get_eq_enum' to get the enumeration value, if user changes one of
controls, the other controls will get 0dB. Is my understanding correct?


Yes, that's what's going to end up happening but it's not how controls
are expected to behave - applications will expect changing one control
to leave others unaffected so it's better to return an error rather than
change the other control.

If application change non EQ controls, the others will be unaffected. 
But the classD IP can only supports one EQ control at once, these three 
EQ controls point to the same register field, if application set a 
different EQ control, the error occurs, there will be many errors, it's 
not very reasonable to application. The best way I think is if 
application set one EQ control, the other EQ controls will change to 
0dB, it's also consistent with fact.

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/2] ASoC: atmel-classd: add the Audio Class D Amplifier code

2015-09-08 Thread Wu, Songjun



On 9/8/2015 20:23, Mark Brown wrote:

On Tue, Sep 08, 2015 at 05:36:01PM +0800, Wu, Songjun wrote:

On 9/8/2015 00:23, Mark Brown wrote:



OK, so that's not actually what the code was doing - it had separate
enums for bass, mid and treble.  If you make this a single enum with all
the above options in it that seems like the best way of handling things.



A single enum seems not very friendly to user, there are tree EQs, bass,
medium and treble.
So I create tree enum controls to control three EQs.
The 'get' function is replaced by 'classd_get_eq_enum', if user operates one
of the tree EQ controls, the other two EQs will show 0 dB.


If you want to have three controls you need to write code so that the
user can only change one of them from 0dB at once, returning an error
otherwise.  That was why it looked like they were three separate
controls.

If user operates two or tree controls at the same time, for my 
understanding, these operations are serial actually in kernel, not 
parallel, and the last operation will be effective. I only write the 
function 'classd_get_eq_enum' to get the enumeration value, if user 
changes one of controls, the other controls will get 0dB. Is my 
understanding correct?

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/2] ASoC: atmel-classd: add the Audio Class D Amplifier code

2015-09-08 Thread Mark Brown
On Tue, Sep 08, 2015 at 05:36:01PM +0800, Wu, Songjun wrote:
> On 9/8/2015 00:23, Mark Brown wrote:

> >OK, so that's not actually what the code was doing - it had separate
> >enums for bass, mid and treble.  If you make this a single enum with all
> >the above options in it that seems like the best way of handling things.

> A single enum seems not very friendly to user, there are tree EQs, bass,
> medium and treble.
> So I create tree enum controls to control three EQs.
> The 'get' function is replaced by 'classd_get_eq_enum', if user operates one
> of the tree EQ controls, the other two EQs will show 0 dB.

If you want to have three controls you need to write code so that the
user can only change one of them from 0dB at once, returning an error
otherwise.  That was why it looked like they were three separate
controls.


signature.asc
Description: Digital signature


Re: [PATCH 1/2] ASoC: atmel-classd: add the Audio Class D Amplifier code

2015-09-08 Thread Wu, Songjun



On 9/8/2015 00:23, Mark Brown wrote:

On Sun, Sep 06, 2015 at 05:44:21PM +0800, Wu, Songjun wrote:

On 9/3/2015 19:37, Mark Brown wrote:

On Tue, Sep 01, 2015 at 01:41:40PM +0800, Songjun Wu wrote:



+static const char * const eqcfg_bass_text[] = {
+   "-12 dB", "-6 dB", "0 dB", "+6 dB", "+12 dB"
+};



+static const unsigned int eqcfg_bass_value[] = {
+   CLASSD_INTPMR_EQCFG_B_CUT_12,
+   CLASSD_INTPMR_EQCFG_B_CUT_6, CLASSD_INTPMR_EQCFG_FLAT,
+   CLASSD_INTPMR_EQCFG_B_BOOST_6, CLASSD_INTPMR_EQCFG_B_BOOST_12
+};



This should be a Volume control with TLV information, as should the
following few controls.



The Volume control with TLV information is not suitable for this case.
Bass, Medium, and treble are mutually exclusive.
So I think the SOC_ENUM control is suitable for this case.
The register layout is not very good,
The register is defined as below.
•  EQCFG: Equalization Selection
Value Name   Description
0 FLAT   Flat Response
1 BBOOST12   Bass boost +12 dB
2 BBOOST6Bass boost +6 dB
3 BCUT12 Bass cut -12 dB
4 BCUT6  Bass cut -6 dB
5 MBOOST3Medium boost +3 dB
6 MBOOST8Medium boost +8 dB
7 MCUT3  Medium cut -3 dB
8 MCUT8  Medium cut -8 dB
9 TBOOST12   Treble boost +12 dB
10TBOOST6Treble boost +6 dB
11TCUT12 Treble cut -12 dB
12TCUT6  Treble cut -6 dB


OK, so that's not actually what the code was doing - it had separate
enums for bass, mid and treble.  If you make this a single enum with all
the above options in it that seems like the best way of handling things.

A single enum seems not very friendly to user, there are tree EQs, bass, 
medium and treble.

So I create tree enum controls to control three EQs.
The 'get' function is replaced by 'classd_get_eq_enum', if user operates 
one of the tree EQ controls, the other two EQs will show 0 dB.



+static const struct snd_kcontrol_new atmel_classd_snd_controls[] = {
+SOC_SINGLE_TLV("Left Volume", CLASSD_INTPMR,
+   CLASSD_INTPMR_ATTL_SHIFT, 78, 1, classd_digital_tlv),
+
+SOC_SINGLE_TLV("Right Volume", CLASSD_INTPMR,
+   CLASSD_INTPMR_ATTR_SHIFT, 78, 1, classd_digital_tlv),


This should be a single stereo control rather than separate left and
right controls.



Since the classD IP defines two register fields to control left volume and
right volume respectively, I think it's better to provide two controls to
user.


No, this is really common, we combine them in Linux to present a
consistent interface to userspace.


I think carefully, your suggestion is reasonable.
The code will be modified, combine the left and right to a single stereo 
control.

Thank you.


+   dev_info(dev,
+   "Atmel Class D Amplifier (CLASSD) device at 0x%p (irq %d)\n",
+   io_base, dd->irq);



This is a bit noisy and not really based on interaction with the
hardware...  dev_dbg() seems better.



This information will occur only once when linux kernel starts.
It shows the classD is loaded to linux kernel.
I think it's better to provide more information to user.


This stuff all adds up and since it'll go out on the console by default
it both makes things more noisy and slows down boot - printing on the
serial port isn't free.  If we want to have this sort of information we
printed we should really do it in the driver core so it appears
consistently for all devices rather than having individual code in each
driver.


Accept, the code will be modified to dev_dbg().
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/2] ASoC: atmel-classd: add the Audio Class D Amplifier code

2015-09-08 Thread Wu, Songjun



On 9/8/2015 00:23, Mark Brown wrote:

On Sun, Sep 06, 2015 at 05:44:21PM +0800, Wu, Songjun wrote:

On 9/3/2015 19:37, Mark Brown wrote:

On Tue, Sep 01, 2015 at 01:41:40PM +0800, Songjun Wu wrote:



+static const char * const eqcfg_bass_text[] = {
+   "-12 dB", "-6 dB", "0 dB", "+6 dB", "+12 dB"
+};



+static const unsigned int eqcfg_bass_value[] = {
+   CLASSD_INTPMR_EQCFG_B_CUT_12,
+   CLASSD_INTPMR_EQCFG_B_CUT_6, CLASSD_INTPMR_EQCFG_FLAT,
+   CLASSD_INTPMR_EQCFG_B_BOOST_6, CLASSD_INTPMR_EQCFG_B_BOOST_12
+};



This should be a Volume control with TLV information, as should the
following few controls.



The Volume control with TLV information is not suitable for this case.
Bass, Medium, and treble are mutually exclusive.
So I think the SOC_ENUM control is suitable for this case.
The register layout is not very good,
The register is defined as below.
•  EQCFG: Equalization Selection
Value Name   Description
0 FLAT   Flat Response
1 BBOOST12   Bass boost +12 dB
2 BBOOST6Bass boost +6 dB
3 BCUT12 Bass cut -12 dB
4 BCUT6  Bass cut -6 dB
5 MBOOST3Medium boost +3 dB
6 MBOOST8Medium boost +8 dB
7 MCUT3  Medium cut -3 dB
8 MCUT8  Medium cut -8 dB
9 TBOOST12   Treble boost +12 dB
10TBOOST6Treble boost +6 dB
11TCUT12 Treble cut -12 dB
12TCUT6  Treble cut -6 dB


OK, so that's not actually what the code was doing - it had separate
enums for bass, mid and treble.  If you make this a single enum with all
the above options in it that seems like the best way of handling things.

A single enum seems not very friendly to user, there are tree EQs, bass, 
medium and treble.

So I create tree enum controls to control three EQs.
The 'get' function is replaced by 'classd_get_eq_enum', if user operates 
one of the tree EQ controls, the other two EQs will show 0 dB.



+static const struct snd_kcontrol_new atmel_classd_snd_controls[] = {
+SOC_SINGLE_TLV("Left Volume", CLASSD_INTPMR,
+   CLASSD_INTPMR_ATTL_SHIFT, 78, 1, classd_digital_tlv),
+
+SOC_SINGLE_TLV("Right Volume", CLASSD_INTPMR,
+   CLASSD_INTPMR_ATTR_SHIFT, 78, 1, classd_digital_tlv),


This should be a single stereo control rather than separate left and
right controls.



Since the classD IP defines two register fields to control left volume and
right volume respectively, I think it's better to provide two controls to
user.


No, this is really common, we combine them in Linux to present a
consistent interface to userspace.


I think carefully, your suggestion is reasonable.
The code will be modified, combine the left and right to a single stereo 
control.

Thank you.


+   dev_info(dev,
+   "Atmel Class D Amplifier (CLASSD) device at 0x%p (irq %d)\n",
+   io_base, dd->irq);



This is a bit noisy and not really based on interaction with the
hardware...  dev_dbg() seems better.



This information will occur only once when linux kernel starts.
It shows the classD is loaded to linux kernel.
I think it's better to provide more information to user.


This stuff all adds up and since it'll go out on the console by default
it both makes things more noisy and slows down boot - printing on the
serial port isn't free.  If we want to have this sort of information we
printed we should really do it in the driver core so it appears
consistently for all devices rather than having individual code in each
driver.


Accept, the code will be modified to dev_dbg().
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/2] ASoC: atmel-classd: add the Audio Class D Amplifier code

2015-09-08 Thread Mark Brown
On Tue, Sep 08, 2015 at 05:36:01PM +0800, Wu, Songjun wrote:
> On 9/8/2015 00:23, Mark Brown wrote:

> >OK, so that's not actually what the code was doing - it had separate
> >enums for bass, mid and treble.  If you make this a single enum with all
> >the above options in it that seems like the best way of handling things.

> A single enum seems not very friendly to user, there are tree EQs, bass,
> medium and treble.
> So I create tree enum controls to control three EQs.
> The 'get' function is replaced by 'classd_get_eq_enum', if user operates one
> of the tree EQ controls, the other two EQs will show 0 dB.

If you want to have three controls you need to write code so that the
user can only change one of them from 0dB at once, returning an error
otherwise.  That was why it looked like they were three separate
controls.


signature.asc
Description: Digital signature


Re: [PATCH 1/2] ASoC: atmel-classd: add the Audio Class D Amplifier code

2015-09-08 Thread Wu, Songjun



On 9/8/2015 20:23, Mark Brown wrote:

On Tue, Sep 08, 2015 at 05:36:01PM +0800, Wu, Songjun wrote:

On 9/8/2015 00:23, Mark Brown wrote:



OK, so that's not actually what the code was doing - it had separate
enums for bass, mid and treble.  If you make this a single enum with all
the above options in it that seems like the best way of handling things.



A single enum seems not very friendly to user, there are tree EQs, bass,
medium and treble.
So I create tree enum controls to control three EQs.
The 'get' function is replaced by 'classd_get_eq_enum', if user operates one
of the tree EQ controls, the other two EQs will show 0 dB.


If you want to have three controls you need to write code so that the
user can only change one of them from 0dB at once, returning an error
otherwise.  That was why it looked like they were three separate
controls.

If user operates two or tree controls at the same time, for my 
understanding, these operations are serial actually in kernel, not 
parallel, and the last operation will be effective. I only write the 
function 'classd_get_eq_enum' to get the enumeration value, if user 
changes one of controls, the other controls will get 0dB. Is my 
understanding correct?

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/2] ASoC: atmel-classd: add the Audio Class D Amplifier code

2015-09-07 Thread Mark Brown
On Sun, Sep 06, 2015 at 05:44:21PM +0800, Wu, Songjun wrote:
> On 9/3/2015 19:37, Mark Brown wrote:
> >On Tue, Sep 01, 2015 at 01:41:40PM +0800, Songjun Wu wrote:

> >>+static const char * const eqcfg_bass_text[] = {
> >>+   "-12 dB", "-6 dB", "0 dB", "+6 dB", "+12 dB"
> >>+};
> >
> >>+static const unsigned int eqcfg_bass_value[] = {
> >>+   CLASSD_INTPMR_EQCFG_B_CUT_12,
> >>+   CLASSD_INTPMR_EQCFG_B_CUT_6, CLASSD_INTPMR_EQCFG_FLAT,
> >>+   CLASSD_INTPMR_EQCFG_B_BOOST_6, CLASSD_INTPMR_EQCFG_B_BOOST_12
> >>+};

> >This should be a Volume control with TLV information, as should the
> >following few controls.

> The Volume control with TLV information is not suitable for this case.
> Bass, Medium, and treble are mutually exclusive.
> So I think the SOC_ENUM control is suitable for this case.
> The register layout is not very good,
> The register is defined as below.
> •  EQCFG: Equalization Selection
> Value Name   Description
> 0 FLAT   Flat Response
> 1 BBOOST12   Bass boost +12 dB
> 2 BBOOST6Bass boost +6 dB
> 3 BCUT12 Bass cut -12 dB
> 4 BCUT6  Bass cut -6 dB
> 5 MBOOST3Medium boost +3 dB
> 6 MBOOST8Medium boost +8 dB
> 7 MCUT3  Medium cut -3 dB
> 8 MCUT8  Medium cut -8 dB
> 9 TBOOST12   Treble boost +12 dB
> 10TBOOST6Treble boost +6 dB
> 11TCUT12 Treble cut -12 dB
> 12TCUT6  Treble cut -6 dB

OK, so that's not actually what the code was doing - it had separate
enums for bass, mid and treble.  If you make this a single enum with all
the above options in it that seems like the best way of handling things.

> >>+static const struct snd_kcontrol_new atmel_classd_snd_controls[] = {
> >>+SOC_SINGLE_TLV("Left Volume", CLASSD_INTPMR,
> >>+   CLASSD_INTPMR_ATTL_SHIFT, 78, 1, classd_digital_tlv),
> >>+
> >>+SOC_SINGLE_TLV("Right Volume", CLASSD_INTPMR,
> >>+   CLASSD_INTPMR_ATTR_SHIFT, 78, 1, classd_digital_tlv),
> >
> >This should be a single stereo control rather than separate left and
> >right controls.

> Since the classD IP defines two register fields to control left volume and
> right volume respectively, I think it's better to provide two controls to
> user.

No, this is really common, we combine them in Linux to present a
consistent interface to userspace.

> >>+   dev_info(dev,
> >>+   "Atmel Class D Amplifier (CLASSD) device at 0x%p (irq %d)\n",
> >>+   io_base, dd->irq);

> >This is a bit noisy and not really based on interaction with the
> >hardware...  dev_dbg() seems better.

> This information will occur only once when linux kernel starts.
> It shows the classD is loaded to linux kernel.
> I think it's better to provide more information to user.

This stuff all adds up and since it'll go out on the console by default
it both makes things more noisy and slows down boot - printing on the
serial port isn't free.  If we want to have this sort of information we
printed we should really do it in the driver core so it appears
consistently for all devices rather than having individual code in each
driver.


signature.asc
Description: Digital signature


Re: [PATCH 1/2] ASoC: atmel-classd: add the Audio Class D Amplifier code

2015-09-07 Thread Mark Brown
On Sun, Sep 06, 2015 at 05:44:21PM +0800, Wu, Songjun wrote:
> On 9/3/2015 19:37, Mark Brown wrote:
> >On Tue, Sep 01, 2015 at 01:41:40PM +0800, Songjun Wu wrote:

> >>+static const char * const eqcfg_bass_text[] = {
> >>+   "-12 dB", "-6 dB", "0 dB", "+6 dB", "+12 dB"
> >>+};
> >
> >>+static const unsigned int eqcfg_bass_value[] = {
> >>+   CLASSD_INTPMR_EQCFG_B_CUT_12,
> >>+   CLASSD_INTPMR_EQCFG_B_CUT_6, CLASSD_INTPMR_EQCFG_FLAT,
> >>+   CLASSD_INTPMR_EQCFG_B_BOOST_6, CLASSD_INTPMR_EQCFG_B_BOOST_12
> >>+};

> >This should be a Volume control with TLV information, as should the
> >following few controls.

> The Volume control with TLV information is not suitable for this case.
> Bass, Medium, and treble are mutually exclusive.
> So I think the SOC_ENUM control is suitable for this case.
> The register layout is not very good,
> The register is defined as below.
> •  EQCFG: Equalization Selection
> Value Name   Description
> 0 FLAT   Flat Response
> 1 BBOOST12   Bass boost +12 dB
> 2 BBOOST6Bass boost +6 dB
> 3 BCUT12 Bass cut -12 dB
> 4 BCUT6  Bass cut -6 dB
> 5 MBOOST3Medium boost +3 dB
> 6 MBOOST8Medium boost +8 dB
> 7 MCUT3  Medium cut -3 dB
> 8 MCUT8  Medium cut -8 dB
> 9 TBOOST12   Treble boost +12 dB
> 10TBOOST6Treble boost +6 dB
> 11TCUT12 Treble cut -12 dB
> 12TCUT6  Treble cut -6 dB

OK, so that's not actually what the code was doing - it had separate
enums for bass, mid and treble.  If you make this a single enum with all
the above options in it that seems like the best way of handling things.

> >>+static const struct snd_kcontrol_new atmel_classd_snd_controls[] = {
> >>+SOC_SINGLE_TLV("Left Volume", CLASSD_INTPMR,
> >>+   CLASSD_INTPMR_ATTL_SHIFT, 78, 1, classd_digital_tlv),
> >>+
> >>+SOC_SINGLE_TLV("Right Volume", CLASSD_INTPMR,
> >>+   CLASSD_INTPMR_ATTR_SHIFT, 78, 1, classd_digital_tlv),
> >
> >This should be a single stereo control rather than separate left and
> >right controls.

> Since the classD IP defines two register fields to control left volume and
> right volume respectively, I think it's better to provide two controls to
> user.

No, this is really common, we combine them in Linux to present a
consistent interface to userspace.

> >>+   dev_info(dev,
> >>+   "Atmel Class D Amplifier (CLASSD) device at 0x%p (irq %d)\n",
> >>+   io_base, dd->irq);

> >This is a bit noisy and not really based on interaction with the
> >hardware...  dev_dbg() seems better.

> This information will occur only once when linux kernel starts.
> It shows the classD is loaded to linux kernel.
> I think it's better to provide more information to user.

This stuff all adds up and since it'll go out on the console by default
it both makes things more noisy and slows down boot - printing on the
serial port isn't free.  If we want to have this sort of information we
printed we should really do it in the driver core so it appears
consistently for all devices rather than having individual code in each
driver.


signature.asc
Description: Digital signature


Re: [PATCH 1/2] ASoC: atmel-classd: add the Audio Class D Amplifier code

2015-09-06 Thread Wu, Songjun



On 9/3/2015 19:37, Mark Brown wrote:

On Tue, Sep 01, 2015 at 01:41:40PM +0800, Songjun Wu wrote:


+static const char * const mono_text[] = {
+   "stereo", "mono"
+};
+
+static SOC_ENUM_SINGLE_DECL(classd_mono_enum,
+   CLASSD_INTPMR, CLASSD_INTPMR_MONO_SHIFT,
+   mono_text);


This looks like it should be a simple Switch control called something
like "Stereo Switch" or "Mono Switch".


Thank you, the code will be modified as you suggest.


+static const char * const deemp_text[] = {
+   "disabled", "enabled"
+};
+
+static SOC_ENUM_SINGLE_DECL(classd_deemp_enum,
+   CLASSD_INTPMR, CLASSD_INTPMR_DEEMP_SHIFT,
+   deemp_text);


Similarly this looks like it should be "Deemph Switch".


Yes, it also will be modified.


+static const char * const eqcfg_bass_text[] = {
+   "-12 dB", "-6 dB", "0 dB", "+6 dB", "+12 dB"
+};



+static const unsigned int eqcfg_bass_value[] = {
+   CLASSD_INTPMR_EQCFG_B_CUT_12,
+   CLASSD_INTPMR_EQCFG_B_CUT_6, CLASSD_INTPMR_EQCFG_FLAT,
+   CLASSD_INTPMR_EQCFG_B_BOOST_6, CLASSD_INTPMR_EQCFG_B_BOOST_12
+};


This should be a Volume control with TLV information, as should the
following few controls.


The Volume control with TLV information is not suitable for this case.
Bass, Medium, and treble are mutually exclusive.
So I think the SOC_ENUM control is suitable for this case.
The register layout is not very good,
The register is defined as below.
•  EQCFG: Equalization Selection
Value Name   Description
0 FLAT   Flat Response
1 BBOOST12   Bass boost +12 dB
2 BBOOST6Bass boost +6 dB
3 BCUT12 Bass cut -12 dB
4 BCUT6  Bass cut -6 dB
5 MBOOST3Medium boost +3 dB
6 MBOOST8Medium boost +8 dB
7 MCUT3  Medium cut -3 dB
8 MCUT8  Medium cut -8 dB
9 TBOOST12   Treble boost +12 dB
10TBOOST6Treble boost +6 dB
11TCUT12 Treble cut -12 dB
12TCUT6  Treble cut -6 dB


+static const struct snd_kcontrol_new atmel_classd_snd_controls[] = {
+SOC_SINGLE_TLV("Left Volume", CLASSD_INTPMR,
+   CLASSD_INTPMR_ATTL_SHIFT, 78, 1, classd_digital_tlv),
+
+SOC_SINGLE_TLV("Right Volume", CLASSD_INTPMR,
+   CLASSD_INTPMR_ATTR_SHIFT, 78, 1, classd_digital_tlv),


This should be a single stereo control rather than separate left and
right controls.

Since the classD IP defines two register fields to control left volume 
and right volume respectively, I think it's better to provide two 
controls to user.



+static const char * const pwm_type[] = {
+   "single-ended", "differential"
+};


The normal style for ALSA controls is to capitalise strings so
"Single ended" and "Differential".


Accept. It will be modified.


+   if (pdata->non_overlap_enable) {
+   val |= (CLASSD_MR_NON_OVERLAP_EN
+   << CLASSD_MR_NON_OVERLAP_SHIFT);
+
+   mask |= CLASSD_MR_NOVR_VAL_MASK;
+   switch (pdata->non_overlap_time) {
+   case 5:
+   val |= (CLASSD_MR_NOVR_VAL_5NS
+   << CLASSD_MR_NOVR_VAL_SHIFT);
+   break;
+   case 10:
+   val |= (CLASSD_MR_NOVR_VAL_10NS
+   << CLASSD_MR_NOVR_VAL_SHIFT);
+   break;
+   case 15:
+   val |= (CLASSD_MR_NOVR_VAL_15NS
+   << CLASSD_MR_NOVR_VAL_SHIFT);
+   break;
+   case 20:
+   val |= (CLASSD_MR_NOVR_VAL_20NS
+   << CLASSD_MR_NOVR_VAL_SHIFT);
+   break;
+   default:
+   val |= (CLASSD_MR_NOVR_VAL_10NS
+   << CLASSD_MR_NOVR_VAL_SHIFT);
+   break;
+   }


I'd expect at least a warning if the user trys to specify an invalid
value (if they didn't specify any value then I'd expect the DT parsing
function to assign the default value).

Accept. A warning will be added if the user trys to sepcify an invalid 
value. This function is optional, So if the user did not specify any 
value, this function will be disabled.



+static struct regmap *atmel_classd_codec_get_remap(struct device *dev)
+{
+   struct atmel_classd *dd = dev_get_drvdata(dev);
+
+   return dd->regmap;
+}


Can you just use dev_get_regmap()?


Thank you for your reminder, it's better to use dev_get_regmap().
The code will be modified.


+static int atmel_classd_codec_dai_startup(struct snd_pcm_substream *substream,
+   struct snd_soc_dai *codec_dai)
+{
+   struct atmel_classd *dd = snd_soc_dai_get_drvdata(codec_dai);
+
+   clk_prepare_enable(dd->aclk);
+   clk_prepare_enable(dd->gclk);


Should check for errors here.


Accept.


+   dev_info(dev,
+   "Atmel Class D Amplifier (CLASSD) device at 

Re: [PATCH 1/2] ASoC: atmel-classd: add the Audio Class D Amplifier code

2015-09-06 Thread Wu, Songjun



On 9/3/2015 19:37, Mark Brown wrote:

On Tue, Sep 01, 2015 at 01:41:40PM +0800, Songjun Wu wrote:


+static const char * const mono_text[] = {
+   "stereo", "mono"
+};
+
+static SOC_ENUM_SINGLE_DECL(classd_mono_enum,
+   CLASSD_INTPMR, CLASSD_INTPMR_MONO_SHIFT,
+   mono_text);


This looks like it should be a simple Switch control called something
like "Stereo Switch" or "Mono Switch".


Thank you, the code will be modified as you suggest.


+static const char * const deemp_text[] = {
+   "disabled", "enabled"
+};
+
+static SOC_ENUM_SINGLE_DECL(classd_deemp_enum,
+   CLASSD_INTPMR, CLASSD_INTPMR_DEEMP_SHIFT,
+   deemp_text);


Similarly this looks like it should be "Deemph Switch".


Yes, it also will be modified.


+static const char * const eqcfg_bass_text[] = {
+   "-12 dB", "-6 dB", "0 dB", "+6 dB", "+12 dB"
+};



+static const unsigned int eqcfg_bass_value[] = {
+   CLASSD_INTPMR_EQCFG_B_CUT_12,
+   CLASSD_INTPMR_EQCFG_B_CUT_6, CLASSD_INTPMR_EQCFG_FLAT,
+   CLASSD_INTPMR_EQCFG_B_BOOST_6, CLASSD_INTPMR_EQCFG_B_BOOST_12
+};


This should be a Volume control with TLV information, as should the
following few controls.


The Volume control with TLV information is not suitable for this case.
Bass, Medium, and treble are mutually exclusive.
So I think the SOC_ENUM control is suitable for this case.
The register layout is not very good,
The register is defined as below.
•  EQCFG: Equalization Selection
Value Name   Description
0 FLAT   Flat Response
1 BBOOST12   Bass boost +12 dB
2 BBOOST6Bass boost +6 dB
3 BCUT12 Bass cut -12 dB
4 BCUT6  Bass cut -6 dB
5 MBOOST3Medium boost +3 dB
6 MBOOST8Medium boost +8 dB
7 MCUT3  Medium cut -3 dB
8 MCUT8  Medium cut -8 dB
9 TBOOST12   Treble boost +12 dB
10TBOOST6Treble boost +6 dB
11TCUT12 Treble cut -12 dB
12TCUT6  Treble cut -6 dB


+static const struct snd_kcontrol_new atmel_classd_snd_controls[] = {
+SOC_SINGLE_TLV("Left Volume", CLASSD_INTPMR,
+   CLASSD_INTPMR_ATTL_SHIFT, 78, 1, classd_digital_tlv),
+
+SOC_SINGLE_TLV("Right Volume", CLASSD_INTPMR,
+   CLASSD_INTPMR_ATTR_SHIFT, 78, 1, classd_digital_tlv),


This should be a single stereo control rather than separate left and
right controls.

Since the classD IP defines two register fields to control left volume 
and right volume respectively, I think it's better to provide two 
controls to user.



+static const char * const pwm_type[] = {
+   "single-ended", "differential"
+};


The normal style for ALSA controls is to capitalise strings so
"Single ended" and "Differential".


Accept. It will be modified.


+   if (pdata->non_overlap_enable) {
+   val |= (CLASSD_MR_NON_OVERLAP_EN
+   << CLASSD_MR_NON_OVERLAP_SHIFT);
+
+   mask |= CLASSD_MR_NOVR_VAL_MASK;
+   switch (pdata->non_overlap_time) {
+   case 5:
+   val |= (CLASSD_MR_NOVR_VAL_5NS
+   << CLASSD_MR_NOVR_VAL_SHIFT);
+   break;
+   case 10:
+   val |= (CLASSD_MR_NOVR_VAL_10NS
+   << CLASSD_MR_NOVR_VAL_SHIFT);
+   break;
+   case 15:
+   val |= (CLASSD_MR_NOVR_VAL_15NS
+   << CLASSD_MR_NOVR_VAL_SHIFT);
+   break;
+   case 20:
+   val |= (CLASSD_MR_NOVR_VAL_20NS
+   << CLASSD_MR_NOVR_VAL_SHIFT);
+   break;
+   default:
+   val |= (CLASSD_MR_NOVR_VAL_10NS
+   << CLASSD_MR_NOVR_VAL_SHIFT);
+   break;
+   }


I'd expect at least a warning if the user trys to specify an invalid
value (if they didn't specify any value then I'd expect the DT parsing
function to assign the default value).

Accept. A warning will be added if the user trys to sepcify an invalid 
value. This function is optional, So if the user did not specify any 
value, this function will be disabled.



+static struct regmap *atmel_classd_codec_get_remap(struct device *dev)
+{
+   struct atmel_classd *dd = dev_get_drvdata(dev);
+
+   return dd->regmap;
+}


Can you just use dev_get_regmap()?


Thank you for your reminder, it's better to use dev_get_regmap().
The code will be modified.


+static int atmel_classd_codec_dai_startup(struct snd_pcm_substream *substream,
+   struct snd_soc_dai *codec_dai)
+{
+   struct atmel_classd *dd = snd_soc_dai_get_drvdata(codec_dai);
+
+   clk_prepare_enable(dd->aclk);
+   clk_prepare_enable(dd->gclk);


Should check for errors here.


Accept.


+   dev_info(dev,
+   "Atmel Class D Amplifier (CLASSD) device at 

Re: [PATCH 1/2] ASoC: atmel-classd: add the Audio Class D Amplifier code

2015-09-03 Thread Mark Brown
On Tue, Sep 01, 2015 at 01:41:40PM +0800, Songjun Wu wrote:

> +static const char * const mono_text[] = {
> + "stereo", "mono"
> +};
> +
> +static SOC_ENUM_SINGLE_DECL(classd_mono_enum,
> + CLASSD_INTPMR, CLASSD_INTPMR_MONO_SHIFT,
> + mono_text);

This looks like it should be a simple Switch control called something
like "Stereo Switch" or "Mono Switch".

> +static const char * const deemp_text[] = {
> + "disabled", "enabled"
> +};
> +
> +static SOC_ENUM_SINGLE_DECL(classd_deemp_enum,
> + CLASSD_INTPMR, CLASSD_INTPMR_DEEMP_SHIFT,
> + deemp_text);

Similarly this looks like it should be "Deemph Switch".

> +static const char * const eqcfg_bass_text[] = {
> + "-12 dB", "-6 dB", "0 dB", "+6 dB", "+12 dB"
> +};

> +static const unsigned int eqcfg_bass_value[] = {
> + CLASSD_INTPMR_EQCFG_B_CUT_12,
> + CLASSD_INTPMR_EQCFG_B_CUT_6, CLASSD_INTPMR_EQCFG_FLAT,
> + CLASSD_INTPMR_EQCFG_B_BOOST_6, CLASSD_INTPMR_EQCFG_B_BOOST_12
> +};

This should be a Volume control with TLV information, as should the
following few controls.

> +static const struct snd_kcontrol_new atmel_classd_snd_controls[] = {
> +SOC_SINGLE_TLV("Left Volume", CLASSD_INTPMR,
> + CLASSD_INTPMR_ATTL_SHIFT, 78, 1, classd_digital_tlv),
> +
> +SOC_SINGLE_TLV("Right Volume", CLASSD_INTPMR,
> + CLASSD_INTPMR_ATTR_SHIFT, 78, 1, classd_digital_tlv),

This should be a single stereo control rather than separate left and
right controls.

> +static const char * const pwm_type[] = {
> + "single-ended", "differential"
> +};

The normal style for ALSA controls is to capitalise strings so
"Single ended" and "Differential".

> + if (pdata->non_overlap_enable) {
> + val |= (CLASSD_MR_NON_OVERLAP_EN
> + << CLASSD_MR_NON_OVERLAP_SHIFT);
> +
> + mask |= CLASSD_MR_NOVR_VAL_MASK;
> + switch (pdata->non_overlap_time) {
> + case 5:
> + val |= (CLASSD_MR_NOVR_VAL_5NS
> + << CLASSD_MR_NOVR_VAL_SHIFT);
> + break;
> + case 10:
> + val |= (CLASSD_MR_NOVR_VAL_10NS
> + << CLASSD_MR_NOVR_VAL_SHIFT);
> + break;
> + case 15:
> + val |= (CLASSD_MR_NOVR_VAL_15NS
> + << CLASSD_MR_NOVR_VAL_SHIFT);
> + break;
> + case 20:
> + val |= (CLASSD_MR_NOVR_VAL_20NS
> + << CLASSD_MR_NOVR_VAL_SHIFT);
> + break;
> + default:
> + val |= (CLASSD_MR_NOVR_VAL_10NS
> + << CLASSD_MR_NOVR_VAL_SHIFT);
> + break;
> + }

I'd expect at least a warning if the user trys to specify an invalid
value (if they didn't specify any value then I'd expect the DT parsing
function to assign the default value).

> +static struct regmap *atmel_classd_codec_get_remap(struct device *dev)
> +{
> + struct atmel_classd *dd = dev_get_drvdata(dev);
> +
> + return dd->regmap;
> +}

Can you just use dev_get_regmap()?

> +static int atmel_classd_codec_dai_startup(struct snd_pcm_substream 
> *substream,
> + struct snd_soc_dai *codec_dai)
> +{
> + struct atmel_classd *dd = snd_soc_dai_get_drvdata(codec_dai);
> +
> + clk_prepare_enable(dd->aclk);
> + clk_prepare_enable(dd->gclk);

Should check for errors here.

> + dev_info(dev,
> + "Atmel Class D Amplifier (CLASSD) device at 0x%p (irq %d)\n",
> + io_base, dd->irq);

This is a bit noisy and not really based on interaction with the
hardware...  dev_dbg() seems better.


signature.asc
Description: Digital signature


Re: [PATCH 1/2] ASoC: atmel-classd: add the Audio Class D Amplifier code

2015-09-03 Thread Mark Brown
On Tue, Sep 01, 2015 at 01:41:40PM +0800, Songjun Wu wrote:

> +static const char * const mono_text[] = {
> + "stereo", "mono"
> +};
> +
> +static SOC_ENUM_SINGLE_DECL(classd_mono_enum,
> + CLASSD_INTPMR, CLASSD_INTPMR_MONO_SHIFT,
> + mono_text);

This looks like it should be a simple Switch control called something
like "Stereo Switch" or "Mono Switch".

> +static const char * const deemp_text[] = {
> + "disabled", "enabled"
> +};
> +
> +static SOC_ENUM_SINGLE_DECL(classd_deemp_enum,
> + CLASSD_INTPMR, CLASSD_INTPMR_DEEMP_SHIFT,
> + deemp_text);

Similarly this looks like it should be "Deemph Switch".

> +static const char * const eqcfg_bass_text[] = {
> + "-12 dB", "-6 dB", "0 dB", "+6 dB", "+12 dB"
> +};

> +static const unsigned int eqcfg_bass_value[] = {
> + CLASSD_INTPMR_EQCFG_B_CUT_12,
> + CLASSD_INTPMR_EQCFG_B_CUT_6, CLASSD_INTPMR_EQCFG_FLAT,
> + CLASSD_INTPMR_EQCFG_B_BOOST_6, CLASSD_INTPMR_EQCFG_B_BOOST_12
> +};

This should be a Volume control with TLV information, as should the
following few controls.

> +static const struct snd_kcontrol_new atmel_classd_snd_controls[] = {
> +SOC_SINGLE_TLV("Left Volume", CLASSD_INTPMR,
> + CLASSD_INTPMR_ATTL_SHIFT, 78, 1, classd_digital_tlv),
> +
> +SOC_SINGLE_TLV("Right Volume", CLASSD_INTPMR,
> + CLASSD_INTPMR_ATTR_SHIFT, 78, 1, classd_digital_tlv),

This should be a single stereo control rather than separate left and
right controls.

> +static const char * const pwm_type[] = {
> + "single-ended", "differential"
> +};

The normal style for ALSA controls is to capitalise strings so
"Single ended" and "Differential".

> + if (pdata->non_overlap_enable) {
> + val |= (CLASSD_MR_NON_OVERLAP_EN
> + << CLASSD_MR_NON_OVERLAP_SHIFT);
> +
> + mask |= CLASSD_MR_NOVR_VAL_MASK;
> + switch (pdata->non_overlap_time) {
> + case 5:
> + val |= (CLASSD_MR_NOVR_VAL_5NS
> + << CLASSD_MR_NOVR_VAL_SHIFT);
> + break;
> + case 10:
> + val |= (CLASSD_MR_NOVR_VAL_10NS
> + << CLASSD_MR_NOVR_VAL_SHIFT);
> + break;
> + case 15:
> + val |= (CLASSD_MR_NOVR_VAL_15NS
> + << CLASSD_MR_NOVR_VAL_SHIFT);
> + break;
> + case 20:
> + val |= (CLASSD_MR_NOVR_VAL_20NS
> + << CLASSD_MR_NOVR_VAL_SHIFT);
> + break;
> + default:
> + val |= (CLASSD_MR_NOVR_VAL_10NS
> + << CLASSD_MR_NOVR_VAL_SHIFT);
> + break;
> + }

I'd expect at least a warning if the user trys to specify an invalid
value (if they didn't specify any value then I'd expect the DT parsing
function to assign the default value).

> +static struct regmap *atmel_classd_codec_get_remap(struct device *dev)
> +{
> + struct atmel_classd *dd = dev_get_drvdata(dev);
> +
> + return dd->regmap;
> +}

Can you just use dev_get_regmap()?

> +static int atmel_classd_codec_dai_startup(struct snd_pcm_substream 
> *substream,
> + struct snd_soc_dai *codec_dai)
> +{
> + struct atmel_classd *dd = snd_soc_dai_get_drvdata(codec_dai);
> +
> + clk_prepare_enable(dd->aclk);
> + clk_prepare_enable(dd->gclk);

Should check for errors here.

> + dev_info(dev,
> + "Atmel Class D Amplifier (CLASSD) device at 0x%p (irq %d)\n",
> + io_base, dd->irq);

This is a bit noisy and not really based on interaction with the
hardware...  dev_dbg() seems better.


signature.asc
Description: Digital signature


[PATCH 1/2] ASoC: atmel-classd: add the Audio Class D Amplifier code

2015-08-31 Thread Songjun Wu
Add driver for the digital imput to PWM output stereo
class D amplifier. It comes with filter, digitally
controlled gain, an equalizer and a dmphase filter.

Signed-off-by: Songjun Wu 
---
 sound/soc/atmel/Kconfig|9 +
 sound/soc/atmel/Makefile   |2 +
 sound/soc/atmel/atmel-classd.c |  801 
 sound/soc/atmel/atmel-classd.h |  120 ++
 4 files changed, 932 insertions(+)
 create mode 100644 sound/soc/atmel/atmel-classd.c
 create mode 100644 sound/soc/atmel/atmel-classd.h

diff --git a/sound/soc/atmel/Kconfig b/sound/soc/atmel/Kconfig
index 1489cd4..2d30464 100644
--- a/sound/soc/atmel/Kconfig
+++ b/sound/soc/atmel/Kconfig
@@ -59,4 +59,13 @@ config SND_AT91_SOC_SAM9X5_WM8731
help
  Say Y if you want to add support for audio SoC on an
  at91sam9x5 based board that is using WM8731 codec.
+
+config SND_ATMEL_SOC_CLASSD
+   tristate "Atmel ASoC driver for boards using CLASSD"
+   depends on ARCH_AT91 || COMPILE_TEST
+   select SND_ATMEL_SOC_DMA
+   select REGMAP_MMIO
+   help
+ Say Y if you want to add support for Atmel ASoC driver for boards 
using
+ CLASSD.
 endif
diff --git a/sound/soc/atmel/Makefile b/sound/soc/atmel/Makefile
index b327e5c..f6f7db4 100644
--- a/sound/soc/atmel/Makefile
+++ b/sound/soc/atmel/Makefile
@@ -11,7 +11,9 @@ obj-$(CONFIG_SND_ATMEL_SOC_SSC) += snd-soc-atmel_ssc_dai.o
 snd-soc-sam9g20-wm8731-objs := sam9g20_wm8731.o
 snd-atmel-soc-wm8904-objs := atmel_wm8904.o
 snd-soc-sam9x5-wm8731-objs := sam9x5_wm8731.o
+snd-atmel-soc-classd-objs := atmel-classd.o
 
 obj-$(CONFIG_SND_AT91_SOC_SAM9G20_WM8731) += snd-soc-sam9g20-wm8731.o
 obj-$(CONFIG_SND_ATMEL_SOC_WM8904) += snd-atmel-soc-wm8904.o
 obj-$(CONFIG_SND_AT91_SOC_SAM9X5_WM8731) += snd-soc-sam9x5-wm8731.o
+obj-$(CONFIG_SND_ATMEL_SOC_CLASSD) += snd-atmel-soc-classd.o
diff --git a/sound/soc/atmel/atmel-classd.c b/sound/soc/atmel/atmel-classd.c
new file mode 100644
index 000..5ceefa9
--- /dev/null
+++ b/sound/soc/atmel/atmel-classd.c
@@ -0,0 +1,801 @@
+/* Atmel ALSA SoC Audio Class D Amplifier (CLASSD) driver
+ *
+ * Copyright (C) 2015 Atmel
+ *
+ * Author: Songjun Wu 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 or later
+ * as published by the Free Software Foundation.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "atmel-classd.h"
+
+struct atmel_classd_pdata {
+   bool non_overlap_enable;
+   int non_overlap_time;
+   int pwm_type;
+};
+
+struct atmel_classd {
+   dma_addr_t phy_base;
+   struct regmap *regmap;
+   struct clk *pclk;
+   struct clk *gclk;
+   struct clk *aclk;
+   int irq;
+   const struct atmel_classd_pdata *pdata;
+};
+
+#ifdef CONFIG_OF
+static const struct of_device_id atmel_classd_of_match[] = {
+   {
+   .compatible = "atmel,sama5d2-classd",
+   }, {
+   /* sentinel */
+   }
+};
+MODULE_DEVICE_TABLE(of, atmel_classd_of_match);
+
+static struct atmel_classd_pdata *atmel_classd_dt_init(struct device *dev)
+{
+   struct device_node *np = dev->of_node;
+   struct atmel_classd_pdata *pdata;
+   const char *pwm_type;
+   int ret;
+
+   if (!np) {
+   dev_err(dev, "device node not found\n");
+   return ERR_PTR(-EINVAL);
+   }
+
+   pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+   if (!pdata)
+   return ERR_PTR(-ENOMEM);
+
+   ret = of_property_read_string(np, "atmel,pwm-type", _type);
+   if ((ret == 0) && (strcmp(pwm_type, "diff") == 0))
+   pdata->pwm_type = CLASSD_MR_PWMTYP_DIFF;
+   else
+   pdata->pwm_type = CLASSD_MR_PWMTYP_SINGLE;
+
+   ret = of_property_read_u32(np,
+   "atmel,non-overlap-time", >non_overlap_time);
+   if (ret != 0)
+   pdata->non_overlap_enable = false;
+   else
+   pdata->non_overlap_enable = true;
+
+   return pdata;
+}
+#else
+static inline struct atmel_classd_pdata *
+atmel_classd_dt_init(struct device *dev)
+{
+   return ERR_PTR(-EINVAL);
+}
+#endif
+
+#define ATMEL_CLASSD_RATES (SNDRV_PCM_RATE_8000 \
+   | SNDRV_PCM_RATE_16000  | SNDRV_PCM_RATE_22050 \
+   | SNDRV_PCM_RATE_32000  | SNDRV_PCM_RATE_44100 \
+   | SNDRV_PCM_RATE_48000  | SNDRV_PCM_RATE_88200 \
+   | SNDRV_PCM_RATE_96000)
+
+static const struct snd_pcm_hardware atmel_classd_hw = {
+   .info   = SNDRV_PCM_INFO_MMAP
+   | SNDRV_PCM_INFO_MMAP_VALID
+   | SNDRV_PCM_INFO_INTERLEAVED
+   | SNDRV_PCM_INFO_RESUME
+   | SNDRV_PCM_INFO_PAUSE,
+   .formats= 

[PATCH 1/2] ASoC: atmel-classd: add the Audio Class D Amplifier code

2015-08-31 Thread Songjun Wu
Add driver for the digital imput to PWM output stereo
class D amplifier. It comes with filter, digitally
controlled gain, an equalizer and a dmphase filter.

Signed-off-by: Songjun Wu 
---
 sound/soc/atmel/Kconfig|9 +
 sound/soc/atmel/Makefile   |2 +
 sound/soc/atmel/atmel-classd.c |  801 
 sound/soc/atmel/atmel-classd.h |  120 ++
 4 files changed, 932 insertions(+)
 create mode 100644 sound/soc/atmel/atmel-classd.c
 create mode 100644 sound/soc/atmel/atmel-classd.h

diff --git a/sound/soc/atmel/Kconfig b/sound/soc/atmel/Kconfig
index 1489cd4..2d30464 100644
--- a/sound/soc/atmel/Kconfig
+++ b/sound/soc/atmel/Kconfig
@@ -59,4 +59,13 @@ config SND_AT91_SOC_SAM9X5_WM8731
help
  Say Y if you want to add support for audio SoC on an
  at91sam9x5 based board that is using WM8731 codec.
+
+config SND_ATMEL_SOC_CLASSD
+   tristate "Atmel ASoC driver for boards using CLASSD"
+   depends on ARCH_AT91 || COMPILE_TEST
+   select SND_ATMEL_SOC_DMA
+   select REGMAP_MMIO
+   help
+ Say Y if you want to add support for Atmel ASoC driver for boards 
using
+ CLASSD.
 endif
diff --git a/sound/soc/atmel/Makefile b/sound/soc/atmel/Makefile
index b327e5c..f6f7db4 100644
--- a/sound/soc/atmel/Makefile
+++ b/sound/soc/atmel/Makefile
@@ -11,7 +11,9 @@ obj-$(CONFIG_SND_ATMEL_SOC_SSC) += snd-soc-atmel_ssc_dai.o
 snd-soc-sam9g20-wm8731-objs := sam9g20_wm8731.o
 snd-atmel-soc-wm8904-objs := atmel_wm8904.o
 snd-soc-sam9x5-wm8731-objs := sam9x5_wm8731.o
+snd-atmel-soc-classd-objs := atmel-classd.o
 
 obj-$(CONFIG_SND_AT91_SOC_SAM9G20_WM8731) += snd-soc-sam9g20-wm8731.o
 obj-$(CONFIG_SND_ATMEL_SOC_WM8904) += snd-atmel-soc-wm8904.o
 obj-$(CONFIG_SND_AT91_SOC_SAM9X5_WM8731) += snd-soc-sam9x5-wm8731.o
+obj-$(CONFIG_SND_ATMEL_SOC_CLASSD) += snd-atmel-soc-classd.o
diff --git a/sound/soc/atmel/atmel-classd.c b/sound/soc/atmel/atmel-classd.c
new file mode 100644
index 000..5ceefa9
--- /dev/null
+++ b/sound/soc/atmel/atmel-classd.c
@@ -0,0 +1,801 @@
+/* Atmel ALSA SoC Audio Class D Amplifier (CLASSD) driver
+ *
+ * Copyright (C) 2015 Atmel
+ *
+ * Author: Songjun Wu 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 or later
+ * as published by the Free Software Foundation.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "atmel-classd.h"
+
+struct atmel_classd_pdata {
+   bool non_overlap_enable;
+   int non_overlap_time;
+   int pwm_type;
+};
+
+struct atmel_classd {
+   dma_addr_t phy_base;
+   struct regmap *regmap;
+   struct clk *pclk;
+   struct clk *gclk;
+   struct clk *aclk;
+   int irq;
+   const struct atmel_classd_pdata *pdata;
+};
+
+#ifdef CONFIG_OF
+static const struct of_device_id atmel_classd_of_match[] = {
+   {
+   .compatible = "atmel,sama5d2-classd",
+   }, {
+   /* sentinel */
+   }
+};
+MODULE_DEVICE_TABLE(of, atmel_classd_of_match);
+
+static struct atmel_classd_pdata *atmel_classd_dt_init(struct device *dev)
+{
+   struct device_node *np = dev->of_node;
+   struct atmel_classd_pdata *pdata;
+   const char *pwm_type;
+   int ret;
+
+   if (!np) {
+   dev_err(dev, "device node not found\n");
+   return ERR_PTR(-EINVAL);
+   }
+
+   pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+   if (!pdata)
+   return ERR_PTR(-ENOMEM);
+
+   ret = of_property_read_string(np, "atmel,pwm-type", _type);
+   if ((ret == 0) && (strcmp(pwm_type, "diff") == 0))
+   pdata->pwm_type = CLASSD_MR_PWMTYP_DIFF;
+   else
+   pdata->pwm_type = CLASSD_MR_PWMTYP_SINGLE;
+
+   ret = of_property_read_u32(np,
+   "atmel,non-overlap-time", >non_overlap_time);
+   if (ret != 0)
+   pdata->non_overlap_enable = false;
+   else
+   pdata->non_overlap_enable = true;
+
+   return pdata;
+}
+#else
+static inline struct atmel_classd_pdata *
+atmel_classd_dt_init(struct device *dev)
+{
+   return ERR_PTR(-EINVAL);
+}
+#endif
+
+#define ATMEL_CLASSD_RATES (SNDRV_PCM_RATE_8000 \
+   | SNDRV_PCM_RATE_16000  | SNDRV_PCM_RATE_22050 \
+   | SNDRV_PCM_RATE_32000  | SNDRV_PCM_RATE_44100 \
+   | SNDRV_PCM_RATE_48000  | SNDRV_PCM_RATE_88200 \
+   | SNDRV_PCM_RATE_96000)
+
+static const struct snd_pcm_hardware atmel_classd_hw = {
+   .info   = SNDRV_PCM_INFO_MMAP
+   | SNDRV_PCM_INFO_MMAP_VALID
+   | SNDRV_PCM_INFO_INTERLEAVED
+   | SNDRV_PCM_INFO_RESUME
+   | SNDRV_PCM_INFO_PAUSE,
+