On Tuesday 15 June 2010 16:53:23 ext Mark Brown wrote:
> On Tue, Jun 15, 2010 at 04:42:32PM +0300, Peter Ujfalusi wrote:
> > On Tuesday 15 June 2010 08:11:10 ext Stuart Longland wrote:
> > > Okay, I've had a close inspection of how the SOC_DOUBLE_R_SX_TLV
> > > widgets are implemented. I couldn't find where in the git trees the
> > > control had been added, I wound up applying this patch myself in my
> > > tree... it apparently got applied in the official trees, but I cannot
> > > find it.
> >
> > I'm not really sure what the SOC_DOUBLE_R_SX_TLV is for...
>> It's for value ranges which have normal unsigned integer mapping but
> where the zero point is not at the lowest value so you need to wrap
> around. Which isn't actually what Stuart is looking for...
I found the CS42L51 datasheet, and now it is clear what the _SX is doing.
> > But would a simple SOC_DOUBLE_R_TLV enough for the aic3204 codec?
> > I have not looked at the datasheet (if it is available), but I'll try to
> > find it.
> > Well looking at the _2r_sx functions in soc-core.c does not really clears
> > the intention, but at least I can see several things in the
> > snd_soc_put_volsw_2r_sx
>> ...and this won't work since Stuart is looking for something that does
> signed values which I don't think we have already, the standard stuff
> all wants unsigned quantities.
Yeah, the aic3204 needs signed values.
There is this _s8 things, which does signed, but never used, nor really checked
it.
> > - instead of updating the bits, it rewrites the register, which I think
> > will erase bits, which it should not touch.
>> It's just open coding the update bits so there's no actual problem here.
It might be so that I have overlooked something, but...
If the register has:
bit # Function
0 .. 6 : Gain
7 : Mute
Let say that the mute is set to one, and the user modifies the gain, than in the
function:
int snd_soc_put_volsw_2r_sx(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
unsigned int mask = (1<<mc->shift)-1;
/*
* mc->shift is 7, whiche means seven bits for the gain bit array
* mask == 0x7f (b0111 1111): it only covers the gain area
*/
int min = mc->min;
int ret;
unsigned int val, valr, oval, ovalr;
val = ((ucontrol->value.integer.value[0]+min) & 0xff);
val &= mask;
valr = ((ucontrol->value.integer.value[1]+min) & 0xff);
valr &= mask;
/*
* Here we make sure that the coming new value has only bits set withing the
* gain area, so we have b0xxx xxxx for the val, and valr
*/
oval = snd_soc_read(codec, mc->reg) & mask;
ovalr = snd_soc_read(codec, mc->rreg) & mask;
/*
* We read the content of the register, and taking only the bits, which is
* within the gain area: b0xxx xxxx
*/
ret = 0;
if (oval != val) {
/* Only update, if the gain in the chip is different than the new one */
ret = snd_soc_write(codec, mc->reg, val);
/*
* Write the val to the chip.
* Now, if the mute was set before it is going to be cleared, since the code has
* masked it out, the val only contains the updated bits for the gain part, the
* rest is 0.
* So if the user changes the volume, the mute bit is going to be erased.
*/
if (ret < 0)
return 0;
ret = 1;
}
if (ovalr != valr) {
ret = snd_soc_write(codec, mc->rreg, valr);
if (ret < 0)
return 0;
ret = 1;
}
return 0;
}
Have I missed something?
--
Péter