diff options
Diffstat (limited to 'ANDROID_3.4.5/sound/pci/oxygen')
27 files changed, 0 insertions, 9360 deletions
diff --git a/ANDROID_3.4.5/sound/pci/oxygen/Makefile b/ANDROID_3.4.5/sound/pci/oxygen/Makefile deleted file mode 100644 index 0f872655..00000000 --- a/ANDROID_3.4.5/sound/pci/oxygen/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -snd-oxygen-lib-objs := oxygen_io.o oxygen_lib.o oxygen_mixer.o oxygen_pcm.o -snd-oxygen-objs := oxygen.o xonar_dg.o -snd-virtuoso-objs := virtuoso.o xonar_lib.o \ - xonar_pcm179x.o xonar_cs43xx.o xonar_wm87x6.o xonar_hdmi.o - -obj-$(CONFIG_SND_OXYGEN_LIB) += snd-oxygen-lib.o -obj-$(CONFIG_SND_OXYGEN) += snd-oxygen.o -obj-$(CONFIG_SND_VIRTUOSO) += snd-virtuoso.o diff --git a/ANDROID_3.4.5/sound/pci/oxygen/ak4396.h b/ANDROID_3.4.5/sound/pci/oxygen/ak4396.h deleted file mode 100644 index 551c1cf8..00000000 --- a/ANDROID_3.4.5/sound/pci/oxygen/ak4396.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef AK4396_H_INCLUDED -#define AK4396_H_INCLUDED - -#define AK4396_WRITE 0x2000 - -#define AK4396_CONTROL_1 0 -#define AK4396_CONTROL_2 1 -#define AK4396_CONTROL_3 2 -#define AK4396_LCH_ATT 3 -#define AK4396_RCH_ATT 4 - -/* control 1 */ -#define AK4396_RSTN 0x01 -#define AK4396_DIF_MASK 0x0e -#define AK4396_DIF_16_LSB 0x00 -#define AK4396_DIF_20_LSB 0x02 -#define AK4396_DIF_24_MSB 0x04 -#define AK4396_DIF_24_I2S 0x06 -#define AK4396_DIF_24_LSB 0x08 -#define AK4396_ACKS 0x80 -/* control 2 */ -#define AK4396_SMUTE 0x01 -#define AK4396_DEM_MASK 0x06 -#define AK4396_DEM_441 0x00 -#define AK4396_DEM_OFF 0x02 -#define AK4396_DEM_48 0x04 -#define AK4396_DEM_32 0x06 -#define AK4396_DFS_MASK 0x18 -#define AK4396_DFS_NORMAL 0x00 -#define AK4396_DFS_DOUBLE 0x08 -#define AK4396_DFS_QUAD 0x10 -#define AK4396_SLOW 0x20 -#define AK4396_DZFM 0x40 -#define AK4396_DZFE 0x80 -/* control 3 */ -#define AK4396_DZFB 0x04 -#define AK4396_DCKB 0x10 -#define AK4396_DCKS 0x20 -#define AK4396_DSDM 0x40 -#define AK4396_D_P_MASK 0x80 -#define AK4396_PCM 0x00 -#define AK4396_DSD 0x80 - -#endif diff --git a/ANDROID_3.4.5/sound/pci/oxygen/cm9780.h b/ANDROID_3.4.5/sound/pci/oxygen/cm9780.h deleted file mode 100644 index 14459679..00000000 --- a/ANDROID_3.4.5/sound/pci/oxygen/cm9780.h +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef CM9780_H_INCLUDED -#define CM9780_H_INCLUDED - -#define CM9780_JACK 0x62 -#define CM9780_MIXER 0x64 -#define CM9780_GPIO_SETUP 0x70 -#define CM9780_GPIO_STATUS 0x72 - -/* jack control */ -#define CM9780_RSOE 0x0001 -#define CM9780_CBOE 0x0002 -#define CM9780_SSOE 0x0004 -#define CM9780_FROE 0x0008 -#define CM9780_HP2FMICOE 0x0010 -#define CM9780_CB2MICOE 0x0020 -#define CM9780_FMIC2LI 0x0040 -#define CM9780_FMIC2MIC 0x0080 -#define CM9780_HP2LI 0x0100 -#define CM9780_HP2MIC 0x0200 -#define CM9780_MIC2LI 0x0400 -#define CM9780_MIC2MIC 0x0800 -#define CM9780_LI2LI 0x1000 -#define CM9780_LI2MIC 0x2000 -#define CM9780_LO2LI 0x4000 -#define CM9780_LO2MIC 0x8000 - -/* mixer control */ -#define CM9780_BSTSEL 0x0001 -#define CM9780_STRO_MIC 0x0002 -#define CM9780_SPDI_FREX 0x0004 -#define CM9780_SPDI_SSEX 0x0008 -#define CM9780_SPDI_CBEX 0x0010 -#define CM9780_SPDI_RSEX 0x0020 -#define CM9780_MIX2FR 0x0040 -#define CM9780_MIX2SS 0x0080 -#define CM9780_MIX2CB 0x0100 -#define CM9780_MIX2RS 0x0200 -#define CM9780_MIX2FR_EX 0x0400 -#define CM9780_MIX2SS_EX 0x0800 -#define CM9780_MIX2CB_EX 0x1000 -#define CM9780_MIX2RS_EX 0x2000 -#define CM9780_P47_IO 0x4000 -#define CM9780_PCBSW 0x8000 - -/* GPIO setup */ -#define CM9780_GPI0EN 0x0001 -#define CM9780_GPI1EN 0x0002 -#define CM9780_SENSE_P 0x0004 -#define CM9780_LOCK_P 0x0008 -#define CM9780_GPIO0P 0x0010 -#define CM9780_GPIO1P 0x0020 -#define CM9780_GPIO0IO 0x0100 -#define CM9780_GPIO1IO 0x0200 - -/* GPIO status */ -#define CM9780_GPO0 0x0001 -#define CM9780_GPO1 0x0002 -#define CM9780_GPIO0S 0x0010 -#define CM9780_GPIO1S 0x0020 -#define CM9780_GPII0S 0x0100 -#define CM9780_GPII1S 0x0200 - -#endif diff --git a/ANDROID_3.4.5/sound/pci/oxygen/cs2000.h b/ANDROID_3.4.5/sound/pci/oxygen/cs2000.h deleted file mode 100644 index c3501bdb..00000000 --- a/ANDROID_3.4.5/sound/pci/oxygen/cs2000.h +++ /dev/null @@ -1,83 +0,0 @@ -#ifndef CS2000_H_INCLUDED -#define CS2000_H_INCLUDED - -#define CS2000_DEV_ID 0x01 -#define CS2000_DEV_CTRL 0x02 -#define CS2000_DEV_CFG_1 0x03 -#define CS2000_DEV_CFG_2 0x04 -#define CS2000_GLOBAL_CFG 0x05 -#define CS2000_RATIO_0 0x06 /* 32 bits, big endian */ -#define CS2000_RATIO_1 0x0a -#define CS2000_RATIO_2 0x0e -#define CS2000_RATIO_3 0x12 -#define CS2000_FUN_CFG_1 0x16 -#define CS2000_FUN_CFG_2 0x17 -#define CS2000_FUN_CFG_3 0x1e - -/* DEV_ID */ -#define CS2000_DEVICE_MASK 0xf8 -#define CS2000_REVISION_MASK 0x07 - -/* DEV_CTRL */ -#define CS2000_UNLOCK 0x80 -#define CS2000_AUX_OUT_DIS 0x02 -#define CS2000_CLK_OUT_DIS 0x01 - -/* DEV_CFG_1 */ -#define CS2000_R_MOD_SEL_MASK 0xe0 -#define CS2000_R_MOD_SEL_1 0x00 -#define CS2000_R_MOD_SEL_2 0x20 -#define CS2000_R_MOD_SEL_4 0x40 -#define CS2000_R_MOD_SEL_8 0x60 -#define CS2000_R_MOD_SEL_1_2 0x80 -#define CS2000_R_MOD_SEL_1_4 0xa0 -#define CS2000_R_MOD_SEL_1_8 0xc0 -#define CS2000_R_MOD_SEL_1_16 0xe0 -#define CS2000_R_SEL_MASK 0x18 -#define CS2000_R_SEL_SHIFT 3 -#define CS2000_AUX_OUT_SRC_MASK 0x06 -#define CS2000_AUX_OUT_SRC_REF_CLK 0x00 -#define CS2000_AUX_OUT_SRC_CLK_IN 0x02 -#define CS2000_AUX_OUT_SRC_CLK_OUT 0x04 -#define CS2000_AUX_OUT_SRC_PLL_LOCK 0x06 -#define CS2000_EN_DEV_CFG_1 0x01 - -/* DEV_CFG_2 */ -#define CS2000_LOCK_CLK_MASK 0x06 -#define CS2000_LOCK_CLK_SHIFT 1 -#define CS2000_FRAC_N_SRC_MASK 0x01 -#define CS2000_FRAC_N_SRC_STATIC 0x00 -#define CS2000_FRAC_N_SRC_DYNAMIC 0x01 - -/* GLOBAL_CFG */ -#define CS2000_FREEZE 0x08 -#define CS2000_EN_DEV_CFG_2 0x01 - -/* FUN_CFG_1 */ -#define CS2000_CLK_SKIP_EN 0x80 -#define CS2000_AUX_LOCK_CFG_MASK 0x40 -#define CS2000_AUX_LOCK_CFG_PP_HIGH 0x00 -#define CS2000_AUX_LOCK_CFG_OD_LOW 0x40 -#define CS2000_REF_CLK_DIV_MASK 0x18 -#define CS2000_REF_CLK_DIV_4 0x00 -#define CS2000_REF_CLK_DIV_2 0x08 -#define CS2000_REF_CLK_DIV_1 0x10 - -/* FUN_CFG_2 */ -#define CS2000_CLK_OUT_UNL 0x10 -#define CS2000_L_F_RATIO_CFG_MASK 0x08 -#define CS2000_L_F_RATIO_CFG_20_12 0x00 -#define CS2000_L_F_RATIO_CFG_12_20 0x08 - -/* FUN_CFG_3 */ -#define CS2000_CLK_IN_BW_MASK 0x70 -#define CS2000_CLK_IN_BW_1 0x00 -#define CS2000_CLK_IN_BW_2 0x10 -#define CS2000_CLK_IN_BW_4 0x20 -#define CS2000_CLK_IN_BW_8 0x30 -#define CS2000_CLK_IN_BW_16 0x40 -#define CS2000_CLK_IN_BW_32 0x50 -#define CS2000_CLK_IN_BW_64 0x60 -#define CS2000_CLK_IN_BW_128 0x70 - -#endif diff --git a/ANDROID_3.4.5/sound/pci/oxygen/cs4245.h b/ANDROID_3.4.5/sound/pci/oxygen/cs4245.h deleted file mode 100644 index 5e0197e0..00000000 --- a/ANDROID_3.4.5/sound/pci/oxygen/cs4245.h +++ /dev/null @@ -1,107 +0,0 @@ -#define CS4245_CHIP_ID 0x01 -#define CS4245_POWER_CTRL 0x02 -#define CS4245_DAC_CTRL_1 0x03 -#define CS4245_ADC_CTRL 0x04 -#define CS4245_MCLK_FREQ 0x05 -#define CS4245_SIGNAL_SEL 0x06 -#define CS4245_PGA_B_CTRL 0x07 -#define CS4245_PGA_A_CTRL 0x08 -#define CS4245_ANALOG_IN 0x09 -#define CS4245_DAC_A_CTRL 0x0a -#define CS4245_DAC_B_CTRL 0x0b -#define CS4245_DAC_CTRL_2 0x0c -#define CS4245_INT_STATUS 0x0d -#define CS4245_INT_MASK 0x0e -#define CS4245_INT_MODE_MSB 0x0f -#define CS4245_INT_MODE_LSB 0x10 - -/* Chip ID */ -#define CS4245_CHIP_PART_MASK 0xf0 -#define CS4245_CHIP_REV_MASK 0x0f - -/* Power Control */ -#define CS4245_FREEZE 0x80 -#define CS4245_PDN_MIC 0x08 -#define CS4245_PDN_ADC 0x04 -#define CS4245_PDN_DAC 0x02 -#define CS4245_PDN 0x01 - -/* DAC Control */ -#define CS4245_DAC_FM_MASK 0xc0 -#define CS4245_DAC_FM_SINGLE 0x00 -#define CS4245_DAC_FM_DOUBLE 0x40 -#define CS4245_DAC_FM_QUAD 0x80 -#define CS4245_DAC_DIF_MASK 0x30 -#define CS4245_DAC_DIF_LJUST 0x00 -#define CS4245_DAC_DIF_I2S 0x10 -#define CS4245_DAC_DIF_RJUST_16 0x20 -#define CS4245_DAC_DIF_RJUST_24 0x30 -#define CS4245_RESERVED_1 0x08 -#define CS4245_MUTE_DAC 0x04 -#define CS4245_DEEMPH 0x02 -#define CS4245_DAC_MASTER 0x01 - -/* ADC Control */ -#define CS4245_ADC_FM_MASK 0xc0 -#define CS4245_ADC_FM_SINGLE 0x00 -#define CS4245_ADC_FM_DOUBLE 0x40 -#define CS4245_ADC_FM_QUAD 0x80 -#define CS4245_ADC_DIF_MASK 0x10 -#define CS4245_ADC_DIF_LJUST 0x00 -#define CS4245_ADC_DIF_I2S 0x10 -#define CS4245_MUTE_ADC 0x04 -#define CS4245_HPF_FREEZE 0x02 -#define CS4245_ADC_MASTER 0x01 - -/* MCLK Frequency */ -#define CS4245_MCLK1_MASK 0x70 -#define CS4245_MCLK1_SHIFT 4 -#define CS4245_MCLK2_MASK 0x07 -#define CS4245_MCLK2_SHIFT 0 -#define CS4245_MCLK_1 0 -#define CS4245_MCLK_1_5 1 -#define CS4245_MCLK_2 2 -#define CS4245_MCLK_3 3 -#define CS4245_MCLK_4 4 - -/* Signal Selection */ -#define CS4245_A_OUT_SEL_MASK 0x60 -#define CS4245_A_OUT_SEL_HIZ 0x00 -#define CS4245_A_OUT_SEL_DAC 0x20 -#define CS4245_A_OUT_SEL_PGA 0x40 -#define CS4245_LOOP 0x02 -#define CS4245_ASYNCH 0x01 - -/* Channel B/A PGA Control */ -#define CS4245_PGA_GAIN_MASK 0x3f - -/* ADC Input Control */ -#define CS4245_PGA_SOFT 0x10 -#define CS4245_PGA_ZERO 0x08 -#define CS4245_SEL_MASK 0x07 -#define CS4245_SEL_MIC 0x00 -#define CS4245_SEL_INPUT_1 0x01 -#define CS4245_SEL_INPUT_2 0x02 -#define CS4245_SEL_INPUT_3 0x03 -#define CS4245_SEL_INPUT_4 0x04 -#define CS4245_SEL_INPUT_5 0x05 -#define CS4245_SEL_INPUT_6 0x06 - -/* DAC Channel A/B Volume Control */ -#define CS4245_VOL_MASK 0xff - -/* DAC Control 2 */ -#define CS4245_DAC_SOFT 0x80 -#define CS4245_DAC_ZERO 0x40 -#define CS4245_INVERT_DAC 0x20 -#define CS4245_INT_ACTIVE_HIGH 0x01 - -/* Interrupt Status/Mask/Mode */ -#define CS4245_ADC_CLK_ERR 0x08 -#define CS4245_DAC_CLK_ERR 0x04 -#define CS4245_ADC_OVFL 0x02 -#define CS4245_ADC_UNDRFL 0x01 - - -#define CS4245_SPI_ADDRESS (0x9e << 16) -#define CS4245_SPI_WRITE (0 << 16) diff --git a/ANDROID_3.4.5/sound/pci/oxygen/cs4362a.h b/ANDROID_3.4.5/sound/pci/oxygen/cs4362a.h deleted file mode 100644 index 6a4fedf5..00000000 --- a/ANDROID_3.4.5/sound/pci/oxygen/cs4362a.h +++ /dev/null @@ -1,69 +0,0 @@ -/* register 01h */ -#define CS4362A_PDN 0x01 -#define CS4362A_DAC1_DIS 0x02 -#define CS4362A_DAC2_DIS 0x04 -#define CS4362A_DAC3_DIS 0x08 -#define CS4362A_MCLKDIV 0x20 -#define CS4362A_FREEZE 0x40 -#define CS4362A_CPEN 0x80 -/* register 02h */ -#define CS4362A_DIF_MASK 0x70 -#define CS4362A_DIF_LJUST 0x00 -#define CS4362A_DIF_I2S 0x10 -#define CS4362A_DIF_RJUST_16 0x20 -#define CS4362A_DIF_RJUST_24 0x30 -#define CS4362A_DIF_RJUST_20 0x40 -#define CS4362A_DIF_RJUST_18 0x50 -/* register 03h */ -#define CS4362A_MUTEC_MASK 0x03 -#define CS4362A_MUTEC_6 0x00 -#define CS4362A_MUTEC_1 0x01 -#define CS4362A_MUTEC_3 0x03 -#define CS4362A_AMUTE 0x04 -#define CS4362A_MUTEC_POL 0x08 -#define CS4362A_RMP_UP 0x10 -#define CS4362A_SNGLVOL 0x20 -#define CS4362A_ZERO_CROSS 0x40 -#define CS4362A_SOFT_RAMP 0x80 -/* register 04h */ -#define CS4362A_RMP_DN 0x01 -#define CS4362A_DEM_MASK 0x06 -#define CS4362A_DEM_NONE 0x00 -#define CS4362A_DEM_44100 0x02 -#define CS4362A_DEM_48000 0x04 -#define CS4362A_DEM_32000 0x06 -#define CS4362A_FILT_SEL 0x10 -/* register 05h */ -#define CS4362A_INV_A1 0x01 -#define CS4362A_INV_B1 0x02 -#define CS4362A_INV_A2 0x04 -#define CS4362A_INV_B2 0x08 -#define CS4362A_INV_A3 0x10 -#define CS4362A_INV_B3 0x20 -/* register 06h */ -#define CS4362A_FM_MASK 0x03 -#define CS4362A_FM_SINGLE 0x00 -#define CS4362A_FM_DOUBLE 0x01 -#define CS4362A_FM_QUAD 0x02 -#define CS4362A_FM_DSD 0x03 -#define CS4362A_ATAPI_MASK 0x7c -#define CS4362A_ATAPI_B_MUTE 0x00 -#define CS4362A_ATAPI_B_R 0x04 -#define CS4362A_ATAPI_B_L 0x08 -#define CS4362A_ATAPI_B_LR 0x0c -#define CS4362A_ATAPI_A_MUTE 0x00 -#define CS4362A_ATAPI_A_R 0x10 -#define CS4362A_ATAPI_A_L 0x20 -#define CS4362A_ATAPI_A_LR 0x30 -#define CS4362A_ATAPI_MIX_LR_VOL 0x40 -#define CS4362A_A_EQ_B 0x80 -/* register 07h */ -#define CS4362A_VOL_MASK 0x7f -#define CS4362A_MUTE 0x80 -/* register 08h: like 07h */ -/* registers 09h..0Bh: like 06h..08h */ -/* registers 0Ch..0Eh: like 06h..08h */ -/* register 12h */ -#define CS4362A_REV_MASK 0x07 -#define CS4362A_PART_MASK 0xf8 -#define CS4362A_PART_CS4362A 0x50 diff --git a/ANDROID_3.4.5/sound/pci/oxygen/cs4398.h b/ANDROID_3.4.5/sound/pci/oxygen/cs4398.h deleted file mode 100644 index 5faf5efc..00000000 --- a/ANDROID_3.4.5/sound/pci/oxygen/cs4398.h +++ /dev/null @@ -1,69 +0,0 @@ -/* register 1 */ -#define CS4398_REV_MASK 0x07 -#define CS4398_PART_MASK 0xf8 -#define CS4398_PART_CS4398 0x70 -/* register 2 */ -#define CS4398_FM_MASK 0x03 -#define CS4398_FM_SINGLE 0x00 -#define CS4398_FM_DOUBLE 0x01 -#define CS4398_FM_QUAD 0x02 -#define CS4398_FM_DSD 0x03 -#define CS4398_DEM_MASK 0x0c -#define CS4398_DEM_NONE 0x00 -#define CS4398_DEM_44100 0x04 -#define CS4398_DEM_48000 0x08 -#define CS4398_DEM_32000 0x0c -#define CS4398_DIF_MASK 0x70 -#define CS4398_DIF_LJUST 0x00 -#define CS4398_DIF_I2S 0x10 -#define CS4398_DIF_RJUST_16 0x20 -#define CS4398_DIF_RJUST_24 0x30 -#define CS4398_DIF_RJUST_20 0x40 -#define CS4398_DIF_RJUST_18 0x50 -#define CS4398_DSD_SRC 0x80 -/* register 3 */ -#define CS4398_ATAPI_MASK 0x1f -#define CS4398_ATAPI_B_MUTE 0x00 -#define CS4398_ATAPI_B_R 0x01 -#define CS4398_ATAPI_B_L 0x02 -#define CS4398_ATAPI_B_LR 0x03 -#define CS4398_ATAPI_A_MUTE 0x00 -#define CS4398_ATAPI_A_R 0x04 -#define CS4398_ATAPI_A_L 0x08 -#define CS4398_ATAPI_A_LR 0x0c -#define CS4398_ATAPI_MIX_LR_VOL 0x10 -#define CS4398_INVERT_B 0x20 -#define CS4398_INVERT_A 0x40 -#define CS4398_VOL_B_EQ_A 0x80 -/* register 4 */ -#define CS4398_MUTEP_MASK 0x03 -#define CS4398_MUTEP_AUTO 0x00 -#define CS4398_MUTEP_LOW 0x02 -#define CS4398_MUTEP_HIGH 0x03 -#define CS4398_MUTE_B 0x08 -#define CS4398_MUTE_A 0x10 -#define CS4398_MUTEC_A_EQ_B 0x20 -#define CS4398_DAMUTE 0x40 -#define CS4398_PAMUTE 0x80 -/* register 5 */ -#define CS4398_VOL_A_MASK 0xff -/* register 6 */ -#define CS4398_VOL_B_MASK 0xff -/* register 7 */ -#define CS4398_DIR_DSD 0x01 -#define CS4398_FILT_SEL 0x04 -#define CS4398_RMP_DN 0x10 -#define CS4398_RMP_UP 0x20 -#define CS4398_ZERO_CROSS 0x40 -#define CS4398_SOFT_RAMP 0x80 -/* register 8 */ -#define CS4398_MCLKDIV3 0x08 -#define CS4398_MCLKDIV2 0x10 -#define CS4398_FREEZE 0x20 -#define CS4398_CPEN 0x40 -#define CS4398_PDN 0x80 -/* register 9 */ -#define CS4398_DSD_PM_EN 0x01 -#define CS4398_DSD_PM_MODE 0x02 -#define CS4398_INVALID_DSD 0x04 -#define CS4398_STATIC_DSD 0x08 diff --git a/ANDROID_3.4.5/sound/pci/oxygen/oxygen.c b/ANDROID_3.4.5/sound/pci/oxygen/oxygen.c deleted file mode 100644 index eab663ee..00000000 --- a/ANDROID_3.4.5/sound/pci/oxygen/oxygen.c +++ /dev/null @@ -1,884 +0,0 @@ -/* - * C-Media CMI8788 driver for C-Media's reference design and similar models - * - * 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, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * CMI8788: - * - * SPI 0 -> 1st AK4396 (front) - * SPI 1 -> 2nd AK4396 (surround) - * SPI 2 -> 3rd AK4396 (center/LFE) - * SPI 3 -> WM8785 - * SPI 4 -> 4th AK4396 (back) - * - * GPIO 0 -> DFS0 of AK5385 - * GPIO 1 -> DFS1 of AK5385 - * - * X-Meridian models: - * GPIO 4 -> enable extension S/PDIF input - * GPIO 6 -> enable on-board S/PDIF input - * - * Claro models: - * GPIO 6 -> S/PDIF from optical (0) or coaxial (1) input - * GPIO 8 -> enable headphone amplifier - * - * 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 ADC input - */ - -#include <linux/delay.h> -#include <linux/mutex.h> -#include <linux/pci.h> -#include <linux/module.h> -#include <sound/ac97_codec.h> -#include <sound/control.h> -#include <sound/core.h> -#include <sound/info.h> -#include <sound/initval.h> -#include <sound/pcm.h> -#include <sound/pcm_params.h> -#include <sound/tlv.h> -#include "oxygen.h" -#include "xonar_dg.h" -#include "ak4396.h" -#include "wm8785.h" - -MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>"); -MODULE_DESCRIPTION("C-Media CMI8788 driver"); -MODULE_LICENSE("GPL v2"); -MODULE_SUPPORTED_DEVICE("{{C-Media,CMI8786}" - ",{C-Media,CMI8787}" - ",{C-Media,CMI8788}}"); - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "card index"); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string"); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "enable card"); - -enum { - MODEL_CMEDIA_REF, - MODEL_MERIDIAN, - MODEL_MERIDIAN_2G, - MODEL_CLARO, - MODEL_CLARO_HALO, - MODEL_FANTASIA, - MODEL_SERENADE, - MODEL_2CH_OUTPUT, - MODEL_HG2PCI, - MODEL_XONAR_DG, -}; - -static DEFINE_PCI_DEVICE_TABLE(oxygen_ids) = { - /* C-Media's reference design */ - { OXYGEN_PCI_SUBID(0x10b0, 0x0216), .driver_data = MODEL_CMEDIA_REF }, - { OXYGEN_PCI_SUBID(0x10b0, 0x0217), .driver_data = MODEL_CMEDIA_REF }, - { OXYGEN_PCI_SUBID(0x10b0, 0x0218), .driver_data = MODEL_CMEDIA_REF }, - { OXYGEN_PCI_SUBID(0x10b0, 0x0219), .driver_data = MODEL_CMEDIA_REF }, - { OXYGEN_PCI_SUBID(0x13f6, 0x0001), .driver_data = MODEL_CMEDIA_REF }, - { OXYGEN_PCI_SUBID(0x13f6, 0x0010), .driver_data = MODEL_CMEDIA_REF }, - { OXYGEN_PCI_SUBID(0x13f6, 0x8788), .driver_data = MODEL_CMEDIA_REF }, - { OXYGEN_PCI_SUBID(0x147a, 0xa017), .driver_data = MODEL_CMEDIA_REF }, - { OXYGEN_PCI_SUBID(0x1a58, 0x0910), .driver_data = MODEL_CMEDIA_REF }, - /* Asus Xonar DG */ - { OXYGEN_PCI_SUBID(0x1043, 0x8467), .driver_data = MODEL_XONAR_DG }, - /* PCI 2.0 HD Audio */ - { OXYGEN_PCI_SUBID(0x13f6, 0x8782), .driver_data = MODEL_2CH_OUTPUT }, - /* Kuroutoshikou CMI8787-HG2PCI */ - { OXYGEN_PCI_SUBID(0x13f6, 0xffff), .driver_data = MODEL_HG2PCI }, - /* TempoTec HiFier Fantasia */ - { OXYGEN_PCI_SUBID(0x14c3, 0x1710), .driver_data = MODEL_FANTASIA }, - /* TempoTec HiFier Serenade */ - { OXYGEN_PCI_SUBID(0x14c3, 0x1711), .driver_data = MODEL_SERENADE }, - /* AuzenTech X-Meridian */ - { OXYGEN_PCI_SUBID(0x415a, 0x5431), .driver_data = MODEL_MERIDIAN }, - /* AuzenTech X-Meridian 2G */ - { OXYGEN_PCI_SUBID(0x5431, 0x017a), .driver_data = MODEL_MERIDIAN_2G }, - /* HT-Omega Claro */ - { OXYGEN_PCI_SUBID(0x7284, 0x9761), .driver_data = MODEL_CLARO }, - /* HT-Omega Claro halo */ - { OXYGEN_PCI_SUBID(0x7284, 0x9781), .driver_data = MODEL_CLARO_HALO }, - { } -}; -MODULE_DEVICE_TABLE(pci, oxygen_ids); - - -#define GPIO_AK5385_DFS_MASK 0x0003 -#define GPIO_AK5385_DFS_NORMAL 0x0000 -#define GPIO_AK5385_DFS_DOUBLE 0x0001 -#define GPIO_AK5385_DFS_QUAD 0x0002 - -#define GPIO_MERIDIAN_DIG_MASK 0x0050 -#define GPIO_MERIDIAN_DIG_EXT 0x0010 -#define GPIO_MERIDIAN_DIG_BOARD 0x0040 - -#define GPIO_CLARO_DIG_COAX 0x0040 -#define GPIO_CLARO_HP 0x0100 - -struct generic_data { - unsigned int dacs; - u8 ak4396_regs[4][5]; - u16 wm8785_regs[3]; -}; - -static void ak4396_write(struct oxygen *chip, unsigned int codec, - u8 reg, u8 value) -{ - /* maps ALSA channel pair number to SPI output */ - static const u8 codec_spi_map[4] = { - 0, 1, 2, 4 - }; - struct generic_data *data = chip->model_data; - - oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER | - OXYGEN_SPI_DATA_LENGTH_2 | - OXYGEN_SPI_CLOCK_160 | - (codec_spi_map[codec] << OXYGEN_SPI_CODEC_SHIFT) | - OXYGEN_SPI_CEN_LATCH_CLOCK_HI, - AK4396_WRITE | (reg << 8) | value); - data->ak4396_regs[codec][reg] = value; -} - -static void ak4396_write_cached(struct oxygen *chip, unsigned int codec, - u8 reg, u8 value) -{ - struct generic_data *data = chip->model_data; - - if (value != data->ak4396_regs[codec][reg]) - ak4396_write(chip, codec, reg, value); -} - -static void wm8785_write(struct oxygen *chip, u8 reg, unsigned int value) -{ - struct generic_data *data = chip->model_data; - - oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER | - OXYGEN_SPI_DATA_LENGTH_2 | - OXYGEN_SPI_CLOCK_160 | - (3 << OXYGEN_SPI_CODEC_SHIFT) | - OXYGEN_SPI_CEN_LATCH_CLOCK_LO, - (reg << 9) | value); - if (reg < ARRAY_SIZE(data->wm8785_regs)) - data->wm8785_regs[reg] = value; -} - -static void ak4396_registers_init(struct oxygen *chip) -{ - struct generic_data *data = chip->model_data; - unsigned int i; - - for (i = 0; i < data->dacs; ++i) { - ak4396_write(chip, i, AK4396_CONTROL_1, - AK4396_DIF_24_MSB | AK4396_RSTN); - ak4396_write(chip, i, AK4396_CONTROL_2, - data->ak4396_regs[0][AK4396_CONTROL_2]); - ak4396_write(chip, i, AK4396_CONTROL_3, - AK4396_PCM); - ak4396_write(chip, i, AK4396_LCH_ATT, - chip->dac_volume[i * 2]); - ak4396_write(chip, i, AK4396_RCH_ATT, - chip->dac_volume[i * 2 + 1]); - } -} - -static void ak4396_init(struct oxygen *chip) -{ - struct generic_data *data = chip->model_data; - - data->dacs = chip->model.dac_channels_pcm / 2; - data->ak4396_regs[0][AK4396_CONTROL_2] = - AK4396_SMUTE | AK4396_DEM_OFF | AK4396_DFS_NORMAL; - ak4396_registers_init(chip); - snd_component_add(chip->card, "AK4396"); -} - -static void ak5385_init(struct oxygen *chip) -{ - oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_AK5385_DFS_MASK); - oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, GPIO_AK5385_DFS_MASK); - snd_component_add(chip->card, "AK5385"); -} - -static void wm8785_registers_init(struct oxygen *chip) -{ - struct generic_data *data = chip->model_data; - - wm8785_write(chip, WM8785_R7, 0); - wm8785_write(chip, WM8785_R0, data->wm8785_regs[0]); - wm8785_write(chip, WM8785_R2, data->wm8785_regs[2]); -} - -static void wm8785_init(struct oxygen *chip) -{ - struct generic_data *data = chip->model_data; - - data->wm8785_regs[0] = - WM8785_MCR_SLAVE | WM8785_OSR_SINGLE | WM8785_FORMAT_LJUST; - data->wm8785_regs[2] = WM8785_HPFR | WM8785_HPFL; - wm8785_registers_init(chip); - snd_component_add(chip->card, "WM8785"); -} - -static void generic_init(struct oxygen *chip) -{ - ak4396_init(chip); - wm8785_init(chip); -} - -static void meridian_init(struct oxygen *chip) -{ - oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, - GPIO_MERIDIAN_DIG_MASK); - oxygen_write16_masked(chip, OXYGEN_GPIO_DATA, - GPIO_MERIDIAN_DIG_BOARD, GPIO_MERIDIAN_DIG_MASK); - ak4396_init(chip); - ak5385_init(chip); -} - -static void claro_enable_hp(struct oxygen *chip) -{ - msleep(300); - oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_CLARO_HP); - oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, GPIO_CLARO_HP); -} - -static void claro_init(struct oxygen *chip) -{ - oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_CLARO_DIG_COAX); - oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, GPIO_CLARO_DIG_COAX); - ak4396_init(chip); - wm8785_init(chip); - claro_enable_hp(chip); -} - -static void claro_halo_init(struct oxygen *chip) -{ - oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_CLARO_DIG_COAX); - oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, GPIO_CLARO_DIG_COAX); - ak4396_init(chip); - ak5385_init(chip); - claro_enable_hp(chip); -} - -static void fantasia_init(struct oxygen *chip) -{ - ak4396_init(chip); - snd_component_add(chip->card, "CS5340"); -} - -static void stereo_output_init(struct oxygen *chip) -{ - ak4396_init(chip); -} - -static void generic_cleanup(struct oxygen *chip) -{ -} - -static void claro_disable_hp(struct oxygen *chip) -{ - oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, GPIO_CLARO_HP); -} - -static void claro_cleanup(struct oxygen *chip) -{ - claro_disable_hp(chip); -} - -static void claro_suspend(struct oxygen *chip) -{ - claro_disable_hp(chip); -} - -static void generic_resume(struct oxygen *chip) -{ - ak4396_registers_init(chip); - wm8785_registers_init(chip); -} - -static void meridian_resume(struct oxygen *chip) -{ - ak4396_registers_init(chip); -} - -static void claro_resume(struct oxygen *chip) -{ - ak4396_registers_init(chip); - claro_enable_hp(chip); -} - -static void stereo_resume(struct oxygen *chip) -{ - ak4396_registers_init(chip); -} - -static void set_ak4396_params(struct oxygen *chip, - struct snd_pcm_hw_params *params) -{ - struct generic_data *data = chip->model_data; - unsigned int i; - u8 value; - - value = data->ak4396_regs[0][AK4396_CONTROL_2] & ~AK4396_DFS_MASK; - if (params_rate(params) <= 54000) - value |= AK4396_DFS_NORMAL; - else if (params_rate(params) <= 108000) - value |= AK4396_DFS_DOUBLE; - else - value |= AK4396_DFS_QUAD; - - msleep(1); /* wait for the new MCLK to become stable */ - - if (value != data->ak4396_regs[0][AK4396_CONTROL_2]) { - for (i = 0; i < data->dacs; ++i) { - ak4396_write(chip, i, AK4396_CONTROL_1, - AK4396_DIF_24_MSB); - ak4396_write(chip, i, AK4396_CONTROL_2, value); - ak4396_write(chip, i, AK4396_CONTROL_1, - AK4396_DIF_24_MSB | AK4396_RSTN); - } - } -} - -static void update_ak4396_volume(struct oxygen *chip) -{ - struct generic_data *data = chip->model_data; - unsigned int i; - - for (i = 0; i < data->dacs; ++i) { - ak4396_write_cached(chip, i, AK4396_LCH_ATT, - chip->dac_volume[i * 2]); - ak4396_write_cached(chip, i, AK4396_RCH_ATT, - chip->dac_volume[i * 2 + 1]); - } -} - -static void update_ak4396_mute(struct oxygen *chip) -{ - struct generic_data *data = chip->model_data; - unsigned int i; - u8 value; - - value = data->ak4396_regs[0][AK4396_CONTROL_2] & ~AK4396_SMUTE; - if (chip->dac_mute) - value |= AK4396_SMUTE; - for (i = 0; i < data->dacs; ++i) - ak4396_write_cached(chip, i, AK4396_CONTROL_2, value); -} - -static void set_wm8785_params(struct oxygen *chip, - struct snd_pcm_hw_params *params) -{ - struct generic_data *data = chip->model_data; - unsigned int value; - - value = WM8785_MCR_SLAVE | WM8785_FORMAT_LJUST; - if (params_rate(params) <= 48000) - value |= WM8785_OSR_SINGLE; - else if (params_rate(params) <= 96000) - value |= WM8785_OSR_DOUBLE; - else - value |= WM8785_OSR_QUAD; - if (value != data->wm8785_regs[0]) { - wm8785_write(chip, WM8785_R7, 0); - wm8785_write(chip, WM8785_R0, value); - wm8785_write(chip, WM8785_R2, data->wm8785_regs[2]); - } -} - -static void set_ak5385_params(struct oxygen *chip, - struct snd_pcm_hw_params *params) -{ - unsigned int value; - - if (params_rate(params) <= 54000) - value = GPIO_AK5385_DFS_NORMAL; - else if (params_rate(params) <= 108000) - value = GPIO_AK5385_DFS_DOUBLE; - else - value = GPIO_AK5385_DFS_QUAD; - oxygen_write16_masked(chip, OXYGEN_GPIO_DATA, - value, GPIO_AK5385_DFS_MASK); -} - -static void set_no_params(struct oxygen *chip, struct snd_pcm_hw_params *params) -{ -} - -static int rolloff_info(struct snd_kcontrol *ctl, - struct snd_ctl_elem_info *info) -{ - static const char *const names[2] = { - "Sharp Roll-off", "Slow Roll-off" - }; - - return snd_ctl_enum_info(info, 1, 2, names); -} - -static int rolloff_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - struct generic_data *data = chip->model_data; - - value->value.enumerated.item[0] = - (data->ak4396_regs[0][AK4396_CONTROL_2] & AK4396_SLOW) != 0; - return 0; -} - -static int rolloff_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - struct generic_data *data = chip->model_data; - unsigned int i; - int changed; - u8 reg; - - mutex_lock(&chip->mutex); - reg = data->ak4396_regs[0][AK4396_CONTROL_2]; - if (value->value.enumerated.item[0]) - reg |= AK4396_SLOW; - else - reg &= ~AK4396_SLOW; - changed = reg != data->ak4396_regs[0][AK4396_CONTROL_2]; - if (changed) { - for (i = 0; i < data->dacs; ++i) - ak4396_write(chip, i, AK4396_CONTROL_2, reg); - } - mutex_unlock(&chip->mutex); - return changed; -} - -static const struct snd_kcontrol_new rolloff_control = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "DAC Filter Playback Enum", - .info = rolloff_info, - .get = rolloff_get, - .put = rolloff_put, -}; - -static int hpf_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info) -{ - static const char *const names[2] = { - "None", "High-pass Filter" - }; - - return snd_ctl_enum_info(info, 1, 2, names); -} - -static int hpf_get(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - struct generic_data *data = chip->model_data; - - value->value.enumerated.item[0] = - (data->wm8785_regs[WM8785_R2] & WM8785_HPFR) != 0; - return 0; -} - -static int hpf_put(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - struct generic_data *data = chip->model_data; - unsigned int reg; - int changed; - - mutex_lock(&chip->mutex); - reg = data->wm8785_regs[WM8785_R2] & ~(WM8785_HPFR | WM8785_HPFL); - if (value->value.enumerated.item[0]) - reg |= WM8785_HPFR | WM8785_HPFL; - changed = reg != data->wm8785_regs[WM8785_R2]; - if (changed) - wm8785_write(chip, WM8785_R2, reg); - mutex_unlock(&chip->mutex); - return changed; -} - -static const struct snd_kcontrol_new hpf_control = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "ADC Filter Capture Enum", - .info = hpf_info, - .get = hpf_get, - .put = hpf_put, -}; - -static int meridian_dig_source_info(struct snd_kcontrol *ctl, - struct snd_ctl_elem_info *info) -{ - static const char *const names[2] = { "On-board", "Extension" }; - - return snd_ctl_enum_info(info, 1, 2, names); -} - -static int claro_dig_source_info(struct snd_kcontrol *ctl, - struct snd_ctl_elem_info *info) -{ - static const char *const names[2] = { "Optical", "Coaxial" }; - - return snd_ctl_enum_info(info, 1, 2, names); -} - -static int meridian_dig_source_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - - value->value.enumerated.item[0] = - !!(oxygen_read16(chip, OXYGEN_GPIO_DATA) & - GPIO_MERIDIAN_DIG_EXT); - return 0; -} - -static int claro_dig_source_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - - value->value.enumerated.item[0] = - !!(oxygen_read16(chip, OXYGEN_GPIO_DATA) & - GPIO_CLARO_DIG_COAX); - return 0; -} - -static int meridian_dig_source_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - u16 old_reg, new_reg; - int changed; - - mutex_lock(&chip->mutex); - old_reg = oxygen_read16(chip, OXYGEN_GPIO_DATA); - new_reg = old_reg & ~GPIO_MERIDIAN_DIG_MASK; - if (value->value.enumerated.item[0] == 0) - new_reg |= GPIO_MERIDIAN_DIG_BOARD; - else - new_reg |= GPIO_MERIDIAN_DIG_EXT; - changed = new_reg != old_reg; - if (changed) - oxygen_write16(chip, OXYGEN_GPIO_DATA, new_reg); - mutex_unlock(&chip->mutex); - return changed; -} - -static int claro_dig_source_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - u16 old_reg, new_reg; - int changed; - - mutex_lock(&chip->mutex); - old_reg = oxygen_read16(chip, OXYGEN_GPIO_DATA); - new_reg = old_reg & ~GPIO_CLARO_DIG_COAX; - if (value->value.enumerated.item[0]) - new_reg |= GPIO_CLARO_DIG_COAX; - changed = new_reg != old_reg; - if (changed) - oxygen_write16(chip, OXYGEN_GPIO_DATA, new_reg); - mutex_unlock(&chip->mutex); - return changed; -} - -static const struct snd_kcontrol_new meridian_dig_source_control = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "IEC958 Source Capture Enum", - .info = meridian_dig_source_info, - .get = meridian_dig_source_get, - .put = meridian_dig_source_put, -}; - -static const struct snd_kcontrol_new claro_dig_source_control = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "IEC958 Source Capture Enum", - .info = claro_dig_source_info, - .get = claro_dig_source_get, - .put = claro_dig_source_put, -}; - -static int generic_mixer_init(struct oxygen *chip) -{ - return snd_ctl_add(chip->card, snd_ctl_new1(&rolloff_control, chip)); -} - -static int generic_wm8785_mixer_init(struct oxygen *chip) -{ - int err; - - err = generic_mixer_init(chip); - if (err < 0) - return err; - err = snd_ctl_add(chip->card, snd_ctl_new1(&hpf_control, chip)); - if (err < 0) - return err; - return 0; -} - -static int meridian_mixer_init(struct oxygen *chip) -{ - int err; - - err = generic_mixer_init(chip); - if (err < 0) - return err; - err = snd_ctl_add(chip->card, - snd_ctl_new1(&meridian_dig_source_control, chip)); - if (err < 0) - return err; - return 0; -} - -static int claro_mixer_init(struct oxygen *chip) -{ - int err; - - err = generic_wm8785_mixer_init(chip); - if (err < 0) - return err; - err = snd_ctl_add(chip->card, - snd_ctl_new1(&claro_dig_source_control, chip)); - if (err < 0) - return err; - return 0; -} - -static int claro_halo_mixer_init(struct oxygen *chip) -{ - int err; - - err = generic_mixer_init(chip); - if (err < 0) - return err; - err = snd_ctl_add(chip->card, - snd_ctl_new1(&claro_dig_source_control, chip)); - if (err < 0) - return err; - return 0; -} - -static void dump_ak4396_registers(struct oxygen *chip, - struct snd_info_buffer *buffer) -{ - struct generic_data *data = chip->model_data; - unsigned int dac, i; - - for (dac = 0; dac < data->dacs; ++dac) { - snd_iprintf(buffer, "\nAK4396 %u:", dac + 1); - for (i = 0; i < 5; ++i) - snd_iprintf(buffer, " %02x", data->ak4396_regs[dac][i]); - } - snd_iprintf(buffer, "\n"); -} - -static void dump_wm8785_registers(struct oxygen *chip, - struct snd_info_buffer *buffer) -{ - struct generic_data *data = chip->model_data; - unsigned int i; - - snd_iprintf(buffer, "\nWM8785:"); - for (i = 0; i < 3; ++i) - snd_iprintf(buffer, " %03x", data->wm8785_regs[i]); - snd_iprintf(buffer, "\n"); -} - -static void dump_oxygen_registers(struct oxygen *chip, - struct snd_info_buffer *buffer) -{ - dump_ak4396_registers(chip, buffer); - dump_wm8785_registers(chip, buffer); -} - -static const DECLARE_TLV_DB_LINEAR(ak4396_db_scale, TLV_DB_GAIN_MUTE, 0); - -static const struct oxygen_model model_generic = { - .shortname = "C-Media CMI8788", - .longname = "C-Media Oxygen HD Audio", - .chip = "CMI8788", - .init = generic_init, - .mixer_init = generic_wm8785_mixer_init, - .cleanup = generic_cleanup, - .resume = generic_resume, - .set_dac_params = set_ak4396_params, - .set_adc_params = set_wm8785_params, - .update_dac_volume = update_ak4396_volume, - .update_dac_mute = update_ak4396_mute, - .dump_registers = dump_oxygen_registers, - .dac_tlv = ak4396_db_scale, - .model_data_size = sizeof(struct generic_data), - .device_config = PLAYBACK_0_TO_I2S | - PLAYBACK_1_TO_SPDIF | - PLAYBACK_2_TO_AC97_1 | - CAPTURE_0_FROM_I2S_1 | - CAPTURE_1_FROM_SPDIF | - CAPTURE_2_FROM_AC97_1 | - AC97_CD_INPUT, - .dac_channels_pcm = 8, - .dac_channels_mixer = 8, - .dac_volume_min = 0, - .dac_volume_max = 255, - .function_flags = OXYGEN_FUNCTION_SPI | - OXYGEN_FUNCTION_ENABLE_SPI_4_5, - .dac_mclks = OXYGEN_MCLKS(256, 128, 128), - .adc_mclks = OXYGEN_MCLKS(256, 256, 128), - .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST, - .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, -}; - -static int __devinit get_oxygen_model(struct oxygen *chip, - const struct pci_device_id *id) -{ - static const char *const names[] = { - [MODEL_MERIDIAN] = "AuzenTech X-Meridian", - [MODEL_MERIDIAN_2G] = "AuzenTech X-Meridian 2G", - [MODEL_CLARO] = "HT-Omega Claro", - [MODEL_CLARO_HALO] = "HT-Omega Claro halo", - [MODEL_FANTASIA] = "TempoTec HiFier Fantasia", - [MODEL_SERENADE] = "TempoTec HiFier Serenade", - [MODEL_HG2PCI] = "CMI8787-HG2PCI", - }; - - chip->model = model_generic; - switch (id->driver_data) { - case MODEL_MERIDIAN: - case MODEL_MERIDIAN_2G: - chip->model.init = meridian_init; - chip->model.mixer_init = meridian_mixer_init; - chip->model.resume = meridian_resume; - chip->model.set_adc_params = set_ak5385_params; - chip->model.dump_registers = dump_ak4396_registers; - chip->model.device_config = PLAYBACK_0_TO_I2S | - PLAYBACK_1_TO_SPDIF | - CAPTURE_0_FROM_I2S_2 | - CAPTURE_1_FROM_SPDIF; - if (id->driver_data == MODEL_MERIDIAN) - chip->model.device_config |= AC97_CD_INPUT; - break; - case MODEL_CLARO: - chip->model.init = claro_init; - chip->model.mixer_init = claro_mixer_init; - chip->model.cleanup = claro_cleanup; - chip->model.suspend = claro_suspend; - chip->model.resume = claro_resume; - break; - case MODEL_CLARO_HALO: - chip->model.init = claro_halo_init; - chip->model.mixer_init = claro_halo_mixer_init; - chip->model.cleanup = claro_cleanup; - chip->model.suspend = claro_suspend; - chip->model.resume = claro_resume; - chip->model.set_adc_params = set_ak5385_params; - chip->model.dump_registers = dump_ak4396_registers; - chip->model.device_config = PLAYBACK_0_TO_I2S | - PLAYBACK_1_TO_SPDIF | - CAPTURE_0_FROM_I2S_2 | - CAPTURE_1_FROM_SPDIF; - break; - case MODEL_FANTASIA: - case MODEL_SERENADE: - case MODEL_2CH_OUTPUT: - case MODEL_HG2PCI: - chip->model.shortname = "C-Media CMI8787"; - chip->model.chip = "CMI8787"; - if (id->driver_data == MODEL_FANTASIA) - chip->model.init = fantasia_init; - else - chip->model.init = stereo_output_init; - chip->model.resume = stereo_resume; - chip->model.mixer_init = generic_mixer_init; - chip->model.set_adc_params = set_no_params; - chip->model.dump_registers = dump_ak4396_registers; - chip->model.device_config = PLAYBACK_0_TO_I2S | - PLAYBACK_1_TO_SPDIF; - if (id->driver_data == MODEL_FANTASIA) { - chip->model.device_config |= CAPTURE_0_FROM_I2S_1; - chip->model.adc_mclks = OXYGEN_MCLKS(256, 128, 128); - } - chip->model.dac_channels_pcm = 2; - chip->model.dac_channels_mixer = 2; - break; - case MODEL_XONAR_DG: - chip->model = model_xonar_dg; - break; - } - if (id->driver_data == MODEL_MERIDIAN || - id->driver_data == MODEL_MERIDIAN_2G || - id->driver_data == MODEL_CLARO_HALO) { - chip->model.misc_flags = OXYGEN_MISC_MIDI; - chip->model.device_config |= MIDI_OUTPUT | MIDI_INPUT; - } - if (id->driver_data < ARRAY_SIZE(names) && names[id->driver_data]) - chip->model.shortname = names[id->driver_data]; - return 0; -} - -static int __devinit generic_oxygen_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id) -{ - static int dev; - int err; - - if (dev >= SNDRV_CARDS) - return -ENODEV; - if (!enable[dev]) { - ++dev; - return -ENOENT; - } - err = oxygen_pci_probe(pci, index[dev], id[dev], THIS_MODULE, - oxygen_ids, get_oxygen_model); - if (err >= 0) - ++dev; - return err; -} - -static struct pci_driver oxygen_driver = { - .name = KBUILD_MODNAME, - .id_table = oxygen_ids, - .probe = generic_oxygen_probe, - .remove = __devexit_p(oxygen_pci_remove), -#ifdef CONFIG_PM - .suspend = oxygen_pci_suspend, - .resume = oxygen_pci_resume, -#endif -}; - -static int __init alsa_card_oxygen_init(void) -{ - return pci_register_driver(&oxygen_driver); -} - -static void __exit alsa_card_oxygen_exit(void) -{ - pci_unregister_driver(&oxygen_driver); -} - -module_init(alsa_card_oxygen_init) -module_exit(alsa_card_oxygen_exit) diff --git a/ANDROID_3.4.5/sound/pci/oxygen/oxygen.h b/ANDROID_3.4.5/sound/pci/oxygen/oxygen.h deleted file mode 100644 index f53897a7..00000000 --- a/ANDROID_3.4.5/sound/pci/oxygen/oxygen.h +++ /dev/null @@ -1,260 +0,0 @@ -#ifndef OXYGEN_H_INCLUDED -#define OXYGEN_H_INCLUDED - -#include <linux/mutex.h> -#include <linux/spinlock.h> -#include <linux/wait.h> -#include <linux/workqueue.h> -#include "oxygen_regs.h" - -/* 1 << PCM_x == OXYGEN_CHANNEL_x */ -#define PCM_A 0 -#define PCM_B 1 -#define PCM_C 2 -#define PCM_SPDIF 3 -#define PCM_MULTICH 4 -#define PCM_AC97 5 -#define PCM_COUNT 6 - -#define OXYGEN_MCLKS(f_single, f_double, f_quad) ((MCLK_##f_single << 0) | \ - (MCLK_##f_double << 2) | \ - (MCLK_##f_quad << 4)) - -#define OXYGEN_IO_SIZE 0x100 - -#define OXYGEN_EEPROM_ID 0x434d /* "CM" */ - -/* model-specific configuration of outputs/inputs */ -#define PLAYBACK_0_TO_I2S 0x0001 - /* PLAYBACK_0_TO_AC97_0 not implemented */ -#define PLAYBACK_1_TO_SPDIF 0x0004 -#define PLAYBACK_2_TO_AC97_1 0x0008 -#define CAPTURE_0_FROM_I2S_1 0x0010 -#define CAPTURE_0_FROM_I2S_2 0x0020 - /* CAPTURE_0_FROM_AC97_0 not implemented */ -#define CAPTURE_1_FROM_SPDIF 0x0080 -#define CAPTURE_2_FROM_I2S_2 0x0100 -#define CAPTURE_2_FROM_AC97_1 0x0200 - /* CAPTURE_3_FROM_I2S_3 not implemented */ -#define MIDI_OUTPUT 0x0800 -#define MIDI_INPUT 0x1000 -#define AC97_CD_INPUT 0x2000 -#define AC97_FMIC_SWITCH 0x4000 - -enum { - CONTROL_SPDIF_PCM, - CONTROL_SPDIF_INPUT_BITS, - CONTROL_MIC_CAPTURE_SWITCH, - CONTROL_LINE_CAPTURE_SWITCH, - CONTROL_CD_CAPTURE_SWITCH, - CONTROL_AUX_CAPTURE_SWITCH, - CONTROL_COUNT -}; - -#define OXYGEN_PCI_SUBID(sv, sd) \ - .vendor = PCI_VENDOR_ID_CMEDIA, \ - .device = 0x8788, \ - .subvendor = sv, \ - .subdevice = sd - -#define BROKEN_EEPROM_DRIVER_DATA ((unsigned long)-1) -#define OXYGEN_PCI_SUBID_BROKEN_EEPROM \ - OXYGEN_PCI_SUBID(PCI_VENDOR_ID_CMEDIA, 0x8788), \ - .driver_data = BROKEN_EEPROM_DRIVER_DATA - -struct pci_dev; -struct pci_device_id; -struct snd_card; -struct snd_pcm_substream; -struct snd_pcm_hardware; -struct snd_pcm_hw_params; -struct snd_kcontrol_new; -struct snd_rawmidi; -struct snd_info_buffer; -struct oxygen; - -struct oxygen_model { - const char *shortname; - const char *longname; - const char *chip; - void (*init)(struct oxygen *chip); - int (*control_filter)(struct snd_kcontrol_new *template); - int (*mixer_init)(struct oxygen *chip); - void (*cleanup)(struct oxygen *chip); - void (*suspend)(struct oxygen *chip); - void (*resume)(struct oxygen *chip); - void (*pcm_hardware_filter)(unsigned int channel, - struct snd_pcm_hardware *hardware); - void (*set_dac_params)(struct oxygen *chip, - struct snd_pcm_hw_params *params); - void (*set_adc_params)(struct oxygen *chip, - struct snd_pcm_hw_params *params); - void (*update_dac_volume)(struct oxygen *chip); - void (*update_dac_mute)(struct oxygen *chip); - void (*update_center_lfe_mix)(struct oxygen *chip, bool mixed); - unsigned int (*adjust_dac_routing)(struct oxygen *chip, - unsigned int play_routing); - void (*gpio_changed)(struct oxygen *chip); - void (*uart_input)(struct oxygen *chip); - void (*ac97_switch)(struct oxygen *chip, - unsigned int reg, unsigned int mute); - void (*dump_registers)(struct oxygen *chip, - struct snd_info_buffer *buffer); - const unsigned int *dac_tlv; - size_t model_data_size; - unsigned int device_config; - u8 dac_channels_pcm; - u8 dac_channels_mixer; - u8 dac_volume_min; - u8 dac_volume_max; - u8 misc_flags; - u8 function_flags; - u8 dac_mclks; - u8 adc_mclks; - u16 dac_i2s_format; - u16 adc_i2s_format; -}; - -struct oxygen { - unsigned long addr; - spinlock_t reg_lock; - struct mutex mutex; - struct snd_card *card; - struct pci_dev *pci; - struct snd_rawmidi *midi; - int irq; - void *model_data; - unsigned int interrupt_mask; - u8 dac_volume[8]; - u8 dac_mute; - u8 pcm_active; - u8 pcm_running; - u8 dac_routing; - u8 spdif_playback_enable; - u8 has_ac97_0; - u8 has_ac97_1; - u32 spdif_bits; - u32 spdif_pcm_bits; - struct snd_pcm_substream *streams[PCM_COUNT]; - struct snd_kcontrol *controls[CONTROL_COUNT]; - struct work_struct spdif_input_bits_work; - struct work_struct gpio_work; - wait_queue_head_t ac97_waitqueue; - union { - u8 _8[OXYGEN_IO_SIZE]; - __le16 _16[OXYGEN_IO_SIZE / 2]; - __le32 _32[OXYGEN_IO_SIZE / 4]; - } saved_registers; - u16 saved_ac97_registers[2][0x40]; - unsigned int uart_input_count; - u8 uart_input[32]; - struct oxygen_model model; -}; - -/* oxygen_lib.c */ - -int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, - struct module *owner, - const struct pci_device_id *ids, - int (*get_model)(struct oxygen *chip, - const struct pci_device_id *id - ) - ); -void oxygen_pci_remove(struct pci_dev *pci); -#ifdef CONFIG_PM -int oxygen_pci_suspend(struct pci_dev *pci, pm_message_t state); -int oxygen_pci_resume(struct pci_dev *pci); -#endif -void oxygen_pci_shutdown(struct pci_dev *pci); - -/* oxygen_mixer.c */ - -int oxygen_mixer_init(struct oxygen *chip); -void oxygen_update_dac_routing(struct oxygen *chip); -void oxygen_update_spdif_source(struct oxygen *chip); - -/* oxygen_pcm.c */ - -int oxygen_pcm_init(struct oxygen *chip); - -/* oxygen_io.c */ - -u8 oxygen_read8(struct oxygen *chip, unsigned int reg); -u16 oxygen_read16(struct oxygen *chip, unsigned int reg); -u32 oxygen_read32(struct oxygen *chip, unsigned int reg); -void oxygen_write8(struct oxygen *chip, unsigned int reg, u8 value); -void oxygen_write16(struct oxygen *chip, unsigned int reg, u16 value); -void oxygen_write32(struct oxygen *chip, unsigned int reg, u32 value); -void oxygen_write8_masked(struct oxygen *chip, unsigned int reg, - u8 value, u8 mask); -void oxygen_write16_masked(struct oxygen *chip, unsigned int reg, - u16 value, u16 mask); -void oxygen_write32_masked(struct oxygen *chip, unsigned int reg, - u32 value, u32 mask); - -u16 oxygen_read_ac97(struct oxygen *chip, unsigned int codec, - unsigned int index); -void oxygen_write_ac97(struct oxygen *chip, unsigned int codec, - unsigned int index, u16 data); -void oxygen_write_ac97_masked(struct oxygen *chip, unsigned int codec, - unsigned int index, u16 data, u16 mask); - -void oxygen_write_spi(struct oxygen *chip, u8 control, unsigned int data); -void oxygen_write_i2c(struct oxygen *chip, u8 device, u8 map, u8 data); - -void oxygen_reset_uart(struct oxygen *chip); -void oxygen_write_uart(struct oxygen *chip, u8 data); - -u16 oxygen_read_eeprom(struct oxygen *chip, unsigned int index); -void oxygen_write_eeprom(struct oxygen *chip, unsigned int index, u16 value); - -static inline void oxygen_set_bits8(struct oxygen *chip, - unsigned int reg, u8 value) -{ - oxygen_write8_masked(chip, reg, value, value); -} - -static inline void oxygen_set_bits16(struct oxygen *chip, - unsigned int reg, u16 value) -{ - oxygen_write16_masked(chip, reg, value, value); -} - -static inline void oxygen_set_bits32(struct oxygen *chip, - unsigned int reg, u32 value) -{ - oxygen_write32_masked(chip, reg, value, value); -} - -static inline void oxygen_clear_bits8(struct oxygen *chip, - unsigned int reg, u8 value) -{ - oxygen_write8_masked(chip, reg, 0, value); -} - -static inline void oxygen_clear_bits16(struct oxygen *chip, - unsigned int reg, u16 value) -{ - oxygen_write16_masked(chip, reg, 0, value); -} - -static inline void oxygen_clear_bits32(struct oxygen *chip, - unsigned int reg, u32 value) -{ - oxygen_write32_masked(chip, reg, 0, value); -} - -static inline void oxygen_ac97_set_bits(struct oxygen *chip, unsigned int codec, - unsigned int index, u16 value) -{ - oxygen_write_ac97_masked(chip, codec, index, value, value); -} - -static inline void oxygen_ac97_clear_bits(struct oxygen *chip, - unsigned int codec, - unsigned int index, u16 value) -{ - oxygen_write_ac97_masked(chip, codec, index, 0, value); -} - -#endif diff --git a/ANDROID_3.4.5/sound/pci/oxygen/oxygen_io.c b/ANDROID_3.4.5/sound/pci/oxygen/oxygen_io.c deleted file mode 100644 index 521eae45..00000000 --- a/ANDROID_3.4.5/sound/pci/oxygen/oxygen_io.c +++ /dev/null @@ -1,279 +0,0 @@ -/* - * C-Media CMI8788 driver - helper functions - * - * 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, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <linux/delay.h> -#include <linux/sched.h> -#include <linux/export.h> -#include <sound/core.h> -#include <sound/mpu401.h> -#include <asm/io.h> -#include "oxygen.h" - -u8 oxygen_read8(struct oxygen *chip, unsigned int reg) -{ - return inb(chip->addr + reg); -} -EXPORT_SYMBOL(oxygen_read8); - -u16 oxygen_read16(struct oxygen *chip, unsigned int reg) -{ - return inw(chip->addr + reg); -} -EXPORT_SYMBOL(oxygen_read16); - -u32 oxygen_read32(struct oxygen *chip, unsigned int reg) -{ - return inl(chip->addr + reg); -} -EXPORT_SYMBOL(oxygen_read32); - -void oxygen_write8(struct oxygen *chip, unsigned int reg, u8 value) -{ - outb(value, chip->addr + reg); - chip->saved_registers._8[reg] = value; -} -EXPORT_SYMBOL(oxygen_write8); - -void oxygen_write16(struct oxygen *chip, unsigned int reg, u16 value) -{ - outw(value, chip->addr + reg); - chip->saved_registers._16[reg / 2] = cpu_to_le16(value); -} -EXPORT_SYMBOL(oxygen_write16); - -void oxygen_write32(struct oxygen *chip, unsigned int reg, u32 value) -{ - outl(value, chip->addr + reg); - chip->saved_registers._32[reg / 4] = cpu_to_le32(value); -} -EXPORT_SYMBOL(oxygen_write32); - -void oxygen_write8_masked(struct oxygen *chip, unsigned int reg, - u8 value, u8 mask) -{ - u8 tmp = inb(chip->addr + reg); - tmp &= ~mask; - tmp |= value & mask; - outb(tmp, chip->addr + reg); - chip->saved_registers._8[reg] = tmp; -} -EXPORT_SYMBOL(oxygen_write8_masked); - -void oxygen_write16_masked(struct oxygen *chip, unsigned int reg, - u16 value, u16 mask) -{ - u16 tmp = inw(chip->addr + reg); - tmp &= ~mask; - tmp |= value & mask; - outw(tmp, chip->addr + reg); - chip->saved_registers._16[reg / 2] = cpu_to_le16(tmp); -} -EXPORT_SYMBOL(oxygen_write16_masked); - -void oxygen_write32_masked(struct oxygen *chip, unsigned int reg, - u32 value, u32 mask) -{ - u32 tmp = inl(chip->addr + reg); - tmp &= ~mask; - tmp |= value & mask; - outl(tmp, chip->addr + reg); - chip->saved_registers._32[reg / 4] = cpu_to_le32(tmp); -} -EXPORT_SYMBOL(oxygen_write32_masked); - -static int oxygen_ac97_wait(struct oxygen *chip, unsigned int mask) -{ - u8 status = 0; - - /* - * Reading the status register also clears the bits, so we have to save - * the read bits in status. - */ - wait_event_timeout(chip->ac97_waitqueue, - ({ status |= oxygen_read8(chip, OXYGEN_AC97_INTERRUPT_STATUS); - status & mask; }), - msecs_to_jiffies(1) + 1); - /* - * Check even after a timeout because this function should not require - * the AC'97 interrupt to be enabled. - */ - status |= oxygen_read8(chip, OXYGEN_AC97_INTERRUPT_STATUS); - return status & mask ? 0 : -EIO; -} - -/* - * About 10% of AC'97 register reads or writes fail to complete, but even those - * where the controller indicates completion aren't guaranteed to have actually - * happened. - * - * It's hard to assign blame to either the controller or the codec because both - * were made by C-Media ... - */ - -void oxygen_write_ac97(struct oxygen *chip, unsigned int codec, - unsigned int index, u16 data) -{ - unsigned int count, succeeded; - u32 reg; - - reg = data; - reg |= index << OXYGEN_AC97_REG_ADDR_SHIFT; - reg |= OXYGEN_AC97_REG_DIR_WRITE; - reg |= codec << OXYGEN_AC97_REG_CODEC_SHIFT; - succeeded = 0; - for (count = 5; count > 0; --count) { - udelay(5); - oxygen_write32(chip, OXYGEN_AC97_REGS, reg); - /* require two "completed" writes, just to be sure */ - if (oxygen_ac97_wait(chip, OXYGEN_AC97_INT_WRITE_DONE) >= 0 && - ++succeeded >= 2) { - chip->saved_ac97_registers[codec][index / 2] = data; - return; - } - } - snd_printk(KERN_ERR "AC'97 write timeout\n"); -} -EXPORT_SYMBOL(oxygen_write_ac97); - -u16 oxygen_read_ac97(struct oxygen *chip, unsigned int codec, - unsigned int index) -{ - unsigned int count; - unsigned int last_read = UINT_MAX; - u32 reg; - - reg = index << OXYGEN_AC97_REG_ADDR_SHIFT; - reg |= OXYGEN_AC97_REG_DIR_READ; - reg |= codec << OXYGEN_AC97_REG_CODEC_SHIFT; - for (count = 5; count > 0; --count) { - udelay(5); - oxygen_write32(chip, OXYGEN_AC97_REGS, reg); - udelay(10); - if (oxygen_ac97_wait(chip, OXYGEN_AC97_INT_READ_DONE) >= 0) { - u16 value = oxygen_read16(chip, OXYGEN_AC97_REGS); - /* we require two consecutive reads of the same value */ - if (value == last_read) - return value; - last_read = value; - /* - * Invert the register value bits to make sure that two - * consecutive unsuccessful reads do not return the same - * value. - */ - reg ^= 0xffff; - } - } - snd_printk(KERN_ERR "AC'97 read timeout on codec %u\n", codec); - return 0; -} -EXPORT_SYMBOL(oxygen_read_ac97); - -void oxygen_write_ac97_masked(struct oxygen *chip, unsigned int codec, - unsigned int index, u16 data, u16 mask) -{ - u16 value = oxygen_read_ac97(chip, codec, index); - value &= ~mask; - value |= data & mask; - oxygen_write_ac97(chip, codec, index, value); -} -EXPORT_SYMBOL(oxygen_write_ac97_masked); - -void oxygen_write_spi(struct oxygen *chip, u8 control, unsigned int data) -{ - unsigned int count; - - /* should not need more than 30.72 us (24 * 1.28 us) */ - count = 10; - while ((oxygen_read8(chip, OXYGEN_SPI_CONTROL) & OXYGEN_SPI_BUSY) - && count > 0) { - udelay(4); - --count; - } - - oxygen_write8(chip, OXYGEN_SPI_DATA1, data); - oxygen_write8(chip, OXYGEN_SPI_DATA2, data >> 8); - if (control & OXYGEN_SPI_DATA_LENGTH_3) - oxygen_write8(chip, OXYGEN_SPI_DATA3, data >> 16); - oxygen_write8(chip, OXYGEN_SPI_CONTROL, control); -} -EXPORT_SYMBOL(oxygen_write_spi); - -void oxygen_write_i2c(struct oxygen *chip, u8 device, u8 map, u8 data) -{ - /* should not need more than about 300 us */ - msleep(1); - - oxygen_write8(chip, OXYGEN_2WIRE_MAP, map); - oxygen_write8(chip, OXYGEN_2WIRE_DATA, data); - oxygen_write8(chip, OXYGEN_2WIRE_CONTROL, - device | OXYGEN_2WIRE_DIR_WRITE); -} -EXPORT_SYMBOL(oxygen_write_i2c); - -static void _write_uart(struct oxygen *chip, unsigned int port, u8 data) -{ - if (oxygen_read8(chip, OXYGEN_MPU401 + 1) & MPU401_TX_FULL) - msleep(1); - oxygen_write8(chip, OXYGEN_MPU401 + port, data); -} - -void oxygen_reset_uart(struct oxygen *chip) -{ - _write_uart(chip, 1, MPU401_RESET); - msleep(1); /* wait for ACK */ - _write_uart(chip, 1, MPU401_ENTER_UART); -} -EXPORT_SYMBOL(oxygen_reset_uart); - -void oxygen_write_uart(struct oxygen *chip, u8 data) -{ - _write_uart(chip, 0, data); -} -EXPORT_SYMBOL(oxygen_write_uart); - -u16 oxygen_read_eeprom(struct oxygen *chip, unsigned int index) -{ - unsigned int timeout; - - oxygen_write8(chip, OXYGEN_EEPROM_CONTROL, - index | OXYGEN_EEPROM_DIR_READ); - for (timeout = 0; timeout < 100; ++timeout) { - udelay(1); - if (!(oxygen_read8(chip, OXYGEN_EEPROM_STATUS) - & OXYGEN_EEPROM_BUSY)) - break; - } - return oxygen_read16(chip, OXYGEN_EEPROM_DATA); -} - -void oxygen_write_eeprom(struct oxygen *chip, unsigned int index, u16 value) -{ - unsigned int timeout; - - oxygen_write16(chip, OXYGEN_EEPROM_DATA, value); - oxygen_write8(chip, OXYGEN_EEPROM_CONTROL, - index | OXYGEN_EEPROM_DIR_WRITE); - for (timeout = 0; timeout < 10; ++timeout) { - msleep(1); - if (!(oxygen_read8(chip, OXYGEN_EEPROM_STATUS) - & OXYGEN_EEPROM_BUSY)) - return; - } - snd_printk(KERN_ERR "EEPROM write timeout\n"); -} diff --git a/ANDROID_3.4.5/sound/pci/oxygen/oxygen_lib.c b/ANDROID_3.4.5/sound/pci/oxygen/oxygen_lib.c deleted file mode 100644 index 92e2d67f..00000000 --- a/ANDROID_3.4.5/sound/pci/oxygen/oxygen_lib.c +++ /dev/null @@ -1,834 +0,0 @@ -/* - * C-Media CMI8788 driver - main driver module - * - * 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, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <linux/delay.h> -#include <linux/interrupt.h> -#include <linux/mutex.h> -#include <linux/pci.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <sound/ac97_codec.h> -#include <sound/asoundef.h> -#include <sound/core.h> -#include <sound/info.h> -#include <sound/mpu401.h> -#include <sound/pcm.h> -#include "oxygen.h" -#include "cm9780.h" - -MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>"); -MODULE_DESCRIPTION("C-Media CMI8788 helper library"); -MODULE_LICENSE("GPL v2"); - -#define DRIVER "oxygen" - -static inline int oxygen_uart_input_ready(struct oxygen *chip) -{ - return !(oxygen_read8(chip, OXYGEN_MPU401 + 1) & MPU401_RX_EMPTY); -} - -static void oxygen_read_uart(struct oxygen *chip) -{ - if (unlikely(!oxygen_uart_input_ready(chip))) { - /* no data, but read it anyway to clear the interrupt */ - oxygen_read8(chip, OXYGEN_MPU401); - return; - } - do { - u8 data = oxygen_read8(chip, OXYGEN_MPU401); - if (data == MPU401_ACK) - continue; - if (chip->uart_input_count >= ARRAY_SIZE(chip->uart_input)) - chip->uart_input_count = 0; - chip->uart_input[chip->uart_input_count++] = data; - } while (oxygen_uart_input_ready(chip)); - if (chip->model.uart_input) - chip->model.uart_input(chip); -} - -static irqreturn_t oxygen_interrupt(int dummy, void *dev_id) -{ - struct oxygen *chip = dev_id; - unsigned int status, clear, elapsed_streams, i; - - status = oxygen_read16(chip, OXYGEN_INTERRUPT_STATUS); - if (!status) - return IRQ_NONE; - - spin_lock(&chip->reg_lock); - - clear = status & (OXYGEN_CHANNEL_A | - OXYGEN_CHANNEL_B | - OXYGEN_CHANNEL_C | - OXYGEN_CHANNEL_SPDIF | - OXYGEN_CHANNEL_MULTICH | - OXYGEN_CHANNEL_AC97 | - OXYGEN_INT_SPDIF_IN_DETECT | - OXYGEN_INT_GPIO | - OXYGEN_INT_AC97); - if (clear) { - if (clear & OXYGEN_INT_SPDIF_IN_DETECT) - chip->interrupt_mask &= ~OXYGEN_INT_SPDIF_IN_DETECT; - oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, - chip->interrupt_mask & ~clear); - oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, - chip->interrupt_mask); - } - - elapsed_streams = status & chip->pcm_running; - - spin_unlock(&chip->reg_lock); - - for (i = 0; i < PCM_COUNT; ++i) - if ((elapsed_streams & (1 << i)) && chip->streams[i]) - snd_pcm_period_elapsed(chip->streams[i]); - - if (status & OXYGEN_INT_SPDIF_IN_DETECT) { - spin_lock(&chip->reg_lock); - i = oxygen_read32(chip, OXYGEN_SPDIF_CONTROL); - if (i & (OXYGEN_SPDIF_SENSE_INT | OXYGEN_SPDIF_LOCK_INT | - OXYGEN_SPDIF_RATE_INT)) { - /* write the interrupt bit(s) to clear */ - oxygen_write32(chip, OXYGEN_SPDIF_CONTROL, i); - schedule_work(&chip->spdif_input_bits_work); - } - spin_unlock(&chip->reg_lock); - } - - if (status & OXYGEN_INT_GPIO) - schedule_work(&chip->gpio_work); - - if (status & OXYGEN_INT_MIDI) { - if (chip->midi) - snd_mpu401_uart_interrupt(0, chip->midi->private_data); - else - oxygen_read_uart(chip); - } - - if (status & OXYGEN_INT_AC97) - wake_up(&chip->ac97_waitqueue); - - return IRQ_HANDLED; -} - -static void oxygen_spdif_input_bits_changed(struct work_struct *work) -{ - struct oxygen *chip = container_of(work, struct oxygen, - spdif_input_bits_work); - u32 reg; - - /* - * This function gets called when there is new activity on the SPDIF - * input, or when we lose lock on the input signal, or when the rate - * changes. - */ - msleep(1); - spin_lock_irq(&chip->reg_lock); - reg = oxygen_read32(chip, OXYGEN_SPDIF_CONTROL); - if ((reg & (OXYGEN_SPDIF_SENSE_STATUS | - OXYGEN_SPDIF_LOCK_STATUS)) - == OXYGEN_SPDIF_SENSE_STATUS) { - /* - * If we detect activity on the SPDIF input but cannot lock to - * a signal, the clock bit is likely to be wrong. - */ - reg ^= OXYGEN_SPDIF_IN_CLOCK_MASK; - oxygen_write32(chip, OXYGEN_SPDIF_CONTROL, reg); - spin_unlock_irq(&chip->reg_lock); - msleep(1); - spin_lock_irq(&chip->reg_lock); - reg = oxygen_read32(chip, OXYGEN_SPDIF_CONTROL); - if ((reg & (OXYGEN_SPDIF_SENSE_STATUS | - OXYGEN_SPDIF_LOCK_STATUS)) - == OXYGEN_SPDIF_SENSE_STATUS) { - /* nothing detected with either clock; give up */ - if ((reg & OXYGEN_SPDIF_IN_CLOCK_MASK) - == OXYGEN_SPDIF_IN_CLOCK_192) { - /* - * Reset clock to <= 96 kHz because this is - * more likely to be received next time. - */ - reg &= ~OXYGEN_SPDIF_IN_CLOCK_MASK; - reg |= OXYGEN_SPDIF_IN_CLOCK_96; - oxygen_write32(chip, OXYGEN_SPDIF_CONTROL, reg); - } - } - } - spin_unlock_irq(&chip->reg_lock); - - if (chip->controls[CONTROL_SPDIF_INPUT_BITS]) { - spin_lock_irq(&chip->reg_lock); - chip->interrupt_mask |= OXYGEN_INT_SPDIF_IN_DETECT; - oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, - chip->interrupt_mask); - spin_unlock_irq(&chip->reg_lock); - - /* - * We don't actually know that any channel status bits have - * changed, but let's send a notification just to be sure. - */ - snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, - &chip->controls[CONTROL_SPDIF_INPUT_BITS]->id); - } -} - -static void oxygen_gpio_changed(struct work_struct *work) -{ - struct oxygen *chip = container_of(work, struct oxygen, gpio_work); - - if (chip->model.gpio_changed) - chip->model.gpio_changed(chip); -} - -#ifdef CONFIG_PROC_FS -static void oxygen_proc_read(struct snd_info_entry *entry, - struct snd_info_buffer *buffer) -{ - struct oxygen *chip = entry->private_data; - int i, j; - - switch (oxygen_read8(chip, OXYGEN_REVISION) & OXYGEN_PACKAGE_ID_MASK) { - case OXYGEN_PACKAGE_ID_8786: i = '6'; break; - case OXYGEN_PACKAGE_ID_8787: i = '7'; break; - case OXYGEN_PACKAGE_ID_8788: i = '8'; break; - default: i = '?'; break; - } - snd_iprintf(buffer, "CMI878%c:\n", i); - for (i = 0; i < OXYGEN_IO_SIZE; i += 0x10) { - snd_iprintf(buffer, "%02x:", i); - for (j = 0; j < 0x10; ++j) - snd_iprintf(buffer, " %02x", oxygen_read8(chip, i + j)); - snd_iprintf(buffer, "\n"); - } - if (mutex_lock_interruptible(&chip->mutex) < 0) - return; - if (chip->has_ac97_0) { - snd_iprintf(buffer, "\nAC97:\n"); - for (i = 0; i < 0x80; i += 0x10) { - snd_iprintf(buffer, "%02x:", i); - for (j = 0; j < 0x10; j += 2) - snd_iprintf(buffer, " %04x", - oxygen_read_ac97(chip, 0, i + j)); - snd_iprintf(buffer, "\n"); - } - } - if (chip->has_ac97_1) { - snd_iprintf(buffer, "\nAC97 2:\n"); - for (i = 0; i < 0x80; i += 0x10) { - snd_iprintf(buffer, "%02x:", i); - for (j = 0; j < 0x10; j += 2) - snd_iprintf(buffer, " %04x", - oxygen_read_ac97(chip, 1, i + j)); - snd_iprintf(buffer, "\n"); - } - } - mutex_unlock(&chip->mutex); - if (chip->model.dump_registers) - chip->model.dump_registers(chip, buffer); -} - -static void oxygen_proc_init(struct oxygen *chip) -{ - struct snd_info_entry *entry; - - if (!snd_card_proc_new(chip->card, "oxygen", &entry)) - snd_info_set_text_ops(entry, chip, oxygen_proc_read); -} -#else -#define oxygen_proc_init(chip) -#endif - -static const struct pci_device_id * -oxygen_search_pci_id(struct oxygen *chip, const struct pci_device_id ids[]) -{ - u16 subdevice; - - /* - * Make sure the EEPROM pins are available, i.e., not used for SPI. - * (This function is called before we initialize or use SPI.) - */ - oxygen_clear_bits8(chip, OXYGEN_FUNCTION, - OXYGEN_FUNCTION_ENABLE_SPI_4_5); - /* - * Read the subsystem device ID directly from the EEPROM, because the - * chip didn't if the first EEPROM word was overwritten. - */ - subdevice = oxygen_read_eeprom(chip, 2); - /* use default ID if EEPROM is missing */ - if (subdevice == 0xffff && oxygen_read_eeprom(chip, 1) == 0xffff) - subdevice = 0x8788; - /* - * We use only the subsystem device ID for searching because it is - * unique even without the subsystem vendor ID, which may have been - * overwritten in the EEPROM. - */ - for (; ids->vendor; ++ids) - if (ids->subdevice == subdevice && - ids->driver_data != BROKEN_EEPROM_DRIVER_DATA) - return ids; - return NULL; -} - -static void oxygen_restore_eeprom(struct oxygen *chip, - const struct pci_device_id *id) -{ - u16 eeprom_id; - - eeprom_id = oxygen_read_eeprom(chip, 0); - if (eeprom_id != OXYGEN_EEPROM_ID && - (eeprom_id != 0xffff || id->subdevice != 0x8788)) { - /* - * This function gets called only when a known card model has - * been detected, i.e., we know there is a valid subsystem - * product ID at index 2 in the EEPROM. Therefore, we have - * been able to deduce the correct subsystem vendor ID, and - * this is enough information to restore the original EEPROM - * contents. - */ - oxygen_write_eeprom(chip, 1, id->subvendor); - oxygen_write_eeprom(chip, 0, OXYGEN_EEPROM_ID); - - oxygen_set_bits8(chip, OXYGEN_MISC, - OXYGEN_MISC_WRITE_PCI_SUBID); - pci_write_config_word(chip->pci, PCI_SUBSYSTEM_VENDOR_ID, - id->subvendor); - pci_write_config_word(chip->pci, PCI_SUBSYSTEM_ID, - id->subdevice); - oxygen_clear_bits8(chip, OXYGEN_MISC, - OXYGEN_MISC_WRITE_PCI_SUBID); - - snd_printk(KERN_INFO "EEPROM ID restored\n"); - } -} - -static void configure_pcie_bridge(struct pci_dev *pci) -{ - enum { PEX811X, PI7C9X110 }; - static const struct pci_device_id bridge_ids[] = { - { PCI_VDEVICE(PLX, 0x8111), .driver_data = PEX811X }, - { PCI_VDEVICE(PLX, 0x8112), .driver_data = PEX811X }, - { PCI_DEVICE(0x12d8, 0xe110), .driver_data = PI7C9X110 }, - { } - }; - struct pci_dev *bridge; - const struct pci_device_id *id; - u32 tmp; - - if (!pci->bus || !pci->bus->self) - return; - bridge = pci->bus->self; - - id = pci_match_id(bridge_ids, bridge); - if (!id) - return; - - switch (id->driver_data) { - case PEX811X: /* PLX PEX8111/PEX8112 PCIe/PCI bridge */ - pci_read_config_dword(bridge, 0x48, &tmp); - tmp |= 1; /* enable blind prefetching */ - tmp |= 1 << 11; /* enable beacon generation */ - pci_write_config_dword(bridge, 0x48, tmp); - - pci_write_config_dword(bridge, 0x84, 0x0c); - pci_read_config_dword(bridge, 0x88, &tmp); - tmp &= ~(7 << 27); - tmp |= 2 << 27; /* set prefetch size to 128 bytes */ - pci_write_config_dword(bridge, 0x88, tmp); - break; - - case PI7C9X110: /* Pericom PI7C9X110 PCIe/PCI bridge */ - pci_read_config_dword(bridge, 0x40, &tmp); - tmp |= 1; /* park the PCI arbiter to the sound chip */ - pci_write_config_dword(bridge, 0x40, tmp); - break; - } -} - -static void oxygen_init(struct oxygen *chip) -{ - unsigned int i; - - chip->dac_routing = 1; - for (i = 0; i < 8; ++i) - chip->dac_volume[i] = chip->model.dac_volume_min; - chip->dac_mute = 1; - chip->spdif_playback_enable = 1; - chip->spdif_bits = OXYGEN_SPDIF_C | OXYGEN_SPDIF_ORIGINAL | - (IEC958_AES1_CON_PCM_CODER << OXYGEN_SPDIF_CATEGORY_SHIFT); - chip->spdif_pcm_bits = chip->spdif_bits; - - if (!(oxygen_read8(chip, OXYGEN_REVISION) & OXYGEN_REVISION_2)) - oxygen_set_bits8(chip, OXYGEN_MISC, - OXYGEN_MISC_PCI_MEM_W_1_CLOCK); - - i = oxygen_read16(chip, OXYGEN_AC97_CONTROL); - chip->has_ac97_0 = (i & OXYGEN_AC97_CODEC_0) != 0; - chip->has_ac97_1 = (i & OXYGEN_AC97_CODEC_1) != 0; - - oxygen_write8_masked(chip, OXYGEN_FUNCTION, - OXYGEN_FUNCTION_RESET_CODEC | - chip->model.function_flags, - OXYGEN_FUNCTION_RESET_CODEC | - OXYGEN_FUNCTION_2WIRE_SPI_MASK | - OXYGEN_FUNCTION_ENABLE_SPI_4_5); - oxygen_write8(chip, OXYGEN_DMA_STATUS, 0); - oxygen_write8(chip, OXYGEN_DMA_PAUSE, 0); - oxygen_write8(chip, OXYGEN_PLAY_CHANNELS, - OXYGEN_PLAY_CHANNELS_2 | - OXYGEN_DMA_A_BURST_8 | - OXYGEN_DMA_MULTICH_BURST_8); - oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, 0); - oxygen_write8_masked(chip, OXYGEN_MISC, - chip->model.misc_flags, - OXYGEN_MISC_WRITE_PCI_SUBID | - OXYGEN_MISC_REC_C_FROM_SPDIF | - OXYGEN_MISC_REC_B_FROM_AC97 | - OXYGEN_MISC_REC_A_FROM_MULTICH | - OXYGEN_MISC_MIDI); - oxygen_write8(chip, OXYGEN_REC_FORMAT, - (OXYGEN_FORMAT_16 << OXYGEN_REC_FORMAT_A_SHIFT) | - (OXYGEN_FORMAT_16 << OXYGEN_REC_FORMAT_B_SHIFT) | - (OXYGEN_FORMAT_16 << OXYGEN_REC_FORMAT_C_SHIFT)); - oxygen_write8(chip, OXYGEN_PLAY_FORMAT, - (OXYGEN_FORMAT_16 << OXYGEN_SPDIF_FORMAT_SHIFT) | - (OXYGEN_FORMAT_16 << OXYGEN_MULTICH_FORMAT_SHIFT)); - oxygen_write8(chip, OXYGEN_REC_CHANNELS, OXYGEN_REC_CHANNELS_2_2_2); - oxygen_write16(chip, OXYGEN_I2S_MULTICH_FORMAT, - OXYGEN_RATE_48000 | - chip->model.dac_i2s_format | - OXYGEN_I2S_MCLK(chip->model.dac_mclks) | - OXYGEN_I2S_BITS_16 | - OXYGEN_I2S_MASTER | - OXYGEN_I2S_BCLK_64); - if (chip->model.device_config & CAPTURE_0_FROM_I2S_1) - oxygen_write16(chip, OXYGEN_I2S_A_FORMAT, - OXYGEN_RATE_48000 | - chip->model.adc_i2s_format | - OXYGEN_I2S_MCLK(chip->model.adc_mclks) | - OXYGEN_I2S_BITS_16 | - OXYGEN_I2S_MASTER | - OXYGEN_I2S_BCLK_64); - else - oxygen_write16(chip, OXYGEN_I2S_A_FORMAT, - OXYGEN_I2S_MASTER | - OXYGEN_I2S_MUTE_MCLK); - if (chip->model.device_config & (CAPTURE_0_FROM_I2S_2 | - CAPTURE_2_FROM_I2S_2)) - oxygen_write16(chip, OXYGEN_I2S_B_FORMAT, - OXYGEN_RATE_48000 | - chip->model.adc_i2s_format | - OXYGEN_I2S_MCLK(chip->model.adc_mclks) | - OXYGEN_I2S_BITS_16 | - OXYGEN_I2S_MASTER | - OXYGEN_I2S_BCLK_64); - else - oxygen_write16(chip, OXYGEN_I2S_B_FORMAT, - OXYGEN_I2S_MASTER | - OXYGEN_I2S_MUTE_MCLK); - oxygen_write16(chip, OXYGEN_I2S_C_FORMAT, - OXYGEN_I2S_MASTER | - OXYGEN_I2S_MUTE_MCLK); - oxygen_clear_bits32(chip, OXYGEN_SPDIF_CONTROL, - OXYGEN_SPDIF_OUT_ENABLE | - OXYGEN_SPDIF_LOOPBACK); - if (chip->model.device_config & CAPTURE_1_FROM_SPDIF) - oxygen_write32_masked(chip, OXYGEN_SPDIF_CONTROL, - OXYGEN_SPDIF_SENSE_MASK | - OXYGEN_SPDIF_LOCK_MASK | - OXYGEN_SPDIF_RATE_MASK | - OXYGEN_SPDIF_LOCK_PAR | - OXYGEN_SPDIF_IN_CLOCK_96, - OXYGEN_SPDIF_SENSE_MASK | - OXYGEN_SPDIF_LOCK_MASK | - OXYGEN_SPDIF_RATE_MASK | - OXYGEN_SPDIF_SENSE_PAR | - OXYGEN_SPDIF_LOCK_PAR | - OXYGEN_SPDIF_IN_CLOCK_MASK); - else - oxygen_clear_bits32(chip, OXYGEN_SPDIF_CONTROL, - OXYGEN_SPDIF_SENSE_MASK | - OXYGEN_SPDIF_LOCK_MASK | - OXYGEN_SPDIF_RATE_MASK); - oxygen_write32(chip, OXYGEN_SPDIF_OUTPUT_BITS, chip->spdif_bits); - oxygen_write16(chip, OXYGEN_2WIRE_BUS_STATUS, - OXYGEN_2WIRE_LENGTH_8 | - OXYGEN_2WIRE_INTERRUPT_MASK | - OXYGEN_2WIRE_SPEED_STANDARD); - oxygen_clear_bits8(chip, OXYGEN_MPU401_CONTROL, OXYGEN_MPU401_LOOPBACK); - oxygen_write8(chip, OXYGEN_GPI_INTERRUPT_MASK, 0); - oxygen_write16(chip, OXYGEN_GPIO_INTERRUPT_MASK, 0); - oxygen_write16(chip, OXYGEN_PLAY_ROUTING, - OXYGEN_PLAY_MULTICH_I2S_DAC | - OXYGEN_PLAY_SPDIF_SPDIF | - (0 << OXYGEN_PLAY_DAC0_SOURCE_SHIFT) | - (1 << OXYGEN_PLAY_DAC1_SOURCE_SHIFT) | - (2 << OXYGEN_PLAY_DAC2_SOURCE_SHIFT) | - (3 << OXYGEN_PLAY_DAC3_SOURCE_SHIFT)); - oxygen_write8(chip, OXYGEN_REC_ROUTING, - OXYGEN_REC_A_ROUTE_I2S_ADC_1 | - OXYGEN_REC_B_ROUTE_I2S_ADC_2 | - OXYGEN_REC_C_ROUTE_SPDIF); - oxygen_write8(chip, OXYGEN_ADC_MONITOR, 0); - oxygen_write8(chip, OXYGEN_A_MONITOR_ROUTING, - (0 << OXYGEN_A_MONITOR_ROUTE_0_SHIFT) | - (1 << OXYGEN_A_MONITOR_ROUTE_1_SHIFT) | - (2 << OXYGEN_A_MONITOR_ROUTE_2_SHIFT) | - (3 << OXYGEN_A_MONITOR_ROUTE_3_SHIFT)); - - if (chip->has_ac97_0 | chip->has_ac97_1) - oxygen_write8(chip, OXYGEN_AC97_INTERRUPT_MASK, - OXYGEN_AC97_INT_READ_DONE | - OXYGEN_AC97_INT_WRITE_DONE); - else - oxygen_write8(chip, OXYGEN_AC97_INTERRUPT_MASK, 0); - oxygen_write32(chip, OXYGEN_AC97_OUT_CONFIG, 0); - oxygen_write32(chip, OXYGEN_AC97_IN_CONFIG, 0); - if (!(chip->has_ac97_0 | chip->has_ac97_1)) - oxygen_set_bits16(chip, OXYGEN_AC97_CONTROL, - OXYGEN_AC97_CLOCK_DISABLE); - if (!chip->has_ac97_0) { - oxygen_set_bits16(chip, OXYGEN_AC97_CONTROL, - OXYGEN_AC97_NO_CODEC_0); - } else { - oxygen_write_ac97(chip, 0, AC97_RESET, 0); - msleep(1); - oxygen_ac97_set_bits(chip, 0, CM9780_GPIO_SETUP, - CM9780_GPIO0IO | CM9780_GPIO1IO); - oxygen_ac97_set_bits(chip, 0, CM9780_MIXER, - CM9780_BSTSEL | CM9780_STRO_MIC | - CM9780_MIX2FR | CM9780_PCBSW); - oxygen_ac97_set_bits(chip, 0, CM9780_JACK, - CM9780_RSOE | CM9780_CBOE | - CM9780_SSOE | CM9780_FROE | - CM9780_MIC2MIC | CM9780_LI2LI); - oxygen_write_ac97(chip, 0, AC97_MASTER, 0x0000); - oxygen_write_ac97(chip, 0, AC97_PC_BEEP, 0x8000); - oxygen_write_ac97(chip, 0, AC97_MIC, 0x8808); - oxygen_write_ac97(chip, 0, AC97_LINE, 0x0808); - oxygen_write_ac97(chip, 0, AC97_CD, 0x8808); - oxygen_write_ac97(chip, 0, AC97_VIDEO, 0x8808); - oxygen_write_ac97(chip, 0, AC97_AUX, 0x8808); - oxygen_write_ac97(chip, 0, AC97_REC_GAIN, 0x8000); - oxygen_write_ac97(chip, 0, AC97_CENTER_LFE_MASTER, 0x8080); - oxygen_write_ac97(chip, 0, AC97_SURROUND_MASTER, 0x8080); - oxygen_ac97_clear_bits(chip, 0, CM9780_GPIO_STATUS, - CM9780_GPO0); - /* power down unused ADCs and DACs */ - oxygen_ac97_set_bits(chip, 0, AC97_POWERDOWN, - AC97_PD_PR0 | AC97_PD_PR1); - oxygen_ac97_set_bits(chip, 0, AC97_EXTENDED_STATUS, - AC97_EA_PRI | AC97_EA_PRJ | AC97_EA_PRK); - } - if (chip->has_ac97_1) { - oxygen_set_bits32(chip, OXYGEN_AC97_OUT_CONFIG, - OXYGEN_AC97_CODEC1_SLOT3 | - OXYGEN_AC97_CODEC1_SLOT4); - oxygen_write_ac97(chip, 1, AC97_RESET, 0); - msleep(1); - oxygen_write_ac97(chip, 1, AC97_MASTER, 0x0000); - oxygen_write_ac97(chip, 1, AC97_HEADPHONE, 0x8000); - oxygen_write_ac97(chip, 1, AC97_PC_BEEP, 0x8000); - oxygen_write_ac97(chip, 1, AC97_MIC, 0x8808); - oxygen_write_ac97(chip, 1, AC97_LINE, 0x8808); - oxygen_write_ac97(chip, 1, AC97_CD, 0x8808); - oxygen_write_ac97(chip, 1, AC97_VIDEO, 0x8808); - oxygen_write_ac97(chip, 1, AC97_AUX, 0x8808); - oxygen_write_ac97(chip, 1, AC97_PCM, 0x0808); - oxygen_write_ac97(chip, 1, AC97_REC_SEL, 0x0000); - oxygen_write_ac97(chip, 1, AC97_REC_GAIN, 0x0000); - oxygen_ac97_set_bits(chip, 1, 0x6a, 0x0040); - } -} - -static void oxygen_shutdown(struct oxygen *chip) -{ - spin_lock_irq(&chip->reg_lock); - chip->interrupt_mask = 0; - chip->pcm_running = 0; - oxygen_write16(chip, OXYGEN_DMA_STATUS, 0); - oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, 0); - spin_unlock_irq(&chip->reg_lock); -} - -static void oxygen_card_free(struct snd_card *card) -{ - struct oxygen *chip = card->private_data; - - oxygen_shutdown(chip); - if (chip->irq >= 0) - free_irq(chip->irq, chip); - flush_work_sync(&chip->spdif_input_bits_work); - flush_work_sync(&chip->gpio_work); - chip->model.cleanup(chip); - kfree(chip->model_data); - mutex_destroy(&chip->mutex); - pci_release_regions(chip->pci); - pci_disable_device(chip->pci); -} - -int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, - struct module *owner, - const struct pci_device_id *ids, - int (*get_model)(struct oxygen *chip, - const struct pci_device_id *id - ) - ) -{ - struct snd_card *card; - struct oxygen *chip; - const struct pci_device_id *pci_id; - int err; - - err = snd_card_create(index, id, owner, sizeof(*chip), &card); - if (err < 0) - return err; - - chip = card->private_data; - chip->card = card; - chip->pci = pci; - chip->irq = -1; - spin_lock_init(&chip->reg_lock); - mutex_init(&chip->mutex); - INIT_WORK(&chip->spdif_input_bits_work, - oxygen_spdif_input_bits_changed); - INIT_WORK(&chip->gpio_work, oxygen_gpio_changed); - init_waitqueue_head(&chip->ac97_waitqueue); - - err = pci_enable_device(pci); - if (err < 0) - goto err_card; - - err = pci_request_regions(pci, DRIVER); - if (err < 0) { - snd_printk(KERN_ERR "cannot reserve PCI resources\n"); - goto err_pci_enable; - } - - if (!(pci_resource_flags(pci, 0) & IORESOURCE_IO) || - pci_resource_len(pci, 0) < OXYGEN_IO_SIZE) { - snd_printk(KERN_ERR "invalid PCI I/O range\n"); - err = -ENXIO; - goto err_pci_regions; - } - chip->addr = pci_resource_start(pci, 0); - - pci_id = oxygen_search_pci_id(chip, ids); - if (!pci_id) { - err = -ENODEV; - goto err_pci_regions; - } - oxygen_restore_eeprom(chip, pci_id); - err = get_model(chip, pci_id); - if (err < 0) - goto err_pci_regions; - - if (chip->model.model_data_size) { - chip->model_data = kzalloc(chip->model.model_data_size, - GFP_KERNEL); - if (!chip->model_data) { - err = -ENOMEM; - goto err_pci_regions; - } - } - - pci_set_master(pci); - snd_card_set_dev(card, &pci->dev); - card->private_free = oxygen_card_free; - - configure_pcie_bridge(pci); - oxygen_init(chip); - chip->model.init(chip); - - err = request_irq(pci->irq, oxygen_interrupt, IRQF_SHARED, - KBUILD_MODNAME, chip); - if (err < 0) { - snd_printk(KERN_ERR "cannot grab interrupt %d\n", pci->irq); - goto err_card; - } - chip->irq = pci->irq; - - strcpy(card->driver, chip->model.chip); - strcpy(card->shortname, chip->model.shortname); - sprintf(card->longname, "%s at %#lx, irq %i", - chip->model.longname, chip->addr, chip->irq); - strcpy(card->mixername, chip->model.chip); - snd_component_add(card, chip->model.chip); - - err = oxygen_pcm_init(chip); - if (err < 0) - goto err_card; - - err = oxygen_mixer_init(chip); - if (err < 0) - goto err_card; - - if (chip->model.device_config & (MIDI_OUTPUT | MIDI_INPUT)) { - unsigned int info_flags = - MPU401_INFO_INTEGRATED | MPU401_INFO_IRQ_HOOK; - if (chip->model.device_config & MIDI_OUTPUT) - info_flags |= MPU401_INFO_OUTPUT; - if (chip->model.device_config & MIDI_INPUT) - info_flags |= MPU401_INFO_INPUT; - err = snd_mpu401_uart_new(card, 0, MPU401_HW_CMIPCI, - chip->addr + OXYGEN_MPU401, - info_flags, -1, &chip->midi); - if (err < 0) - goto err_card; - } - - oxygen_proc_init(chip); - - spin_lock_irq(&chip->reg_lock); - if (chip->model.device_config & CAPTURE_1_FROM_SPDIF) - chip->interrupt_mask |= OXYGEN_INT_SPDIF_IN_DETECT; - if (chip->has_ac97_0 | chip->has_ac97_1) - chip->interrupt_mask |= OXYGEN_INT_AC97; - oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, chip->interrupt_mask); - spin_unlock_irq(&chip->reg_lock); - - err = snd_card_register(card); - if (err < 0) - goto err_card; - - pci_set_drvdata(pci, card); - return 0; - -err_pci_regions: - pci_release_regions(pci); -err_pci_enable: - pci_disable_device(pci); -err_card: - snd_card_free(card); - return err; -} -EXPORT_SYMBOL(oxygen_pci_probe); - -void oxygen_pci_remove(struct pci_dev *pci) -{ - snd_card_free(pci_get_drvdata(pci)); - pci_set_drvdata(pci, NULL); -} -EXPORT_SYMBOL(oxygen_pci_remove); - -#ifdef CONFIG_PM -int oxygen_pci_suspend(struct pci_dev *pci, pm_message_t state) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct oxygen *chip = card->private_data; - unsigned int i, saved_interrupt_mask; - - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - - for (i = 0; i < PCM_COUNT; ++i) - if (chip->streams[i]) - snd_pcm_suspend(chip->streams[i]); - - if (chip->model.suspend) - chip->model.suspend(chip); - - spin_lock_irq(&chip->reg_lock); - saved_interrupt_mask = chip->interrupt_mask; - chip->interrupt_mask = 0; - oxygen_write16(chip, OXYGEN_DMA_STATUS, 0); - oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, 0); - spin_unlock_irq(&chip->reg_lock); - - synchronize_irq(chip->irq); - flush_work_sync(&chip->spdif_input_bits_work); - flush_work_sync(&chip->gpio_work); - chip->interrupt_mask = saved_interrupt_mask; - - pci_disable_device(pci); - pci_save_state(pci); - pci_set_power_state(pci, pci_choose_state(pci, state)); - return 0; -} -EXPORT_SYMBOL(oxygen_pci_suspend); - -static const u32 registers_to_restore[OXYGEN_IO_SIZE / 32] = { - 0xffffffff, 0x00ff077f, 0x00011d08, 0x007f00ff, - 0x00300000, 0x00000fe4, 0x0ff7001f, 0x00000000 -}; -static const u32 ac97_registers_to_restore[2][0x40 / 32] = { - { 0x18284fa2, 0x03060000 }, - { 0x00007fa6, 0x00200000 } -}; - -static inline int is_bit_set(const u32 *bitmap, unsigned int bit) -{ - return bitmap[bit / 32] & (1 << (bit & 31)); -} - -static void oxygen_restore_ac97(struct oxygen *chip, unsigned int codec) -{ - unsigned int i; - - oxygen_write_ac97(chip, codec, AC97_RESET, 0); - msleep(1); - for (i = 1; i < 0x40; ++i) - if (is_bit_set(ac97_registers_to_restore[codec], i)) - oxygen_write_ac97(chip, codec, i * 2, - chip->saved_ac97_registers[codec][i]); -} - -int oxygen_pci_resume(struct pci_dev *pci) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct oxygen *chip = card->private_data; - unsigned int i; - - pci_set_power_state(pci, PCI_D0); - pci_restore_state(pci); - if (pci_enable_device(pci) < 0) { - snd_printk(KERN_ERR "cannot reenable device"); - snd_card_disconnect(card); - return -EIO; - } - pci_set_master(pci); - - oxygen_write16(chip, OXYGEN_DMA_STATUS, 0); - oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, 0); - for (i = 0; i < OXYGEN_IO_SIZE; ++i) - if (is_bit_set(registers_to_restore, i)) - oxygen_write8(chip, i, chip->saved_registers._8[i]); - if (chip->has_ac97_0) - oxygen_restore_ac97(chip, 0); - if (chip->has_ac97_1) - oxygen_restore_ac97(chip, 1); - - if (chip->model.resume) - chip->model.resume(chip); - - oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, chip->interrupt_mask); - - snd_power_change_state(card, SNDRV_CTL_POWER_D0); - return 0; -} -EXPORT_SYMBOL(oxygen_pci_resume); -#endif /* CONFIG_PM */ - -void oxygen_pci_shutdown(struct pci_dev *pci) -{ - struct snd_card *card = pci_get_drvdata(pci); - struct oxygen *chip = card->private_data; - - oxygen_shutdown(chip); - chip->model.cleanup(chip); -} -EXPORT_SYMBOL(oxygen_pci_shutdown); diff --git a/ANDROID_3.4.5/sound/pci/oxygen/oxygen_mixer.c b/ANDROID_3.4.5/sound/pci/oxygen/oxygen_mixer.c deleted file mode 100644 index c0dbb52d..00000000 --- a/ANDROID_3.4.5/sound/pci/oxygen/oxygen_mixer.c +++ /dev/null @@ -1,1102 +0,0 @@ -/* - * C-Media CMI8788 driver - mixer code - * - * 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, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <linux/mutex.h> -#include <sound/ac97_codec.h> -#include <sound/asoundef.h> -#include <sound/control.h> -#include <sound/tlv.h> -#include "oxygen.h" -#include "cm9780.h" - -static int dac_volume_info(struct snd_kcontrol *ctl, - struct snd_ctl_elem_info *info) -{ - struct oxygen *chip = ctl->private_data; - - info->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - info->count = chip->model.dac_channels_mixer; - info->value.integer.min = chip->model.dac_volume_min; - info->value.integer.max = chip->model.dac_volume_max; - return 0; -} - -static int dac_volume_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - unsigned int i; - - mutex_lock(&chip->mutex); - for (i = 0; i < chip->model.dac_channels_mixer; ++i) - value->value.integer.value[i] = chip->dac_volume[i]; - mutex_unlock(&chip->mutex); - return 0; -} - -static int dac_volume_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - unsigned int i; - int changed; - - changed = 0; - mutex_lock(&chip->mutex); - for (i = 0; i < chip->model.dac_channels_mixer; ++i) - if (value->value.integer.value[i] != chip->dac_volume[i]) { - chip->dac_volume[i] = value->value.integer.value[i]; - changed = 1; - } - if (changed) - chip->model.update_dac_volume(chip); - mutex_unlock(&chip->mutex); - return changed; -} - -static int dac_mute_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - - mutex_lock(&chip->mutex); - value->value.integer.value[0] = !chip->dac_mute; - mutex_unlock(&chip->mutex); - return 0; -} - -static int dac_mute_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - int changed; - - mutex_lock(&chip->mutex); - changed = !value->value.integer.value[0] != chip->dac_mute; - if (changed) { - chip->dac_mute = !value->value.integer.value[0]; - chip->model.update_dac_mute(chip); - } - mutex_unlock(&chip->mutex); - return changed; -} - -static unsigned int upmix_item_count(struct oxygen *chip) -{ - if (chip->model.dac_channels_pcm < 8) - return 2; - else if (chip->model.update_center_lfe_mix) - return 5; - else - return 3; -} - -static int upmix_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info) -{ - static const char *const names[5] = { - "Front", - "Front+Surround", - "Front+Surround+Back", - "Front+Surround+Center/LFE", - "Front+Surround+Center/LFE+Back", - }; - struct oxygen *chip = ctl->private_data; - unsigned int count = upmix_item_count(chip); - - return snd_ctl_enum_info(info, 1, count, names); -} - -static int upmix_get(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - - mutex_lock(&chip->mutex); - value->value.enumerated.item[0] = chip->dac_routing; - mutex_unlock(&chip->mutex); - return 0; -} - -void oxygen_update_dac_routing(struct oxygen *chip) -{ - /* DAC 0: front, DAC 1: surround, DAC 2: center/LFE, DAC 3: back */ - static const unsigned int reg_values[5] = { - /* stereo -> front */ - (0 << OXYGEN_PLAY_DAC0_SOURCE_SHIFT) | - (1 << OXYGEN_PLAY_DAC1_SOURCE_SHIFT) | - (2 << OXYGEN_PLAY_DAC2_SOURCE_SHIFT) | - (3 << OXYGEN_PLAY_DAC3_SOURCE_SHIFT), - /* stereo -> front+surround */ - (0 << OXYGEN_PLAY_DAC0_SOURCE_SHIFT) | - (0 << OXYGEN_PLAY_DAC1_SOURCE_SHIFT) | - (2 << OXYGEN_PLAY_DAC2_SOURCE_SHIFT) | - (3 << OXYGEN_PLAY_DAC3_SOURCE_SHIFT), - /* stereo -> front+surround+back */ - (0 << OXYGEN_PLAY_DAC0_SOURCE_SHIFT) | - (0 << OXYGEN_PLAY_DAC1_SOURCE_SHIFT) | - (2 << OXYGEN_PLAY_DAC2_SOURCE_SHIFT) | - (0 << OXYGEN_PLAY_DAC3_SOURCE_SHIFT), - /* stereo -> front+surround+center/LFE */ - (0 << OXYGEN_PLAY_DAC0_SOURCE_SHIFT) | - (0 << OXYGEN_PLAY_DAC1_SOURCE_SHIFT) | - (0 << OXYGEN_PLAY_DAC2_SOURCE_SHIFT) | - (3 << OXYGEN_PLAY_DAC3_SOURCE_SHIFT), - /* stereo -> front+surround+center/LFE+back */ - (0 << OXYGEN_PLAY_DAC0_SOURCE_SHIFT) | - (0 << OXYGEN_PLAY_DAC1_SOURCE_SHIFT) | - (0 << OXYGEN_PLAY_DAC2_SOURCE_SHIFT) | - (0 << OXYGEN_PLAY_DAC3_SOURCE_SHIFT), - }; - u8 channels; - unsigned int reg_value; - - channels = oxygen_read8(chip, OXYGEN_PLAY_CHANNELS) & - OXYGEN_PLAY_CHANNELS_MASK; - if (channels == OXYGEN_PLAY_CHANNELS_2) - reg_value = reg_values[chip->dac_routing]; - else if (channels == OXYGEN_PLAY_CHANNELS_8) - /* in 7.1 mode, "rear" channels go to the "back" jack */ - reg_value = (0 << OXYGEN_PLAY_DAC0_SOURCE_SHIFT) | - (3 << OXYGEN_PLAY_DAC1_SOURCE_SHIFT) | - (2 << OXYGEN_PLAY_DAC2_SOURCE_SHIFT) | - (1 << OXYGEN_PLAY_DAC3_SOURCE_SHIFT); - else - reg_value = (0 << OXYGEN_PLAY_DAC0_SOURCE_SHIFT) | - (1 << OXYGEN_PLAY_DAC1_SOURCE_SHIFT) | - (2 << OXYGEN_PLAY_DAC2_SOURCE_SHIFT) | - (3 << OXYGEN_PLAY_DAC3_SOURCE_SHIFT); - if (chip->model.adjust_dac_routing) - reg_value = chip->model.adjust_dac_routing(chip, reg_value); - oxygen_write16_masked(chip, OXYGEN_PLAY_ROUTING, reg_value, - OXYGEN_PLAY_DAC0_SOURCE_MASK | - OXYGEN_PLAY_DAC1_SOURCE_MASK | - OXYGEN_PLAY_DAC2_SOURCE_MASK | - OXYGEN_PLAY_DAC3_SOURCE_MASK); - if (chip->model.update_center_lfe_mix) - chip->model.update_center_lfe_mix(chip, chip->dac_routing > 2); -} - -static int upmix_put(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - unsigned int count = upmix_item_count(chip); - int changed; - - if (value->value.enumerated.item[0] >= count) - return -EINVAL; - mutex_lock(&chip->mutex); - changed = value->value.enumerated.item[0] != chip->dac_routing; - if (changed) { - chip->dac_routing = value->value.enumerated.item[0]; - oxygen_update_dac_routing(chip); - } - mutex_unlock(&chip->mutex); - return changed; -} - -static int spdif_switch_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - - mutex_lock(&chip->mutex); - value->value.integer.value[0] = chip->spdif_playback_enable; - mutex_unlock(&chip->mutex); - return 0; -} - -static unsigned int oxygen_spdif_rate(unsigned int oxygen_rate) -{ - switch (oxygen_rate) { - case OXYGEN_RATE_32000: - return IEC958_AES3_CON_FS_32000 << OXYGEN_SPDIF_CS_RATE_SHIFT; - case OXYGEN_RATE_44100: - return IEC958_AES3_CON_FS_44100 << OXYGEN_SPDIF_CS_RATE_SHIFT; - default: /* OXYGEN_RATE_48000 */ - return IEC958_AES3_CON_FS_48000 << OXYGEN_SPDIF_CS_RATE_SHIFT; - case OXYGEN_RATE_64000: - return 0xb << OXYGEN_SPDIF_CS_RATE_SHIFT; - case OXYGEN_RATE_88200: - return IEC958_AES3_CON_FS_88200 << OXYGEN_SPDIF_CS_RATE_SHIFT; - case OXYGEN_RATE_96000: - return IEC958_AES3_CON_FS_96000 << OXYGEN_SPDIF_CS_RATE_SHIFT; - case OXYGEN_RATE_176400: - return IEC958_AES3_CON_FS_176400 << OXYGEN_SPDIF_CS_RATE_SHIFT; - case OXYGEN_RATE_192000: - return IEC958_AES3_CON_FS_192000 << OXYGEN_SPDIF_CS_RATE_SHIFT; - } -} - -void oxygen_update_spdif_source(struct oxygen *chip) -{ - u32 old_control, new_control; - u16 old_routing, new_routing; - unsigned int oxygen_rate; - - old_control = oxygen_read32(chip, OXYGEN_SPDIF_CONTROL); - old_routing = oxygen_read16(chip, OXYGEN_PLAY_ROUTING); - if (chip->pcm_active & (1 << PCM_SPDIF)) { - new_control = old_control | OXYGEN_SPDIF_OUT_ENABLE; - new_routing = (old_routing & ~OXYGEN_PLAY_SPDIF_MASK) - | OXYGEN_PLAY_SPDIF_SPDIF; - oxygen_rate = (old_control >> OXYGEN_SPDIF_OUT_RATE_SHIFT) - & OXYGEN_I2S_RATE_MASK; - /* S/PDIF rate was already set by the caller */ - } else if ((chip->pcm_active & (1 << PCM_MULTICH)) && - chip->spdif_playback_enable) { - new_routing = (old_routing & ~OXYGEN_PLAY_SPDIF_MASK) - | OXYGEN_PLAY_SPDIF_MULTICH_01; - oxygen_rate = oxygen_read16(chip, OXYGEN_I2S_MULTICH_FORMAT) - & OXYGEN_I2S_RATE_MASK; - new_control = (old_control & ~OXYGEN_SPDIF_OUT_RATE_MASK) | - (oxygen_rate << OXYGEN_SPDIF_OUT_RATE_SHIFT) | - OXYGEN_SPDIF_OUT_ENABLE; - } else { - new_control = old_control & ~OXYGEN_SPDIF_OUT_ENABLE; - new_routing = old_routing; - oxygen_rate = OXYGEN_RATE_44100; - } - if (old_routing != new_routing) { - oxygen_write32(chip, OXYGEN_SPDIF_CONTROL, - new_control & ~OXYGEN_SPDIF_OUT_ENABLE); - oxygen_write16(chip, OXYGEN_PLAY_ROUTING, new_routing); - } - if (new_control & OXYGEN_SPDIF_OUT_ENABLE) - oxygen_write32(chip, OXYGEN_SPDIF_OUTPUT_BITS, - oxygen_spdif_rate(oxygen_rate) | - ((chip->pcm_active & (1 << PCM_SPDIF)) ? - chip->spdif_pcm_bits : chip->spdif_bits)); - oxygen_write32(chip, OXYGEN_SPDIF_CONTROL, new_control); -} - -static int spdif_switch_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - int changed; - - mutex_lock(&chip->mutex); - changed = value->value.integer.value[0] != chip->spdif_playback_enable; - if (changed) { - chip->spdif_playback_enable = !!value->value.integer.value[0]; - spin_lock_irq(&chip->reg_lock); - oxygen_update_spdif_source(chip); - spin_unlock_irq(&chip->reg_lock); - } - mutex_unlock(&chip->mutex); - return changed; -} - -static int spdif_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info) -{ - info->type = SNDRV_CTL_ELEM_TYPE_IEC958; - info->count = 1; - return 0; -} - -static void oxygen_to_iec958(u32 bits, struct snd_ctl_elem_value *value) -{ - value->value.iec958.status[0] = - bits & (OXYGEN_SPDIF_NONAUDIO | OXYGEN_SPDIF_C | - OXYGEN_SPDIF_PREEMPHASIS); - value->value.iec958.status[1] = /* category and original */ - bits >> OXYGEN_SPDIF_CATEGORY_SHIFT; -} - -static u32 iec958_to_oxygen(struct snd_ctl_elem_value *value) -{ - u32 bits; - - bits = value->value.iec958.status[0] & - (OXYGEN_SPDIF_NONAUDIO | OXYGEN_SPDIF_C | - OXYGEN_SPDIF_PREEMPHASIS); - bits |= value->value.iec958.status[1] << OXYGEN_SPDIF_CATEGORY_SHIFT; - if (bits & OXYGEN_SPDIF_NONAUDIO) - bits |= OXYGEN_SPDIF_V; - return bits; -} - -static inline void write_spdif_bits(struct oxygen *chip, u32 bits) -{ - oxygen_write32_masked(chip, OXYGEN_SPDIF_OUTPUT_BITS, bits, - OXYGEN_SPDIF_NONAUDIO | - OXYGEN_SPDIF_C | - OXYGEN_SPDIF_PREEMPHASIS | - OXYGEN_SPDIF_CATEGORY_MASK | - OXYGEN_SPDIF_ORIGINAL | - OXYGEN_SPDIF_V); -} - -static int spdif_default_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - - mutex_lock(&chip->mutex); - oxygen_to_iec958(chip->spdif_bits, value); - mutex_unlock(&chip->mutex); - return 0; -} - -static int spdif_default_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - u32 new_bits; - int changed; - - new_bits = iec958_to_oxygen(value); - mutex_lock(&chip->mutex); - changed = new_bits != chip->spdif_bits; - if (changed) { - chip->spdif_bits = new_bits; - if (!(chip->pcm_active & (1 << PCM_SPDIF))) - write_spdif_bits(chip, new_bits); - } - mutex_unlock(&chip->mutex); - return changed; -} - -static int spdif_mask_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - value->value.iec958.status[0] = IEC958_AES0_NONAUDIO | - IEC958_AES0_CON_NOT_COPYRIGHT | IEC958_AES0_CON_EMPHASIS; - value->value.iec958.status[1] = - IEC958_AES1_CON_CATEGORY | IEC958_AES1_CON_ORIGINAL; - return 0; -} - -static int spdif_pcm_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - - mutex_lock(&chip->mutex); - oxygen_to_iec958(chip->spdif_pcm_bits, value); - mutex_unlock(&chip->mutex); - return 0; -} - -static int spdif_pcm_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - u32 new_bits; - int changed; - - new_bits = iec958_to_oxygen(value); - mutex_lock(&chip->mutex); - changed = new_bits != chip->spdif_pcm_bits; - if (changed) { - chip->spdif_pcm_bits = new_bits; - if (chip->pcm_active & (1 << PCM_SPDIF)) - write_spdif_bits(chip, new_bits); - } - mutex_unlock(&chip->mutex); - return changed; -} - -static int spdif_input_mask_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - value->value.iec958.status[0] = 0xff; - value->value.iec958.status[1] = 0xff; - value->value.iec958.status[2] = 0xff; - value->value.iec958.status[3] = 0xff; - return 0; -} - -static int spdif_input_default_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - u32 bits; - - bits = oxygen_read32(chip, OXYGEN_SPDIF_INPUT_BITS); - value->value.iec958.status[0] = bits; - value->value.iec958.status[1] = bits >> 8; - value->value.iec958.status[2] = bits >> 16; - value->value.iec958.status[3] = bits >> 24; - return 0; -} - -static int spdif_bit_switch_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - u32 bit = ctl->private_value; - - value->value.integer.value[0] = - !!(oxygen_read32(chip, OXYGEN_SPDIF_CONTROL) & bit); - return 0; -} - -static int spdif_bit_switch_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - u32 bit = ctl->private_value; - u32 oldreg, newreg; - int changed; - - spin_lock_irq(&chip->reg_lock); - oldreg = oxygen_read32(chip, OXYGEN_SPDIF_CONTROL); - if (value->value.integer.value[0]) - newreg = oldreg | bit; - else - newreg = oldreg & ~bit; - changed = newreg != oldreg; - if (changed) - oxygen_write32(chip, OXYGEN_SPDIF_CONTROL, newreg); - spin_unlock_irq(&chip->reg_lock); - return changed; -} - -static int monitor_volume_info(struct snd_kcontrol *ctl, - struct snd_ctl_elem_info *info) -{ - info->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - info->count = 1; - info->value.integer.min = 0; - info->value.integer.max = 1; - return 0; -} - -static int monitor_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - u8 bit = ctl->private_value; - int invert = ctl->private_value & (1 << 8); - - value->value.integer.value[0] = - !!invert ^ !!(oxygen_read8(chip, OXYGEN_ADC_MONITOR) & bit); - return 0; -} - -static int monitor_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - u8 bit = ctl->private_value; - int invert = ctl->private_value & (1 << 8); - u8 oldreg, newreg; - int changed; - - spin_lock_irq(&chip->reg_lock); - oldreg = oxygen_read8(chip, OXYGEN_ADC_MONITOR); - if ((!!value->value.integer.value[0] ^ !!invert) != 0) - newreg = oldreg | bit; - else - newreg = oldreg & ~bit; - changed = newreg != oldreg; - if (changed) - oxygen_write8(chip, OXYGEN_ADC_MONITOR, newreg); - spin_unlock_irq(&chip->reg_lock); - return changed; -} - -static int ac97_switch_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - unsigned int codec = (ctl->private_value >> 24) & 1; - unsigned int index = ctl->private_value & 0xff; - unsigned int bitnr = (ctl->private_value >> 8) & 0xff; - int invert = ctl->private_value & (1 << 16); - u16 reg; - - mutex_lock(&chip->mutex); - reg = oxygen_read_ac97(chip, codec, index); - mutex_unlock(&chip->mutex); - if (!(reg & (1 << bitnr)) ^ !invert) - value->value.integer.value[0] = 1; - else - value->value.integer.value[0] = 0; - return 0; -} - -static void mute_ac97_ctl(struct oxygen *chip, unsigned int control) -{ - unsigned int priv_idx; - u16 value; - - if (!chip->controls[control]) - return; - priv_idx = chip->controls[control]->private_value & 0xff; - value = oxygen_read_ac97(chip, 0, priv_idx); - if (!(value & 0x8000)) { - oxygen_write_ac97(chip, 0, priv_idx, value | 0x8000); - if (chip->model.ac97_switch) - chip->model.ac97_switch(chip, priv_idx, 0x8000); - snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, - &chip->controls[control]->id); - } -} - -static int ac97_switch_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - unsigned int codec = (ctl->private_value >> 24) & 1; - unsigned int index = ctl->private_value & 0xff; - unsigned int bitnr = (ctl->private_value >> 8) & 0xff; - int invert = ctl->private_value & (1 << 16); - u16 oldreg, newreg; - int change; - - mutex_lock(&chip->mutex); - oldreg = oxygen_read_ac97(chip, codec, index); - newreg = oldreg; - if (!value->value.integer.value[0] ^ !invert) - newreg |= 1 << bitnr; - else - newreg &= ~(1 << bitnr); - change = newreg != oldreg; - if (change) { - oxygen_write_ac97(chip, codec, index, newreg); - if (codec == 0 && chip->model.ac97_switch) - chip->model.ac97_switch(chip, index, newreg & 0x8000); - if (index == AC97_LINE) { - oxygen_write_ac97_masked(chip, 0, CM9780_GPIO_STATUS, - newreg & 0x8000 ? - CM9780_GPO0 : 0, CM9780_GPO0); - if (!(newreg & 0x8000)) { - mute_ac97_ctl(chip, CONTROL_MIC_CAPTURE_SWITCH); - mute_ac97_ctl(chip, CONTROL_CD_CAPTURE_SWITCH); - mute_ac97_ctl(chip, CONTROL_AUX_CAPTURE_SWITCH); - } - } else if ((index == AC97_MIC || index == AC97_CD || - index == AC97_VIDEO || index == AC97_AUX) && - bitnr == 15 && !(newreg & 0x8000)) { - mute_ac97_ctl(chip, CONTROL_LINE_CAPTURE_SWITCH); - oxygen_write_ac97_masked(chip, 0, CM9780_GPIO_STATUS, - CM9780_GPO0, CM9780_GPO0); - } - } - mutex_unlock(&chip->mutex); - return change; -} - -static int ac97_volume_info(struct snd_kcontrol *ctl, - struct snd_ctl_elem_info *info) -{ - int stereo = (ctl->private_value >> 16) & 1; - - info->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - info->count = stereo ? 2 : 1; - info->value.integer.min = 0; - info->value.integer.max = 0x1f; - return 0; -} - -static int ac97_volume_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - unsigned int codec = (ctl->private_value >> 24) & 1; - int stereo = (ctl->private_value >> 16) & 1; - unsigned int index = ctl->private_value & 0xff; - u16 reg; - - mutex_lock(&chip->mutex); - reg = oxygen_read_ac97(chip, codec, index); - mutex_unlock(&chip->mutex); - if (!stereo) { - value->value.integer.value[0] = 31 - (reg & 0x1f); - } else { - value->value.integer.value[0] = 31 - ((reg >> 8) & 0x1f); - value->value.integer.value[1] = 31 - (reg & 0x1f); - } - return 0; -} - -static int ac97_volume_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - unsigned int codec = (ctl->private_value >> 24) & 1; - int stereo = (ctl->private_value >> 16) & 1; - unsigned int index = ctl->private_value & 0xff; - u16 oldreg, newreg; - int change; - - mutex_lock(&chip->mutex); - oldreg = oxygen_read_ac97(chip, codec, index); - if (!stereo) { - newreg = oldreg & ~0x1f; - newreg |= 31 - (value->value.integer.value[0] & 0x1f); - } else { - newreg = oldreg & ~0x1f1f; - newreg |= (31 - (value->value.integer.value[0] & 0x1f)) << 8; - newreg |= 31 - (value->value.integer.value[1] & 0x1f); - } - change = newreg != oldreg; - if (change) - oxygen_write_ac97(chip, codec, index, newreg); - mutex_unlock(&chip->mutex); - return change; -} - -static int mic_fmic_source_info(struct snd_kcontrol *ctl, - struct snd_ctl_elem_info *info) -{ - static const char *const names[] = { "Mic Jack", "Front Panel" }; - - return snd_ctl_enum_info(info, 1, 2, names); -} - -static int mic_fmic_source_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - - mutex_lock(&chip->mutex); - value->value.enumerated.item[0] = - !!(oxygen_read_ac97(chip, 0, CM9780_JACK) & CM9780_FMIC2MIC); - mutex_unlock(&chip->mutex); - return 0; -} - -static int mic_fmic_source_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - u16 oldreg, newreg; - int change; - - mutex_lock(&chip->mutex); - oldreg = oxygen_read_ac97(chip, 0, CM9780_JACK); - if (value->value.enumerated.item[0]) - newreg = oldreg | CM9780_FMIC2MIC; - else - newreg = oldreg & ~CM9780_FMIC2MIC; - change = newreg != oldreg; - if (change) - oxygen_write_ac97(chip, 0, CM9780_JACK, newreg); - mutex_unlock(&chip->mutex); - return change; -} - -static int ac97_fp_rec_volume_info(struct snd_kcontrol *ctl, - struct snd_ctl_elem_info *info) -{ - info->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - info->count = 2; - info->value.integer.min = 0; - info->value.integer.max = 7; - return 0; -} - -static int ac97_fp_rec_volume_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - u16 reg; - - mutex_lock(&chip->mutex); - reg = oxygen_read_ac97(chip, 1, AC97_REC_GAIN); - mutex_unlock(&chip->mutex); - value->value.integer.value[0] = reg & 7; - value->value.integer.value[1] = (reg >> 8) & 7; - return 0; -} - -static int ac97_fp_rec_volume_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - u16 oldreg, newreg; - int change; - - mutex_lock(&chip->mutex); - oldreg = oxygen_read_ac97(chip, 1, AC97_REC_GAIN); - newreg = oldreg & ~0x0707; - newreg = newreg | (value->value.integer.value[0] & 7); - newreg = newreg | ((value->value.integer.value[0] & 7) << 8); - change = newreg != oldreg; - if (change) - oxygen_write_ac97(chip, 1, AC97_REC_GAIN, newreg); - mutex_unlock(&chip->mutex); - return change; -} - -#define AC97_SWITCH(xname, codec, index, bitnr, invert) { \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .info = snd_ctl_boolean_mono_info, \ - .get = ac97_switch_get, \ - .put = ac97_switch_put, \ - .private_value = ((codec) << 24) | ((invert) << 16) | \ - ((bitnr) << 8) | (index), \ - } -#define AC97_VOLUME(xname, codec, index, stereo) { \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \ - SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ - .info = ac97_volume_info, \ - .get = ac97_volume_get, \ - .put = ac97_volume_put, \ - .tlv = { .p = ac97_db_scale, }, \ - .private_value = ((codec) << 24) | ((stereo) << 16) | (index), \ - } - -static DECLARE_TLV_DB_SCALE(monitor_db_scale, -600, 600, 0); -static DECLARE_TLV_DB_SCALE(ac97_db_scale, -3450, 150, 0); -static DECLARE_TLV_DB_SCALE(ac97_rec_db_scale, 0, 150, 0); - -static const struct snd_kcontrol_new controls[] = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Master Playback Volume", - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .info = dac_volume_info, - .get = dac_volume_get, - .put = dac_volume_put, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Master Playback Switch", - .info = snd_ctl_boolean_mono_info, - .get = dac_mute_get, - .put = dac_mute_put, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Stereo Upmixing", - .info = upmix_info, - .get = upmix_get, - .put = upmix_put, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, SWITCH), - .info = snd_ctl_boolean_mono_info, - .get = spdif_switch_get, - .put = spdif_switch_put, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .device = 1, - .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT), - .info = spdif_info, - .get = spdif_default_get, - .put = spdif_default_put, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .device = 1, - .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, CON_MASK), - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .info = spdif_info, - .get = spdif_mask_get, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .device = 1, - .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, PCM_STREAM), - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_INACTIVE, - .info = spdif_info, - .get = spdif_pcm_get, - .put = spdif_pcm_put, - }, -}; - -static const struct snd_kcontrol_new spdif_input_controls[] = { - { - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .device = 1, - .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, MASK), - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .info = spdif_info, - .get = spdif_input_mask_get, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .device = 1, - .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT), - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .info = spdif_info, - .get = spdif_input_default_get, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("Loopback ", NONE, SWITCH), - .info = snd_ctl_boolean_mono_info, - .get = spdif_bit_switch_get, - .put = spdif_bit_switch_put, - .private_value = OXYGEN_SPDIF_LOOPBACK, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = SNDRV_CTL_NAME_IEC958("Validity Check ",CAPTURE,SWITCH), - .info = snd_ctl_boolean_mono_info, - .get = spdif_bit_switch_get, - .put = spdif_bit_switch_put, - .private_value = OXYGEN_SPDIF_SPDVALID, - }, -}; - -static const struct { - unsigned int pcm_dev; - struct snd_kcontrol_new controls[2]; -} monitor_controls[] = { - { - .pcm_dev = CAPTURE_0_FROM_I2S_1, - .controls = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Analog Input Monitor Playback Switch", - .info = snd_ctl_boolean_mono_info, - .get = monitor_get, - .put = monitor_put, - .private_value = OXYGEN_ADC_MONITOR_A, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Analog Input Monitor Playback Volume", - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ, - .info = monitor_volume_info, - .get = monitor_get, - .put = monitor_put, - .private_value = OXYGEN_ADC_MONITOR_A_HALF_VOL - | (1 << 8), - .tlv = { .p = monitor_db_scale, }, - }, - }, - }, - { - .pcm_dev = CAPTURE_0_FROM_I2S_2, - .controls = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Analog Input Monitor Playback Switch", - .info = snd_ctl_boolean_mono_info, - .get = monitor_get, - .put = monitor_put, - .private_value = OXYGEN_ADC_MONITOR_B, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Analog Input Monitor Playback Volume", - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ, - .info = monitor_volume_info, - .get = monitor_get, - .put = monitor_put, - .private_value = OXYGEN_ADC_MONITOR_B_HALF_VOL - | (1 << 8), - .tlv = { .p = monitor_db_scale, }, - }, - }, - }, - { - .pcm_dev = CAPTURE_2_FROM_I2S_2, - .controls = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Analog Input Monitor Playback Switch", - .index = 1, - .info = snd_ctl_boolean_mono_info, - .get = monitor_get, - .put = monitor_put, - .private_value = OXYGEN_ADC_MONITOR_B, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Analog Input Monitor Playback Volume", - .index = 1, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ, - .info = monitor_volume_info, - .get = monitor_get, - .put = monitor_put, - .private_value = OXYGEN_ADC_MONITOR_B_HALF_VOL - | (1 << 8), - .tlv = { .p = monitor_db_scale, }, - }, - }, - }, - { - .pcm_dev = CAPTURE_1_FROM_SPDIF, - .controls = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Digital Input Monitor Playback Switch", - .info = snd_ctl_boolean_mono_info, - .get = monitor_get, - .put = monitor_put, - .private_value = OXYGEN_ADC_MONITOR_C, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Digital Input Monitor Playback Volume", - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ, - .info = monitor_volume_info, - .get = monitor_get, - .put = monitor_put, - .private_value = OXYGEN_ADC_MONITOR_C_HALF_VOL - | (1 << 8), - .tlv = { .p = monitor_db_scale, }, - }, - }, - }, -}; - -static const struct snd_kcontrol_new ac97_controls[] = { - AC97_VOLUME("Mic Capture Volume", 0, AC97_MIC, 0), - AC97_SWITCH("Mic Capture Switch", 0, AC97_MIC, 15, 1), - AC97_SWITCH("Mic Boost (+20dB)", 0, AC97_MIC, 6, 0), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Mic Source Capture Enum", - .info = mic_fmic_source_info, - .get = mic_fmic_source_get, - .put = mic_fmic_source_put, - }, - AC97_SWITCH("Line Capture Switch", 0, AC97_LINE, 15, 1), - AC97_VOLUME("CD Capture Volume", 0, AC97_CD, 1), - AC97_SWITCH("CD Capture Switch", 0, AC97_CD, 15, 1), - AC97_VOLUME("Aux Capture Volume", 0, AC97_AUX, 1), - AC97_SWITCH("Aux Capture Switch", 0, AC97_AUX, 15, 1), -}; - -static const struct snd_kcontrol_new ac97_fp_controls[] = { - AC97_VOLUME("Front Panel Playback Volume", 1, AC97_HEADPHONE, 1), - AC97_SWITCH("Front Panel Playback Switch", 1, AC97_HEADPHONE, 15, 1), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Front Panel Capture Volume", - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ, - .info = ac97_fp_rec_volume_info, - .get = ac97_fp_rec_volume_get, - .put = ac97_fp_rec_volume_put, - .tlv = { .p = ac97_rec_db_scale, }, - }, - AC97_SWITCH("Front Panel Capture Switch", 1, AC97_REC_GAIN, 15, 1), -}; - -static void oxygen_any_ctl_free(struct snd_kcontrol *ctl) -{ - struct oxygen *chip = ctl->private_data; - unsigned int i; - - /* I'm too lazy to write a function for each control :-) */ - for (i = 0; i < ARRAY_SIZE(chip->controls); ++i) - chip->controls[i] = NULL; -} - -static int add_controls(struct oxygen *chip, - const struct snd_kcontrol_new controls[], - unsigned int count) -{ - static const char *const known_ctl_names[CONTROL_COUNT] = { - [CONTROL_SPDIF_PCM] = - SNDRV_CTL_NAME_IEC958("", PLAYBACK, PCM_STREAM), - [CONTROL_SPDIF_INPUT_BITS] = - SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT), - [CONTROL_MIC_CAPTURE_SWITCH] = "Mic Capture Switch", - [CONTROL_LINE_CAPTURE_SWITCH] = "Line Capture Switch", - [CONTROL_CD_CAPTURE_SWITCH] = "CD Capture Switch", - [CONTROL_AUX_CAPTURE_SWITCH] = "Aux Capture Switch", - }; - unsigned int i, j; - struct snd_kcontrol_new template; - struct snd_kcontrol *ctl; - int err; - - for (i = 0; i < count; ++i) { - template = controls[i]; - if (chip->model.control_filter) { - err = chip->model.control_filter(&template); - if (err < 0) - return err; - if (err == 1) - continue; - } - if (!strcmp(template.name, "Stereo Upmixing") && - chip->model.dac_channels_pcm == 2) - continue; - if (!strcmp(template.name, "Mic Source Capture Enum") && - !(chip->model.device_config & AC97_FMIC_SWITCH)) - continue; - if (!strncmp(template.name, "CD Capture ", 11) && - !(chip->model.device_config & AC97_CD_INPUT)) - continue; - if (!strcmp(template.name, "Master Playback Volume") && - chip->model.dac_tlv) { - template.tlv.p = chip->model.dac_tlv; - template.access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ; - } - ctl = snd_ctl_new1(&template, chip); - if (!ctl) - return -ENOMEM; - err = snd_ctl_add(chip->card, ctl); - if (err < 0) - return err; - for (j = 0; j < CONTROL_COUNT; ++j) - if (!strcmp(ctl->id.name, known_ctl_names[j])) { - chip->controls[j] = ctl; - ctl->private_free = oxygen_any_ctl_free; - } - } - return 0; -} - -int oxygen_mixer_init(struct oxygen *chip) -{ - unsigned int i; - int err; - - err = add_controls(chip, controls, ARRAY_SIZE(controls)); - if (err < 0) - return err; - if (chip->model.device_config & CAPTURE_1_FROM_SPDIF) { - err = add_controls(chip, spdif_input_controls, - ARRAY_SIZE(spdif_input_controls)); - if (err < 0) - return err; - } - for (i = 0; i < ARRAY_SIZE(monitor_controls); ++i) { - if (!(chip->model.device_config & monitor_controls[i].pcm_dev)) - continue; - err = add_controls(chip, monitor_controls[i].controls, - ARRAY_SIZE(monitor_controls[i].controls)); - if (err < 0) - return err; - } - if (chip->has_ac97_0) { - err = add_controls(chip, ac97_controls, - ARRAY_SIZE(ac97_controls)); - if (err < 0) - return err; - } - if (chip->has_ac97_1) { - err = add_controls(chip, ac97_fp_controls, - ARRAY_SIZE(ac97_fp_controls)); - if (err < 0) - return err; - } - return chip->model.mixer_init ? chip->model.mixer_init(chip) : 0; -} diff --git a/ANDROID_3.4.5/sound/pci/oxygen/oxygen_pcm.c b/ANDROID_3.4.5/sound/pci/oxygen/oxygen_pcm.c deleted file mode 100644 index cc0bcd9f..00000000 --- a/ANDROID_3.4.5/sound/pci/oxygen/oxygen_pcm.c +++ /dev/null @@ -1,766 +0,0 @@ -/* - * C-Media CMI8788 driver - PCM code - * - * 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, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <linux/pci.h> -#include <sound/control.h> -#include <sound/core.h> -#include <sound/pcm.h> -#include <sound/pcm_params.h> -#include "oxygen.h" - -/* most DMA channels have a 16-bit counter for 32-bit words */ -#define BUFFER_BYTES_MAX ((1 << 16) * 4) -/* the multichannel DMA channel has a 24-bit counter */ -#define BUFFER_BYTES_MAX_MULTICH ((1 << 24) * 4) - -#define PERIOD_BYTES_MIN 64 - -#define DEFAULT_BUFFER_BYTES (BUFFER_BYTES_MAX / 2) -#define DEFAULT_BUFFER_BYTES_MULTICH (1024 * 1024) - -static const struct snd_pcm_hardware oxygen_stereo_hardware = { - .info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_SYNC_START | - SNDRV_PCM_INFO_NO_PERIOD_WAKEUP, - .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S32_LE, - .rates = SNDRV_PCM_RATE_32000 | - SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_64000 | - SNDRV_PCM_RATE_88200 | - SNDRV_PCM_RATE_96000 | - SNDRV_PCM_RATE_176400 | - SNDRV_PCM_RATE_192000, - .rate_min = 32000, - .rate_max = 192000, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = BUFFER_BYTES_MAX, - .period_bytes_min = PERIOD_BYTES_MIN, - .period_bytes_max = BUFFER_BYTES_MAX, - .periods_min = 1, - .periods_max = BUFFER_BYTES_MAX / PERIOD_BYTES_MIN, -}; -static const struct snd_pcm_hardware oxygen_multichannel_hardware = { - .info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_SYNC_START | - SNDRV_PCM_INFO_NO_PERIOD_WAKEUP, - .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S32_LE, - .rates = SNDRV_PCM_RATE_32000 | - SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_64000 | - SNDRV_PCM_RATE_88200 | - SNDRV_PCM_RATE_96000 | - SNDRV_PCM_RATE_176400 | - SNDRV_PCM_RATE_192000, - .rate_min = 32000, - .rate_max = 192000, - .channels_min = 2, - .channels_max = 8, - .buffer_bytes_max = BUFFER_BYTES_MAX_MULTICH, - .period_bytes_min = PERIOD_BYTES_MIN, - .period_bytes_max = BUFFER_BYTES_MAX_MULTICH, - .periods_min = 1, - .periods_max = BUFFER_BYTES_MAX_MULTICH / PERIOD_BYTES_MIN, -}; -static const struct snd_pcm_hardware oxygen_ac97_hardware = { - .info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_SYNC_START | - SNDRV_PCM_INFO_NO_PERIOD_WAKEUP, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_48000, - .rate_min = 48000, - .rate_max = 48000, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = BUFFER_BYTES_MAX, - .period_bytes_min = PERIOD_BYTES_MIN, - .period_bytes_max = BUFFER_BYTES_MAX, - .periods_min = 1, - .periods_max = BUFFER_BYTES_MAX / PERIOD_BYTES_MIN, -}; - -static const struct snd_pcm_hardware *const oxygen_hardware[PCM_COUNT] = { - [PCM_A] = &oxygen_stereo_hardware, - [PCM_B] = &oxygen_stereo_hardware, - [PCM_C] = &oxygen_stereo_hardware, - [PCM_SPDIF] = &oxygen_stereo_hardware, - [PCM_MULTICH] = &oxygen_multichannel_hardware, - [PCM_AC97] = &oxygen_ac97_hardware, -}; - -static inline unsigned int -oxygen_substream_channel(struct snd_pcm_substream *substream) -{ - return (unsigned int)(uintptr_t)substream->runtime->private_data; -} - -static int oxygen_open(struct snd_pcm_substream *substream, - unsigned int channel) -{ - struct oxygen *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - int err; - - runtime->private_data = (void *)(uintptr_t)channel; - if (channel == PCM_B && chip->has_ac97_1 && - (chip->model.device_config & CAPTURE_2_FROM_AC97_1)) - runtime->hw = oxygen_ac97_hardware; - else - runtime->hw = *oxygen_hardware[channel]; - switch (channel) { - case PCM_C: - runtime->hw.rates &= ~(SNDRV_PCM_RATE_32000 | - SNDRV_PCM_RATE_64000); - runtime->hw.rate_min = 44100; - break; - case PCM_MULTICH: - runtime->hw.channels_max = chip->model.dac_channels_pcm; - break; - } - if (chip->model.pcm_hardware_filter) - chip->model.pcm_hardware_filter(channel, &runtime->hw); - err = snd_pcm_hw_constraint_step(runtime, 0, - SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32); - if (err < 0) - return err; - err = snd_pcm_hw_constraint_step(runtime, 0, - SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 32); - if (err < 0) - return err; - if (runtime->hw.formats & SNDRV_PCM_FMTBIT_S32_LE) { - err = snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24); - if (err < 0) - return err; - } - if (runtime->hw.channels_max > 2) { - err = snd_pcm_hw_constraint_step(runtime, 0, - SNDRV_PCM_HW_PARAM_CHANNELS, - 2); - if (err < 0) - return err; - } - snd_pcm_set_sync(substream); - chip->streams[channel] = substream; - - mutex_lock(&chip->mutex); - chip->pcm_active |= 1 << channel; - if (channel == PCM_SPDIF) { - chip->spdif_pcm_bits = chip->spdif_bits; - chip->controls[CONTROL_SPDIF_PCM]->vd[0].access &= - ~SNDRV_CTL_ELEM_ACCESS_INACTIVE; - snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE | - SNDRV_CTL_EVENT_MASK_INFO, - &chip->controls[CONTROL_SPDIF_PCM]->id); - } - mutex_unlock(&chip->mutex); - - return 0; -} - -static int oxygen_rec_a_open(struct snd_pcm_substream *substream) -{ - return oxygen_open(substream, PCM_A); -} - -static int oxygen_rec_b_open(struct snd_pcm_substream *substream) -{ - return oxygen_open(substream, PCM_B); -} - -static int oxygen_rec_c_open(struct snd_pcm_substream *substream) -{ - return oxygen_open(substream, PCM_C); -} - -static int oxygen_spdif_open(struct snd_pcm_substream *substream) -{ - return oxygen_open(substream, PCM_SPDIF); -} - -static int oxygen_multich_open(struct snd_pcm_substream *substream) -{ - return oxygen_open(substream, PCM_MULTICH); -} - -static int oxygen_ac97_open(struct snd_pcm_substream *substream) -{ - return oxygen_open(substream, PCM_AC97); -} - -static int oxygen_close(struct snd_pcm_substream *substream) -{ - struct oxygen *chip = snd_pcm_substream_chip(substream); - unsigned int channel = oxygen_substream_channel(substream); - - mutex_lock(&chip->mutex); - chip->pcm_active &= ~(1 << channel); - if (channel == PCM_SPDIF) { - chip->controls[CONTROL_SPDIF_PCM]->vd[0].access |= - SNDRV_CTL_ELEM_ACCESS_INACTIVE; - snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE | - SNDRV_CTL_EVENT_MASK_INFO, - &chip->controls[CONTROL_SPDIF_PCM]->id); - } - if (channel == PCM_SPDIF || channel == PCM_MULTICH) - oxygen_update_spdif_source(chip); - mutex_unlock(&chip->mutex); - - chip->streams[channel] = NULL; - return 0; -} - -static unsigned int oxygen_format(struct snd_pcm_hw_params *hw_params) -{ - if (params_format(hw_params) == SNDRV_PCM_FORMAT_S32_LE) - return OXYGEN_FORMAT_24; - else - return OXYGEN_FORMAT_16; -} - -static unsigned int oxygen_rate(struct snd_pcm_hw_params *hw_params) -{ - switch (params_rate(hw_params)) { - case 32000: - return OXYGEN_RATE_32000; - case 44100: - return OXYGEN_RATE_44100; - default: /* 48000 */ - return OXYGEN_RATE_48000; - case 64000: - return OXYGEN_RATE_64000; - case 88200: - return OXYGEN_RATE_88200; - case 96000: - return OXYGEN_RATE_96000; - case 176400: - return OXYGEN_RATE_176400; - case 192000: - return OXYGEN_RATE_192000; - } -} - -static unsigned int oxygen_i2s_bits(struct snd_pcm_hw_params *hw_params) -{ - if (params_format(hw_params) == SNDRV_PCM_FORMAT_S32_LE) - return OXYGEN_I2S_BITS_24; - else - return OXYGEN_I2S_BITS_16; -} - -static unsigned int oxygen_play_channels(struct snd_pcm_hw_params *hw_params) -{ - switch (params_channels(hw_params)) { - default: /* 2 */ - return OXYGEN_PLAY_CHANNELS_2; - case 4: - return OXYGEN_PLAY_CHANNELS_4; - case 6: - return OXYGEN_PLAY_CHANNELS_6; - case 8: - return OXYGEN_PLAY_CHANNELS_8; - } -} - -static const unsigned int channel_base_registers[PCM_COUNT] = { - [PCM_A] = OXYGEN_DMA_A_ADDRESS, - [PCM_B] = OXYGEN_DMA_B_ADDRESS, - [PCM_C] = OXYGEN_DMA_C_ADDRESS, - [PCM_SPDIF] = OXYGEN_DMA_SPDIF_ADDRESS, - [PCM_MULTICH] = OXYGEN_DMA_MULTICH_ADDRESS, - [PCM_AC97] = OXYGEN_DMA_AC97_ADDRESS, -}; - -static int oxygen_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct oxygen *chip = snd_pcm_substream_chip(substream); - unsigned int channel = oxygen_substream_channel(substream); - int err; - - err = snd_pcm_lib_malloc_pages(substream, - params_buffer_bytes(hw_params)); - if (err < 0) - return err; - - oxygen_write32(chip, channel_base_registers[channel], - (u32)substream->runtime->dma_addr); - if (channel == PCM_MULTICH) { - oxygen_write32(chip, OXYGEN_DMA_MULTICH_COUNT, - params_buffer_bytes(hw_params) / 4 - 1); - oxygen_write32(chip, OXYGEN_DMA_MULTICH_TCOUNT, - params_period_bytes(hw_params) / 4 - 1); - } else { - oxygen_write16(chip, channel_base_registers[channel] + 4, - params_buffer_bytes(hw_params) / 4 - 1); - oxygen_write16(chip, channel_base_registers[channel] + 6, - params_period_bytes(hw_params) / 4 - 1); - } - return 0; -} - -static u16 get_mclk(struct oxygen *chip, unsigned int channel, - struct snd_pcm_hw_params *params) -{ - unsigned int mclks, shift; - - if (channel == PCM_MULTICH) - mclks = chip->model.dac_mclks; - else - mclks = chip->model.adc_mclks; - - if (params_rate(params) <= 48000) - shift = 0; - else if (params_rate(params) <= 96000) - shift = 2; - else - shift = 4; - - return OXYGEN_I2S_MCLK(mclks >> shift); -} - -static int oxygen_rec_a_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct oxygen *chip = snd_pcm_substream_chip(substream); - int err; - - err = oxygen_hw_params(substream, hw_params); - if (err < 0) - return err; - - spin_lock_irq(&chip->reg_lock); - oxygen_write8_masked(chip, OXYGEN_REC_FORMAT, - oxygen_format(hw_params) << OXYGEN_REC_FORMAT_A_SHIFT, - OXYGEN_REC_FORMAT_A_MASK); - oxygen_write16_masked(chip, OXYGEN_I2S_A_FORMAT, - oxygen_rate(hw_params) | - chip->model.adc_i2s_format | - get_mclk(chip, PCM_A, hw_params) | - oxygen_i2s_bits(hw_params), - OXYGEN_I2S_RATE_MASK | - OXYGEN_I2S_FORMAT_MASK | - OXYGEN_I2S_MCLK_MASK | - OXYGEN_I2S_BITS_MASK); - spin_unlock_irq(&chip->reg_lock); - - mutex_lock(&chip->mutex); - chip->model.set_adc_params(chip, hw_params); - mutex_unlock(&chip->mutex); - return 0; -} - -static int oxygen_rec_b_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct oxygen *chip = snd_pcm_substream_chip(substream); - int is_ac97; - int err; - - err = oxygen_hw_params(substream, hw_params); - if (err < 0) - return err; - - is_ac97 = chip->has_ac97_1 && - (chip->model.device_config & CAPTURE_2_FROM_AC97_1); - - spin_lock_irq(&chip->reg_lock); - oxygen_write8_masked(chip, OXYGEN_REC_FORMAT, - oxygen_format(hw_params) << OXYGEN_REC_FORMAT_B_SHIFT, - OXYGEN_REC_FORMAT_B_MASK); - if (!is_ac97) - oxygen_write16_masked(chip, OXYGEN_I2S_B_FORMAT, - oxygen_rate(hw_params) | - chip->model.adc_i2s_format | - get_mclk(chip, PCM_B, hw_params) | - oxygen_i2s_bits(hw_params), - OXYGEN_I2S_RATE_MASK | - OXYGEN_I2S_FORMAT_MASK | - OXYGEN_I2S_MCLK_MASK | - OXYGEN_I2S_BITS_MASK); - spin_unlock_irq(&chip->reg_lock); - - if (!is_ac97) { - mutex_lock(&chip->mutex); - chip->model.set_adc_params(chip, hw_params); - mutex_unlock(&chip->mutex); - } - return 0; -} - -static int oxygen_rec_c_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct oxygen *chip = snd_pcm_substream_chip(substream); - int err; - - err = oxygen_hw_params(substream, hw_params); - if (err < 0) - return err; - - spin_lock_irq(&chip->reg_lock); - oxygen_write8_masked(chip, OXYGEN_REC_FORMAT, - oxygen_format(hw_params) << OXYGEN_REC_FORMAT_C_SHIFT, - OXYGEN_REC_FORMAT_C_MASK); - spin_unlock_irq(&chip->reg_lock); - return 0; -} - -static int oxygen_spdif_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct oxygen *chip = snd_pcm_substream_chip(substream); - int err; - - err = oxygen_hw_params(substream, hw_params); - if (err < 0) - return err; - - mutex_lock(&chip->mutex); - spin_lock_irq(&chip->reg_lock); - oxygen_clear_bits32(chip, OXYGEN_SPDIF_CONTROL, - OXYGEN_SPDIF_OUT_ENABLE); - oxygen_write8_masked(chip, OXYGEN_PLAY_FORMAT, - oxygen_format(hw_params) << OXYGEN_SPDIF_FORMAT_SHIFT, - OXYGEN_SPDIF_FORMAT_MASK); - oxygen_write32_masked(chip, OXYGEN_SPDIF_CONTROL, - oxygen_rate(hw_params) << OXYGEN_SPDIF_OUT_RATE_SHIFT, - OXYGEN_SPDIF_OUT_RATE_MASK); - oxygen_update_spdif_source(chip); - spin_unlock_irq(&chip->reg_lock); - mutex_unlock(&chip->mutex); - return 0; -} - -static int oxygen_multich_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct oxygen *chip = snd_pcm_substream_chip(substream); - int err; - - err = oxygen_hw_params(substream, hw_params); - if (err < 0) - return err; - - mutex_lock(&chip->mutex); - spin_lock_irq(&chip->reg_lock); - oxygen_write8_masked(chip, OXYGEN_PLAY_CHANNELS, - oxygen_play_channels(hw_params), - OXYGEN_PLAY_CHANNELS_MASK); - oxygen_write8_masked(chip, OXYGEN_PLAY_FORMAT, - oxygen_format(hw_params) << OXYGEN_MULTICH_FORMAT_SHIFT, - OXYGEN_MULTICH_FORMAT_MASK); - oxygen_write16_masked(chip, OXYGEN_I2S_MULTICH_FORMAT, - oxygen_rate(hw_params) | - chip->model.dac_i2s_format | - get_mclk(chip, PCM_MULTICH, hw_params) | - oxygen_i2s_bits(hw_params), - OXYGEN_I2S_RATE_MASK | - OXYGEN_I2S_FORMAT_MASK | - OXYGEN_I2S_MCLK_MASK | - OXYGEN_I2S_BITS_MASK); - oxygen_update_spdif_source(chip); - spin_unlock_irq(&chip->reg_lock); - - chip->model.set_dac_params(chip, hw_params); - oxygen_update_dac_routing(chip); - mutex_unlock(&chip->mutex); - return 0; -} - -static int oxygen_hw_free(struct snd_pcm_substream *substream) -{ - struct oxygen *chip = snd_pcm_substream_chip(substream); - unsigned int channel = oxygen_substream_channel(substream); - unsigned int channel_mask = 1 << channel; - - spin_lock_irq(&chip->reg_lock); - chip->interrupt_mask &= ~channel_mask; - oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, chip->interrupt_mask); - - oxygen_set_bits8(chip, OXYGEN_DMA_FLUSH, channel_mask); - oxygen_clear_bits8(chip, OXYGEN_DMA_FLUSH, channel_mask); - spin_unlock_irq(&chip->reg_lock); - - return snd_pcm_lib_free_pages(substream); -} - -static int oxygen_spdif_hw_free(struct snd_pcm_substream *substream) -{ - struct oxygen *chip = snd_pcm_substream_chip(substream); - - spin_lock_irq(&chip->reg_lock); - oxygen_clear_bits32(chip, OXYGEN_SPDIF_CONTROL, - OXYGEN_SPDIF_OUT_ENABLE); - spin_unlock_irq(&chip->reg_lock); - return oxygen_hw_free(substream); -} - -static int oxygen_prepare(struct snd_pcm_substream *substream) -{ - struct oxygen *chip = snd_pcm_substream_chip(substream); - unsigned int channel = oxygen_substream_channel(substream); - unsigned int channel_mask = 1 << channel; - - spin_lock_irq(&chip->reg_lock); - oxygen_set_bits8(chip, OXYGEN_DMA_FLUSH, channel_mask); - oxygen_clear_bits8(chip, OXYGEN_DMA_FLUSH, channel_mask); - - if (substream->runtime->no_period_wakeup) - chip->interrupt_mask &= ~channel_mask; - else - chip->interrupt_mask |= channel_mask; - oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, chip->interrupt_mask); - spin_unlock_irq(&chip->reg_lock); - return 0; -} - -static int oxygen_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct oxygen *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_substream *s; - unsigned int mask = 0; - int pausing; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_SUSPEND: - pausing = 0; - break; - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - pausing = 1; - break; - default: - return -EINVAL; - } - - snd_pcm_group_for_each_entry(s, substream) { - if (snd_pcm_substream_chip(s) == chip) { - mask |= 1 << oxygen_substream_channel(s); - snd_pcm_trigger_done(s, substream); - } - } - - spin_lock(&chip->reg_lock); - if (!pausing) { - if (cmd == SNDRV_PCM_TRIGGER_START) - chip->pcm_running |= mask; - else - chip->pcm_running &= ~mask; - oxygen_write8(chip, OXYGEN_DMA_STATUS, chip->pcm_running); - } else { - if (cmd == SNDRV_PCM_TRIGGER_PAUSE_PUSH) - oxygen_set_bits8(chip, OXYGEN_DMA_PAUSE, mask); - else - oxygen_clear_bits8(chip, OXYGEN_DMA_PAUSE, mask); - } - spin_unlock(&chip->reg_lock); - return 0; -} - -static snd_pcm_uframes_t oxygen_pointer(struct snd_pcm_substream *substream) -{ - struct oxygen *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned int channel = oxygen_substream_channel(substream); - u32 curr_addr; - - /* no spinlock, this read should be atomic */ - curr_addr = oxygen_read32(chip, channel_base_registers[channel]); - return bytes_to_frames(runtime, curr_addr - (u32)runtime->dma_addr); -} - -static struct snd_pcm_ops oxygen_rec_a_ops = { - .open = oxygen_rec_a_open, - .close = oxygen_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = oxygen_rec_a_hw_params, - .hw_free = oxygen_hw_free, - .prepare = oxygen_prepare, - .trigger = oxygen_trigger, - .pointer = oxygen_pointer, -}; - -static struct snd_pcm_ops oxygen_rec_b_ops = { - .open = oxygen_rec_b_open, - .close = oxygen_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = oxygen_rec_b_hw_params, - .hw_free = oxygen_hw_free, - .prepare = oxygen_prepare, - .trigger = oxygen_trigger, - .pointer = oxygen_pointer, -}; - -static struct snd_pcm_ops oxygen_rec_c_ops = { - .open = oxygen_rec_c_open, - .close = oxygen_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = oxygen_rec_c_hw_params, - .hw_free = oxygen_hw_free, - .prepare = oxygen_prepare, - .trigger = oxygen_trigger, - .pointer = oxygen_pointer, -}; - -static struct snd_pcm_ops oxygen_spdif_ops = { - .open = oxygen_spdif_open, - .close = oxygen_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = oxygen_spdif_hw_params, - .hw_free = oxygen_spdif_hw_free, - .prepare = oxygen_prepare, - .trigger = oxygen_trigger, - .pointer = oxygen_pointer, -}; - -static struct snd_pcm_ops oxygen_multich_ops = { - .open = oxygen_multich_open, - .close = oxygen_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = oxygen_multich_hw_params, - .hw_free = oxygen_hw_free, - .prepare = oxygen_prepare, - .trigger = oxygen_trigger, - .pointer = oxygen_pointer, -}; - -static struct snd_pcm_ops oxygen_ac97_ops = { - .open = oxygen_ac97_open, - .close = oxygen_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = oxygen_hw_params, - .hw_free = oxygen_hw_free, - .prepare = oxygen_prepare, - .trigger = oxygen_trigger, - .pointer = oxygen_pointer, -}; - -static void oxygen_pcm_free(struct snd_pcm *pcm) -{ - snd_pcm_lib_preallocate_free_for_all(pcm); -} - -int oxygen_pcm_init(struct oxygen *chip) -{ - struct snd_pcm *pcm; - int outs, ins; - int err; - - outs = !!(chip->model.device_config & PLAYBACK_0_TO_I2S); - ins = !!(chip->model.device_config & (CAPTURE_0_FROM_I2S_1 | - CAPTURE_0_FROM_I2S_2)); - if (outs | ins) { - err = snd_pcm_new(chip->card, "Multichannel", - 0, outs, ins, &pcm); - if (err < 0) - return err; - if (outs) - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, - &oxygen_multich_ops); - if (chip->model.device_config & CAPTURE_0_FROM_I2S_1) - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, - &oxygen_rec_a_ops); - else if (chip->model.device_config & CAPTURE_0_FROM_I2S_2) - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, - &oxygen_rec_b_ops); - pcm->private_data = chip; - pcm->private_free = oxygen_pcm_free; - strcpy(pcm->name, "Multichannel"); - if (outs) - snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream, - SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(chip->pci), - DEFAULT_BUFFER_BYTES_MULTICH, - BUFFER_BYTES_MAX_MULTICH); - if (ins) - snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream, - SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(chip->pci), - DEFAULT_BUFFER_BYTES, - BUFFER_BYTES_MAX); - } - - outs = !!(chip->model.device_config & PLAYBACK_1_TO_SPDIF); - ins = !!(chip->model.device_config & CAPTURE_1_FROM_SPDIF); - if (outs | ins) { - err = snd_pcm_new(chip->card, "Digital", 1, outs, ins, &pcm); - if (err < 0) - return err; - if (outs) - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, - &oxygen_spdif_ops); - if (ins) - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, - &oxygen_rec_c_ops); - pcm->private_data = chip; - pcm->private_free = oxygen_pcm_free; - strcpy(pcm->name, "Digital"); - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(chip->pci), - DEFAULT_BUFFER_BYTES, - BUFFER_BYTES_MAX); - } - - if (chip->has_ac97_1) { - outs = !!(chip->model.device_config & PLAYBACK_2_TO_AC97_1); - ins = !!(chip->model.device_config & CAPTURE_2_FROM_AC97_1); - } else { - outs = 0; - ins = !!(chip->model.device_config & CAPTURE_2_FROM_I2S_2); - } - if (outs | ins) { - err = snd_pcm_new(chip->card, outs ? "AC97" : "Analog2", - 2, outs, ins, &pcm); - if (err < 0) - return err; - if (outs) { - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, - &oxygen_ac97_ops); - oxygen_write8_masked(chip, OXYGEN_REC_ROUTING, - OXYGEN_REC_B_ROUTE_AC97_1, - OXYGEN_REC_B_ROUTE_MASK); - } - if (ins) - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, - &oxygen_rec_b_ops); - pcm->private_data = chip; - pcm->private_free = oxygen_pcm_free; - strcpy(pcm->name, outs ? "Front Panel" : "Analog 2"); - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(chip->pci), - DEFAULT_BUFFER_BYTES, - BUFFER_BYTES_MAX); - } - return 0; -} diff --git a/ANDROID_3.4.5/sound/pci/oxygen/oxygen_regs.h b/ANDROID_3.4.5/sound/pci/oxygen/oxygen_regs.h deleted file mode 100644 index 63dc7a0a..00000000 --- a/ANDROID_3.4.5/sound/pci/oxygen/oxygen_regs.h +++ /dev/null @@ -1,457 +0,0 @@ -#ifndef OXYGEN_REGS_H_INCLUDED -#define OXYGEN_REGS_H_INCLUDED - -/* recording channel A */ -#define OXYGEN_DMA_A_ADDRESS 0x00 /* 32-bit base address */ -#define OXYGEN_DMA_A_COUNT 0x04 /* buffer counter (dwords) */ -#define OXYGEN_DMA_A_TCOUNT 0x06 /* interrupt counter (dwords) */ - -/* recording channel B */ -#define OXYGEN_DMA_B_ADDRESS 0x08 -#define OXYGEN_DMA_B_COUNT 0x0c -#define OXYGEN_DMA_B_TCOUNT 0x0e - -/* recording channel C */ -#define OXYGEN_DMA_C_ADDRESS 0x10 -#define OXYGEN_DMA_C_COUNT 0x14 -#define OXYGEN_DMA_C_TCOUNT 0x16 - -/* SPDIF playback channel */ -#define OXYGEN_DMA_SPDIF_ADDRESS 0x18 -#define OXYGEN_DMA_SPDIF_COUNT 0x1c -#define OXYGEN_DMA_SPDIF_TCOUNT 0x1e - -/* multichannel playback channel */ -#define OXYGEN_DMA_MULTICH_ADDRESS 0x20 -#define OXYGEN_DMA_MULTICH_COUNT 0x24 /* 24 bits */ -#define OXYGEN_DMA_MULTICH_TCOUNT 0x28 /* 24 bits */ - -/* AC'97 (front panel) playback channel */ -#define OXYGEN_DMA_AC97_ADDRESS 0x30 -#define OXYGEN_DMA_AC97_COUNT 0x34 -#define OXYGEN_DMA_AC97_TCOUNT 0x36 - -/* all registers 0x00..0x36 return current position on read */ - -#define OXYGEN_DMA_STATUS 0x40 /* 1 = running, 0 = stop */ -#define OXYGEN_CHANNEL_A 0x01 -#define OXYGEN_CHANNEL_B 0x02 -#define OXYGEN_CHANNEL_C 0x04 -#define OXYGEN_CHANNEL_SPDIF 0x08 -#define OXYGEN_CHANNEL_MULTICH 0x10 -#define OXYGEN_CHANNEL_AC97 0x20 - -#define OXYGEN_DMA_PAUSE 0x41 /* 1 = pause */ -/* OXYGEN_CHANNEL_* */ - -#define OXYGEN_DMA_RESET 0x42 -/* OXYGEN_CHANNEL_* */ - -#define OXYGEN_PLAY_CHANNELS 0x43 -#define OXYGEN_PLAY_CHANNELS_MASK 0x03 -#define OXYGEN_PLAY_CHANNELS_2 0x00 -#define OXYGEN_PLAY_CHANNELS_4 0x01 -#define OXYGEN_PLAY_CHANNELS_6 0x02 -#define OXYGEN_PLAY_CHANNELS_8 0x03 -#define OXYGEN_DMA_A_BURST_MASK 0x04 -#define OXYGEN_DMA_A_BURST_8 0x00 /* dwords */ -#define OXYGEN_DMA_A_BURST_16 0x04 -#define OXYGEN_DMA_MULTICH_BURST_MASK 0x08 -#define OXYGEN_DMA_MULTICH_BURST_8 0x00 -#define OXYGEN_DMA_MULTICH_BURST_16 0x08 - -#define OXYGEN_INTERRUPT_MASK 0x44 -/* OXYGEN_CHANNEL_* */ -#define OXYGEN_INT_SPDIF_IN_DETECT 0x0100 -#define OXYGEN_INT_MCU 0x0200 -#define OXYGEN_INT_2WIRE 0x0400 -#define OXYGEN_INT_GPIO 0x0800 -#define OXYGEN_INT_MCB 0x2000 -#define OXYGEN_INT_AC97 0x4000 - -#define OXYGEN_INTERRUPT_STATUS 0x46 -/* OXYGEN_CHANNEL_* amd OXYGEN_INT_* */ -#define OXYGEN_INT_MIDI 0x1000 - -#define OXYGEN_MISC 0x48 -#define OXYGEN_MISC_WRITE_PCI_SUBID 0x01 -#define OXYGEN_MISC_LATENCY_3F 0x02 -#define OXYGEN_MISC_REC_C_FROM_SPDIF 0x04 -#define OXYGEN_MISC_REC_B_FROM_AC97 0x08 -#define OXYGEN_MISC_REC_A_FROM_MULTICH 0x10 -#define OXYGEN_MISC_PCI_MEM_W_1_CLOCK 0x20 -#define OXYGEN_MISC_MIDI 0x40 -#define OXYGEN_MISC_CRYSTAL_MASK 0x80 -#define OXYGEN_MISC_CRYSTAL_24576 0x00 -#define OXYGEN_MISC_CRYSTAL_27 0x80 /* MHz */ - -#define OXYGEN_REC_FORMAT 0x4a -#define OXYGEN_REC_FORMAT_A_MASK 0x03 -#define OXYGEN_REC_FORMAT_A_SHIFT 0 -#define OXYGEN_REC_FORMAT_B_MASK 0x0c -#define OXYGEN_REC_FORMAT_B_SHIFT 2 -#define OXYGEN_REC_FORMAT_C_MASK 0x30 -#define OXYGEN_REC_FORMAT_C_SHIFT 4 -#define OXYGEN_FORMAT_16 0x00 -#define OXYGEN_FORMAT_24 0x01 -#define OXYGEN_FORMAT_32 0x02 - -#define OXYGEN_PLAY_FORMAT 0x4b -#define OXYGEN_SPDIF_FORMAT_MASK 0x03 -#define OXYGEN_SPDIF_FORMAT_SHIFT 0 -#define OXYGEN_MULTICH_FORMAT_MASK 0x0c -#define OXYGEN_MULTICH_FORMAT_SHIFT 2 -/* OXYGEN_FORMAT_* */ - -#define OXYGEN_REC_CHANNELS 0x4c -#define OXYGEN_REC_CHANNELS_MASK 0x07 -#define OXYGEN_REC_CHANNELS_2_2_2 0x00 /* DMA A, B, C */ -#define OXYGEN_REC_CHANNELS_4_2_2 0x01 -#define OXYGEN_REC_CHANNELS_6_0_2 0x02 -#define OXYGEN_REC_CHANNELS_6_2_0 0x03 -#define OXYGEN_REC_CHANNELS_8_0_0 0x04 - -#define OXYGEN_FUNCTION 0x50 -#define OXYGEN_FUNCTION_CLOCK_MASK 0x01 -#define OXYGEN_FUNCTION_CLOCK_PLL 0x00 -#define OXYGEN_FUNCTION_CLOCK_CRYSTAL 0x01 -#define OXYGEN_FUNCTION_RESET_CODEC 0x02 -#define OXYGEN_FUNCTION_RESET_POL 0x04 -#define OXYGEN_FUNCTION_PWDN 0x08 -#define OXYGEN_FUNCTION_PWDN_EN 0x10 -#define OXYGEN_FUNCTION_PWDN_POL 0x20 -#define OXYGEN_FUNCTION_2WIRE_SPI_MASK 0x40 -#define OXYGEN_FUNCTION_SPI 0x00 -#define OXYGEN_FUNCTION_2WIRE 0x40 -#define OXYGEN_FUNCTION_ENABLE_SPI_4_5 0x80 /* 0 = EEPROM */ - -#define OXYGEN_I2S_MULTICH_FORMAT 0x60 -#define OXYGEN_I2S_RATE_MASK 0x0007 /* LRCK */ -#define OXYGEN_RATE_32000 0x0000 -#define OXYGEN_RATE_44100 0x0001 -#define OXYGEN_RATE_48000 0x0002 -#define OXYGEN_RATE_64000 0x0003 -#define OXYGEN_RATE_88200 0x0004 -#define OXYGEN_RATE_96000 0x0005 -#define OXYGEN_RATE_176400 0x0006 -#define OXYGEN_RATE_192000 0x0007 -#define OXYGEN_I2S_FORMAT_MASK 0x0008 -#define OXYGEN_I2S_FORMAT_I2S 0x0000 -#define OXYGEN_I2S_FORMAT_LJUST 0x0008 -#define OXYGEN_I2S_MCLK_MASK 0x0030 /* MCLK/LRCK */ -#define OXYGEN_I2S_MCLK_SHIFT 4 -#define MCLK_128 0 -#define MCLK_256 1 -#define MCLK_512 2 -#define OXYGEN_I2S_MCLK(f) (((f) & 3) << OXYGEN_I2S_MCLK_SHIFT) -#define OXYGEN_I2S_BITS_MASK 0x00c0 -#define OXYGEN_I2S_BITS_16 0x0000 -#define OXYGEN_I2S_BITS_20 0x0040 -#define OXYGEN_I2S_BITS_24 0x0080 -#define OXYGEN_I2S_BITS_32 0x00c0 -#define OXYGEN_I2S_MASTER 0x0100 -#define OXYGEN_I2S_BCLK_MASK 0x0600 /* BCLK/LRCK */ -#define OXYGEN_I2S_BCLK_64 0x0000 -#define OXYGEN_I2S_BCLK_128 0x0200 -#define OXYGEN_I2S_BCLK_256 0x0400 -#define OXYGEN_I2S_MUTE_MCLK 0x0800 - -#define OXYGEN_I2S_A_FORMAT 0x62 -#define OXYGEN_I2S_B_FORMAT 0x64 -#define OXYGEN_I2S_C_FORMAT 0x66 -/* like OXYGEN_I2S_MULTICH_FORMAT */ - -#define OXYGEN_SPDIF_CONTROL 0x70 -#define OXYGEN_SPDIF_OUT_ENABLE 0x00000002 -#define OXYGEN_SPDIF_LOOPBACK 0x00000004 /* in to out */ -#define OXYGEN_SPDIF_SENSE_MASK 0x00000008 -#define OXYGEN_SPDIF_LOCK_MASK 0x00000010 -#define OXYGEN_SPDIF_RATE_MASK 0x00000020 -#define OXYGEN_SPDIF_SPDVALID 0x00000040 -#define OXYGEN_SPDIF_SENSE_PAR 0x00000200 -#define OXYGEN_SPDIF_LOCK_PAR 0x00000400 -#define OXYGEN_SPDIF_SENSE_STATUS 0x00000800 -#define OXYGEN_SPDIF_LOCK_STATUS 0x00001000 -#define OXYGEN_SPDIF_SENSE_INT 0x00002000 /* r/wc */ -#define OXYGEN_SPDIF_LOCK_INT 0x00004000 /* r/wc */ -#define OXYGEN_SPDIF_RATE_INT 0x00008000 /* r/wc */ -#define OXYGEN_SPDIF_IN_CLOCK_MASK 0x00010000 -#define OXYGEN_SPDIF_IN_CLOCK_96 0x00000000 /* <= 96 kHz */ -#define OXYGEN_SPDIF_IN_CLOCK_192 0x00010000 /* > 96 kHz */ -#define OXYGEN_SPDIF_OUT_RATE_MASK 0x07000000 -#define OXYGEN_SPDIF_OUT_RATE_SHIFT 24 -/* OXYGEN_RATE_* << OXYGEN_SPDIF_OUT_RATE_SHIFT */ - -#define OXYGEN_SPDIF_OUTPUT_BITS 0x74 -#define OXYGEN_SPDIF_NONAUDIO 0x00000002 -#define OXYGEN_SPDIF_C 0x00000004 -#define OXYGEN_SPDIF_PREEMPHASIS 0x00000008 -#define OXYGEN_SPDIF_CATEGORY_MASK 0x000007f0 -#define OXYGEN_SPDIF_CATEGORY_SHIFT 4 -#define OXYGEN_SPDIF_ORIGINAL 0x00000800 -#define OXYGEN_SPDIF_CS_RATE_MASK 0x0000f000 -#define OXYGEN_SPDIF_CS_RATE_SHIFT 12 -#define OXYGEN_SPDIF_V 0x00010000 /* 0 = valid */ - -#define OXYGEN_SPDIF_INPUT_BITS 0x78 -/* 32 bits, IEC958_AES_* */ - -#define OXYGEN_EEPROM_CONTROL 0x80 -#define OXYGEN_EEPROM_ADDRESS_MASK 0x7f -#define OXYGEN_EEPROM_DIR_MASK 0x80 -#define OXYGEN_EEPROM_DIR_READ 0x00 -#define OXYGEN_EEPROM_DIR_WRITE 0x80 - -#define OXYGEN_EEPROM_STATUS 0x81 -#define OXYGEN_EEPROM_VALID 0x40 -#define OXYGEN_EEPROM_BUSY 0x80 - -#define OXYGEN_EEPROM_DATA 0x82 /* 16 bits */ - -#define OXYGEN_2WIRE_CONTROL 0x90 -#define OXYGEN_2WIRE_DIR_MASK 0x01 -#define OXYGEN_2WIRE_DIR_WRITE 0x00 -#define OXYGEN_2WIRE_DIR_READ 0x01 -#define OXYGEN_2WIRE_ADDRESS_MASK 0xfe /* slave device address */ -#define OXYGEN_2WIRE_ADDRESS_SHIFT 1 - -#define OXYGEN_2WIRE_MAP 0x91 /* address, 8 bits */ -#define OXYGEN_2WIRE_DATA 0x92 /* data, 16 bits */ - -#define OXYGEN_2WIRE_BUS_STATUS 0x94 -#define OXYGEN_2WIRE_BUSY 0x0001 -#define OXYGEN_2WIRE_LENGTH_MASK 0x0002 -#define OXYGEN_2WIRE_LENGTH_8 0x0000 -#define OXYGEN_2WIRE_LENGTH_16 0x0002 -#define OXYGEN_2WIRE_MANUAL_READ 0x0004 /* 0 = auto read */ -#define OXYGEN_2WIRE_WRITE_MAP_ONLY 0x0008 -#define OXYGEN_2WIRE_SLAVE_AD_MASK 0x0030 /* AD0, AD1 */ -#define OXYGEN_2WIRE_INTERRUPT_MASK 0x0040 /* 0 = int. if not responding */ -#define OXYGEN_2WIRE_SLAVE_NO_RESPONSE 0x0080 -#define OXYGEN_2WIRE_SPEED_MASK 0x0100 -#define OXYGEN_2WIRE_SPEED_STANDARD 0x0000 -#define OXYGEN_2WIRE_SPEED_FAST 0x0100 -#define OXYGEN_2WIRE_CLOCK_SYNC 0x0200 -#define OXYGEN_2WIRE_BUS_RESET 0x0400 - -#define OXYGEN_SPI_CONTROL 0x98 -#define OXYGEN_SPI_BUSY 0x01 /* read */ -#define OXYGEN_SPI_TRIGGER 0x01 /* write */ -#define OXYGEN_SPI_DATA_LENGTH_MASK 0x02 -#define OXYGEN_SPI_DATA_LENGTH_2 0x00 -#define OXYGEN_SPI_DATA_LENGTH_3 0x02 -#define OXYGEN_SPI_CLOCK_MASK 0x0c -#define OXYGEN_SPI_CLOCK_160 0x00 /* ns */ -#define OXYGEN_SPI_CLOCK_320 0x04 -#define OXYGEN_SPI_CLOCK_640 0x08 -#define OXYGEN_SPI_CLOCK_1280 0x0c -#define OXYGEN_SPI_CODEC_MASK 0x70 /* 0..5 */ -#define OXYGEN_SPI_CODEC_SHIFT 4 -#define OXYGEN_SPI_CEN_MASK 0x80 -#define OXYGEN_SPI_CEN_LATCH_CLOCK_LO 0x00 -#define OXYGEN_SPI_CEN_LATCH_CLOCK_HI 0x80 - -#define OXYGEN_SPI_DATA1 0x99 -#define OXYGEN_SPI_DATA2 0x9a -#define OXYGEN_SPI_DATA3 0x9b - -#define OXYGEN_MPU401 0xa0 - -#define OXYGEN_MPU401_CONTROL 0xa2 -#define OXYGEN_MPU401_LOOPBACK 0x01 /* TXD to RXD */ - -#define OXYGEN_GPI_DATA 0xa4 -/* bits 0..5 = pin XGPI0..XGPI5 */ - -#define OXYGEN_GPI_INTERRUPT_MASK 0xa5 -/* bits 0..5, 1 = enable */ - -#define OXYGEN_GPIO_DATA 0xa6 -/* bits 0..9 */ - -#define OXYGEN_GPIO_CONTROL 0xa8 -/* bits 0..9, 0 = input, 1 = output */ -#define OXYGEN_GPIO1_XSLAVE_RDY 0x8000 - -#define OXYGEN_GPIO_INTERRUPT_MASK 0xaa -/* bits 0..9, 1 = enable */ - -#define OXYGEN_DEVICE_SENSE 0xac -#define OXYGEN_HEAD_PHONE_DETECT 0x01 -#define OXYGEN_HEAD_PHONE_MASK 0x06 -#define OXYGEN_HEAD_PHONE_PASSIVE_SPK 0x00 -#define OXYGEN_HEAD_PHONE_HP 0x02 -#define OXYGEN_HEAD_PHONE_ACTIVE_SPK 0x04 - -#define OXYGEN_MCU_2WIRE_DATA 0xb0 - -#define OXYGEN_MCU_2WIRE_MAP 0xb2 - -#define OXYGEN_MCU_2WIRE_STATUS 0xb3 -#define OXYGEN_MCU_2WIRE_BUSY 0x01 -#define OXYGEN_MCU_2WIRE_LENGTH_MASK 0x06 -#define OXYGEN_MCU_2WIRE_LENGTH_1 0x00 -#define OXYGEN_MCU_2WIRE_LENGTH_2 0x02 -#define OXYGEN_MCU_2WIRE_LENGTH_3 0x04 -#define OXYGEN_MCU_2WIRE_WRITE 0x08 /* r/wc */ -#define OXYGEN_MCU_2WIRE_READ 0x10 /* r/wc */ -#define OXYGEN_MCU_2WIRE_DRV_XACT_FAIL 0x20 /* r/wc */ -#define OXYGEN_MCU_2WIRE_RESET 0x40 - -#define OXYGEN_MCU_2WIRE_CONTROL 0xb4 -#define OXYGEN_MCU_2WIRE_DRV_ACK 0x01 -#define OXYGEN_MCU_2WIRE_DRV_XACT 0x02 -#define OXYGEN_MCU_2WIRE_INT_MASK 0x04 -#define OXYGEN_MCU_2WIRE_SYNC_MASK 0x08 -#define OXYGEN_MCU_2WIRE_SYNC_RDY_PIN 0x00 -#define OXYGEN_MCU_2WIRE_SYNC_DATA 0x08 -#define OXYGEN_MCU_2WIRE_ADDRESS_MASK 0x30 -#define OXYGEN_MCU_2WIRE_ADDRESS_10 0x00 -#define OXYGEN_MCU_2WIRE_ADDRESS_12 0x10 -#define OXYGEN_MCU_2WIRE_ADDRESS_14 0x20 -#define OXYGEN_MCU_2WIRE_ADDRESS_16 0x30 -#define OXYGEN_MCU_2WIRE_INT_POL 0x40 -#define OXYGEN_MCU_2WIRE_SYNC_ENABLE 0x80 - -#define OXYGEN_PLAY_ROUTING 0xc0 -#define OXYGEN_PLAY_MUTE01 0x0001 -#define OXYGEN_PLAY_MUTE23 0x0002 -#define OXYGEN_PLAY_MUTE45 0x0004 -#define OXYGEN_PLAY_MUTE67 0x0008 -#define OXYGEN_PLAY_MULTICH_MASK 0x0010 -#define OXYGEN_PLAY_MULTICH_I2S_DAC 0x0000 -#define OXYGEN_PLAY_MULTICH_AC97 0x0010 -#define OXYGEN_PLAY_SPDIF_MASK 0x00e0 -#define OXYGEN_PLAY_SPDIF_SPDIF 0x0000 -#define OXYGEN_PLAY_SPDIF_MULTICH_01 0x0020 -#define OXYGEN_PLAY_SPDIF_MULTICH_23 0x0040 -#define OXYGEN_PLAY_SPDIF_MULTICH_45 0x0060 -#define OXYGEN_PLAY_SPDIF_MULTICH_67 0x0080 -#define OXYGEN_PLAY_SPDIF_REC_A 0x00a0 -#define OXYGEN_PLAY_SPDIF_REC_B 0x00c0 -#define OXYGEN_PLAY_SPDIF_I2S_ADC_3 0x00e0 -#define OXYGEN_PLAY_DAC0_SOURCE_MASK 0x0300 -#define OXYGEN_PLAY_DAC0_SOURCE_SHIFT 8 -#define OXYGEN_PLAY_DAC1_SOURCE_MASK 0x0c00 -#define OXYGEN_PLAY_DAC1_SOURCE_SHIFT 10 -#define OXYGEN_PLAY_DAC2_SOURCE_MASK 0x3000 -#define OXYGEN_PLAY_DAC2_SOURCE_SHIFT 12 -#define OXYGEN_PLAY_DAC3_SOURCE_MASK 0xc000 -#define OXYGEN_PLAY_DAC3_SOURCE_SHIFT 14 - -#define OXYGEN_REC_ROUTING 0xc2 -#define OXYGEN_MUTE_I2S_ADC_1 0x01 -#define OXYGEN_MUTE_I2S_ADC_2 0x02 -#define OXYGEN_MUTE_I2S_ADC_3 0x04 -#define OXYGEN_REC_A_ROUTE_MASK 0x08 -#define OXYGEN_REC_A_ROUTE_I2S_ADC_1 0x00 -#define OXYGEN_REC_A_ROUTE_AC97_0 0x08 -#define OXYGEN_REC_B_ROUTE_MASK 0x10 -#define OXYGEN_REC_B_ROUTE_I2S_ADC_2 0x00 -#define OXYGEN_REC_B_ROUTE_AC97_1 0x10 -#define OXYGEN_REC_C_ROUTE_MASK 0x20 -#define OXYGEN_REC_C_ROUTE_SPDIF 0x00 -#define OXYGEN_REC_C_ROUTE_I2S_ADC_3 0x20 - -#define OXYGEN_ADC_MONITOR 0xc3 -#define OXYGEN_ADC_MONITOR_A 0x01 -#define OXYGEN_ADC_MONITOR_A_HALF_VOL 0x02 -#define OXYGEN_ADC_MONITOR_B 0x04 -#define OXYGEN_ADC_MONITOR_B_HALF_VOL 0x08 -#define OXYGEN_ADC_MONITOR_C 0x10 -#define OXYGEN_ADC_MONITOR_C_HALF_VOL 0x20 - -#define OXYGEN_A_MONITOR_ROUTING 0xc4 -#define OXYGEN_A_MONITOR_ROUTE_0_MASK 0x03 -#define OXYGEN_A_MONITOR_ROUTE_0_SHIFT 0 -#define OXYGEN_A_MONITOR_ROUTE_1_MASK 0x0c -#define OXYGEN_A_MONITOR_ROUTE_1_SHIFT 2 -#define OXYGEN_A_MONITOR_ROUTE_2_MASK 0x30 -#define OXYGEN_A_MONITOR_ROUTE_2_SHIFT 4 -#define OXYGEN_A_MONITOR_ROUTE_3_MASK 0xc0 -#define OXYGEN_A_MONITOR_ROUTE_3_SHIFT 6 - -#define OXYGEN_AC97_CONTROL 0xd0 -#define OXYGEN_AC97_COLD_RESET 0x0001 -#define OXYGEN_AC97_SUSPENDED 0x0002 /* read */ -#define OXYGEN_AC97_RESUME 0x0002 /* write */ -#define OXYGEN_AC97_CLOCK_DISABLE 0x0004 -#define OXYGEN_AC97_NO_CODEC_0 0x0008 -#define OXYGEN_AC97_CODEC_0 0x0010 -#define OXYGEN_AC97_CODEC_1 0x0020 - -#define OXYGEN_AC97_INTERRUPT_MASK 0xd2 -#define OXYGEN_AC97_INT_READ_DONE 0x01 -#define OXYGEN_AC97_INT_WRITE_DONE 0x02 -#define OXYGEN_AC97_INT_CODEC_0 0x10 -#define OXYGEN_AC97_INT_CODEC_1 0x20 - -#define OXYGEN_AC97_INTERRUPT_STATUS 0xd3 -/* OXYGEN_AC97_INT_* */ - -#define OXYGEN_AC97_OUT_CONFIG 0xd4 -#define OXYGEN_AC97_CODEC1_SLOT3 0x00000001 -#define OXYGEN_AC97_CODEC1_SLOT3_VSR 0x00000002 -#define OXYGEN_AC97_CODEC1_SLOT4 0x00000010 -#define OXYGEN_AC97_CODEC1_SLOT4_VSR 0x00000020 -#define OXYGEN_AC97_CODEC0_FRONTL 0x00000100 -#define OXYGEN_AC97_CODEC0_FRONTR 0x00000200 -#define OXYGEN_AC97_CODEC0_SIDEL 0x00000400 -#define OXYGEN_AC97_CODEC0_SIDER 0x00000800 -#define OXYGEN_AC97_CODEC0_CENTER 0x00001000 -#define OXYGEN_AC97_CODEC0_BASE 0x00002000 -#define OXYGEN_AC97_CODEC0_REARL 0x00004000 -#define OXYGEN_AC97_CODEC0_REARR 0x00008000 - -#define OXYGEN_AC97_IN_CONFIG 0xd8 -#define OXYGEN_AC97_CODEC1_LINEL 0x00000001 -#define OXYGEN_AC97_CODEC1_LINEL_VSR 0x00000002 -#define OXYGEN_AC97_CODEC1_LINEL_16 0x00000000 -#define OXYGEN_AC97_CODEC1_LINEL_18 0x00000004 -#define OXYGEN_AC97_CODEC1_LINEL_20 0x00000008 -#define OXYGEN_AC97_CODEC1_LINER 0x00000010 -#define OXYGEN_AC97_CODEC1_LINER_VSR 0x00000020 -#define OXYGEN_AC97_CODEC1_LINER_16 0x00000000 -#define OXYGEN_AC97_CODEC1_LINER_18 0x00000040 -#define OXYGEN_AC97_CODEC1_LINER_20 0x00000080 -#define OXYGEN_AC97_CODEC0_LINEL 0x00000100 -#define OXYGEN_AC97_CODEC0_LINER 0x00000200 - -#define OXYGEN_AC97_REGS 0xdc -#define OXYGEN_AC97_REG_DATA_MASK 0x0000ffff -#define OXYGEN_AC97_REG_ADDR_MASK 0x007f0000 -#define OXYGEN_AC97_REG_ADDR_SHIFT 16 -#define OXYGEN_AC97_REG_DIR_MASK 0x00800000 -#define OXYGEN_AC97_REG_DIR_WRITE 0x00000000 -#define OXYGEN_AC97_REG_DIR_READ 0x00800000 -#define OXYGEN_AC97_REG_CODEC_MASK 0x01000000 -#define OXYGEN_AC97_REG_CODEC_SHIFT 24 - -#define OXYGEN_TEST 0xe0 -#define OXYGEN_TEST_RAM_SUCCEEDED 0x01 -#define OXYGEN_TEST_PLAYBACK_RAM 0x02 -#define OXYGEN_TEST_RECORD_RAM 0x04 -#define OXYGEN_TEST_PLL 0x08 -#define OXYGEN_TEST_2WIRE_LOOPBACK 0x10 - -#define OXYGEN_DMA_FLUSH 0xe1 -/* OXYGEN_CHANNEL_* */ - -#define OXYGEN_CODEC_VERSION 0xe4 -#define OXYGEN_CODEC_ID_MASK 0x07 - -#define OXYGEN_REVISION 0xe6 -#define OXYGEN_PACKAGE_ID_MASK 0x0007 -#define OXYGEN_PACKAGE_ID_8786 0x0004 -#define OXYGEN_PACKAGE_ID_8787 0x0006 -#define OXYGEN_PACKAGE_ID_8788 0x0007 -#define OXYGEN_REVISION_MASK 0xfff8 -#define OXYGEN_REVISION_2 0x0008 - -#define OXYGEN_OFFSIN_48K 0xe8 -#define OXYGEN_OFFSBASE_48K 0xe9 -#define OXYGEN_OFFSBASE_MASK 0x0fff -#define OXYGEN_OFFSIN_44K 0xec -#define OXYGEN_OFFSBASE_44K 0xed - -#endif diff --git a/ANDROID_3.4.5/sound/pci/oxygen/pcm1796.h b/ANDROID_3.4.5/sound/pci/oxygen/pcm1796.h deleted file mode 100644 index 698bf46c..00000000 --- a/ANDROID_3.4.5/sound/pci/oxygen/pcm1796.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef PCM1796_H_INCLUDED -#define PCM1796_H_INCLUDED - -/* register 16 */ -#define PCM1796_ATL_MASK 0xff -/* register 17 */ -#define PCM1796_ATR_MASK 0xff -/* register 18 */ -#define PCM1796_MUTE 0x01 -#define PCM1796_DME 0x02 -#define PCM1796_DMF_MASK 0x0c -#define PCM1796_DMF_DISABLED 0x00 -#define PCM1796_DMF_48 0x04 -#define PCM1796_DMF_441 0x08 -#define PCM1796_DMF_32 0x0c -#define PCM1796_FMT_MASK 0x70 -#define PCM1796_FMT_16_RJUST 0x00 -#define PCM1796_FMT_20_RJUST 0x10 -#define PCM1796_FMT_24_RJUST 0x20 -#define PCM1796_FMT_24_LJUST 0x30 -#define PCM1796_FMT_16_I2S 0x40 -#define PCM1796_FMT_24_I2S 0x50 -#define PCM1796_ATLD 0x80 -/* register 19 */ -#define PCM1796_INZD 0x01 -#define PCM1796_FLT_MASK 0x02 -#define PCM1796_FLT_SHARP 0x00 -#define PCM1796_FLT_SLOW 0x02 -#define PCM1796_DFMS 0x04 -#define PCM1796_OPE 0x10 -#define PCM1796_ATS_MASK 0x60 -#define PCM1796_ATS_1 0x00 -#define PCM1796_ATS_2 0x20 -#define PCM1796_ATS_4 0x40 -#define PCM1796_ATS_8 0x60 -#define PCM1796_REV 0x80 -/* register 20 */ -#define PCM1796_OS_MASK 0x03 -#define PCM1796_OS_64 0x00 -#define PCM1796_OS_32 0x01 -#define PCM1796_OS_128 0x02 -#define PCM1796_CHSL_MASK 0x04 -#define PCM1796_CHSL_LEFT 0x00 -#define PCM1796_CHSL_RIGHT 0x04 -#define PCM1796_MONO 0x08 -#define PCM1796_DFTH 0x10 -#define PCM1796_DSD 0x20 -#define PCM1796_SRST 0x40 -/* register 21 */ -#define PCM1796_PCMZ 0x01 -#define PCM1796_DZ_MASK 0x06 -/* register 22 */ -#define PCM1796_ZFGL 0x01 -#define PCM1796_ZFGR 0x02 -/* register 23 */ -#define PCM1796_ID_MASK 0x1f - -#endif diff --git a/ANDROID_3.4.5/sound/pci/oxygen/virtuoso.c b/ANDROID_3.4.5/sound/pci/oxygen/virtuoso.c deleted file mode 100644 index 3fdee495..00000000 --- a/ANDROID_3.4.5/sound/pci/oxygen/virtuoso.c +++ /dev/null @@ -1,114 +0,0 @@ -/* - * C-Media CMI8788 driver for Asus Xonar cards - * - * 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, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <linux/pci.h> -#include <linux/delay.h> -#include <linux/module.h> -#include <sound/core.h> -#include <sound/initval.h> -#include <sound/pcm.h> -#include "xonar.h" - -MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>"); -MODULE_DESCRIPTION("Asus Virtuoso driver"); -MODULE_LICENSE("GPL v2"); -MODULE_SUPPORTED_DEVICE("{{Asus,AV66},{Asus,AV100},{Asus,AV200}}"); - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; -static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "card index"); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string"); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "enable card"); - -static DEFINE_PCI_DEVICE_TABLE(xonar_ids) = { - { OXYGEN_PCI_SUBID(0x1043, 0x8269) }, - { OXYGEN_PCI_SUBID(0x1043, 0x8275) }, - { OXYGEN_PCI_SUBID(0x1043, 0x82b7) }, - { OXYGEN_PCI_SUBID(0x1043, 0x8314) }, - { OXYGEN_PCI_SUBID(0x1043, 0x8327) }, - { OXYGEN_PCI_SUBID(0x1043, 0x834f) }, - { OXYGEN_PCI_SUBID(0x1043, 0x835c) }, - { OXYGEN_PCI_SUBID(0x1043, 0x835d) }, - { OXYGEN_PCI_SUBID(0x1043, 0x835e) }, - { OXYGEN_PCI_SUBID(0x1043, 0x838e) }, - { OXYGEN_PCI_SUBID_BROKEN_EEPROM }, - { } -}; -MODULE_DEVICE_TABLE(pci, xonar_ids); - -static int __devinit get_xonar_model(struct oxygen *chip, - const struct pci_device_id *id) -{ - if (get_xonar_pcm179x_model(chip, id) >= 0) - return 0; - if (get_xonar_cs43xx_model(chip, id) >= 0) - return 0; - if (get_xonar_wm87x6_model(chip, id) >= 0) - return 0; - return -EINVAL; -} - -static int __devinit xonar_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id) -{ - static int dev; - int err; - - if (dev >= SNDRV_CARDS) - return -ENODEV; - if (!enable[dev]) { - ++dev; - return -ENOENT; - } - err = oxygen_pci_probe(pci, index[dev], id[dev], THIS_MODULE, - xonar_ids, get_xonar_model); - if (err >= 0) - ++dev; - return err; -} - -static struct pci_driver xonar_driver = { - .name = KBUILD_MODNAME, - .id_table = xonar_ids, - .probe = xonar_probe, - .remove = __devexit_p(oxygen_pci_remove), -#ifdef CONFIG_PM - .suspend = oxygen_pci_suspend, - .resume = oxygen_pci_resume, -#endif - .shutdown = oxygen_pci_shutdown, -}; - -static int __init alsa_card_xonar_init(void) -{ - return pci_register_driver(&xonar_driver); -} - -static void __exit alsa_card_xonar_exit(void) -{ - pci_unregister_driver(&xonar_driver); -} - -module_init(alsa_card_xonar_init) -module_exit(alsa_card_xonar_exit) diff --git a/ANDROID_3.4.5/sound/pci/oxygen/wm8766.h b/ANDROID_3.4.5/sound/pci/oxygen/wm8766.h deleted file mode 100644 index e0e849a7..00000000 --- a/ANDROID_3.4.5/sound/pci/oxygen/wm8766.h +++ /dev/null @@ -1,73 +0,0 @@ -#ifndef WM8766_H_INCLUDED -#define WM8766_H_INCLUDED - -#define WM8766_LDA1 0x00 -#define WM8766_RDA1 0x01 -#define WM8766_DAC_CTRL 0x02 -#define WM8766_INT_CTRL 0x03 -#define WM8766_LDA2 0x04 -#define WM8766_RDA2 0x05 -#define WM8766_LDA3 0x06 -#define WM8766_RDA3 0x07 -#define WM8766_MASTDA 0x08 -#define WM8766_DAC_CTRL2 0x09 -#define WM8766_DAC_CTRL3 0x0a -#define WM8766_MUTE1 0x0c -#define WM8766_MUTE2 0x0f -#define WM8766_RESET 0x1f - -/* LDAx/RDAx/MASTDA */ -#define WM8766_ATT_MASK 0x0ff -#define WM8766_UPDATE 0x100 -/* DAC_CTRL */ -#define WM8766_MUTEALL 0x001 -#define WM8766_DEEMPALL 0x002 -#define WM8766_PWDN 0x004 -#define WM8766_ATC 0x008 -#define WM8766_IZD 0x010 -#define WM8766_PL_LEFT_MASK 0x060 -#define WM8766_PL_LEFT_MUTE 0x000 -#define WM8766_PL_LEFT_LEFT 0x020 -#define WM8766_PL_LEFT_RIGHT 0x040 -#define WM8766_PL_LEFT_LRMIX 0x060 -#define WM8766_PL_RIGHT_MASK 0x180 -#define WM8766_PL_RIGHT_MUTE 0x000 -#define WM8766_PL_RIGHT_LEFT 0x080 -#define WM8766_PL_RIGHT_RIGHT 0x100 -#define WM8766_PL_RIGHT_LRMIX 0x180 -/* INT_CTRL */ -#define WM8766_FMT_MASK 0x003 -#define WM8766_FMT_RJUST 0x000 -#define WM8766_FMT_LJUST 0x001 -#define WM8766_FMT_I2S 0x002 -#define WM8766_FMT_DSP 0x003 -#define WM8766_LRP 0x004 -#define WM8766_BCP 0x008 -#define WM8766_IWL_MASK 0x030 -#define WM8766_IWL_16 0x000 -#define WM8766_IWL_20 0x010 -#define WM8766_IWL_24 0x020 -#define WM8766_IWL_32 0x030 -#define WM8766_PHASE_MASK 0x1c0 -/* DAC_CTRL2 */ -#define WM8766_ZCD 0x001 -#define WM8766_DZFM_MASK 0x006 -#define WM8766_DMUTE_MASK 0x038 -#define WM8766_DEEMP_MASK 0x1c0 -/* DAC_CTRL3 */ -#define WM8766_DACPD_MASK 0x00e -#define WM8766_PWRDNALL 0x010 -#define WM8766_MS 0x020 -#define WM8766_RATE_MASK 0x1c0 -#define WM8766_RATE_128 0x000 -#define WM8766_RATE_192 0x040 -#define WM8766_RATE_256 0x080 -#define WM8766_RATE_384 0x0c0 -#define WM8766_RATE_512 0x100 -#define WM8766_RATE_768 0x140 -/* MUTE1 */ -#define WM8766_MPD1 0x040 -/* MUTE2 */ -#define WM8766_MPD2 0x020 - -#endif diff --git a/ANDROID_3.4.5/sound/pci/oxygen/wm8776.h b/ANDROID_3.4.5/sound/pci/oxygen/wm8776.h deleted file mode 100644 index 1a96f561..00000000 --- a/ANDROID_3.4.5/sound/pci/oxygen/wm8776.h +++ /dev/null @@ -1,177 +0,0 @@ -#ifndef WM8776_H_INCLUDED -#define WM8776_H_INCLUDED - -/* - * the following register names are from: - * wm8776.h -- WM8776 ASoC driver - * - * Copyright 2009 Wolfson Microelectronics plc - * - * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#define WM8776_HPLVOL 0x00 -#define WM8776_HPRVOL 0x01 -#define WM8776_HPMASTER 0x02 -#define WM8776_DACLVOL 0x03 -#define WM8776_DACRVOL 0x04 -#define WM8776_DACMASTER 0x05 -#define WM8776_PHASESWAP 0x06 -#define WM8776_DACCTRL1 0x07 -#define WM8776_DACMUTE 0x08 -#define WM8776_DACCTRL2 0x09 -#define WM8776_DACIFCTRL 0x0a -#define WM8776_ADCIFCTRL 0x0b -#define WM8776_MSTRCTRL 0x0c -#define WM8776_PWRDOWN 0x0d -#define WM8776_ADCLVOL 0x0e -#define WM8776_ADCRVOL 0x0f -#define WM8776_ALCCTRL1 0x10 -#define WM8776_ALCCTRL2 0x11 -#define WM8776_ALCCTRL3 0x12 -#define WM8776_NOISEGATE 0x13 -#define WM8776_LIMITER 0x14 -#define WM8776_ADCMUX 0x15 -#define WM8776_OUTMUX 0x16 -#define WM8776_RESET 0x17 - - -/* HPLVOL/HPRVOL/HPMASTER */ -#define WM8776_HPATT_MASK 0x07f -#define WM8776_HPZCEN 0x080 -#define WM8776_UPDATE 0x100 - -/* DACLVOL/DACRVOL/DACMASTER */ -#define WM8776_DATT_MASK 0x0ff -/*#define WM8776_UPDATE 0x100*/ - -/* PHASESWAP */ -#define WM8776_PH_MASK 0x003 - -/* DACCTRL1 */ -#define WM8776_DZCEN 0x001 -#define WM8776_ATC 0x002 -#define WM8776_IZD 0x004 -#define WM8776_TOD 0x008 -#define WM8776_PL_LEFT_MASK 0x030 -#define WM8776_PL_LEFT_MUTE 0x000 -#define WM8776_PL_LEFT_LEFT 0x010 -#define WM8776_PL_LEFT_RIGHT 0x020 -#define WM8776_PL_LEFT_LRMIX 0x030 -#define WM8776_PL_RIGHT_MASK 0x0c0 -#define WM8776_PL_RIGHT_MUTE 0x000 -#define WM8776_PL_RIGHT_LEFT 0x040 -#define WM8776_PL_RIGHT_RIGHT 0x080 -#define WM8776_PL_RIGHT_LRMIX 0x0c0 - -/* DACMUTE */ -#define WM8776_DMUTE 0x001 - -/* DACCTRL2 */ -#define WM8776_DEEMPH 0x001 -#define WM8776_DZFM_MASK 0x006 -#define WM8776_DZFM_NONE 0x000 -#define WM8776_DZFM_LR 0x002 -#define WM8776_DZFM_BOTH 0x004 -#define WM8776_DZFM_EITHER 0x006 - -/* DACIFCTRL */ -#define WM8776_DACFMT_MASK 0x003 -#define WM8776_DACFMT_RJUST 0x000 -#define WM8776_DACFMT_LJUST 0x001 -#define WM8776_DACFMT_I2S 0x002 -#define WM8776_DACFMT_DSP 0x003 -#define WM8776_DACLRP 0x004 -#define WM8776_DACBCP 0x008 -#define WM8776_DACWL_MASK 0x030 -#define WM8776_DACWL_16 0x000 -#define WM8776_DACWL_20 0x010 -#define WM8776_DACWL_24 0x020 -#define WM8776_DACWL_32 0x030 - -/* ADCIFCTRL */ -#define WM8776_ADCFMT_MASK 0x003 -#define WM8776_ADCFMT_RJUST 0x000 -#define WM8776_ADCFMT_LJUST 0x001 -#define WM8776_ADCFMT_I2S 0x002 -#define WM8776_ADCFMT_DSP 0x003 -#define WM8776_ADCLRP 0x004 -#define WM8776_ADCBCP 0x008 -#define WM8776_ADCWL_MASK 0x030 -#define WM8776_ADCWL_16 0x000 -#define WM8776_ADCWL_20 0x010 -#define WM8776_ADCWL_24 0x020 -#define WM8776_ADCWL_32 0x030 -#define WM8776_ADCMCLK 0x040 -#define WM8776_ADCHPD 0x100 - -/* MSTRCTRL */ -#define WM8776_ADCRATE_MASK 0x007 -#define WM8776_ADCRATE_256 0x002 -#define WM8776_ADCRATE_384 0x003 -#define WM8776_ADCRATE_512 0x004 -#define WM8776_ADCRATE_768 0x005 -#define WM8776_ADCOSR 0x008 -#define WM8776_DACRATE_MASK 0x070 -#define WM8776_DACRATE_128 0x000 -#define WM8776_DACRATE_192 0x010 -#define WM8776_DACRATE_256 0x020 -#define WM8776_DACRATE_384 0x030 -#define WM8776_DACRATE_512 0x040 -#define WM8776_DACRATE_768 0x050 -#define WM8776_DACMS 0x080 -#define WM8776_ADCMS 0x100 - -/* PWRDOWN */ -#define WM8776_PDWN 0x001 -#define WM8776_ADCPD 0x002 -#define WM8776_DACPD 0x004 -#define WM8776_HPPD 0x008 -#define WM8776_AINPD 0x040 - -/* ADCLVOL/ADCRVOL */ -#define WM8776_AGMASK 0x0ff -#define WM8776_ZCA 0x100 - -/* ALCCTRL1 */ -#define WM8776_LCT_MASK 0x00f -#define WM8776_MAXGAIN_MASK 0x070 -#define WM8776_LCSEL_MASK 0x180 -#define WM8776_LCSEL_LIMITER 0x000 -#define WM8776_LCSEL_ALC_RIGHT 0x080 -#define WM8776_LCSEL_ALC_LEFT 0x100 -#define WM8776_LCSEL_ALC_STEREO 0x180 - -/* ALCCTRL2 */ -#define WM8776_HLD_MASK 0x00f -#define WM8776_ALCZC 0x080 -#define WM8776_LCEN 0x100 - -/* ALCCTRL3 */ -#define WM8776_ATK_MASK 0x00f -#define WM8776_DCY_MASK 0x0f0 - -/* NOISEGATE */ -#define WM8776_NGAT 0x001 -#define WM8776_NGTH_MASK 0x01c - -/* LIMITER */ -#define WM8776_MAXATTEN_MASK 0x00f -#define WM8776_TRANWIN_MASK 0x070 - -/* ADCMUX */ -#define WM8776_AMX_MASK 0x01f -#define WM8776_MUTERA 0x040 -#define WM8776_MUTELA 0x080 -#define WM8776_LRBOTH 0x100 - -/* OUTMUX */ -#define WM8776_MX_DAC 0x001 -#define WM8776_MX_AUX 0x002 -#define WM8776_MX_BYPASS 0x004 - -#endif diff --git a/ANDROID_3.4.5/sound/pci/oxygen/wm8785.h b/ANDROID_3.4.5/sound/pci/oxygen/wm8785.h deleted file mode 100644 index 8c23e315..00000000 --- a/ANDROID_3.4.5/sound/pci/oxygen/wm8785.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef WM8785_H_INCLUDED -#define WM8785_H_INCLUDED - -#define WM8785_R0 0 -#define WM8785_R1 1 -#define WM8785_R2 2 -#define WM8785_R7 7 - -/* R0 */ -#define WM8785_MCR_MASK 0x007 -#define WM8785_MCR_SLAVE 0x000 -#define WM8785_MCR_MASTER_128 0x001 -#define WM8785_MCR_MASTER_192 0x002 -#define WM8785_MCR_MASTER_256 0x003 -#define WM8785_MCR_MASTER_384 0x004 -#define WM8785_MCR_MASTER_512 0x005 -#define WM8785_MCR_MASTER_768 0x006 -#define WM8785_OSR_MASK 0x018 -#define WM8785_OSR_SINGLE 0x000 -#define WM8785_OSR_DOUBLE 0x008 -#define WM8785_OSR_QUAD 0x010 -#define WM8785_FORMAT_MASK 0x060 -#define WM8785_FORMAT_RJUST 0x000 -#define WM8785_FORMAT_LJUST 0x020 -#define WM8785_FORMAT_I2S 0x040 -#define WM8785_FORMAT_DSP 0x060 -/* R1 */ -#define WM8785_WL_MASK 0x003 -#define WM8785_WL_16 0x000 -#define WM8785_WL_20 0x001 -#define WM8785_WL_24 0x002 -#define WM8785_WL_32 0x003 -#define WM8785_LRP 0x004 -#define WM8785_BCLKINV 0x008 -#define WM8785_LRSWAP 0x010 -#define WM8785_DEVNO_MASK 0x0e0 -/* R2 */ -#define WM8785_HPFR 0x001 -#define WM8785_HPFL 0x002 -#define WM8785_SDODIS 0x004 -#define WM8785_PWRDNR 0x008 -#define WM8785_PWRDNL 0x010 -#define WM8785_TDM_MASK 0x1c0 - -#endif diff --git a/ANDROID_3.4.5/sound/pci/oxygen/xonar.h b/ANDROID_3.4.5/sound/pci/oxygen/xonar.h deleted file mode 100644 index 0434c207..00000000 --- a/ANDROID_3.4.5/sound/pci/oxygen/xonar.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef XONAR_H_INCLUDED -#define XONAR_H_INCLUDED - -#include "oxygen.h" - -struct xonar_generic { - unsigned int anti_pop_delay; - u16 output_enable_bit; - u8 ext_power_reg; - u8 ext_power_int_reg; - u8 ext_power_bit; - u8 has_power; -}; - -struct xonar_hdmi { - u8 params[5]; -}; - -/* generic helper functions */ - -void xonar_enable_output(struct oxygen *chip); -void xonar_disable_output(struct oxygen *chip); -void xonar_init_ext_power(struct oxygen *chip); -void xonar_init_cs53x1(struct oxygen *chip); -void xonar_set_cs53x1_params(struct oxygen *chip, - struct snd_pcm_hw_params *params); - -#define XONAR_GPIO_BIT_INVERT (1 << 16) -int xonar_gpio_bit_switch_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value); -int xonar_gpio_bit_switch_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value); - -/* model-specific card drivers */ - -int get_xonar_pcm179x_model(struct oxygen *chip, - const struct pci_device_id *id); -int get_xonar_cs43xx_model(struct oxygen *chip, - const struct pci_device_id *id); -int get_xonar_wm87x6_model(struct oxygen *chip, - const struct pci_device_id *id); - -/* HDMI helper functions */ - -void xonar_hdmi_init(struct oxygen *chip, struct xonar_hdmi *data); -void xonar_hdmi_cleanup(struct oxygen *chip); -void xonar_hdmi_resume(struct oxygen *chip, struct xonar_hdmi *hdmi); -void xonar_hdmi_pcm_hardware_filter(unsigned int channel, - struct snd_pcm_hardware *hardware); -void xonar_set_hdmi_params(struct oxygen *chip, struct xonar_hdmi *hdmi, - struct snd_pcm_hw_params *params); -void xonar_hdmi_uart_input(struct oxygen *chip); - -#endif diff --git a/ANDROID_3.4.5/sound/pci/oxygen/xonar_cs43xx.c b/ANDROID_3.4.5/sound/pci/oxygen/xonar_cs43xx.c deleted file mode 100644 index c8febf4b..00000000 --- a/ANDROID_3.4.5/sound/pci/oxygen/xonar_cs43xx.c +++ /dev/null @@ -1,452 +0,0 @@ -/* - * card driver for models with CS4398/CS4362A DACs (Xonar D1/DX) - * - * 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 D1/DX - * ----------- - * - * CMI8788: - * - * I²C <-> CS4398 (addr 1001111) (front) - * <-> CS4362A (addr 0011000) (surround, center/LFE, back) - * - * GPI 0 <- external power present (DX only) - * - * GPIO 0 -> enable output to speakers - * GPIO 1 -> route output to front panel - * GPIO 2 -> M0 of CS5361 - * GPIO 3 -> M1 of CS5361 - * GPIO 6 -> ? - * GPIO 7 -> ? - * GPIO 8 -> route input jack to line-in (0) or mic-in (1) - * - * CM9780: - * - * LINE_OUT -> input of ADC - * - * AUX_IN <- aux - * MIC_IN <- mic - * FMIC_IN <- front mic - * - * GPO 0 -> route line-in (0) or AC97 output (1) to CS5361 input - */ - -#include <linux/pci.h> -#include <linux/delay.h> -#include <sound/ac97_codec.h> -#include <sound/control.h> -#include <sound/core.h> -#include <sound/pcm.h> -#include <sound/pcm_params.h> -#include <sound/tlv.h> -#include "xonar.h" -#include "cm9780.h" -#include "cs4398.h" -#include "cs4362a.h" - -#define GPI_EXT_POWER 0x01 -#define GPIO_D1_OUTPUT_ENABLE 0x0001 -#define GPIO_D1_FRONT_PANEL 0x0002 -#define GPIO_D1_MAGIC 0x00c0 -#define GPIO_D1_INPUT_ROUTE 0x0100 - -#define I2C_DEVICE_CS4398 0x9e /* 10011, AD1=1, AD0=1, /W=0 */ -#define I2C_DEVICE_CS4362A 0x30 /* 001100, AD0=0, /W=0 */ - -struct xonar_cs43xx { - struct xonar_generic generic; - u8 cs4398_regs[8]; - u8 cs4362a_regs[15]; -}; - -static void cs4398_write(struct oxygen *chip, u8 reg, u8 value) -{ - struct xonar_cs43xx *data = chip->model_data; - - oxygen_write_i2c(chip, I2C_DEVICE_CS4398, reg, value); - if (reg < ARRAY_SIZE(data->cs4398_regs)) - data->cs4398_regs[reg] = value; -} - -static void cs4398_write_cached(struct oxygen *chip, u8 reg, u8 value) -{ - struct xonar_cs43xx *data = chip->model_data; - - if (value != data->cs4398_regs[reg]) - cs4398_write(chip, reg, value); -} - -static void cs4362a_write(struct oxygen *chip, u8 reg, u8 value) -{ - struct xonar_cs43xx *data = chip->model_data; - - oxygen_write_i2c(chip, I2C_DEVICE_CS4362A, reg, value); - if (reg < ARRAY_SIZE(data->cs4362a_regs)) - data->cs4362a_regs[reg] = value; -} - -static void cs4362a_write_cached(struct oxygen *chip, u8 reg, u8 value) -{ - struct xonar_cs43xx *data = chip->model_data; - - if (value != data->cs4362a_regs[reg]) - cs4362a_write(chip, reg, value); -} - -static void cs43xx_registers_init(struct oxygen *chip) -{ - struct xonar_cs43xx *data = chip->model_data; - unsigned int i; - - /* set CPEN (control port mode) and power down */ - cs4398_write(chip, 8, CS4398_CPEN | CS4398_PDN); - cs4362a_write(chip, 0x01, CS4362A_PDN | CS4362A_CPEN); - /* configure */ - cs4398_write(chip, 2, data->cs4398_regs[2]); - cs4398_write(chip, 3, CS4398_ATAPI_B_R | CS4398_ATAPI_A_L); - cs4398_write(chip, 4, data->cs4398_regs[4]); - cs4398_write(chip, 5, data->cs4398_regs[5]); - cs4398_write(chip, 6, data->cs4398_regs[6]); - cs4398_write(chip, 7, data->cs4398_regs[7]); - cs4362a_write(chip, 0x02, CS4362A_DIF_LJUST); - cs4362a_write(chip, 0x03, CS4362A_MUTEC_6 | CS4362A_AMUTE | - CS4362A_RMP_UP | CS4362A_ZERO_CROSS | CS4362A_SOFT_RAMP); - cs4362a_write(chip, 0x04, data->cs4362a_regs[0x04]); - cs4362a_write(chip, 0x05, 0); - for (i = 6; i <= 14; ++i) - cs4362a_write(chip, i, data->cs4362a_regs[i]); - /* clear power down */ - cs4398_write(chip, 8, CS4398_CPEN); - cs4362a_write(chip, 0x01, CS4362A_CPEN); -} - -static void xonar_d1_init(struct oxygen *chip) -{ - struct xonar_cs43xx *data = chip->model_data; - - data->generic.anti_pop_delay = 800; - data->generic.output_enable_bit = GPIO_D1_OUTPUT_ENABLE; - data->cs4398_regs[2] = - CS4398_FM_SINGLE | CS4398_DEM_NONE | CS4398_DIF_LJUST; - data->cs4398_regs[4] = CS4398_MUTEP_LOW | - CS4398_MUTE_B | CS4398_MUTE_A | CS4398_PAMUTE; - data->cs4398_regs[5] = 60 * 2; - data->cs4398_regs[6] = 60 * 2; - data->cs4398_regs[7] = CS4398_RMP_DN | CS4398_RMP_UP | - CS4398_ZERO_CROSS | CS4398_SOFT_RAMP; - data->cs4362a_regs[4] = CS4362A_RMP_DN | CS4362A_DEM_NONE; - data->cs4362a_regs[6] = CS4362A_FM_SINGLE | - CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L; - data->cs4362a_regs[7] = 60 | CS4362A_MUTE; - data->cs4362a_regs[8] = 60 | CS4362A_MUTE; - data->cs4362a_regs[9] = data->cs4362a_regs[6]; - data->cs4362a_regs[10] = 60 | CS4362A_MUTE; - data->cs4362a_regs[11] = 60 | CS4362A_MUTE; - data->cs4362a_regs[12] = data->cs4362a_regs[6]; - data->cs4362a_regs[13] = 60 | CS4362A_MUTE; - data->cs4362a_regs[14] = 60 | CS4362A_MUTE; - - oxygen_write16(chip, OXYGEN_2WIRE_BUS_STATUS, - OXYGEN_2WIRE_LENGTH_8 | - OXYGEN_2WIRE_INTERRUPT_MASK | - OXYGEN_2WIRE_SPEED_FAST); - - cs43xx_registers_init(chip); - - oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, - GPIO_D1_FRONT_PANEL | - GPIO_D1_MAGIC | - GPIO_D1_INPUT_ROUTE); - oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, - GPIO_D1_FRONT_PANEL | GPIO_D1_INPUT_ROUTE); - - xonar_init_cs53x1(chip); - xonar_enable_output(chip); - - snd_component_add(chip->card, "CS4398"); - snd_component_add(chip->card, "CS4362A"); - snd_component_add(chip->card, "CS5361"); -} - -static void xonar_dx_init(struct oxygen *chip) -{ - struct xonar_cs43xx *data = chip->model_data; - - data->generic.ext_power_reg = OXYGEN_GPI_DATA; - data->generic.ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK; - data->generic.ext_power_bit = GPI_EXT_POWER; - xonar_init_ext_power(chip); - xonar_d1_init(chip); -} - -static void xonar_d1_cleanup(struct oxygen *chip) -{ - xonar_disable_output(chip); - cs4362a_write(chip, 0x01, CS4362A_PDN | CS4362A_CPEN); - oxygen_clear_bits8(chip, OXYGEN_FUNCTION, OXYGEN_FUNCTION_RESET_CODEC); -} - -static void xonar_d1_suspend(struct oxygen *chip) -{ - xonar_d1_cleanup(chip); -} - -static void xonar_d1_resume(struct oxygen *chip) -{ - oxygen_set_bits8(chip, OXYGEN_FUNCTION, OXYGEN_FUNCTION_RESET_CODEC); - msleep(1); - cs43xx_registers_init(chip); - xonar_enable_output(chip); -} - -static void set_cs43xx_params(struct oxygen *chip, - struct snd_pcm_hw_params *params) -{ - struct xonar_cs43xx *data = chip->model_data; - u8 cs4398_fm, cs4362a_fm; - - if (params_rate(params) <= 50000) { - cs4398_fm = CS4398_FM_SINGLE; - cs4362a_fm = CS4362A_FM_SINGLE; - } else if (params_rate(params) <= 100000) { - cs4398_fm = CS4398_FM_DOUBLE; - cs4362a_fm = CS4362A_FM_DOUBLE; - } else { - cs4398_fm = CS4398_FM_QUAD; - cs4362a_fm = CS4362A_FM_QUAD; - } - cs4398_fm |= CS4398_DEM_NONE | CS4398_DIF_LJUST; - cs4398_write_cached(chip, 2, cs4398_fm); - cs4362a_fm |= data->cs4362a_regs[6] & ~CS4362A_FM_MASK; - cs4362a_write_cached(chip, 6, cs4362a_fm); - cs4362a_write_cached(chip, 12, cs4362a_fm); - cs4362a_fm &= CS4362A_FM_MASK; - cs4362a_fm |= data->cs4362a_regs[9] & ~CS4362A_FM_MASK; - cs4362a_write_cached(chip, 9, cs4362a_fm); -} - -static void update_cs4362a_volumes(struct oxygen *chip) -{ - unsigned int i; - u8 mute; - - mute = chip->dac_mute ? CS4362A_MUTE : 0; - for (i = 0; i < 6; ++i) - cs4362a_write_cached(chip, 7 + i + i / 2, - (127 - chip->dac_volume[2 + i]) | mute); -} - -static void update_cs43xx_volume(struct oxygen *chip) -{ - cs4398_write_cached(chip, 5, (127 - chip->dac_volume[0]) * 2); - cs4398_write_cached(chip, 6, (127 - chip->dac_volume[1]) * 2); - update_cs4362a_volumes(chip); -} - -static void update_cs43xx_mute(struct oxygen *chip) -{ - u8 reg; - - reg = CS4398_MUTEP_LOW | CS4398_PAMUTE; - if (chip->dac_mute) - reg |= CS4398_MUTE_B | CS4398_MUTE_A; - cs4398_write_cached(chip, 4, reg); - update_cs4362a_volumes(chip); -} - -static void update_cs43xx_center_lfe_mix(struct oxygen *chip, bool mixed) -{ - struct xonar_cs43xx *data = chip->model_data; - u8 reg; - - reg = data->cs4362a_regs[9] & ~CS4362A_ATAPI_MASK; - if (mixed) - reg |= CS4362A_ATAPI_B_LR | CS4362A_ATAPI_A_LR; - else - reg |= CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L; - cs4362a_write_cached(chip, 9, reg); -} - -static const struct snd_kcontrol_new front_panel_switch = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Front Panel Playback Switch", - .info = snd_ctl_boolean_mono_info, - .get = xonar_gpio_bit_switch_get, - .put = xonar_gpio_bit_switch_put, - .private_value = GPIO_D1_FRONT_PANEL, -}; - -static int rolloff_info(struct snd_kcontrol *ctl, - struct snd_ctl_elem_info *info) -{ - static const char *const names[2] = { - "Fast Roll-off", "Slow Roll-off" - }; - - return snd_ctl_enum_info(info, 1, 2, names); -} - -static int rolloff_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - struct xonar_cs43xx *data = chip->model_data; - - value->value.enumerated.item[0] = - (data->cs4398_regs[7] & CS4398_FILT_SEL) != 0; - return 0; -} - -static int rolloff_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - struct xonar_cs43xx *data = chip->model_data; - int changed; - u8 reg; - - mutex_lock(&chip->mutex); - reg = data->cs4398_regs[7]; - if (value->value.enumerated.item[0]) - reg |= CS4398_FILT_SEL; - else - reg &= ~CS4398_FILT_SEL; - changed = reg != data->cs4398_regs[7]; - if (changed) { - cs4398_write(chip, 7, reg); - if (reg & CS4398_FILT_SEL) - reg = data->cs4362a_regs[0x04] | CS4362A_FILT_SEL; - else - reg = data->cs4362a_regs[0x04] & ~CS4362A_FILT_SEL; - cs4362a_write(chip, 0x04, reg); - } - mutex_unlock(&chip->mutex); - return changed; -} - -static const struct snd_kcontrol_new rolloff_control = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "DAC Filter Playback Enum", - .info = rolloff_info, - .get = rolloff_get, - .put = rolloff_put, -}; - -static void xonar_d1_line_mic_ac97_switch(struct oxygen *chip, - unsigned int reg, unsigned int mute) -{ - if (reg == AC97_LINE) { - spin_lock_irq(&chip->reg_lock); - oxygen_write16_masked(chip, OXYGEN_GPIO_DATA, - mute ? GPIO_D1_INPUT_ROUTE : 0, - GPIO_D1_INPUT_ROUTE); - spin_unlock_irq(&chip->reg_lock); - } -} - -static const DECLARE_TLV_DB_SCALE(cs4362a_db_scale, -6000, 100, 0); - -static int xonar_d1_mixer_init(struct oxygen *chip) -{ - int err; - - err = snd_ctl_add(chip->card, snd_ctl_new1(&front_panel_switch, chip)); - if (err < 0) - return err; - err = snd_ctl_add(chip->card, snd_ctl_new1(&rolloff_control, chip)); - if (err < 0) - return err; - return 0; -} - -static void dump_cs4362a_registers(struct xonar_cs43xx *data, - struct snd_info_buffer *buffer) -{ - unsigned int i; - - snd_iprintf(buffer, "\nCS4362A:"); - for (i = 1; i <= 14; ++i) - snd_iprintf(buffer, " %02x", data->cs4362a_regs[i]); - snd_iprintf(buffer, "\n"); -} - -static void dump_d1_registers(struct oxygen *chip, - struct snd_info_buffer *buffer) -{ - struct xonar_cs43xx *data = chip->model_data; - unsigned int i; - - snd_iprintf(buffer, "\nCS4398: 7?"); - for (i = 2; i < 8; ++i) - snd_iprintf(buffer, " %02x", data->cs4398_regs[i]); - snd_iprintf(buffer, "\n"); - dump_cs4362a_registers(data, buffer); -} - -static const struct oxygen_model model_xonar_d1 = { - .longname = "Asus Virtuoso 100", - .chip = "AV200", - .init = xonar_d1_init, - .mixer_init = xonar_d1_mixer_init, - .cleanup = xonar_d1_cleanup, - .suspend = xonar_d1_suspend, - .resume = xonar_d1_resume, - .set_dac_params = set_cs43xx_params, - .set_adc_params = xonar_set_cs53x1_params, - .update_dac_volume = update_cs43xx_volume, - .update_dac_mute = update_cs43xx_mute, - .update_center_lfe_mix = update_cs43xx_center_lfe_mix, - .ac97_switch = xonar_d1_line_mic_ac97_switch, - .dump_registers = dump_d1_registers, - .dac_tlv = cs4362a_db_scale, - .model_data_size = sizeof(struct xonar_cs43xx), - .device_config = PLAYBACK_0_TO_I2S | - PLAYBACK_1_TO_SPDIF | - CAPTURE_0_FROM_I2S_2 | - CAPTURE_1_FROM_SPDIF | - AC97_FMIC_SWITCH, - .dac_channels_pcm = 8, - .dac_channels_mixer = 8, - .dac_volume_min = 127 - 60, - .dac_volume_max = 127, - .function_flags = OXYGEN_FUNCTION_2WIRE, - .dac_mclks = OXYGEN_MCLKS(256, 128, 128), - .adc_mclks = OXYGEN_MCLKS(256, 128, 128), - .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST, - .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, -}; - -int __devinit get_xonar_cs43xx_model(struct oxygen *chip, - const struct pci_device_id *id) -{ - switch (id->subdevice) { - case 0x834f: - chip->model = model_xonar_d1; - chip->model.shortname = "Xonar D1"; - break; - case 0x8275: - case 0x8327: - chip->model = model_xonar_d1; - chip->model.shortname = "Xonar DX"; - chip->model.init = xonar_dx_init; - break; - default: - return -EINVAL; - } - return 0; -} diff --git a/ANDROID_3.4.5/sound/pci/oxygen/xonar_dg.c b/ANDROID_3.4.5/sound/pci/oxygen/xonar_dg.c deleted file mode 100644 index 793bdf03..00000000 --- a/ANDROID_3.4.5/sound/pci/oxygen/xonar_dg.c +++ /dev/null @@ -1,609 +0,0 @@ -/* - * card driver for the Xonar DG - * - * 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 DG - * -------- - * - * CMI8788: - * - * SPI 0 -> CS4245 - * - * I²S 1 -> CS4245 - * I²S 2 -> CS4361 (center/LFE) - * I²S 3 -> CS4361 (surround) - * I²S 4 -> CS4361 (front) - * - * GPIO 3 <- ? - * GPIO 4 <- headphone detect - * GPIO 5 -> route input jack to line-in (0) or mic-in (1) - * GPIO 6 -> route input jack to line-in (0) or mic-in (1) - * GPIO 7 -> enable rear headphone amp - * GPIO 8 -> enable output to speakers - * - * CS4245: - * - * input 1 <- aux - * input 2 <- front mic - * input 4 <- line/mic - * DAC out -> headphones - * aux out -> front panel headphones - */ - -#include <linux/pci.h> -#include <linux/delay.h> -#include <sound/control.h> -#include <sound/core.h> -#include <sound/info.h> -#include <sound/pcm.h> -#include <sound/tlv.h> -#include "oxygen.h" -#include "xonar_dg.h" -#include "cs4245.h" - -#define GPIO_MAGIC 0x0008 -#define GPIO_HP_DETECT 0x0010 -#define GPIO_INPUT_ROUTE 0x0060 -#define GPIO_HP_REAR 0x0080 -#define GPIO_OUTPUT_ENABLE 0x0100 - -struct dg { - unsigned int output_sel; - s8 input_vol[4][2]; - unsigned int input_sel; - u8 hp_vol_att; - u8 cs4245_regs[0x11]; -}; - -static void cs4245_write(struct oxygen *chip, unsigned int reg, u8 value) -{ - struct dg *data = chip->model_data; - - oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER | - OXYGEN_SPI_DATA_LENGTH_3 | - OXYGEN_SPI_CLOCK_1280 | - (0 << OXYGEN_SPI_CODEC_SHIFT) | - OXYGEN_SPI_CEN_LATCH_CLOCK_HI, - CS4245_SPI_ADDRESS | - CS4245_SPI_WRITE | - (reg << 8) | value); - data->cs4245_regs[reg] = value; -} - -static void cs4245_write_cached(struct oxygen *chip, unsigned int reg, u8 value) -{ - struct dg *data = chip->model_data; - - if (value != data->cs4245_regs[reg]) - cs4245_write(chip, reg, value); -} - -static void cs4245_registers_init(struct oxygen *chip) -{ - struct dg *data = chip->model_data; - - cs4245_write(chip, CS4245_POWER_CTRL, CS4245_PDN); - cs4245_write(chip, CS4245_DAC_CTRL_1, - data->cs4245_regs[CS4245_DAC_CTRL_1]); - cs4245_write(chip, CS4245_ADC_CTRL, - data->cs4245_regs[CS4245_ADC_CTRL]); - cs4245_write(chip, CS4245_SIGNAL_SEL, - data->cs4245_regs[CS4245_SIGNAL_SEL]); - cs4245_write(chip, CS4245_PGA_B_CTRL, - data->cs4245_regs[CS4245_PGA_B_CTRL]); - cs4245_write(chip, CS4245_PGA_A_CTRL, - data->cs4245_regs[CS4245_PGA_A_CTRL]); - cs4245_write(chip, CS4245_ANALOG_IN, - data->cs4245_regs[CS4245_ANALOG_IN]); - cs4245_write(chip, CS4245_DAC_A_CTRL, - data->cs4245_regs[CS4245_DAC_A_CTRL]); - cs4245_write(chip, CS4245_DAC_B_CTRL, - data->cs4245_regs[CS4245_DAC_B_CTRL]); - cs4245_write(chip, CS4245_DAC_CTRL_2, - CS4245_DAC_SOFT | CS4245_DAC_ZERO | CS4245_INVERT_DAC); - cs4245_write(chip, CS4245_INT_MASK, 0); - cs4245_write(chip, CS4245_POWER_CTRL, 0); -} - -static void cs4245_init(struct oxygen *chip) -{ - struct dg *data = chip->model_data; - - data->cs4245_regs[CS4245_DAC_CTRL_1] = - CS4245_DAC_FM_SINGLE | CS4245_DAC_DIF_LJUST; - data->cs4245_regs[CS4245_ADC_CTRL] = - CS4245_ADC_FM_SINGLE | CS4245_ADC_DIF_LJUST; - data->cs4245_regs[CS4245_SIGNAL_SEL] = - CS4245_A_OUT_SEL_HIZ | CS4245_ASYNCH; - data->cs4245_regs[CS4245_PGA_B_CTRL] = 0; - data->cs4245_regs[CS4245_PGA_A_CTRL] = 0; - data->cs4245_regs[CS4245_ANALOG_IN] = - CS4245_PGA_SOFT | CS4245_PGA_ZERO | CS4245_SEL_INPUT_4; - data->cs4245_regs[CS4245_DAC_A_CTRL] = 0; - data->cs4245_regs[CS4245_DAC_B_CTRL] = 0; - cs4245_registers_init(chip); - snd_component_add(chip->card, "CS4245"); -} - -static void dg_output_enable(struct oxygen *chip) -{ - msleep(2500); - oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, GPIO_OUTPUT_ENABLE); -} - -static void dg_init(struct oxygen *chip) -{ - struct dg *data = chip->model_data; - - data->output_sel = 0; - data->input_sel = 3; - data->hp_vol_att = 2 * 16; - - cs4245_init(chip); - - oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL, - GPIO_MAGIC | GPIO_HP_DETECT); - oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, - GPIO_INPUT_ROUTE | GPIO_HP_REAR | GPIO_OUTPUT_ENABLE); - oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, - GPIO_INPUT_ROUTE | GPIO_HP_REAR); - dg_output_enable(chip); -} - -static void dg_cleanup(struct oxygen *chip) -{ - oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, GPIO_OUTPUT_ENABLE); -} - -static void dg_suspend(struct oxygen *chip) -{ - dg_cleanup(chip); -} - -static void dg_resume(struct oxygen *chip) -{ - cs4245_registers_init(chip); - dg_output_enable(chip); -} - -static void set_cs4245_dac_params(struct oxygen *chip, - struct snd_pcm_hw_params *params) -{ - struct dg *data = chip->model_data; - u8 value; - - value = data->cs4245_regs[CS4245_DAC_CTRL_1] & ~CS4245_DAC_FM_MASK; - if (params_rate(params) <= 50000) - value |= CS4245_DAC_FM_SINGLE; - else if (params_rate(params) <= 100000) - value |= CS4245_DAC_FM_DOUBLE; - else - value |= CS4245_DAC_FM_QUAD; - cs4245_write_cached(chip, CS4245_DAC_CTRL_1, value); -} - -static void set_cs4245_adc_params(struct oxygen *chip, - struct snd_pcm_hw_params *params) -{ - struct dg *data = chip->model_data; - u8 value; - - value = data->cs4245_regs[CS4245_ADC_CTRL] & ~CS4245_ADC_FM_MASK; - if (params_rate(params) <= 50000) - value |= CS4245_ADC_FM_SINGLE; - else if (params_rate(params) <= 100000) - value |= CS4245_ADC_FM_DOUBLE; - else - value |= CS4245_ADC_FM_QUAD; - cs4245_write_cached(chip, CS4245_ADC_CTRL, value); -} - -static inline unsigned int shift_bits(unsigned int value, - unsigned int shift_from, - unsigned int shift_to, - unsigned int mask) -{ - if (shift_from < shift_to) - return (value << (shift_to - shift_from)) & mask; - else - return (value >> (shift_from - shift_to)) & mask; -} - -static unsigned int adjust_dg_dac_routing(struct oxygen *chip, - unsigned int play_routing) -{ - return (play_routing & OXYGEN_PLAY_DAC0_SOURCE_MASK) | - shift_bits(play_routing, - OXYGEN_PLAY_DAC2_SOURCE_SHIFT, - OXYGEN_PLAY_DAC1_SOURCE_SHIFT, - OXYGEN_PLAY_DAC1_SOURCE_MASK) | - shift_bits(play_routing, - OXYGEN_PLAY_DAC1_SOURCE_SHIFT, - OXYGEN_PLAY_DAC2_SOURCE_SHIFT, - OXYGEN_PLAY_DAC2_SOURCE_MASK) | - shift_bits(play_routing, - OXYGEN_PLAY_DAC0_SOURCE_SHIFT, - OXYGEN_PLAY_DAC3_SOURCE_SHIFT, - OXYGEN_PLAY_DAC3_SOURCE_MASK); -} - -static int output_switch_info(struct snd_kcontrol *ctl, - struct snd_ctl_elem_info *info) -{ - static const char *const names[3] = { - "Speakers", "Headphones", "FP Headphones" - }; - - return snd_ctl_enum_info(info, 1, 3, names); -} - -static int output_switch_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - struct dg *data = chip->model_data; - - mutex_lock(&chip->mutex); - value->value.enumerated.item[0] = data->output_sel; - mutex_unlock(&chip->mutex); - return 0; -} - -static int output_switch_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - struct dg *data = chip->model_data; - u8 reg; - int changed; - - if (value->value.enumerated.item[0] > 2) - return -EINVAL; - - mutex_lock(&chip->mutex); - changed = value->value.enumerated.item[0] != data->output_sel; - if (changed) { - data->output_sel = value->value.enumerated.item[0]; - - reg = data->cs4245_regs[CS4245_SIGNAL_SEL] & - ~CS4245_A_OUT_SEL_MASK; - reg |= data->output_sel == 2 ? - CS4245_A_OUT_SEL_DAC : CS4245_A_OUT_SEL_HIZ; - cs4245_write_cached(chip, CS4245_SIGNAL_SEL, reg); - - cs4245_write_cached(chip, CS4245_DAC_A_CTRL, - data->output_sel ? data->hp_vol_att : 0); - cs4245_write_cached(chip, CS4245_DAC_B_CTRL, - data->output_sel ? data->hp_vol_att : 0); - - oxygen_write16_masked(chip, OXYGEN_GPIO_DATA, - data->output_sel == 1 ? GPIO_HP_REAR : 0, - GPIO_HP_REAR); - } - mutex_unlock(&chip->mutex); - return changed; -} - -static int hp_volume_offset_info(struct snd_kcontrol *ctl, - struct snd_ctl_elem_info *info) -{ - static const char *const names[3] = { - "< 64 ohms", "64-150 ohms", "150-300 ohms" - }; - - return snd_ctl_enum_info(info, 1, 3, names); -} - -static int hp_volume_offset_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - struct dg *data = chip->model_data; - - mutex_lock(&chip->mutex); - if (data->hp_vol_att > 2 * 7) - value->value.enumerated.item[0] = 0; - else if (data->hp_vol_att > 0) - value->value.enumerated.item[0] = 1; - else - value->value.enumerated.item[0] = 2; - mutex_unlock(&chip->mutex); - return 0; -} - -static int hp_volume_offset_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - static const s8 atts[3] = { 2 * 16, 2 * 7, 0 }; - struct oxygen *chip = ctl->private_data; - struct dg *data = chip->model_data; - s8 att; - int changed; - - if (value->value.enumerated.item[0] > 2) - return -EINVAL; - att = atts[value->value.enumerated.item[0]]; - mutex_lock(&chip->mutex); - changed = att != data->hp_vol_att; - if (changed) { - data->hp_vol_att = att; - if (data->output_sel) { - cs4245_write_cached(chip, CS4245_DAC_A_CTRL, att); - cs4245_write_cached(chip, CS4245_DAC_B_CTRL, att); - } - } - mutex_unlock(&chip->mutex); - return changed; -} - -static int input_vol_info(struct snd_kcontrol *ctl, - struct snd_ctl_elem_info *info) -{ - info->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - info->count = 2; - info->value.integer.min = 2 * -12; - info->value.integer.max = 2 * 12; - return 0; -} - -static int input_vol_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - struct dg *data = chip->model_data; - unsigned int idx = ctl->private_value; - - mutex_lock(&chip->mutex); - value->value.integer.value[0] = data->input_vol[idx][0]; - value->value.integer.value[1] = data->input_vol[idx][1]; - mutex_unlock(&chip->mutex); - return 0; -} - -static int input_vol_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - struct dg *data = chip->model_data; - unsigned int idx = ctl->private_value; - int changed = 0; - - if (value->value.integer.value[0] < 2 * -12 || - value->value.integer.value[0] > 2 * 12 || - value->value.integer.value[1] < 2 * -12 || - value->value.integer.value[1] > 2 * 12) - return -EINVAL; - mutex_lock(&chip->mutex); - changed = data->input_vol[idx][0] != value->value.integer.value[0] || - data->input_vol[idx][1] != value->value.integer.value[1]; - if (changed) { - data->input_vol[idx][0] = value->value.integer.value[0]; - data->input_vol[idx][1] = value->value.integer.value[1]; - if (idx == data->input_sel) { - cs4245_write_cached(chip, CS4245_PGA_A_CTRL, - data->input_vol[idx][0]); - cs4245_write_cached(chip, CS4245_PGA_B_CTRL, - data->input_vol[idx][1]); - } - } - mutex_unlock(&chip->mutex); - return changed; -} - -static DECLARE_TLV_DB_SCALE(cs4245_pga_db_scale, -1200, 50, 0); - -static int input_sel_info(struct snd_kcontrol *ctl, - struct snd_ctl_elem_info *info) -{ - static const char *const names[4] = { - "Mic", "Aux", "Front Mic", "Line" - }; - - return snd_ctl_enum_info(info, 1, 4, names); -} - -static int input_sel_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - struct dg *data = chip->model_data; - - mutex_lock(&chip->mutex); - value->value.enumerated.item[0] = data->input_sel; - mutex_unlock(&chip->mutex); - return 0; -} - -static int input_sel_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - static const u8 sel_values[4] = { - CS4245_SEL_MIC, - CS4245_SEL_INPUT_1, - CS4245_SEL_INPUT_2, - CS4245_SEL_INPUT_4 - }; - struct oxygen *chip = ctl->private_data; - struct dg *data = chip->model_data; - int changed; - - if (value->value.enumerated.item[0] > 3) - return -EINVAL; - - mutex_lock(&chip->mutex); - changed = value->value.enumerated.item[0] != data->input_sel; - if (changed) { - data->input_sel = value->value.enumerated.item[0]; - - cs4245_write(chip, CS4245_ANALOG_IN, - (data->cs4245_regs[CS4245_ANALOG_IN] & - ~CS4245_SEL_MASK) | - sel_values[data->input_sel]); - - cs4245_write_cached(chip, CS4245_PGA_A_CTRL, - data->input_vol[data->input_sel][0]); - cs4245_write_cached(chip, CS4245_PGA_B_CTRL, - data->input_vol[data->input_sel][1]); - - oxygen_write16_masked(chip, OXYGEN_GPIO_DATA, - data->input_sel ? 0 : GPIO_INPUT_ROUTE, - GPIO_INPUT_ROUTE); - } - mutex_unlock(&chip->mutex); - return changed; -} - -static int hpf_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info) -{ - static const char *const names[2] = { "Active", "Frozen" }; - - return snd_ctl_enum_info(info, 1, 2, names); -} - -static int hpf_get(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - struct dg *data = chip->model_data; - - value->value.enumerated.item[0] = - !!(data->cs4245_regs[CS4245_ADC_CTRL] & CS4245_HPF_FREEZE); - return 0; -} - -static int hpf_put(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - struct dg *data = chip->model_data; - u8 reg; - int changed; - - mutex_lock(&chip->mutex); - reg = data->cs4245_regs[CS4245_ADC_CTRL] & ~CS4245_HPF_FREEZE; - if (value->value.enumerated.item[0]) - reg |= CS4245_HPF_FREEZE; - changed = reg != data->cs4245_regs[CS4245_ADC_CTRL]; - if (changed) - cs4245_write(chip, CS4245_ADC_CTRL, reg); - mutex_unlock(&chip->mutex); - return changed; -} - -#define INPUT_VOLUME(xname, index) { \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .info = input_vol_info, \ - .get = input_vol_get, \ - .put = input_vol_put, \ - .tlv = { .p = cs4245_pga_db_scale }, \ - .private_value = index, \ -} -static const struct snd_kcontrol_new dg_controls[] = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Analog Output Playback Enum", - .info = output_switch_info, - .get = output_switch_get, - .put = output_switch_put, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Headphones Impedance Playback Enum", - .info = hp_volume_offset_info, - .get = hp_volume_offset_get, - .put = hp_volume_offset_put, - }, - INPUT_VOLUME("Mic Capture Volume", 0), - INPUT_VOLUME("Aux Capture Volume", 1), - INPUT_VOLUME("Front Mic Capture Volume", 2), - INPUT_VOLUME("Line Capture Volume", 3), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Source", - .info = input_sel_info, - .get = input_sel_get, - .put = input_sel_put, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "ADC High-pass Filter Capture Enum", - .info = hpf_info, - .get = hpf_get, - .put = hpf_put, - }, -}; - -static int dg_control_filter(struct snd_kcontrol_new *template) -{ - if (!strncmp(template->name, "Master Playback ", 16)) - return 1; - return 0; -} - -static int dg_mixer_init(struct oxygen *chip) -{ - unsigned int i; - int err; - - for (i = 0; i < ARRAY_SIZE(dg_controls); ++i) { - err = snd_ctl_add(chip->card, - snd_ctl_new1(&dg_controls[i], chip)); - if (err < 0) - return err; - } - return 0; -} - -static void dump_cs4245_registers(struct oxygen *chip, - struct snd_info_buffer *buffer) -{ - struct dg *data = chip->model_data; - unsigned int i; - - snd_iprintf(buffer, "\nCS4245:"); - for (i = 1; i <= 0x10; ++i) - snd_iprintf(buffer, " %02x", data->cs4245_regs[i]); - snd_iprintf(buffer, "\n"); -} - -struct oxygen_model model_xonar_dg = { - .shortname = "Xonar DG", - .longname = "C-Media Oxygen HD Audio", - .chip = "CMI8786", - .init = dg_init, - .control_filter = dg_control_filter, - .mixer_init = dg_mixer_init, - .cleanup = dg_cleanup, - .suspend = dg_suspend, - .resume = dg_resume, - .set_dac_params = set_cs4245_dac_params, - .set_adc_params = set_cs4245_adc_params, - .adjust_dac_routing = adjust_dg_dac_routing, - .dump_registers = dump_cs4245_registers, - .model_data_size = sizeof(struct dg), - .device_config = PLAYBACK_0_TO_I2S | - PLAYBACK_1_TO_SPDIF | - CAPTURE_0_FROM_I2S_2 | - CAPTURE_1_FROM_SPDIF, - .dac_channels_pcm = 6, - .dac_channels_mixer = 0, - .function_flags = OXYGEN_FUNCTION_SPI, - .dac_mclks = OXYGEN_MCLKS(256, 128, 128), - .adc_mclks = OXYGEN_MCLKS(256, 128, 128), - .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST, - .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, -}; diff --git a/ANDROID_3.4.5/sound/pci/oxygen/xonar_dg.h b/ANDROID_3.4.5/sound/pci/oxygen/xonar_dg.h deleted file mode 100644 index 5688d786..00000000 --- a/ANDROID_3.4.5/sound/pci/oxygen/xonar_dg.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef XONAR_DG_H_INCLUDED -#define XONAR_DG_H_INCLUDED - -#include "oxygen.h" - -extern struct oxygen_model model_xonar_dg; - -#endif diff --git a/ANDROID_3.4.5/sound/pci/oxygen/xonar_hdmi.c b/ANDROID_3.4.5/sound/pci/oxygen/xonar_hdmi.c deleted file mode 100644 index 136dac6a..00000000 --- a/ANDROID_3.4.5/sound/pci/oxygen/xonar_hdmi.c +++ /dev/null @@ -1,128 +0,0 @@ -/* - * helper functions for HDMI models (Xonar HDAV1.3/HDAV1.3 Slim) - * - * 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/>. - */ - -#include <linux/pci.h> -#include <linux/delay.h> -#include <sound/asoundef.h> -#include <sound/control.h> -#include <sound/core.h> -#include <sound/pcm.h> -#include <sound/pcm_params.h> -#include <sound/tlv.h> -#include "xonar.h" - -static void hdmi_write_command(struct oxygen *chip, u8 command, - unsigned int count, const u8 *params) -{ - unsigned int i; - u8 checksum; - - oxygen_write_uart(chip, 0xfb); - oxygen_write_uart(chip, 0xef); - oxygen_write_uart(chip, command); - oxygen_write_uart(chip, count); - for (i = 0; i < count; ++i) - oxygen_write_uart(chip, params[i]); - checksum = 0xfb + 0xef + command + count; - for (i = 0; i < count; ++i) - checksum += params[i]; - oxygen_write_uart(chip, checksum); -} - -static void xonar_hdmi_init_commands(struct oxygen *chip, - struct xonar_hdmi *hdmi) -{ - u8 param; - - oxygen_reset_uart(chip); - param = 0; - hdmi_write_command(chip, 0x61, 1, ¶m); - param = 1; - hdmi_write_command(chip, 0x74, 1, ¶m); - hdmi_write_command(chip, 0x54, 5, hdmi->params); -} - -void xonar_hdmi_init(struct oxygen *chip, struct xonar_hdmi *hdmi) -{ - hdmi->params[1] = IEC958_AES3_CON_FS_48000; - hdmi->params[4] = 1; - xonar_hdmi_init_commands(chip, hdmi); -} - -void xonar_hdmi_cleanup(struct oxygen *chip) -{ - u8 param = 0; - - hdmi_write_command(chip, 0x74, 1, ¶m); -} - -void xonar_hdmi_resume(struct oxygen *chip, struct xonar_hdmi *hdmi) -{ - xonar_hdmi_init_commands(chip, hdmi); -} - -void xonar_hdmi_pcm_hardware_filter(unsigned int channel, - struct snd_pcm_hardware *hardware) -{ - if (channel == PCM_MULTICH) { - hardware->rates = SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_96000 | - SNDRV_PCM_RATE_192000; - hardware->rate_min = 44100; - } -} - -void xonar_set_hdmi_params(struct oxygen *chip, struct xonar_hdmi *hdmi, - struct snd_pcm_hw_params *params) -{ - hdmi->params[0] = 0; /* 1 = non-audio */ - switch (params_rate(params)) { - case 44100: - hdmi->params[1] = IEC958_AES3_CON_FS_44100; - break; - case 48000: - hdmi->params[1] = IEC958_AES3_CON_FS_48000; - break; - default: /* 96000 */ - hdmi->params[1] = IEC958_AES3_CON_FS_96000; - break; - case 192000: - hdmi->params[1] = IEC958_AES3_CON_FS_192000; - break; - } - hdmi->params[2] = params_channels(params) / 2 - 1; - if (params_format(params) == SNDRV_PCM_FORMAT_S16_LE) - hdmi->params[3] = 0; - else - hdmi->params[3] = 0xc0; - hdmi->params[4] = 1; /* ? */ - hdmi_write_command(chip, 0x54, 5, hdmi->params); -} - -void xonar_hdmi_uart_input(struct oxygen *chip) -{ - if (chip->uart_input_count >= 2 && - chip->uart_input[chip->uart_input_count - 2] == 'O' && - chip->uart_input[chip->uart_input_count - 1] == 'K') { - printk(KERN_DEBUG "message from HDMI chip received:\n"); - print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, - chip->uart_input, chip->uart_input_count); - chip->uart_input_count = 0; - } -} diff --git a/ANDROID_3.4.5/sound/pci/oxygen/xonar_lib.c b/ANDROID_3.4.5/sound/pci/oxygen/xonar_lib.c deleted file mode 100644 index 0ebe7f59..00000000 --- a/ANDROID_3.4.5/sound/pci/oxygen/xonar_lib.c +++ /dev/null @@ -1,134 +0,0 @@ -/* - * helper functions for Asus Xonar cards - * - * 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/>. - */ - -#include <linux/delay.h> -#include <sound/core.h> -#include <sound/control.h> -#include <sound/pcm.h> -#include <sound/pcm_params.h> -#include "xonar.h" - - -#define GPIO_CS53x1_M_MASK 0x000c -#define GPIO_CS53x1_M_SINGLE 0x0000 -#define GPIO_CS53x1_M_DOUBLE 0x0004 -#define GPIO_CS53x1_M_QUAD 0x0008 - - -void xonar_enable_output(struct oxygen *chip) -{ - struct xonar_generic *data = chip->model_data; - - oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, data->output_enable_bit); - msleep(data->anti_pop_delay); - oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, data->output_enable_bit); -} - -void xonar_disable_output(struct oxygen *chip) -{ - struct xonar_generic *data = chip->model_data; - - oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, data->output_enable_bit); -} - -static void xonar_ext_power_gpio_changed(struct oxygen *chip) -{ - struct xonar_generic *data = chip->model_data; - u8 has_power; - - has_power = !!(oxygen_read8(chip, data->ext_power_reg) - & data->ext_power_bit); - if (has_power != data->has_power) { - data->has_power = has_power; - if (has_power) { - snd_printk(KERN_NOTICE "power restored\n"); - } else { - snd_printk(KERN_CRIT - "Hey! Don't unplug the power cable!\n"); - /* TODO: stop PCMs */ - } - } -} - -void xonar_init_ext_power(struct oxygen *chip) -{ - struct xonar_generic *data = chip->model_data; - - oxygen_set_bits8(chip, data->ext_power_int_reg, - data->ext_power_bit); - chip->interrupt_mask |= OXYGEN_INT_GPIO; - chip->model.gpio_changed = xonar_ext_power_gpio_changed; - data->has_power = !!(oxygen_read8(chip, data->ext_power_reg) - & data->ext_power_bit); -} - -void xonar_init_cs53x1(struct oxygen *chip) -{ - oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_CS53x1_M_MASK); - oxygen_write16_masked(chip, OXYGEN_GPIO_DATA, - GPIO_CS53x1_M_SINGLE, GPIO_CS53x1_M_MASK); -} - -void xonar_set_cs53x1_params(struct oxygen *chip, - struct snd_pcm_hw_params *params) -{ - unsigned int value; - - if (params_rate(params) <= 54000) - value = GPIO_CS53x1_M_SINGLE; - else if (params_rate(params) <= 108000) - value = GPIO_CS53x1_M_DOUBLE; - else - value = GPIO_CS53x1_M_QUAD; - oxygen_write16_masked(chip, OXYGEN_GPIO_DATA, - value, GPIO_CS53x1_M_MASK); -} - -int xonar_gpio_bit_switch_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - u16 bit = ctl->private_value; - bool invert = ctl->private_value & XONAR_GPIO_BIT_INVERT; - - value->value.integer.value[0] = - !!(oxygen_read16(chip, OXYGEN_GPIO_DATA) & bit) ^ invert; - return 0; -} - -int xonar_gpio_bit_switch_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - u16 bit = ctl->private_value; - bool invert = ctl->private_value & XONAR_GPIO_BIT_INVERT; - u16 old_bits, new_bits; - int changed; - - spin_lock_irq(&chip->reg_lock); - old_bits = oxygen_read16(chip, OXYGEN_GPIO_DATA); - if (!!value->value.integer.value[0] ^ invert) - new_bits = old_bits | bit; - else - new_bits = old_bits & ~bit; - changed = new_bits != old_bits; - if (changed) - oxygen_write16(chip, OXYGEN_GPIO_DATA, new_bits); - spin_unlock_irq(&chip->reg_lock); - return changed; -} diff --git a/ANDROID_3.4.5/sound/pci/oxygen/xonar_pcm179x.c b/ANDROID_3.4.5/sound/pci/oxygen/xonar_pcm179x.c deleted file mode 100644 index 8433aa7c..00000000 --- a/ANDROID_3.4.5/sound/pci/oxygen/xonar_pcm179x.c +++ /dev/null @@ -1,1145 +0,0 @@ -/* - * 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); -} - -static void pcm1796_write(struct oxygen *chip, unsigned int codec, - u8 reg, u8 value) -{ - struct xonar_pcm179x *data = chip->model_data; - - if ((chip->model.function_flags & OXYGEN_FUNCTION_2WIRE_SPI_MASK) == - OXYGEN_FUNCTION_SPI) - pcm1796_write_spi(chip, codec, reg, value); - else - pcm1796_write_i2c(chip, codec, reg, value); - if ((unsigned int)(reg - PCM1796_REG_BASE) - < ARRAY_SIZE(data->pcm1796_regs[codec])) - data->pcm1796_regs[codec][reg - PCM1796_REG_BASE] = value; -} - -static void pcm1796_write_cached(struct oxygen *chip, unsigned int codec, - u8 reg, u8 value) -{ - struct xonar_pcm179x *data = chip->model_data; - - if (value != data->pcm1796_regs[codec][reg - PCM1796_REG_BASE]) - pcm1796_write(chip, codec, reg, value); -} - -static void cs2000_write(struct oxygen *chip, u8 reg, u8 value) -{ - struct xonar_pcm179x *data = chip->model_data; - - oxygen_write_i2c(chip, I2C_DEVICE_CS2000, reg, value); - data->cs2000_regs[reg] = value; -} - -static void cs2000_write_cached(struct oxygen *chip, u8 reg, u8 value) -{ - struct xonar_pcm179x *data = chip->model_data; - - if (value != data->cs2000_regs[reg]) - cs2000_write(chip, reg, value); -} - -static void pcm1796_registers_init(struct oxygen *chip) -{ - struct xonar_pcm179x *data = chip->model_data; - unsigned int i; - s8 gain_offset; - - msleep(1); - gain_offset = data->hp_active ? data->hp_gain_offset : 0; - for (i = 0; i < data->dacs; ++i) { - /* set ATLD before ATL/ATR */ - pcm1796_write(chip, i, 18, - data->pcm1796_regs[0][18 - PCM1796_REG_BASE]); - pcm1796_write(chip, i, 16, chip->dac_volume[i * 2] - + gain_offset); - pcm1796_write(chip, i, 17, chip->dac_volume[i * 2 + 1] - + gain_offset); - pcm1796_write(chip, i, 19, - data->pcm1796_regs[0][19 - PCM1796_REG_BASE]); - pcm1796_write(chip, i, 20, - data->pcm1796_regs[0][20 - PCM1796_REG_BASE]); - pcm1796_write(chip, i, 21, 0); - gain_offset = 0; - } -} - -static void pcm1796_init(struct oxygen *chip) -{ - struct xonar_pcm179x *data = chip->model_data; - - data->pcm1796_regs[0][18 - PCM1796_REG_BASE] = - PCM1796_DMF_DISABLED | PCM1796_FMT_24_I2S | PCM1796_ATLD; - if (!data->broken_i2c) - data->pcm1796_regs[0][18 - PCM1796_REG_BASE] |= PCM1796_MUTE; - data->pcm1796_regs[0][19 - PCM1796_REG_BASE] = - PCM1796_FLT_SHARP | PCM1796_ATS_1; - data->pcm1796_regs[0][20 - PCM1796_REG_BASE] = - data->h6 ? PCM1796_OS_64 : PCM1796_OS_128; - pcm1796_registers_init(chip); - data->current_rate = 48000; -} - -static void xonar_d2_init(struct oxygen *chip) -{ - struct xonar_pcm179x *data = chip->model_data; - - data->generic.anti_pop_delay = 300; - data->generic.output_enable_bit = GPIO_D2_OUTPUT_ENABLE; - data->dacs = 4; - - pcm1796_init(chip); - - oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_D2_ALT); - oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, GPIO_D2_ALT); - - oxygen_ac97_set_bits(chip, 0, CM9780_JACK, CM9780_FMIC2MIC); - - xonar_init_cs53x1(chip); - xonar_enable_output(chip); - - snd_component_add(chip->card, "PCM1796"); - snd_component_add(chip->card, "CS5381"); -} - -static void xonar_d2x_init(struct oxygen *chip) -{ - struct xonar_pcm179x *data = chip->model_data; - - data->generic.ext_power_reg = OXYGEN_GPIO_DATA; - data->generic.ext_power_int_reg = OXYGEN_GPIO_INTERRUPT_MASK; - data->generic.ext_power_bit = GPIO_D2X_EXT_POWER; - oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_D2X_EXT_POWER); - xonar_init_ext_power(chip); - xonar_d2_init(chip); -} - -static void xonar_hdav_init(struct oxygen *chip) -{ - struct xonar_hdav *data = chip->model_data; - - oxygen_write16(chip, OXYGEN_2WIRE_BUS_STATUS, - OXYGEN_2WIRE_LENGTH_8 | - OXYGEN_2WIRE_INTERRUPT_MASK | - OXYGEN_2WIRE_SPEED_STANDARD); - - data->pcm179x.generic.anti_pop_delay = 100; - data->pcm179x.generic.output_enable_bit = GPIO_HDAV_OUTPUT_ENABLE; - data->pcm179x.generic.ext_power_reg = OXYGEN_GPI_DATA; - data->pcm179x.generic.ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK; - data->pcm179x.generic.ext_power_bit = GPI_EXT_POWER; - data->pcm179x.dacs = chip->model.dac_channels_mixer / 2; - data->pcm179x.h6 = chip->model.dac_channels_mixer > 2; - - pcm1796_init(chip); - - oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, - GPIO_HDAV_MAGIC | GPIO_INPUT_ROUTE); - oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, GPIO_INPUT_ROUTE); - - xonar_init_cs53x1(chip); - xonar_init_ext_power(chip); - xonar_hdmi_init(chip, &data->hdmi); - xonar_enable_output(chip); - - snd_component_add(chip->card, "PCM1796"); - snd_component_add(chip->card, "CS5381"); -} - -static void xonar_st_init_i2c(struct oxygen *chip) -{ - oxygen_write16(chip, OXYGEN_2WIRE_BUS_STATUS, - OXYGEN_2WIRE_LENGTH_8 | - OXYGEN_2WIRE_INTERRUPT_MASK | - OXYGEN_2WIRE_SPEED_STANDARD); -} - -static void xonar_st_init_common(struct oxygen *chip) -{ - struct xonar_pcm179x *data = chip->model_data; - - data->generic.output_enable_bit = GPIO_ST_OUTPUT_ENABLE; - data->dacs = chip->model.dac_channels_mixer / 2; - data->hp_gain_offset = 2*-18; - - pcm1796_init(chip); - - oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, - GPIO_INPUT_ROUTE | GPIO_ST_HP_REAR | - GPIO_ST_MAGIC | GPIO_ST_HP); - oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, - GPIO_INPUT_ROUTE | GPIO_ST_HP_REAR | GPIO_ST_HP); - - xonar_init_cs53x1(chip); - xonar_enable_output(chip); - - snd_component_add(chip->card, "PCM1792A"); - snd_component_add(chip->card, "CS5381"); -} - -static void cs2000_registers_init(struct oxygen *chip) -{ - struct xonar_pcm179x *data = chip->model_data; - - cs2000_write(chip, CS2000_GLOBAL_CFG, CS2000_FREEZE); - cs2000_write(chip, CS2000_DEV_CTRL, 0); - cs2000_write(chip, CS2000_DEV_CFG_1, - CS2000_R_MOD_SEL_1 | - (0 << CS2000_R_SEL_SHIFT) | - CS2000_AUX_OUT_SRC_REF_CLK | - CS2000_EN_DEV_CFG_1); - cs2000_write(chip, CS2000_DEV_CFG_2, - (0 << CS2000_LOCK_CLK_SHIFT) | - CS2000_FRAC_N_SRC_STATIC); - cs2000_write(chip, CS2000_RATIO_0 + 0, 0x00); /* 1.0 */ - cs2000_write(chip, CS2000_RATIO_0 + 1, 0x10); - cs2000_write(chip, CS2000_RATIO_0 + 2, 0x00); - cs2000_write(chip, CS2000_RATIO_0 + 3, 0x00); - cs2000_write(chip, CS2000_FUN_CFG_1, - data->cs2000_regs[CS2000_FUN_CFG_1]); - cs2000_write(chip, CS2000_FUN_CFG_2, 0); - cs2000_write(chip, CS2000_GLOBAL_CFG, CS2000_EN_DEV_CFG_2); - msleep(3); /* PLL lock delay */ -} - -static void xonar_st_init(struct oxygen *chip) -{ - struct xonar_pcm179x *data = chip->model_data; - - data->generic.anti_pop_delay = 100; - data->h6 = chip->model.dac_channels_mixer > 2; - data->has_cs2000 = 1; - data->cs2000_regs[CS2000_FUN_CFG_1] = CS2000_REF_CLK_DIV_1; - data->broken_i2c = true; - - oxygen_write16(chip, OXYGEN_I2S_A_FORMAT, - OXYGEN_RATE_48000 | - OXYGEN_I2S_FORMAT_I2S | - OXYGEN_I2S_MCLK(data->h6 ? MCLK_256 : MCLK_512) | - OXYGEN_I2S_BITS_16 | - OXYGEN_I2S_MASTER | - OXYGEN_I2S_BCLK_64); - - xonar_st_init_i2c(chip); - cs2000_registers_init(chip); - xonar_st_init_common(chip); - - snd_component_add(chip->card, "CS2000"); -} - -static void xonar_stx_init(struct oxygen *chip) -{ - struct xonar_pcm179x *data = chip->model_data; - - xonar_st_init_i2c(chip); - data->generic.anti_pop_delay = 800; - data->generic.ext_power_reg = OXYGEN_GPI_DATA; - data->generic.ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK; - data->generic.ext_power_bit = GPI_EXT_POWER; - xonar_init_ext_power(chip); - xonar_st_init_common(chip); -} - -static void xonar_d2_cleanup(struct oxygen *chip) -{ - xonar_disable_output(chip); -} - -static void xonar_hdav_cleanup(struct oxygen *chip) -{ - xonar_hdmi_cleanup(chip); - xonar_disable_output(chip); - msleep(2); -} - -static void xonar_st_cleanup(struct oxygen *chip) -{ - xonar_disable_output(chip); -} - -static void xonar_d2_suspend(struct oxygen *chip) -{ - xonar_d2_cleanup(chip); -} - -static void xonar_hdav_suspend(struct oxygen *chip) -{ - xonar_hdav_cleanup(chip); -} - -static void xonar_st_suspend(struct oxygen *chip) -{ - xonar_st_cleanup(chip); -} - -static void xonar_d2_resume(struct oxygen *chip) -{ - pcm1796_registers_init(chip); - xonar_enable_output(chip); -} - -static void xonar_hdav_resume(struct oxygen *chip) -{ - struct xonar_hdav *data = chip->model_data; - - pcm1796_registers_init(chip); - xonar_hdmi_resume(chip, &data->hdmi); - xonar_enable_output(chip); -} - -static void xonar_stx_resume(struct oxygen *chip) -{ - pcm1796_registers_init(chip); - xonar_enable_output(chip); -} - -static void xonar_st_resume(struct oxygen *chip) -{ - cs2000_registers_init(chip); - xonar_stx_resume(chip); -} - -static void update_pcm1796_oversampling(struct oxygen *chip) -{ - struct xonar_pcm179x *data = chip->model_data; - unsigned int i; - u8 reg; - - if (data->current_rate <= 48000 && !data->h6) - reg = PCM1796_OS_128; - else - reg = PCM1796_OS_64; - for (i = 0; i < data->dacs; ++i) - pcm1796_write_cached(chip, i, 20, reg); -} - -static void set_pcm1796_params(struct oxygen *chip, - struct snd_pcm_hw_params *params) -{ - struct xonar_pcm179x *data = chip->model_data; - - msleep(1); - data->current_rate = params_rate(params); - update_pcm1796_oversampling(chip); -} - -static void update_pcm1796_volume(struct oxygen *chip) -{ - struct xonar_pcm179x *data = chip->model_data; - unsigned int i; - s8 gain_offset; - - gain_offset = data->hp_active ? data->hp_gain_offset : 0; - for (i = 0; i < data->dacs; ++i) { - pcm1796_write_cached(chip, i, 16, chip->dac_volume[i * 2] - + gain_offset); - pcm1796_write_cached(chip, i, 17, chip->dac_volume[i * 2 + 1] - + gain_offset); - gain_offset = 0; - } -} - -static void update_pcm1796_mute(struct oxygen *chip) -{ - struct xonar_pcm179x *data = chip->model_data; - unsigned int i; - u8 value; - - value = PCM1796_DMF_DISABLED | PCM1796_FMT_24_I2S | PCM1796_ATLD; - if (chip->dac_mute) - value |= PCM1796_MUTE; - for (i = 0; i < data->dacs; ++i) - pcm1796_write_cached(chip, i, 18, value); -} - -static void update_cs2000_rate(struct oxygen *chip, unsigned int rate) -{ - struct xonar_pcm179x *data = chip->model_data; - u8 rate_mclk, reg; - - switch (rate) { - case 32000: - case 64000: - rate_mclk = OXYGEN_RATE_32000; - break; - case 44100: - case 88200: - case 176400: - rate_mclk = OXYGEN_RATE_44100; - break; - default: - case 48000: - case 96000: - case 192000: - rate_mclk = OXYGEN_RATE_48000; - break; - } - - if (rate <= 96000 && (rate > 48000 || data->h6)) { - rate_mclk |= OXYGEN_I2S_MCLK(MCLK_256); - reg = CS2000_REF_CLK_DIV_1; - } else { - rate_mclk |= OXYGEN_I2S_MCLK(MCLK_512); - reg = CS2000_REF_CLK_DIV_2; - } - - oxygen_write16_masked(chip, OXYGEN_I2S_A_FORMAT, rate_mclk, - OXYGEN_I2S_RATE_MASK | OXYGEN_I2S_MCLK_MASK); - cs2000_write_cached(chip, CS2000_FUN_CFG_1, reg); - msleep(3); /* PLL lock delay */ -} - -static void set_st_params(struct oxygen *chip, - struct snd_pcm_hw_params *params) -{ - update_cs2000_rate(chip, params_rate(params)); - set_pcm1796_params(chip, params); -} - -static void set_hdav_params(struct oxygen *chip, - struct snd_pcm_hw_params *params) -{ - struct xonar_hdav *data = chip->model_data; - - set_pcm1796_params(chip, params); - xonar_set_hdmi_params(chip, &data->hdmi, params); -} - -static const struct snd_kcontrol_new alt_switch = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Analog Loopback Switch", - .info = snd_ctl_boolean_mono_info, - .get = xonar_gpio_bit_switch_get, - .put = xonar_gpio_bit_switch_put, - .private_value = GPIO_D2_ALT, -}; - -static int rolloff_info(struct snd_kcontrol *ctl, - struct snd_ctl_elem_info *info) -{ - static const char *const names[2] = { - "Sharp Roll-off", "Slow Roll-off" - }; - - return snd_ctl_enum_info(info, 1, 2, names); -} - -static int rolloff_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - struct xonar_pcm179x *data = chip->model_data; - - value->value.enumerated.item[0] = - (data->pcm1796_regs[0][19 - PCM1796_REG_BASE] & - PCM1796_FLT_MASK) != PCM1796_FLT_SHARP; - return 0; -} - -static int rolloff_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - struct xonar_pcm179x *data = chip->model_data; - unsigned int i; - int changed; - u8 reg; - - mutex_lock(&chip->mutex); - reg = data->pcm1796_regs[0][19 - PCM1796_REG_BASE]; - reg &= ~PCM1796_FLT_MASK; - if (!value->value.enumerated.item[0]) - reg |= PCM1796_FLT_SHARP; - else - reg |= PCM1796_FLT_SLOW; - changed = reg != data->pcm1796_regs[0][19 - PCM1796_REG_BASE]; - if (changed) { - for (i = 0; i < data->dacs; ++i) - pcm1796_write(chip, i, 19, reg); - } - mutex_unlock(&chip->mutex); - return changed; -} - -static const struct snd_kcontrol_new rolloff_control = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "DAC Filter Playback Enum", - .info = rolloff_info, - .get = rolloff_get, - .put = rolloff_put, -}; - -static const struct snd_kcontrol_new hdav_hdmi_control = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "HDMI Playback Switch", - .info = snd_ctl_boolean_mono_info, - .get = xonar_gpio_bit_switch_get, - .put = xonar_gpio_bit_switch_put, - .private_value = GPIO_HDAV_OUTPUT_ENABLE | XONAR_GPIO_BIT_INVERT, -}; - -static int st_output_switch_info(struct snd_kcontrol *ctl, - struct snd_ctl_elem_info *info) -{ - static const char *const names[3] = { - "Speakers", "Headphones", "FP Headphones" - }; - - return snd_ctl_enum_info(info, 1, 3, names); -} - -static int st_output_switch_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - u16 gpio; - - gpio = oxygen_read16(chip, OXYGEN_GPIO_DATA); - if (!(gpio & GPIO_ST_HP)) - value->value.enumerated.item[0] = 0; - else if (gpio & GPIO_ST_HP_REAR) - value->value.enumerated.item[0] = 1; - else - value->value.enumerated.item[0] = 2; - return 0; -} - - -static int st_output_switch_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - struct xonar_pcm179x *data = chip->model_data; - u16 gpio_old, gpio; - - mutex_lock(&chip->mutex); - gpio_old = oxygen_read16(chip, OXYGEN_GPIO_DATA); - gpio = gpio_old; - switch (value->value.enumerated.item[0]) { - case 0: - gpio &= ~(GPIO_ST_HP | GPIO_ST_HP_REAR); - break; - case 1: - gpio |= GPIO_ST_HP | GPIO_ST_HP_REAR; - break; - case 2: - gpio = (gpio | GPIO_ST_HP) & ~GPIO_ST_HP_REAR; - break; - } - oxygen_write16(chip, OXYGEN_GPIO_DATA, gpio); - data->hp_active = gpio & GPIO_ST_HP; - update_pcm1796_volume(chip); - mutex_unlock(&chip->mutex); - return gpio != gpio_old; -} - -static int st_hp_volume_offset_info(struct snd_kcontrol *ctl, - struct snd_ctl_elem_info *info) -{ - static const char *const names[3] = { - "< 64 ohms", "64-300 ohms", "300-600 ohms" - }; - - return snd_ctl_enum_info(info, 1, 3, names); -} - -static int st_hp_volume_offset_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - struct xonar_pcm179x *data = chip->model_data; - - mutex_lock(&chip->mutex); - if (data->hp_gain_offset < 2*-6) - value->value.enumerated.item[0] = 0; - else if (data->hp_gain_offset < 0) - value->value.enumerated.item[0] = 1; - else - value->value.enumerated.item[0] = 2; - mutex_unlock(&chip->mutex); - return 0; -} - - -static int st_hp_volume_offset_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - static const s8 offsets[] = { 2*-18, 2*-6, 0 }; - struct oxygen *chip = ctl->private_data; - struct xonar_pcm179x *data = chip->model_data; - s8 offset; - int changed; - - if (value->value.enumerated.item[0] > 2) - return -EINVAL; - offset = offsets[value->value.enumerated.item[0]]; - mutex_lock(&chip->mutex); - changed = offset != data->hp_gain_offset; - if (changed) { - data->hp_gain_offset = offset; - update_pcm1796_volume(chip); - } - mutex_unlock(&chip->mutex); - return changed; -} - -static const struct snd_kcontrol_new st_controls[] = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Analog Output", - .info = st_output_switch_info, - .get = st_output_switch_get, - .put = st_output_switch_put, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Headphones Impedance Playback Enum", - .info = st_hp_volume_offset_info, - .get = st_hp_volume_offset_get, - .put = st_hp_volume_offset_put, - }, -}; - -static void xonar_line_mic_ac97_switch(struct oxygen *chip, - unsigned int reg, unsigned int mute) -{ - if (reg == AC97_LINE) { - spin_lock_irq(&chip->reg_lock); - oxygen_write16_masked(chip, OXYGEN_GPIO_DATA, - mute ? GPIO_INPUT_ROUTE : 0, - GPIO_INPUT_ROUTE); - spin_unlock_irq(&chip->reg_lock); - } -} - -static const DECLARE_TLV_DB_SCALE(pcm1796_db_scale, -6000, 50, 0); - -static int xonar_d2_control_filter(struct snd_kcontrol_new *template) -{ - if (!strncmp(template->name, "CD Capture ", 11)) - /* CD in is actually connected to the video in pin */ - template->private_value ^= AC97_CD ^ AC97_VIDEO; - return 0; -} - -static int xonar_st_h6_control_filter(struct snd_kcontrol_new *template) -{ - if (!strncmp(template->name, "Master Playback ", 16)) - /* no volume/mute, as I²C to the third DAC does not work */ - return 1; - return 0; -} - -static int add_pcm1796_controls(struct oxygen *chip) -{ - struct xonar_pcm179x *data = chip->model_data; - int err; - - if (!data->broken_i2c) { - err = snd_ctl_add(chip->card, - snd_ctl_new1(&rolloff_control, chip)); - if (err < 0) - return err; - } - return 0; -} - -static int xonar_d2_mixer_init(struct oxygen *chip) -{ - int err; - - err = snd_ctl_add(chip->card, snd_ctl_new1(&alt_switch, chip)); - if (err < 0) - return err; - err = add_pcm1796_controls(chip); - if (err < 0) - return err; - return 0; -} - -static int xonar_hdav_mixer_init(struct oxygen *chip) -{ - int err; - - err = snd_ctl_add(chip->card, snd_ctl_new1(&hdav_hdmi_control, chip)); - if (err < 0) - return err; - err = add_pcm1796_controls(chip); - if (err < 0) - return err; - return 0; -} - -static int xonar_st_mixer_init(struct oxygen *chip) -{ - unsigned int i; - int err; - - for (i = 0; i < ARRAY_SIZE(st_controls); ++i) { - err = snd_ctl_add(chip->card, - snd_ctl_new1(&st_controls[i], chip)); - if (err < 0) - return err; - } - err = add_pcm1796_controls(chip); - if (err < 0) - return err; - return 0; -} - -static void dump_pcm1796_registers(struct oxygen *chip, - struct snd_info_buffer *buffer) -{ - struct xonar_pcm179x *data = chip->model_data; - unsigned int dac, i; - - for (dac = 0; dac < data->dacs; ++dac) { - snd_iprintf(buffer, "\nPCM1796 %u:", dac + 1); - for (i = 0; i < 5; ++i) - snd_iprintf(buffer, " %02x", - data->pcm1796_regs[dac][i]); - } - snd_iprintf(buffer, "\n"); -} - -static void dump_cs2000_registers(struct oxygen *chip, - struct snd_info_buffer *buffer) -{ - struct xonar_pcm179x *data = chip->model_data; - unsigned int i; - - if (data->has_cs2000) { - snd_iprintf(buffer, "\nCS2000:\n00: "); - for (i = 1; i < 0x10; ++i) - snd_iprintf(buffer, " %02x", data->cs2000_regs[i]); - snd_iprintf(buffer, "\n10:"); - for (i = 0x10; i < 0x1f; ++i) - snd_iprintf(buffer, " %02x", data->cs2000_regs[i]); - snd_iprintf(buffer, "\n"); - } -} - -static void dump_st_registers(struct oxygen *chip, - struct snd_info_buffer *buffer) -{ - dump_pcm1796_registers(chip, buffer); - dump_cs2000_registers(chip, buffer); -} - -static const struct oxygen_model model_xonar_d2 = { - .longname = "Asus Virtuoso 200", - .chip = "AV200", - .init = xonar_d2_init, - .control_filter = xonar_d2_control_filter, - .mixer_init = xonar_d2_mixer_init, - .cleanup = xonar_d2_cleanup, - .suspend = xonar_d2_suspend, - .resume = xonar_d2_resume, - .set_dac_params = set_pcm1796_params, - .set_adc_params = xonar_set_cs53x1_params, - .update_dac_volume = update_pcm1796_volume, - .update_dac_mute = update_pcm1796_mute, - .dump_registers = dump_pcm1796_registers, - .dac_tlv = pcm1796_db_scale, - .model_data_size = sizeof(struct xonar_pcm179x), - .device_config = PLAYBACK_0_TO_I2S | - PLAYBACK_1_TO_SPDIF | - CAPTURE_0_FROM_I2S_2 | - CAPTURE_1_FROM_SPDIF | - MIDI_OUTPUT | - MIDI_INPUT | - AC97_CD_INPUT, - .dac_channels_pcm = 8, - .dac_channels_mixer = 8, - .dac_volume_min = 255 - 2*60, - .dac_volume_max = 255, - .misc_flags = OXYGEN_MISC_MIDI, - .function_flags = OXYGEN_FUNCTION_SPI | - OXYGEN_FUNCTION_ENABLE_SPI_4_5, - .dac_mclks = OXYGEN_MCLKS(512, 128, 128), - .adc_mclks = OXYGEN_MCLKS(256, 128, 128), - .dac_i2s_format = OXYGEN_I2S_FORMAT_I2S, - .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, -}; - -static const struct oxygen_model model_xonar_hdav = { - .longname = "Asus Virtuoso 200", - .chip = "AV200", - .init = xonar_hdav_init, - .mixer_init = xonar_hdav_mixer_init, - .cleanup = xonar_hdav_cleanup, - .suspend = xonar_hdav_suspend, - .resume = xonar_hdav_resume, - .pcm_hardware_filter = xonar_hdmi_pcm_hardware_filter, - .set_dac_params = set_hdav_params, - .set_adc_params = xonar_set_cs53x1_params, - .update_dac_volume = update_pcm1796_volume, - .update_dac_mute = update_pcm1796_mute, - .uart_input = xonar_hdmi_uart_input, - .ac97_switch = xonar_line_mic_ac97_switch, - .dump_registers = dump_pcm1796_registers, - .dac_tlv = pcm1796_db_scale, - .model_data_size = sizeof(struct xonar_hdav), - .device_config = PLAYBACK_0_TO_I2S | - PLAYBACK_1_TO_SPDIF | - CAPTURE_0_FROM_I2S_2 | - CAPTURE_1_FROM_SPDIF, - .dac_channels_pcm = 8, - .dac_channels_mixer = 2, - .dac_volume_min = 255 - 2*60, - .dac_volume_max = 255, - .misc_flags = OXYGEN_MISC_MIDI, - .function_flags = OXYGEN_FUNCTION_2WIRE, - .dac_mclks = OXYGEN_MCLKS(512, 128, 128), - .adc_mclks = OXYGEN_MCLKS(256, 128, 128), - .dac_i2s_format = OXYGEN_I2S_FORMAT_I2S, - .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, -}; - -static const struct oxygen_model model_xonar_st = { - .longname = "Asus Virtuoso 100", - .chip = "AV200", - .init = xonar_st_init, - .mixer_init = xonar_st_mixer_init, - .cleanup = xonar_st_cleanup, - .suspend = xonar_st_suspend, - .resume = xonar_st_resume, - .set_dac_params = set_st_params, - .set_adc_params = xonar_set_cs53x1_params, - .update_dac_volume = update_pcm1796_volume, - .update_dac_mute = update_pcm1796_mute, - .ac97_switch = xonar_line_mic_ac97_switch, - .dump_registers = dump_st_registers, - .dac_tlv = pcm1796_db_scale, - .model_data_size = sizeof(struct xonar_pcm179x), - .device_config = PLAYBACK_0_TO_I2S | - PLAYBACK_1_TO_SPDIF | - CAPTURE_0_FROM_I2S_2 | - CAPTURE_1_FROM_SPDIF | - AC97_FMIC_SWITCH, - .dac_channels_pcm = 2, - .dac_channels_mixer = 2, - .dac_volume_min = 255 - 2*60, - .dac_volume_max = 255, - .function_flags = OXYGEN_FUNCTION_2WIRE, - .dac_mclks = OXYGEN_MCLKS(512, 128, 128), - .adc_mclks = OXYGEN_MCLKS(256, 128, 128), - .dac_i2s_format = OXYGEN_I2S_FORMAT_I2S, - .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, -}; - -int __devinit get_xonar_pcm179x_model(struct oxygen *chip, - const struct pci_device_id *id) -{ - switch (id->subdevice) { - case 0x8269: - chip->model = model_xonar_d2; - chip->model.shortname = "Xonar D2"; - break; - case 0x82b7: - chip->model = model_xonar_d2; - chip->model.shortname = "Xonar D2X"; - chip->model.init = xonar_d2x_init; - break; - case 0x8314: - chip->model = model_xonar_hdav; - oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_DB_MASK); - switch (oxygen_read16(chip, OXYGEN_GPIO_DATA) & GPIO_DB_MASK) { - default: - chip->model.shortname = "Xonar HDAV1.3"; - break; - case GPIO_DB_H6: - chip->model.shortname = "Xonar HDAV1.3+H6"; - chip->model.dac_channels_mixer = 8; - chip->model.dac_mclks = OXYGEN_MCLKS(256, 128, 128); - break; - } - break; - case 0x835d: - chip->model = model_xonar_st; - oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_DB_MASK); - switch (oxygen_read16(chip, OXYGEN_GPIO_DATA) & GPIO_DB_MASK) { - default: - chip->model.shortname = "Xonar ST"; - break; - case GPIO_DB_H6: - chip->model.shortname = "Xonar ST+H6"; - chip->model.control_filter = xonar_st_h6_control_filter; - chip->model.dac_channels_pcm = 8; - chip->model.dac_channels_mixer = 8; - chip->model.dac_volume_min = 255; - chip->model.dac_mclks = OXYGEN_MCLKS(256, 128, 128); - break; - } - break; - case 0x835c: - chip->model = model_xonar_st; - chip->model.shortname = "Xonar STX"; - chip->model.init = xonar_stx_init; - chip->model.resume = xonar_stx_resume; - chip->model.set_dac_params = set_pcm1796_params; - break; - default: - return -EINVAL; - } - return 0; -} diff --git a/ANDROID_3.4.5/sound/pci/oxygen/xonar_wm87x6.c b/ANDROID_3.4.5/sound/pci/oxygen/xonar_wm87x6.c deleted file mode 100644 index 63cff907..00000000 --- a/ANDROID_3.4.5/sound/pci/oxygen/xonar_wm87x6.c +++ /dev/null @@ -1,1338 +0,0 @@ -/* - * card driver for models with WM8776/WM8766 DACs (Xonar DS/HDAV1.3 Slim) - * - * 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 DS - * -------- - * - * CMI8788: - * - * SPI 0 -> WM8766 (surround, center/LFE, back) - * SPI 1 -> WM8776 (front, input) - * - * GPIO 4 <- headphone detect, 0 = plugged - * GPIO 6 -> route input jack to mic-in (0) or line-in (1) - * GPIO 7 -> enable output to front L/R speaker channels - * GPIO 8 -> enable output to other speaker channels and front panel headphone - * - * WM8776: - * - * input 1 <- line - * input 2 <- mic - * input 3 <- front mic - * input 4 <- aux - */ - -/* - * Xonar HDAV1.3 Slim - * ------------------ - * - * CMI8788: - * - * I²C <-> WM8776 (addr 0011010) - * - * GPIO 0 -> disable HDMI output - * GPIO 1 -> enable HP output - * GPIO 6 -> firmware EEPROM I²C clock - * GPIO 7 <-> firmware EEPROM I²C data - * - * UART <-> HDMI controller - * - * WM8776: - * - * input 1 <- mic - * input 2 <- aux - */ - -#include <linux/pci.h> -#include <linux/delay.h> -#include <sound/control.h> -#include <sound/core.h> -#include <sound/info.h> -#include <sound/jack.h> -#include <sound/pcm.h> -#include <sound/pcm_params.h> -#include <sound/tlv.h> -#include "xonar.h" -#include "wm8776.h" -#include "wm8766.h" - -#define GPIO_DS_HP_DETECT 0x0010 -#define GPIO_DS_INPUT_ROUTE 0x0040 -#define GPIO_DS_OUTPUT_FRONTLR 0x0080 -#define GPIO_DS_OUTPUT_ENABLE 0x0100 - -#define GPIO_SLIM_HDMI_DISABLE 0x0001 -#define GPIO_SLIM_OUTPUT_ENABLE 0x0002 -#define GPIO_SLIM_FIRMWARE_CLK 0x0040 -#define GPIO_SLIM_FIRMWARE_DATA 0x0080 - -#define I2C_DEVICE_WM8776 0x34 /* 001101, 0, /W=0 */ - -#define LC_CONTROL_LIMITER 0x40000000 -#define LC_CONTROL_ALC 0x20000000 - -struct xonar_wm87x6 { - struct xonar_generic generic; - u16 wm8776_regs[0x17]; - u16 wm8766_regs[0x10]; - struct snd_kcontrol *line_adcmux_control; - struct snd_kcontrol *mic_adcmux_control; - struct snd_kcontrol *lc_controls[13]; - struct snd_jack *hp_jack; - struct xonar_hdmi hdmi; -}; - -static void wm8776_write_spi(struct oxygen *chip, - unsigned int reg, unsigned int value) -{ - oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER | - OXYGEN_SPI_DATA_LENGTH_2 | - OXYGEN_SPI_CLOCK_160 | - (1 << OXYGEN_SPI_CODEC_SHIFT) | - OXYGEN_SPI_CEN_LATCH_CLOCK_LO, - (reg << 9) | value); -} - -static void wm8776_write_i2c(struct oxygen *chip, - unsigned int reg, unsigned int value) -{ - oxygen_write_i2c(chip, I2C_DEVICE_WM8776, - (reg << 1) | (value >> 8), value); -} - -static void wm8776_write(struct oxygen *chip, - unsigned int reg, unsigned int value) -{ - struct xonar_wm87x6 *data = chip->model_data; - - if ((chip->model.function_flags & OXYGEN_FUNCTION_2WIRE_SPI_MASK) == - OXYGEN_FUNCTION_SPI) - wm8776_write_spi(chip, reg, value); - else - wm8776_write_i2c(chip, reg, value); - if (reg < ARRAY_SIZE(data->wm8776_regs)) { - if (reg >= WM8776_HPLVOL && reg <= WM8776_DACMASTER) - value &= ~WM8776_UPDATE; - data->wm8776_regs[reg] = value; - } -} - -static void wm8776_write_cached(struct oxygen *chip, - unsigned int reg, unsigned int value) -{ - struct xonar_wm87x6 *data = chip->model_data; - - if (reg >= ARRAY_SIZE(data->wm8776_regs) || - value != data->wm8776_regs[reg]) - wm8776_write(chip, reg, value); -} - -static void wm8766_write(struct oxygen *chip, - unsigned int reg, unsigned int value) -{ - struct xonar_wm87x6 *data = chip->model_data; - - oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER | - OXYGEN_SPI_DATA_LENGTH_2 | - OXYGEN_SPI_CLOCK_160 | - (0 << OXYGEN_SPI_CODEC_SHIFT) | - OXYGEN_SPI_CEN_LATCH_CLOCK_LO, - (reg << 9) | value); - if (reg < ARRAY_SIZE(data->wm8766_regs)) { - if ((reg >= WM8766_LDA1 && reg <= WM8766_RDA1) || - (reg >= WM8766_LDA2 && reg <= WM8766_MASTDA)) - value &= ~WM8766_UPDATE; - data->wm8766_regs[reg] = value; - } -} - -static void wm8766_write_cached(struct oxygen *chip, - unsigned int reg, unsigned int value) -{ - struct xonar_wm87x6 *data = chip->model_data; - - if (reg >= ARRAY_SIZE(data->wm8766_regs) || - value != data->wm8766_regs[reg]) - wm8766_write(chip, reg, value); -} - -static void wm8776_registers_init(struct oxygen *chip) -{ - struct xonar_wm87x6 *data = chip->model_data; - - wm8776_write(chip, WM8776_RESET, 0); - wm8776_write(chip, WM8776_PHASESWAP, WM8776_PH_MASK); - wm8776_write(chip, WM8776_DACCTRL1, WM8776_DZCEN | - WM8776_PL_LEFT_LEFT | WM8776_PL_RIGHT_RIGHT); - wm8776_write(chip, WM8776_DACMUTE, chip->dac_mute ? WM8776_DMUTE : 0); - wm8776_write(chip, WM8776_DACIFCTRL, - WM8776_DACFMT_LJUST | WM8776_DACWL_24); - wm8776_write(chip, WM8776_ADCIFCTRL, - data->wm8776_regs[WM8776_ADCIFCTRL]); - wm8776_write(chip, WM8776_MSTRCTRL, data->wm8776_regs[WM8776_MSTRCTRL]); - wm8776_write(chip, WM8776_PWRDOWN, data->wm8776_regs[WM8776_PWRDOWN]); - wm8776_write(chip, WM8776_HPLVOL, data->wm8776_regs[WM8776_HPLVOL]); - wm8776_write(chip, WM8776_HPRVOL, data->wm8776_regs[WM8776_HPRVOL] | - WM8776_UPDATE); - wm8776_write(chip, WM8776_ADCLVOL, data->wm8776_regs[WM8776_ADCLVOL]); - wm8776_write(chip, WM8776_ADCRVOL, data->wm8776_regs[WM8776_ADCRVOL]); - wm8776_write(chip, WM8776_ADCMUX, data->wm8776_regs[WM8776_ADCMUX]); - wm8776_write(chip, WM8776_DACLVOL, chip->dac_volume[0]); - wm8776_write(chip, WM8776_DACRVOL, chip->dac_volume[1] | WM8776_UPDATE); -} - -static void wm8766_registers_init(struct oxygen *chip) -{ - struct xonar_wm87x6 *data = chip->model_data; - - wm8766_write(chip, WM8766_RESET, 0); - wm8766_write(chip, WM8766_DAC_CTRL, data->wm8766_regs[WM8766_DAC_CTRL]); - wm8766_write(chip, WM8766_INT_CTRL, WM8766_FMT_LJUST | WM8766_IWL_24); - wm8766_write(chip, WM8766_DAC_CTRL2, - WM8766_ZCD | (chip->dac_mute ? WM8766_DMUTE_MASK : 0)); - wm8766_write(chip, WM8766_LDA1, chip->dac_volume[2]); - wm8766_write(chip, WM8766_RDA1, chip->dac_volume[3]); - wm8766_write(chip, WM8766_LDA2, chip->dac_volume[4]); - wm8766_write(chip, WM8766_RDA2, chip->dac_volume[5]); - wm8766_write(chip, WM8766_LDA3, chip->dac_volume[6]); - wm8766_write(chip, WM8766_RDA3, chip->dac_volume[7] | WM8766_UPDATE); -} - -static void wm8776_init(struct oxygen *chip) -{ - struct xonar_wm87x6 *data = chip->model_data; - - data->wm8776_regs[WM8776_HPLVOL] = (0x79 - 60) | WM8776_HPZCEN; - data->wm8776_regs[WM8776_HPRVOL] = (0x79 - 60) | WM8776_HPZCEN; - data->wm8776_regs[WM8776_ADCIFCTRL] = - WM8776_ADCFMT_LJUST | WM8776_ADCWL_24 | WM8776_ADCMCLK; - data->wm8776_regs[WM8776_MSTRCTRL] = - WM8776_ADCRATE_256 | WM8776_DACRATE_256; - data->wm8776_regs[WM8776_PWRDOWN] = WM8776_HPPD; - data->wm8776_regs[WM8776_ADCLVOL] = 0xa5 | WM8776_ZCA; - data->wm8776_regs[WM8776_ADCRVOL] = 0xa5 | WM8776_ZCA; - data->wm8776_regs[WM8776_ADCMUX] = 0x001; - wm8776_registers_init(chip); -} - -static void wm8766_init(struct oxygen *chip) -{ - struct xonar_wm87x6 *data = chip->model_data; - - data->wm8766_regs[WM8766_DAC_CTRL] = - WM8766_PL_LEFT_LEFT | WM8766_PL_RIGHT_RIGHT; - wm8766_registers_init(chip); -} - -static void xonar_ds_handle_hp_jack(struct oxygen *chip) -{ - struct xonar_wm87x6 *data = chip->model_data; - bool hp_plugged; - unsigned int reg; - - mutex_lock(&chip->mutex); - - hp_plugged = !(oxygen_read16(chip, OXYGEN_GPIO_DATA) & - GPIO_DS_HP_DETECT); - - oxygen_write16_masked(chip, OXYGEN_GPIO_DATA, - hp_plugged ? 0 : GPIO_DS_OUTPUT_FRONTLR, - GPIO_DS_OUTPUT_FRONTLR); - - reg = data->wm8766_regs[WM8766_DAC_CTRL] & ~WM8766_MUTEALL; - if (hp_plugged) - reg |= WM8766_MUTEALL; - wm8766_write_cached(chip, WM8766_DAC_CTRL, reg); - - snd_jack_report(data->hp_jack, hp_plugged ? SND_JACK_HEADPHONE : 0); - - mutex_unlock(&chip->mutex); -} - -static void xonar_ds_init(struct oxygen *chip) -{ - struct xonar_wm87x6 *data = chip->model_data; - - data->generic.anti_pop_delay = 300; - data->generic.output_enable_bit = GPIO_DS_OUTPUT_ENABLE; - - wm8776_init(chip); - wm8766_init(chip); - - oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, - GPIO_DS_INPUT_ROUTE | GPIO_DS_OUTPUT_FRONTLR); - oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL, - GPIO_DS_HP_DETECT); - oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, GPIO_DS_INPUT_ROUTE); - oxygen_set_bits16(chip, OXYGEN_GPIO_INTERRUPT_MASK, GPIO_DS_HP_DETECT); - chip->interrupt_mask |= OXYGEN_INT_GPIO; - - xonar_enable_output(chip); - - snd_jack_new(chip->card, "Headphone", - SND_JACK_HEADPHONE, &data->hp_jack); - xonar_ds_handle_hp_jack(chip); - - snd_component_add(chip->card, "WM8776"); - snd_component_add(chip->card, "WM8766"); -} - -static void xonar_hdav_slim_init(struct oxygen *chip) -{ - struct xonar_wm87x6 *data = chip->model_data; - - data->generic.anti_pop_delay = 300; - data->generic.output_enable_bit = GPIO_SLIM_OUTPUT_ENABLE; - - wm8776_init(chip); - - oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, - GPIO_SLIM_HDMI_DISABLE | - GPIO_SLIM_FIRMWARE_CLK | - GPIO_SLIM_FIRMWARE_DATA); - - xonar_hdmi_init(chip, &data->hdmi); - xonar_enable_output(chip); - - snd_component_add(chip->card, "WM8776"); -} - -static void xonar_ds_cleanup(struct oxygen *chip) -{ - xonar_disable_output(chip); - wm8776_write(chip, WM8776_RESET, 0); -} - -static void xonar_hdav_slim_cleanup(struct oxygen *chip) -{ - xonar_hdmi_cleanup(chip); - xonar_disable_output(chip); - wm8776_write(chip, WM8776_RESET, 0); - msleep(2); -} - -static void xonar_ds_suspend(struct oxygen *chip) -{ - xonar_ds_cleanup(chip); -} - -static void xonar_hdav_slim_suspend(struct oxygen *chip) -{ - xonar_hdav_slim_cleanup(chip); -} - -static void xonar_ds_resume(struct oxygen *chip) -{ - wm8776_registers_init(chip); - wm8766_registers_init(chip); - xonar_enable_output(chip); - xonar_ds_handle_hp_jack(chip); -} - -static void xonar_hdav_slim_resume(struct oxygen *chip) -{ - struct xonar_wm87x6 *data = chip->model_data; - - wm8776_registers_init(chip); - xonar_hdmi_resume(chip, &data->hdmi); - xonar_enable_output(chip); -} - -static void wm8776_adc_hardware_filter(unsigned int channel, - struct snd_pcm_hardware *hardware) -{ - if (channel == PCM_A) { - hardware->rates = SNDRV_PCM_RATE_32000 | - SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_64000 | - SNDRV_PCM_RATE_88200 | - SNDRV_PCM_RATE_96000; - hardware->rate_max = 96000; - } -} - -static void xonar_hdav_slim_hardware_filter(unsigned int channel, - struct snd_pcm_hardware *hardware) -{ - wm8776_adc_hardware_filter(channel, hardware); - xonar_hdmi_pcm_hardware_filter(channel, hardware); -} - -static void set_wm87x6_dac_params(struct oxygen *chip, - struct snd_pcm_hw_params *params) -{ -} - -static void set_wm8776_adc_params(struct oxygen *chip, - struct snd_pcm_hw_params *params) -{ - u16 reg; - - reg = WM8776_ADCRATE_256 | WM8776_DACRATE_256; - if (params_rate(params) > 48000) - reg |= WM8776_ADCOSR; - wm8776_write_cached(chip, WM8776_MSTRCTRL, reg); -} - -static void set_hdav_slim_dac_params(struct oxygen *chip, - struct snd_pcm_hw_params *params) -{ - struct xonar_wm87x6 *data = chip->model_data; - - xonar_set_hdmi_params(chip, &data->hdmi, params); -} - -static void update_wm8776_volume(struct oxygen *chip) -{ - struct xonar_wm87x6 *data = chip->model_data; - u8 to_change; - - if (chip->dac_volume[0] == chip->dac_volume[1]) { - if (chip->dac_volume[0] != data->wm8776_regs[WM8776_DACLVOL] || - chip->dac_volume[1] != data->wm8776_regs[WM8776_DACRVOL]) { - wm8776_write(chip, WM8776_DACMASTER, - chip->dac_volume[0] | WM8776_UPDATE); - data->wm8776_regs[WM8776_DACLVOL] = chip->dac_volume[0]; - data->wm8776_regs[WM8776_DACRVOL] = chip->dac_volume[0]; - } - } else { - to_change = (chip->dac_volume[0] != - data->wm8776_regs[WM8776_DACLVOL]) << 0; - to_change |= (chip->dac_volume[1] != - data->wm8776_regs[WM8776_DACLVOL]) << 1; - if (to_change & 1) - wm8776_write(chip, WM8776_DACLVOL, chip->dac_volume[0] | - ((to_change & 2) ? 0 : WM8776_UPDATE)); - if (to_change & 2) - wm8776_write(chip, WM8776_DACRVOL, - chip->dac_volume[1] | WM8776_UPDATE); - } -} - -static void update_wm87x6_volume(struct oxygen *chip) -{ - static const u8 wm8766_regs[6] = { - WM8766_LDA1, WM8766_RDA1, - WM8766_LDA2, WM8766_RDA2, - WM8766_LDA3, WM8766_RDA3, - }; - struct xonar_wm87x6 *data = chip->model_data; - unsigned int i; - u8 to_change; - - update_wm8776_volume(chip); - if (chip->dac_volume[2] == chip->dac_volume[3] && - chip->dac_volume[2] == chip->dac_volume[4] && - chip->dac_volume[2] == chip->dac_volume[5] && - chip->dac_volume[2] == chip->dac_volume[6] && - chip->dac_volume[2] == chip->dac_volume[7]) { - to_change = 0; - for (i = 0; i < 6; ++i) - if (chip->dac_volume[2] != - data->wm8766_regs[wm8766_regs[i]]) - to_change = 1; - if (to_change) { - wm8766_write(chip, WM8766_MASTDA, - chip->dac_volume[2] | WM8766_UPDATE); - for (i = 0; i < 6; ++i) - data->wm8766_regs[wm8766_regs[i]] = - chip->dac_volume[2]; - } - } else { - to_change = 0; - for (i = 0; i < 6; ++i) - to_change |= (chip->dac_volume[2 + i] != - data->wm8766_regs[wm8766_regs[i]]) << i; - for (i = 0; i < 6; ++i) - if (to_change & (1 << i)) - wm8766_write(chip, wm8766_regs[i], - chip->dac_volume[2 + i] | - ((to_change & (0x3e << i)) - ? 0 : WM8766_UPDATE)); - } -} - -static void update_wm8776_mute(struct oxygen *chip) -{ - wm8776_write_cached(chip, WM8776_DACMUTE, - chip->dac_mute ? WM8776_DMUTE : 0); -} - -static void update_wm87x6_mute(struct oxygen *chip) -{ - update_wm8776_mute(chip); - wm8766_write_cached(chip, WM8766_DAC_CTRL2, WM8766_ZCD | - (chip->dac_mute ? WM8766_DMUTE_MASK : 0)); -} - -static void update_wm8766_center_lfe_mix(struct oxygen *chip, bool mixed) -{ - struct xonar_wm87x6 *data = chip->model_data; - unsigned int reg; - - /* - * The WM8766 can mix left and right channels, but this setting - * applies to all three stereo pairs. - */ - reg = data->wm8766_regs[WM8766_DAC_CTRL] & - ~(WM8766_PL_LEFT_MASK | WM8766_PL_RIGHT_MASK); - if (mixed) - reg |= WM8766_PL_LEFT_LRMIX | WM8766_PL_RIGHT_LRMIX; - else - reg |= WM8766_PL_LEFT_LEFT | WM8766_PL_RIGHT_RIGHT; - wm8766_write_cached(chip, WM8766_DAC_CTRL, reg); -} - -static void xonar_ds_gpio_changed(struct oxygen *chip) -{ - xonar_ds_handle_hp_jack(chip); -} - -static int wm8776_bit_switch_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - struct xonar_wm87x6 *data = chip->model_data; - u16 bit = ctl->private_value & 0xffff; - unsigned int reg_index = (ctl->private_value >> 16) & 0xff; - bool invert = (ctl->private_value >> 24) & 1; - - value->value.integer.value[0] = - ((data->wm8776_regs[reg_index] & bit) != 0) ^ invert; - return 0; -} - -static int wm8776_bit_switch_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - struct xonar_wm87x6 *data = chip->model_data; - u16 bit = ctl->private_value & 0xffff; - u16 reg_value; - unsigned int reg_index = (ctl->private_value >> 16) & 0xff; - bool invert = (ctl->private_value >> 24) & 1; - int changed; - - mutex_lock(&chip->mutex); - reg_value = data->wm8776_regs[reg_index] & ~bit; - if (value->value.integer.value[0] ^ invert) - reg_value |= bit; - changed = reg_value != data->wm8776_regs[reg_index]; - if (changed) - wm8776_write(chip, reg_index, reg_value); - mutex_unlock(&chip->mutex); - return changed; -} - -static int wm8776_field_enum_info(struct snd_kcontrol *ctl, - struct snd_ctl_elem_info *info) -{ - static const char *const hld[16] = { - "0 ms", "2.67 ms", "5.33 ms", "10.6 ms", - "21.3 ms", "42.7 ms", "85.3 ms", "171 ms", - "341 ms", "683 ms", "1.37 s", "2.73 s", - "5.46 s", "10.9 s", "21.8 s", "43.7 s", - }; - static const char *const atk_lim[11] = { - "0.25 ms", "0.5 ms", "1 ms", "2 ms", - "4 ms", "8 ms", "16 ms", "32 ms", - "64 ms", "128 ms", "256 ms", - }; - static const char *const atk_alc[11] = { - "8.40 ms", "16.8 ms", "33.6 ms", "67.2 ms", - "134 ms", "269 ms", "538 ms", "1.08 s", - "2.15 s", "4.3 s", "8.6 s", - }; - static const char *const dcy_lim[11] = { - "1.2 ms", "2.4 ms", "4.8 ms", "9.6 ms", - "19.2 ms", "38.4 ms", "76.8 ms", "154 ms", - "307 ms", "614 ms", "1.23 s", - }; - static const char *const dcy_alc[11] = { - "33.5 ms", "67.0 ms", "134 ms", "268 ms", - "536 ms", "1.07 s", "2.14 s", "4.29 s", - "8.58 s", "17.2 s", "34.3 s", - }; - static const char *const tranwin[8] = { - "0 us", "62.5 us", "125 us", "250 us", - "500 us", "1 ms", "2 ms", "4 ms", - }; - u8 max; - const char *const *names; - - max = (ctl->private_value >> 12) & 0xf; - switch ((ctl->private_value >> 24) & 0x1f) { - case WM8776_ALCCTRL2: - names = hld; - break; - case WM8776_ALCCTRL3: - if (((ctl->private_value >> 20) & 0xf) == 0) { - if (ctl->private_value & LC_CONTROL_LIMITER) - names = atk_lim; - else - names = atk_alc; - } else { - if (ctl->private_value & LC_CONTROL_LIMITER) - names = dcy_lim; - else - names = dcy_alc; - } - break; - case WM8776_LIMITER: - names = tranwin; - break; - default: - return -ENXIO; - } - return snd_ctl_enum_info(info, 1, max + 1, names); -} - -static int wm8776_field_volume_info(struct snd_kcontrol *ctl, - struct snd_ctl_elem_info *info) -{ - info->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - info->count = 1; - info->value.integer.min = (ctl->private_value >> 8) & 0xf; - info->value.integer.max = (ctl->private_value >> 12) & 0xf; - return 0; -} - -static void wm8776_field_set_from_ctl(struct snd_kcontrol *ctl) -{ - struct oxygen *chip = ctl->private_data; - struct xonar_wm87x6 *data = chip->model_data; - unsigned int value, reg_index, mode; - u8 min, max, shift; - u16 mask, reg_value; - bool invert; - - if ((data->wm8776_regs[WM8776_ALCCTRL1] & WM8776_LCSEL_MASK) == - WM8776_LCSEL_LIMITER) - mode = LC_CONTROL_LIMITER; - else - mode = LC_CONTROL_ALC; - if (!(ctl->private_value & mode)) - return; - - value = ctl->private_value & 0xf; - min = (ctl->private_value >> 8) & 0xf; - max = (ctl->private_value >> 12) & 0xf; - mask = (ctl->private_value >> 16) & 0xf; - shift = (ctl->private_value >> 20) & 0xf; - reg_index = (ctl->private_value >> 24) & 0x1f; - invert = (ctl->private_value >> 29) & 0x1; - - if (invert) - value = max - (value - min); - reg_value = data->wm8776_regs[reg_index]; - reg_value &= ~(mask << shift); - reg_value |= value << shift; - wm8776_write_cached(chip, reg_index, reg_value); -} - -static int wm8776_field_set(struct snd_kcontrol *ctl, unsigned int value) -{ - struct oxygen *chip = ctl->private_data; - u8 min, max; - int changed; - - min = (ctl->private_value >> 8) & 0xf; - max = (ctl->private_value >> 12) & 0xf; - if (value < min || value > max) - return -EINVAL; - mutex_lock(&chip->mutex); - changed = value != (ctl->private_value & 0xf); - if (changed) { - ctl->private_value = (ctl->private_value & ~0xf) | value; - wm8776_field_set_from_ctl(ctl); - } - mutex_unlock(&chip->mutex); - return changed; -} - -static int wm8776_field_enum_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - value->value.enumerated.item[0] = ctl->private_value & 0xf; - return 0; -} - -static int wm8776_field_volume_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - value->value.integer.value[0] = ctl->private_value & 0xf; - return 0; -} - -static int wm8776_field_enum_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - return wm8776_field_set(ctl, value->value.enumerated.item[0]); -} - -static int wm8776_field_volume_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - return wm8776_field_set(ctl, value->value.integer.value[0]); -} - -static int wm8776_hp_vol_info(struct snd_kcontrol *ctl, - struct snd_ctl_elem_info *info) -{ - info->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - info->count = 2; - info->value.integer.min = 0x79 - 60; - info->value.integer.max = 0x7f; - return 0; -} - -static int wm8776_hp_vol_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - struct xonar_wm87x6 *data = chip->model_data; - - mutex_lock(&chip->mutex); - value->value.integer.value[0] = - data->wm8776_regs[WM8776_HPLVOL] & WM8776_HPATT_MASK; - value->value.integer.value[1] = - data->wm8776_regs[WM8776_HPRVOL] & WM8776_HPATT_MASK; - mutex_unlock(&chip->mutex); - return 0; -} - -static int wm8776_hp_vol_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - struct xonar_wm87x6 *data = chip->model_data; - u8 to_update; - - mutex_lock(&chip->mutex); - to_update = (value->value.integer.value[0] != - (data->wm8776_regs[WM8776_HPLVOL] & WM8776_HPATT_MASK)) - << 0; - to_update |= (value->value.integer.value[1] != - (data->wm8776_regs[WM8776_HPRVOL] & WM8776_HPATT_MASK)) - << 1; - if (value->value.integer.value[0] == value->value.integer.value[1]) { - if (to_update) { - wm8776_write(chip, WM8776_HPMASTER, - value->value.integer.value[0] | - WM8776_HPZCEN | WM8776_UPDATE); - data->wm8776_regs[WM8776_HPLVOL] = - value->value.integer.value[0] | WM8776_HPZCEN; - data->wm8776_regs[WM8776_HPRVOL] = - value->value.integer.value[0] | WM8776_HPZCEN; - } - } else { - if (to_update & 1) - wm8776_write(chip, WM8776_HPLVOL, - value->value.integer.value[0] | - WM8776_HPZCEN | - ((to_update & 2) ? 0 : WM8776_UPDATE)); - if (to_update & 2) - wm8776_write(chip, WM8776_HPRVOL, - value->value.integer.value[1] | - WM8776_HPZCEN | WM8776_UPDATE); - } - mutex_unlock(&chip->mutex); - return to_update != 0; -} - -static int wm8776_input_mux_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - struct xonar_wm87x6 *data = chip->model_data; - unsigned int mux_bit = ctl->private_value; - - value->value.integer.value[0] = - !!(data->wm8776_regs[WM8776_ADCMUX] & mux_bit); - return 0; -} - -static int wm8776_input_mux_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - struct xonar_wm87x6 *data = chip->model_data; - struct snd_kcontrol *other_ctl; - unsigned int mux_bit = ctl->private_value; - u16 reg; - int changed; - - mutex_lock(&chip->mutex); - reg = data->wm8776_regs[WM8776_ADCMUX]; - if (value->value.integer.value[0]) { - reg |= mux_bit; - /* line-in and mic-in are exclusive */ - mux_bit ^= 3; - if (reg & mux_bit) { - reg &= ~mux_bit; - if (mux_bit == 1) - other_ctl = data->line_adcmux_control; - else - other_ctl = data->mic_adcmux_control; - snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, - &other_ctl->id); - } - } else - reg &= ~mux_bit; - changed = reg != data->wm8776_regs[WM8776_ADCMUX]; - if (changed) { - oxygen_write16_masked(chip, OXYGEN_GPIO_DATA, - reg & 1 ? GPIO_DS_INPUT_ROUTE : 0, - GPIO_DS_INPUT_ROUTE); - wm8776_write(chip, WM8776_ADCMUX, reg); - } - mutex_unlock(&chip->mutex); - return changed; -} - -static int wm8776_input_vol_info(struct snd_kcontrol *ctl, - struct snd_ctl_elem_info *info) -{ - info->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - info->count = 2; - info->value.integer.min = 0xa5; - info->value.integer.max = 0xff; - return 0; -} - -static int wm8776_input_vol_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - struct xonar_wm87x6 *data = chip->model_data; - - mutex_lock(&chip->mutex); - value->value.integer.value[0] = - data->wm8776_regs[WM8776_ADCLVOL] & WM8776_AGMASK; - value->value.integer.value[1] = - data->wm8776_regs[WM8776_ADCRVOL] & WM8776_AGMASK; - mutex_unlock(&chip->mutex); - return 0; -} - -static int wm8776_input_vol_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - struct xonar_wm87x6 *data = chip->model_data; - int changed = 0; - - mutex_lock(&chip->mutex); - changed = (value->value.integer.value[0] != - (data->wm8776_regs[WM8776_ADCLVOL] & WM8776_AGMASK)) || - (value->value.integer.value[1] != - (data->wm8776_regs[WM8776_ADCRVOL] & WM8776_AGMASK)); - wm8776_write_cached(chip, WM8776_ADCLVOL, - value->value.integer.value[0] | WM8776_ZCA); - wm8776_write_cached(chip, WM8776_ADCRVOL, - value->value.integer.value[1] | WM8776_ZCA); - mutex_unlock(&chip->mutex); - return changed; -} - -static int wm8776_level_control_info(struct snd_kcontrol *ctl, - struct snd_ctl_elem_info *info) -{ - static const char *const names[3] = { - "None", "Peak Limiter", "Automatic Level Control" - }; - - return snd_ctl_enum_info(info, 1, 3, names); -} - -static int wm8776_level_control_get(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - struct xonar_wm87x6 *data = chip->model_data; - - if (!(data->wm8776_regs[WM8776_ALCCTRL2] & WM8776_LCEN)) - value->value.enumerated.item[0] = 0; - else if ((data->wm8776_regs[WM8776_ALCCTRL1] & WM8776_LCSEL_MASK) == - WM8776_LCSEL_LIMITER) - value->value.enumerated.item[0] = 1; - else - value->value.enumerated.item[0] = 2; - return 0; -} - -static void activate_control(struct oxygen *chip, - struct snd_kcontrol *ctl, unsigned int mode) -{ - unsigned int access; - - if (ctl->private_value & mode) - access = 0; - else - access = SNDRV_CTL_ELEM_ACCESS_INACTIVE; - if ((ctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_INACTIVE) != access) { - ctl->vd[0].access ^= SNDRV_CTL_ELEM_ACCESS_INACTIVE; - snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_INFO, &ctl->id); - } -} - -static int wm8776_level_control_put(struct snd_kcontrol *ctl, - struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - struct xonar_wm87x6 *data = chip->model_data; - unsigned int mode = 0, i; - u16 ctrl1, ctrl2; - int changed; - - if (value->value.enumerated.item[0] >= 3) - return -EINVAL; - mutex_lock(&chip->mutex); - changed = value->value.enumerated.item[0] != ctl->private_value; - if (changed) { - ctl->private_value = value->value.enumerated.item[0]; - ctrl1 = data->wm8776_regs[WM8776_ALCCTRL1]; - ctrl2 = data->wm8776_regs[WM8776_ALCCTRL2]; - switch (value->value.enumerated.item[0]) { - default: - wm8776_write_cached(chip, WM8776_ALCCTRL2, - ctrl2 & ~WM8776_LCEN); - break; - case 1: - wm8776_write_cached(chip, WM8776_ALCCTRL1, - (ctrl1 & ~WM8776_LCSEL_MASK) | - WM8776_LCSEL_LIMITER); - wm8776_write_cached(chip, WM8776_ALCCTRL2, - ctrl2 | WM8776_LCEN); - mode = LC_CONTROL_LIMITER; - break; - case 2: - wm8776_write_cached(chip, WM8776_ALCCTRL1, - (ctrl1 & ~WM8776_LCSEL_MASK) | - WM8776_LCSEL_ALC_STEREO); - wm8776_write_cached(chip, WM8776_ALCCTRL2, - ctrl2 | WM8776_LCEN); - mode = LC_CONTROL_ALC; - break; - } - for (i = 0; i < ARRAY_SIZE(data->lc_controls); ++i) - activate_control(chip, data->lc_controls[i], mode); - } - mutex_unlock(&chip->mutex); - return changed; -} - -static int hpf_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info) -{ - static const char *const names[2] = { - "None", "High-pass Filter" - }; - - return snd_ctl_enum_info(info, 1, 2, names); -} - -static int hpf_get(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - struct xonar_wm87x6 *data = chip->model_data; - - value->value.enumerated.item[0] = - !(data->wm8776_regs[WM8776_ADCIFCTRL] & WM8776_ADCHPD); - return 0; -} - -static int hpf_put(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value) -{ - struct oxygen *chip = ctl->private_data; - struct xonar_wm87x6 *data = chip->model_data; - unsigned int reg; - int changed; - - mutex_lock(&chip->mutex); - reg = data->wm8776_regs[WM8776_ADCIFCTRL] & ~WM8776_ADCHPD; - if (!value->value.enumerated.item[0]) - reg |= WM8776_ADCHPD; - changed = reg != data->wm8776_regs[WM8776_ADCIFCTRL]; - if (changed) - wm8776_write(chip, WM8776_ADCIFCTRL, reg); - mutex_unlock(&chip->mutex); - return changed; -} - -#define WM8776_BIT_SWITCH(xname, reg, bit, invert, flags) { \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .info = snd_ctl_boolean_mono_info, \ - .get = wm8776_bit_switch_get, \ - .put = wm8776_bit_switch_put, \ - .private_value = ((reg) << 16) | (bit) | ((invert) << 24) | (flags), \ -} -#define _WM8776_FIELD_CTL(xname, reg, shift, initval, min, max, mask, flags) \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .private_value = (initval) | ((min) << 8) | ((max) << 12) | \ - ((mask) << 16) | ((shift) << 20) | ((reg) << 24) | (flags) -#define WM8776_FIELD_CTL_ENUM(xname, reg, shift, init, min, max, mask, flags) {\ - _WM8776_FIELD_CTL(xname " Capture Enum", \ - reg, shift, init, min, max, mask, flags), \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \ - SNDRV_CTL_ELEM_ACCESS_INACTIVE, \ - .info = wm8776_field_enum_info, \ - .get = wm8776_field_enum_get, \ - .put = wm8776_field_enum_put, \ -} -#define WM8776_FIELD_CTL_VOLUME(a, b, c, d, e, f, g, h, tlv_p) { \ - _WM8776_FIELD_CTL(a " Capture Volume", b, c, d, e, f, g, h), \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \ - SNDRV_CTL_ELEM_ACCESS_INACTIVE | \ - SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ - .info = wm8776_field_volume_info, \ - .get = wm8776_field_volume_get, \ - .put = wm8776_field_volume_put, \ - .tlv = { .p = tlv_p }, \ -} - -static const DECLARE_TLV_DB_SCALE(wm87x6_dac_db_scale, -6000, 50, 0); -static const DECLARE_TLV_DB_SCALE(wm8776_adc_db_scale, -2100, 50, 0); -static const DECLARE_TLV_DB_SCALE(wm8776_hp_db_scale, -6000, 100, 0); -static const DECLARE_TLV_DB_SCALE(wm8776_lct_db_scale, -1600, 100, 0); -static const DECLARE_TLV_DB_SCALE(wm8776_maxgain_db_scale, 0, 400, 0); -static const DECLARE_TLV_DB_SCALE(wm8776_ngth_db_scale, -7800, 600, 0); -static const DECLARE_TLV_DB_SCALE(wm8776_maxatten_lim_db_scale, -1200, 100, 0); -static const DECLARE_TLV_DB_SCALE(wm8776_maxatten_alc_db_scale, -2100, 400, 0); - -static const struct snd_kcontrol_new ds_controls[] = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Headphone Playback Volume", - .info = wm8776_hp_vol_info, - .get = wm8776_hp_vol_get, - .put = wm8776_hp_vol_put, - .tlv = { .p = wm8776_hp_db_scale }, - }, - WM8776_BIT_SWITCH("Headphone Playback Switch", - WM8776_PWRDOWN, WM8776_HPPD, 1, 0), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Input Capture Volume", - .info = wm8776_input_vol_info, - .get = wm8776_input_vol_get, - .put = wm8776_input_vol_put, - .tlv = { .p = wm8776_adc_db_scale }, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Line Capture Switch", - .info = snd_ctl_boolean_mono_info, - .get = wm8776_input_mux_get, - .put = wm8776_input_mux_put, - .private_value = 1 << 0, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Mic Capture Switch", - .info = snd_ctl_boolean_mono_info, - .get = wm8776_input_mux_get, - .put = wm8776_input_mux_put, - .private_value = 1 << 1, - }, - WM8776_BIT_SWITCH("Front Mic Capture Switch", - WM8776_ADCMUX, 1 << 2, 0, 0), - WM8776_BIT_SWITCH("Aux Capture Switch", - WM8776_ADCMUX, 1 << 3, 0, 0), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "ADC Filter Capture Enum", - .info = hpf_info, - .get = hpf_get, - .put = hpf_put, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Level Control Capture Enum", - .info = wm8776_level_control_info, - .get = wm8776_level_control_get, - .put = wm8776_level_control_put, - .private_value = 0, - }, -}; -static const struct snd_kcontrol_new hdav_slim_controls[] = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "HDMI Playback Switch", - .info = snd_ctl_boolean_mono_info, - .get = xonar_gpio_bit_switch_get, - .put = xonar_gpio_bit_switch_put, - .private_value = GPIO_SLIM_HDMI_DISABLE | XONAR_GPIO_BIT_INVERT, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Headphone Playback Volume", - .info = wm8776_hp_vol_info, - .get = wm8776_hp_vol_get, - .put = wm8776_hp_vol_put, - .tlv = { .p = wm8776_hp_db_scale }, - }, - WM8776_BIT_SWITCH("Headphone Playback Switch", - WM8776_PWRDOWN, WM8776_HPPD, 1, 0), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Input Capture Volume", - .info = wm8776_input_vol_info, - .get = wm8776_input_vol_get, - .put = wm8776_input_vol_put, - .tlv = { .p = wm8776_adc_db_scale }, - }, - WM8776_BIT_SWITCH("Mic Capture Switch", - WM8776_ADCMUX, 1 << 0, 0, 0), - WM8776_BIT_SWITCH("Aux Capture Switch", - WM8776_ADCMUX, 1 << 1, 0, 0), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "ADC Filter Capture Enum", - .info = hpf_info, - .get = hpf_get, - .put = hpf_put, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Level Control Capture Enum", - .info = wm8776_level_control_info, - .get = wm8776_level_control_get, - .put = wm8776_level_control_put, - .private_value = 0, - }, -}; -static const struct snd_kcontrol_new lc_controls[] = { - WM8776_FIELD_CTL_VOLUME("Limiter Threshold", - WM8776_ALCCTRL1, 0, 11, 0, 15, 0xf, - LC_CONTROL_LIMITER, wm8776_lct_db_scale), - WM8776_FIELD_CTL_ENUM("Limiter Attack Time", - WM8776_ALCCTRL3, 0, 2, 0, 10, 0xf, - LC_CONTROL_LIMITER), - WM8776_FIELD_CTL_ENUM("Limiter Decay Time", - WM8776_ALCCTRL3, 4, 3, 0, 10, 0xf, - LC_CONTROL_LIMITER), - WM8776_FIELD_CTL_ENUM("Limiter Transient Window", - WM8776_LIMITER, 4, 2, 0, 7, 0x7, - LC_CONTROL_LIMITER), - WM8776_FIELD_CTL_VOLUME("Limiter Maximum Attenuation", - WM8776_LIMITER, 0, 6, 3, 12, 0xf, - LC_CONTROL_LIMITER, - wm8776_maxatten_lim_db_scale), - WM8776_FIELD_CTL_VOLUME("ALC Target Level", - WM8776_ALCCTRL1, 0, 11, 0, 15, 0xf, - LC_CONTROL_ALC, wm8776_lct_db_scale), - WM8776_FIELD_CTL_ENUM("ALC Attack Time", - WM8776_ALCCTRL3, 0, 2, 0, 10, 0xf, - LC_CONTROL_ALC), - WM8776_FIELD_CTL_ENUM("ALC Decay Time", - WM8776_ALCCTRL3, 4, 3, 0, 10, 0xf, - LC_CONTROL_ALC), - WM8776_FIELD_CTL_VOLUME("ALC Maximum Gain", - WM8776_ALCCTRL1, 4, 7, 1, 7, 0x7, - LC_CONTROL_ALC, wm8776_maxgain_db_scale), - WM8776_FIELD_CTL_VOLUME("ALC Maximum Attenuation", - WM8776_LIMITER, 0, 10, 10, 15, 0xf, - LC_CONTROL_ALC, wm8776_maxatten_alc_db_scale), - WM8776_FIELD_CTL_ENUM("ALC Hold Time", - WM8776_ALCCTRL2, 0, 0, 0, 15, 0xf, - LC_CONTROL_ALC), - WM8776_BIT_SWITCH("Noise Gate Capture Switch", - WM8776_NOISEGATE, WM8776_NGAT, 0, - LC_CONTROL_ALC), - WM8776_FIELD_CTL_VOLUME("Noise Gate Threshold", - WM8776_NOISEGATE, 2, 0, 0, 7, 0x7, - LC_CONTROL_ALC, wm8776_ngth_db_scale), -}; - -static int add_lc_controls(struct oxygen *chip) -{ - struct xonar_wm87x6 *data = chip->model_data; - unsigned int i; - struct snd_kcontrol *ctl; - int err; - - BUILD_BUG_ON(ARRAY_SIZE(lc_controls) != ARRAY_SIZE(data->lc_controls)); - for (i = 0; i < ARRAY_SIZE(lc_controls); ++i) { - ctl = snd_ctl_new1(&lc_controls[i], chip); - if (!ctl) - return -ENOMEM; - err = snd_ctl_add(chip->card, ctl); - if (err < 0) - return err; - data->lc_controls[i] = ctl; - } - return 0; -} - -static int xonar_ds_mixer_init(struct oxygen *chip) -{ - struct xonar_wm87x6 *data = chip->model_data; - unsigned int i; - struct snd_kcontrol *ctl; - int err; - - for (i = 0; i < ARRAY_SIZE(ds_controls); ++i) { - ctl = snd_ctl_new1(&ds_controls[i], chip); - if (!ctl) - return -ENOMEM; - err = snd_ctl_add(chip->card, ctl); - if (err < 0) - return err; - if (!strcmp(ctl->id.name, "Line Capture Switch")) - data->line_adcmux_control = ctl; - else if (!strcmp(ctl->id.name, "Mic Capture Switch")) - data->mic_adcmux_control = ctl; - } - if (!data->line_adcmux_control || !data->mic_adcmux_control) - return -ENXIO; - - return add_lc_controls(chip); -} - -static int xonar_hdav_slim_mixer_init(struct oxygen *chip) -{ - unsigned int i; - struct snd_kcontrol *ctl; - int err; - - for (i = 0; i < ARRAY_SIZE(hdav_slim_controls); ++i) { - ctl = snd_ctl_new1(&hdav_slim_controls[i], chip); - if (!ctl) - return -ENOMEM; - err = snd_ctl_add(chip->card, ctl); - if (err < 0) - return err; - } - - return add_lc_controls(chip); -} - -static void dump_wm8776_registers(struct oxygen *chip, - struct snd_info_buffer *buffer) -{ - struct xonar_wm87x6 *data = chip->model_data; - unsigned int i; - - snd_iprintf(buffer, "\nWM8776:\n00:"); - for (i = 0; i < 0x10; ++i) - snd_iprintf(buffer, " %03x", data->wm8776_regs[i]); - snd_iprintf(buffer, "\n10:"); - for (i = 0x10; i < 0x17; ++i) - snd_iprintf(buffer, " %03x", data->wm8776_regs[i]); - snd_iprintf(buffer, "\n"); -} - -static void dump_wm87x6_registers(struct oxygen *chip, - struct snd_info_buffer *buffer) -{ - struct xonar_wm87x6 *data = chip->model_data; - unsigned int i; - - dump_wm8776_registers(chip, buffer); - snd_iprintf(buffer, "\nWM8766:\n00:"); - for (i = 0; i < 0x10; ++i) - snd_iprintf(buffer, " %03x", data->wm8766_regs[i]); - snd_iprintf(buffer, "\n"); -} - -static const struct oxygen_model model_xonar_ds = { - .shortname = "Xonar DS", - .longname = "Asus Virtuoso 66", - .chip = "AV200", - .init = xonar_ds_init, - .mixer_init = xonar_ds_mixer_init, - .cleanup = xonar_ds_cleanup, - .suspend = xonar_ds_suspend, - .resume = xonar_ds_resume, - .pcm_hardware_filter = wm8776_adc_hardware_filter, - .set_dac_params = set_wm87x6_dac_params, - .set_adc_params = set_wm8776_adc_params, - .update_dac_volume = update_wm87x6_volume, - .update_dac_mute = update_wm87x6_mute, - .update_center_lfe_mix = update_wm8766_center_lfe_mix, - .gpio_changed = xonar_ds_gpio_changed, - .dump_registers = dump_wm87x6_registers, - .dac_tlv = wm87x6_dac_db_scale, - .model_data_size = sizeof(struct xonar_wm87x6), - .device_config = PLAYBACK_0_TO_I2S | - PLAYBACK_1_TO_SPDIF | - CAPTURE_0_FROM_I2S_1 | - CAPTURE_1_FROM_SPDIF, - .dac_channels_pcm = 8, - .dac_channels_mixer = 8, - .dac_volume_min = 255 - 2*60, - .dac_volume_max = 255, - .function_flags = OXYGEN_FUNCTION_SPI, - .dac_mclks = OXYGEN_MCLKS(256, 256, 128), - .adc_mclks = OXYGEN_MCLKS(256, 256, 128), - .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST, - .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, -}; - -static const struct oxygen_model model_xonar_hdav_slim = { - .shortname = "Xonar HDAV1.3 Slim", - .longname = "Asus Virtuoso 200", - .chip = "AV200", - .init = xonar_hdav_slim_init, - .mixer_init = xonar_hdav_slim_mixer_init, - .cleanup = xonar_hdav_slim_cleanup, - .suspend = xonar_hdav_slim_suspend, - .resume = xonar_hdav_slim_resume, - .pcm_hardware_filter = xonar_hdav_slim_hardware_filter, - .set_dac_params = set_hdav_slim_dac_params, - .set_adc_params = set_wm8776_adc_params, - .update_dac_volume = update_wm8776_volume, - .update_dac_mute = update_wm8776_mute, - .uart_input = xonar_hdmi_uart_input, - .dump_registers = dump_wm8776_registers, - .dac_tlv = wm87x6_dac_db_scale, - .model_data_size = sizeof(struct xonar_wm87x6), - .device_config = PLAYBACK_0_TO_I2S | - PLAYBACK_1_TO_SPDIF | - CAPTURE_0_FROM_I2S_1 | - CAPTURE_1_FROM_SPDIF, - .dac_channels_pcm = 8, - .dac_channels_mixer = 2, - .dac_volume_min = 255 - 2*60, - .dac_volume_max = 255, - .function_flags = OXYGEN_FUNCTION_2WIRE, - .dac_mclks = OXYGEN_MCLKS(256, 256, 128), - .adc_mclks = OXYGEN_MCLKS(256, 256, 128), - .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST, - .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, -}; - -int __devinit get_xonar_wm87x6_model(struct oxygen *chip, - const struct pci_device_id *id) -{ - switch (id->subdevice) { - case 0x838e: - chip->model = model_xonar_ds; - break; - case 0x835e: - chip->model = model_xonar_hdav_slim; - break; - default: - return -EINVAL; - } - return 0; -} |