summaryrefslogtreecommitdiffstats
path: root/sound/pci/ice1712/ice1724.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/ice1712/ice1724.c')
-rw-r--r--sound/pci/ice1712/ice1724.c431
1 files changed, 247 insertions, 184 deletions
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c
index f533850ec6e..4490422fb93 100644
--- a/sound/pci/ice1712/ice1724.c
+++ b/sound/pci/ice1712/ice1724.c
@@ -106,15 +106,19 @@ static unsigned int PRO_RATE_DEFAULT = 44100;
* Basic I/O
*/
+/*
+ * default rates, default clock routines
+ */
+
/* check whether the clock mode is spdif-in */
-static inline int is_spdif_master(struct snd_ice1712 *ice)
+static inline int stdclock_is_spdif_master(struct snd_ice1712 *ice)
{
return (inb(ICEMT1724(ice, RATE)) & VT1724_SPDIF_MASTER) ? 1 : 0;
}
static inline int is_pro_rate_locked(struct snd_ice1712 *ice)
{
- return is_spdif_master(ice) || PRO_RATE_LOCKED;
+ return ice->is_spdif_master(ice) || PRO_RATE_LOCKED;
}
/*
@@ -219,6 +223,32 @@ static unsigned int snd_vt1724_get_gpio_data(struct snd_ice1712 *ice)
}
/*
+ * MPU401 accessor
+ */
+static unsigned char snd_vt1724_mpu401_read(struct snd_mpu401 *mpu,
+ unsigned long addr)
+{
+ /* fix status bits to the standard position */
+ /* only RX_EMPTY and TX_FULL are checked */
+ if (addr == MPU401C(mpu))
+ return (inb(addr) & 0x0c) << 4;
+ else
+ return inb(addr);
+}
+
+static void snd_vt1724_mpu401_write(struct snd_mpu401 *mpu,
+ unsigned char data, unsigned long addr)
+{
+ if (addr == MPU401C(mpu)) {
+ if (data == MPU401_ENTER_UART)
+ outb(0x01, addr);
+ /* what else? */
+ } else
+ outb(data, addr);
+}
+
+
+/*
* Interrupt handler
*/
@@ -226,24 +256,53 @@ static irqreturn_t snd_vt1724_interrupt(int irq, void *dev_id)
{
struct snd_ice1712 *ice = dev_id;
unsigned char status;
+ unsigned char status_mask =
+ VT1724_IRQ_MPU_RX | VT1724_IRQ_MPU_TX | VT1724_IRQ_MTPCM;
int handled = 0;
+#ifdef CONFIG_SND_DEBUG
+ int timeout = 0;
+#endif
while (1) {
status = inb(ICEREG1724(ice, IRQSTAT));
+ status &= status_mask;
if (status == 0)
break;
-
+#ifdef CONFIG_SND_DEBUG
+ if (++timeout > 10) {
+ printk(KERN_ERR
+ "ice1724: Too long irq loop, status = 0x%x\n",
+ status);
+ break;
+ }
+#endif
handled = 1;
- /* these should probably be separated at some point,
- * but as we don't currently have MPU support on the board
- * I will leave it
- */
- if ((status & VT1724_IRQ_MPU_RX)||(status & VT1724_IRQ_MPU_TX)) {
+ if (status & VT1724_IRQ_MPU_TX) {
+ if (ice->rmidi[0])
+ snd_mpu401_uart_interrupt_tx(irq,
+ ice->rmidi[0]->private_data);
+ else /* disable TX to be sure */
+ outb(inb(ICEREG1724(ice, IRQMASK)) |
+ VT1724_IRQ_MPU_TX,
+ ICEREG1724(ice, IRQMASK));
+ /* Due to mysterical reasons, MPU_TX is always
+ * generated (and can't be cleared) when a PCM
+ * playback is going. So let's ignore at the
+ * next loop.
+ */
+ status_mask &= ~VT1724_IRQ_MPU_TX;
+ }
+ if (status & VT1724_IRQ_MPU_RX) {
if (ice->rmidi[0])
- snd_mpu401_uart_interrupt(irq, ice->rmidi[0]->private_data);
- outb(status & (VT1724_IRQ_MPU_RX|VT1724_IRQ_MPU_TX), ICEREG1724(ice, IRQSTAT));
- status &= ~(VT1724_IRQ_MPU_RX|VT1724_IRQ_MPU_TX);
+ snd_mpu401_uart_interrupt(irq,
+ ice->rmidi[0]->private_data);
+ else /* disable RX to be sure */
+ outb(inb(ICEREG1724(ice, IRQMASK)) |
+ VT1724_IRQ_MPU_RX,
+ ICEREG1724(ice, IRQMASK));
}
+ /* ack MPU irq */
+ outb(status, ICEREG1724(ice, IRQSTAT));
if (status & VT1724_IRQ_MTPCM) {
/*
* Multi-track PCM
@@ -391,51 +450,61 @@ static int snd_vt1724_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
#define DMA_PAUSES (VT1724_RDMA0_PAUSE|VT1724_PDMA0_PAUSE|VT1724_RDMA1_PAUSE|\
VT1724_PDMA1_PAUSE|VT1724_PDMA2_PAUSE|VT1724_PDMA3_PAUSE|VT1724_PDMA4_PAUSE)
-static int get_max_rate(struct snd_ice1712 *ice)
+static const unsigned int stdclock_rate_list[16] = {
+ 48000, 24000, 12000, 9600, 32000, 16000, 8000, 96000, 44100,
+ 22050, 11025, 88200, 176400, 0, 192000, 64000
+};
+
+static unsigned int stdclock_get_rate(struct snd_ice1712 *ice)
{
+ unsigned int rate;
+ rate = stdclock_rate_list[inb(ICEMT1724(ice, RATE)) & 15];
+ return rate;
+}
+
+static void stdclock_set_rate(struct snd_ice1712 *ice, unsigned int rate)
+{
+ int i;
+ for (i = 0; i < ARRAY_SIZE(stdclock_rate_list); i++) {
+ if (stdclock_rate_list[i] == rate) {
+ outb(i, ICEMT1724(ice, RATE));
+ return;
+ }
+ }
+}
+
+static unsigned char stdclock_set_mclk(struct snd_ice1712 *ice,
+ unsigned int rate)
+{
+ unsigned char val, old;
+ /* check MT02 */
if (ice->eeprom.data[ICE_EEP2_ACLINK] & VT1724_CFG_PRO_I2S) {
- if ((ice->eeprom.data[ICE_EEP2_I2S] & 0x08) && !ice->vt1720)
- return 192000;
+ val = old = inb(ICEMT1724(ice, I2S_FORMAT));
+ if (rate > 96000)
+ val |= VT1724_MT_I2S_MCLK_128X; /* 128x MCLK */
else
- return 96000;
- } else
- return 48000;
+ val &= ~VT1724_MT_I2S_MCLK_128X; /* 256x MCLK */
+ if (val != old) {
+ outb(val, ICEMT1724(ice, I2S_FORMAT));
+ /* master clock changed */
+ return 1;
+ }
+ }
+ /* no change in master clock */
+ return 0;
}
static void snd_vt1724_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate,
int force)
{
unsigned long flags;
- unsigned char val, old;
- unsigned int i, mclk_change;
+ unsigned char mclk_change;
+ unsigned int i, old_rate;
- if (rate > get_max_rate(ice))
+ if (rate > ice->hw_rates->list[ice->hw_rates->count - 1])
return;
-
- switch (rate) {
- case 8000: val = 6; break;
- case 9600: val = 3; break;
- case 11025: val = 10; break;
- case 12000: val = 2; break;
- case 16000: val = 5; break;
- case 22050: val = 9; break;
- case 24000: val = 1; break;
- case 32000: val = 4; break;
- case 44100: val = 8; break;
- case 48000: val = 0; break;
- case 64000: val = 15; break;
- case 88200: val = 11; break;
- case 96000: val = 7; break;
- case 176400: val = 12; break;
- case 192000: val = 14; break;
- default:
- snd_BUG();
- val = 0;
- break;
- }
-
spin_lock_irqsave(&ice->reg_lock, flags);
- if ((inb(ICEMT1724(ice, DMA_CONTROL)) & DMA_STARTS) ||
+ if ((inb(ICEMT1724(ice, DMA_CONTROL)) & DMA_STARTS) ||
(inb(ICEMT1724(ice, DMA_PAUSE)) & DMA_PAUSES)) {
/* running? we cannot change the rate now... */
spin_unlock_irqrestore(&ice->reg_lock, flags);
@@ -446,9 +515,9 @@ static void snd_vt1724_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate,
return;
}
- old = inb(ICEMT1724(ice, RATE));
- if (force || old != val)
- outb(val, ICEMT1724(ice, RATE));
+ old_rate = ice->get_rate(ice);
+ if (force || (old_rate != rate))
+ ice->set_rate(ice, rate);
else if (rate == ice->cur_rate) {
spin_unlock_irqrestore(&ice->reg_lock, flags);
return;
@@ -456,19 +525,9 @@ static void snd_vt1724_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate,
ice->cur_rate = rate;
- /* check MT02 */
- mclk_change = 0;
- if (ice->eeprom.data[ICE_EEP2_ACLINK] & VT1724_CFG_PRO_I2S) {
- val = old = inb(ICEMT1724(ice, I2S_FORMAT));
- if (rate > 96000)
- val |= VT1724_MT_I2S_MCLK_128X; /* 128x MCLK */
- else
- val &= ~VT1724_MT_I2S_MCLK_128X; /* 256x MCLK */
- if (val != old) {
- outb(val, ICEMT1724(ice, I2S_FORMAT));
- mclk_change = 1;
- }
- }
+ /* setting master clock */
+ mclk_change = ice->set_mclk(ice, rate);
+
spin_unlock_irqrestore(&ice->reg_lock, flags);
if (mclk_change && ice->gpio.i2s_mclk_changed)
@@ -727,43 +786,32 @@ static const struct snd_pcm_hardware snd_vt1724_2ch_stereo =
/*
* set rate constraints
*/
-static int set_rate_constraints(struct snd_ice1712 *ice,
- struct snd_pcm_substream *substream)
+static void set_std_hw_rates(struct snd_ice1712 *ice)
{
- struct snd_pcm_runtime *runtime = substream->runtime;
- if (ice->hw_rates) {
- /* hardware specific */
- runtime->hw.rate_min = ice->hw_rates->list[0];
- runtime->hw.rate_max = ice->hw_rates->list[ice->hw_rates->count - 1];
- runtime->hw.rates = SNDRV_PCM_RATE_KNOT;
- return snd_pcm_hw_constraint_list(runtime, 0,
- SNDRV_PCM_HW_PARAM_RATE,
- ice->hw_rates);
- }
if (ice->eeprom.data[ICE_EEP2_ACLINK] & VT1724_CFG_PRO_I2S) {
/* I2S */
/* VT1720 doesn't support more than 96kHz */
if ((ice->eeprom.data[ICE_EEP2_I2S] & 0x08) && !ice->vt1720)
- return snd_pcm_hw_constraint_list(runtime, 0,
- SNDRV_PCM_HW_PARAM_RATE,
- &hw_constraints_rates_192);
- else {
- runtime->hw.rates = SNDRV_PCM_RATE_KNOT |
- SNDRV_PCM_RATE_8000_96000;
- runtime->hw.rate_max = 96000;
- return snd_pcm_hw_constraint_list(runtime, 0,
- SNDRV_PCM_HW_PARAM_RATE,
- &hw_constraints_rates_96);
- }
- } else if (ice->ac97) {
+ ice->hw_rates = &hw_constraints_rates_192;
+ else
+ ice->hw_rates = &hw_constraints_rates_96;
+ } else {
/* ACLINK */
- runtime->hw.rate_max = 48000;
- runtime->hw.rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000;
- return snd_pcm_hw_constraint_list(runtime, 0,
- SNDRV_PCM_HW_PARAM_RATE,
- &hw_constraints_rates_48);
+ ice->hw_rates = &hw_constraints_rates_48;
}
- return 0;
+}
+
+static int set_rate_constraints(struct snd_ice1712 *ice,
+ struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+
+ runtime->hw.rate_min = ice->hw_rates->list[0];
+ runtime->hw.rate_max = ice->hw_rates->list[ice->hw_rates->count - 1];
+ runtime->hw.rates = SNDRV_PCM_RATE_KNOT;
+ return snd_pcm_hw_constraint_list(runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE,
+ ice->hw_rates);
}
/* multi-channel playback needs alignment 8x32bit regardless of the channels
@@ -824,7 +872,7 @@ static int snd_vt1724_playback_pro_close(struct snd_pcm_substream *substream)
struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
if (PRO_RATE_RESET)
- snd_vt1724_set_pro_rate(ice, PRO_RATE_DEFAULT, 0);
+ snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 0);
ice->playback_pro_substream = NULL;
return 0;
@@ -835,7 +883,7 @@ static int snd_vt1724_capture_pro_close(struct snd_pcm_substream *substream)
struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
if (PRO_RATE_RESET)
- snd_vt1724_set_pro_rate(ice, PRO_RATE_DEFAULT, 0);
+ snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 0);
ice->capture_pro_substream = NULL;
return 0;
}
@@ -970,6 +1018,8 @@ static int snd_vt1724_playback_spdif_open(struct snd_pcm_substream *substream)
VT1724_BUFFER_ALIGN);
snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
VT1724_BUFFER_ALIGN);
+ if (ice->spdif.ops.open)
+ ice->spdif.ops.open(ice, substream);
return 0;
}
@@ -978,8 +1028,10 @@ static int snd_vt1724_playback_spdif_close(struct snd_pcm_substream *substream)
struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
if (PRO_RATE_RESET)
- snd_vt1724_set_pro_rate(ice, PRO_RATE_DEFAULT, 0);
+ snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 0);
ice->playback_con_substream = NULL;
+ if (ice->spdif.ops.close)
+ ice->spdif.ops.close(ice, substream);
return 0;
}
@@ -1002,6 +1054,8 @@ static int snd_vt1724_capture_spdif_open(struct snd_pcm_substream *substream)
VT1724_BUFFER_ALIGN);
snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
VT1724_BUFFER_ALIGN);
+ if (ice->spdif.ops.open)
+ ice->spdif.ops.open(ice, substream);
return 0;
}
@@ -1010,8 +1064,10 @@ static int snd_vt1724_capture_spdif_close(struct snd_pcm_substream *substream)
struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
if (PRO_RATE_RESET)
- snd_vt1724_set_pro_rate(ice, PRO_RATE_DEFAULT, 0);
+ snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 0);
ice->capture_con_substream = NULL;
+ if (ice->spdif.ops.close)
+ ice->spdif.ops.close(ice, substream);
return 0;
}
@@ -1154,7 +1210,7 @@ static int snd_vt1724_playback_indep_close(struct snd_pcm_substream *substream)
struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
if (PRO_RATE_RESET)
- snd_vt1724_set_pro_rate(ice, PRO_RATE_DEFAULT, 0);
+ snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 0);
ice->playback_con_substream_ds[substream->number] = NULL;
ice->pcm_reserved[substream->number] = NULL;
@@ -1572,50 +1628,18 @@ int snd_ice1712_gpio_put(struct snd_kcontrol *kcontrol,
static int snd_vt1724_pro_internal_clock_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
- static const char * const texts_1724[] = {
- "8000", /* 0: 6 */
- "9600", /* 1: 3 */
- "11025", /* 2: 10 */
- "12000", /* 3: 2 */
- "16000", /* 4: 5 */
- "22050", /* 5: 9 */
- "24000", /* 6: 1 */
- "32000", /* 7: 4 */
- "44100", /* 8: 8 */
- "48000", /* 9: 0 */
- "64000", /* 10: 15 */
- "88200", /* 11: 11 */
- "96000", /* 12: 7 */
- "176400", /* 13: 12 */
- "192000", /* 14: 14 */
- "IEC958 Input", /* 15: -- */
- };
- static const char * const texts_1720[] = {
- "8000", /* 0: 6 */
- "9600", /* 1: 3 */
- "11025", /* 2: 10 */
- "12000", /* 3: 2 */
- "16000", /* 4: 5 */
- "22050", /* 5: 9 */
- "24000", /* 6: 1 */
- "32000", /* 7: 4 */
- "44100", /* 8: 8 */
- "48000", /* 9: 0 */
- "64000", /* 10: 15 */
- "88200", /* 11: 11 */
- "96000", /* 12: 7 */
- "IEC958 Input", /* 13: -- */
- };
struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
- uinfo->value.enumerated.items = ice->vt1720 ? 14 : 16;
+ uinfo->value.enumerated.items = ice->hw_rates->count + 1;
if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
- strcpy(uinfo->value.enumerated.name,
- ice->vt1720 ? texts_1720[uinfo->value.enumerated.item] :
- texts_1724[uinfo->value.enumerated.item]);
+ if (uinfo->value.enumerated.item == uinfo->value.enumerated.items - 1)
+ strcpy(uinfo->value.enumerated.name, "IEC958 Input");
+ else
+ sprintf(uinfo->value.enumerated.name, "%d",
+ ice->hw_rates->list[uinfo->value.enumerated.item]);
return 0;
}
@@ -1623,68 +1647,79 @@ static int snd_vt1724_pro_internal_clock_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
- static const unsigned char xlate[16] = {
- 9, 6, 3, 1, 7, 4, 0, 12, 8, 5, 2, 11, 13, 255, 14, 10
- };
- unsigned char val;
+ unsigned int i, rate;
spin_lock_irq(&ice->reg_lock);
- if (is_spdif_master(ice)) {
- ucontrol->value.enumerated.item[0] = ice->vt1720 ? 13 : 15;
+ if (ice->is_spdif_master(ice)) {
+ ucontrol->value.enumerated.item[0] = ice->hw_rates->count;
} else {
- val = xlate[inb(ICEMT1724(ice, RATE)) & 15];
- if (val == 255) {
- snd_BUG();
- val = 0;
+ rate = ice->get_rate(ice);
+ ucontrol->value.enumerated.item[0] = 0;
+ for (i = 0; i < ice->hw_rates->count; i++) {
+ if (ice->hw_rates->list[i] == rate) {
+ ucontrol->value.enumerated.item[0] = i;
+ break;
+ }
}
- ucontrol->value.enumerated.item[0] = val;
}
spin_unlock_irq(&ice->reg_lock);
return 0;
}
+/* setting clock to external - SPDIF */
+static void stdclock_set_spdif_clock(struct snd_ice1712 *ice)
+{
+ unsigned char oval;
+ unsigned char i2s_oval;
+ oval = inb(ICEMT1724(ice, RATE));
+ outb(oval | VT1724_SPDIF_MASTER, ICEMT1724(ice, RATE));
+ /* setting 256fs */
+ i2s_oval = inb(ICEMT1724(ice, I2S_FORMAT));
+ outb(i2s_oval & ~VT1724_MT_I2S_MCLK_128X, ICEMT1724(ice, I2S_FORMAT));
+}
+
static int snd_vt1724_pro_internal_clock_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
- unsigned char oval;
- int rate;
- int change = 0;
- int spdif = ice->vt1720 ? 13 : 15;
+ unsigned int old_rate, new_rate;
+ unsigned int item = ucontrol->value.enumerated.item[0];
+ unsigned int spdif = ice->hw_rates->count;
+
+ if (item > spdif)
+ return -EINVAL;
spin_lock_irq(&ice->reg_lock);
- oval = inb(ICEMT1724(ice, RATE));
- if (ucontrol->value.enumerated.item[0] == spdif) {
- unsigned char i2s_oval;
- outb(oval | VT1724_SPDIF_MASTER, ICEMT1724(ice, RATE));
- /* setting 256fs */
- i2s_oval = inb(ICEMT1724(ice, I2S_FORMAT));
- outb(i2s_oval & ~VT1724_MT_I2S_MCLK_128X,
- ICEMT1724(ice, I2S_FORMAT));
+ if (ice->is_spdif_master(ice))
+ old_rate = 0;
+ else
+ old_rate = ice->get_rate(ice);
+ if (item == spdif) {
+ /* switching to external clock via SPDIF */
+ ice->set_spdif_clock(ice);
+ new_rate = 0;
} else {
- rate = rates[ucontrol->value.integer.value[0] % 15];
- if (rate <= get_max_rate(ice)) {
- PRO_RATE_DEFAULT = rate;
- spin_unlock_irq(&ice->reg_lock);
- snd_vt1724_set_pro_rate(ice, PRO_RATE_DEFAULT, 1);
- spin_lock_irq(&ice->reg_lock);
- }
+ /* internal on-card clock */
+ new_rate = ice->hw_rates->list[item];
+ ice->pro_rate_default = new_rate;
+ spin_unlock_irq(&ice->reg_lock);
+ snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 1);
+ spin_lock_irq(&ice->reg_lock);
}
- change = inb(ICEMT1724(ice, RATE)) != oval;
spin_unlock_irq(&ice->reg_lock);
- if ((oval & VT1724_SPDIF_MASTER) !=
- (inb(ICEMT1724(ice, RATE)) & VT1724_SPDIF_MASTER)) {
+ /* the first reset to the SPDIF master mode? */
+ if (old_rate != new_rate && !new_rate) {
/* notify akm chips as well */
- if (is_spdif_master(ice)) {
- unsigned int i;
- for (i = 0; i < ice->akm_codecs; i++) {
- if (ice->akm[i].ops.set_rate_val)
- ice->akm[i].ops.set_rate_val(&ice->akm[i], 0);
- }
+ unsigned int i;
+ if (ice->gpio.set_pro_rate)
+ ice->gpio.set_pro_rate(ice, 0);
+ for (i = 0; i < ice->akm_codecs; i++) {
+ if (ice->akm[i].ops.set_rate_val)
+ ice->akm[i].ops.set_rate_val(&ice->akm[i], 0);
}
}
- return change;
+ return old_rate != new_rate;
}
static struct snd_kcontrol_new snd_vt1724_pro_internal_clock __devinitdata = {
@@ -2065,12 +2100,16 @@ static int __devinit snd_vt1724_read_eeprom(struct snd_ice1712 *ice,
-static int __devinit snd_vt1724_chip_init(struct snd_ice1712 *ice)
+static void __devinit snd_vt1724_chip_reset(struct snd_ice1712 *ice)
{
outb(VT1724_RESET , ICEREG1724(ice, CONTROL));
- udelay(200);
+ msleep(10);
outb(0, ICEREG1724(ice, CONTROL));
- udelay(200);
+ msleep(10);
+}
+
+static int __devinit snd_vt1724_chip_init(struct snd_ice1712 *ice)
+{
outb(ice->eeprom.data[ICE_EEP2_SYSCONF], ICEREG1724(ice, SYS_CFG));
outb(ice->eeprom.data[ICE_EEP2_ACLINK], ICEREG1724(ice, AC97_CFG));
outb(ice->eeprom.data[ICE_EEP2_I2S], ICEREG1724(ice, I2S_FEATURES));
@@ -2169,10 +2208,8 @@ static int snd_vt1724_free(struct snd_ice1712 *ice)
outb(0xff, ICEREG1724(ice, IRQMASK));
/* --- */
__hw_end:
- if (ice->irq >= 0) {
- synchronize_irq(ice->irq);
+ if (ice->irq >= 0)
free_irq(ice->irq, ice);
- }
pci_release_regions(ice->pci);
snd_ice1712_akm4xxx_free(ice);
pci_disable_device(ice->pci);
@@ -2243,6 +2280,7 @@ static int __devinit snd_vt1724_create(struct snd_card *card,
ice->irq = pci->irq;
+ snd_vt1724_chip_reset(ice);
if (snd_vt1724_read_eeprom(ice, modelname) < 0) {
snd_vt1724_free(ice);
return -EIO;
@@ -2253,10 +2291,7 @@ static int __devinit snd_vt1724_create(struct snd_card *card,
}
/* unmask used interrupts */
- if (! (ice->eeprom.data[ICE_EEP2_SYSCONF] & VT1724_CFG_MPU401))
- mask = VT1724_IRQ_MPU_RX | VT1724_IRQ_MPU_TX;
- else
- mask = 0;
+ mask = VT1724_IRQ_MPU_RX | VT1724_IRQ_MPU_TX;
outb(mask, ICEREG1724(ice, IRQMASK));
/* don't handle FIFO overrun/underruns (just yet),
* since they cause machine lockups
@@ -2335,6 +2370,19 @@ static int __devinit snd_vt1724_probe(struct pci_dev *pci,
* was called so in ice1712 driver, and vt1724 driver is derived from
* ice1712 driver.
*/
+ ice->pro_rate_default = PRO_RATE_DEFAULT;
+ if (!ice->is_spdif_master)
+ ice->is_spdif_master = stdclock_is_spdif_master;
+ if (!ice->get_rate)
+ ice->get_rate = stdclock_get_rate;
+ if (!ice->set_rate)
+ ice->set_rate = stdclock_set_rate;
+ if (!ice->set_mclk)
+ ice->set_mclk = stdclock_set_mclk;
+ if (!ice->set_spdif_clock)
+ ice->set_spdif_clock = stdclock_set_spdif_clock;
+ if (!ice->hw_rates)
+ set_std_hw_rates(ice);
if ((err = snd_vt1724_pcm_profi(ice, pcm_dev++)) < 0) {
snd_card_free(card);
@@ -2377,14 +2425,29 @@ static int __devinit snd_vt1724_probe(struct pci_dev *pci,
if (! c->no_mpu401) {
if (ice->eeprom.data[ICE_EEP2_SYSCONF] & VT1724_CFG_MPU401) {
+ struct snd_mpu401 *mpu;
if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_ICE1712,
ICEREG1724(ice, MPU_CTRL),
- MPU401_INFO_INTEGRATED,
+ (MPU401_INFO_INTEGRATED |
+ MPU401_INFO_TX_IRQ),
ice->irq, 0,
&ice->rmidi[0])) < 0) {
snd_card_free(card);
return err;
}
+ mpu = ice->rmidi[0]->private_data;
+ mpu->read = snd_vt1724_mpu401_read;
+ mpu->write = snd_vt1724_mpu401_write;
+ /* unmask MPU RX/TX irqs */
+ outb(inb(ICEREG1724(ice, IRQMASK)) &
+ ~(VT1724_IRQ_MPU_RX | VT1724_IRQ_MPU_TX),
+ ICEREG1724(ice, IRQMASK));
+#if 0 /* for testing */
+ /* set watermarks */
+ outb(VT1724_MPU_RX_FIFO | 0x1,
+ ICEREG1724(ice, MPU_FIFO_WM));
+ outb(0x1, ICEREG1724(ice, MPU_FIFO_WM));
+#endif
}
}