Re: [PATCH] ASoC: dapm: Add support for multi register mux
On Fri, Apr 04, 2014 at 05:12:10PM -0700, Arun Shamanna Lakshmi wrote: > 1. Modify soc_enum struct to handle pointers for reg and mask > 2. Add dapm get and put APIs for multi register one hot encoded mux > 3. Update snd_soc_dapm_update struct to support multiple reg update > If you've got several changes like this it's probably a sign that the > change ought to be split into a patch series. > I'm still not seeing any handling of the issues with having invalid > configurations written to the device during the process of carrying out > multi register updates; I did raise this with one of the earlier > versions but don't recall any response. To handle the invalid configurations in case of a multi register update, the 'not selected registers' are cleared first and only then 'selected register' is set. This is ensured by initializing the snd_soc_dapm_update structure in the right order inside put_value_enum_onehot API. > I also think I agree with Takashi on this one - trying to implement this > without adding an abstraction for the control values is making the code > more complex than it needs to be, all the conditional paths for _ONEHOT > aren't pretty (and don't use switches which is the usual idiom for this > stuff if it's not indirected via functions). To summarize, I need to add get and put function pointers inside kcontrol structure and use them during dapm_connect_mux and dapm_set_mixer_path_status. Then, a separate soc_enum_onehot structure can be used along with the above patch. I can probably first submit a patch for adding abstraction to control values and then submit the change for soc_enum_onehot. Please correct me if my understanding is wrong. -- View this message in context: http://linux-kernel.2935.n7.nabble.com/PATCH-ASoC-dapm-Add-support-for-multi-register-mux-tp835209p837198.html Sent from the Linux Kernel mailing list archive at Nabble.com. -- 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] ASoC: dapm: Add support for multi register mux
On Fri, Apr 04, 2014 at 05:12:10PM -0700, Arun Shamanna Lakshmi wrote: > 1. Modify soc_enum struct to handle pointers for reg and mask > 2. Add dapm get and put APIs for multi register one hot encoded mux > 3. Update snd_soc_dapm_update struct to support multiple reg update If you've got several changes like this it's probably a sign that the change ought to be split into a patch series. I'm still not seeing any handling of the issues with having invalid configurations written to the device during the process of carrying out multi register updates; I did raise this with one of the earlier versions but don't recall any response. I also think I agree with Takashi on this one - trying to implement this without adding an abstraction for the control values is making the code more complex than it needs to be, all the conditional paths for _ONEHOT aren't pretty (and don't use switches which is the usual idiom for this stuff if it's not indirected via functions). signature.asc Description: Digital signature
Re: [PATCH] ASoC: dapm: Add support for multi register mux
On Fri, Apr 04, 2014 at 05:12:10PM -0700, Arun Shamanna Lakshmi wrote: 1. Modify soc_enum struct to handle pointers for reg and mask 2. Add dapm get and put APIs for multi register one hot encoded mux 3. Update snd_soc_dapm_update struct to support multiple reg update If you've got several changes like this it's probably a sign that the change ought to be split into a patch series. I'm still not seeing any handling of the issues with having invalid configurations written to the device during the process of carrying out multi register updates; I did raise this with one of the earlier versions but don't recall any response. I also think I agree with Takashi on this one - trying to implement this without adding an abstraction for the control values is making the code more complex than it needs to be, all the conditional paths for _ONEHOT aren't pretty (and don't use switches which is the usual idiom for this stuff if it's not indirected via functions). signature.asc Description: Digital signature
Re: [PATCH] ASoC: dapm: Add support for multi register mux
On Fri, Apr 04, 2014 at 05:12:10PM -0700, Arun Shamanna Lakshmi wrote: 1. Modify soc_enum struct to handle pointers for reg and mask 2. Add dapm get and put APIs for multi register one hot encoded mux 3. Update snd_soc_dapm_update struct to support multiple reg update If you've got several changes like this it's probably a sign that the change ought to be split into a patch series. I'm still not seeing any handling of the issues with having invalid configurations written to the device during the process of carrying out multi register updates; I did raise this with one of the earlier versions but don't recall any response. To handle the invalid configurations in case of a multi register update, the 'not selected registers' are cleared first and only then 'selected register' is set. This is ensured by initializing the snd_soc_dapm_update structure in the right order inside put_value_enum_onehot API. I also think I agree with Takashi on this one - trying to implement this without adding an abstraction for the control values is making the code more complex than it needs to be, all the conditional paths for _ONEHOT aren't pretty (and don't use switches which is the usual idiom for this stuff if it's not indirected via functions). To summarize, I need to add get and put function pointers inside kcontrol structure and use them during dapm_connect_mux and dapm_set_mixer_path_status. Then, a separate soc_enum_onehot structure can be used along with the above patch. I can probably first submit a patch for adding abstraction to control values and then submit the change for soc_enum_onehot. Please correct me if my understanding is wrong. -- View this message in context: http://linux-kernel.2935.n7.nabble.com/PATCH-ASoC-dapm-Add-support-for-multi-register-mux-tp835209p837198.html Sent from the Linux Kernel mailing list archive at Nabble.com. -- 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] ASoC: dapm: Add support for multi register mux
At Mon, 07 Apr 2014 14:54:11 +0200, Lars-Peter Clausen wrote: > > On 04/05/2014 02:12 AM, Arun Shamanna Lakshmi wrote: > > 1. Modify soc_enum struct to handle pointers for reg and mask > > 2. Add dapm get and put APIs for multi register one hot encoded mux > > 3. Update snd_soc_dapm_update struct to support multiple reg update > > > > Signed-off-by: Arun S L > > Signed-off-by: Songhee Baek > > Looks good to me, so: > > Reviewed-by: Lars-Peter Clausen > > > As Takashi said it is not that nice that there is a bit of code churn by > having to update all the existing users of e->reg and e->mask. But > implementing this properly seems to cause even more code churn. Well, I'm not sure about it. It's already too late for 3.15, so we have some time to enhance for this feature properly. I personally like a hackish solution, too, but only if it really gives a clear benefit over the generic solution. In this case, it changes the data type and yet increases the data size significantly, which isn't a good sign. (Note that replacing int with pointer can be twice on 64bit, and there will be pads for alignment, in addition to the extra space for number instances by this implementation.) Also, as the data handling is branched per type, a more readable implementation would be to impose a union between normal and onehot types in soc_enum struct, I guess. But, then a question comes to the point whether we really want such a unification at all. Last but not least, another concern is that there can be multiple onehot types: with 0 or without 0 handling. It'd be easy to add the implementation, but it indicates that the implementation isn't generic enough in comparison with the existing snd_soc code for single register. > And I think > it will be done best in an effort to consolidate the kcontrol helpers and > the DAPM kcontrol helpers by adding an additional layer of abstraction > between the kcontrols and the hardware access that translates between the > logical value and the physical value(s). > > E.g. something like > > struct kcontrol_ops { > int (*read)(...); > int (*write)(...); > }; > > And then have one kind of ops for each kind of control type and at the high > level only have put and get handlers for enums and for switches/volumes. This might work well, indeed. But, let the actual code talk :) thanks, Takashi -- 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] ASoC: dapm: Add support for multi register mux
On 04/05/2014 02:12 AM, Arun Shamanna Lakshmi wrote: 1. Modify soc_enum struct to handle pointers for reg and mask 2. Add dapm get and put APIs for multi register one hot encoded mux 3. Update snd_soc_dapm_update struct to support multiple reg update Signed-off-by: Arun S L Signed-off-by: Songhee Baek Looks good to me, so: Reviewed-by: Lars-Peter Clausen As Takashi said it is not that nice that there is a bit of code churn by having to update all the existing users of e->reg and e->mask. But implementing this properly seems to cause even more code churn. And I think it will be done best in an effort to consolidate the kcontrol helpers and the DAPM kcontrol helpers by adding an additional layer of abstraction between the kcontrols and the hardware access that translates between the logical value and the physical value(s). E.g. something like struct kcontrol_ops { int (*read)(...); int (*write)(...); }; And then have one kind of ops for each kind of control type and at the high level only have put and get handlers for enums and for switches/volumes. - Lars -- 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] ASoC: dapm: Add support for multi register mux
On 04/05/2014 02:12 AM, Arun Shamanna Lakshmi wrote: 1. Modify soc_enum struct to handle pointers for reg and mask 2. Add dapm get and put APIs for multi register one hot encoded mux 3. Update snd_soc_dapm_update struct to support multiple reg update Signed-off-by: Arun S L ar...@nvidia.com Signed-off-by: Songhee Baek sb...@nvidia.com Looks good to me, so: Reviewed-by: Lars-Peter Clausen l...@metafoo.de As Takashi said it is not that nice that there is a bit of code churn by having to update all the existing users of e-reg and e-mask. But implementing this properly seems to cause even more code churn. And I think it will be done best in an effort to consolidate the kcontrol helpers and the DAPM kcontrol helpers by adding an additional layer of abstraction between the kcontrols and the hardware access that translates between the logical value and the physical value(s). E.g. something like struct kcontrol_ops { int (*read)(...); int (*write)(...); }; And then have one kind of ops for each kind of control type and at the high level only have put and get handlers for enums and for switches/volumes. - Lars -- 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] ASoC: dapm: Add support for multi register mux
At Mon, 07 Apr 2014 14:54:11 +0200, Lars-Peter Clausen wrote: On 04/05/2014 02:12 AM, Arun Shamanna Lakshmi wrote: 1. Modify soc_enum struct to handle pointers for reg and mask 2. Add dapm get and put APIs for multi register one hot encoded mux 3. Update snd_soc_dapm_update struct to support multiple reg update Signed-off-by: Arun S L ar...@nvidia.com Signed-off-by: Songhee Baek sb...@nvidia.com Looks good to me, so: Reviewed-by: Lars-Peter Clausen l...@metafoo.de As Takashi said it is not that nice that there is a bit of code churn by having to update all the existing users of e-reg and e-mask. But implementing this properly seems to cause even more code churn. Well, I'm not sure about it. It's already too late for 3.15, so we have some time to enhance for this feature properly. I personally like a hackish solution, too, but only if it really gives a clear benefit over the generic solution. In this case, it changes the data type and yet increases the data size significantly, which isn't a good sign. (Note that replacing int with pointer can be twice on 64bit, and there will be pads for alignment, in addition to the extra space for number instances by this implementation.) Also, as the data handling is branched per type, a more readable implementation would be to impose a union between normal and onehot types in soc_enum struct, I guess. But, then a question comes to the point whether we really want such a unification at all. Last but not least, another concern is that there can be multiple onehot types: with 0 or without 0 handling. It'd be easy to add the implementation, but it indicates that the implementation isn't generic enough in comparison with the existing snd_soc code for single register. And I think it will be done best in an effort to consolidate the kcontrol helpers and the DAPM kcontrol helpers by adding an additional layer of abstraction between the kcontrols and the hardware access that translates between the logical value and the physical value(s). E.g. something like struct kcontrol_ops { int (*read)(...); int (*write)(...); }; And then have one kind of ops for each kind of control type and at the high level only have put and get handlers for enums and for switches/volumes. This might work well, indeed. But, let the actual code talk :) thanks, Takashi -- 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] ASoC: dapm: Add support for multi register mux
On 04/04/2014 09:34 AM, Arun Shamanna Lakshmi wrote: -Original Message- From: Lars-Peter Clausen [mailto:l...@metafoo.de] Sent: Friday, April 04, 2014 12:32 AM To: Arun Shamanna Lakshmi Cc: lgirdw...@gmail.com; broo...@kernel.org; swar...@wwwdotorg.org; pe...@perex.cz; ti...@suse.de; alsa- de...@alsa-project.org; linux-kernel@vger.kernel.org; Songhee Baek Subject: Re: [PATCH] ASoC: dapm: Add support for multi register mux On 04/03/2014 10:11 PM, Arun Shamanna Lakshmi wrote: [...] Here as well, default for bit_pos should be 0. This means when 'None' of the options are selected, by default, it enumerates to 0. Since we are using __ffs, BIT(0) of Register-0 also enumerates to 0. That's the reason why I used just ffs in the first place. Let me know your opinion. My value table looks like below. #define MUX_VALUE(npart, nbit) (nbit + 32 * npart) static const int mux_values[] = { 0, MUX_VALUE(0, 0), . . . MUX_VALUE(0, 31), /* above inputs are for part0 mux */ MUX_VALUE(1, 0), . . . MUX_VALUE(1, 31), /* above inputs are for part1 mux */ MUX_VALUE(2, 0), . . . MUX_VALUE(2, 31), /* above inputs are for part2 mux */ }; Ok, so having none of the input selected should be a valid user selectable option? Yes. If 'None' is selected, it goes and clears the register. So, can we have ffs( ) instead of __ffs( ) ? It would fix this case. Yes, but you need to make sure to handle it also correctly in the put handler, since all of the registers need to be written to 0 in that case. -- 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] ASoC: dapm: Add support for multi register mux
> -Original Message- > From: Lars-Peter Clausen [mailto:l...@metafoo.de] > Sent: Friday, April 04, 2014 12:32 AM > To: Arun Shamanna Lakshmi > Cc: lgirdw...@gmail.com; broo...@kernel.org; > swar...@wwwdotorg.org; pe...@perex.cz; ti...@suse.de; alsa- > de...@alsa-project.org; linux-kernel@vger.kernel.org; Songhee Baek > Subject: Re: [PATCH] ASoC: dapm: Add support for multi register mux > > On 04/03/2014 10:11 PM, Arun Shamanna Lakshmi wrote: > [...] > >> Here as well, default for bit_pos should be 0. > > > > This means when 'None' of the options are selected, by default, it > > enumerates to 0. Since we are using __ffs, BIT(0) of Register-0 also > > enumerates to 0. That's the reason why I used just ffs in the first place. > > Let me know your opinion. My value table looks like below. > > > > #define MUX_VALUE(npart, nbit) (nbit + 32 * npart) > > static const int mux_values[] = { > > 0, > > MUX_VALUE(0, 0), > > . > > . > > . > > MUX_VALUE(0, 31), > > /* above inputs are for part0 mux */ > > MUX_VALUE(1, 0), > > . > > . > > . > > MUX_VALUE(1, 31), > > /* above inputs are for part1 mux */ > > MUX_VALUE(2, 0), > > . > > . > > . > > MUX_VALUE(2, 31), > > /* above inputs are for part2 mux */ > > }; > > Ok, so having none of the input selected should be a valid user selectable > option? Yes. If 'None' is selected, it goes and clears the register. So, can we have ffs( ) instead of __ffs( ) ? It would fix this case. - Arun -- 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] ASoC: dapm: Add support for multi register mux
On 04/03/2014 10:11 PM, Arun Shamanna Lakshmi wrote: [...] Here as well, default for bit_pos should be 0. This means when 'None' of the options are selected, by default, it enumerates to 0. Since we are using __ffs, BIT(0) of Register-0 also enumerates to 0. That's the reason why I used just ffs in the first place. Let me know your opinion. My value table looks like below. #define MUX_VALUE(npart, nbit) (nbit + 32 * npart) static const int mux_values[] = { 0, MUX_VALUE(0, 0), . . . MUX_VALUE(0, 31), /* above inputs are for part0 mux */ MUX_VALUE(1, 0), . . . MUX_VALUE(1, 31), /* above inputs are for part1 mux */ MUX_VALUE(2, 0), . . . MUX_VALUE(2, 31), /* above inputs are for part2 mux */ }; Ok, so having none of the input selected should be a valid user selectable option? -- 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] ASoC: dapm: Add support for multi register mux
On 04/03/2014 10:11 PM, Arun Shamanna Lakshmi wrote: [...] Here as well, default for bit_pos should be 0. This means when 'None' of the options are selected, by default, it enumerates to 0. Since we are using __ffs, BIT(0) of Register-0 also enumerates to 0. That's the reason why I used just ffs in the first place. Let me know your opinion. My value table looks like below. #define MUX_VALUE(npart, nbit) (nbit + 32 * npart) static const int mux_values[] = { 0, MUX_VALUE(0, 0), . . . MUX_VALUE(0, 31), /* above inputs are for part0 mux */ MUX_VALUE(1, 0), . . . MUX_VALUE(1, 31), /* above inputs are for part1 mux */ MUX_VALUE(2, 0), . . . MUX_VALUE(2, 31), /* above inputs are for part2 mux */ }; Ok, so having none of the input selected should be a valid user selectable option? -- 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] ASoC: dapm: Add support for multi register mux
-Original Message- From: Lars-Peter Clausen [mailto:l...@metafoo.de] Sent: Friday, April 04, 2014 12:32 AM To: Arun Shamanna Lakshmi Cc: lgirdw...@gmail.com; broo...@kernel.org; swar...@wwwdotorg.org; pe...@perex.cz; ti...@suse.de; alsa- de...@alsa-project.org; linux-kernel@vger.kernel.org; Songhee Baek Subject: Re: [PATCH] ASoC: dapm: Add support for multi register mux On 04/03/2014 10:11 PM, Arun Shamanna Lakshmi wrote: [...] Here as well, default for bit_pos should be 0. This means when 'None' of the options are selected, by default, it enumerates to 0. Since we are using __ffs, BIT(0) of Register-0 also enumerates to 0. That's the reason why I used just ffs in the first place. Let me know your opinion. My value table looks like below. #define MUX_VALUE(npart, nbit) (nbit + 32 * npart) static const int mux_values[] = { 0, MUX_VALUE(0, 0), . . . MUX_VALUE(0, 31), /* above inputs are for part0 mux */ MUX_VALUE(1, 0), . . . MUX_VALUE(1, 31), /* above inputs are for part1 mux */ MUX_VALUE(2, 0), . . . MUX_VALUE(2, 31), /* above inputs are for part2 mux */ }; Ok, so having none of the input selected should be a valid user selectable option? Yes. If 'None' is selected, it goes and clears the register. So, can we have ffs( ) instead of __ffs( ) ? It would fix this case. - Arun -- 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] ASoC: dapm: Add support for multi register mux
On 04/04/2014 09:34 AM, Arun Shamanna Lakshmi wrote: -Original Message- From: Lars-Peter Clausen [mailto:l...@metafoo.de] Sent: Friday, April 04, 2014 12:32 AM To: Arun Shamanna Lakshmi Cc: lgirdw...@gmail.com; broo...@kernel.org; swar...@wwwdotorg.org; pe...@perex.cz; ti...@suse.de; alsa- de...@alsa-project.org; linux-kernel@vger.kernel.org; Songhee Baek Subject: Re: [PATCH] ASoC: dapm: Add support for multi register mux On 04/03/2014 10:11 PM, Arun Shamanna Lakshmi wrote: [...] Here as well, default for bit_pos should be 0. This means when 'None' of the options are selected, by default, it enumerates to 0. Since we are using __ffs, BIT(0) of Register-0 also enumerates to 0. That's the reason why I used just ffs in the first place. Let me know your opinion. My value table looks like below. #define MUX_VALUE(npart, nbit) (nbit + 32 * npart) static const int mux_values[] = { 0, MUX_VALUE(0, 0), . . . MUX_VALUE(0, 31), /* above inputs are for part0 mux */ MUX_VALUE(1, 0), . . . MUX_VALUE(1, 31), /* above inputs are for part1 mux */ MUX_VALUE(2, 0), . . . MUX_VALUE(2, 31), /* above inputs are for part2 mux */ }; Ok, so having none of the input selected should be a valid user selectable option? Yes. If 'None' is selected, it goes and clears the register. So, can we have ffs( ) instead of __ffs( ) ? It would fix this case. Yes, but you need to make sure to handle it also correctly in the put handler, since all of the registers need to be written to 0 in that case. -- 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] ASoC: dapm: Add support for multi register mux
> -Original Message- > From: Lars-Peter Clausen [mailto:l...@metafoo.de] > Sent: Thursday, April 03, 2014 1:27 AM > To: Arun Shamanna Lakshmi > Cc: lgirdw...@gmail.com; broo...@kernel.org; swar...@wwwdotorg.org; > pe...@perex.cz; ti...@suse.de; alsa- de...@alsa-project.org; > linux-kernel@vger.kernel.org; Songhee Baek > Subject: Re: [PATCH] ASoC: dapm: Add support for multi register mux > > On 04/03/2014 05:11 AM, Arun Shamanna Lakshmi wrote: > > This looks essentially good to me. A few minor issues, once those are > fixed things should be good to go. > > [...] > > @@ -2984,6 +3002,112 @@ int > snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, > > EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double); > > > > /** > > + * snd_soc_dapm_get_enum_onehot - dapm enumerated onehot > mixer get > > +callback > > + * @kcontrol: mixer control > > + * @ucontrol: control element information > > + * > > + * Callback to get the value of a dapm enumerated onehot encoded > > +mixer control > > + * > > + * Returns 0 for success. > > + */ > > +int snd_soc_dapm_get_enum_onehot(struct snd_kcontrol *kcontrol, > > + struct snd_ctl_elem_value *ucontrol) { > > + struct snd_soc_codec *codec = > snd_soc_dapm_kcontrol_codec(kcontrol); > > + struct soc_enum *e = (struct soc_enum *)kcontrol- > >private_value; > > + unsigned int reg_val, val, bit_pos = -1, reg_idx; > > Here as well, default for bit_pos should be 0. This means when 'None' of the options are selected, by default, it enumerates to 0. Since we are using __ffs, BIT(0) of Register-0 also enumerates to 0. That's the reason why I used just ffs in the first place. Let me know your opinion. My value table looks like below. #define MUX_VALUE(npart, nbit) (nbit + 32 * npart) static const int mux_values[] = { 0, MUX_VALUE(0, 0), . . . MUX_VALUE(0, 31), /* above inputs are for part0 mux */ MUX_VALUE(1, 0), . . . MUX_VALUE(1, 31), /* above inputs are for part1 mux */ MUX_VALUE(2, 0), . . . MUX_VALUE(2, 31), /* above inputs are for part2 mux */ }; > > > + > > + for (reg_idx = 0; reg_idx < e->num_regs; reg_idx++) { > > + reg_val = snd_soc_read(codec, e->reg[reg_idx]); > > + val = reg_val & e->mask[reg_idx]; > > + if (val != 0) { > > + bit_pos = __ffs(val) + (8 * codec->val_bytes * > reg_idx); > > + break; > > + } > > + } > > + > > + ucontrol->value.enumerated.item[0] = > > + snd_soc_enum_val_to_item(e, bit_pos); > > + > > + return 0; > > +} > > +EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_onehot); > > + > > +/** > > + -- 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] ASoC: dapm: Add support for multi register mux
On Thu, Apr 03, 2014 at 05:06:28PM +0200, Takashi Iwai wrote: > Lars-Peter Clausen wrote: > > It would be nice, but it also requires some slight restructuring. The issue > > we have right now is that there is strictly speaking a bit of a layering > > violation. The DAPM widgets should not need to know how the kcontrols that > > are attached to the widget do their IO. What we essentially do in > > dapm_connect_mux() (and also dapm_connect_mixer) is an open-coded version > > of > > the controls get handler. Replacing that by calling the get handler instead > > should allow us to use different structs for enums and onehot enums. Right, that's because DAPM has always just reimplemented everything and the virtual controls were grafted on the side of the existing register stuff rather than adding an abstraction layer. > So, something like below? It's totally untested, just a proof of > concept. Yes, that looks sensible to me but I didn't test it yet either. > If the performance matters, we can optimize it by checking > kcontrol->get == snd_soc_dapm_get_enum_double or kcontrol->get == > snd_soc_dapm_get_volsw and bypass to the current open-code functions > instead of the generic get/put callers. Performance isn't that big a deal, probably avoiding the alloc/frees by just keeping one around somewhere convenient would be useful too. signature.asc Description: Digital signature
Re: [PATCH] ASoC: dapm: Add support for multi register mux
At Thu, 03 Apr 2014 15:31:58 +0200, Lars-Peter Clausen wrote: > > On 04/03/2014 11:53 AM, Mark Brown wrote: > > On Thu, Apr 03, 2014 at 11:47:15AM +0200, Takashi Iwai wrote: > > > >> I'm a bit late in the game, but I feel a bit uneasy through looking > >> at the whole changes. My primary question is, whether do we really > >> need to share the same struct soc_enum for the onehot type? What > >> makes hard to use a struct soc_enum_onehot for them? You need > >> different individual get/put for each type. We may still need to > >> change soc_dapm_update stuff, but it's different from sharing > >> soc_enum. > > > > Indeed, I had thought this was where the discussion was heading - not > > looked at this version of the patch yet. > > > > It would be nice, but it also requires some slight restructuring. The issue > we have right now is that there is strictly speaking a bit of a layering > violation. The DAPM widgets should not need to know how the kcontrols that > are attached to the widget do their IO. What we essentially do in > dapm_connect_mux() (and also dapm_connect_mixer) is an open-coded version of > the controls get handler. Replacing that by calling the get handler instead > should allow us to use different structs for enums and onehot enums. So, something like below? It's totally untested, just a proof of concept. If the performance matters, we can optimize it by checking kcontrol->get == snd_soc_dapm_get_enum_double or kcontrol->get == snd_soc_dapm_get_volsw and bypass to the current open-code functions instead of the generic get/put callers. thanks, Takashi --- diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index c8a780d0d057..5947c6e2fcc8 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -508,64 +508,71 @@ out: static int dapm_connect_mux(struct snd_soc_dapm_context *dapm, struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest, struct snd_soc_dapm_path *path, const char *control_name, - const struct snd_kcontrol_new *kcontrol) + struct snd_kcontrol *kcontrol) { - struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int val, item; - int i; + struct snd_ctl_elem_info *uinfo; + struct snd_ctl_elem_value *ucontrol; + unsigned int i, item, items; + int err; - if (e->reg != SND_SOC_NOPM) { - soc_widget_read(dest, e->reg, ); - val = (val >> e->shift_l) & e->mask; - item = snd_soc_enum_val_to_item(e, val); - } else { - /* since a virtual mux has no backing registers to -* decide which path to connect, it will try to match -* with the first enumeration. This is to ensure -* that the default mux choice (the first) will be -* correctly powered up during initialization. -*/ - item = 0; + uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL); + ucontrol = kzalloc(sizeof(*ucontrol), GFP_KERNEL); + if (!uinfo || !ucontrol) { + err = -ENOMEM; + goto out; + } + + err = kcontrol->info(kcontrol, uinfo); + if (err < 0) + goto out; + if (WARN_ON(uinfo->type != SNDRV_CTL_ELEM_TYPE_ENUMERATED)) { + err = -EINVAL; + goto out; } + items = uinfo->value.enumerated.items; - for (i = 0; i < e->items; i++) { - if (!(strcmp(control_name, e->texts[i]))) { + err = kcontrol->get(kcontrol, ucontrol); + if (err < 0) + goto out; + item = ucontrol->value.enumerated.item[0]; + + for (i = 0; i < items; i++) { + uinfo->value.enumerated.item = i; + err = kcontrol->info(kcontrol, uinfo); + if (err < 0) + goto out; + if (!(strcmp(control_name, uinfo->value.enumerated.name))) { list_add(>list, >card->paths); list_add(>list_sink, >sources); list_add(>list_source, >sinks); - path->name = (char*)e->texts[i]; + path->name = control_name; if (i == item) path->connect = 1; else path->connect = 0; - return 0; + goto out; } } - return -ENODEV; + err = -ENODEV; + out: + kfree(ucontrol); + kfree(uinfo); + return err < 0 ? err : 0; } /* set up initial codec paths */ static void dapm_set_mixer_path_status(struct snd_soc_dapm_widget *w, struct snd_soc_dapm_path *p, int i) { - struct soc_mixer_control *mc = (struct soc_mixer_control *) - w->kcontrol_news[i].private_value; - unsigned int reg = mc->reg; - unsigned int shift =
Re: [PATCH] ASoC: dapm: Add support for multi register mux
On 04/03/2014 11:53 AM, Mark Brown wrote: On Thu, Apr 03, 2014 at 11:47:15AM +0200, Takashi Iwai wrote: I'm a bit late in the game, but I feel a bit uneasy through looking at the whole changes. My primary question is, whether do we really need to share the same struct soc_enum for the onehot type? What makes hard to use a struct soc_enum_onehot for them? You need different individual get/put for each type. We may still need to change soc_dapm_update stuff, but it's different from sharing soc_enum. Indeed, I had thought this was where the discussion was heading - not looked at this version of the patch yet. It would be nice, but it also requires some slight restructuring. The issue we have right now is that there is strictly speaking a bit of a layering violation. The DAPM widgets should not need to know how the kcontrols that are attached to the widget do their IO. What we essentially do in dapm_connect_mux() (and also dapm_connect_mixer) is an open-coded version of the controls get handler. Replacing that by calling the get handler instead should allow us to use different structs for enums and onehot enums. - Lars -- 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] ASoC: dapm: Add support for multi register mux
On Thu, Apr 03, 2014 at 11:47:15AM +0200, Takashi Iwai wrote: > I'm a bit late in the game, but I feel a bit uneasy through looking > at the whole changes. My primary question is, whether do we really > need to share the same struct soc_enum for the onehot type? What > makes hard to use a struct soc_enum_onehot for them? You need > different individual get/put for each type. We may still need to > change soc_dapm_update stuff, but it's different from sharing > soc_enum. Indeed, I had thought this was where the discussion was heading - not looked at this version of the patch yet. signature.asc Description: Digital signature
Re: [PATCH] ASoC: dapm: Add support for multi register mux
At Wed, 2 Apr 2014 20:11:50 -0700, Arun Shamanna Lakshmi wrote: > > - Modify soc_enum struct to handle pointers for reg and mask > - Add dapm get and put APIs for multi register mux with one hot encoding > - Update snd_soc_dapm_update struct to support multiple reg update > > Signed-off-by: Arun Shamanna Lakshmi > Signed-off-by: Songhee Baek I'm a bit late in the game, but I feel a bit uneasy through looking at the whole changes. My primary question is, whether do we really need to share the same struct soc_enum for the onehot type? What makes hard to use a struct soc_enum_onehot for them? You need different individual get/put for each type. We may still need to change soc_dapm_update stuff, but it's different from sharing soc_enum. thanks, Takashi > --- > include/sound/soc-dapm.h | 17 - > include/sound/soc.h | 34 +++-- > sound/soc/soc-core.c | 12 ++-- > sound/soc/soc-dapm.c | 174 > +++--- > 4 files changed, 197 insertions(+), 40 deletions(-) > > diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h > index ef78f56..ded46732 100644 > --- a/include/sound/soc-dapm.h > +++ b/include/sound/soc-dapm.h > @@ -305,6 +305,12 @@ struct device; > .get = snd_soc_dapm_get_enum_double, \ > .put = snd_soc_dapm_put_enum_double, \ > .private_value = (unsigned long) } > +#define SOC_DAPM_ENUM_ONEHOT(xname, xenum) \ > +{.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ > + .info = snd_soc_info_enum_double, \ > + .get = snd_soc_dapm_get_enum_onehot, \ > + .put = snd_soc_dapm_put_enum_onehot, \ > + .private_value = (unsigned long) } > #define SOC_DAPM_ENUM_VIRT(xname, xenum) \ > SOC_DAPM_ENUM(xname, xenum) > #define SOC_DAPM_ENUM_EXT(xname, xenum, xget, xput) \ > @@ -378,6 +384,10 @@ int snd_soc_dapm_get_enum_double(struct snd_kcontrol > *kcontrol, > struct snd_ctl_elem_value *ucontrol); > int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, > struct snd_ctl_elem_value *ucontrol); > +int snd_soc_dapm_get_enum_onehot(struct snd_kcontrol *kcontrol, > + struct snd_ctl_elem_value *ucontrol); > +int snd_soc_dapm_put_enum_onehot(struct snd_kcontrol *kcontrol, > + struct snd_ctl_elem_value *ucontrol); > int snd_soc_dapm_info_pin_switch(struct snd_kcontrol *kcontrol, > struct snd_ctl_elem_info *uinfo); > int snd_soc_dapm_get_pin_switch(struct snd_kcontrol *kcontrol, > @@ -590,9 +600,10 @@ struct snd_soc_dapm_widget { > > struct snd_soc_dapm_update { > struct snd_kcontrol *kcontrol; > - int reg; > - int mask; > - int val; > + int reg[3]; > + int mask[3]; > + int val[3]; > + int num_regs; > }; > > /* DAPM context */ > diff --git a/include/sound/soc.h b/include/sound/soc.h > index 0b83168..add326a 100644 > --- a/include/sound/soc.h > +++ b/include/sound/soc.h > @@ -177,18 +177,24 @@ > {.reg = xreg, .min = xmin, .max = xmax, \ >.platform_max = xmax} } > #define SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xitems, xtexts) \ > -{.reg = xreg, .shift_l = xshift_l, .shift_r = xshift_r, \ > +{.reg = &(int){(xreg)}, .shift_l = xshift_l, .shift_r = xshift_r, \ > .items = xitems, .texts = xtexts, \ > - .mask = xitems ? roundup_pow_of_two(xitems) - 1 : 0} > + .mask = &(unsigned int){(xitems ? roundup_pow_of_two(xitems) - 1 : 0)}, > \ > + .num_regs = 1, .type = SND_SOC_ENUM_NONE } > #define SOC_ENUM_SINGLE(xreg, xshift, xitems, xtexts) \ > SOC_ENUM_DOUBLE(xreg, xshift, xshift, xitems, xtexts) > #define SOC_ENUM_SINGLE_EXT(xitems, xtexts) \ > {.items = xitems, .texts = xtexts } > #define SOC_VALUE_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, xitems, > xtexts, xvalues) \ > -{.reg = xreg, .shift_l = xshift_l, .shift_r = xshift_r, \ > - .mask = xmask, .items = xitems, .texts = xtexts, .values = xvalues} > +{.reg = &(int){(xreg)}, .shift_l = xshift_l, .shift_r = xshift_r, \ > + .mask = &(unsigned int){(xmask)}, .items = xitems, .texts = xtexts, \ > + .values = xvalues, .num_regs = 1, .type = SND_SOC_ENUM_NONE } > #define SOC_VALUE_ENUM_SINGLE(xreg, xshift, xmask, xnitmes, xtexts, xvalues) > \ > SOC_VALUE_ENUM_DOUBLE(xreg, xshift, xshift, xmask, xnitmes, xtexts, > xvalues) > +#define SOC_VALUE_ENUM_ONEHOT(xregs, xmasks, xnum_regs, xitems, xtexts, > xvalues) \ > +{.reg = xregs, .mask = xmasks, .num_regs = xnum_regs, \ > + .items = xitems, .texts = xtexts, .values = xvalues, \ > + .type = SND_SOC_ENUM_ONEHOT } > #define SOC_ENUM_SINGLE_VIRT(xitems, xtexts) \ > SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, xitems, xtexts) > #define SOC_ENUM(xname, xenum) \ > @@ -293,6 +299,9 @@ > #define SOC_VALUE_ENUM_DOUBLE_DECL(name, xreg, xshift_l, xshift_r, xmask, > xtexts, xvalues) \ > const struct soc_enum name = SOC_VALUE_ENUM_DOUBLE(xreg, xshift_l, > xshift_r, xmask, \ >
Re: [PATCH] ASoC: dapm: Add support for multi register mux
On Thu, Apr 03, 2014 at 10:27:17AM +0200, Lars-Peter Clausen wrote: > On 04/03/2014 05:11 AM, Arun Shamanna Lakshmi wrote: > >+enum snd_soc_enum_type { > >+SND_SOC_ENUM_NONE = 0, > I'm not sure if NONE is the right term. Maybe BINARY is better. Yes, it's definitely not none. signature.asc Description: Digital signature
Re: [PATCH] ASoC: dapm: Add support for multi register mux
On 04/03/2014 05:11 AM, Arun Shamanna Lakshmi wrote: This looks essentially good to me. A few minor issues, once those are fixed things should be good to go. [...] struct snd_soc_dapm_update { struct snd_kcontrol *kcontrol; - int reg; - int mask; - int val; + int reg[3]; + int mask[3]; + int val[3]; Make the 3 a define and check against it in the put handler. + int num_regs; unsigned int }; [...] +/* + * Soc Enum Type + * + * @NONE:soc_enum type for SINGLE, DOUBLE or VIRTUAL mux + * @ONEHOT: soc_enum type for one hot encoding mux + */ This should be kernel doc style so /** * enum snd_soc_enum_type - Type of the ASoC enum control * @SND_SOC_ENUM_NONE: ... * ... */ +enum snd_soc_enum_type { + SND_SOC_ENUM_NONE = 0, I'm not sure if NONE is the right term. Maybe BINARY is better. + SND_SOC_ENUM_ONEHOT = 1, +}; + [...] diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index c8a780d..19b004a 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -511,13 +511,26 @@ static int dapm_connect_mux(struct snd_soc_dapm_context *dapm, const struct snd_kcontrol_new *kcontrol) { struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int val, item; + unsigned int val, item, bit_pos = -1; default for bit_pos should probably be 0. [...] @@ -1575,8 +1588,12 @@ static void dapm_widget_update(struct snd_soc_card *card) if (!w) return; - ret = soc_widget_update_bits_locked(w, update->reg, update->mask, - update->val); + /* dapm update for multiple registers */ + for (i = 0; i < update->num_regs; i++) { + ret |= soc_widget_update_bits_locked(w, update->reg[i], + update->mask[i], update->val[i]); I'd prefer ret = soc_widget_update_bits_locked(...); if (ret < 0) break; + } + if (ret < 0) dev_err(w->dapm->dev, "ASoC: %s DAPM update failed: %d\n", w->name, ret); [...] @@ -2984,6 +3002,112 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double); /** + * snd_soc_dapm_get_enum_onehot - dapm enumerated onehot mixer get callback + * @kcontrol: mixer control + * @ucontrol: control element information + * + * Callback to get the value of a dapm enumerated onehot encoded mixer control + * + * Returns 0 for success. + */ +int snd_soc_dapm_get_enum_onehot(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + unsigned int reg_val, val, bit_pos = -1, reg_idx; Here as well, default for bit_pos should be 0. + + for (reg_idx = 0; reg_idx < e->num_regs; reg_idx++) { + reg_val = snd_soc_read(codec, e->reg[reg_idx]); + val = reg_val & e->mask[reg_idx]; + if (val != 0) { + bit_pos = __ffs(val) + (8 * codec->val_bytes * reg_idx); + break; + } + } + + ucontrol->value.enumerated.item[0] = + snd_soc_enum_val_to_item(e, bit_pos); + + return 0; +} +EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_onehot); + +/** + * snd_soc_dapm_put_enum_onehot - dapm enumerated onehot mixer put callback + * @kcontrol: mixer control + * @ucontrol: control element information + * + * Callback to put the value of a dapm enumerated onehot encoded mixer control + * + * Returns 0 for success. + */ +int snd_soc_dapm_put_enum_onehot(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); + struct snd_soc_card *card = codec->card; + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + unsigned int *item = ucontrol->value.enumerated.item; + unsigned int change = 0, reg_idx = 0, value, bit_pos; + struct snd_soc_dapm_update update; + int ret = 0, reg_val = 0, i, update_idx = 0; + + if (item[0] >= e->items) + return -EINVAL; + + value = snd_soc_enum_item_to_val(e, item[0]); + + if (value >= 0) { value is unsigned int, so this is never false. + /* get the register index and value to set */ + reg_idx = value / (8 * codec->val_bytes); + bit_pos = value % (8 * codec->val_bytes); + reg_val = BIT(bit_pos); + } + + for (i = 0; i < e->num_regs; i++) { + if (i == reg_idx) { + change = snd_soc_test_bits(codec, e->reg[i], + e->mask[i], reg_val); change |=
Re: [PATCH] ASoC: dapm: Add support for multi register mux
On 04/03/2014 11:53 AM, Mark Brown wrote: On Thu, Apr 03, 2014 at 11:47:15AM +0200, Takashi Iwai wrote: I'm a bit late in the game, but I feel a bit uneasy through looking at the whole changes. My primary question is, whether do we really need to share the same struct soc_enum for the onehot type? What makes hard to use a struct soc_enum_onehot for them? You need different individual get/put for each type. We may still need to change soc_dapm_update stuff, but it's different from sharing soc_enum. Indeed, I had thought this was where the discussion was heading - not looked at this version of the patch yet. It would be nice, but it also requires some slight restructuring. The issue we have right now is that there is strictly speaking a bit of a layering violation. The DAPM widgets should not need to know how the kcontrols that are attached to the widget do their IO. What we essentially do in dapm_connect_mux() (and also dapm_connect_mixer) is an open-coded version of the controls get handler. Replacing that by calling the get handler instead should allow us to use different structs for enums and onehot enums. - Lars -- 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] ASoC: dapm: Add support for multi register mux
At Thu, 03 Apr 2014 15:31:58 +0200, Lars-Peter Clausen wrote: On 04/03/2014 11:53 AM, Mark Brown wrote: On Thu, Apr 03, 2014 at 11:47:15AM +0200, Takashi Iwai wrote: I'm a bit late in the game, but I feel a bit uneasy through looking at the whole changes. My primary question is, whether do we really need to share the same struct soc_enum for the onehot type? What makes hard to use a struct soc_enum_onehot for them? You need different individual get/put for each type. We may still need to change soc_dapm_update stuff, but it's different from sharing soc_enum. Indeed, I had thought this was where the discussion was heading - not looked at this version of the patch yet. It would be nice, but it also requires some slight restructuring. The issue we have right now is that there is strictly speaking a bit of a layering violation. The DAPM widgets should not need to know how the kcontrols that are attached to the widget do their IO. What we essentially do in dapm_connect_mux() (and also dapm_connect_mixer) is an open-coded version of the controls get handler. Replacing that by calling the get handler instead should allow us to use different structs for enums and onehot enums. So, something like below? It's totally untested, just a proof of concept. If the performance matters, we can optimize it by checking kcontrol-get == snd_soc_dapm_get_enum_double or kcontrol-get == snd_soc_dapm_get_volsw and bypass to the current open-code functions instead of the generic get/put callers. thanks, Takashi --- diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index c8a780d0d057..5947c6e2fcc8 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -508,64 +508,71 @@ out: static int dapm_connect_mux(struct snd_soc_dapm_context *dapm, struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest, struct snd_soc_dapm_path *path, const char *control_name, - const struct snd_kcontrol_new *kcontrol) + struct snd_kcontrol *kcontrol) { - struct soc_enum *e = (struct soc_enum *)kcontrol-private_value; - unsigned int val, item; - int i; + struct snd_ctl_elem_info *uinfo; + struct snd_ctl_elem_value *ucontrol; + unsigned int i, item, items; + int err; - if (e-reg != SND_SOC_NOPM) { - soc_widget_read(dest, e-reg, val); - val = (val e-shift_l) e-mask; - item = snd_soc_enum_val_to_item(e, val); - } else { - /* since a virtual mux has no backing registers to -* decide which path to connect, it will try to match -* with the first enumeration. This is to ensure -* that the default mux choice (the first) will be -* correctly powered up during initialization. -*/ - item = 0; + uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL); + ucontrol = kzalloc(sizeof(*ucontrol), GFP_KERNEL); + if (!uinfo || !ucontrol) { + err = -ENOMEM; + goto out; + } + + err = kcontrol-info(kcontrol, uinfo); + if (err 0) + goto out; + if (WARN_ON(uinfo-type != SNDRV_CTL_ELEM_TYPE_ENUMERATED)) { + err = -EINVAL; + goto out; } + items = uinfo-value.enumerated.items; - for (i = 0; i e-items; i++) { - if (!(strcmp(control_name, e-texts[i]))) { + err = kcontrol-get(kcontrol, ucontrol); + if (err 0) + goto out; + item = ucontrol-value.enumerated.item[0]; + + for (i = 0; i items; i++) { + uinfo-value.enumerated.item = i; + err = kcontrol-info(kcontrol, uinfo); + if (err 0) + goto out; + if (!(strcmp(control_name, uinfo-value.enumerated.name))) { list_add(path-list, dapm-card-paths); list_add(path-list_sink, dest-sources); list_add(path-list_source, src-sinks); - path-name = (char*)e-texts[i]; + path-name = control_name; if (i == item) path-connect = 1; else path-connect = 0; - return 0; + goto out; } } - return -ENODEV; + err = -ENODEV; + out: + kfree(ucontrol); + kfree(uinfo); + return err 0 ? err : 0; } /* set up initial codec paths */ static void dapm_set_mixer_path_status(struct snd_soc_dapm_widget *w, struct snd_soc_dapm_path *p, int i) { - struct soc_mixer_control *mc = (struct soc_mixer_control *) - w-kcontrol_news[i].private_value; - unsigned int reg = mc-reg; - unsigned int shift = mc-shift; - unsigned int max = mc-max; -
Re: [PATCH] ASoC: dapm: Add support for multi register mux
On Thu, Apr 03, 2014 at 05:06:28PM +0200, Takashi Iwai wrote: Lars-Peter Clausen wrote: It would be nice, but it also requires some slight restructuring. The issue we have right now is that there is strictly speaking a bit of a layering violation. The DAPM widgets should not need to know how the kcontrols that are attached to the widget do their IO. What we essentially do in dapm_connect_mux() (and also dapm_connect_mixer) is an open-coded version of the controls get handler. Replacing that by calling the get handler instead should allow us to use different structs for enums and onehot enums. Right, that's because DAPM has always just reimplemented everything and the virtual controls were grafted on the side of the existing register stuff rather than adding an abstraction layer. So, something like below? It's totally untested, just a proof of concept. Yes, that looks sensible to me but I didn't test it yet either. If the performance matters, we can optimize it by checking kcontrol-get == snd_soc_dapm_get_enum_double or kcontrol-get == snd_soc_dapm_get_volsw and bypass to the current open-code functions instead of the generic get/put callers. Performance isn't that big a deal, probably avoiding the alloc/frees by just keeping one around somewhere convenient would be useful too. signature.asc Description: Digital signature
RE: [PATCH] ASoC: dapm: Add support for multi register mux
-Original Message- From: Lars-Peter Clausen [mailto:l...@metafoo.de] Sent: Thursday, April 03, 2014 1:27 AM To: Arun Shamanna Lakshmi Cc: lgirdw...@gmail.com; broo...@kernel.org; swar...@wwwdotorg.org; pe...@perex.cz; ti...@suse.de; alsa- de...@alsa-project.org; linux-kernel@vger.kernel.org; Songhee Baek Subject: Re: [PATCH] ASoC: dapm: Add support for multi register mux On 04/03/2014 05:11 AM, Arun Shamanna Lakshmi wrote: This looks essentially good to me. A few minor issues, once those are fixed things should be good to go. [...] @@ -2984,6 +3002,112 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double); /** + * snd_soc_dapm_get_enum_onehot - dapm enumerated onehot mixer get +callback + * @kcontrol: mixer control + * @ucontrol: control element information + * + * Callback to get the value of a dapm enumerated onehot encoded +mixer control + * + * Returns 0 for success. + */ +int snd_soc_dapm_get_enum_onehot(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { + struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); + struct soc_enum *e = (struct soc_enum *)kcontrol- private_value; + unsigned int reg_val, val, bit_pos = -1, reg_idx; Here as well, default for bit_pos should be 0. This means when 'None' of the options are selected, by default, it enumerates to 0. Since we are using __ffs, BIT(0) of Register-0 also enumerates to 0. That's the reason why I used just ffs in the first place. Let me know your opinion. My value table looks like below. #define MUX_VALUE(npart, nbit) (nbit + 32 * npart) static const int mux_values[] = { 0, MUX_VALUE(0, 0), . . . MUX_VALUE(0, 31), /* above inputs are for part0 mux */ MUX_VALUE(1, 0), . . . MUX_VALUE(1, 31), /* above inputs are for part1 mux */ MUX_VALUE(2, 0), . . . MUX_VALUE(2, 31), /* above inputs are for part2 mux */ }; + + for (reg_idx = 0; reg_idx e-num_regs; reg_idx++) { + reg_val = snd_soc_read(codec, e-reg[reg_idx]); + val = reg_val e-mask[reg_idx]; + if (val != 0) { + bit_pos = __ffs(val) + (8 * codec-val_bytes * reg_idx); + break; + } + } + + ucontrol-value.enumerated.item[0] = + snd_soc_enum_val_to_item(e, bit_pos); + + return 0; +} +EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_onehot); + +/** + -- 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] ASoC: dapm: Add support for multi register mux
On 04/03/2014 05:11 AM, Arun Shamanna Lakshmi wrote: This looks essentially good to me. A few minor issues, once those are fixed things should be good to go. [...] struct snd_soc_dapm_update { struct snd_kcontrol *kcontrol; - int reg; - int mask; - int val; + int reg[3]; + int mask[3]; + int val[3]; Make the 3 a define and check against it in the put handler. + int num_regs; unsigned int }; [...] +/* + * Soc Enum Type + * + * @NONE:soc_enum type for SINGLE, DOUBLE or VIRTUAL mux + * @ONEHOT: soc_enum type for one hot encoding mux + */ This should be kernel doc style so /** * enum snd_soc_enum_type - Type of the ASoC enum control * @SND_SOC_ENUM_NONE: ... * ... */ +enum snd_soc_enum_type { + SND_SOC_ENUM_NONE = 0, I'm not sure if NONE is the right term. Maybe BINARY is better. + SND_SOC_ENUM_ONEHOT = 1, +}; + [...] diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index c8a780d..19b004a 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -511,13 +511,26 @@ static int dapm_connect_mux(struct snd_soc_dapm_context *dapm, const struct snd_kcontrol_new *kcontrol) { struct soc_enum *e = (struct soc_enum *)kcontrol-private_value; - unsigned int val, item; + unsigned int val, item, bit_pos = -1; default for bit_pos should probably be 0. [...] @@ -1575,8 +1588,12 @@ static void dapm_widget_update(struct snd_soc_card *card) if (!w) return; - ret = soc_widget_update_bits_locked(w, update-reg, update-mask, - update-val); + /* dapm update for multiple registers */ + for (i = 0; i update-num_regs; i++) { + ret |= soc_widget_update_bits_locked(w, update-reg[i], + update-mask[i], update-val[i]); I'd prefer ret = soc_widget_update_bits_locked(...); if (ret 0) break; + } + if (ret 0) dev_err(w-dapm-dev, ASoC: %s DAPM update failed: %d\n, w-name, ret); [...] @@ -2984,6 +3002,112 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double); /** + * snd_soc_dapm_get_enum_onehot - dapm enumerated onehot mixer get callback + * @kcontrol: mixer control + * @ucontrol: control element information + * + * Callback to get the value of a dapm enumerated onehot encoded mixer control + * + * Returns 0 for success. + */ +int snd_soc_dapm_get_enum_onehot(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); + struct soc_enum *e = (struct soc_enum *)kcontrol-private_value; + unsigned int reg_val, val, bit_pos = -1, reg_idx; Here as well, default for bit_pos should be 0. + + for (reg_idx = 0; reg_idx e-num_regs; reg_idx++) { + reg_val = snd_soc_read(codec, e-reg[reg_idx]); + val = reg_val e-mask[reg_idx]; + if (val != 0) { + bit_pos = __ffs(val) + (8 * codec-val_bytes * reg_idx); + break; + } + } + + ucontrol-value.enumerated.item[0] = + snd_soc_enum_val_to_item(e, bit_pos); + + return 0; +} +EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_onehot); + +/** + * snd_soc_dapm_put_enum_onehot - dapm enumerated onehot mixer put callback + * @kcontrol: mixer control + * @ucontrol: control element information + * + * Callback to put the value of a dapm enumerated onehot encoded mixer control + * + * Returns 0 for success. + */ +int snd_soc_dapm_put_enum_onehot(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); + struct snd_soc_card *card = codec-card; + struct soc_enum *e = (struct soc_enum *)kcontrol-private_value; + unsigned int *item = ucontrol-value.enumerated.item; + unsigned int change = 0, reg_idx = 0, value, bit_pos; + struct snd_soc_dapm_update update; + int ret = 0, reg_val = 0, i, update_idx = 0; + + if (item[0] = e-items) + return -EINVAL; + + value = snd_soc_enum_item_to_val(e, item[0]); + + if (value = 0) { value is unsigned int, so this is never false. + /* get the register index and value to set */ + reg_idx = value / (8 * codec-val_bytes); + bit_pos = value % (8 * codec-val_bytes); + reg_val = BIT(bit_pos); + } + + for (i = 0; i e-num_regs; i++) { + if (i == reg_idx) { + change = snd_soc_test_bits(codec, e-reg[i], + e-mask[i], reg_val); change |= + /* set the
Re: [PATCH] ASoC: dapm: Add support for multi register mux
On Thu, Apr 03, 2014 at 10:27:17AM +0200, Lars-Peter Clausen wrote: On 04/03/2014 05:11 AM, Arun Shamanna Lakshmi wrote: +enum snd_soc_enum_type { +SND_SOC_ENUM_NONE = 0, I'm not sure if NONE is the right term. Maybe BINARY is better. Yes, it's definitely not none. signature.asc Description: Digital signature
Re: [PATCH] ASoC: dapm: Add support for multi register mux
At Wed, 2 Apr 2014 20:11:50 -0700, Arun Shamanna Lakshmi wrote: - Modify soc_enum struct to handle pointers for reg and mask - Add dapm get and put APIs for multi register mux with one hot encoding - Update snd_soc_dapm_update struct to support multiple reg update Signed-off-by: Arun Shamanna Lakshmi ar...@nvidia.com Signed-off-by: Songhee Baek sb...@nvidia.com I'm a bit late in the game, but I feel a bit uneasy through looking at the whole changes. My primary question is, whether do we really need to share the same struct soc_enum for the onehot type? What makes hard to use a struct soc_enum_onehot for them? You need different individual get/put for each type. We may still need to change soc_dapm_update stuff, but it's different from sharing soc_enum. thanks, Takashi --- include/sound/soc-dapm.h | 17 - include/sound/soc.h | 34 +++-- sound/soc/soc-core.c | 12 ++-- sound/soc/soc-dapm.c | 174 +++--- 4 files changed, 197 insertions(+), 40 deletions(-) diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index ef78f56..ded46732 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -305,6 +305,12 @@ struct device; .get = snd_soc_dapm_get_enum_double, \ .put = snd_soc_dapm_put_enum_double, \ .private_value = (unsigned long)xenum } +#define SOC_DAPM_ENUM_ONEHOT(xname, xenum) \ +{.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ + .info = snd_soc_info_enum_double, \ + .get = snd_soc_dapm_get_enum_onehot, \ + .put = snd_soc_dapm_put_enum_onehot, \ + .private_value = (unsigned long)xenum } #define SOC_DAPM_ENUM_VIRT(xname, xenum) \ SOC_DAPM_ENUM(xname, xenum) #define SOC_DAPM_ENUM_EXT(xname, xenum, xget, xput) \ @@ -378,6 +384,10 @@ int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); +int snd_soc_dapm_get_enum_onehot(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol); +int snd_soc_dapm_put_enum_onehot(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol); int snd_soc_dapm_info_pin_switch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo); int snd_soc_dapm_get_pin_switch(struct snd_kcontrol *kcontrol, @@ -590,9 +600,10 @@ struct snd_soc_dapm_widget { struct snd_soc_dapm_update { struct snd_kcontrol *kcontrol; - int reg; - int mask; - int val; + int reg[3]; + int mask[3]; + int val[3]; + int num_regs; }; /* DAPM context */ diff --git a/include/sound/soc.h b/include/sound/soc.h index 0b83168..add326a 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -177,18 +177,24 @@ {.reg = xreg, .min = xmin, .max = xmax, \ .platform_max = xmax} } #define SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xitems, xtexts) \ -{.reg = xreg, .shift_l = xshift_l, .shift_r = xshift_r, \ +{.reg = (int){(xreg)}, .shift_l = xshift_l, .shift_r = xshift_r, \ .items = xitems, .texts = xtexts, \ - .mask = xitems ? roundup_pow_of_two(xitems) - 1 : 0} + .mask = (unsigned int){(xitems ? roundup_pow_of_two(xitems) - 1 : 0)}, \ + .num_regs = 1, .type = SND_SOC_ENUM_NONE } #define SOC_ENUM_SINGLE(xreg, xshift, xitems, xtexts) \ SOC_ENUM_DOUBLE(xreg, xshift, xshift, xitems, xtexts) #define SOC_ENUM_SINGLE_EXT(xitems, xtexts) \ {.items = xitems, .texts = xtexts } #define SOC_VALUE_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, xitems, xtexts, xvalues) \ -{.reg = xreg, .shift_l = xshift_l, .shift_r = xshift_r, \ - .mask = xmask, .items = xitems, .texts = xtexts, .values = xvalues} +{.reg = (int){(xreg)}, .shift_l = xshift_l, .shift_r = xshift_r, \ + .mask = (unsigned int){(xmask)}, .items = xitems, .texts = xtexts, \ + .values = xvalues, .num_regs = 1, .type = SND_SOC_ENUM_NONE } #define SOC_VALUE_ENUM_SINGLE(xreg, xshift, xmask, xnitmes, xtexts, xvalues) \ SOC_VALUE_ENUM_DOUBLE(xreg, xshift, xshift, xmask, xnitmes, xtexts, xvalues) +#define SOC_VALUE_ENUM_ONEHOT(xregs, xmasks, xnum_regs, xitems, xtexts, xvalues) \ +{.reg = xregs, .mask = xmasks, .num_regs = xnum_regs, \ + .items = xitems, .texts = xtexts, .values = xvalues, \ + .type = SND_SOC_ENUM_ONEHOT } #define SOC_ENUM_SINGLE_VIRT(xitems, xtexts) \ SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, xitems, xtexts) #define SOC_ENUM(xname, xenum) \ @@ -293,6 +299,9 @@ #define SOC_VALUE_ENUM_DOUBLE_DECL(name, xreg, xshift_l, xshift_r, xmask, xtexts, xvalues) \ const struct soc_enum name = SOC_VALUE_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, \ ARRAY_SIZE(xtexts), xtexts, xvalues) +#define
Re: [PATCH] ASoC: dapm: Add support for multi register mux
On Thu, Apr 03, 2014 at 11:47:15AM +0200, Takashi Iwai wrote: I'm a bit late in the game, but I feel a bit uneasy through looking at the whole changes. My primary question is, whether do we really need to share the same struct soc_enum for the onehot type? What makes hard to use a struct soc_enum_onehot for them? You need different individual get/put for each type. We may still need to change soc_dapm_update stuff, but it's different from sharing soc_enum. Indeed, I had thought this was where the discussion was heading - not looked at this version of the patch yet. signature.asc Description: Digital signature
Re: [PATCH] ASoC: DAPM: Add support for multi register mux
On 04/02/2014 05:26 PM, Songhee Baek wrote: -Original Message- From: Lars-Peter Clausen [mailto:l...@metafoo.de] Sent: Wednesday, April 02, 2014 12:02 AM To: Songhee Baek Cc: Arun Shamanna Lakshmi; lgirdw...@gmail.com; broo...@kernel.org; swar...@wwwdotorg.org; pe...@perex.cz; ti...@suse.de; alsa- de...@alsa-project.org; linux-kernel@vger.kernel.org Subject: Re: [PATCH] ASoC: DAPM: Add support for multi register mux On 04/02/2014 08:56 AM, Songhee Baek wrote: -Original Message- From: Lars-Peter Clausen [mailto:l...@metafoo.de] Sent: Tuesday, April 01, 2014 11:47 PM To: Songhee Baek Cc: Arun Shamanna Lakshmi; lgirdw...@gmail.com; broo...@kernel.org; swar...@wwwdotorg.org; pe...@perex.cz; ti...@suse.de; alsa- de...@alsa-project.org; linux-kernel@vger.kernel.org Subject: Re: [PATCH] ASoC: DAPM: Add support for multi register mux On 04/02/2014 08:17 AM, Songhee Baek wrote: -Original Message- From: Lars-Peter Clausen [mailto:l...@metafoo.de] Sent: Tuesday, April 01, 2014 11:00 PM To: Arun Shamanna Lakshmi Cc: lgirdw...@gmail.com; broo...@kernel.org; swar...@wwwdotorg.org; pe...@perex.cz; ti...@suse.de; alsa-de...@alsa-project.org; linux- ker...@vger.kernel.org; Songhee Baek Subject: Re: [PATCH] ASoC: DAPM: Add support for multi register mux On 04/01/2014 08:26 PM, Arun Shamanna Lakshmi wrote: [...] diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index c8a780d..4d2b35c 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -514,9 +514,9 @@ static int dapm_connect_mux(struct snd_soc_dapm_context *dapm, unsigned int val, item; int i; - if (e->reg != SND_SOC_NOPM) { - soc_widget_read(dest, e->reg, ); - val = (val >> e->shift_l) & e->mask; + if (e->reg[0] != SND_SOC_NOPM) { + soc_widget_read(dest, e->reg[0], ); + val = (val >> e->shift_l) & e->mask[0]; item = snd_soc_enum_val_to_item(e, val); This probably should handle the new enum type as well. You'll probably need some kind of flag in the struct to distinguish between the two enum types. Any suggestion on the flag name ? How about 'onehot'? [...] + reg_val = BIT(bit_pos); + } + + for (i = 0; i < e->num_regs; i++) { + if (i == reg_idx) { + change = snd_soc_test_bits(codec, e->reg[i], + e->mask[i], reg_val); + + } else { + /* accumulate the change to update the DAPM path + when none is selected */ + change += snd_soc_test_bits(codec, e- reg[i], + e->mask[i], 0); change |= + + /* clear the register when not selected */ + snd_soc_write(codec, e->reg[i], 0); I think this should happen as part of the DAPM update sequence like you had earlier. Some special care should probably be take to make sure that you de-select the previous mux input before selecting the new one if the new one is in a different register than the previous one. I am not sure I follow this part. We are clearing the 'not selected' registers before we set the one we want. Do you want us to loop the logic of soc_dapm_mux_update_power for each register ? or do you want to change the dapm_update structure so that it takes all the regs, masks, and values together ? The idea with the dapm_update struct is that the register updates are done in the middle of the power-down and power-up sequence. So yes, change the dapm_update struct to be able to hold all register updates and do all register updates in dapm_widget_update. I think an earlier version of your patch already had this. Is the change similar to as shown below? for (reg_idx = 0; reg_idx < e->num_regs; reg_idx++) { val = e->values[item * e->num_regs + reg_idx]; ret = snd_soc_update_bits_locked(codec, e->reg[reg_idx], e->mask[reg_idx], val); if (ret) return ret; } During updating of the register's value, the above change can create non-zero value in two different registers (very short transition) as Mark mentioned for that change so we need to clear register first before writing the desired value in the register. Should we add the clearing all registers and write the mux value in desired register in the update function? In dapm_update_widget() you have this line: ret = soc_widget_update_bits(w, update->reg, update->mask, update- val); That needs to be done for every register update. When you setup the update struct you need to make sure that the register clears come before the register set. E.g. if you have register 0x3, 0x4, 0x5 and you select a bit in register 0x4 it should look like this. update->reg[
RE: [PATCH] ASoC: DAPM: Add support for multi register mux
> -Original Message- > From: Lars-Peter Clausen [mailto:l...@metafoo.de] > Sent: Wednesday, April 02, 2014 12:02 AM > To: Songhee Baek > Cc: Arun Shamanna Lakshmi; lgirdw...@gmail.com; broo...@kernel.org; > swar...@wwwdotorg.org; pe...@perex.cz; ti...@suse.de; alsa- > de...@alsa-project.org; linux-kernel@vger.kernel.org > Subject: Re: [PATCH] ASoC: DAPM: Add support for multi register mux > > On 04/02/2014 08:56 AM, Songhee Baek wrote: > > > > > >> -Original Message- > >> From: Lars-Peter Clausen [mailto:l...@metafoo.de] > >> Sent: Tuesday, April 01, 2014 11:47 PM > >> To: Songhee Baek > >> Cc: Arun Shamanna Lakshmi; lgirdw...@gmail.com; broo...@kernel.org; > >> swar...@wwwdotorg.org; pe...@perex.cz; ti...@suse.de; alsa- > >> de...@alsa-project.org; linux-kernel@vger.kernel.org > >> Subject: Re: [PATCH] ASoC: DAPM: Add support for multi register mux > >> > >> On 04/02/2014 08:17 AM, Songhee Baek wrote: > >>>> -Original Message- > >>>> From: Lars-Peter Clausen [mailto:l...@metafoo.de] > >>>> Sent: Tuesday, April 01, 2014 11:00 PM > >>>> To: Arun Shamanna Lakshmi > >>>> Cc: lgirdw...@gmail.com; broo...@kernel.org; > >> swar...@wwwdotorg.org; > >>>> pe...@perex.cz; ti...@suse.de; alsa-de...@alsa-project.org; linux- > >>>> ker...@vger.kernel.org; Songhee Baek > >>>> Subject: Re: [PATCH] ASoC: DAPM: Add support for multi register mux > >>>> > >>>> On 04/01/2014 08:26 PM, Arun Shamanna Lakshmi wrote: > >>>> [...] > >>>>>>> diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index > >>>>>>> c8a780d..4d2b35c 100644 > >>>>>>> --- a/sound/soc/soc-dapm.c > >>>>>>> +++ b/sound/soc/soc-dapm.c > >>>>>>> @@ -514,9 +514,9 @@ static int dapm_connect_mux(struct > >>>>>> snd_soc_dapm_context *dapm, > >>>>>>> unsigned int val, item; > >>>>>>> int i; > >>>>>>> > >>>>>>> - if (e->reg != SND_SOC_NOPM) { > >>>>>>> - soc_widget_read(dest, e->reg, ); > >>>>>>> - val = (val >> e->shift_l) & e->mask; > >>>>>>> + if (e->reg[0] != SND_SOC_NOPM) { > >>>>>>> + soc_widget_read(dest, e->reg[0], ); > >>>>>>> + val = (val >> e->shift_l) & e->mask[0]; > >>>>>>> item = snd_soc_enum_val_to_item(e, val); > >>>>>> > >>>>>> This probably should handle the new enum type as well. You'll > >>>>>> probably need some kind of flag in the struct to distinguish > >>>>>> between the two enum types. > >>>>> > >>>>> Any suggestion on the flag name ? > >>>>> > >>>> > >>>> How about 'onehot'? > >>>> > >>>> [...] > >>>>>>> + reg_val = BIT(bit_pos); > >>>>>>> + } > >>>>>>> + > >>>>>>> + for (i = 0; i < e->num_regs; i++) { > >>>>>>> + if (i == reg_idx) { > >>>>>>> + change = snd_soc_test_bits(codec, e->reg[i], > >>>>>>> + e->mask[i], > >>>>>> reg_val); > >>>>>>> + > >>>>>>> + } else { > >>>>>>> + /* accumulate the change to update the > >> DAPM > >>>>>> path > >>>>>>> + when none is selected */ > >>>>>>> + change += snd_soc_test_bits(codec, e- > >>> reg[i], > >>>>>>> + e->mask[i], 0); > >>>>>> > >>>>>> change |= > >>>>>> > >>>>>>> + > >>>>>>> + /* clear the register when not selected */ > >>>>>>> + snd_soc_write(codec, e->reg[i], 0); > >>>>>> > >>>>>> I think this should happen as part of the DAPM update sequence
RE: [PATCH] ASoC: DAPM: Add support for multi register mux
> -Original Message- > From: Lars-Peter Clausen [mailto:l...@metafoo.de] > Sent: Wednesday, April 02, 2014 12:02 AM > To: Songhee Baek > Cc: Arun Shamanna Lakshmi; lgirdw...@gmail.com; broo...@kernel.org; > swar...@wwwdotorg.org; pe...@perex.cz; ti...@suse.de; alsa- > de...@alsa-project.org; linux-kernel@vger.kernel.org > Subject: Re: [PATCH] ASoC: DAPM: Add support for multi register mux > > On 04/02/2014 08:56 AM, Songhee Baek wrote: > > > > > >> -Original Message- > >> From: Lars-Peter Clausen [mailto:l...@metafoo.de] > >> Sent: Tuesday, April 01, 2014 11:47 PM > >> To: Songhee Baek > >> Cc: Arun Shamanna Lakshmi; lgirdw...@gmail.com; broo...@kernel.org; > >> swar...@wwwdotorg.org; pe...@perex.cz; ti...@suse.de; alsa- > >> de...@alsa-project.org; linux-kernel@vger.kernel.org > >> Subject: Re: [PATCH] ASoC: DAPM: Add support for multi register mux > >> > >> On 04/02/2014 08:17 AM, Songhee Baek wrote: > >>>> -Original Message- > >>>> From: Lars-Peter Clausen [mailto:l...@metafoo.de] > >>>> Sent: Tuesday, April 01, 2014 11:00 PM > >>>> To: Arun Shamanna Lakshmi > >>>> Cc: lgirdw...@gmail.com; broo...@kernel.org; > >> swar...@wwwdotorg.org; > >>>> pe...@perex.cz; ti...@suse.de; alsa-de...@alsa-project.org; linux- > >>>> ker...@vger.kernel.org; Songhee Baek > >>>> Subject: Re: [PATCH] ASoC: DAPM: Add support for multi register mux > >>>> > >>>> On 04/01/2014 08:26 PM, Arun Shamanna Lakshmi wrote: > >>>> [...] > >>>>>>> diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index > >>>>>>> c8a780d..4d2b35c 100644 > >>>>>>> --- a/sound/soc/soc-dapm.c > >>>>>>> +++ b/sound/soc/soc-dapm.c > >>>>>>> @@ -514,9 +514,9 @@ static int dapm_connect_mux(struct > >>>>>> snd_soc_dapm_context *dapm, > >>>>>>> unsigned int val, item; > >>>>>>> int i; > >>>>>>> > >>>>>>> - if (e->reg != SND_SOC_NOPM) { > >>>>>>> - soc_widget_read(dest, e->reg, ); > >>>>>>> - val = (val >> e->shift_l) & e->mask; > >>>>>>> + if (e->reg[0] != SND_SOC_NOPM) { > >>>>>>> + soc_widget_read(dest, e->reg[0], ); > >>>>>>> + val = (val >> e->shift_l) & e->mask[0]; > >>>>>>> item = snd_soc_enum_val_to_item(e, val); > >>>>>> > >>>>>> This probably should handle the new enum type as well. You'll > >>>>>> probably need some kind of flag in the struct to distinguish > >>>>>> between the two enum types. > >>>>> > >>>>> Any suggestion on the flag name ? > >>>>> > >>>> > >>>> How about 'onehot'? > >>>> > >>>> [...] > >>>>>>> + reg_val = BIT(bit_pos); > >>>>>>> + } > >>>>>>> + > >>>>>>> + for (i = 0; i < e->num_regs; i++) { > >>>>>>> + if (i == reg_idx) { > >>>>>>> + change = snd_soc_test_bits(codec, e->reg[i], > >>>>>>> + e->mask[i], > >>>>>> reg_val); > >>>>>>> + > >>>>>>> + } else { > >>>>>>> + /* accumulate the change to update the > >> DAPM > >>>>>> path > >>>>>>> + when none is selected */ > >>>>>>> + change += snd_soc_test_bits(codec, e- > >>> reg[i], > >>>>>>> + e->mask[i], 0); > >>>>>> > >>>>>> change |= > >>>>>> > >>>>>>> + > >>>>>>> + /* clear the register when not selected */ > >>>>>>> + snd_soc_write(codec, e->reg[i], 0); > >>>>>> > >>>>>> I think this should happen as part of the DAPM update sequence
Re: [PATCH] ASoC: DAPM: Add support for multi register mux
On 04/02/2014 08:56 AM, Songhee Baek wrote: -Original Message- From: Lars-Peter Clausen [mailto:l...@metafoo.de] Sent: Tuesday, April 01, 2014 11:47 PM To: Songhee Baek Cc: Arun Shamanna Lakshmi; lgirdw...@gmail.com; broo...@kernel.org; swar...@wwwdotorg.org; pe...@perex.cz; ti...@suse.de; alsa- de...@alsa-project.org; linux-kernel@vger.kernel.org Subject: Re: [PATCH] ASoC: DAPM: Add support for multi register mux On 04/02/2014 08:17 AM, Songhee Baek wrote: -Original Message- From: Lars-Peter Clausen [mailto:l...@metafoo.de] Sent: Tuesday, April 01, 2014 11:00 PM To: Arun Shamanna Lakshmi Cc: lgirdw...@gmail.com; broo...@kernel.org; swar...@wwwdotorg.org; pe...@perex.cz; ti...@suse.de; alsa-de...@alsa-project.org; linux- ker...@vger.kernel.org; Songhee Baek Subject: Re: [PATCH] ASoC: DAPM: Add support for multi register mux On 04/01/2014 08:26 PM, Arun Shamanna Lakshmi wrote: [...] diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index c8a780d..4d2b35c 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -514,9 +514,9 @@ static int dapm_connect_mux(struct snd_soc_dapm_context *dapm, unsigned int val, item; int i; - if (e->reg != SND_SOC_NOPM) { - soc_widget_read(dest, e->reg, ); - val = (val >> e->shift_l) & e->mask; + if (e->reg[0] != SND_SOC_NOPM) { + soc_widget_read(dest, e->reg[0], ); + val = (val >> e->shift_l) & e->mask[0]; item = snd_soc_enum_val_to_item(e, val); This probably should handle the new enum type as well. You'll probably need some kind of flag in the struct to distinguish between the two enum types. Any suggestion on the flag name ? How about 'onehot'? [...] + reg_val = BIT(bit_pos); + } + + for (i = 0; i < e->num_regs; i++) { + if (i == reg_idx) { + change = snd_soc_test_bits(codec, e->reg[i], + e->mask[i], reg_val); + + } else { + /* accumulate the change to update the DAPM path + when none is selected */ + change += snd_soc_test_bits(codec, e- reg[i], + e->mask[i], 0); change |= + + /* clear the register when not selected */ + snd_soc_write(codec, e->reg[i], 0); I think this should happen as part of the DAPM update sequence like you had earlier. Some special care should probably be take to make sure that you de-select the previous mux input before selecting the new one if the new one is in a different register than the previous one. I am not sure I follow this part. We are clearing the 'not selected' registers before we set the one we want. Do you want us to loop the logic of soc_dapm_mux_update_power for each register ? or do you want to change the dapm_update structure so that it takes all the regs, masks, and values together ? The idea with the dapm_update struct is that the register updates are done in the middle of the power-down and power-up sequence. So yes, change the dapm_update struct to be able to hold all register updates and do all register updates in dapm_widget_update. I think an earlier version of your patch already had this. Is the change similar to as shown below? for (reg_idx = 0; reg_idx < e->num_regs; reg_idx++) { val = e->values[item * e->num_regs + reg_idx]; ret = snd_soc_update_bits_locked(codec, e->reg[reg_idx], e->mask[reg_idx], val); if (ret) return ret; } During updating of the register's value, the above change can create non-zero value in two different registers (very short transition) as Mark mentioned for that change so we need to clear register first before writing the desired value in the register. Should we add the clearing all registers and write the mux value in desired register in the update function? In dapm_update_widget() you have this line: ret = soc_widget_update_bits(w, update->reg, update->mask, update- val); That needs to be done for every register update. When you setup the update struct you need to make sure that the register clears come before the register set. E.g. if you have register 0x3, 0x4, 0x5 and you select a bit in register 0x4 it should look like this. update->reg[0] = 0x3; update->val[0] = 0x0; update->reg[1] = 0x5; update->val[1] = 0x0; update->reg[2] = 0x4; update->val[2] = 0x8; When you set a bit in register 0x3 it should look like this: update->reg[0] = 0x4; update->val[0] = 0x0; update->reg[1] = 0x5; update->val[1] = 0x0; update->reg[2] = 0x3; update->val[2] = 0x1; So basically the write operation goes into update->reg[e->num_regs-1] the clear
RE: [PATCH] ASoC: DAPM: Add support for multi register mux
> -Original Message- > From: Lars-Peter Clausen [mailto:l...@metafoo.de] > Sent: Tuesday, April 01, 2014 11:47 PM > To: Songhee Baek > Cc: Arun Shamanna Lakshmi; lgirdw...@gmail.com; broo...@kernel.org; > swar...@wwwdotorg.org; pe...@perex.cz; ti...@suse.de; alsa- > de...@alsa-project.org; linux-kernel@vger.kernel.org > Subject: Re: [PATCH] ASoC: DAPM: Add support for multi register mux > > On 04/02/2014 08:17 AM, Songhee Baek wrote: > >> -Original Message- > >> From: Lars-Peter Clausen [mailto:l...@metafoo.de] > >> Sent: Tuesday, April 01, 2014 11:00 PM > >> To: Arun Shamanna Lakshmi > >> Cc: lgirdw...@gmail.com; broo...@kernel.org; > swar...@wwwdotorg.org; > >> pe...@perex.cz; ti...@suse.de; alsa-de...@alsa-project.org; linux- > >> ker...@vger.kernel.org; Songhee Baek > >> Subject: Re: [PATCH] ASoC: DAPM: Add support for multi register mux > >> > >> On 04/01/2014 08:26 PM, Arun Shamanna Lakshmi wrote: > >> [...] > >>>>> diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index > >>>>> c8a780d..4d2b35c 100644 > >>>>> --- a/sound/soc/soc-dapm.c > >>>>> +++ b/sound/soc/soc-dapm.c > >>>>> @@ -514,9 +514,9 @@ static int dapm_connect_mux(struct > >>>> snd_soc_dapm_context *dapm, > >>>>> unsigned int val, item; > >>>>> int i; > >>>>> > >>>>> - if (e->reg != SND_SOC_NOPM) { > >>>>> - soc_widget_read(dest, e->reg, ); > >>>>> - val = (val >> e->shift_l) & e->mask; > >>>>> + if (e->reg[0] != SND_SOC_NOPM) { > >>>>> + soc_widget_read(dest, e->reg[0], ); > >>>>> + val = (val >> e->shift_l) & e->mask[0]; > >>>>> item = snd_soc_enum_val_to_item(e, val); > >>>> > >>>> This probably should handle the new enum type as well. You'll > >>>> probably need some kind of flag in the struct to distinguish > >>>> between the two enum types. > >>> > >>> Any suggestion on the flag name ? > >>> > >> > >> How about 'onehot'? > >> > >> [...] > >>>>> + reg_val = BIT(bit_pos); > >>>>> + } > >>>>> + > >>>>> + for (i = 0; i < e->num_regs; i++) { > >>>>> + if (i == reg_idx) { > >>>>> + change = snd_soc_test_bits(codec, e->reg[i], > >>>>> + e->mask[i], > >>>> reg_val); > >>>>> + > >>>>> + } else { > >>>>> + /* accumulate the change to update the > DAPM > >>>> path > >>>>> + when none is selected */ > >>>>> + change += snd_soc_test_bits(codec, e- > >reg[i], > >>>>> + e->mask[i], 0); > >>>> > >>>> change |= > >>>> > >>>>> + > >>>>> + /* clear the register when not selected */ > >>>>> + snd_soc_write(codec, e->reg[i], 0); > >>>> > >>>> I think this should happen as part of the DAPM update sequence like > >>>> you had earlier. Some special care should probably be take to make > >>>> sure that you de-select the previous mux input before selecting the > >>>> new one if the new one is in a different register than the previous one. > >>> > >>> I am not sure I follow this part. We are clearing the 'not selected' > >>> registers before we set the one we want. Do you want us to loop the > >>> logic of soc_dapm_mux_update_power for each register ? or do you > >>> want to change the dapm_update structure so that it takes all the > >>> regs, masks, and values together ? > >> > >> The idea with the dapm_update struct is that the register updates are > >> done in the middle of the power-down and power-up sequence. So yes, > >> change the dapm_update struct to be able to hold all register updates > >> and do all register updates in dapm_widget_update. I think an earlier >
Re: [PATCH] ASoC: DAPM: Add support for multi register mux
On 04/02/2014 08:17 AM, Songhee Baek wrote: -Original Message- From: Lars-Peter Clausen [mailto:l...@metafoo.de] Sent: Tuesday, April 01, 2014 11:00 PM To: Arun Shamanna Lakshmi Cc: lgirdw...@gmail.com; broo...@kernel.org; swar...@wwwdotorg.org; pe...@perex.cz; ti...@suse.de; alsa-de...@alsa-project.org; linux- ker...@vger.kernel.org; Songhee Baek Subject: Re: [PATCH] ASoC: DAPM: Add support for multi register mux On 04/01/2014 08:26 PM, Arun Shamanna Lakshmi wrote: [...] diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index c8a780d..4d2b35c 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -514,9 +514,9 @@ static int dapm_connect_mux(struct snd_soc_dapm_context *dapm, unsigned int val, item; int i; - if (e->reg != SND_SOC_NOPM) { - soc_widget_read(dest, e->reg, ); - val = (val >> e->shift_l) & e->mask; + if (e->reg[0] != SND_SOC_NOPM) { + soc_widget_read(dest, e->reg[0], ); + val = (val >> e->shift_l) & e->mask[0]; item = snd_soc_enum_val_to_item(e, val); This probably should handle the new enum type as well. You'll probably need some kind of flag in the struct to distinguish between the two enum types. Any suggestion on the flag name ? How about 'onehot'? [...] + reg_val = BIT(bit_pos); + } + + for (i = 0; i < e->num_regs; i++) { + if (i == reg_idx) { + change = snd_soc_test_bits(codec, e->reg[i], + e->mask[i], reg_val); + + } else { + /* accumulate the change to update the DAPM path + when none is selected */ + change += snd_soc_test_bits(codec, e->reg[i], + e->mask[i], 0); change |= + + /* clear the register when not selected */ + snd_soc_write(codec, e->reg[i], 0); I think this should happen as part of the DAPM update sequence like you had earlier. Some special care should probably be take to make sure that you de-select the previous mux input before selecting the new one if the new one is in a different register than the previous one. I am not sure I follow this part. We are clearing the 'not selected' registers before we set the one we want. Do you want us to loop the logic of soc_dapm_mux_update_power for each register ? or do you want to change the dapm_update structure so that it takes all the regs, masks, and values together ? The idea with the dapm_update struct is that the register updates are done in the middle of the power-down and power-up sequence. So yes, change the dapm_update struct to be able to hold all register updates and do all register updates in dapm_widget_update. I think an earlier version of your patch already had this. Is the change similar to as shown below? for (reg_idx = 0; reg_idx < e->num_regs; reg_idx++) { val = e->values[item * e->num_regs + reg_idx]; ret = snd_soc_update_bits_locked(codec, e->reg[reg_idx], e->mask[reg_idx], val); if (ret) return ret; } During updating of the register's value, the above change can create non-zero value in two different registers (very short transition) as Mark mentioned for that change so we need to clear register first before writing the desired value in the register. Should we add the clearing all registers and write the mux value in desired register in the update function? In dapm_update_widget() you have this line: ret = soc_widget_update_bits(w, update->reg, update->mask, update->val); That needs to be done for every register update. When you setup the update struct you need to make sure that the register clears come before the register set. E.g. if you have register 0x3, 0x4, 0x5 and you select a bit in register 0x4 it should look like this. update->reg[0] = 0x3; update->val[0] = 0x0; update->reg[1] = 0x5; update->val[1] = 0x0; update->reg[2] = 0x4; update->val[2] = 0x8; When you set a bit in register 0x3 it should look like this: update->reg[0] = 0x4; update->val[0] = 0x0; update->reg[1] = 0x5; update->val[1] = 0x0; update->reg[2] = 0x3; update->val[2] = 0x1; So basically the write operation goes into update->reg[e->num_regs-1] the clear operations go into the other slots before that. - Lars -- 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] ASoC: DAPM: Add support for multi register mux
> -Original Message- > From: Lars-Peter Clausen [mailto:l...@metafoo.de] > Sent: Tuesday, April 01, 2014 11:00 PM > To: Arun Shamanna Lakshmi > Cc: lgirdw...@gmail.com; broo...@kernel.org; swar...@wwwdotorg.org; > pe...@perex.cz; ti...@suse.de; alsa-de...@alsa-project.org; linux- > ker...@vger.kernel.org; Songhee Baek > Subject: Re: [PATCH] ASoC: DAPM: Add support for multi register mux > > On 04/01/2014 08:26 PM, Arun Shamanna Lakshmi wrote: > [...] > >>> diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index > >>> c8a780d..4d2b35c 100644 > >>> --- a/sound/soc/soc-dapm.c > >>> +++ b/sound/soc/soc-dapm.c > >>> @@ -514,9 +514,9 @@ static int dapm_connect_mux(struct > >> snd_soc_dapm_context *dapm, > >>> unsigned int val, item; > >>> int i; > >>> > >>> - if (e->reg != SND_SOC_NOPM) { > >>> - soc_widget_read(dest, e->reg, ); > >>> - val = (val >> e->shift_l) & e->mask; > >>> + if (e->reg[0] != SND_SOC_NOPM) { > >>> + soc_widget_read(dest, e->reg[0], ); > >>> + val = (val >> e->shift_l) & e->mask[0]; > >>> item = snd_soc_enum_val_to_item(e, val); > >> > >> This probably should handle the new enum type as well. You'll > >> probably need some kind of flag in the struct to distinguish between > >> the two enum types. > > > > Any suggestion on the flag name ? > > > > How about 'onehot'? > > [...] > >>> + reg_val = BIT(bit_pos); > >>> + } > >>> + > >>> + for (i = 0; i < e->num_regs; i++) { > >>> + if (i == reg_idx) { > >>> + change = snd_soc_test_bits(codec, e->reg[i], > >>> + e->mask[i], > >> reg_val); > >>> + > >>> + } else { > >>> + /* accumulate the change to update the DAPM > >> path > >>> + when none is selected */ > >>> + change += snd_soc_test_bits(codec, e->reg[i], > >>> + e->mask[i], 0); > >> > >> change |= > >> > >>> + > >>> + /* clear the register when not selected */ > >>> + snd_soc_write(codec, e->reg[i], 0); > >> > >> I think this should happen as part of the DAPM update sequence like > >> you had earlier. Some special care should probably be take to make > >> sure that you de-select the previous mux input before selecting the > >> new one if the new one is in a different register than the previous one. > > > > I am not sure I follow this part. We are clearing the 'not selected' > > registers before we set the one we want. Do you want us to loop the > > logic of soc_dapm_mux_update_power for each register ? or do you want > > to change the dapm_update structure so that it takes all the regs, > > masks, and values together ? > > The idea with the dapm_update struct is that the register updates are done > in the middle of the power-down and power-up sequence. So yes, change > the dapm_update struct to be able to hold all register updates and do all > register updates in dapm_widget_update. I think an earlier version of your > patch already had this. Is the change similar to as shown below? for (reg_idx = 0; reg_idx < e->num_regs; reg_idx++) { val = e->values[item * e->num_regs + reg_idx]; ret = snd_soc_update_bits_locked(codec, e->reg[reg_idx], e->mask[reg_idx], val); if (ret) return ret; } During updating of the register's value, the above change can create non-zero value in two different registers (very short transition) as Mark mentioned for that change so we need to clear register first before writing the desired value in the register. Should we add the clearing all registers and write the mux value in desired register in the update function? -- 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] ASoC: DAPM: Add support for multi register mux
On 04/01/2014 08:26 PM, Arun Shamanna Lakshmi wrote: [...] diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index c8a780d..4d2b35c 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -514,9 +514,9 @@ static int dapm_connect_mux(struct snd_soc_dapm_context *dapm, unsigned int val, item; int i; - if (e->reg != SND_SOC_NOPM) { - soc_widget_read(dest, e->reg, ); - val = (val >> e->shift_l) & e->mask; + if (e->reg[0] != SND_SOC_NOPM) { + soc_widget_read(dest, e->reg[0], ); + val = (val >> e->shift_l) & e->mask[0]; item = snd_soc_enum_val_to_item(e, val); This probably should handle the new enum type as well. You'll probably need some kind of flag in the struct to distinguish between the two enum types. Any suggestion on the flag name ? How about 'onehot'? [...] + reg_val = BIT(bit_pos); + } + + for (i = 0; i < e->num_regs; i++) { + if (i == reg_idx) { + change = snd_soc_test_bits(codec, e->reg[i], + e->mask[i], reg_val); + + } else { + /* accumulate the change to update the DAPM path + when none is selected */ + change += snd_soc_test_bits(codec, e->reg[i], + e->mask[i], 0); change |= + + /* clear the register when not selected */ + snd_soc_write(codec, e->reg[i], 0); I think this should happen as part of the DAPM update sequence like you had earlier. Some special care should probably be take to make sure that you de-select the previous mux input before selecting the new one if the new one is in a different register than the previous one. I am not sure I follow this part. We are clearing the 'not selected' registers before we set the one we want. Do you want us to loop the logic of soc_dapm_mux_update_power for each register ? or do you want to change the dapm_update structure so that it takes all the regs, masks, and values together ? The idea with the dapm_update struct is that the register updates are done in the middle of the power-down and power-up sequence. So yes, change the dapm_update struct to be able to hold all register updates and do all register updates in dapm_widget_update. I think an earlier version of your patch already had this. -- 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] ASoC: DAPM: Add support for multi register mux
On 04/01/2014 08:26 PM, Arun Shamanna Lakshmi wrote: [...] diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index c8a780d..4d2b35c 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -514,9 +514,9 @@ static int dapm_connect_mux(struct snd_soc_dapm_context *dapm, unsigned int val, item; int i; - if (e-reg != SND_SOC_NOPM) { - soc_widget_read(dest, e-reg, val); - val = (val e-shift_l) e-mask; + if (e-reg[0] != SND_SOC_NOPM) { + soc_widget_read(dest, e-reg[0], val); + val = (val e-shift_l) e-mask[0]; item = snd_soc_enum_val_to_item(e, val); This probably should handle the new enum type as well. You'll probably need some kind of flag in the struct to distinguish between the two enum types. Any suggestion on the flag name ? How about 'onehot'? [...] + reg_val = BIT(bit_pos); + } + + for (i = 0; i e-num_regs; i++) { + if (i == reg_idx) { + change = snd_soc_test_bits(codec, e-reg[i], + e-mask[i], reg_val); + + } else { + /* accumulate the change to update the DAPM path + when none is selected */ + change += snd_soc_test_bits(codec, e-reg[i], + e-mask[i], 0); change |= + + /* clear the register when not selected */ + snd_soc_write(codec, e-reg[i], 0); I think this should happen as part of the DAPM update sequence like you had earlier. Some special care should probably be take to make sure that you de-select the previous mux input before selecting the new one if the new one is in a different register than the previous one. I am not sure I follow this part. We are clearing the 'not selected' registers before we set the one we want. Do you want us to loop the logic of soc_dapm_mux_update_power for each register ? or do you want to change the dapm_update structure so that it takes all the regs, masks, and values together ? The idea with the dapm_update struct is that the register updates are done in the middle of the power-down and power-up sequence. So yes, change the dapm_update struct to be able to hold all register updates and do all register updates in dapm_widget_update. I think an earlier version of your patch already had this. -- 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] ASoC: DAPM: Add support for multi register mux
-Original Message- From: Lars-Peter Clausen [mailto:l...@metafoo.de] Sent: Tuesday, April 01, 2014 11:00 PM To: Arun Shamanna Lakshmi Cc: lgirdw...@gmail.com; broo...@kernel.org; swar...@wwwdotorg.org; pe...@perex.cz; ti...@suse.de; alsa-de...@alsa-project.org; linux- ker...@vger.kernel.org; Songhee Baek Subject: Re: [PATCH] ASoC: DAPM: Add support for multi register mux On 04/01/2014 08:26 PM, Arun Shamanna Lakshmi wrote: [...] diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index c8a780d..4d2b35c 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -514,9 +514,9 @@ static int dapm_connect_mux(struct snd_soc_dapm_context *dapm, unsigned int val, item; int i; - if (e-reg != SND_SOC_NOPM) { - soc_widget_read(dest, e-reg, val); - val = (val e-shift_l) e-mask; + if (e-reg[0] != SND_SOC_NOPM) { + soc_widget_read(dest, e-reg[0], val); + val = (val e-shift_l) e-mask[0]; item = snd_soc_enum_val_to_item(e, val); This probably should handle the new enum type as well. You'll probably need some kind of flag in the struct to distinguish between the two enum types. Any suggestion on the flag name ? How about 'onehot'? [...] + reg_val = BIT(bit_pos); + } + + for (i = 0; i e-num_regs; i++) { + if (i == reg_idx) { + change = snd_soc_test_bits(codec, e-reg[i], + e-mask[i], reg_val); + + } else { + /* accumulate the change to update the DAPM path + when none is selected */ + change += snd_soc_test_bits(codec, e-reg[i], + e-mask[i], 0); change |= + + /* clear the register when not selected */ + snd_soc_write(codec, e-reg[i], 0); I think this should happen as part of the DAPM update sequence like you had earlier. Some special care should probably be take to make sure that you de-select the previous mux input before selecting the new one if the new one is in a different register than the previous one. I am not sure I follow this part. We are clearing the 'not selected' registers before we set the one we want. Do you want us to loop the logic of soc_dapm_mux_update_power for each register ? or do you want to change the dapm_update structure so that it takes all the regs, masks, and values together ? The idea with the dapm_update struct is that the register updates are done in the middle of the power-down and power-up sequence. So yes, change the dapm_update struct to be able to hold all register updates and do all register updates in dapm_widget_update. I think an earlier version of your patch already had this. Is the change similar to as shown below? for (reg_idx = 0; reg_idx e-num_regs; reg_idx++) { val = e-values[item * e-num_regs + reg_idx]; ret = snd_soc_update_bits_locked(codec, e-reg[reg_idx], e-mask[reg_idx], val); if (ret) return ret; } During updating of the register's value, the above change can create non-zero value in two different registers (very short transition) as Mark mentioned for that change so we need to clear register first before writing the desired value in the register. Should we add the clearing all registers and write the mux value in desired register in the update function? -- 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] ASoC: DAPM: Add support for multi register mux
On 04/02/2014 08:17 AM, Songhee Baek wrote: -Original Message- From: Lars-Peter Clausen [mailto:l...@metafoo.de] Sent: Tuesday, April 01, 2014 11:00 PM To: Arun Shamanna Lakshmi Cc: lgirdw...@gmail.com; broo...@kernel.org; swar...@wwwdotorg.org; pe...@perex.cz; ti...@suse.de; alsa-de...@alsa-project.org; linux- ker...@vger.kernel.org; Songhee Baek Subject: Re: [PATCH] ASoC: DAPM: Add support for multi register mux On 04/01/2014 08:26 PM, Arun Shamanna Lakshmi wrote: [...] diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index c8a780d..4d2b35c 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -514,9 +514,9 @@ static int dapm_connect_mux(struct snd_soc_dapm_context *dapm, unsigned int val, item; int i; - if (e-reg != SND_SOC_NOPM) { - soc_widget_read(dest, e-reg, val); - val = (val e-shift_l) e-mask; + if (e-reg[0] != SND_SOC_NOPM) { + soc_widget_read(dest, e-reg[0], val); + val = (val e-shift_l) e-mask[0]; item = snd_soc_enum_val_to_item(e, val); This probably should handle the new enum type as well. You'll probably need some kind of flag in the struct to distinguish between the two enum types. Any suggestion on the flag name ? How about 'onehot'? [...] + reg_val = BIT(bit_pos); + } + + for (i = 0; i e-num_regs; i++) { + if (i == reg_idx) { + change = snd_soc_test_bits(codec, e-reg[i], + e-mask[i], reg_val); + + } else { + /* accumulate the change to update the DAPM path + when none is selected */ + change += snd_soc_test_bits(codec, e-reg[i], + e-mask[i], 0); change |= + + /* clear the register when not selected */ + snd_soc_write(codec, e-reg[i], 0); I think this should happen as part of the DAPM update sequence like you had earlier. Some special care should probably be take to make sure that you de-select the previous mux input before selecting the new one if the new one is in a different register than the previous one. I am not sure I follow this part. We are clearing the 'not selected' registers before we set the one we want. Do you want us to loop the logic of soc_dapm_mux_update_power for each register ? or do you want to change the dapm_update structure so that it takes all the regs, masks, and values together ? The idea with the dapm_update struct is that the register updates are done in the middle of the power-down and power-up sequence. So yes, change the dapm_update struct to be able to hold all register updates and do all register updates in dapm_widget_update. I think an earlier version of your patch already had this. Is the change similar to as shown below? for (reg_idx = 0; reg_idx e-num_regs; reg_idx++) { val = e-values[item * e-num_regs + reg_idx]; ret = snd_soc_update_bits_locked(codec, e-reg[reg_idx], e-mask[reg_idx], val); if (ret) return ret; } During updating of the register's value, the above change can create non-zero value in two different registers (very short transition) as Mark mentioned for that change so we need to clear register first before writing the desired value in the register. Should we add the clearing all registers and write the mux value in desired register in the update function? In dapm_update_widget() you have this line: ret = soc_widget_update_bits(w, update-reg, update-mask, update-val); That needs to be done for every register update. When you setup the update struct you need to make sure that the register clears come before the register set. E.g. if you have register 0x3, 0x4, 0x5 and you select a bit in register 0x4 it should look like this. update-reg[0] = 0x3; update-val[0] = 0x0; update-reg[1] = 0x5; update-val[1] = 0x0; update-reg[2] = 0x4; update-val[2] = 0x8; When you set a bit in register 0x3 it should look like this: update-reg[0] = 0x4; update-val[0] = 0x0; update-reg[1] = 0x5; update-val[1] = 0x0; update-reg[2] = 0x3; update-val[2] = 0x1; So basically the write operation goes into update-reg[e-num_regs-1] the clear operations go into the other slots before that. - Lars -- 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] ASoC: DAPM: Add support for multi register mux
-Original Message- From: Lars-Peter Clausen [mailto:l...@metafoo.de] Sent: Tuesday, April 01, 2014 11:47 PM To: Songhee Baek Cc: Arun Shamanna Lakshmi; lgirdw...@gmail.com; broo...@kernel.org; swar...@wwwdotorg.org; pe...@perex.cz; ti...@suse.de; alsa- de...@alsa-project.org; linux-kernel@vger.kernel.org Subject: Re: [PATCH] ASoC: DAPM: Add support for multi register mux On 04/02/2014 08:17 AM, Songhee Baek wrote: -Original Message- From: Lars-Peter Clausen [mailto:l...@metafoo.de] Sent: Tuesday, April 01, 2014 11:00 PM To: Arun Shamanna Lakshmi Cc: lgirdw...@gmail.com; broo...@kernel.org; swar...@wwwdotorg.org; pe...@perex.cz; ti...@suse.de; alsa-de...@alsa-project.org; linux- ker...@vger.kernel.org; Songhee Baek Subject: Re: [PATCH] ASoC: DAPM: Add support for multi register mux On 04/01/2014 08:26 PM, Arun Shamanna Lakshmi wrote: [...] diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index c8a780d..4d2b35c 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -514,9 +514,9 @@ static int dapm_connect_mux(struct snd_soc_dapm_context *dapm, unsigned int val, item; int i; - if (e-reg != SND_SOC_NOPM) { - soc_widget_read(dest, e-reg, val); - val = (val e-shift_l) e-mask; + if (e-reg[0] != SND_SOC_NOPM) { + soc_widget_read(dest, e-reg[0], val); + val = (val e-shift_l) e-mask[0]; item = snd_soc_enum_val_to_item(e, val); This probably should handle the new enum type as well. You'll probably need some kind of flag in the struct to distinguish between the two enum types. Any suggestion on the flag name ? How about 'onehot'? [...] + reg_val = BIT(bit_pos); + } + + for (i = 0; i e-num_regs; i++) { + if (i == reg_idx) { + change = snd_soc_test_bits(codec, e-reg[i], + e-mask[i], reg_val); + + } else { + /* accumulate the change to update the DAPM path + when none is selected */ + change += snd_soc_test_bits(codec, e- reg[i], + e-mask[i], 0); change |= + + /* clear the register when not selected */ + snd_soc_write(codec, e-reg[i], 0); I think this should happen as part of the DAPM update sequence like you had earlier. Some special care should probably be take to make sure that you de-select the previous mux input before selecting the new one if the new one is in a different register than the previous one. I am not sure I follow this part. We are clearing the 'not selected' registers before we set the one we want. Do you want us to loop the logic of soc_dapm_mux_update_power for each register ? or do you want to change the dapm_update structure so that it takes all the regs, masks, and values together ? The idea with the dapm_update struct is that the register updates are done in the middle of the power-down and power-up sequence. So yes, change the dapm_update struct to be able to hold all register updates and do all register updates in dapm_widget_update. I think an earlier version of your patch already had this. Is the change similar to as shown below? for (reg_idx = 0; reg_idx e-num_regs; reg_idx++) { val = e-values[item * e-num_regs + reg_idx]; ret = snd_soc_update_bits_locked(codec, e-reg[reg_idx], e-mask[reg_idx], val); if (ret) return ret; } During updating of the register's value, the above change can create non-zero value in two different registers (very short transition) as Mark mentioned for that change so we need to clear register first before writing the desired value in the register. Should we add the clearing all registers and write the mux value in desired register in the update function? In dapm_update_widget() you have this line: ret = soc_widget_update_bits(w, update-reg, update-mask, update- val); That needs to be done for every register update. When you setup the update struct you need to make sure that the register clears come before the register set. E.g. if you have register 0x3, 0x4, 0x5 and you select a bit in register 0x4 it should look like this. update-reg[0] = 0x3; update-val[0] = 0x0; update-reg[1] = 0x5; update-val[1] = 0x0; update-reg[2] = 0x4; update-val[2] = 0x8; When you set a bit in register 0x3 it should look like this: update-reg[0] = 0x4; update-val[0] = 0x0; update-reg[1] = 0x5; update-val[1] = 0x0; update-reg[2] = 0x3; update-val[2] = 0x1; So basically the write operation goes into update-reg[e-num_regs-1] the clear operations go into the other slots before
Re: [PATCH] ASoC: DAPM: Add support for multi register mux
On 04/02/2014 08:56 AM, Songhee Baek wrote: -Original Message- From: Lars-Peter Clausen [mailto:l...@metafoo.de] Sent: Tuesday, April 01, 2014 11:47 PM To: Songhee Baek Cc: Arun Shamanna Lakshmi; lgirdw...@gmail.com; broo...@kernel.org; swar...@wwwdotorg.org; pe...@perex.cz; ti...@suse.de; alsa- de...@alsa-project.org; linux-kernel@vger.kernel.org Subject: Re: [PATCH] ASoC: DAPM: Add support for multi register mux On 04/02/2014 08:17 AM, Songhee Baek wrote: -Original Message- From: Lars-Peter Clausen [mailto:l...@metafoo.de] Sent: Tuesday, April 01, 2014 11:00 PM To: Arun Shamanna Lakshmi Cc: lgirdw...@gmail.com; broo...@kernel.org; swar...@wwwdotorg.org; pe...@perex.cz; ti...@suse.de; alsa-de...@alsa-project.org; linux- ker...@vger.kernel.org; Songhee Baek Subject: Re: [PATCH] ASoC: DAPM: Add support for multi register mux On 04/01/2014 08:26 PM, Arun Shamanna Lakshmi wrote: [...] diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index c8a780d..4d2b35c 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -514,9 +514,9 @@ static int dapm_connect_mux(struct snd_soc_dapm_context *dapm, unsigned int val, item; int i; - if (e-reg != SND_SOC_NOPM) { - soc_widget_read(dest, e-reg, val); - val = (val e-shift_l) e-mask; + if (e-reg[0] != SND_SOC_NOPM) { + soc_widget_read(dest, e-reg[0], val); + val = (val e-shift_l) e-mask[0]; item = snd_soc_enum_val_to_item(e, val); This probably should handle the new enum type as well. You'll probably need some kind of flag in the struct to distinguish between the two enum types. Any suggestion on the flag name ? How about 'onehot'? [...] + reg_val = BIT(bit_pos); + } + + for (i = 0; i e-num_regs; i++) { + if (i == reg_idx) { + change = snd_soc_test_bits(codec, e-reg[i], + e-mask[i], reg_val); + + } else { + /* accumulate the change to update the DAPM path + when none is selected */ + change += snd_soc_test_bits(codec, e- reg[i], + e-mask[i], 0); change |= + + /* clear the register when not selected */ + snd_soc_write(codec, e-reg[i], 0); I think this should happen as part of the DAPM update sequence like you had earlier. Some special care should probably be take to make sure that you de-select the previous mux input before selecting the new one if the new one is in a different register than the previous one. I am not sure I follow this part. We are clearing the 'not selected' registers before we set the one we want. Do you want us to loop the logic of soc_dapm_mux_update_power for each register ? or do you want to change the dapm_update structure so that it takes all the regs, masks, and values together ? The idea with the dapm_update struct is that the register updates are done in the middle of the power-down and power-up sequence. So yes, change the dapm_update struct to be able to hold all register updates and do all register updates in dapm_widget_update. I think an earlier version of your patch already had this. Is the change similar to as shown below? for (reg_idx = 0; reg_idx e-num_regs; reg_idx++) { val = e-values[item * e-num_regs + reg_idx]; ret = snd_soc_update_bits_locked(codec, e-reg[reg_idx], e-mask[reg_idx], val); if (ret) return ret; } During updating of the register's value, the above change can create non-zero value in two different registers (very short transition) as Mark mentioned for that change so we need to clear register first before writing the desired value in the register. Should we add the clearing all registers and write the mux value in desired register in the update function? In dapm_update_widget() you have this line: ret = soc_widget_update_bits(w, update-reg, update-mask, update- val); That needs to be done for every register update. When you setup the update struct you need to make sure that the register clears come before the register set. E.g. if you have register 0x3, 0x4, 0x5 and you select a bit in register 0x4 it should look like this. update-reg[0] = 0x3; update-val[0] = 0x0; update-reg[1] = 0x5; update-val[1] = 0x0; update-reg[2] = 0x4; update-val[2] = 0x8; When you set a bit in register 0x3 it should look like this: update-reg[0] = 0x4; update-val[0] = 0x0; update-reg[1] = 0x5; update-val[1] = 0x0; update-reg[2] = 0x3; update-val[2] = 0x1; So basically the write operation goes into update-reg[e-num_regs-1] the clear operations go into the other slots before that. Does update reg/val array have the writing sequence, is it correct? And can I assume that update struct has reg/val
RE: [PATCH] ASoC: DAPM: Add support for multi register mux
-Original Message- From: Lars-Peter Clausen [mailto:l...@metafoo.de] Sent: Wednesday, April 02, 2014 12:02 AM To: Songhee Baek Cc: Arun Shamanna Lakshmi; lgirdw...@gmail.com; broo...@kernel.org; swar...@wwwdotorg.org; pe...@perex.cz; ti...@suse.de; alsa- de...@alsa-project.org; linux-kernel@vger.kernel.org Subject: Re: [PATCH] ASoC: DAPM: Add support for multi register mux On 04/02/2014 08:56 AM, Songhee Baek wrote: -Original Message- From: Lars-Peter Clausen [mailto:l...@metafoo.de] Sent: Tuesday, April 01, 2014 11:47 PM To: Songhee Baek Cc: Arun Shamanna Lakshmi; lgirdw...@gmail.com; broo...@kernel.org; swar...@wwwdotorg.org; pe...@perex.cz; ti...@suse.de; alsa- de...@alsa-project.org; linux-kernel@vger.kernel.org Subject: Re: [PATCH] ASoC: DAPM: Add support for multi register mux On 04/02/2014 08:17 AM, Songhee Baek wrote: -Original Message- From: Lars-Peter Clausen [mailto:l...@metafoo.de] Sent: Tuesday, April 01, 2014 11:00 PM To: Arun Shamanna Lakshmi Cc: lgirdw...@gmail.com; broo...@kernel.org; swar...@wwwdotorg.org; pe...@perex.cz; ti...@suse.de; alsa-de...@alsa-project.org; linux- ker...@vger.kernel.org; Songhee Baek Subject: Re: [PATCH] ASoC: DAPM: Add support for multi register mux On 04/01/2014 08:26 PM, Arun Shamanna Lakshmi wrote: [...] diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index c8a780d..4d2b35c 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -514,9 +514,9 @@ static int dapm_connect_mux(struct snd_soc_dapm_context *dapm, unsigned int val, item; int i; - if (e-reg != SND_SOC_NOPM) { - soc_widget_read(dest, e-reg, val); - val = (val e-shift_l) e-mask; + if (e-reg[0] != SND_SOC_NOPM) { + soc_widget_read(dest, e-reg[0], val); + val = (val e-shift_l) e-mask[0]; item = snd_soc_enum_val_to_item(e, val); This probably should handle the new enum type as well. You'll probably need some kind of flag in the struct to distinguish between the two enum types. Any suggestion on the flag name ? How about 'onehot'? [...] + reg_val = BIT(bit_pos); + } + + for (i = 0; i e-num_regs; i++) { + if (i == reg_idx) { + change = snd_soc_test_bits(codec, e-reg[i], + e-mask[i], reg_val); + + } else { + /* accumulate the change to update the DAPM path + when none is selected */ + change += snd_soc_test_bits(codec, e- reg[i], + e-mask[i], 0); change |= + + /* clear the register when not selected */ + snd_soc_write(codec, e-reg[i], 0); I think this should happen as part of the DAPM update sequence like you had earlier. Some special care should probably be take to make sure that you de-select the previous mux input before selecting the new one if the new one is in a different register than the previous one. I am not sure I follow this part. We are clearing the 'not selected' registers before we set the one we want. Do you want us to loop the logic of soc_dapm_mux_update_power for each register ? or do you want to change the dapm_update structure so that it takes all the regs, masks, and values together ? The idea with the dapm_update struct is that the register updates are done in the middle of the power-down and power-up sequence. So yes, change the dapm_update struct to be able to hold all register updates and do all register updates in dapm_widget_update. I think an earlier version of your patch already had this. Is the change similar to as shown below? for (reg_idx = 0; reg_idx e-num_regs; reg_idx++) { val = e-values[item * e-num_regs + reg_idx]; ret = snd_soc_update_bits_locked(codec, e-reg[reg_idx], e-mask[reg_idx], val); if (ret) return ret; } During updating of the register's value, the above change can create non-zero value in two different registers (very short transition) as Mark mentioned for that change so we need to clear register first before writing the desired value in the register. Should we add the clearing all registers and write the mux value in desired register in the update function? In dapm_update_widget() you have this line: ret = soc_widget_update_bits(w, update-reg, update-mask, update- val); That needs to be done for every register update. When you setup the update struct you need to make sure that the register clears come before the register set. E.g. if you have register 0x3, 0x4, 0x5 and you select a bit in register 0x4 it should look like this. update-reg[0] = 0x3; update-val[0] = 0x0
RE: [PATCH] ASoC: DAPM: Add support for multi register mux
-Original Message- From: Lars-Peter Clausen [mailto:l...@metafoo.de] Sent: Wednesday, April 02, 2014 12:02 AM To: Songhee Baek Cc: Arun Shamanna Lakshmi; lgirdw...@gmail.com; broo...@kernel.org; swar...@wwwdotorg.org; pe...@perex.cz; ti...@suse.de; alsa- de...@alsa-project.org; linux-kernel@vger.kernel.org Subject: Re: [PATCH] ASoC: DAPM: Add support for multi register mux On 04/02/2014 08:56 AM, Songhee Baek wrote: -Original Message- From: Lars-Peter Clausen [mailto:l...@metafoo.de] Sent: Tuesday, April 01, 2014 11:47 PM To: Songhee Baek Cc: Arun Shamanna Lakshmi; lgirdw...@gmail.com; broo...@kernel.org; swar...@wwwdotorg.org; pe...@perex.cz; ti...@suse.de; alsa- de...@alsa-project.org; linux-kernel@vger.kernel.org Subject: Re: [PATCH] ASoC: DAPM: Add support for multi register mux On 04/02/2014 08:17 AM, Songhee Baek wrote: -Original Message- From: Lars-Peter Clausen [mailto:l...@metafoo.de] Sent: Tuesday, April 01, 2014 11:00 PM To: Arun Shamanna Lakshmi Cc: lgirdw...@gmail.com; broo...@kernel.org; swar...@wwwdotorg.org; pe...@perex.cz; ti...@suse.de; alsa-de...@alsa-project.org; linux- ker...@vger.kernel.org; Songhee Baek Subject: Re: [PATCH] ASoC: DAPM: Add support for multi register mux On 04/01/2014 08:26 PM, Arun Shamanna Lakshmi wrote: [...] diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index c8a780d..4d2b35c 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -514,9 +514,9 @@ static int dapm_connect_mux(struct snd_soc_dapm_context *dapm, unsigned int val, item; int i; - if (e-reg != SND_SOC_NOPM) { - soc_widget_read(dest, e-reg, val); - val = (val e-shift_l) e-mask; + if (e-reg[0] != SND_SOC_NOPM) { + soc_widget_read(dest, e-reg[0], val); + val = (val e-shift_l) e-mask[0]; item = snd_soc_enum_val_to_item(e, val); This probably should handle the new enum type as well. You'll probably need some kind of flag in the struct to distinguish between the two enum types. Any suggestion on the flag name ? How about 'onehot'? [...] + reg_val = BIT(bit_pos); + } + + for (i = 0; i e-num_regs; i++) { + if (i == reg_idx) { + change = snd_soc_test_bits(codec, e-reg[i], + e-mask[i], reg_val); + + } else { + /* accumulate the change to update the DAPM path + when none is selected */ + change += snd_soc_test_bits(codec, e- reg[i], + e-mask[i], 0); change |= + + /* clear the register when not selected */ + snd_soc_write(codec, e-reg[i], 0); I think this should happen as part of the DAPM update sequence like you had earlier. Some special care should probably be take to make sure that you de-select the previous mux input before selecting the new one if the new one is in a different register than the previous one. I am not sure I follow this part. We are clearing the 'not selected' registers before we set the one we want. Do you want us to loop the logic of soc_dapm_mux_update_power for each register ? or do you want to change the dapm_update structure so that it takes all the regs, masks, and values together ? The idea with the dapm_update struct is that the register updates are done in the middle of the power-down and power-up sequence. So yes, change the dapm_update struct to be able to hold all register updates and do all register updates in dapm_widget_update. I think an earlier version of your patch already had this. Is the change similar to as shown below? for (reg_idx = 0; reg_idx e-num_regs; reg_idx++) { val = e-values[item * e-num_regs + reg_idx]; ret = snd_soc_update_bits_locked(codec, e-reg[reg_idx], e-mask[reg_idx], val); if (ret) return ret; } During updating of the register's value, the above change can create non-zero value in two different registers (very short transition) as Mark mentioned for that change so we need to clear register first before writing the desired value in the register. Should we add the clearing all registers and write the mux value in desired register in the update function? In dapm_update_widget() you have this line: ret = soc_widget_update_bits(w, update-reg, update-mask, update- val); That needs to be done for every register update. When you setup the update struct you need to make sure that the register clears come before the register set. E.g. if you have register 0x3, 0x4, 0x5 and you select a bit in register 0x4 it should look like this. update-reg[0] = 0x3; update-val[0] = 0x0
Re: [PATCH] ASoC: DAPM: Add support for multi register mux
On 04/02/2014 05:26 PM, Songhee Baek wrote: -Original Message- From: Lars-Peter Clausen [mailto:l...@metafoo.de] Sent: Wednesday, April 02, 2014 12:02 AM To: Songhee Baek Cc: Arun Shamanna Lakshmi; lgirdw...@gmail.com; broo...@kernel.org; swar...@wwwdotorg.org; pe...@perex.cz; ti...@suse.de; alsa- de...@alsa-project.org; linux-kernel@vger.kernel.org Subject: Re: [PATCH] ASoC: DAPM: Add support for multi register mux On 04/02/2014 08:56 AM, Songhee Baek wrote: -Original Message- From: Lars-Peter Clausen [mailto:l...@metafoo.de] Sent: Tuesday, April 01, 2014 11:47 PM To: Songhee Baek Cc: Arun Shamanna Lakshmi; lgirdw...@gmail.com; broo...@kernel.org; swar...@wwwdotorg.org; pe...@perex.cz; ti...@suse.de; alsa- de...@alsa-project.org; linux-kernel@vger.kernel.org Subject: Re: [PATCH] ASoC: DAPM: Add support for multi register mux On 04/02/2014 08:17 AM, Songhee Baek wrote: -Original Message- From: Lars-Peter Clausen [mailto:l...@metafoo.de] Sent: Tuesday, April 01, 2014 11:00 PM To: Arun Shamanna Lakshmi Cc: lgirdw...@gmail.com; broo...@kernel.org; swar...@wwwdotorg.org; pe...@perex.cz; ti...@suse.de; alsa-de...@alsa-project.org; linux- ker...@vger.kernel.org; Songhee Baek Subject: Re: [PATCH] ASoC: DAPM: Add support for multi register mux On 04/01/2014 08:26 PM, Arun Shamanna Lakshmi wrote: [...] diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index c8a780d..4d2b35c 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -514,9 +514,9 @@ static int dapm_connect_mux(struct snd_soc_dapm_context *dapm, unsigned int val, item; int i; - if (e-reg != SND_SOC_NOPM) { - soc_widget_read(dest, e-reg, val); - val = (val e-shift_l) e-mask; + if (e-reg[0] != SND_SOC_NOPM) { + soc_widget_read(dest, e-reg[0], val); + val = (val e-shift_l) e-mask[0]; item = snd_soc_enum_val_to_item(e, val); This probably should handle the new enum type as well. You'll probably need some kind of flag in the struct to distinguish between the two enum types. Any suggestion on the flag name ? How about 'onehot'? [...] + reg_val = BIT(bit_pos); + } + + for (i = 0; i e-num_regs; i++) { + if (i == reg_idx) { + change = snd_soc_test_bits(codec, e-reg[i], + e-mask[i], reg_val); + + } else { + /* accumulate the change to update the DAPM path + when none is selected */ + change += snd_soc_test_bits(codec, e- reg[i], + e-mask[i], 0); change |= + + /* clear the register when not selected */ + snd_soc_write(codec, e-reg[i], 0); I think this should happen as part of the DAPM update sequence like you had earlier. Some special care should probably be take to make sure that you de-select the previous mux input before selecting the new one if the new one is in a different register than the previous one. I am not sure I follow this part. We are clearing the 'not selected' registers before we set the one we want. Do you want us to loop the logic of soc_dapm_mux_update_power for each register ? or do you want to change the dapm_update structure so that it takes all the regs, masks, and values together ? The idea with the dapm_update struct is that the register updates are done in the middle of the power-down and power-up sequence. So yes, change the dapm_update struct to be able to hold all register updates and do all register updates in dapm_widget_update. I think an earlier version of your patch already had this. Is the change similar to as shown below? for (reg_idx = 0; reg_idx e-num_regs; reg_idx++) { val = e-values[item * e-num_regs + reg_idx]; ret = snd_soc_update_bits_locked(codec, e-reg[reg_idx], e-mask[reg_idx], val); if (ret) return ret; } During updating of the register's value, the above change can create non-zero value in two different registers (very short transition) as Mark mentioned for that change so we need to clear register first before writing the desired value in the register. Should we add the clearing all registers and write the mux value in desired register in the update function? In dapm_update_widget() you have this line: ret = soc_widget_update_bits(w, update-reg, update-mask, update- val); That needs to be done for every register update. When you setup the update struct you need to make sure that the register clears come before the register set. E.g. if you have register 0x3, 0x4, 0x5 and you select a bit in register 0x4 it should look like this. update-reg[0] = 0x3; update-val[0] = 0x0; update-reg[1] = 0x5; update-val[1] = 0x0; update-reg[2] = 0x4; update-val[2] = 0x8
RE: [PATCH] ASoC: DAPM: Add support for multi register mux
> -Original Message- > From: Lars-Peter Clausen [mailto:l...@metafoo.de] > Sent: Tuesday, April 01, 2014 12:48 AM > To: Arun Shamanna Lakshmi > Cc: lgirdw...@gmail.com; broo...@kernel.org; swar...@wwwdotorg.org; > pe...@perex.cz; ti...@suse.de; alsa- de...@alsa-project.org; > linux-kernel@vger.kernel.org; Songhee Baek > Subject: Re: [PATCH] ASoC: DAPM: Add support for multi register mux > > On 04/01/2014 08:21 AM, Arun Shamanna Lakshmi wrote: > > Modify soc_enum struct to handle pointers for reg and mask. Add dapm > > get and put APIs for multi register mux with one hot encoding. > > > > Signed-off-by: Arun Shamanna Lakshmi > > Signed-off-by: Songhee Baek > > Looks in my opinion much better than the previous version :) Just a > few minor issues, comments inline > > > --- > > include/sound/soc-dapm.h | 10 > > include/sound/soc.h | 22 +-- > > sound/soc/soc-core.c | 12 ++-- > > sound/soc/soc-dapm.c | 143 > +- > > 4 files changed, 162 insertions(+), 25 deletions(-) > > > > diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h > index > > ef78f56..983b0ab 100644 > > --- a/include/sound/soc-dapm.h > > +++ b/include/sound/soc-dapm.h > > @@ -305,6 +305,12 @@ struct device; > > .get = snd_soc_dapm_get_enum_double, \ > > .put = snd_soc_dapm_put_enum_double, \ > > .private_value = (unsigned long) } > > +#define SOC_DAPM_ENUM_WIDE(xname, xenum) \ > > maybe just call it ENUM_ONEHOT, since it doesn't actually have to be > more than one register. > > [...] > > diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index > > cd52d52..aba0094 100644 > > --- a/sound/soc/soc-core.c > > +++ b/sound/soc/soc-core.c > > @@ -2601,12 +2601,12 @@ int snd_soc_get_enum_double(struct > snd_kcontrol *kcontrol, > > unsigned int val, item; > > unsigned int reg_val; > > > > - reg_val = snd_soc_read(codec, e->reg); > > - val = (reg_val >> e->shift_l) & e->mask; > > + reg_val = snd_soc_read(codec, e->reg[0]); > > + val = (reg_val >> e->shift_l) & e->mask[0]; > > item = snd_soc_enum_val_to_item(e, val); > > ucontrol->value.enumerated.item[0] = item; > > if (e->shift_l != e->shift_r) { > > - val = (reg_val >> e->shift_l) & e->mask; > > + val = (reg_val >> e->shift_l) & e->mask[0]; > > item = snd_soc_enum_val_to_item(e, val); > > ucontrol->value.enumerated.item[1] = item; > > } > > @@ -2636,15 +2636,15 @@ int snd_soc_put_enum_double(struct > snd_kcontrol *kcontrol, > > if (item[0] >= e->items) > > return -EINVAL; > > val = snd_soc_enum_item_to_val(e, item[0]) << e->shift_l; > > - mask = e->mask << e->shift_l; > > + mask = e->mask[0] << e->shift_l; > > if (e->shift_l != e->shift_r) { > > if (item[1] >= e->items) > > return -EINVAL; > > val |= snd_soc_enum_item_to_val(e, item[1]) << e- shift_r; > > - mask |= e->mask << e->shift_r; > > + mask |= e->mask[0] << e->shift_r; > > } > > > > - return snd_soc_update_bits_locked(codec, e->reg, mask, val); > > + return snd_soc_update_bits_locked(codec, e->reg[0], mask, val); > > } > > EXPORT_SYMBOL_GPL(snd_soc_put_enum_double); > > > > diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index > > c8a780d..4d2b35c 100644 > > --- a/sound/soc/soc-dapm.c > > +++ b/sound/soc/soc-dapm.c > > @@ -514,9 +514,9 @@ static int dapm_connect_mux(struct > snd_soc_dapm_context *dapm, > > unsigned int val, item; > > int i; > > > > - if (e->reg != SND_SOC_NOPM) { > > - soc_widget_read(dest, e->reg, ); > > - val = (val >> e->shift_l) & e->mask; > > + if (e->reg[0] != SND_SOC_NOPM) { > > + soc_widget_read(dest, e->reg[0], ); > > + val = (val >> e->shift_l) & e->mask[0]; > > item = snd_soc_enum_val_to_item(e, val); > > This probably should handle the new enum type as well. You'll probably > need some kind of flag in the struct to distinguish between the two > enum types. Any suggestion on the flag name ? > > > } else { > > /* since a virtual mux has no backing registers to > [
Re: [PATCH] ASoC: DAPM: Add support for multi register mux
On 04/01/2014 08:21 AM, Arun Shamanna Lakshmi wrote: Modify soc_enum struct to handle pointers for reg and mask. Add dapm get and put APIs for multi register mux with one hot encoding. Signed-off-by: Arun Shamanna Lakshmi Signed-off-by: Songhee Baek Looks in my opinion much better than the previous version :) Just a few minor issues, comments inline --- include/sound/soc-dapm.h | 10 include/sound/soc.h | 22 +-- sound/soc/soc-core.c | 12 ++-- sound/soc/soc-dapm.c | 143 +- 4 files changed, 162 insertions(+), 25 deletions(-) diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index ef78f56..983b0ab 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -305,6 +305,12 @@ struct device; .get = snd_soc_dapm_get_enum_double, \ .put = snd_soc_dapm_put_enum_double, \ .private_value = (unsigned long) } +#define SOC_DAPM_ENUM_WIDE(xname, xenum) \ maybe just call it ENUM_ONEHOT, since it doesn't actually have to be more than one register. [...] diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index cd52d52..aba0094 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2601,12 +2601,12 @@ int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol, unsigned int val, item; unsigned int reg_val; - reg_val = snd_soc_read(codec, e->reg); - val = (reg_val >> e->shift_l) & e->mask; + reg_val = snd_soc_read(codec, e->reg[0]); + val = (reg_val >> e->shift_l) & e->mask[0]; item = snd_soc_enum_val_to_item(e, val); ucontrol->value.enumerated.item[0] = item; if (e->shift_l != e->shift_r) { - val = (reg_val >> e->shift_l) & e->mask; + val = (reg_val >> e->shift_l) & e->mask[0]; item = snd_soc_enum_val_to_item(e, val); ucontrol->value.enumerated.item[1] = item; } @@ -2636,15 +2636,15 @@ int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol, if (item[0] >= e->items) return -EINVAL; val = snd_soc_enum_item_to_val(e, item[0]) << e->shift_l; - mask = e->mask << e->shift_l; + mask = e->mask[0] << e->shift_l; if (e->shift_l != e->shift_r) { if (item[1] >= e->items) return -EINVAL; val |= snd_soc_enum_item_to_val(e, item[1]) << e->shift_r; - mask |= e->mask << e->shift_r; + mask |= e->mask[0] << e->shift_r; } - return snd_soc_update_bits_locked(codec, e->reg, mask, val); + return snd_soc_update_bits_locked(codec, e->reg[0], mask, val); } EXPORT_SYMBOL_GPL(snd_soc_put_enum_double); diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index c8a780d..4d2b35c 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -514,9 +514,9 @@ static int dapm_connect_mux(struct snd_soc_dapm_context *dapm, unsigned int val, item; int i; - if (e->reg != SND_SOC_NOPM) { - soc_widget_read(dest, e->reg, ); - val = (val >> e->shift_l) & e->mask; + if (e->reg[0] != SND_SOC_NOPM) { + soc_widget_read(dest, e->reg[0], ); + val = (val >> e->shift_l) & e->mask[0]; item = snd_soc_enum_val_to_item(e, val); This probably should handle the new enum type as well. You'll probably need some kind of flag in the struct to distinguish between the two enum types. } else { /* since a virtual mux has no backing registers to [...] /** + * snd_soc_dapm_get_enum_wide - dapm semi enumerated multiple registers What's a semi-enumerated register? + * mixer get callback + * @kcontrol: mixer control + * @ucontrol: control element information + * + * Callback to get the value of a dapm semi enumerated multiple register mixer + * control. + * + * semi enumerated multiple registers mixer: + * the mixer has multiple registers to set the enumerated items. The enumerated + * items are referred as values. + * Can be used for handling bit field coded enumeration for example. + * + * Returns 0 for success. + */ +int snd_soc_dapm_get_enum_wide(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + unsigned int reg_val, val, bit_pos = 0, reg_idx; + + for (reg_idx = 0; reg_idx < e->num_regs; reg_idx++) { + reg_val = snd_soc_read(codec, e->reg[reg_idx]); + val = reg_val & e->mask[reg_idx]; + if (val != 0) { + bit_pos = ffs(val) + (e->reg_width * reg_idx); Should be __ffs. __ffs returns the bits zero-indexed and ffs one-indexed. That will work better for cases where there is not
Re: [PATCH] ASoC: DAPM: Add support for multi register mux
On 04/01/2014 08:21 AM, Arun Shamanna Lakshmi wrote: Modify soc_enum struct to handle pointers for reg and mask. Add dapm get and put APIs for multi register mux with one hot encoding. Signed-off-by: Arun Shamanna Lakshmi ar...@nvidia.com Signed-off-by: Songhee Baek sb...@nvidia.com Looks in my opinion much better than the previous version :) Just a few minor issues, comments inline --- include/sound/soc-dapm.h | 10 include/sound/soc.h | 22 +-- sound/soc/soc-core.c | 12 ++-- sound/soc/soc-dapm.c | 143 +- 4 files changed, 162 insertions(+), 25 deletions(-) diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index ef78f56..983b0ab 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -305,6 +305,12 @@ struct device; .get = snd_soc_dapm_get_enum_double, \ .put = snd_soc_dapm_put_enum_double, \ .private_value = (unsigned long)xenum } +#define SOC_DAPM_ENUM_WIDE(xname, xenum) \ maybe just call it ENUM_ONEHOT, since it doesn't actually have to be more than one register. [...] diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index cd52d52..aba0094 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2601,12 +2601,12 @@ int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol, unsigned int val, item; unsigned int reg_val; - reg_val = snd_soc_read(codec, e-reg); - val = (reg_val e-shift_l) e-mask; + reg_val = snd_soc_read(codec, e-reg[0]); + val = (reg_val e-shift_l) e-mask[0]; item = snd_soc_enum_val_to_item(e, val); ucontrol-value.enumerated.item[0] = item; if (e-shift_l != e-shift_r) { - val = (reg_val e-shift_l) e-mask; + val = (reg_val e-shift_l) e-mask[0]; item = snd_soc_enum_val_to_item(e, val); ucontrol-value.enumerated.item[1] = item; } @@ -2636,15 +2636,15 @@ int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol, if (item[0] = e-items) return -EINVAL; val = snd_soc_enum_item_to_val(e, item[0]) e-shift_l; - mask = e-mask e-shift_l; + mask = e-mask[0] e-shift_l; if (e-shift_l != e-shift_r) { if (item[1] = e-items) return -EINVAL; val |= snd_soc_enum_item_to_val(e, item[1]) e-shift_r; - mask |= e-mask e-shift_r; + mask |= e-mask[0] e-shift_r; } - return snd_soc_update_bits_locked(codec, e-reg, mask, val); + return snd_soc_update_bits_locked(codec, e-reg[0], mask, val); } EXPORT_SYMBOL_GPL(snd_soc_put_enum_double); diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index c8a780d..4d2b35c 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -514,9 +514,9 @@ static int dapm_connect_mux(struct snd_soc_dapm_context *dapm, unsigned int val, item; int i; - if (e-reg != SND_SOC_NOPM) { - soc_widget_read(dest, e-reg, val); - val = (val e-shift_l) e-mask; + if (e-reg[0] != SND_SOC_NOPM) { + soc_widget_read(dest, e-reg[0], val); + val = (val e-shift_l) e-mask[0]; item = snd_soc_enum_val_to_item(e, val); This probably should handle the new enum type as well. You'll probably need some kind of flag in the struct to distinguish between the two enum types. } else { /* since a virtual mux has no backing registers to [...] /** + * snd_soc_dapm_get_enum_wide - dapm semi enumerated multiple registers What's a semi-enumerated register? + * mixer get callback + * @kcontrol: mixer control + * @ucontrol: control element information + * + * Callback to get the value of a dapm semi enumerated multiple register mixer + * control. + * + * semi enumerated multiple registers mixer: + * the mixer has multiple registers to set the enumerated items. The enumerated + * items are referred as values. + * Can be used for handling bit field coded enumeration for example. + * + * Returns 0 for success. + */ +int snd_soc_dapm_get_enum_wide(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); + struct soc_enum *e = (struct soc_enum *)kcontrol-private_value; + unsigned int reg_val, val, bit_pos = 0, reg_idx; + + for (reg_idx = 0; reg_idx e-num_regs; reg_idx++) { + reg_val = snd_soc_read(codec, e-reg[reg_idx]); + val = reg_val e-mask[reg_idx]; + if (val != 0) { + bit_pos = ffs(val) + (e-reg_width * reg_idx); Should be __ffs. __ffs returns the bits zero-indexed and ffs one-indexed. That will work better for cases where there is not additional value table necessary, since it
RE: [PATCH] ASoC: DAPM: Add support for multi register mux
-Original Message- From: Lars-Peter Clausen [mailto:l...@metafoo.de] Sent: Tuesday, April 01, 2014 12:48 AM To: Arun Shamanna Lakshmi Cc: lgirdw...@gmail.com; broo...@kernel.org; swar...@wwwdotorg.org; pe...@perex.cz; ti...@suse.de; alsa- de...@alsa-project.org; linux-kernel@vger.kernel.org; Songhee Baek Subject: Re: [PATCH] ASoC: DAPM: Add support for multi register mux On 04/01/2014 08:21 AM, Arun Shamanna Lakshmi wrote: Modify soc_enum struct to handle pointers for reg and mask. Add dapm get and put APIs for multi register mux with one hot encoding. Signed-off-by: Arun Shamanna Lakshmi ar...@nvidia.com Signed-off-by: Songhee Baek sb...@nvidia.com Looks in my opinion much better than the previous version :) Just a few minor issues, comments inline --- include/sound/soc-dapm.h | 10 include/sound/soc.h | 22 +-- sound/soc/soc-core.c | 12 ++-- sound/soc/soc-dapm.c | 143 +- 4 files changed, 162 insertions(+), 25 deletions(-) diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index ef78f56..983b0ab 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -305,6 +305,12 @@ struct device; .get = snd_soc_dapm_get_enum_double, \ .put = snd_soc_dapm_put_enum_double, \ .private_value = (unsigned long)xenum } +#define SOC_DAPM_ENUM_WIDE(xname, xenum) \ maybe just call it ENUM_ONEHOT, since it doesn't actually have to be more than one register. [...] diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index cd52d52..aba0094 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2601,12 +2601,12 @@ int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol, unsigned int val, item; unsigned int reg_val; - reg_val = snd_soc_read(codec, e-reg); - val = (reg_val e-shift_l) e-mask; + reg_val = snd_soc_read(codec, e-reg[0]); + val = (reg_val e-shift_l) e-mask[0]; item = snd_soc_enum_val_to_item(e, val); ucontrol-value.enumerated.item[0] = item; if (e-shift_l != e-shift_r) { - val = (reg_val e-shift_l) e-mask; + val = (reg_val e-shift_l) e-mask[0]; item = snd_soc_enum_val_to_item(e, val); ucontrol-value.enumerated.item[1] = item; } @@ -2636,15 +2636,15 @@ int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol, if (item[0] = e-items) return -EINVAL; val = snd_soc_enum_item_to_val(e, item[0]) e-shift_l; - mask = e-mask e-shift_l; + mask = e-mask[0] e-shift_l; if (e-shift_l != e-shift_r) { if (item[1] = e-items) return -EINVAL; val |= snd_soc_enum_item_to_val(e, item[1]) e- shift_r; - mask |= e-mask e-shift_r; + mask |= e-mask[0] e-shift_r; } - return snd_soc_update_bits_locked(codec, e-reg, mask, val); + return snd_soc_update_bits_locked(codec, e-reg[0], mask, val); } EXPORT_SYMBOL_GPL(snd_soc_put_enum_double); diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index c8a780d..4d2b35c 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -514,9 +514,9 @@ static int dapm_connect_mux(struct snd_soc_dapm_context *dapm, unsigned int val, item; int i; - if (e-reg != SND_SOC_NOPM) { - soc_widget_read(dest, e-reg, val); - val = (val e-shift_l) e-mask; + if (e-reg[0] != SND_SOC_NOPM) { + soc_widget_read(dest, e-reg[0], val); + val = (val e-shift_l) e-mask[0]; item = snd_soc_enum_val_to_item(e, val); This probably should handle the new enum type as well. You'll probably need some kind of flag in the struct to distinguish between the two enum types. Any suggestion on the flag name ? } else { /* since a virtual mux has no backing registers to [...] /** + * snd_soc_dapm_get_enum_wide - dapm semi enumerated multiple + registers What's a semi-enumerated register? + * mixer get callback + * @kcontrol: mixer control + * @ucontrol: control element information + * + * Callback to get the value of a dapm semi enumerated multiple +register mixer + * control. + * + * semi enumerated multiple registers mixer: + * the mixer has multiple registers to set the enumerated items. +The enumerated + * items are referred as values. + * Can be used for handling bit field coded enumeration for example. + * + * Returns 0 for success. + */ +int snd_soc_dapm_get_enum_wide(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { + struct snd_soc_codec *codec = snd_soc_dapm_kcontrol_codec(kcontrol); + struct soc_enum *e = (struct soc_enum *)kcontrol- private_value; + unsigned int reg_val, val, bit_pos = 0, reg_idx