Skip to content

Commit

Permalink
ALSA: wss_lib: use wss mixer code instead of ad1848 one
Browse files Browse the repository at this point in the history
Use the wss mixer code and kill the ad1848 mixer code.

Signed-off-by: Krzysztof Helt <krzysztof.h1@wp.pl>
Reviewed-by: Rene Herman <rene.herman@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
  • Loading branch information
Krzysztof-H authored and perexg committed Aug 6, 2008
1 parent 811585e commit 5664daa
Show file tree
Hide file tree
Showing 8 changed files with 98 additions and 283 deletions.
1 change: 0 additions & 1 deletion include/sound/ad1848.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,5 @@ int snd_ad1848_create(struct snd_card *card,

int snd_ad1848_pcm(struct snd_wss *chip, int device, struct snd_pcm **rpcm);
const struct snd_pcm_ops *snd_ad1848_get_pcm_ops(int direction);
int snd_ad1848_mixer(struct snd_wss *chip);

#endif /* __SOUND_AD1848_H */
25 changes: 25 additions & 0 deletions include/sound/wss.h
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,31 @@ int snd_wss_put_single(struct snd_kcontrol *kcontrol,
.private_value = left_reg | (right_reg << 8) | (shift_left << 16) | \
(shift_right << 19) | (mask << 24) | (invert << 22) }

#define WSS_SINGLE_TLV(xname, xindex, reg, shift, mask, invert, xtlv) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
.name = xname, \
.index = xindex, \
.info = snd_wss_info_single, \
.get = snd_wss_get_single, \
.put = snd_wss_put_single, \
.private_value = reg | (shift << 8) | (mask << 16) | (invert << 24), \
.tlv = { .p = (xtlv) } }

#define WSS_DOUBLE_TLV(xname, xindex, left_reg, right_reg, \
shift_left, shift_right, mask, invert, xtlv) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
.name = xname, \
.index = xindex, \
.info = snd_wss_info_double, \
.get = snd_wss_get_double, \
.put = snd_wss_put_double, \
.private_value = left_reg | (right_reg << 8) | (shift_left << 16) | \
(shift_right << 19) | (mask << 24) | (invert << 22), \
.tlv = { .p = (xtlv) } }


int snd_wss_info_double(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo);
int snd_wss_get_double(struct snd_kcontrol *kcontrol,
Expand Down
2 changes: 1 addition & 1 deletion sound/isa/ad1848/ad1848.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ static int __devinit snd_ad1848_probe(struct device *dev, unsigned int n)
if (error < 0)
goto out;

error = snd_ad1848_mixer(chip);
error = snd_wss_mixer(chip);
if (error < 0)
goto out;

Expand Down
261 changes: 0 additions & 261 deletions sound/isa/ad1848/ad1848_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -994,267 +994,6 @@ const struct snd_pcm_ops *snd_ad1848_get_pcm_ops(int direction)

EXPORT_SYMBOL(snd_ad1848_get_pcm_ops);

/*
* MIXER part
*/

static int snd_ad1848_info_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
static char *texts[4] = {
"Line", "Aux", "Mic", "Mix"
};

uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 2;
uinfo->value.enumerated.items = 4;
if (uinfo->value.enumerated.item > 3)
uinfo->value.enumerated.item = 3;
strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
return 0;
}

static int snd_ad1848_get_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;

spin_lock_irqsave(&chip->reg_lock, flags);
ucontrol->value.enumerated.item[0] = (chip->image[AD1848_LEFT_INPUT] & AD1848_MIXS_ALL) >> 6;
ucontrol->value.enumerated.item[1] = (chip->image[AD1848_RIGHT_INPUT] & AD1848_MIXS_ALL) >> 6;
spin_unlock_irqrestore(&chip->reg_lock, flags);
return 0;
}

static int snd_ad1848_put_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
unsigned short left, right;
int change;

if (ucontrol->value.enumerated.item[0] > 3 ||
ucontrol->value.enumerated.item[1] > 3)
return -EINVAL;
left = ucontrol->value.enumerated.item[0] << 6;
right = ucontrol->value.enumerated.item[1] << 6;
spin_lock_irqsave(&chip->reg_lock, flags);
left = (chip->image[AD1848_LEFT_INPUT] & ~AD1848_MIXS_ALL) | left;
right = (chip->image[AD1848_RIGHT_INPUT] & ~AD1848_MIXS_ALL) | right;
change = left != chip->image[AD1848_LEFT_INPUT] ||
right != chip->image[AD1848_RIGHT_INPUT];
snd_ad1848_out(chip, AD1848_LEFT_INPUT, left);
snd_ad1848_out(chip, AD1848_RIGHT_INPUT, right);
spin_unlock_irqrestore(&chip->reg_lock, flags);
return change;
}

static int snd_ad1848_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
int mask = (kcontrol->private_value >> 16) & 0xff;

uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 1;
uinfo->value.integer.min = 0;
uinfo->value.integer.max = mask;
return 0;
}

static int snd_ad1848_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int reg = kcontrol->private_value & 0xff;
int shift = (kcontrol->private_value >> 8) & 0xff;
int mask = (kcontrol->private_value >> 16) & 0xff;
int invert = (kcontrol->private_value >> 24) & 0xff;

