All of lore.kernel.org
 help / color / mirror / Atom feed
From: Peter Ujfalusi <peter.ujfalusi@ti.com>
To: "Benoît Thébaudeau" <benoit.thebaudeau.dev@gmail.com>
Cc: Jyri Sarha <jsarha@ti.com>,
	linux-omap@vger.kernel.org,
	Alsa-devel <alsa-devel@alsa-project.org>,
	devicetree@vger.kernel.org, broonie@kernel.org,
	liam.r.girdwood@linux.intel.com, wlear@appliedlogix.com
Subject: Re: [PATCH v2] ASoC: tlv320aic3x: Add support for tlv320aic3104
Date: Wed, 4 Feb 2015 14:35:39 +0200	[thread overview]
Message-ID: <54D2121B.3030200@ti.com> (raw)
In-Reply-To: <CA+sos7_kRHru5_AZcVyhzYHtA3JkdcRVfq=bT3X=bMWjFvrd=Q@mail.gmail.com>

On 02/04/2015 01:11 PM, Benoît Thébaudeau wrote:
> Dear Peter Ujfalusi,
> 
> On Wed, Feb 4, 2015 at 11:02 AM, Peter Ujfalusi <peter.ujfalusi@ti.com> wrote:
>> On 02/04/2015 11:33 AM, Benoît Thébaudeau wrote:
>>> What I meant was to do the following instead:
>>>
>>> /*
>>>  * ADC PGA mix input volumes. From -12 to 0 dB in 1.5 dB steps. Disconnected
>>>  * below -12 dB
>>>  */
>>> static const DECLARE_TLV_DB_SCALE(mix_tlv, -1350, 150, 1);
>>>
>>> /* Left PGA Mixer for tlv320aic3104 */
>>> static const struct snd_kcontrol_new aic3104_left_pga_mixer_controls[] = {
>>>     SOC_DAPM_SINGLE_MUT_TLV("Line1L Volume",
>>>                 LINE1L_2_LADC_CTRL, 3, 7, 15, 1, mix_tlv),
>>
>> You mean SOC_DAPM_SINGLE_TLV() ?
> 
> No. It would not fit our needs here.
> 
>> There is no _MUT_ variant AFAIK.
> 
> Indeed, but support could be added, for it, something like (might need
> updating and some other changes in DAPM):
> 
> #define SOC_DAPM_SINGLE_MUT_TLV(xname, reg, shift, min, max, invert,
> tlv_array) \
> {    .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
>     .info = snd_soc_info_volsw_mut, \
>     .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | SNDRV_CTL_ELEM_ACCESS_READWRITE,\
>     .tlv.p = (tlv_array), \
>     .get = snd_soc_dapm_get_volsw_mut, .put = snd_soc_dapm_put_volsw_mut, \
>     .private_value = SOC_SINGLE_MUT_VALUE(reg, shift, min, max, invert) }

We would need more than this for aic3x driver. Something which handles:
valid field values: 0 - 8 (inverted or not)
Plus when mute is asked we should write 0xf (mute value)
0b1001 - 0b1110 is reserved value on all codecs.

#define SOC_DAPM_SINGLE_MUT_TLV(xname, reg, shift, min, max, mute_val,
				invert, tlv_array)

