/*
* card driver for models with PCM1796 DACs (Xonar D2/D2X/HDAV1.3/ST/STX)
*
* Copyright (c) Clemens Ladisch <clemens@ladisch.de>
*
*
* This driver is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, version 2.
*
* This driver is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this driver; if not, see <http://www.gnu.org/licenses/>.
*/
/*
* Xonar D2/D2X
* ------------
*
* CMI8788:
*
* SPI 0 -> 1st PCM1796 (front)
* SPI 1 -> 2nd PCM1796 (surround)
* SPI 2 -> 3rd PCM1796 (center/LFE)
* SPI 4 -> 4th PCM1796 (back)
*
* GPIO 2 -> M0 of CS5381
* GPIO 3 -> M1 of CS5381
* GPIO 5 <- external power present (D2X only)
* GPIO 7 -> ALT
* GPIO 8 -> enable output to speakers
*
* CM9780:
*
* LINE_OUT -> input of ADC
*
* AUX_IN <- aux
* VIDEO_IN <- CD
* FMIC_IN <- mic
*
* GPO 0 -> route line-in (0) or AC97 output (1) to CS5381 input
*/
/*
* Xonar HDAV1.3 (Deluxe)
* ----------------------
*
* CMI8788:
*
* I²C <-> PCM1796 (addr 1001100) (front)
*
* GPI 0 <- external power present
*
* GPIO 0 -> enable HDMI (0) or speaker (1) output
* GPIO 2 -> M0 of CS5381
* GPIO 3 -> M1 of CS5381
* GPIO 4 <- daughterboard detection
* GPIO 5 <- daughterboard detection
* GPIO 6 -> ?
* GPIO 7 -> ?
* GPIO 8 -> route input jack to line-in (0) or mic-in (1)
*
* UART <-> HDMI controller
*
* CM9780:
*
* LINE_OUT -> input of ADC
*
* AUX_IN <- aux
* CD_IN <- CD
* MIC_IN <- mic
*
* GPO 0 -> route line-in (0) or AC97 output (1) to CS5381 input
*
* no daughterboard
* ----------------
*
* GPIO 4 <- 1
*
* H6 daughterboard
* ----------------
*
* GPIO 4 <- 0
* GPIO 5 <- 0
*
* I²C <-> PCM1796 (addr 1001101) (surround)
* <-> PCM1796 (addr 1001110) (center/LFE)
* <-> PCM1796 (addr 1001111) (back)
*
* unknown daughterboard
* ---------------------
*
* GPIO 4 <- 0
* GPIO 5 <- 1
*
* I²C <-> CS4362A (addr 0011000) (surround, center/LFE, back)
*/
/*
* Xonar Essence ST (Deluxe)/STX
* -----------------------------
*
* CMI8788:
*
* I²C <-> PCM1792A (addr 1001100)
* <-> CS2000 (addr 1001110) (ST only)
*
* ADC1 MCLK -> REF_CLK of CS2000 (ST only)
*
* GPI 0 <- external power present (STX only)
*
* GPIO 0 -> enable output to speakers
* GPIO 1 -> route HP to front panel (0) or rear jack (1)
* GPIO 2 -> M0 of CS5381
* GPIO 3 -> M1 of CS5381
* GPIO 4 <- daughterboard detection
* GPIO 5 <- daughterboard detection
* GPIO 6 -> ?
* GPIO 7 -> route output to speaker jacks (0) or HP (1)
* GPIO 8 -> route input jack to line-in (0) or mic-in (1)
*
* PCM1792A:
*
* SCK <- CLK_OUT of CS2000 (ST only)
*
* CM9780:
*
* LINE_OUT -> input of ADC
*
* AUX_IN <- aux
* MIC_IN <- mic
*
* GPO 0 -> route line-in (0) or AC97 output (1) to CS5381 input
*
* H6 daughterboard
* ----------------
*
* GPIO 4 <- 0
* GPIO 5 <- 0
*/
/*
* Xonar Xense
* -----------
*
* CMI8788:
*
* I²C <-> PCM1796 (addr 1001100) (front)
* <-> CS4362A (addr 0011000) (surround, center/LFE, back)
* <-> CS2000 (addr 1001110)
*
* ADC1 MCLK -> REF_CLK of CS2000
*
* GPI 0 <- external power present
*
* GPIO 0 -> enable output
* GPIO 1 -> route HP to front panel (0) or rear jack (1)
* GPIO 2 -> M0 of CS5381
* GPIO 3 -> M1 of CS5381
* GPIO 4 -> enable output
* GPIO 5 -> enable output
* GPIO 6 -> ?
* GPIO 7 -> route output to HP (0) or speaker (1)
* GPIO 8 -> route input jack to mic-in (0) or line-in (1)
*
* CM9780:
*
* LINE_OUT -> input of ADC
*
* AUX_IN <- aux
* VIDEO_IN <- ?
* FMIC_IN <- mic
*
* GPO 0 -> route line-in (0) or AC97 output (1) to CS5381 input
* GPO 1 -> route mic-in from input jack (0) or front panel header (1)
*/
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/mutex.h>
#include <sound/ac97_codec.h>
#include <sound/control.h>
#include <sound/core.h>
#include <sound/info.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/tlv.h>
#include "xonar.h"
#include "cm9780.h"
#include "pcm1796.h"
#include "cs2000.h"
#define GPIO_D2X_EXT_POWER 0x0020
#define GPIO_D2_ALT 0x0080
#define GPIO_D2_OUTPUT_ENABLE 0x0100
#define GPI_EXT_POWER 0x01
#define GPIO_INPUT_ROUTE 0x0100
#define GPIO_HDAV_OUTPUT_ENABLE 0x0001
#define GPIO_HDAV_MAGIC 0x00c0
#define GPIO_DB_MASK 0x0030
#define GPIO_DB_H6 0x0000
#define GPIO_ST_OUTPUT_ENABLE 0x0001
#define GPIO_ST_HP_REAR 0x0002
#define GPIO_ST_MAGIC 0x0040
#define GPIO_ST_HP 0x0080
#define I2C_DEVICE_PCM1796(i) (0x98 + ((i) << 1)) /* 10011, ii, /W=0 */
#define I2C_DEVICE_CS2000 0x9c /* 100111, 0, /W=0 */
#define PCM1796_REG_BASE 16
struct xonar_pcm179x {
struct xonar_generic generic;
unsigned int dacs;
u8 pcm1796_regs[4][5];
unsigned int current_rate;
bool h6;
bool hp_active;
s8 hp_gain_offset;
bool has_cs2000;
u8 cs2000_regs[0x1f];
bool broken_i2c;
};
struct xonar_hdav {
struct xonar_pcm179x pcm179x;
struct xonar_hdmi hdmi;
};
static inline void pcm1796_write_spi(struct oxygen *chip, unsigned int codec,
u8 reg, u8 value)
{
/* maps ALSA channel pair number to SPI output */
static const u8 codec_map[4] = {
0, 1, 2, 4
};
oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER |
OXYGEN_SPI_DATA_LENGTH_2 |
OXYGEN_SPI_CLOCK_160 |
(codec_map[codec] << OXYGEN_SPI_CODEC_SHIFT) |
OXYGEN_SPI_CEN_LATCH_CLOCK_HI,
(reg << 8) | value);
}
static inline void pcm1796_write_i2c(struct oxygen *chip, unsigned int codec,
u8 reg, u8 value)
{
oxygen_write_i2c(chip, I2C_DEVICE_PCM1796(codec), reg, value);
}
st