spin_lock_irqsave(&chip->reg_lock, flags);
ucontrol->value.integer.value[0] = (chip->image[reg] >> shift) & mask;
spin_unlock_irqrestore(&chip->reg_lock, flags);
if (invert)
ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
return 0;
}

static int snd_ad1848_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int reg = kcontrol->private_value & 0xff;
int shift = (kcontrol->private_value >> 8) & 0xff;
int mask = (kcontrol->private_value >> 16) & 0xff;
int invert = (kcontrol->private_value >> 24) & 0xff;
int change;
unsigned short val;

val = (ucontrol->value.integer.value[0] & mask);
if (invert)
val = mask - val;
val <<= shift;
spin_lock_irqsave(&chip->reg_lock, flags);
val = (chip->image[reg] & ~(mask << shift)) | val;
change = val != chip->image[reg];
snd_ad1848_out(chip, reg, val);
spin_unlock_irqrestore(&chip->reg_lock, flags);
return change;
}

static int snd_ad1848_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
int mask = (kcontrol->private_value >> 24) & 0xff;

uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 2;
uinfo->value.integer.min = 0;
uinfo->value.integer.max = mask;
return 0;
}

static int snd_ad1848_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int left_reg = kcontrol->private_value & 0xff;
int right_reg = (kcontrol->private_value >> 8) & 0xff;
int shift_left = (kcontrol->private_value >> 16) & 0x07;
int shift_right = (kcontrol->private_value >> 19) & 0x07;
int mask = (kcontrol->private_value >> 24) & 0xff;
int invert = (kcontrol->private_value >> 22) & 1;

spin_lock_irqsave(&chip->reg_lock, flags);
ucontrol->value.integer.value[0] = (chip->image[left_reg] >> shift_left) & mask;
ucontrol->value.integer.value[1] = (chip->image[right_reg] >> shift_right) & mask;
spin_unlock_irqrestore(&chip->reg_lock, flags);
if (invert) {
ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1];
}
return 0;
}

static int snd_ad1848_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
unsigned long flags;
int left_reg = kcontrol->private_value & 0xff;
int right_reg = (kcontrol->private_value >> 8) & 0xff;
int shift_left = (kcontrol->private_value >> 16) & 0x07;
int shift_right = (kcontrol->private_value >> 19) & 0x07;
int mask = (kcontrol->private_value >> 24) & 0xff;
int invert = (kcontrol->private_value >> 22) & 1;
int change;
unsigned short val1, val2;

val1 = ucontrol->value.integer.value[0] & mask;
val2 = ucontrol->value.integer.value[1] & mask;
if (invert) {
val1 = mask - val1;
val2 = mask - val2;
}
val1 <<= shift_left;
val2 <<= shift_right;
spin_lock_irqsave(&chip->reg_lock, flags);
if (left_reg != right_reg) {
val1 = (chip->image[left_reg] & ~(mask << shift_left)) | val1;
val2 = (chip->image[right_reg] & ~(mask << shift_right)) | val2;
change = val1 != chip->image[left_reg] || val2 != chip->image[right_reg];
snd_ad1848_out(chip, left_reg, val1);
snd_ad1848_out(chip, right_reg, val2);
} else {
val1 = (chip->image[left_reg] & ~((mask << shift_left) | (mask << shift_right))) | val1 | val2;
change = val1 != chip->image[left_reg];
snd_ad1848_out(chip, left_reg, val1);
}
spin_unlock_irqrestore(&chip->reg_lock, flags);
return change;
}

static const DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0);
static const DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0);
static const DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0);

#define AD1848_SINGLE_TLV(xname, xindex, reg, shift, mask, invert, xtlv) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
.name = xname, \
.index = xindex, \
.info = snd_ad1848_info_single, \
.get = snd_ad1848_get_single, \
.put = snd_ad1848_put_single, \
.private_value = reg | (shift << 8) | (mask << 16) | (invert << 24), \
.tlv = { .p = (xtlv) } }

#define AD1848_DOUBLE_TLV(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert, xtlv) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
.name = xname, \
.index = xindex, \
.info = snd_ad1848_info_double, \
.get = snd_ad1848_get_double, \
.put = snd_ad1848_put_double, \
.private_value = left_reg | (right_reg << 8) | (shift_left << 16) | \
(shift_right << 19) | (mask << 24) | (invert << 22), \
.tlv = { .p = (xtlv) } }

