^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) #define __NO_VERSION__
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Driver for Digigram pcxhr compatible soundcards
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * mixer callbacks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright (c) 2004 by Digigram <alsa@digigram.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/time.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <sound/core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include "pcxhr.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "pcxhr_hwdep.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include "pcxhr_core.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <sound/control.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <sound/tlv.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <sound/asoundef.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include "pcxhr_mixer.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include "pcxhr_mix22.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define PCXHR_LINE_CAPTURE_LEVEL_MIN 0 /* -112.0 dB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define PCXHR_LINE_CAPTURE_LEVEL_MAX 255 /* +15.5 dB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define PCXHR_LINE_CAPTURE_ZERO_LEVEL 224 /* 0.0 dB ( 0 dBu -> 0 dBFS ) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define PCXHR_LINE_PLAYBACK_LEVEL_MIN 0 /* -104.0 dB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define PCXHR_LINE_PLAYBACK_LEVEL_MAX 128 /* +24.0 dB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define PCXHR_LINE_PLAYBACK_ZERO_LEVEL 104 /* 0.0 dB ( 0 dBFS -> 0 dBu ) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) static const DECLARE_TLV_DB_SCALE(db_scale_analog_capture, -11200, 50, 1550);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) static const DECLARE_TLV_DB_SCALE(db_scale_analog_playback, -10400, 100, 2400);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) static const DECLARE_TLV_DB_SCALE(db_scale_a_hr222_capture, -11150, 50, 1600);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) static const DECLARE_TLV_DB_SCALE(db_scale_a_hr222_playback, -2550, 50, 2400);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) static int pcxhr_update_analog_audio_level(struct snd_pcxhr *chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) int is_capture, int channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) int err, vol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) struct pcxhr_rmh rmh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) if (is_capture) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) rmh.cmd[0] |= IO_NUM_REG_IN_ANA_LEVEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) rmh.cmd[2] = chip->analog_capture_volume[channel];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) rmh.cmd[0] |= IO_NUM_REG_OUT_ANA_LEVEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) if (chip->analog_playback_active[channel])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) vol = chip->analog_playback_volume[channel];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) vol = PCXHR_LINE_PLAYBACK_LEVEL_MIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) /* playback analog levels are inversed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) rmh.cmd[2] = PCXHR_LINE_PLAYBACK_LEVEL_MAX - vol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) rmh.cmd[1] = 1 << ((2 * chip->chip_idx) + channel); /* audio mask */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) rmh.cmd_len = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) err = pcxhr_send_msg(chip->mgr, &rmh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) dev_dbg(chip->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) "error update_analog_audio_level card(%d)"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) " is_capture(%d) err(%x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) chip->chip_idx, is_capture, err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * analog level control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) static int pcxhr_analog_vol_info(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) uinfo->count = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) if (kcontrol->private_value == 0) { /* playback */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) if (chip->mgr->is_hr_stereo) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) uinfo->value.integer.min =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) HR222_LINE_PLAYBACK_LEVEL_MIN; /* -25 dB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) uinfo->value.integer.max =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) HR222_LINE_PLAYBACK_LEVEL_MAX; /* +24 dB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) uinfo->value.integer.min =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) PCXHR_LINE_PLAYBACK_LEVEL_MIN; /*-104 dB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) uinfo->value.integer.max =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) PCXHR_LINE_PLAYBACK_LEVEL_MAX; /* +24 dB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) } else { /* capture */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) if (chip->mgr->is_hr_stereo) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) uinfo->value.integer.min =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) HR222_LINE_CAPTURE_LEVEL_MIN; /*-112 dB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) uinfo->value.integer.max =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) HR222_LINE_CAPTURE_LEVEL_MAX; /* +15.5 dB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) uinfo->value.integer.min =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) PCXHR_LINE_CAPTURE_LEVEL_MIN; /*-112 dB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) uinfo->value.integer.max =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) PCXHR_LINE_CAPTURE_LEVEL_MAX; /* +15.5 dB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) static int pcxhr_analog_vol_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) mutex_lock(&chip->mgr->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) if (kcontrol->private_value == 0) { /* playback */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) ucontrol->value.integer.value[0] = chip->analog_playback_volume[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) ucontrol->value.integer.value[1] = chip->analog_playback_volume[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) } else { /* capture */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) ucontrol->value.integer.value[0] = chip->analog_capture_volume[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) ucontrol->value.integer.value[1] = chip->analog_capture_volume[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) mutex_unlock(&chip->mgr->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) static int pcxhr_analog_vol_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) int changed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) int is_capture, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) mutex_lock(&chip->mgr->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) is_capture = (kcontrol->private_value != 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) for (i = 0; i < 2; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) int new_volume = ucontrol->value.integer.value[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) int *stored_volume = is_capture ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) &chip->analog_capture_volume[i] :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) &chip->analog_playback_volume[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) if (is_capture) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) if (chip->mgr->is_hr_stereo) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) if (new_volume < HR222_LINE_CAPTURE_LEVEL_MIN ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) new_volume > HR222_LINE_CAPTURE_LEVEL_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) if (new_volume < PCXHR_LINE_CAPTURE_LEVEL_MIN ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) new_volume > PCXHR_LINE_CAPTURE_LEVEL_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) if (chip->mgr->is_hr_stereo) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) if (new_volume < HR222_LINE_PLAYBACK_LEVEL_MIN ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) new_volume > HR222_LINE_PLAYBACK_LEVEL_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) if (new_volume < PCXHR_LINE_PLAYBACK_LEVEL_MIN ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) new_volume > PCXHR_LINE_PLAYBACK_LEVEL_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) if (*stored_volume != new_volume) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) *stored_volume = new_volume;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) changed = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) if (chip->mgr->is_hr_stereo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) hr222_update_analog_audio_level(chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) is_capture, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) pcxhr_update_analog_audio_level(chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) is_capture, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) mutex_unlock(&chip->mgr->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) return changed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) static const struct snd_kcontrol_new pcxhr_control_analog_level = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) SNDRV_CTL_ELEM_ACCESS_TLV_READ),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) /* name will be filled later */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) .info = pcxhr_analog_vol_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) .get = pcxhr_analog_vol_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) .put = pcxhr_analog_vol_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) /* tlv will be filled later */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) /* shared */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) #define pcxhr_sw_info snd_ctl_boolean_stereo_info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) static int pcxhr_audio_sw_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) mutex_lock(&chip->mgr->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) ucontrol->value.integer.value[0] = chip->analog_playback_active[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) ucontrol->value.integer.value[1] = chip->analog_playback_active[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) mutex_unlock(&chip->mgr->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) static int pcxhr_audio_sw_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) int i, changed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) mutex_lock(&chip->mgr->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) for(i = 0; i < 2; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) if (chip->analog_playback_active[i] !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) ucontrol->value.integer.value[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) chip->analog_playback_active[i] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) !!ucontrol->value.integer.value[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) changed = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) /* update playback levels */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) if (chip->mgr->is_hr_stereo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) hr222_update_analog_audio_level(chip, 0, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) pcxhr_update_analog_audio_level(chip, 0, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) mutex_unlock(&chip->mgr->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) return changed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) static const struct snd_kcontrol_new pcxhr_control_output_switch = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) .name = "Master Playback Switch",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) .info = pcxhr_sw_info, /* shared */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) .get = pcxhr_audio_sw_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) .put = pcxhr_audio_sw_put
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) #define PCXHR_DIGITAL_LEVEL_MIN 0x000 /* -110 dB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) #define PCXHR_DIGITAL_LEVEL_MAX 0x1ff /* +18 dB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) #define PCXHR_DIGITAL_ZERO_LEVEL 0x1b7 /* 0 dB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) static const DECLARE_TLV_DB_SCALE(db_scale_digital, -10975, 25, 1800);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) #define MORE_THAN_ONE_STREAM_LEVEL 0x000001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) #define VALID_STREAM_PAN_LEVEL_MASK 0x800000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) #define VALID_STREAM_LEVEL_MASK 0x400000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) #define VALID_STREAM_LEVEL_1_MASK 0x200000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) #define VALID_STREAM_LEVEL_2_MASK 0x100000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) static int pcxhr_update_playback_stream_level(struct snd_pcxhr* chip, int idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) struct pcxhr_rmh rmh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) struct pcxhr_pipe *pipe = &chip->playback_pipe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) int left, right;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) if (chip->digital_playback_active[idx][0])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) left = chip->digital_playback_volume[idx][0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) left = PCXHR_DIGITAL_LEVEL_MIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) if (chip->digital_playback_active[idx][1])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) right = chip->digital_playback_volume[idx][1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) right = PCXHR_DIGITAL_LEVEL_MIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) pcxhr_init_rmh(&rmh, CMD_STREAM_OUT_LEVEL_ADJUST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) /* add pipe and stream mask */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) pcxhr_set_pipe_cmd_params(&rmh, 0, pipe->first_audio, 0, 1<<idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) /* volume left->left / right->right panoramic level */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) rmh.cmd[0] |= MORE_THAN_ONE_STREAM_LEVEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) rmh.cmd[2] = VALID_STREAM_PAN_LEVEL_MASK | VALID_STREAM_LEVEL_1_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) rmh.cmd[2] |= (left << 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) rmh.cmd[3] = VALID_STREAM_PAN_LEVEL_MASK | VALID_STREAM_LEVEL_2_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) rmh.cmd[3] |= right;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) rmh.cmd_len = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) err = pcxhr_send_msg(chip->mgr, &rmh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) dev_dbg(chip->card->dev, "error update_playback_stream_level "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) "card(%d) err(%x)\n", chip->chip_idx, err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) #define AUDIO_IO_HAS_MUTE_LEVEL 0x400000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) #define AUDIO_IO_HAS_MUTE_MONITOR_1 0x200000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) #define VALID_AUDIO_IO_DIGITAL_LEVEL 0x000001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) #define VALID_AUDIO_IO_MONITOR_LEVEL 0x000002
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) #define VALID_AUDIO_IO_MUTE_LEVEL 0x000004
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) #define VALID_AUDIO_IO_MUTE_MONITOR_1 0x000008
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) static int pcxhr_update_audio_pipe_level(struct snd_pcxhr *chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) int capture, int channel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) struct pcxhr_rmh rmh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) struct pcxhr_pipe *pipe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) if (capture)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) pipe = &chip->capture_pipe[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) pipe = &chip->playback_pipe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) pcxhr_init_rmh(&rmh, CMD_AUDIO_LEVEL_ADJUST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) /* add channel mask */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) pcxhr_set_pipe_cmd_params(&rmh, capture, 0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 1 << (channel + pipe->first_audio));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) /* TODO : if mask (3 << pipe->first_audio) is used, left and right
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) * channel will be programmed to the same params */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) if (capture) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) rmh.cmd[0] |= VALID_AUDIO_IO_DIGITAL_LEVEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) /* VALID_AUDIO_IO_MUTE_LEVEL not yet handled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) * (capture pipe level) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) rmh.cmd[2] = chip->digital_capture_volume[channel];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) rmh.cmd[0] |= VALID_AUDIO_IO_MONITOR_LEVEL |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) VALID_AUDIO_IO_MUTE_MONITOR_1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) /* VALID_AUDIO_IO_DIGITAL_LEVEL and VALID_AUDIO_IO_MUTE_LEVEL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) * not yet handled (playback pipe level)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) rmh.cmd[2] = chip->monitoring_volume[channel] << 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) if (chip->monitoring_active[channel] == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) rmh.cmd[2] |= AUDIO_IO_HAS_MUTE_MONITOR_1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) rmh.cmd_len = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) err = pcxhr_send_msg(chip->mgr, &rmh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) dev_dbg(chip->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) "error update_audio_level(%d) err=%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) chip->chip_idx, err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) /* shared */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) static int pcxhr_digital_vol_info(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) uinfo->count = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) uinfo->value.integer.min = PCXHR_DIGITAL_LEVEL_MIN; /* -109.5 dB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) uinfo->value.integer.max = PCXHR_DIGITAL_LEVEL_MAX; /* 18.0 dB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) static int pcxhr_pcm_vol_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) int *stored_volume;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) int is_capture = kcontrol->private_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) mutex_lock(&chip->mgr->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) if (is_capture) /* digital capture */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) stored_volume = chip->digital_capture_volume;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) else /* digital playback */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) stored_volume = chip->digital_playback_volume[idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) ucontrol->value.integer.value[0] = stored_volume[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) ucontrol->value.integer.value[1] = stored_volume[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) mutex_unlock(&chip->mgr->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) static int pcxhr_pcm_vol_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) int changed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) int is_capture = kcontrol->private_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) int *stored_volume;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) mutex_lock(&chip->mgr->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) if (is_capture) /* digital capture */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) stored_volume = chip->digital_capture_volume;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) else /* digital playback */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) stored_volume = chip->digital_playback_volume[idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) for (i = 0; i < 2; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) int vol = ucontrol->value.integer.value[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) if (vol < PCXHR_DIGITAL_LEVEL_MIN ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) vol > PCXHR_DIGITAL_LEVEL_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) if (stored_volume[i] != vol) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) stored_volume[i] = vol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) changed = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) if (is_capture) /* update capture volume */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) pcxhr_update_audio_pipe_level(chip, 1, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) if (!is_capture && changed) /* update playback volume */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) pcxhr_update_playback_stream_level(chip, idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) mutex_unlock(&chip->mgr->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) return changed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) static const struct snd_kcontrol_new snd_pcxhr_pcm_vol =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) SNDRV_CTL_ELEM_ACCESS_TLV_READ),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) /* name will be filled later */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) /* count will be filled later */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) .info = pcxhr_digital_vol_info, /* shared */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) .get = pcxhr_pcm_vol_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) .put = pcxhr_pcm_vol_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) .tlv = { .p = db_scale_digital },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) static int pcxhr_pcm_sw_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) mutex_lock(&chip->mgr->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) ucontrol->value.integer.value[0] = chip->digital_playback_active[idx][0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) ucontrol->value.integer.value[1] = chip->digital_playback_active[idx][1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) mutex_unlock(&chip->mgr->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) static int pcxhr_pcm_sw_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) int changed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) int i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) mutex_lock(&chip->mgr->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) j = idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) for (i = 0; i < 2; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) if (chip->digital_playback_active[j][i] !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) ucontrol->value.integer.value[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) chip->digital_playback_active[j][i] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) !!ucontrol->value.integer.value[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) changed = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) if (changed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) pcxhr_update_playback_stream_level(chip, idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) mutex_unlock(&chip->mgr->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) return changed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) static const struct snd_kcontrol_new pcxhr_control_pcm_switch = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) .name = "PCM Playback Switch",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) .count = PCXHR_PLAYBACK_STREAMS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) .info = pcxhr_sw_info, /* shared */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) .get = pcxhr_pcm_sw_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) .put = pcxhr_pcm_sw_put
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) * monitoring level control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) static int pcxhr_monitor_vol_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) mutex_lock(&chip->mgr->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) ucontrol->value.integer.value[0] = chip->monitoring_volume[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) ucontrol->value.integer.value[1] = chip->monitoring_volume[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) mutex_unlock(&chip->mgr->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) static int pcxhr_monitor_vol_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) int changed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) mutex_lock(&chip->mgr->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) for (i = 0; i < 2; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) if (chip->monitoring_volume[i] !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) ucontrol->value.integer.value[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) chip->monitoring_volume[i] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) ucontrol->value.integer.value[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) if (chip->monitoring_active[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) /* update monitoring volume and mute */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) /* do only when monitoring is unmuted */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) pcxhr_update_audio_pipe_level(chip, 0, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) changed = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) mutex_unlock(&chip->mgr->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) return changed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) static const struct snd_kcontrol_new pcxhr_control_monitor_vol = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) SNDRV_CTL_ELEM_ACCESS_TLV_READ),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) .name = "Monitoring Playback Volume",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) .info = pcxhr_digital_vol_info, /* shared */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) .get = pcxhr_monitor_vol_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) .put = pcxhr_monitor_vol_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) .tlv = { .p = db_scale_digital },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) * monitoring switch control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) static int pcxhr_monitor_sw_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) mutex_lock(&chip->mgr->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) ucontrol->value.integer.value[0] = chip->monitoring_active[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) ucontrol->value.integer.value[1] = chip->monitoring_active[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) mutex_unlock(&chip->mgr->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) static int pcxhr_monitor_sw_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) int changed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) mutex_lock(&chip->mgr->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) for (i = 0; i < 2; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) if (chip->monitoring_active[i] !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) ucontrol->value.integer.value[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) chip->monitoring_active[i] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) !!ucontrol->value.integer.value[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) changed |= (1<<i); /* mask 0x01 and 0x02 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) if (changed & 0x01)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) /* update left monitoring volume and mute */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) pcxhr_update_audio_pipe_level(chip, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) if (changed & 0x02)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) /* update right monitoring volume and mute */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) pcxhr_update_audio_pipe_level(chip, 0, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) mutex_unlock(&chip->mgr->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) return (changed != 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) static const struct snd_kcontrol_new pcxhr_control_monitor_sw = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) .name = "Monitoring Playback Switch",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) .info = pcxhr_sw_info, /* shared */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) .get = pcxhr_monitor_sw_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) .put = pcxhr_monitor_sw_put
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) * audio source select
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) #define PCXHR_SOURCE_AUDIO01_UER 0x000100
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) #define PCXHR_SOURCE_AUDIO01_SYNC 0x000200
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) #define PCXHR_SOURCE_AUDIO23_UER 0x000400
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) #define PCXHR_SOURCE_AUDIO45_UER 0x001000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) #define PCXHR_SOURCE_AUDIO67_UER 0x040000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) static int pcxhr_set_audio_source(struct snd_pcxhr* chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) struct pcxhr_rmh rmh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) unsigned int mask, reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) unsigned int codec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) int err, changed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) switch (chip->chip_idx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) case 0 : mask = PCXHR_SOURCE_AUDIO01_UER; codec = CS8420_01_CS; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) case 1 : mask = PCXHR_SOURCE_AUDIO23_UER; codec = CS8420_23_CS; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) case 2 : mask = PCXHR_SOURCE_AUDIO45_UER; codec = CS8420_45_CS; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) case 3 : mask = PCXHR_SOURCE_AUDIO67_UER; codec = CS8420_67_CS; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) default: return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) if (chip->audio_capture_source != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) reg = mask; /* audio source from digital plug */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) reg = 0; /* audio source from analog plug */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) /* set the input source */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) pcxhr_write_io_num_reg_cont(chip->mgr, mask, reg, &changed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) /* resync them (otherwise channel inversion possible) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) if (changed) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) pcxhr_init_rmh(&rmh, CMD_RESYNC_AUDIO_INPUTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) rmh.cmd[0] |= (1 << chip->chip_idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) err = pcxhr_send_msg(chip->mgr, &rmh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) if (chip->mgr->board_aes_in_192k) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) unsigned int src_config = 0xC0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) /* update all src configs with one call */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) for (i = 0; (i < 4) && (i < chip->mgr->capture_chips); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) if (chip->mgr->chip[i]->audio_capture_source == 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) src_config |= (1 << (3 - i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) /* set codec SRC on off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) rmh.cmd_len = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) rmh.cmd[0] |= IO_NUM_REG_CONFIG_SRC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) rmh.cmd[1] = src_config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) err = pcxhr_send_msg(chip->mgr, &rmh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) int use_src = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) if (chip->audio_capture_source == 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) use_src = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) /* set codec SRC on off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) rmh.cmd_len = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) rmh.cmd[0] |= IO_NUM_UER_CHIP_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) rmh.cmd[1] = codec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) rmh.cmd[2] = ((CS8420_DATA_FLOW_CTL & CHIP_SIG_AND_MAP_SPI) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) (use_src ? 0x41 : 0x54));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) err = pcxhr_send_msg(chip->mgr, &rmh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) rmh.cmd[2] = ((CS8420_CLOCK_SRC_CTL & CHIP_SIG_AND_MAP_SPI) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) (use_src ? 0x41 : 0x49));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) err = pcxhr_send_msg(chip->mgr, &rmh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) static int pcxhr_audio_src_info(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) static const char *texts[5] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) "Line", "Digital", "Digi+SRC", "Mic", "Line+Mic"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) i = 2; /* no SRC, no Mic available */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) if (chip->mgr->board_has_aes1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) i = 3; /* SRC available */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) if (chip->mgr->board_has_mic)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) i = 5; /* Mic and MicroMix available */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) return snd_ctl_enum_info(uinfo, 1, i, texts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) static int pcxhr_audio_src_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) ucontrol->value.enumerated.item[0] = chip->audio_capture_source;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) static int pcxhr_audio_src_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) int i = 2; /* no SRC, no Mic available */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) if (chip->mgr->board_has_aes1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) i = 3; /* SRC available */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) if (chip->mgr->board_has_mic)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) i = 5; /* Mic and MicroMix available */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) if (ucontrol->value.enumerated.item[0] >= i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) mutex_lock(&chip->mgr->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) if (chip->audio_capture_source != ucontrol->value.enumerated.item[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) chip->audio_capture_source = ucontrol->value.enumerated.item[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) if (chip->mgr->is_hr_stereo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) hr222_set_audio_source(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) pcxhr_set_audio_source(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) ret = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) mutex_unlock(&chip->mgr->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) static const struct snd_kcontrol_new pcxhr_control_audio_src = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) .name = "Capture Source",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) .info = pcxhr_audio_src_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) .get = pcxhr_audio_src_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) .put = pcxhr_audio_src_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) * clock type selection
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) * enum pcxhr_clock_type {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) * PCXHR_CLOCK_TYPE_INTERNAL = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) * PCXHR_CLOCK_TYPE_WORD_CLOCK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) * PCXHR_CLOCK_TYPE_AES_SYNC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) * PCXHR_CLOCK_TYPE_AES_1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) * PCXHR_CLOCK_TYPE_AES_2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) * PCXHR_CLOCK_TYPE_AES_3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) * PCXHR_CLOCK_TYPE_AES_4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) * PCXHR_CLOCK_TYPE_MAX = PCXHR_CLOCK_TYPE_AES_4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) * HR22_CLOCK_TYPE_INTERNAL = PCXHR_CLOCK_TYPE_INTERNAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) * HR22_CLOCK_TYPE_AES_SYNC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) * HR22_CLOCK_TYPE_AES_1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) * HR22_CLOCK_TYPE_MAX = HR22_CLOCK_TYPE_AES_1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) * };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) static int pcxhr_clock_type_info(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) static const char *textsPCXHR[7] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) "Internal", "WordClock", "AES Sync",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) "AES 1", "AES 2", "AES 3", "AES 4"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) static const char *textsHR22[3] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) "Internal", "AES Sync", "AES 1"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) const char **texts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) struct pcxhr_mgr *mgr = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) int clock_items = 2; /* at least Internal and AES Sync clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) if (mgr->board_has_aes1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) clock_items += mgr->capture_chips; /* add AES x */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) if (!mgr->is_hr_stereo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) clock_items += 1; /* add word clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) if (mgr->is_hr_stereo) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) texts = textsHR22;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) snd_BUG_ON(clock_items > (HR22_CLOCK_TYPE_MAX+1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) texts = textsPCXHR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) snd_BUG_ON(clock_items > (PCXHR_CLOCK_TYPE_MAX+1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) return snd_ctl_enum_info(uinfo, 1, clock_items, texts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) static int pcxhr_clock_type_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) struct pcxhr_mgr *mgr = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) ucontrol->value.enumerated.item[0] = mgr->use_clock_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) static int pcxhr_clock_type_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) struct pcxhr_mgr *mgr = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) int rate, ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) unsigned int clock_items = 2; /* at least Internal and AES Sync clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) if (mgr->board_has_aes1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) clock_items += mgr->capture_chips; /* add AES x */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) if (!mgr->is_hr_stereo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) clock_items += 1; /* add word clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) if (ucontrol->value.enumerated.item[0] >= clock_items)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) mutex_lock(&mgr->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) if (mgr->use_clock_type != ucontrol->value.enumerated.item[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) mutex_lock(&mgr->setup_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) mgr->use_clock_type = ucontrol->value.enumerated.item[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) rate = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) if (mgr->use_clock_type != PCXHR_CLOCK_TYPE_INTERNAL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) pcxhr_get_external_clock(mgr, mgr->use_clock_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) &rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) rate = mgr->sample_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) if (!rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) rate = 48000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) if (rate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) pcxhr_set_clock(mgr, rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) if (mgr->sample_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) mgr->sample_rate = rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) mutex_unlock(&mgr->setup_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) ret = 1; /* return 1 even if the set was not done. ok ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) mutex_unlock(&mgr->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) static const struct snd_kcontrol_new pcxhr_control_clock_type = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) .name = "Clock Mode",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) .info = pcxhr_clock_type_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) .get = pcxhr_clock_type_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) .put = pcxhr_clock_type_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) * clock rate control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) * specific control that scans the sample rates on the external plugs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) static int pcxhr_clock_rate_info(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) struct pcxhr_mgr *mgr = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) uinfo->count = 3 + mgr->capture_chips;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) uinfo->value.integer.min = 0; /* clock not present */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) uinfo->value.integer.max = 192000; /* max sample rate 192 kHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) static int pcxhr_clock_rate_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) struct pcxhr_mgr *mgr = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) int i, err, rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) mutex_lock(&mgr->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) for(i = 0; i < 3 + mgr->capture_chips; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) if (i == PCXHR_CLOCK_TYPE_INTERNAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) rate = mgr->sample_rate_real;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) err = pcxhr_get_external_clock(mgr, i, &rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) ucontrol->value.integer.value[i] = rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) mutex_unlock(&mgr->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) static const struct snd_kcontrol_new pcxhr_control_clock_rate = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) .access = SNDRV_CTL_ELEM_ACCESS_READ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) .iface = SNDRV_CTL_ELEM_IFACE_CARD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) .name = "Clock Rates",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) .info = pcxhr_clock_rate_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) .get = pcxhr_clock_rate_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) * IEC958 status bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) static int pcxhr_iec958_info(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) uinfo->count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) static int pcxhr_iec958_capture_byte(struct snd_pcxhr *chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) int aes_idx, unsigned char *aes_bits)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) int i, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) unsigned char temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) struct pcxhr_rmh rmh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_READ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) rmh.cmd[0] |= IO_NUM_UER_CHIP_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) switch (chip->chip_idx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) /* instead of CS8420_01_CS use CS8416_01_CS for AES SYNC plug */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) case 0: rmh.cmd[1] = CS8420_01_CS; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) case 1: rmh.cmd[1] = CS8420_23_CS; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) case 2: rmh.cmd[1] = CS8420_45_CS; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) case 3: rmh.cmd[1] = CS8420_67_CS; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) default: return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) if (chip->mgr->board_aes_in_192k) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) switch (aes_idx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) case 0: rmh.cmd[2] = CS8416_CSB0; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) case 1: rmh.cmd[2] = CS8416_CSB1; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) case 2: rmh.cmd[2] = CS8416_CSB2; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) case 3: rmh.cmd[2] = CS8416_CSB3; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) case 4: rmh.cmd[2] = CS8416_CSB4; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) default: return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) switch (aes_idx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) /* instead of CS8420_CSB0 use CS8416_CSBx for AES SYNC plug */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) case 0: rmh.cmd[2] = CS8420_CSB0; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) case 1: rmh.cmd[2] = CS8420_CSB1; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) case 2: rmh.cmd[2] = CS8420_CSB2; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) case 3: rmh.cmd[2] = CS8420_CSB3; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) case 4: rmh.cmd[2] = CS8420_CSB4; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) default: return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) /* size and code the chip id for the fpga */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) rmh.cmd[1] &= 0x0fffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) /* chip signature + map for spi read */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) rmh.cmd[2] &= CHIP_SIG_AND_MAP_SPI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) rmh.cmd_len = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) err = pcxhr_send_msg(chip->mgr, &rmh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) if (chip->mgr->board_aes_in_192k) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) temp = (unsigned char)rmh.stat[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) temp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) /* reversed bit order (not with CS8416_01_CS) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) for (i = 0; i < 8; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) temp <<= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) if (rmh.stat[1] & (1 << i))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) temp |= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) dev_dbg(chip->card->dev, "read iec958 AES %d byte %d = 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) chip->chip_idx, aes_idx, temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) *aes_bits = temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) static int pcxhr_iec958_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) unsigned char aes_bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) int i, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) mutex_lock(&chip->mgr->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) for(i = 0; i < 5; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) if (kcontrol->private_value == 0) /* playback */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) aes_bits = chip->aes_bits[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) else { /* capture */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) if (chip->mgr->is_hr_stereo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) err = hr222_iec958_capture_byte(chip, i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) &aes_bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) err = pcxhr_iec958_capture_byte(chip, i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) &aes_bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) ucontrol->value.iec958.status[i] = aes_bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) mutex_unlock(&chip->mgr->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) static int pcxhr_iec958_mask_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) for (i = 0; i < 5; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) ucontrol->value.iec958.status[i] = 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) static int pcxhr_iec958_update_byte(struct snd_pcxhr *chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) int aes_idx, unsigned char aes_bits)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) int i, err, cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) unsigned char new_bits = aes_bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) unsigned char old_bits = chip->aes_bits[aes_idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) struct pcxhr_rmh rmh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) for (i = 0; i < 8; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) if ((old_bits & 0x01) != (new_bits & 0x01)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) cmd = chip->chip_idx & 0x03; /* chip index 0..3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) if (chip->chip_idx > 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) /* new bit used if chip_idx>3 (PCX1222HR) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) cmd |= 1 << 22;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) cmd |= ((aes_idx << 3) + i) << 2; /* add bit offset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) cmd |= (new_bits & 0x01) << 23; /* add bit value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) rmh.cmd[0] |= IO_NUM_REG_CUER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) rmh.cmd[1] = cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) rmh.cmd_len = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) dev_dbg(chip->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) "write iec958 AES %d byte %d bit %d (cmd %x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) chip->chip_idx, aes_idx, i, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) err = pcxhr_send_msg(chip->mgr, &rmh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) old_bits >>= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) new_bits >>= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) chip->aes_bits[aes_idx] = aes_bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) static int pcxhr_iec958_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) int i, changed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) /* playback */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) mutex_lock(&chip->mgr->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) for (i = 0; i < 5; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) if (ucontrol->value.iec958.status[i] != chip->aes_bits[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) if (chip->mgr->is_hr_stereo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) hr222_iec958_update_byte(chip, i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) ucontrol->value.iec958.status[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) pcxhr_iec958_update_byte(chip, i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) ucontrol->value.iec958.status[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) changed = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) mutex_unlock(&chip->mgr->mixer_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) return changed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) static const struct snd_kcontrol_new pcxhr_control_playback_iec958_mask = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) .access = SNDRV_CTL_ELEM_ACCESS_READ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) .iface = SNDRV_CTL_ELEM_IFACE_PCM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) .info = pcxhr_iec958_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) .get = pcxhr_iec958_mask_get
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) static const struct snd_kcontrol_new pcxhr_control_playback_iec958 = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) .iface = SNDRV_CTL_ELEM_IFACE_PCM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) .info = pcxhr_iec958_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) .get = pcxhr_iec958_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) .put = pcxhr_iec958_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) .private_value = 0 /* playback */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) static const struct snd_kcontrol_new pcxhr_control_capture_iec958_mask = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) .access = SNDRV_CTL_ELEM_ACCESS_READ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) .iface = SNDRV_CTL_ELEM_IFACE_PCM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,MASK),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) .info = pcxhr_iec958_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) .get = pcxhr_iec958_mask_get
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) static const struct snd_kcontrol_new pcxhr_control_capture_iec958 = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) .access = SNDRV_CTL_ELEM_ACCESS_READ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) .iface = SNDRV_CTL_ELEM_IFACE_PCM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) .info = pcxhr_iec958_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) .get = pcxhr_iec958_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) .private_value = 1 /* capture */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) static void pcxhr_init_audio_levels(struct snd_pcxhr *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) for (i = 0; i < 2; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) if (chip->nb_streams_play) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) int j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) /* at boot time the digital volumes are unmuted 0dB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) for (j = 0; j < PCXHR_PLAYBACK_STREAMS; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) chip->digital_playback_active[j][i] = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) chip->digital_playback_volume[j][i] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) PCXHR_DIGITAL_ZERO_LEVEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) /* after boot, only two bits are set on the uer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) * interface
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) chip->aes_bits[0] = (IEC958_AES0_PROFESSIONAL |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) IEC958_AES0_PRO_FS_48000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) #ifdef CONFIG_SND_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) /* analog volumes for playback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) * (is LEVEL_MIN after boot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) chip->analog_playback_active[i] = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) if (chip->mgr->is_hr_stereo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) chip->analog_playback_volume[i] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) HR222_LINE_PLAYBACK_ZERO_LEVEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) chip->analog_playback_volume[i] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) PCXHR_LINE_PLAYBACK_ZERO_LEVEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) pcxhr_update_analog_audio_level(chip, 0, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) /* stereo cards need to be initialised after boot */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) if (chip->mgr->is_hr_stereo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) hr222_update_analog_audio_level(chip, 0, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) if (chip->nb_streams_capt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) /* at boot time the digital volumes are unmuted 0dB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) chip->digital_capture_volume[i] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) PCXHR_DIGITAL_ZERO_LEVEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) chip->analog_capture_active = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) #ifdef CONFIG_SND_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) /* analog volumes for playback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) * (is LEVEL_MIN after boot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) if (chip->mgr->is_hr_stereo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) chip->analog_capture_volume[i] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) HR222_LINE_CAPTURE_ZERO_LEVEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) chip->analog_capture_volume[i] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) PCXHR_LINE_CAPTURE_ZERO_LEVEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) pcxhr_update_analog_audio_level(chip, 1, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) /* stereo cards need to be initialised after boot */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) if (chip->mgr->is_hr_stereo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) hr222_update_analog_audio_level(chip, 1, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) int pcxhr_create_mixer(struct pcxhr_mgr *mgr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) struct snd_pcxhr *chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) int err, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) mutex_init(&mgr->mixer_mutex); /* can be in another place */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) for (i = 0; i < mgr->num_cards; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) struct snd_kcontrol_new temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) chip = mgr->chip[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) if (chip->nb_streams_play) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) /* analog output level control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) temp = pcxhr_control_analog_level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) temp.name = "Master Playback Volume";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) temp.private_value = 0; /* playback */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) if (mgr->is_hr_stereo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) temp.tlv.p = db_scale_a_hr222_playback;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) temp.tlv.p = db_scale_analog_playback;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) err = snd_ctl_add(chip->card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) snd_ctl_new1(&temp, chip));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) /* output mute controls */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) err = snd_ctl_add(chip->card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) snd_ctl_new1(&pcxhr_control_output_switch,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) chip));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) temp = snd_pcxhr_pcm_vol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) temp.name = "PCM Playback Volume";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) temp.count = PCXHR_PLAYBACK_STREAMS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) temp.private_value = 0; /* playback */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) err = snd_ctl_add(chip->card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) snd_ctl_new1(&temp, chip));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) err = snd_ctl_add(chip->card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) snd_ctl_new1(&pcxhr_control_pcm_switch, chip));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) /* IEC958 controls */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) err = snd_ctl_add(chip->card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) snd_ctl_new1(&pcxhr_control_playback_iec958_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) chip));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) err = snd_ctl_add(chip->card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) snd_ctl_new1(&pcxhr_control_playback_iec958,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) chip));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) if (chip->nb_streams_capt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) /* analog input level control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) temp = pcxhr_control_analog_level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) temp.name = "Line Capture Volume";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) temp.private_value = 1; /* capture */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) if (mgr->is_hr_stereo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) temp.tlv.p = db_scale_a_hr222_capture;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) temp.tlv.p = db_scale_analog_capture;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) err = snd_ctl_add(chip->card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) snd_ctl_new1(&temp, chip));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) temp = snd_pcxhr_pcm_vol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) temp.name = "PCM Capture Volume";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) temp.count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) temp.private_value = 1; /* capture */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) err = snd_ctl_add(chip->card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) snd_ctl_new1(&temp, chip));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) /* Audio source */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) err = snd_ctl_add(chip->card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) snd_ctl_new1(&pcxhr_control_audio_src, chip));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) /* IEC958 controls */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) err = snd_ctl_add(chip->card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) snd_ctl_new1(&pcxhr_control_capture_iec958_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) chip));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) err = snd_ctl_add(chip->card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) snd_ctl_new1(&pcxhr_control_capture_iec958,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) chip));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) if (mgr->is_hr_stereo) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) err = hr222_add_mic_controls(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) /* monitoring only if playback and capture device available */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) if (chip->nb_streams_capt > 0 && chip->nb_streams_play > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) /* monitoring */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) err = snd_ctl_add(chip->card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) snd_ctl_new1(&pcxhr_control_monitor_vol, chip));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) err = snd_ctl_add(chip->card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) snd_ctl_new1(&pcxhr_control_monitor_sw, chip));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) if (i == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) /* clock mode only one control per pcxhr */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) err = snd_ctl_add(chip->card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) snd_ctl_new1(&pcxhr_control_clock_type, mgr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) /* non standard control used to scan
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) * the external clock presence/frequencies
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) err = snd_ctl_add(chip->card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) snd_ctl_new1(&pcxhr_control_clock_rate, mgr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) /* init values for the mixer data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) pcxhr_init_audio_levels(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) }