^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 Audiotrak Prodigy 7.1 Hifi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * based on pontis.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright (c) 2007 Julian Scheel <julian@jusst.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Copyright (c) 2007 allank
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <sound/core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <sound/info.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <sound/tlv.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include "ice1712.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include "envy24ht.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include "prodigy_hifi.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) struct prodigy_hifi_spec {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) unsigned short master[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) unsigned short vol[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) /* I2C addresses */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define WM_DEV 0x34
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) /* WM8776 registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define WM_HP_ATTEN_L 0x00 /* headphone left attenuation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define WM_HP_ATTEN_R 0x01 /* headphone left attenuation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define WM_HP_MASTER 0x02 /* headphone master (both channels),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) override LLR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define WM_DAC_ATTEN_L 0x03 /* digital left attenuation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define WM_DAC_ATTEN_R 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define WM_DAC_MASTER 0x05
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define WM_PHASE_SWAP 0x06 /* DAC phase swap */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define WM_DAC_CTRL1 0x07
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define WM_DAC_MUTE 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define WM_DAC_CTRL2 0x09
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define WM_DAC_INT 0x0a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define WM_ADC_INT 0x0b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define WM_MASTER_CTRL 0x0c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define WM_POWERDOWN 0x0d
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define WM_ADC_ATTEN_L 0x0e
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define WM_ADC_ATTEN_R 0x0f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define WM_ALC_CTRL1 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define WM_ALC_CTRL2 0x11
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define WM_ALC_CTRL3 0x12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define WM_NOISE_GATE 0x13
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define WM_LIMITER 0x14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define WM_ADC_MUX 0x15
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define WM_OUT_MUX 0x16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define WM_RESET 0x17
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) /* Analog Recording Source :- Mic, LineIn, CD/Video, */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) /* implement capture source select control for WM8776 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define WM_AIN1 "AIN1"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define WM_AIN2 "AIN2"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define WM_AIN3 "AIN3"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define WM_AIN4 "AIN4"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define WM_AIN5 "AIN5"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) /* GPIO pins of envy24ht connected to wm8766 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define WM8766_SPI_CLK (1<<17) /* CLK, Pin97 on ICE1724 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define WM8766_SPI_MD (1<<16) /* DATA VT1724 -> WM8766, Pin96 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define WM8766_SPI_ML (1<<18) /* Latch, Pin98 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) /* WM8766 registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define WM8766_DAC_CTRL 0x02 /* DAC Control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define WM8766_INT_CTRL 0x03 /* Interface Control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define WM8766_DAC_CTRL2 0x09
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #define WM8766_DAC_CTRL3 0x0a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define WM8766_RESET 0x1f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #define WM8766_LDA1 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #define WM8766_LDA2 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #define WM8766_LDA3 0x06
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define WM8766_RDA1 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #define WM8766_RDA2 0x05
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #define WM8766_RDA3 0x07
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #define WM8766_MUTE1 0x0C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #define WM8766_MUTE2 0x0F
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) * Prodigy HD2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #define AK4396_ADDR 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) #define AK4396_CSN (1 << 8) /* CSN->GPIO8, pin 75 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) #define AK4396_CCLK (1 << 9) /* CCLK->GPIO9, pin 76 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #define AK4396_CDTI (1 << 10) /* CDTI->GPIO10, pin 77 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) /* ak4396 registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #define AK4396_CTRL1 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) #define AK4396_CTRL2 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) #define AK4396_CTRL3 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) #define AK4396_LCH_ATT 0x03
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) #define AK4396_RCH_ATT 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) * get the current register value of WM codec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) static unsigned short wm_get(struct snd_ice1712 *ice, int reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) reg <<= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) return ((unsigned short)ice->akm[0].images[reg] << 8) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) ice->akm[0].images[reg + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) * set the register value of WM codec and remember it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) static void wm_put_nocache(struct snd_ice1712 *ice, int reg, unsigned short val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) unsigned short cval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) cval = (reg << 9) | val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) snd_vt1724_write_i2c(ice, WM_DEV, cval >> 8, cval & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) static void wm_put(struct snd_ice1712 *ice, int reg, unsigned short val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) wm_put_nocache(ice, reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) reg <<= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) ice->akm[0].images[reg] = val >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) ice->akm[0].images[reg + 1] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) * write data in the SPI mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) static void set_gpio_bit(struct snd_ice1712 *ice, unsigned int bit, int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) unsigned int tmp = snd_ice1712_gpio_read(ice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) if (val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) tmp |= bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) tmp &= ~bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) snd_ice1712_gpio_write(ice, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) * SPI implementation for WM8766 codec - only writing supported, no readback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) static void wm8766_spi_send_word(struct snd_ice1712 *ice, unsigned int data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) for (i = 0; i < 16; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) set_gpio_bit(ice, WM8766_SPI_CLK, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) set_gpio_bit(ice, WM8766_SPI_MD, data & 0x8000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) set_gpio_bit(ice, WM8766_SPI_CLK, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) data <<= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) }
^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 void wm8766_spi_write(struct snd_ice1712 *ice, unsigned int reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) unsigned int data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) unsigned int block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) snd_ice1712_gpio_set_dir(ice, WM8766_SPI_MD|
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) WM8766_SPI_CLK|WM8766_SPI_ML);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) snd_ice1712_gpio_set_mask(ice, ~(WM8766_SPI_MD|
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) WM8766_SPI_CLK|WM8766_SPI_ML));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) /* latch must be low when writing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) set_gpio_bit(ice, WM8766_SPI_ML, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) block = (reg << 9) | (data & 0x1ff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) wm8766_spi_send_word(ice, block); /* REGISTER ADDRESS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) /* release latch */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) set_gpio_bit(ice, WM8766_SPI_ML, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) /* restore */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) snd_ice1712_gpio_set_mask(ice, ice->gpio.write_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) snd_ice1712_gpio_set_dir(ice, ice->gpio.direction);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) * serial interface for ak4396 - only writing supported, no readback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) static void ak4396_send_word(struct snd_ice1712 *ice, unsigned int data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) for (i = 0; i < 16; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) set_gpio_bit(ice, AK4396_CCLK, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) set_gpio_bit(ice, AK4396_CDTI, data & 0x8000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) set_gpio_bit(ice, AK4396_CCLK, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) data <<= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) static void ak4396_write(struct snd_ice1712 *ice, unsigned int reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) unsigned int data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) unsigned int block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) snd_ice1712_gpio_set_dir(ice, AK4396_CSN|AK4396_CCLK|AK4396_CDTI);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) snd_ice1712_gpio_set_mask(ice, ~(AK4396_CSN|AK4396_CCLK|AK4396_CDTI));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) /* latch must be low when writing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) set_gpio_bit(ice, AK4396_CSN, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) block = ((AK4396_ADDR & 0x03) << 14) | (1 << 13) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) ((reg & 0x1f) << 8) | (data & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) ak4396_send_word(ice, block); /* REGISTER ADDRESS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) /* release latch */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) set_gpio_bit(ice, AK4396_CSN, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) /* restore */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) snd_ice1712_gpio_set_mask(ice, ice->gpio.write_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) snd_ice1712_gpio_set_dir(ice, ice->gpio.direction);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) * ak4396 mixers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) * DAC volume attenuation mixer control (-64dB to 0dB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) static int ak4396_dac_vol_info(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) uinfo->count = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) uinfo->value.integer.min = 0; /* mute */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) uinfo->value.integer.max = 0xFF; /* linear */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) static int ak4396_dac_vol_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) struct prodigy_hifi_spec *spec = ice->spec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) for (i = 0; i < 2; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) ucontrol->value.integer.value[i] = spec->vol[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) static int ak4396_dac_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) struct prodigy_hifi_spec *spec = ice->spec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) int change = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) mutex_lock(&ice->gpio_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) for (i = 0; i < 2; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) if (ucontrol->value.integer.value[i] != spec->vol[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) spec->vol[i] = ucontrol->value.integer.value[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) ak4396_write(ice, AK4396_LCH_ATT + i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) spec->vol[i] & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) change = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) mutex_unlock(&ice->gpio_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) return change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) static const DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -12700, 100, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) static const DECLARE_TLV_DB_LINEAR(ak4396_db_scale, TLV_DB_GAIN_MUTE, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) static const struct snd_kcontrol_new prodigy_hd2_controls[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) SNDRV_CTL_ELEM_ACCESS_TLV_READ),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) .name = "Front Playback Volume",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) .info = ak4396_dac_vol_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) .get = ak4396_dac_vol_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) .put = ak4396_dac_vol_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) .tlv = { .p = ak4396_db_scale },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) /* --------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) #define WM_VOL_MAX 255
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) #define WM_VOL_MUTE 0x8000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) #define DAC_0dB 0xff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) #define DAC_RES 128
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) #define DAC_MIN (DAC_0dB - DAC_RES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) static void wm_set_vol(struct snd_ice1712 *ice, unsigned int index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) unsigned short vol, unsigned short master)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) unsigned char nvol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) if ((master & WM_VOL_MUTE) || (vol & WM_VOL_MUTE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) nvol = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) nvol = (((vol & ~WM_VOL_MUTE) * (master & ~WM_VOL_MUTE)) / 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) & WM_VOL_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) nvol = (nvol ? (nvol + DAC_MIN) : 0) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) wm_put(ice, index, nvol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) wm_put_nocache(ice, index, 0x100 | nvol);
^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) static void wm8766_set_vol(struct snd_ice1712 *ice, unsigned int index,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) unsigned short vol, unsigned short master)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) unsigned char nvol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) if ((master & WM_VOL_MUTE) || (vol & WM_VOL_MUTE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) nvol = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) nvol = (((vol & ~WM_VOL_MUTE) * (master & ~WM_VOL_MUTE)) / 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) & WM_VOL_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) nvol = (nvol ? (nvol + DAC_MIN) : 0) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) wm8766_spi_write(ice, index, (0x0100 | nvol));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) }
^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) * DAC volume attenuation mixer control (-64dB to 0dB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) static int wm_dac_vol_info(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) uinfo->count = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) uinfo->value.integer.min = 0; /* mute */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) uinfo->value.integer.max = DAC_RES; /* 0dB, 0.5dB step */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) static int wm_dac_vol_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) struct prodigy_hifi_spec *spec = ice->spec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) for (i = 0; i < 2; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) ucontrol->value.integer.value[i] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) spec->vol[2 + i] & ~WM_VOL_MUTE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) static int wm_dac_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) struct prodigy_hifi_spec *spec = ice->spec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) int i, idx, change = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) mutex_lock(&ice->gpio_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) for (i = 0; i < 2; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) if (ucontrol->value.integer.value[i] != spec->vol[2 + i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) idx = WM_DAC_ATTEN_L + i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) spec->vol[2 + i] &= WM_VOL_MUTE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) spec->vol[2 + i] |= ucontrol->value.integer.value[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) wm_set_vol(ice, idx, spec->vol[2 + i], spec->master[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) change = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) mutex_unlock(&ice->gpio_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) return change;
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) * WM8766 DAC volume attenuation mixer control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) static int wm8766_vol_info(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) int voices = kcontrol->private_value >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) uinfo->count = voices;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) uinfo->value.integer.min = 0; /* mute */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) uinfo->value.integer.max = DAC_RES; /* 0dB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) static int wm8766_vol_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) struct prodigy_hifi_spec *spec = ice->spec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) int i, ofs, voices;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) voices = kcontrol->private_value >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) ofs = kcontrol->private_value & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) for (i = 0; i < voices; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) ucontrol->value.integer.value[i] = spec->vol[ofs + i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) return 0;
^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) static int wm8766_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) struct prodigy_hifi_spec *spec = ice->spec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) int i, idx, ofs, voices;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) int change = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) voices = kcontrol->private_value >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) ofs = kcontrol->private_value & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) mutex_lock(&ice->gpio_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) for (i = 0; i < voices; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) if (ucontrol->value.integer.value[i] != spec->vol[ofs + i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) idx = WM8766_LDA1 + ofs + i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) spec->vol[ofs + i] &= WM_VOL_MUTE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) spec->vol[ofs + i] |= ucontrol->value.integer.value[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) wm8766_set_vol(ice, idx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) spec->vol[ofs + i], spec->master[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) change = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) mutex_unlock(&ice->gpio_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) return change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) * Master volume attenuation mixer control / applied to WM8776+WM8766
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) static int wm_master_vol_info(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) uinfo->count = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) uinfo->value.integer.min = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) uinfo->value.integer.max = DAC_RES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) return 0;
^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) static int wm_master_vol_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) struct prodigy_hifi_spec *spec = ice->spec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) for (i = 0; i < 2; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) ucontrol->value.integer.value[i] = spec->master[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) static int wm_master_vol_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) struct prodigy_hifi_spec *spec = ice->spec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) int ch, change = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) mutex_lock(&ice->gpio_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) for (ch = 0; ch < 2; ch++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) if (ucontrol->value.integer.value[ch] != spec->master[ch]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) spec->master[ch] = ucontrol->value.integer.value[ch];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) /* Apply to front DAC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) wm_set_vol(ice, WM_DAC_ATTEN_L + ch,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) spec->vol[2 + ch], spec->master[ch]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) wm8766_set_vol(ice, WM8766_LDA1 + ch,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) spec->vol[0 + ch], spec->master[ch]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) wm8766_set_vol(ice, WM8766_LDA2 + ch,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) spec->vol[4 + ch], spec->master[ch]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) wm8766_set_vol(ice, WM8766_LDA3 + ch,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) spec->vol[6 + ch], spec->master[ch]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) change = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) mutex_unlock(&ice->gpio_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) return change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) /* KONSTI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) static int wm_adc_mux_enum_info(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) static const char * const texts[32] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) "NULL", WM_AIN1, WM_AIN2, WM_AIN1 "+" WM_AIN2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) WM_AIN3, WM_AIN1 "+" WM_AIN3, WM_AIN2 "+" WM_AIN3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) WM_AIN1 "+" WM_AIN2 "+" WM_AIN3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) WM_AIN4, WM_AIN1 "+" WM_AIN4, WM_AIN2 "+" WM_AIN4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) WM_AIN1 "+" WM_AIN2 "+" WM_AIN4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) WM_AIN3 "+" WM_AIN4, WM_AIN1 "+" WM_AIN3 "+" WM_AIN4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) WM_AIN2 "+" WM_AIN3 "+" WM_AIN4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) WM_AIN1 "+" WM_AIN2 "+" WM_AIN3 "+" WM_AIN4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) WM_AIN5, WM_AIN1 "+" WM_AIN5, WM_AIN2 "+" WM_AIN5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) WM_AIN1 "+" WM_AIN2 "+" WM_AIN5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) WM_AIN3 "+" WM_AIN5, WM_AIN1 "+" WM_AIN3 "+" WM_AIN5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) WM_AIN2 "+" WM_AIN3 "+" WM_AIN5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) WM_AIN1 "+" WM_AIN2 "+" WM_AIN3 "+" WM_AIN5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) WM_AIN4 "+" WM_AIN5, WM_AIN1 "+" WM_AIN4 "+" WM_AIN5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) WM_AIN2 "+" WM_AIN4 "+" WM_AIN5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) WM_AIN1 "+" WM_AIN2 "+" WM_AIN4 "+" WM_AIN5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) WM_AIN3 "+" WM_AIN4 "+" WM_AIN5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) WM_AIN1 "+" WM_AIN3 "+" WM_AIN4 "+" WM_AIN5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) WM_AIN2 "+" WM_AIN3 "+" WM_AIN4 "+" WM_AIN5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) WM_AIN1 "+" WM_AIN2 "+" WM_AIN3 "+" WM_AIN4 "+" WM_AIN5
^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) return snd_ctl_enum_info(uinfo, 1, 32, texts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) static int wm_adc_mux_enum_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) mutex_lock(&ice->gpio_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) ucontrol->value.enumerated.item[0] = wm_get(ice, WM_ADC_MUX) & 0x1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) mutex_unlock(&ice->gpio_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) static int wm_adc_mux_enum_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) unsigned short oval, nval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) int change = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) mutex_lock(&ice->gpio_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) oval = wm_get(ice, WM_ADC_MUX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) nval = (oval & 0xe0) | ucontrol->value.enumerated.item[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) if (nval != oval) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) wm_put(ice, WM_ADC_MUX, nval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) change = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) mutex_unlock(&ice->gpio_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) return change;
^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) /* KONSTI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) * ADC gain mixer control (-64dB to 0dB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) #define ADC_0dB 0xcf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) #define ADC_RES 128
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) #define ADC_MIN (ADC_0dB - ADC_RES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) static int wm_adc_vol_info(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) uinfo->count = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) uinfo->value.integer.min = 0; /* mute (-64dB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) uinfo->value.integer.max = ADC_RES; /* 0dB, 0.5dB step */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) static int wm_adc_vol_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) unsigned short val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) mutex_lock(&ice->gpio_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) for (i = 0; i < 2; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) val = wm_get(ice, WM_ADC_ATTEN_L + i) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) val = val > ADC_MIN ? (val - ADC_MIN) : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) ucontrol->value.integer.value[i] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) mutex_unlock(&ice->gpio_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) static int wm_adc_vol_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) unsigned short ovol, nvol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) int i, idx, change = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) mutex_lock(&ice->gpio_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) for (i = 0; i < 2; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) nvol = ucontrol->value.integer.value[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) nvol = nvol ? (nvol + ADC_MIN) : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) idx = WM_ADC_ATTEN_L + i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) ovol = wm_get(ice, idx) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) if (ovol != nvol) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) wm_put(ice, idx, nvol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) change = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) mutex_unlock(&ice->gpio_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) return change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) * ADC input mux mixer control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) #define wm_adc_mux_info snd_ctl_boolean_mono_info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) static int wm_adc_mux_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) int bit = kcontrol->private_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) mutex_lock(&ice->gpio_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) ucontrol->value.integer.value[0] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) (wm_get(ice, WM_ADC_MUX) & (1 << bit)) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) mutex_unlock(&ice->gpio_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) static int wm_adc_mux_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) int bit = kcontrol->private_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) unsigned short oval, nval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) int change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) mutex_lock(&ice->gpio_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) nval = oval = wm_get(ice, WM_ADC_MUX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) if (ucontrol->value.integer.value[0])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) nval |= (1 << bit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) nval &= ~(1 << bit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) change = nval != oval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) if (change) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) wm_put(ice, WM_ADC_MUX, nval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) mutex_unlock(&ice->gpio_mutex);
^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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) * Analog bypass (In -> Out)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) #define wm_bypass_info snd_ctl_boolean_mono_info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) static int wm_bypass_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) mutex_lock(&ice->gpio_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) ucontrol->value.integer.value[0] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) (wm_get(ice, WM_OUT_MUX) & 0x04) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) mutex_unlock(&ice->gpio_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) static int wm_bypass_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) unsigned short val, oval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) int change = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) mutex_lock(&ice->gpio_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) val = oval = wm_get(ice, WM_OUT_MUX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) if (ucontrol->value.integer.value[0])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) val |= 0x04;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) val &= ~0x04;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) if (val != oval) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) wm_put(ice, WM_OUT_MUX, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) change = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) mutex_unlock(&ice->gpio_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) return change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) * Left/Right swap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) #define wm_chswap_info snd_ctl_boolean_mono_info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) static int wm_chswap_get(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) mutex_lock(&ice->gpio_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) ucontrol->value.integer.value[0] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) (wm_get(ice, WM_DAC_CTRL1) & 0xf0) != 0x90;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) mutex_unlock(&ice->gpio_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) static int wm_chswap_put(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) unsigned short val, oval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) int change = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) mutex_lock(&ice->gpio_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) oval = wm_get(ice, WM_DAC_CTRL1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) val = oval & 0x0f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) if (ucontrol->value.integer.value[0])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) val |= 0x60;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) val |= 0x90;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) if (val != oval) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) wm_put(ice, WM_DAC_CTRL1, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) wm_put_nocache(ice, WM_DAC_CTRL1, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) change = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) mutex_unlock(&ice->gpio_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) return change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) * mixers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) static const struct snd_kcontrol_new prodigy_hifi_controls[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) SNDRV_CTL_ELEM_ACCESS_TLV_READ),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) .name = "Master Playback Volume",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) .info = wm_master_vol_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) .get = wm_master_vol_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) .put = wm_master_vol_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) .tlv = { .p = db_scale_wm_dac }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) SNDRV_CTL_ELEM_ACCESS_TLV_READ),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) .name = "Front Playback Volume",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) .info = wm_dac_vol_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) .get = wm_dac_vol_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) .put = wm_dac_vol_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) .tlv = { .p = db_scale_wm_dac },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) SNDRV_CTL_ELEM_ACCESS_TLV_READ),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) .name = "Rear Playback Volume",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) .info = wm8766_vol_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) .get = wm8766_vol_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) .put = wm8766_vol_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) .private_value = (2 << 8) | 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) .tlv = { .p = db_scale_wm_dac },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) SNDRV_CTL_ELEM_ACCESS_TLV_READ),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) .name = "Center Playback Volume",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) .info = wm8766_vol_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) .get = wm8766_vol_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) .put = wm8766_vol_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) .private_value = (1 << 8) | 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) .tlv = { .p = db_scale_wm_dac }
^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) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) SNDRV_CTL_ELEM_ACCESS_TLV_READ),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) .name = "LFE Playback Volume",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) .info = wm8766_vol_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) .get = wm8766_vol_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) .put = wm8766_vol_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) .private_value = (1 << 8) | 5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) .tlv = { .p = db_scale_wm_dac }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) SNDRV_CTL_ELEM_ACCESS_TLV_READ),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) .name = "Side Playback Volume",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) .info = wm8766_vol_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) .get = wm8766_vol_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) .put = wm8766_vol_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) .private_value = (2 << 8) | 6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) .tlv = { .p = db_scale_wm_dac },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) SNDRV_CTL_ELEM_ACCESS_TLV_READ),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) .name = "Capture Volume",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) .info = wm_adc_vol_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) .get = wm_adc_vol_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) .put = wm_adc_vol_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) .tlv = { .p = db_scale_wm_dac },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) .name = "CD Capture Switch",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) .info = wm_adc_mux_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) .get = wm_adc_mux_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) .put = wm_adc_mux_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) .private_value = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) .name = "Line Capture Switch",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) .info = wm_adc_mux_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) .get = wm_adc_mux_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) .put = wm_adc_mux_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) .private_value = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) .name = "Analog Bypass Switch",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) .info = wm_bypass_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) .get = wm_bypass_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) .put = wm_bypass_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) .name = "Swap Output Channels",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) .info = wm_chswap_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) .get = wm_chswap_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) .put = wm_chswap_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) .name = "Analog Capture Source",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) .info = wm_adc_mux_enum_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) .get = wm_adc_mux_enum_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) .put = wm_adc_mux_enum_put,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) * WM codec registers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) static void wm_proc_regs_write(struct snd_info_entry *entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) struct snd_info_buffer *buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) struct snd_ice1712 *ice = entry->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) char line[64];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) unsigned int reg, val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) mutex_lock(&ice->gpio_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) while (!snd_info_get_line(buffer, line, sizeof(line))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) if (sscanf(line, "%x %x", ®, &val) != 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) if (reg <= 0x17 && val <= 0xffff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) wm_put(ice, reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) mutex_unlock(&ice->gpio_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) static void wm_proc_regs_read(struct snd_info_entry *entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) struct snd_info_buffer *buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) struct snd_ice1712 *ice = entry->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) int reg, val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) mutex_lock(&ice->gpio_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) for (reg = 0; reg <= 0x17; reg++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) val = wm_get(ice, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) snd_iprintf(buffer, "%02x = %04x\n", reg, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) mutex_unlock(&ice->gpio_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) static void wm_proc_init(struct snd_ice1712 *ice)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) snd_card_rw_proc_new(ice->card, "wm_codec", ice, wm_proc_regs_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) wm_proc_regs_write);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) static int prodigy_hifi_add_controls(struct snd_ice1712 *ice)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) for (i = 0; i < ARRAY_SIZE(prodigy_hifi_controls); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) err = snd_ctl_add(ice->card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) snd_ctl_new1(&prodigy_hifi_controls[i], ice));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) wm_proc_init(ice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910)
^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 prodigy_hd2_add_controls(struct snd_ice1712 *ice)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) for (i = 0; i < ARRAY_SIZE(prodigy_hd2_controls); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) err = snd_ctl_add(ice->card,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) snd_ctl_new1(&prodigy_hd2_controls[i], ice));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) wm_proc_init(ice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) static void wm8766_init(struct snd_ice1712 *ice)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) static const unsigned short wm8766_inits[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) WM8766_RESET, 0x0000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) WM8766_DAC_CTRL, 0x0120,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) WM8766_INT_CTRL, 0x0022, /* I2S Normal Mode, 24 bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) WM8766_DAC_CTRL2, 0x0001,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) WM8766_DAC_CTRL3, 0x0080,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) WM8766_LDA1, 0x0100,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) WM8766_LDA2, 0x0100,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) WM8766_LDA3, 0x0100,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) WM8766_RDA1, 0x0100,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) WM8766_RDA2, 0x0100,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) WM8766_RDA3, 0x0100,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) WM8766_MUTE1, 0x0000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) WM8766_MUTE2, 0x0000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) for (i = 0; i < ARRAY_SIZE(wm8766_inits); i += 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) wm8766_spi_write(ice, wm8766_inits[i], wm8766_inits[i + 1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) static void wm8776_init(struct snd_ice1712 *ice)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) static const unsigned short wm8776_inits[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) /* These come first to reduce init pop noise */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) WM_ADC_MUX, 0x0003, /* ADC mute */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) /* 0x00c0 replaced by 0x0003 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) WM_DAC_MUTE, 0x0001, /* DAC softmute */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) WM_DAC_CTRL1, 0x0000, /* DAC mute */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) WM_POWERDOWN, 0x0008, /* All power-up except HP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) WM_RESET, 0x0000, /* reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) for (i = 0; i < ARRAY_SIZE(wm8776_inits); i += 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) wm_put(ice, wm8776_inits[i], wm8776_inits[i + 1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) #ifdef CONFIG_PM_SLEEP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) static int prodigy_hifi_resume(struct snd_ice1712 *ice)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) static const unsigned short wm8776_reinit_registers[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) WM_MASTER_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) WM_DAC_INT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) WM_ADC_INT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) WM_OUT_MUX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) WM_HP_ATTEN_L,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) WM_HP_ATTEN_R,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) WM_PHASE_SWAP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) WM_DAC_CTRL2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) WM_ADC_ATTEN_L,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) WM_ADC_ATTEN_R,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) WM_ALC_CTRL1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) WM_ALC_CTRL2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) WM_ALC_CTRL3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) WM_NOISE_GATE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) WM_ADC_MUX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) /* no DAC attenuation here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) struct prodigy_hifi_spec *spec = ice->spec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) int i, ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) mutex_lock(&ice->gpio_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) /* reinitialize WM8776 and re-apply old register values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) wm8776_init(ice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) schedule_timeout_uninterruptible(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) for (i = 0; i < ARRAY_SIZE(wm8776_reinit_registers); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) wm_put(ice, wm8776_reinit_registers[i],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) wm_get(ice, wm8776_reinit_registers[i]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) /* reinitialize WM8766 and re-apply volumes for all DACs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) wm8766_init(ice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) for (ch = 0; ch < 2; ch++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) wm_set_vol(ice, WM_DAC_ATTEN_L + ch,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) spec->vol[2 + ch], spec->master[ch]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) wm8766_set_vol(ice, WM8766_LDA1 + ch,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) spec->vol[0 + ch], spec->master[ch]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) wm8766_set_vol(ice, WM8766_LDA2 + ch,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) spec->vol[4 + ch], spec->master[ch]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) wm8766_set_vol(ice, WM8766_LDA3 + ch,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) spec->vol[6 + ch], spec->master[ch]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) /* unmute WM8776 DAC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) wm_put(ice, WM_DAC_MUTE, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) wm_put(ice, WM_DAC_CTRL1, 0x90);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) mutex_unlock(&ice->gpio_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) * initialize the chip
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) static int prodigy_hifi_init(struct snd_ice1712 *ice)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) static const unsigned short wm8776_defaults[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) WM_MASTER_CTRL, 0x0022, /* 256fs, slave mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) WM_DAC_INT, 0x0022, /* I2S, normal polarity, 24bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) WM_ADC_INT, 0x0022, /* I2S, normal polarity, 24bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) WM_DAC_CTRL1, 0x0090, /* DAC L/R */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) WM_OUT_MUX, 0x0001, /* OUT DAC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) WM_HP_ATTEN_L, 0x0179, /* HP 0dB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) WM_HP_ATTEN_R, 0x0179, /* HP 0dB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) WM_DAC_ATTEN_L, 0x0000, /* DAC 0dB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) WM_DAC_ATTEN_L, 0x0100, /* DAC 0dB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) WM_DAC_ATTEN_R, 0x0000, /* DAC 0dB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) WM_DAC_ATTEN_R, 0x0100, /* DAC 0dB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) WM_PHASE_SWAP, 0x0000, /* phase normal */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) WM_DAC_MASTER, 0x0100, /* DAC master muted */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) WM_DAC_CTRL2, 0x0000, /* no deemphasis, no ZFLG */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) WM_ADC_ATTEN_L, 0x0000, /* ADC muted */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) WM_ADC_ATTEN_R, 0x0000, /* ADC muted */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) #if 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) WM_ALC_CTRL1, 0x007b, /* */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) WM_ALC_CTRL2, 0x0000, /* */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) WM_ALC_CTRL3, 0x0000, /* */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) WM_NOISE_GATE, 0x0000, /* */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) WM_DAC_MUTE, 0x0000, /* DAC unmute */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) WM_ADC_MUX, 0x0003, /* ADC unmute, both CD/Line On */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) struct prodigy_hifi_spec *spec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) ice->vt1720 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) ice->vt1724 = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) ice->num_total_dacs = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) ice->num_total_adcs = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) /* HACK - use this as the SPDIF source.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) * don't call snd_ice1712_gpio_get/put(), otherwise it's overwritten
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) ice->gpio.saved[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) /* to remember the register values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) if (! ice->akm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) ice->akm_codecs = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) spec = kzalloc(sizeof(*spec), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) if (!spec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) ice->spec = spec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) /* initialize WM8776 codec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) wm8776_init(ice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) schedule_timeout_uninterruptible(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) for (i = 0; i < ARRAY_SIZE(wm8776_defaults); i += 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) wm_put(ice, wm8776_defaults[i], wm8776_defaults[i + 1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) wm8766_init(ice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) #ifdef CONFIG_PM_SLEEP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) ice->pm_resume = &prodigy_hifi_resume;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) ice->pm_suspend_enabled = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) * initialize the chip
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) static void ak4396_init(struct snd_ice1712 *ice)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) static const unsigned short ak4396_inits[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) AK4396_CTRL1, 0x87, /* I2S Normal Mode, 24 bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) AK4396_CTRL2, 0x02,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) AK4396_CTRL3, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) AK4396_LCH_ATT, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) AK4396_RCH_ATT, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) /* initialize ak4396 codec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) /* reset codec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) ak4396_write(ice, AK4396_CTRL1, 0x86);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) msleep(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) ak4396_write(ice, AK4396_CTRL1, 0x87);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) for (i = 0; i < ARRAY_SIZE(ak4396_inits); i += 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) ak4396_write(ice, ak4396_inits[i], ak4396_inits[i+1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) #ifdef CONFIG_PM_SLEEP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) static int prodigy_hd2_resume(struct snd_ice1712 *ice)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) /* initialize ak4396 codec and restore previous mixer volumes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) struct prodigy_hifi_spec *spec = ice->spec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) mutex_lock(&ice->gpio_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) ak4396_init(ice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) for (i = 0; i < 2; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) ak4396_write(ice, AK4396_LCH_ATT + i, spec->vol[i] & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) mutex_unlock(&ice->gpio_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) static int prodigy_hd2_init(struct snd_ice1712 *ice)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) struct prodigy_hifi_spec *spec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) ice->vt1720 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) ice->vt1724 = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) ice->num_total_dacs = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) ice->num_total_adcs = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) /* HACK - use this as the SPDIF source.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) * don't call snd_ice1712_gpio_get/put(), otherwise it's overwritten
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) ice->gpio.saved[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) /* to remember the register values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) if (! ice->akm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) ice->akm_codecs = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) spec = kzalloc(sizeof(*spec), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) if (!spec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) ice->spec = spec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) #ifdef CONFIG_PM_SLEEP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) ice->pm_resume = &prodigy_hd2_resume;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) ice->pm_suspend_enabled = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) ak4396_init(ice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) static const unsigned char prodigy71hifi_eeprom[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) 0x4b, /* SYSCONF: clock 512, spdif-in/ADC, 4DACs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) 0x80, /* ACLINK: I2S */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) 0xfc, /* I2S: vol, 96k, 24bit, 192k */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) 0xc3, /* SPDIF: out-en, out-int, spdif-in */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) 0xff, /* GPIO_DIR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) 0xff, /* GPIO_DIR1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) 0x5f, /* GPIO_DIR2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) 0x00, /* GPIO_MASK */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) 0x00, /* GPIO_MASK1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) 0x00, /* GPIO_MASK2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) 0x00, /* GPIO_STATE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) 0x00, /* GPIO_STATE1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) 0x00, /* GPIO_STATE2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) static const unsigned char prodigyhd2_eeprom[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) 0x4b, /* SYSCONF: clock 512, spdif-in/ADC, 4DACs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) 0x80, /* ACLINK: I2S */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) 0xfc, /* I2S: vol, 96k, 24bit, 192k */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) 0xc3, /* SPDIF: out-en, out-int, spdif-in */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) 0xff, /* GPIO_DIR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) 0xff, /* GPIO_DIR1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) 0x5f, /* GPIO_DIR2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) 0x00, /* GPIO_MASK */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) 0x00, /* GPIO_MASK1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) 0x00, /* GPIO_MASK2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) 0x00, /* GPIO_STATE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) 0x00, /* GPIO_STATE1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) 0x00, /* GPIO_STATE2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) static const unsigned char fortissimo4_eeprom[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) 0x43, /* SYSCONF: clock 512, ADC, 4DACs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) 0x80, /* ACLINK: I2S */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) 0xfc, /* I2S: vol, 96k, 24bit, 192k */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) 0xc1, /* SPDIF: out-en, out-int */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) 0xff, /* GPIO_DIR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) 0xff, /* GPIO_DIR1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) 0x5f, /* GPIO_DIR2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) 0x00, /* GPIO_MASK */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) 0x00, /* GPIO_MASK1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) 0x00, /* GPIO_MASK2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) 0x00, /* GPIO_STATE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) 0x00, /* GPIO_STATE1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) 0x00, /* GPIO_STATE2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) /* entry point */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) struct snd_ice1712_card_info snd_vt1724_prodigy_hifi_cards[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) .subvendor = VT1724_SUBDEVICE_PRODIGY_HIFI,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) .name = "Audiotrak Prodigy 7.1 HiFi",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) .model = "prodigy71hifi",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) .chip_init = prodigy_hifi_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) .build_controls = prodigy_hifi_add_controls,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) .eeprom_size = sizeof(prodigy71hifi_eeprom),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) .eeprom_data = prodigy71hifi_eeprom,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) .driver = "Prodigy71HIFI",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) .subvendor = VT1724_SUBDEVICE_PRODIGY_HD2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) .name = "Audiotrak Prodigy HD2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) .model = "prodigyhd2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) .chip_init = prodigy_hd2_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) .build_controls = prodigy_hd2_add_controls,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) .eeprom_size = sizeof(prodigyhd2_eeprom),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) .eeprom_data = prodigyhd2_eeprom,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) .driver = "Prodigy71HD2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) .subvendor = VT1724_SUBDEVICE_FORTISSIMO4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) .name = "Hercules Fortissimo IV",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) .model = "fortissimo4",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) .chip_init = prodigy_hifi_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) .build_controls = prodigy_hifi_add_controls,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) .eeprom_size = sizeof(fortissimo4_eeprom),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) .eeprom_data = fortissimo4_eeprom,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) .driver = "Fortissimo4",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) { } /* terminator */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265)