^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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * ALSA driver for ICEnsemble VT1724 (Envy24HT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Lowlevel functions for ESI Maya44 cards
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (c) 2009 Takashi Iwai <tiwai@suse.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Based on the patches by Rainer Zimmermann <mail@lightshed.de>
^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/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <sound/core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <sound/control.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <sound/pcm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <sound/tlv.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include "ice1712.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include "envy24ht.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include "maya44.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) /* WM8776 register indexes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define WM8776_REG_HEADPHONE_L 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define WM8776_REG_HEADPHONE_R 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define WM8776_REG_HEADPHONE_MASTER 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define WM8776_REG_DAC_ATTEN_L 0x03
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define WM8776_REG_DAC_ATTEN_R 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define WM8776_REG_DAC_ATTEN_MASTER 0x05
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define WM8776_REG_DAC_PHASE 0x06
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define WM8776_REG_DAC_CONTROL 0x07
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define WM8776_REG_DAC_MUTE 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define WM8776_REG_DAC_DEEMPH 0x09
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define WM8776_REG_DAC_IF_CONTROL 0x0a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define WM8776_REG_ADC_IF_CONTROL 0x0b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define WM8776_REG_MASTER_MODE_CONTROL 0x0c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define WM8776_REG_POWERDOWN 0x0d
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define WM8776_REG_ADC_ATTEN_L 0x0e
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define WM8776_REG_ADC_ATTEN_R 0x0f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define WM8776_REG_ADC_ALC1 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define WM8776_REG_ADC_ALC2 0x11
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define WM8776_REG_ADC_ALC3 0x12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define WM8776_REG_ADC_NOISE_GATE 0x13
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define WM8776_REG_ADC_LIMITER 0x14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define WM8776_REG_ADC_MUX 0x15
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define WM8776_REG_OUTPUT_MUX 0x16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define WM8776_REG_RESET 0x17
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define WM8776_NUM_REGS 0x18
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) /* clock ratio identifiers for snd_wm8776_set_rate() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define WM8776_CLOCK_RATIO_128FS 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define WM8776_CLOCK_RATIO_192FS 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define WM8776_CLOCK_RATIO_256FS 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define WM8776_CLOCK_RATIO_384FS 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define WM8776_CLOCK_RATIO_512FS 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define WM8776_CLOCK_RATIO_768FS 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) enum { WM_VOL_HP, WM_VOL_DAC, WM_VOL_ADC, WM_NUM_VOLS };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) enum { WM_SW_DAC, WM_SW_BYPASS, WM_NUM_SWITCHES };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) struct snd_wm8776 {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) unsigned char addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) unsigned short regs[WM8776_NUM_REGS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) unsigned char volumes[WM_NUM_VOLS][2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) unsigned int switch_bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) struct snd_maya44 {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) struct snd_ice1712 *ice;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) struct snd_wm8776 wm[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) struct mutex mutex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) /* write the given register and save the data to the cache */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) static void wm8776_write(struct snd_ice1712 *ice, struct snd_wm8776 *wm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) unsigned char reg, unsigned short val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) * WM8776 registers are up to 9 bits wide, bit 8 is placed in the LSB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) * of the address field
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) snd_vt1724_write_i2c(ice, wm->addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) (reg << 1) | ((val >> 8) & 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) val & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) wm->regs[reg] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) * update the given register with and/or mask and save the data to the cache
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) static int wm8776_write_bits(struct snd_ice1712 *ice, struct snd_wm8776 *wm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) unsigned char reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) unsigned short mask, unsigned short val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) val |= wm->regs[reg] & ~mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) if (val != wm->regs[reg]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) wm8776_write(ice, wm, reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^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) * WM8776 volume controls
^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) struct maya_vol_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) unsigned int maxval; /* volume range: 0..maxval */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) unsigned char regs[2]; /* left and right registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) unsigned short mask; /* value mask */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) unsigned short offset; /* zero-value offset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) unsigned short mute; /* mute bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) unsigned short update; /* update bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) unsigned char mux_bits[2]; /* extra bits for ADC mute */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) static const struct maya_vol_info vol_info[WM_NUM_VOLS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) [WM_VOL_HP] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) .maxval = 80,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) .regs = { WM8776_REG_HEADPHONE_L, WM8776_REG_HEADPHONE_R },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) .mask = 0x7f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) .offset = 0x30,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) .mute = 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) .update = 0x180, /* update and zero-cross enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) [WM_VOL_DAC] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) .maxval = 255,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) .regs = { WM8776_REG_DAC_ATTEN_L, WM8776_REG_DAC_ATTEN_R },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) .mask = 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) .offset = 0x01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) .mute = 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) .update = 0x100, /* zero-cross enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) [WM_VOL_ADC] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) .maxval = 91,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) .regs = { WM8776_REG_ADC_ATTEN_L, WM8776_REG_ADC_ATTEN_R },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) .mask = 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) .offset = 0xa5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) .mute = 0xa5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) .update = 0x100, /* update */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) .mux_bits = { 0x80, 0x40 }, /* ADCMUX bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) * dB tables
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) /* headphone output: mute, -73..+6db (1db step) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) static const DECLARE_TLV_DB_SCALE(db_scale_hp, -7400, 100, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) /* DAC output: mute, -127..0db (0.5db step) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) static const DECLARE_TLV_DB_SCALE(db_scale_dac, -12750, 50, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) /* ADC gain: mute, -21..+24db (0.5db step) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) static const DECLARE_TLV_DB_SCALE(db_scale_adc, -2100, 50, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) static int maya_vol_info(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) unsigned int idx = kcontrol->private_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) const struct maya_vol_info *vol = &vol_info[idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) uinfo->count = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) uinfo->value.integer.min = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) uinfo->value.integer.max = vol->maxval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) static int maya_vol_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) struct snd_wm8776 *wm =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) &chip->wm[snd_ctl_get_ioff(kcontrol, &ucontrol->id)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) unsigned int idx = kcontrol->private_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) mutex_lock(&chip->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) ucontrol->value.integer.value[0] = wm->volumes[idx][0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) ucontrol->value.integer.value[1] = wm->volumes[idx][1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) mutex_unlock(&chip->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) static int maya_vol_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) struct snd_wm8776 *wm =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) &chip->wm[snd_ctl_get_ioff(kcontrol, &ucontrol->id)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) unsigned int idx = kcontrol->private_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) const struct maya_vol_info *vol = &vol_info[idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) unsigned int val, data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) int ch, changed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) mutex_lock(&chip->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) for (ch = 0; ch < 2; ch++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) val = ucontrol->value.integer.value[ch];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) if (val > vol->maxval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) val = vol->maxval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) if (val == wm->volumes[idx][ch])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) if (!val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) data = vol->mute;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) data = (val - 1) + vol->offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) data |= vol->update;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) changed |= wm8776_write_bits(chip->ice, wm, vol->regs[ch],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) vol->mask | vol->update, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) if (vol->mux_bits[ch])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) wm8776_write_bits(chip->ice, wm, WM8776_REG_ADC_MUX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) vol->mux_bits[ch],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) val ? 0 : vol->mux_bits[ch]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) wm->volumes[idx][ch] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) mutex_unlock(&chip->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) return changed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) }
^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) * WM8776 switch controls
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) #define COMPOSE_SW_VAL(idx, reg, mask) ((idx) | ((reg) << 8) | ((mask) << 16))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) #define GET_SW_VAL_IDX(val) ((val) & 0xff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) #define GET_SW_VAL_REG(val) (((val) >> 8) & 0xff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) #define GET_SW_VAL_MASK(val) (((val) >> 16) & 0xff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) #define maya_sw_info snd_ctl_boolean_mono_info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) static int maya_sw_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) struct snd_wm8776 *wm =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) &chip->wm[snd_ctl_get_ioff(kcontrol, &ucontrol->id)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) unsigned int idx = GET_SW_VAL_IDX(kcontrol->private_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) ucontrol->value.integer.value[0] = (wm->switch_bits >> idx) & 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) static int maya_sw_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) struct snd_wm8776 *wm =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) &chip->wm[snd_ctl_get_ioff(kcontrol, &ucontrol->id)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) unsigned int idx = GET_SW_VAL_IDX(kcontrol->private_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) unsigned int mask, val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) int changed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) mutex_lock(&chip->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) mask = 1 << idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) wm->switch_bits &= ~mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) val = ucontrol->value.integer.value[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) if (val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) wm->switch_bits |= mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) mask = GET_SW_VAL_MASK(kcontrol->private_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) changed = wm8776_write_bits(chip->ice, wm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) GET_SW_VAL_REG(kcontrol->private_value),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) mask, val ? mask : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) mutex_unlock(&chip->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) return changed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) * GPIO pins (known ones for maya44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) #define GPIO_PHANTOM_OFF 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) #define GPIO_MIC_RELAY 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) #define GPIO_SPDIF_IN_INV 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) #define GPIO_MUST_BE_0 7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) * GPIO switch controls
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) #define COMPOSE_GPIO_VAL(shift, inv) ((shift) | ((inv) << 8))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) #define GET_GPIO_VAL_SHIFT(val) ((val) & 0xff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) #define GET_GPIO_VAL_INV(val) (((val) >> 8) & 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) static int maya_set_gpio_bits(struct snd_ice1712 *ice, unsigned int mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) unsigned int bits)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) unsigned int data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) data = snd_ice1712_gpio_read(ice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) if ((data & mask) == bits)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) snd_ice1712_gpio_write(ice, (data & ~mask) | bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) #define maya_gpio_sw_info snd_ctl_boolean_mono_info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) static int maya_gpio_sw_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) unsigned int shift = GET_GPIO_VAL_SHIFT(kcontrol->private_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) val = (snd_ice1712_gpio_read(chip->ice) >> shift) & 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) if (GET_GPIO_VAL_INV(kcontrol->private_value))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) val = !val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) ucontrol->value.integer.value[0] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) static int maya_gpio_sw_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) unsigned int shift = GET_GPIO_VAL_SHIFT(kcontrol->private_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) unsigned int val, mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) int changed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) mutex_lock(&chip->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) mask = 1 << shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) val = ucontrol->value.integer.value[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) if (GET_GPIO_VAL_INV(kcontrol->private_value))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) val = !val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) val = val ? mask : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) changed = maya_set_gpio_bits(chip->ice, mask, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) mutex_unlock(&chip->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) return changed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) * capture source selection
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) /* known working input slots (0-4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) #define MAYA_LINE_IN 1 /* in-2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) #define MAYA_MIC_IN 3 /* in-4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) static void wm8776_select_input(struct snd_maya44 *chip, int idx, int line)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) wm8776_write_bits(chip->ice, &chip->wm[idx], WM8776_REG_ADC_MUX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 0x1f, 1 << line);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) static int maya_rec_src_info(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) static const char * const texts[] = { "Line", "Mic" };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(texts), texts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) static int maya_rec_src_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) int sel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) if (snd_ice1712_gpio_read(chip->ice) & (1 << GPIO_MIC_RELAY))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) sel = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) sel = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) ucontrol->value.enumerated.item[0] = sel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) static int maya_rec_src_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) int sel = ucontrol->value.enumerated.item[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) int changed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) mutex_lock(&chip->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) changed = maya_set_gpio_bits(chip->ice, 1 << GPIO_MIC_RELAY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) sel ? (1 << GPIO_MIC_RELAY) : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) wm8776_select_input(chip, 0, sel ? MAYA_MIC_IN : MAYA_LINE_IN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) mutex_unlock(&chip->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) return changed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) * Maya44 routing switch settings have different meanings than the standard
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) * ice1724 switches as defined in snd_vt1724_pro_route_info (ice1724.c).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) static int maya_pb_route_info(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) static const char * const texts[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) "PCM Out", /* 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) "Input 1", "Input 2", "Input 3", "Input 4"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(texts), texts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) static int maya_pb_route_shift(int idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) static const unsigned char shift[10] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) { 8, 20, 0, 3, 11, 23, 14, 26, 17, 29 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) return shift[idx % 10];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) static int maya_pb_route_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) ucontrol->value.enumerated.item[0] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) snd_ice1724_get_route_val(chip->ice, maya_pb_route_shift(idx));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) return 0;
^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) static int maya_pb_route_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) return snd_ice1724_put_route_val(chip->ice,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) ucontrol->value.enumerated.item[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) maya_pb_route_shift(idx));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) * controls to be added
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) static const struct snd_kcontrol_new maya_controls[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) .name = "Crossmix Playback Volume",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) SNDRV_CTL_ELEM_ACCESS_TLV_READ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) .info = maya_vol_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) .get = maya_vol_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) .put = maya_vol_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) .tlv = { .p = db_scale_hp },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) .private_value = WM_VOL_HP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) .count = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) .name = "PCM Playback Volume",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) SNDRV_CTL_ELEM_ACCESS_TLV_READ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) .info = maya_vol_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) .get = maya_vol_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) .put = maya_vol_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) .tlv = { .p = db_scale_dac },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) .private_value = WM_VOL_DAC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) .count = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) .name = "Line Capture Volume",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) SNDRV_CTL_ELEM_ACCESS_TLV_READ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) .info = maya_vol_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) .get = maya_vol_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) .put = maya_vol_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) .tlv = { .p = db_scale_adc },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) .private_value = WM_VOL_ADC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) .count = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) .name = "PCM Playback Switch",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) .info = maya_sw_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) .get = maya_sw_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) .put = maya_sw_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) .private_value = COMPOSE_SW_VAL(WM_SW_DAC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) WM8776_REG_OUTPUT_MUX, 0x01),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) .count = 2,
^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) .name = "Bypass Playback Switch",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) .info = maya_sw_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) .get = maya_sw_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) .put = maya_sw_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) .private_value = COMPOSE_SW_VAL(WM_SW_BYPASS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) WM8776_REG_OUTPUT_MUX, 0x04),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) .count = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) .name = "Capture Source",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) .info = maya_rec_src_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) .get = maya_rec_src_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) .put = maya_rec_src_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) .name = "Mic Phantom Power Switch",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) .info = maya_gpio_sw_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) .get = maya_gpio_sw_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) .put = maya_gpio_sw_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) .private_value = COMPOSE_GPIO_VAL(GPIO_PHANTOM_OFF, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) .name = "SPDIF Capture Switch",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) .info = maya_gpio_sw_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) .get = maya_gpio_sw_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) .put = maya_gpio_sw_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) .private_value = COMPOSE_GPIO_VAL(GPIO_SPDIF_IN_INV, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) .name = "H/W Playback Route",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) .info = maya_pb_route_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) .get = maya_pb_route_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) .put = maya_pb_route_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) .count = 4, /* FIXME: do controls 5-9 have any meaning? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) static int maya44_add_controls(struct snd_ice1712 *ice)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) int err, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) for (i = 0; i < ARRAY_SIZE(maya_controls); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) err = snd_ctl_add(ice->card, snd_ctl_new1(&maya_controls[i],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) ice->spec));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) * initialize a wm8776 chip
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) static void wm8776_init(struct snd_ice1712 *ice,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) struct snd_wm8776 *wm, unsigned int addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) static const unsigned short inits_wm8776[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) 0x02, 0x100, /* R2: headphone L+R muted + update */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) 0x05, 0x100, /* R5: DAC output L+R muted + update */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) 0x06, 0x000, /* R6: DAC output phase normal */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) 0x07, 0x091, /* R7: DAC enable zero cross detection,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) normal output */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) 0x08, 0x000, /* R8: DAC soft mute off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) 0x09, 0x000, /* R9: no deemph, DAC zero detect disabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) 0x0a, 0x022, /* R10: DAC I2C mode, std polarities, 24bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) 0x0b, 0x022, /* R11: ADC I2C mode, std polarities, 24bit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) highpass filter enabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) 0x0c, 0x042, /* R12: ADC+DAC slave, ADC+DAC 44,1kHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) 0x0d, 0x000, /* R13: all power up */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) 0x0e, 0x100, /* R14: ADC left muted,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) enable zero cross detection */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) 0x0f, 0x100, /* R15: ADC right muted,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) enable zero cross detection */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) /* R16: ALC...*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) 0x11, 0x000, /* R17: disable ALC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) /* R18: ALC...*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) /* R19: noise gate...*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) 0x15, 0x000, /* R21: ADC input mux init, mute all inputs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) 0x16, 0x001, /* R22: output mux, select DAC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) 0xff, 0xff
^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) const unsigned short *ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) unsigned char reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) unsigned short data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) wm->addr = addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) /* enable DAC output; mute bypass, aux & all inputs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) wm->switch_bits = (1 << WM_SW_DAC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) ptr = inits_wm8776;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) while (*ptr != 0xff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) reg = *ptr++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) data = *ptr++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) wm8776_write(ice, wm, reg, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) * change the rate on the WM8776 codecs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) * this assumes that the VT17xx's rate is changed by the calling function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) * NOTE: even though the WM8776's are running in slave mode and rate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) * selection is automatic, we need to call snd_wm8776_set_rate() here
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) * to make sure some flags are set correctly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) static void set_rate(struct snd_ice1712 *ice, unsigned int rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) struct snd_maya44 *chip = ice->spec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) unsigned int ratio, adc_ratio, val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) switch (rate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) case 192000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) ratio = WM8776_CLOCK_RATIO_128FS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) case 176400:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) ratio = WM8776_CLOCK_RATIO_128FS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) case 96000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) ratio = WM8776_CLOCK_RATIO_256FS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) case 88200:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) ratio = WM8776_CLOCK_RATIO_384FS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) case 48000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) ratio = WM8776_CLOCK_RATIO_512FS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) case 44100:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) ratio = WM8776_CLOCK_RATIO_512FS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) case 32000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) ratio = WM8776_CLOCK_RATIO_768FS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) /* no hint - S/PDIF input is master, simply return */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) snd_BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) * this currently sets the same rate for ADC and DAC, but limits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) * ADC rate to 256X (96kHz). For 256X mode (96kHz), this sets ADC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) * oversampling to 64x, as recommended by WM8776 datasheet.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) * Setting the rate is not really necessary in slave mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) adc_ratio = ratio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) if (adc_ratio < WM8776_CLOCK_RATIO_256FS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) adc_ratio = WM8776_CLOCK_RATIO_256FS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) val = adc_ratio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) if (adc_ratio == WM8776_CLOCK_RATIO_256FS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) val |= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) val |= ratio << 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) mutex_lock(&chip->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) for (i = 0; i < 2; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) wm8776_write_bits(ice, &chip->wm[i],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) WM8776_REG_MASTER_MODE_CONTROL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) 0x180, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) mutex_unlock(&chip->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) * supported sample rates (to override the default one)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) static const unsigned int rates[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) 32000, 44100, 48000, 64000, 88200, 96000, 176400, 192000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) /* playback rates: 32..192 kHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) static const struct snd_pcm_hw_constraint_list dac_rates = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) .count = ARRAY_SIZE(rates),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) .list = rates,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) .mask = 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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) * chip addresses on I2C bus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) static const unsigned char wm8776_addr[2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) 0x34, 0x36, /* codec 0 & 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) * initialize the chip
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) static int maya44_init(struct snd_ice1712 *ice)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) struct snd_maya44 *chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) chip = kzalloc(sizeof(*chip), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) if (!chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) mutex_init(&chip->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) chip->ice = ice;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) ice->spec = chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) /* initialise codecs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) ice->num_total_dacs = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) ice->num_total_adcs = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) ice->akm_codecs = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) for (i = 0; i < 2; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) wm8776_init(ice, &chip->wm[i], wm8776_addr[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) wm8776_select_input(chip, i, MAYA_LINE_IN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) /* set card specific rates */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) ice->hw_rates = &dac_rates;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) /* register change rate notifier */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) ice->gpio.set_pro_rate = set_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) /* RDMA1 (2nd input channel) is used for ADC by default */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) ice->force_rdma1 = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) /* have an own routing control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) ice->own_routing = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) * Maya44 boards don't provide the EEPROM data except for the vendor IDs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) * hence the driver needs to sets up it properly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) static const unsigned char maya44_eeprom[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) [ICE_EEP2_SYSCONF] = 0x45,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) /* clock xin1=49.152MHz, mpu401, 2 stereo ADCs+DACs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) [ICE_EEP2_ACLINK] = 0x80,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) /* I2S */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) [ICE_EEP2_I2S] = 0xf8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) /* vol, 96k, 24bit, 192k */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) [ICE_EEP2_SPDIF] = 0xc3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) /* enable spdif out, spdif out supp, spdif-in, ext spdif out */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) [ICE_EEP2_GPIO_DIR] = 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) [ICE_EEP2_GPIO_DIR1] = 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) [ICE_EEP2_GPIO_DIR2] = 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) [ICE_EEP2_GPIO_MASK] = 0/*0x9f*/,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) [ICE_EEP2_GPIO_MASK1] = 0/*0xff*/,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) [ICE_EEP2_GPIO_MASK2] = 0/*0x7f*/,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) [ICE_EEP2_GPIO_STATE] = (1 << GPIO_PHANTOM_OFF) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) (1 << GPIO_SPDIF_IN_INV),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) [ICE_EEP2_GPIO_STATE1] = 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) [ICE_EEP2_GPIO_STATE2] = 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) /* entry point */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) struct snd_ice1712_card_info snd_vt1724_maya44_cards[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) .subvendor = VT1724_SUBDEVICE_MAYA44,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) .name = "ESI Maya44",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) .model = "maya44",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) .chip_init = maya44_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) .build_controls = maya44_add_controls,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) .eeprom_size = sizeof(maya44_eeprom),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) .eeprom_data = maya44_eeprom,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) { } /* terminator */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) };