|
@@ -8,7 +8,7 @@
|
|
|
* @File cthw20k2.c
|
|
|
*
|
|
|
* @Brief
|
|
|
- * This file contains the implementation of hardware access methord for 20k2.
|
|
|
+ * This file contains the implementation of hardware access method for 20k2.
|
|
|
*
|
|
|
* @Author Liu Chun
|
|
|
* @Date May 14 2008
|
|
@@ -38,6 +38,8 @@ struct hw20k2 {
|
|
|
unsigned char dev_id;
|
|
|
unsigned char addr_size;
|
|
|
unsigned char data_size;
|
|
|
+
|
|
|
+ int mic_source;
|
|
|
};
|
|
|
|
|
|
static u32 hw_read_20kx(struct hw *hw, u32 reg);
|
|
@@ -1163,7 +1165,12 @@ static int hw_daio_init(struct hw *hw, const struct daio_conf *info)
|
|
|
hw_write_20kx(hw, AUDIO_IO_TX_BLRCLK, 0x01010101);
|
|
|
hw_write_20kx(hw, AUDIO_IO_RX_BLRCLK, 0);
|
|
|
} else if (2 == info->msr) {
|
|
|
- hw_write_20kx(hw, AUDIO_IO_MCLK, 0x11111111);
|
|
|
+ if (hw->model != CTSB1270) {
|
|
|
+ hw_write_20kx(hw, AUDIO_IO_MCLK, 0x11111111);
|
|
|
+ } else {
|
|
|
+ /* PCM4220 on Titanium HD is different. */
|
|
|
+ hw_write_20kx(hw, AUDIO_IO_MCLK, 0x11011111);
|
|
|
+ }
|
|
|
/* Specify all playing 96khz
|
|
|
* EA [0] - Enabled
|
|
|
* RTA [4:5] - 96kHz
|
|
@@ -1175,6 +1182,10 @@ static int hw_daio_init(struct hw *hw, const struct daio_conf *info)
|
|
|
* RTD [28:29] - 96kHz */
|
|
|
hw_write_20kx(hw, AUDIO_IO_TX_BLRCLK, 0x11111111);
|
|
|
hw_write_20kx(hw, AUDIO_IO_RX_BLRCLK, 0);
|
|
|
+ } else if ((4 == info->msr) && (hw->model == CTSB1270)) {
|
|
|
+ hw_write_20kx(hw, AUDIO_IO_MCLK, 0x21011111);
|
|
|
+ hw_write_20kx(hw, AUDIO_IO_TX_BLRCLK, 0x21212121);
|
|
|
+ hw_write_20kx(hw, AUDIO_IO_RX_BLRCLK, 0);
|
|
|
} else {
|
|
|
printk(KERN_ALERT "ctxfi: ERROR!!! Invalid sampling rate!!!\n");
|
|
|
return -EINVAL;
|
|
@@ -1182,6 +1193,8 @@ static int hw_daio_init(struct hw *hw, const struct daio_conf *info)
|
|
|
|
|
|
for (i = 0; i < 8; i++) {
|
|
|
if (i <= 3) {
|
|
|
+ /* This comment looks wrong since loop is over 4 */
|
|
|
+ /* channels and emu20k2 supports 4 spdif IOs. */
|
|
|
/* 1st 3 channels are SPDIFs (SB0960) */
|
|
|
if (i == 3)
|
|
|
data = 0x1001001;
|
|
@@ -1206,12 +1219,16 @@ static int hw_daio_init(struct hw *hw, const struct daio_conf *info)
|
|
|
|
|
|
hw_write_20kx(hw, AUDIO_IO_TX_CSTAT_H+(0x40*i), 0x0B);
|
|
|
} else {
|
|
|
+ /* Again, loop is over 4 channels not 5. */
|
|
|
/* Next 5 channels are I2S (SB0960) */
|
|
|
data = 0x11;
|
|
|
hw_write_20kx(hw, AUDIO_IO_RX_CTL+(0x40*i), data);
|
|
|
if (2 == info->msr) {
|
|
|
/* Four channels per sample period */
|
|
|
data |= 0x1000;
|
|
|
+ } else if (4 == info->msr) {
|
|
|
+ /* FIXME: check this against the chip spec */
|
|
|
+ data |= 0x2000;
|
|
|
}
|
|
|
hw_write_20kx(hw, AUDIO_IO_TX_CTL+(0x40*i), data);
|
|
|
}
|
|
@@ -1557,7 +1574,7 @@ static int hw20k2_i2c_write(struct hw *hw, u16 addr, u32 data)
|
|
|
|
|
|
hw_write_20kx(hw, I2C_IF_STATUS, i2c_status);
|
|
|
hw20k2_i2c_wait_data_ready(hw);
|
|
|
- /* Dummy write to trigger the write oprtation */
|
|
|
+ /* Dummy write to trigger the write operation */
|
|
|
hw_write_20kx(hw, I2C_IF_WDATA, 0);
|
|
|
hw20k2_i2c_wait_data_ready(hw);
|
|
|
|
|
@@ -1568,6 +1585,30 @@ static int hw20k2_i2c_write(struct hw *hw, u16 addr, u32 data)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static void hw_dac_stop(struct hw *hw)
|
|
|
+{
|
|
|
+ u32 data;
|
|
|
+ data = hw_read_20kx(hw, GPIO_DATA);
|
|
|
+ data &= 0xFFFFFFFD;
|
|
|
+ hw_write_20kx(hw, GPIO_DATA, data);
|
|
|
+ mdelay(10);
|
|
|
+}
|
|
|
+
|
|
|
+static void hw_dac_start(struct hw *hw)
|
|
|
+{
|
|
|
+ u32 data;
|
|
|
+ data = hw_read_20kx(hw, GPIO_DATA);
|
|
|
+ data |= 0x2;
|
|
|
+ hw_write_20kx(hw, GPIO_DATA, data);
|
|
|
+ mdelay(50);
|
|
|
+}
|
|
|
+
|
|
|
+static void hw_dac_reset(struct hw *hw)
|
|
|
+{
|
|
|
+ hw_dac_stop(hw);
|
|
|
+ hw_dac_start(hw);
|
|
|
+}
|
|
|
+
|
|
|
static int hw_dac_init(struct hw *hw, const struct dac_conf *info)
|
|
|
{
|
|
|
int err;
|
|
@@ -1594,6 +1635,21 @@ static int hw_dac_init(struct hw *hw, const struct dac_conf *info)
|
|
|
0x00000000 /* Vol Control B4 */
|
|
|
};
|
|
|
|
|
|
+ if (hw->model == CTSB1270) {
|
|
|
+ hw_dac_stop(hw);
|
|
|
+ data = hw_read_20kx(hw, GPIO_DATA);
|
|
|
+ data &= ~0x0600;
|
|
|
+ if (1 == info->msr)
|
|
|
+ data |= 0x0000; /* Single Speed Mode 0-50kHz */
|
|
|
+ else if (2 == info->msr)
|
|
|
+ data |= 0x0200; /* Double Speed Mode 50-100kHz */
|
|
|
+ else
|
|
|
+ data |= 0x0600; /* Quad Speed Mode 100-200kHz */
|
|
|
+ hw_write_20kx(hw, GPIO_DATA, data);
|
|
|
+ hw_dac_start(hw);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
/* Set DAC reset bit as output */
|
|
|
data = hw_read_20kx(hw, GPIO_CTRL);
|
|
|
data |= 0x02;
|
|
@@ -1606,22 +1662,8 @@ static int hw_dac_init(struct hw *hw, const struct dac_conf *info)
|
|
|
for (i = 0; i < 2; i++) {
|
|
|
/* Reset DAC twice just in-case the chip
|
|
|
* didn't initialized properly */
|
|
|
- data = hw_read_20kx(hw, GPIO_DATA);
|
|
|
- /* GPIO data bit 1 */
|
|
|
- data &= 0xFFFFFFFD;
|
|
|
- hw_write_20kx(hw, GPIO_DATA, data);
|
|
|
- mdelay(10);
|
|
|
- data |= 0x2;
|
|
|
- hw_write_20kx(hw, GPIO_DATA, data);
|
|
|
- mdelay(50);
|
|
|
-
|
|
|
- /* Reset the 2nd time */
|
|
|
- data &= 0xFFFFFFFD;
|
|
|
- hw_write_20kx(hw, GPIO_DATA, data);
|
|
|
- mdelay(10);
|
|
|
- data |= 0x2;
|
|
|
- hw_write_20kx(hw, GPIO_DATA, data);
|
|
|
- mdelay(50);
|
|
|
+ hw_dac_reset(hw);
|
|
|
+ hw_dac_reset(hw);
|
|
|
|
|
|
if (hw20k2_i2c_read(hw, CS4382_MC1, &cs_read.mode_control_1))
|
|
|
continue;
|
|
@@ -1725,7 +1767,11 @@ End:
|
|
|
static int hw_is_adc_input_selected(struct hw *hw, enum ADCSRC type)
|
|
|
{
|
|
|
u32 data;
|
|
|
-
|
|
|
+ if (hw->model == CTSB1270) {
|
|
|
+ /* Titanium HD has two ADC chips, one for line in and one */
|
|
|
+ /* for MIC. We don't need to switch the ADC input. */
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
data = hw_read_20kx(hw, GPIO_DATA);
|
|
|
switch (type) {
|
|
|
case ADC_MICIN:
|
|
@@ -1742,35 +1788,47 @@ static int hw_is_adc_input_selected(struct hw *hw, enum ADCSRC type)
|
|
|
|
|
|
#define MIC_BOOST_0DB 0xCF
|
|
|
#define MIC_BOOST_STEPS_PER_DB 2
|
|
|
-#define MIC_BOOST_20DB (MIC_BOOST_0DB + 20 * MIC_BOOST_STEPS_PER_DB)
|
|
|
+
|
|
|
+static void hw_wm8775_input_select(struct hw *hw, u8 input, s8 gain_in_db)
|
|
|
+{
|
|
|
+ u32 adcmc, gain;
|
|
|
+
|
|
|
+ if (input > 3)
|
|
|
+ input = 3;
|
|
|
+
|
|
|
+ adcmc = ((u32)1 << input) | 0x100; /* Link L+R gain... */
|
|
|
+
|
|
|
+ hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_ADCMC, adcmc),
|
|
|
+ MAKE_WM8775_DATA(adcmc));
|
|
|
+
|
|
|
+ if (gain_in_db < -103)
|
|
|
+ gain_in_db = -103;
|
|
|
+ if (gain_in_db > 24)
|
|
|
+ gain_in_db = 24;
|
|
|
+
|
|
|
+ gain = gain_in_db * MIC_BOOST_STEPS_PER_DB + MIC_BOOST_0DB;
|
|
|
+
|
|
|
+ hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_AADCL, gain),
|
|
|
+ MAKE_WM8775_DATA(gain));
|
|
|
+ /* ...so there should be no need for the following. */
|
|
|
+ hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_AADCR, gain),
|
|
|
+ MAKE_WM8775_DATA(gain));
|
|
|
+}
|
|
|
|
|
|
static int hw_adc_input_select(struct hw *hw, enum ADCSRC type)
|
|
|
{
|
|
|
u32 data;
|
|
|
-
|
|
|
data = hw_read_20kx(hw, GPIO_DATA);
|
|
|
switch (type) {
|
|
|
case ADC_MICIN:
|
|
|
data |= (0x1 << 14);
|
|
|
hw_write_20kx(hw, GPIO_DATA, data);
|
|
|
- hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_ADCMC, 0x101),
|
|
|
- MAKE_WM8775_DATA(0x101)); /* Mic-in */
|
|
|
- hw20k2_i2c_write(hw,
|
|
|
- MAKE_WM8775_ADDR(WM8775_AADCL, MIC_BOOST_20DB),
|
|
|
- MAKE_WM8775_DATA(MIC_BOOST_20DB)); /* +20dB */
|
|
|
- hw20k2_i2c_write(hw,
|
|
|
- MAKE_WM8775_ADDR(WM8775_AADCR, MIC_BOOST_20DB),
|
|
|
- MAKE_WM8775_DATA(MIC_BOOST_20DB)); /* +20dB */
|
|
|
+ hw_wm8775_input_select(hw, 0, 20); /* Mic, 20dB */
|
|
|
break;
|
|
|
case ADC_LINEIN:
|
|
|
data &= ~(0x1 << 14);
|
|
|
hw_write_20kx(hw, GPIO_DATA, data);
|
|
|
- hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_ADCMC, 0x102),
|
|
|
- MAKE_WM8775_DATA(0x102)); /* Line-in */
|
|
|
- hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_AADCL, 0xCF),
|
|
|
- MAKE_WM8775_DATA(0xCF)); /* No boost */
|
|
|
- hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_AADCR, 0xCF),
|
|
|
- MAKE_WM8775_DATA(0xCF)); /* No boost */
|
|
|
+ hw_wm8775_input_select(hw, 1, 0); /* Line-in, 0dB */
|
|
|
break;
|
|
|
default:
|
|
|
break;
|
|
@@ -1782,7 +1840,7 @@ static int hw_adc_input_select(struct hw *hw, enum ADCSRC type)
|
|
|
static int hw_adc_init(struct hw *hw, const struct adc_conf *info)
|
|
|
{
|
|
|
int err;
|
|
|
- u32 mux = 2, data, ctl;
|
|
|
+ u32 data, ctl;
|
|
|
|
|
|
/* Set ADC reset bit as output */
|
|
|
data = hw_read_20kx(hw, GPIO_CTRL);
|
|
@@ -1796,19 +1854,42 @@ static int hw_adc_init(struct hw *hw, const struct adc_conf *info)
|
|
|
goto error;
|
|
|
}
|
|
|
|
|
|
- /* Make ADC in normal operation */
|
|
|
+ /* Reset the ADC (reset is active low). */
|
|
|
data = hw_read_20kx(hw, GPIO_DATA);
|
|
|
data &= ~(0x1 << 15);
|
|
|
+ hw_write_20kx(hw, GPIO_DATA, data);
|
|
|
+
|
|
|
+ if (hw->model == CTSB1270) {
|
|
|
+ /* Set up the PCM4220 ADC on Titanium HD */
|
|
|
+ data &= ~0x0C;
|
|
|
+ if (1 == info->msr)
|
|
|
+ data |= 0x00; /* Single Speed Mode 32-50kHz */
|
|
|
+ else if (2 == info->msr)
|
|
|
+ data |= 0x08; /* Double Speed Mode 50-108kHz */
|
|
|
+ else
|
|
|
+ data |= 0x04; /* Quad Speed Mode 108kHz-216kHz */
|
|
|
+ hw_write_20kx(hw, GPIO_DATA, data);
|
|
|
+ }
|
|
|
+
|
|
|
mdelay(10);
|
|
|
+ /* Return the ADC to normal operation. */
|
|
|
data |= (0x1 << 15);
|
|
|
hw_write_20kx(hw, GPIO_DATA, data);
|
|
|
mdelay(50);
|
|
|
|
|
|
+ /* I2C write to register offset 0x0B to set ADC LRCLK polarity */
|
|
|
+ /* invert bit, interface format to I2S, word length to 24-bit, */
|
|
|
+ /* enable ADC high pass filter. Fixes bug 5323? */
|
|
|
+ hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_IC, 0x26),
|
|
|
+ MAKE_WM8775_DATA(0x26));
|
|
|
+
|
|
|
/* Set the master mode (256fs) */
|
|
|
if (1 == info->msr) {
|
|
|
+ /* slave mode, 128x oversampling 256fs */
|
|
|
hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_MMC, 0x02),
|
|
|
MAKE_WM8775_DATA(0x02));
|
|
|
- } else if (2 == info->msr) {
|
|
|
+ } else if ((2 == info->msr) || (4 == info->msr)) {
|
|
|
+ /* slave mode, 64x oversampling, 256fs */
|
|
|
hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_MMC, 0x0A),
|
|
|
MAKE_WM8775_DATA(0x0A));
|
|
|
} else {
|
|
@@ -1818,47 +1899,17 @@ static int hw_adc_init(struct hw *hw, const struct adc_conf *info)
|
|
|
goto error;
|
|
|
}
|
|
|
|
|
|
- /* Configure GPIO bit 14 change to line-in/mic-in */
|
|
|
- ctl = hw_read_20kx(hw, GPIO_CTRL);
|
|
|
- ctl |= 0x1 << 14;
|
|
|
- hw_write_20kx(hw, GPIO_CTRL, ctl);
|
|
|
-
|
|
|
- /* Check using Mic-in or Line-in */
|
|
|
- data = hw_read_20kx(hw, GPIO_DATA);
|
|
|
-
|
|
|
- if (mux == 1) {
|
|
|
- /* Configures GPIO data to select Mic-in */
|
|
|
- data |= 0x1 << 14;
|
|
|
- hw_write_20kx(hw, GPIO_DATA, data);
|
|
|
-
|
|
|
- hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_ADCMC, 0x101),
|
|
|
- MAKE_WM8775_DATA(0x101)); /* Mic-in */
|
|
|
- hw20k2_i2c_write(hw,
|
|
|
- MAKE_WM8775_ADDR(WM8775_AADCL, MIC_BOOST_20DB),
|
|
|
- MAKE_WM8775_DATA(MIC_BOOST_20DB)); /* +20dB */
|
|
|
- hw20k2_i2c_write(hw,
|
|
|
- MAKE_WM8775_ADDR(WM8775_AADCR, MIC_BOOST_20DB),
|
|
|
- MAKE_WM8775_DATA(MIC_BOOST_20DB)); /* +20dB */
|
|
|
- } else if (mux == 2) {
|
|
|
- /* Configures GPIO data to select Line-in */
|
|
|
- data &= ~(0x1 << 14);
|
|
|
- hw_write_20kx(hw, GPIO_DATA, data);
|
|
|
-
|
|
|
- /* Setup ADC */
|
|
|
- hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_ADCMC, 0x102),
|
|
|
- MAKE_WM8775_DATA(0x102)); /* Line-in */
|
|
|
- hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_AADCL, 0xCF),
|
|
|
- MAKE_WM8775_DATA(0xCF)); /* No boost */
|
|
|
- hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_AADCR, 0xCF),
|
|
|
- MAKE_WM8775_DATA(0xCF)); /* No boost */
|
|
|
+ if (hw->model != CTSB1270) {
|
|
|
+ /* Configure GPIO bit 14 change to line-in/mic-in */
|
|
|
+ ctl = hw_read_20kx(hw, GPIO_CTRL);
|
|
|
+ ctl |= 0x1 << 14;
|
|
|
+ hw_write_20kx(hw, GPIO_CTRL, ctl);
|
|
|
+ hw_adc_input_select(hw, ADC_LINEIN);
|
|
|
} else {
|
|
|
- printk(KERN_ALERT "ctxfi: ERROR!!! Invalid input mux!!!\n");
|
|
|
- err = -EINVAL;
|
|
|
- goto error;
|
|
|
+ hw_wm8775_input_select(hw, 0, 0);
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
|
-
|
|
|
error:
|
|
|
hw20k2_i2c_uninit(hw);
|
|
|
return err;
|
|
@@ -1869,6 +1920,102 @@ static int hw_have_digit_io_switch(struct hw *hw)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static int hw_have_dedicated_mic(struct hw *hw)
|
|
|
+{
|
|
|
+ return hw->model == CTSB1270;
|
|
|
+}
|
|
|
+
|
|
|
+static int hw_have_output_switch(struct hw *hw)
|
|
|
+{
|
|
|
+ return hw->model == CTSB1270;
|
|
|
+}
|
|
|
+
|
|
|
+static int hw_output_switch_get(struct hw *hw)
|
|
|
+{
|
|
|
+ u32 data = hw_read_20kx(hw, GPIO_EXT_DATA);
|
|
|
+
|
|
|
+ switch (data & 0x30) {
|
|
|
+ case 0x00:
|
|
|
+ return 0;
|
|
|
+ case 0x10:
|
|
|
+ return 1;
|
|
|
+ case 0x20:
|
|
|
+ return 2;
|
|
|
+ default:
|
|
|
+ return 3;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static int hw_output_switch_put(struct hw *hw, int position)
|
|
|
+{
|
|
|
+ u32 data;
|
|
|
+
|
|
|
+ if (position == hw_output_switch_get(hw))
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ /* Mute line and headphones (intended for anti-pop). */
|
|
|
+ data = hw_read_20kx(hw, GPIO_DATA);
|
|
|
+ data |= (0x03 << 11);
|
|
|
+ hw_write_20kx(hw, GPIO_DATA, data);
|
|
|
+
|
|
|
+ data = hw_read_20kx(hw, GPIO_EXT_DATA) & ~0x30;
|
|
|
+ switch (position) {
|
|
|
+ case 0:
|
|
|
+ break;
|
|
|
+ case 1:
|
|
|
+ data |= 0x10;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ data |= 0x20;
|
|
|
+ }
|
|
|
+ hw_write_20kx(hw, GPIO_EXT_DATA, data);
|
|
|
+
|
|
|
+ /* Unmute line and headphones. */
|
|
|
+ data = hw_read_20kx(hw, GPIO_DATA);
|
|
|
+ data &= ~(0x03 << 11);
|
|
|
+ hw_write_20kx(hw, GPIO_DATA, data);
|
|
|
+
|
|
|
+ return 1;
|
|
|
+}
|
|
|
+
|
|
|
+static int hw_have_mic_source_switch(struct hw *hw)
|
|
|
+{
|
|
|
+ return hw->model == CTSB1270;
|
|
|
+}
|
|
|
+
|
|
|
+static int hw_mic_source_switch_get(struct hw *hw)
|
|
|
+{
|
|
|
+ struct hw20k2 *hw20k2 = (struct hw20k2 *)hw;
|
|
|
+
|
|
|
+ return hw20k2->mic_source;
|
|
|
+}
|
|
|
+
|
|
|
+static int hw_mic_source_switch_put(struct hw *hw, int position)
|
|
|
+{
|
|
|
+ struct hw20k2 *hw20k2 = (struct hw20k2 *)hw;
|
|
|
+
|
|
|
+ if (position == hw20k2->mic_source)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ switch (position) {
|
|
|
+ case 0:
|
|
|
+ hw_wm8775_input_select(hw, 0, 0); /* Mic, 0dB */
|
|
|
+ break;
|
|
|
+ case 1:
|
|
|
+ hw_wm8775_input_select(hw, 1, 0); /* FP Mic, 0dB */
|
|
|
+ break;
|
|
|
+ case 2:
|
|
|
+ hw_wm8775_input_select(hw, 3, 0); /* Aux Ext, 0dB */
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ hw20k2->mic_source = position;
|
|
|
+
|
|
|
+ return 1;
|
|
|
+}
|
|
|
+
|
|
|
static irqreturn_t ct_20k2_interrupt(int irq, void *dev_id)
|
|
|
{
|
|
|
struct hw *hw = dev_id;
|
|
@@ -2023,13 +2170,16 @@ static int hw_card_init(struct hw *hw, struct card_conf *info)
|
|
|
/* Reset all SRC pending interrupts */
|
|
|
hw_write_20kx(hw, SRC_IP, 0);
|
|
|
|
|
|
- /* TODO: detect the card ID and configure GPIO accordingly. */
|
|
|
- /* Configures GPIO (0xD802 0x98028) */
|
|
|
- /*hw_write_20kx(hw, GPIO_CTRL, 0x7F07);*/
|
|
|
- /* Configures GPIO (SB0880) */
|
|
|
- /*hw_write_20kx(hw, GPIO_CTRL, 0xFF07);*/
|
|
|
- hw_write_20kx(hw, GPIO_CTRL, 0xD802);
|
|
|
-
|
|
|
+ if (hw->model != CTSB1270) {
|
|
|
+ /* TODO: detect the card ID and configure GPIO accordingly. */
|
|
|
+ /* Configures GPIO (0xD802 0x98028) */
|
|
|
+ /*hw_write_20kx(hw, GPIO_CTRL, 0x7F07);*/
|
|
|
+ /* Configures GPIO (SB0880) */
|
|
|
+ /*hw_write_20kx(hw, GPIO_CTRL, 0xFF07);*/
|
|
|
+ hw_write_20kx(hw, GPIO_CTRL, 0xD802);
|
|
|
+ } else {
|
|
|
+ hw_write_20kx(hw, GPIO_CTRL, 0x9E5F);
|
|
|
+ }
|
|
|
/* Enable audio ring */
|
|
|
hw_write_20kx(hw, MIXER_AR_ENABLE, 0x01);
|
|
|
|
|
@@ -2107,6 +2257,13 @@ static struct hw ct20k2_preset __devinitdata = {
|
|
|
.is_adc_source_selected = hw_is_adc_input_selected,
|
|
|
.select_adc_source = hw_adc_input_select,
|
|
|
.have_digit_io_switch = hw_have_digit_io_switch,
|
|
|
+ .have_dedicated_mic = hw_have_dedicated_mic,
|
|
|
+ .have_output_switch = hw_have_output_switch,
|
|
|
+ .output_switch_get = hw_output_switch_get,
|
|
|
+ .output_switch_put = hw_output_switch_put,
|
|
|
+ .have_mic_source_switch = hw_have_mic_source_switch,
|
|
|
+ .mic_source_switch_get = hw_mic_source_switch_get,
|
|
|
+ .mic_source_switch_put = hw_mic_source_switch_put,
|
|
|
#ifdef CONFIG_PM
|
|
|
.suspend = hw_suspend,
|
|
|
.resume = hw_resume,
|