#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/vmalloc.h>
#include <linux/io.h>
#include <sound/core.h>
#include <sound/control.h>
#include <sound/pcm.h>
#include <sound/tlv.h>
#include "lola.h"
static int lola_init_pin(struct lola *chip, struct lola_pin *pin,
int dir, int nid)
{ … }
int lola_init_pins(struct lola *chip, int dir, int *nidp)
{ … }
void lola_free_mixer(struct lola *chip)
{ … }
int lola_init_mixer_widget(struct lola *chip, int nid)
{ … }
static int lola_mixer_set_src_gain(struct lola *chip, unsigned int id,
unsigned short gain, bool on)
{ … }
#if 0
static int lola_mixer_set_src_gains(struct lola *chip, unsigned int mask,
unsigned short *gains)
{
int i;
if ((chip->mixer.src_mask & mask) != mask)
return -EINVAL;
for (i = 0; i < LOLA_MIXER_DIM; i++) {
if (mask & (1 << i)) {
writew(*gains, &chip->mixer.array->src_gain[i]);
gains++;
}
}
writel(mask, &chip->mixer.array->src_gain_enable);
lola_codec_flush(chip);
if (chip->mixer.caps & LOLA_PEAK_METER_CAN_AGC_MASK) {
return lola_codec_write(chip, chip->mixer.nid,
LOLA_VERB_SET_SOURCE_GAIN, 0x80, 0);
}
for (i = 0; i < LOLA_MIXER_DIM; i++) {
if (mask & (1 << i)) {
lola_codec_write(chip, chip->mixer.nid,
LOLA_VERB_SET_SOURCE_GAIN, i, 0);
}
}
return 0;
}
#endif
static int lola_mixer_set_mapping_gain(struct lola *chip,
unsigned int src, unsigned int dest,
unsigned short gain, bool on)
{ … }
#if 0
static int lola_mixer_set_dest_gains(struct lola *chip, unsigned int id,
unsigned int mask, unsigned short *gains)
{
int i;
if (!(chip->mixer.dest_mask & (1 << id)) ||
(chip->mixer.src_mask & mask) != mask)
return -EINVAL;
for (i = 0; i < LOLA_MIXER_DIM; i++) {
if (mask & (1 << i)) {
writew(*gains, &chip->mixer.array->dest_mix_gain[id][i]);
gains++;
}
}
writel(mask, &chip->mixer.array->dest_mix_gain_enable[id]);
lola_codec_flush(chip);
return lola_codec_write(chip, chip->mixer.nid,
LOLA_VERB_SET_DESTINATION_GAIN, id, 0);
}
#endif
static int set_analog_volume(struct lola *chip, int dir,
unsigned int idx, unsigned int val,
bool external_call);
int lola_setup_all_analog_gains(struct lola *chip, int dir, bool mute)
{ … }
void lola_save_mixer(struct lola *chip)
{ … }
void lola_restore_mixer(struct lola *chip)
{ … }
static int set_analog_volume(struct lola *chip, int dir,
unsigned int idx, unsigned int val,
bool external_call)
{ … }
int lola_set_src_config(struct lola *chip, unsigned int src_mask, bool update)
{ … }
static int init_mixer_values(struct lola *chip)
{ … }
static int lola_analog_vol_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{ … }
static int lola_analog_vol_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{ … }
static int lola_analog_vol_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{ … }
static int lola_analog_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag,
unsigned int size, unsigned int __user *tlv)
{ … }
static struct snd_kcontrol_new lola_analog_mixer = …;
static int create_analog_mixer(struct lola *chip, int dir, char *name)
{ … }
static int lola_input_src_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{ … }
static int lola_input_src_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{ … }
static int lola_input_src_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{ … }
static const struct snd_kcontrol_new lola_input_src_mixer = …;
static int create_input_src_mixer(struct lola *chip)
{ … }
static int lola_src_gain_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{ … }
static int lola_src_gain_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{ … }
static int lola_src_gain_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{ … }
static const DECLARE_TLV_DB_SCALE(lola_src_gain_tlv, -8425, 25, 1);
static struct snd_kcontrol_new lola_src_gain_mixer = …;
static int create_src_gain_mixer(struct lola *chip,
int num, int ofs, char *name)
{ … }
#if 0
static int lola_dest_gain_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
unsigned int src_num = (kcontrol->private_value >> 8) & 0xff;
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = src_num;
uinfo->value.integer.min = 0;
uinfo->value.integer.max = 433;
return 0;
}
static int lola_dest_gain_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct lola *chip = snd_kcontrol_chip(kcontrol);
unsigned int src_ofs = kcontrol->private_value & 0xff;
unsigned int src_num = (kcontrol->private_value >> 8) & 0xff;
unsigned int dst_ofs = (kcontrol->private_value >> 16) & 0xff;
unsigned int dst, mask, i;
dst = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + dst_ofs;
mask = readl(&chip->mixer.array->dest_mix_gain_enable[dst]);
for (i = 0; i < src_num; i++) {
unsigned int src = src_ofs + i;
unsigned short val;
if (!(chip->mixer.src_mask & (1 << src)))
return -EINVAL;
if (mask & (1 << dst))
val = readw(&chip->mixer.array->dest_mix_gain[dst][src]) + 1;
else
val = 0;
ucontrol->value.integer.value[i] = val;
}
return 0;
}
static int lola_dest_gain_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct lola *chip = snd_kcontrol_chip(kcontrol);
unsigned int src_ofs = kcontrol->private_value & 0xff;
unsigned int src_num = (kcontrol->private_value >> 8) & 0xff;
unsigned int dst_ofs = (kcontrol->private_value >> 16) & 0xff;
unsigned int dst, mask;
unsigned short gains[MAX_STREAM_COUNT];
int i, num;
mask = 0;
num = 0;
for (i = 0; i < src_num; i++) {
unsigned short val = ucontrol->value.integer.value[i];
if (val) {
gains[num++] = val - 1;
mask |= 1 << i;
}
}
mask <<= src_ofs;
dst = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id) + dst_ofs;
return lola_mixer_set_dest_gains(chip, dst, mask, gains);
}
static const DECLARE_TLV_DB_SCALE(lola_dest_gain_tlv, -8425, 25, 1);
static struct snd_kcontrol_new lola_dest_gain_mixer = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
SNDRV_CTL_ELEM_ACCESS_TLV_READ),
.info = lola_dest_gain_info,
.get = lola_dest_gain_get,
.put = lola_dest_gain_put,
.tlv.p = lola_dest_gain_tlv,
};
static int create_dest_gain_mixer(struct lola *chip,
int src_num, int src_ofs,
int num, int ofs, char *name)
{
lola_dest_gain_mixer.count = num;
lola_dest_gain_mixer.name = name;
lola_dest_gain_mixer.private_value =
src_ofs + (src_num << 8) + (ofs << 16) + (num << 24);
return snd_ctl_add(chip->card,
snd_ctl_new1(&lola_dest_gain_mixer, chip));
}
#endif
int lola_create_mixer(struct lola *chip)
{ … }