// SPDX-License-Identifier: GPL-2.0-or-later
/*
* ALSA driver for ICEnsemble VT1724 (Envy24HT)
*
* Lowlevel functions for Audiotrak Prodigy 7.1 Hifi
* based on pontis.c
*
* Copyright (c) 2007 Julian Scheel <julian@jusst.de>
* Copyright (c) 2007 allank
* Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
*/
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/mutex.h>
#include <sound/core.h>
#include <sound/info.h>
#include <sound/tlv.h>
#include "ice1712.h"
#include "envy24ht.h"
#include "prodigy_hifi.h"
struct prodigy_hifi_spec {
unsigned short master[2];
unsigned short vol[8];
};
/* I2C addresses */
#define WM_DEV 0x34
/* WM8776 registers */
#define WM_HP_ATTEN_L 0x00 /* headphone left attenuation */
#define WM_HP_ATTEN_R 0x01 /* headphone left attenuation */
#define WM_HP_MASTER 0x02 /* headphone master (both channels),
override LLR */
#define WM_DAC_ATTEN_L 0x03 /* digital left attenuation */
#define WM_DAC_ATTEN_R 0x04
#define WM_DAC_MASTER 0x05
#define WM_PHASE_SWAP 0x06 /* DAC phase swap */
#define WM_DAC_CTRL1 0x07
#define WM_DAC_MUTE 0x08
#define WM_DAC_CTRL2 0x09
#define WM_DAC_INT 0x0a
#define WM_ADC_INT 0x0b
#define WM_MASTER_CTRL 0x0c
#define WM_POWERDOWN 0x0d
#define WM_ADC_ATTEN_L 0x0e
#define WM_ADC_ATTEN_R 0x0f
#define WM_ALC_CTRL1 0x10
#define WM_ALC_CTRL2 0x11
#define WM_ALC_CTRL3 0x12
#define WM_NOISE_GATE 0x13
#define WM_LIMITER 0x14
#define WM_ADC_MUX 0x15
#define WM_OUT_MUX 0x16
#define WM_RESET 0x17
/* Analog Recording Source :- Mic, LineIn, CD/Video, */
/* implement capture source select control for WM8776 */
#define WM_AIN1 "AIN1"
#define WM_AIN2 "AIN2"
#define WM_AIN3 "AIN3"
#define WM_AIN4 "AIN4"
#define WM_AIN5 "AIN5"
/* GPIO pins of envy24ht connected to wm8766 */
#define WM8766_SPI_CLK (1<<17) /* CLK, Pin97 on ICE1724 */
#define WM8766_SPI_MD (1<<16) /* DATA VT1724 -> WM8766, Pin96 */
#define WM8766_SPI_ML (1<<18) /* Latch, Pin98 */
/* WM8766 registers */
#define WM8766_DAC_CTRL 0x02 /* DAC Control */
#define WM8766_INT_CTRL 0x03 /* Interface Control */
#define WM8766_DAC_CTRL2 0x09
#define WM8766_DAC_CTRL3 0x0a
#define WM8766_RESET 0x1f
#define WM8766_LDA1 0x00
#define WM8766_LDA2 0x04
#define WM8766_LDA3 0x06
#define WM8766_RDA1 0x01
#define WM8766_RDA2 0x05
#define WM8766_RDA3 0x07
#define WM8766_MUTE1 0x0C
#define WM8766_MUTE2 0x0F
/*
* Prodigy HD2
*/
#define AK4396_ADDR 0x00
#define AK4396_CSN (1 << 8) /* CSN->GPIO8, pin 75 */
#define AK4396_CCLK (1 << 9) /* CCLK->GPIO9, pin 76 */
#define AK4396_CDTI (1 << 10) /* CDTI->GPIO10, pin 77 */
/* ak4396 registers */
#define AK4396_CTRL1 0x00
#define AK4396_CTRL2 0x01
#define AK4396_CTRL3 0x02
#define AK4396_LCH_ATT 0x03
#define AK4396_RCH_ATT 0x04
/*
* get the current register value of WM codec
*/
static unsigned short wm_get(struct snd_ice1712 *ice, int reg)
{
reg <<= 1;
return ((unsigned short)ice->akm[0].images[reg] << 8) |
ice->akm[0].images[reg + 1];
}
/*
* set the register value of WM codec and remember it
*/
static void wm_put_nocache(struct snd_ice1712 *ice, int reg, unsigned short val)
{
unsigned short cval;
cval = (reg << 9) | val;
snd_vt1724_write_i2c(ice, WM_DEV, cval >> 8, cval & 0xff);
}
static void wm_put(struct snd_ice1712 *ice, int reg, unsigned short val)
{
wm_put_nocache(ice, reg, val);
reg <<= 1;
ice->akm[0].images[reg] = val >> 8;
ice->akm[0].images[reg + 1] = val;
}
/*
* write data in the SPI mode
*/
static void set_gpio_bit(struct