> /**
>  * snd_soc_dapm_get_volsw_mut - dapm mixer get callback
>  * @kcontrol: mixer control
>  * @ucontrol: control element information
>  *
>  * Callback to get the value of a dapm mixer control with a hole separating the
>  * mute value from the other valid values.
>  *
>  * Returns 0 for success.
>  */
> int snd_soc_dapm_get_volsw_mut(struct snd_kcontrol *kcontrol,
>     struct snd_ctl_elem_value *ucontrol)
> {
>     struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
>     struct snd_soc_dapm_widget *widget = wlist->widgets[0];
>     struct soc_mixer_control *mc =
>         (struct soc_mixer_control *)kcontrol->private_value;
>     unsigned int reg = mc->reg;
>     unsigned int shift = mc->shift;
>     unsigned int rshift = mc->rshift;
>     int min = mc->min;
>     int max = mc->max;
>     unsigned int invert = mc->invert;
>     unsigned int mask = (1 << fls(max)) - 1;
> 
>     ucontrol->value.integer.value[0] =
>         (snd_soc_read(widget->codec, reg) >> shift) & mask;
>     if (shift != rshift)
>         ucontrol->value.integer.value[1] =
>             (snd_soc_read(widget->codec, reg) >> rshift) & mask;
>     if (invert) {
>         ucontrol->value.integer.value[0] =
>             mask - ucontrol->value.integer.value[0];
>         if (shift != rshift)
>             ucontrol->value.integer.value[1] =
>                 mask - ucontrol->value.integer.value[1];
>     }
>     if (ucontrol->value.integer.value[0] > 0)
>         ucontrol->value.integer.value[0] -= min - 1;
>     if (shift != rshift)
>         if (ucontrol->value.integer.value[1] > 0)
>             ucontrol->value.integer.value[1] -= min - 1;
> 
>     return 0;
> }
> EXPORT_SYMBOL_GPL(snd_soc_dapm_get_volsw_mut);
> 
> /**
>  * snd_soc_dapm_put_volsw_mut - dapm mixer set callback
>  * @kcontrol: mixer control
>  * @ucontrol: control element information
>  *
>  * Callback to set the value of a dapm mixer control with a hole separating the
>  * mute value from the other valid values.
>  *
>  * Returns 0 for success.
>  */
> int snd_soc_dapm_put_volsw_mut(struct snd_kcontrol *kcontrol,
>     struct snd_ctl_elem_value *ucontrol)
> {
>     struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
>     struct snd_soc_dapm_widget *widget = wlist->widgets[0];
>     struct snd_soc_codec *codec = widget->codec;
>     struct soc_mixer_control *mc =
>         (struct soc_mixer_control *)kcontrol->private_value;
>     unsigned int reg = mc->reg;
>     unsigned int shift = mc->shift;
>     int min = mc->min;
>     int max = mc->max;
>     unsigned int mask = (1 << fls(max)) - 1;
>     unsigned int invert = mc->invert;
>     unsigned int val;
>     int connect, change;
>     struct snd_soc_dapm_update update;
>     int wi;
> 
>     val = (ucontrol->value.integer.value[0] & mask);
>     connect = !!val;
> 
>     if (val)
>         val += min - 1;
>     if (invert)
>         val = mask - val;
>     mask = mask << shift;
>     val = val << shift;
> 
>     mutex_lock(&codec->mutex);
> 
>     change = snd_soc_test_bits(widget->codec, reg, mask, val);
>     if (change) {
>         for (wi = 0; wi < wlist->num_widgets; wi++) {
>             widget = wlist->widgets[wi];
> 
>             widget->value = val;
> 
>             update.kcontrol = kcontrol;
>             update.widget = widget;
>             update.reg = reg;
>             update.mask = mask;
>             update.val = val;
>             widget->dapm->update = &update;
> 
>             dapm_mixer_update_power(widget, kcontrol, connect);
> 
>             widget->dapm->update = NULL;
>         }
>     }
> 
>     mutex_unlock(&codec->mutex);
>     return 0;
> }
> EXPORT_SYMBOL_GPL(snd_soc_dapm_put_volsw_mut);
> 
>> According to the datasheets of aic3106, aic3104:
>> 0b0000 - 0b1000 is valid (0 - -12 dB)
>> 0b1001 - 0b1110 is reserved, do not write these sequences to the register
>> 0b1111 is disconnected.
>>
>> And for fun the aic3007's reg20 for example:
>> 0b0000 - 0dB
>> 0b0001 - 0b0011 - reserved
>> 0b0100 - -6dB
>> 0b0101 - 0b0111 - reserved
>> 0b1000 - -12dB
>> 0b1001 - 0b1110 - reserved
>> 0b1111 - disconnected
>>
>> Note that the driver never had control for these gains and the aic3104 support
>> is following this behavior, but if we do it for aic3104 we should do it for
>> all other support codecs as well as a followup patch or series. IMHO.
> 
> I had not checked the other CODECs. So for all these CODECs, toggling
> either as 0b0000/0b0001 or as 0b1110/0b1111 (like the driver currently
> does) is wrong.

The driver toggles between 0b0000 and 0b1111 currently, which is correct:
# amixer sset 'Left PGA Mixer Line1L' off
snd_soc_dapm_put_volsw_aic3x 1: reg: 0x13, val: 0x00
snd_soc_dapm_put_volsw_aic3x 2: val: 0x78, mask: 0x78

# amixer sset 'Left PGA Mixer Line1L' on
snd_soc_dapm_put_volsw_aic3x 1: reg: 0x13, val: 0x01
snd_soc_dapm_put_volsw_aic3x 2: val: 0x00, mask: 0x78

> I agree that they should be fixed too. But for them,
> it's even more complicated because of the multiple reserved value
> ranges. Or maybe we could just ignore these reserved ranges and handle
> the mute value, but that would mean relying on the user not to use
> reserved values. So maybe use TLV_DB_RANGE_HEAD() and
> TLV_DB_SCALE_ITEM() to define mix_tlv, then use
> SOC_(DAPM_)SINGLE_TLV().

I myself also wondered time to time why the driver was written the way it has
been regarding to these gain controls.

-- 
Péter
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

  reply	other threads:[~2015-02-04 12:35 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-01-30 16:02 [PATCH] ASoC: tlv320aic3x: Add support for tlv320aic3104 Jyri Sarha
     [not found] ` <1422633743-11758-1-git-send-email-jsarha-l0cyMroinI0@public.gmane.org>
2015-02-02  7:52   ` Peter Ujfalusi
2015-02-02 14:48     ` [PATCH v2] " Jyri Sarha
2015-02-03 12:16       ` Mark Brown
     [not found]       ` <1422888485-13626-1-git-send-email-jsarha-l0cyMroinI0@public.gmane.org>
2015-02-03 22:25         ` Benoît Thébaudeau
2015-02-04  8:27           ` Peter Ujfalusi
     [not found]             ` <54D1D80F.1090304-l0cyMroinI0@public.gmane.org>
2015-02-04  9:33               ` Benoît Thébaudeau
     [not found]                 ` <CA+sos797a7CT2KqCwrW5CaL1vF0GVCHQGxp3gDAB7PTFi4jZjQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2015-02-04 10:02                   ` Peter Ujfalusi
     [not found]                     ` <54D1EE24.3000309-l0cyMroinI0@public.gmane.org>
2015-02-04 11:11                       ` Benoît Thébaudeau
2015-02-04 12:35                         ` Peter Ujfalusi [this message]
2015-02-04 13:30                           ` Benoît Thébaudeau

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=54D2121B.3030200@ti.com \
    --to=peter.ujfalusi@ti.com \
    --cc=alsa-devel@alsa-project.org \
    --cc=benoit.thebaudeau.dev@gmail.com \
    --cc=broonie@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=jsarha@ti.com \
    --cc=liam.r.girdwood@linux.intel.com \
    --cc=linux-omap@vger.kernel.org \
    --cc=wlear@appliedlogix.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.