static struct snd_kcontrol_new snd_ad1848_controls[] = {
WSS_DOUBLE("PCM Playback Switch", 0,
AD1848_LEFT_OUTPUT, AD1848_RIGHT_OUTPUT, 7, 7, 1, 1),
AD1848_DOUBLE_TLV("PCM Playback Volume", 0,
AD1848_LEFT_OUTPUT, AD1848_RIGHT_OUTPUT, 0, 0, 63, 1,
db_scale_6bit),
WSS_DOUBLE("Aux Playback Switch", 0,
AD1848_AUX1_LEFT_INPUT, AD1848_AUX1_RIGHT_INPUT, 7, 7, 1, 1),
AD1848_DOUBLE_TLV("Aux Playback Volume", 0,
AD1848_AUX1_LEFT_INPUT, AD1848_AUX1_RIGHT_INPUT, 0, 0, 31, 1,
db_scale_5bit_12db_max),
WSS_DOUBLE("Aux Playback Switch", 1,
AD1848_AUX2_LEFT_INPUT, AD1848_AUX2_RIGHT_INPUT, 7, 7, 1, 1),
AD1848_DOUBLE_TLV("Aux Playback Volume", 1,
AD1848_AUX2_LEFT_INPUT, AD1848_AUX2_RIGHT_INPUT, 0, 0, 31, 1,
db_scale_5bit_12db_max),
AD1848_DOUBLE_TLV("Capture Volume", 0,
AD1848_LEFT_INPUT, AD1848_RIGHT_INPUT, 0, 0, 15, 0,
db_scale_rec_gain),
{
.name = "Capture Source",
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.info = snd_ad1848_info_mux,
.get = snd_ad1848_get_mux,
.put = snd_ad1848_put_mux,
},
WSS_SINGLE("Loopback Capture Switch", 0,
AD1848_LOOPBACK, 0, 1, 0),
AD1848_SINGLE_TLV("Loopback Capture Volume", 0,
AD1848_LOOPBACK, 1, 63, 0,
db_scale_6bit),
};

int snd_ad1848_mixer(struct snd_wss *chip)
{
struct snd_card *card;
struct snd_pcm *pcm;
unsigned int idx;
int err;

snd_assert(chip != NULL && chip->pcm != NULL, return -EINVAL);

pcm = chip->pcm;
card = chip->card;

strcpy(card->mixername, pcm->name);

for (idx = 0; idx < ARRAY_SIZE(snd_ad1848_controls); idx++) {
err = snd_ctl_add(card,
snd_ctl_new1(&snd_ad1848_controls[idx], chip));
if (err < 0)
return err;
}

return 0;
}

EXPORT_SYMBOL(snd_ad1848_mixer);

/*
* INIT part
*/
Expand Down
22 changes: 11 additions & 11 deletions sound/isa/opti9xx/opti92x-ad1848.c
Original file line number Diff line number Diff line change
Expand Up @@ -757,30 +757,30 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card)
error = snd_wss_pcm(codec, 0, &pcm);
if (error < 0)
return error;
#else
error = snd_ad1848_create(card, chip->wss_base + 4, chip->irq,
chip->dma1, WSS_HW_DETECT, &codec);
if (error < 0)
return error;
error = snd_ad1848_pcm(codec, 0, &pcm);
if (error < 0)
return error;
#endif
error = snd_wss_mixer(codec);
if (error < 0)
return error;
#ifdef CS4231
error = snd_wss_timer(codec, 0, &timer);
if (error < 0)
return error;
#else /* OPTI93X */
#endif
#ifdef OPTi93X
error = request_irq(chip->irq, snd_opti93x_interrupt,
IRQF_DISABLED, DEV_NAME" - WSS", codec);
if (error < 0) {
snd_printk(KERN_ERR "opti9xx: can't grab IRQ %d\n", chip->irq);
return error;
}
#endif
#else
if ((error = snd_ad1848_create(card, chip->wss_base + 4,
chip->irq, chip->dma1,
WSS_HW_DETECT, &codec)) < 0)
return error;
if ((error = snd_ad1848_pcm(codec, 0, &pcm)) < 0)
return error;
if ((error = snd_ad1848_mixer(codec)) < 0)
return error;
#endif
strcpy(card->driver, chip->name);
sprintf(card->shortname, "OPTi %s", card->driver);
Expand Down
4 changes: 2 additions & 2 deletions sound/isa/sc6000.c
Original file line number Diff line number Diff line change
Expand Up @@ -560,9 +560,9 @@ static int __devinit snd_sc6000_probe(struct device *devptr, unsigned int dev)
"error creating new ad1848 PCM device\n");
goto err_unmap2;
}
err = snd_ad1848_mixer(chip);
err = snd_wss_mixer(chip);
if (err < 0) {
snd_printk(KERN_ERR PFX "error creating new ad1848 mixer\n");
snd_printk(KERN_ERR PFX "error creating new WSS mixer\n");
goto err_unmap2;
}
err = snd_sc6000_mixer(chip);
Expand Down
5 changes: 3 additions & 2 deletions sound/isa/sgalaxy.c
Original file line number Diff line number Diff line change
Expand Up @@ -277,8 +277,9 @@ static int __devinit snd_sgalaxy_probe(struct device *devptr, unsigned int dev)
snd_printdd(PFX "error creating new ad1848 PCM device\n");
goto _err;
}
if ((err = snd_ad1848_mixer(chip)) < 0) {
snd_printdd(PFX "error creating new ad1848 mixer\n");
err = snd_wss_mixer(chip);
if (err < 0) {
snd_printdd(PFX "error creating new WSS mixer\n");
goto _err;
}
if ((err = snd_sgalaxy_mixer(chip)) < 0) {
Expand Down
Loading

0 comments on commit 5664daa

Please sign in to comment.