/*
* C-Media CMI8788 driver - mixer code
*
* Copyright (c) Clemens Ladisch <clemens@ladisch.de>
*
*
* This driver is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, version 2.
*
* This driver is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this driver; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/mutex.h>
#include <sound/ac97_codec.h>
#include <sound/asoundef.h>
#include <sound/control.h>
#include <sound/tlv.h>
#include "oxygen.h"
#include "cm9780.h"
static int dac_volume_info(struct snd_kcontrol *ctl,
struct snd_ctl_elem_info *info)
{
struct oxygen *chip = ctl->private_data;
info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
info->count = chip->model->dac_channels;
info->value.integer.min = chip->model->dac_volume_min;
info->value.integer.max = chip->model->dac_volume_max;
return 0;
}
static int dac_volume_get(struct snd_kcontrol *ctl,
struct snd_ctl_elem_value *value)
{
struct oxygen *chip = ctl->private_data;
unsigned int i;
mutex_lock(&chip->mutex);
for (i = 0; i < chip->model->dac_channels; ++i)
value->value.integer.value[i] = chip->dac_volume[i];
mutex_unlock(&chip->mutex);
return 0;
}
static int dac_volume_put(struct snd_kcontrol *ctl,
struct snd_ctl_elem_value *value)
{
struct oxygen *chip = ctl->private_data;
unsigned int i;
int changed;
changed = 0;
mutex_lock(&chip->mutex);
for (i = 0; i < chip->model->dac_channels; ++i)
if (value->value.integer.value[i] != chip->dac_volume[i]) {
chip->dac_volume[i] = value->value.integer.value[i];
changed = 1;
}
if (changed)
chip->model->update_dac_volume(chip);
mutex_unlock(&chip->mutex);
return changed;
}
static int dac_mute_get(struct snd_kcontrol *ctl,
struct snd_ctl_elem_value *value)
{
struct oxygen *chip = ctl->private_data;
mutex_lock(&chip->mutex);
value->value.integer.value[0] = !chip->dac_mute;
mutex_unlock(&chip->mutex);
return 0;
}
static int dac_mute_put(struct snd_kcontrol *ctl,
struct snd_ctl_elem_value *value)
{
struct oxygen *chip = ctl->private_data;
int changed;
mutex_lock(&chip->mutex);
changed = !value->value.integer.value[0] != chip->dac_mute;
if (changed) {
chip->dac_mute = !value->value.integer.value[0];
chip->model->update_dac_mute(chip);
}
mutex_unlock(&chip->mutex);
return changed;
}
static int upmix_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info)
{
static const char *const names[3] = {
"Front", "Front+Surround", "Front+Surround+Back"
};
struct oxygen *chip = ctl->private_data;
unsigned int count = 2 + (chip->model->dac_channels == 8);
info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
info->count = 1;
info->value.enumerated.items = count;
if (info->value.enumerated.item >= count)
info->value.enumerated.item = count - 1;
strcpy(info->value.enumerated.name, names[info->value.enumerated.item]);
return 0;
}
static int upmix_get(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value)
{
struct oxygen *chip =