summaryrefslogtreecommitdiff
path: root/sound/pci/intel8x0.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/intel8x0.c')
-rw-r--r--sound/pci/intel8x0.c788
1 files changed, 302 insertions, 486 deletions
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
index 59c8aaebb91e..3b53c5e63c29 100644
--- a/sound/pci/intel8x0.c
+++ b/sound/pci/intel8x0.c
@@ -1,32 +1,17 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* ALSA driver for Intel ICH (i8x0) chipsets
*
* Copyright (c) 2000 Jaroslav Kysela <perex@perex.cz>
*
- *
* This code also contains alpha support for SiS 735 chipsets provided
* by Mike Pieper <mptei@users.sourceforge.net>. We have no datasheet
* for SiS735, so the code is not fully functional.
*
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program 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 program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
*/
-#include <asm/io.h>
+#include <linux/io.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/init.h>
@@ -38,42 +23,10 @@
#include <sound/ac97_codec.h>
#include <sound/info.h>
#include <sound/initval.h>
-/* for 440MX workaround */
-#include <asm/pgtable.h>
-#include <asm/cacheflush.h>
-
-#ifdef CONFIG_KVM_GUEST
-#include <linux/kvm_para.h>
-#else
-#define kvm_para_available() (0)
-#endif
MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
MODULE_DESCRIPTION("Intel 82801AA,82901AB,i810,i820,i830,i840,i845,MX440; SiS 7012; Ali 5455");
MODULE_LICENSE("GPL");
-MODULE_SUPPORTED_DEVICE("{{Intel,82801AA-ICH},"
- "{Intel,82901AB-ICH0},"
- "{Intel,82801BA-ICH2},"
- "{Intel,82801CA-ICH3},"
- "{Intel,82801DB-ICH4},"
- "{Intel,ICH5},"
- "{Intel,ICH6},"
- "{Intel,ICH7},"
- "{Intel,6300ESB},"
- "{Intel,ESB2},"
- "{Intel,MX440},"
- "{SiS,SI7012},"
- "{NVidia,nForce Audio},"
- "{NVidia,nForce2 Audio},"
- "{NVidia,nForce3 Audio},"
- "{NVidia,MCP04},"
- "{NVidia,MCP501},"
- "{NVidia,CK804},"
- "{NVidia,CK8},"
- "{NVidia,CK8S},"
- "{AMD,AMD768},"
- "{AMD,AMD8111},"
- "{ALI,M5455}}");
static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */
static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */
@@ -90,7 +43,7 @@ MODULE_PARM_DESC(index, "Index value for Intel i8x0 soundcard.");
module_param(id, charp, 0444);
MODULE_PARM_DESC(id, "ID string for Intel i8x0 soundcard.");
module_param(ac97_clock, int, 0444);
-MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (0 = whitelist + auto-detect, 1 = force autodetect).");
+MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (0 = allowlist + auto-detect, 1 = force autodetect).");
module_param(ac97_quirk, charp, 0444);
MODULE_PARM_DESC(ac97_quirk, "AC'97 workaround for strange hardware.");
module_param(buggy_semaphore, bool, 0444);
@@ -126,7 +79,7 @@ enum { \
ICH_REG_##name##_PICB = base + 0x08, /* word - position in current buffer */ \
ICH_REG_##name##_PIV = base + 0x0a, /* byte - prefetched index value */ \
ICH_REG_##name##_CR = base + 0x0b, /* byte - control register */ \
-};
+}
/* busmaster blocks */
DEFINE_REGSET(OFF, 0); /* offset */
@@ -355,7 +308,7 @@ enum {
struct ichdev {
unsigned int ichd; /* ich device number */
unsigned long reg_offset; /* offset to bmaddr */
- u32 *bdbar; /* CPU address (32bit) */
+ __le32 *bdbar; /* CPU address (32bit) */
unsigned int bdbar_addr; /* PCI bus address (32bit) */
struct snd_pcm_substream *substream;
unsigned int physbuf; /* physical address (32bit) */
@@ -378,7 +331,7 @@ struct ichdev {
unsigned int ali_slot; /* ALI DMA slot */
struct ac97_pcm *pcm;
int pcm_open_flag;
- unsigned int page_attr_changed: 1;
+ unsigned int prepared:1;
unsigned int suspended: 1;
};
@@ -418,19 +371,19 @@ struct intel8x0 {
struct snd_ac97 *ac97[3];
unsigned int ac97_sdin[3];
unsigned int max_codecs, ncodecs;
- unsigned int *codec_bit;
+ const unsigned int *codec_bit;
unsigned int codec_isr_bits;
unsigned int codec_ready_bits;
spinlock_t reg_lock;
u32 bdbars_count;
- struct snd_dma_buffer bdbars;
+ struct snd_dma_buffer *bdbars;
u32 int_sta_reg; /* interrupt status register */
u32 int_sta_mask; /* interrupt status mask */
};
-static DEFINE_PCI_DEVICE_TABLE(snd_intel8x0_ids) = {
+static const struct pci_device_id snd_intel8x0_ids[] = {
{ PCI_VDEVICE(INTEL, 0x2415), DEVICE_INTEL }, /* 82801AA */
{ PCI_VDEVICE(INTEL, 0x2425), DEVICE_INTEL }, /* 82901AB */
{ PCI_VDEVICE(INTEL, 0x2445), DEVICE_INTEL }, /* 82801BA */
@@ -547,7 +500,8 @@ static int snd_intel8x0_codec_semaphore(struct intel8x0 *chip, unsigned int code
/* access to some forbidden (non existent) ac97 registers will not
* reset the semaphore. So even if you don't get the semaphore, still
* continue the access. We don't need the semaphore anyway. */
- snd_printk(KERN_ERR "codec_semaphore: semaphore is not ready [0x%x][0x%x]\n",
+ dev_err(chip->card->dev,
+ "codec_semaphore: semaphore is not ready [0x%x][0x%x]\n",
igetbyte(chip, ICHREG(ACC_SEMA)), igetdword(chip, ICHREG(GLOB_STA)));
iagetword(chip, 0); /* clear semaphore flag */
/* I don't care about the semaphore */
@@ -562,7 +516,9 @@ static void snd_intel8x0_codec_write(struct snd_ac97 *ac97,
if (snd_intel8x0_codec_semaphore(chip, ac97->num) < 0) {
if (! chip->in_ac97_init)
- snd_printk(KERN_ERR "codec_write %d: semaphore is not ready for register 0x%x\n", ac97->num, reg);
+ dev_err(chip->card->dev,
+ "codec_write %d: semaphore is not ready for register 0x%x\n",
+ ac97->num, reg);
}
iaputword(chip, reg + ac97->num * 0x80, val);
}
@@ -576,16 +532,21 @@ static unsigned short snd_intel8x0_codec_read(struct snd_ac97 *ac97,
if (snd_intel8x0_codec_semaphore(chip, ac97->num) < 0) {
if (! chip->in_ac97_init)
- snd_printk(KERN_ERR "codec_read %d: semaphore is not ready for register 0x%x\n", ac97->num, reg);
+ dev_err(chip->card->dev,
+ "codec_read %d: semaphore is not ready for register 0x%x\n",
+ ac97->num, reg);
res = 0xffff;
} else {
res = iagetword(chip, reg + ac97->num * 0x80);
- if ((tmp = igetdword(chip, ICHREG(GLOB_STA))) & ICH_RCS) {
+ tmp = igetdword(chip, ICHREG(GLOB_STA));
+ if (tmp & ICH_RCS) {
/* reset RCS and preserve other R/WC bits */
iputdword(chip, ICHREG(GLOB_STA), tmp &
~(chip->codec_ready_bits | ICH_GSCI));
if (! chip->in_ac97_init)
- snd_printk(KERN_ERR "codec_read %d: read timeout for register 0x%x\n", ac97->num, reg);
+ dev_err(chip->card->dev,
+ "codec_read %d: read timeout for register 0x%x\n",
+ ac97->num, reg);
res = 0xffff;
}
}
@@ -599,7 +560,8 @@ static void snd_intel8x0_codec_read_test(struct intel8x0 *chip,
if (snd_intel8x0_codec_semaphore(chip, codec) >= 0) {
iagetword(chip, codec * 0x80);
- if ((tmp = igetdword(chip, ICHREG(GLOB_STA))) & ICH_RCS) {
+ tmp = igetdword(chip, ICHREG(GLOB_STA));
+ if (tmp & ICH_RCS) {
/* reset RCS and preserve other R/WC bits */
iputdword(chip, ICHREG(GLOB_STA), tmp &
~(chip->codec_ready_bits | ICH_GSCI));
@@ -619,7 +581,7 @@ static int snd_intel8x0_ali_codec_ready(struct intel8x0 *chip, int mask)
return 0;
}
if (! chip->in_ac97_init)
- snd_printd(KERN_WARNING "intel8x0: AC97 codec ready timeout.\n");
+ dev_warn(chip->card->dev, "AC97 codec ready timeout.\n");
return -EBUSY;
}
@@ -631,7 +593,7 @@ static int snd_intel8x0_ali_codec_semaphore(struct intel8x0 *chip)
while (--time && (igetdword(chip, ICHREG(ALI_CAS)) & ALI_CAS_SEM_BUSY))
udelay(1);
if (! time && ! chip->in_ac97_init)
- snd_printk(KERN_WARNING "ali_codec_semaphore timeout\n");
+ dev_warn(chip->card->dev, "ali_codec_semaphore timeout\n");
return snd_intel8x0_ali_codec_ready(chip, ALI_CSPSR_CODEC_READY);
}
@@ -674,7 +636,7 @@ static void snd_intel8x0_ali_codec_write(struct snd_ac97 *ac97, unsigned short r
static void snd_intel8x0_setup_periods(struct intel8x0 *chip, struct ichdev *ichdev)
{
int idx;
- u32 *bdbar = ichdev->bdbar;
+ __le32 *bdbar = ichdev->bdbar;
unsigned long port = ichdev->reg_offset;
iputdword(chip, port + ICH_REG_OFF_BDBAR, ichdev->bdbar_addr);
@@ -700,7 +662,7 @@ static void snd_intel8x0_setup_periods(struct intel8x0 *chip, struct ichdev *ich
bdbar[idx + 1] = cpu_to_le32(0x80000000 | /* interrupt on completion */
ichdev->fragsize >> ichdev->pos_shift);
#if 0
- printk(KERN_DEBUG "bdbar[%i] = 0x%x [0x%x]\n",
+ dev_dbg(chip->card->dev, "bdbar[%i] = 0x%x [0x%x]\n",
idx + 0, bdbar[idx + 0], bdbar[idx + 1]);
#endif
}
@@ -712,8 +674,8 @@ static void snd_intel8x0_setup_periods(struct intel8x0 *chip, struct ichdev *ich
ichdev->lvi_frag = ICH_REG_LVI_MASK % ichdev->frags;
ichdev->position = 0;
#if 0
- printk(KERN_DEBUG "lvi_frag = %i, frags = %i, period_size = 0x%x, "
- "period_size1 = 0x%x\n",
+ dev_dbg(chip->card->dev,
+ "lvi_frag = %i, frags = %i, period_size = 0x%x, period_size1 = 0x%x\n",
ichdev->lvi_frag, ichdev->frags, ichdev->fragsize,
ichdev->fragsize1);
#endif
@@ -721,25 +683,6 @@ static void snd_intel8x0_setup_periods(struct intel8x0 *chip, struct ichdev *ich
iputbyte(chip, port + ichdev->roff_sr, ICH_FIFOE | ICH_BCIS | ICH_LVBCI);
}
-#ifdef __i386__
-/*
- * Intel 82443MX running a 100MHz processor system bus has a hardware bug,
- * which aborts PCI busmaster for audio transfer. A workaround is to set
- * the pages as non-cached. For details, see the errata in
- * http://download.intel.com/design/chipsets/specupdt/24505108.pdf
- */
-static void fill_nocache(void *buf, int size, int nocache)
-{
- size = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
- if (nocache)
- set_pages_uc(virt_to_page(buf), size);
- else
- set_pages_wb(virt_to_page(buf), size);
-}
-#else
-#define fill_nocache(buf, size, nocache) do { ; } while (0)
-#endif
-
/*
* Interrupt handler
*/
@@ -747,52 +690,51 @@ static void fill_nocache(void *buf, int size, int nocache)
static inline void snd_intel8x0_update(struct intel8x0 *chip, struct ichdev *ichdev)
{
unsigned long port = ichdev->reg_offset;
- unsigned long flags;
int status, civ, i, step;
int ack = 0;
- spin_lock_irqsave(&chip->reg_lock, flags);
- status = igetbyte(chip, port + ichdev->roff_sr);
- civ = igetbyte(chip, port + ICH_REG_OFF_CIV);
- if (!(status & ICH_BCIS)) {
- step = 0;
- } else if (civ == ichdev->civ) {
- // snd_printd("civ same %d\n", civ);
- step = 1;
- ichdev->civ++;
- ichdev->civ &= ICH_REG_LVI_MASK;
- } else {
- step = civ - ichdev->civ;
- if (step < 0)
- step += ICH_REG_LVI_MASK + 1;
- // if (step != 1)
- // snd_printd("step = %d, %d -> %d\n", step, ichdev->civ, civ);
- ichdev->civ = civ;
- }
-
- ichdev->position += step * ichdev->fragsize1;
- if (! chip->in_measurement)
- ichdev->position %= ichdev->size;
- ichdev->lvi += step;
- ichdev->lvi &= ICH_REG_LVI_MASK;
- iputbyte(chip, port + ICH_REG_OFF_LVI, ichdev->lvi);
- for (i = 0; i < step; i++) {
- ichdev->lvi_frag++;
- ichdev->lvi_frag %= ichdev->frags;
- ichdev->bdbar[ichdev->lvi * 2] = cpu_to_le32(ichdev->physbuf + ichdev->lvi_frag * ichdev->fragsize1);
+ if (!(ichdev->prepared || chip->in_measurement) || ichdev->suspended)
+ return;
+
+ scoped_guard(spinlock_irqsave, &chip->reg_lock) {
+ status = igetbyte(chip, port + ichdev->roff_sr);
+ civ = igetbyte(chip, port + ICH_REG_OFF_CIV);
+ if (!(status & ICH_BCIS)) {
+ step = 0;
+ } else if (civ == ichdev->civ) {
+ step = 1;
+ ichdev->civ++;
+ ichdev->civ &= ICH_REG_LVI_MASK;
+ } else {
+ step = civ - ichdev->civ;
+ if (step < 0)
+ step += ICH_REG_LVI_MASK + 1;
+ ichdev->civ = civ;
+ }
+
+ ichdev->position += step * ichdev->fragsize1;
+ if (! chip->in_measurement)
+ ichdev->position %= ichdev->size;
+ ichdev->lvi += step;
+ ichdev->lvi &= ICH_REG_LVI_MASK;
+ iputbyte(chip, port + ICH_REG_OFF_LVI, ichdev->lvi);
+ for (i = 0; i < step; i++) {
+ ichdev->lvi_frag++;
+ ichdev->lvi_frag %= ichdev->frags;
+ ichdev->bdbar[ichdev->lvi * 2] = cpu_to_le32(ichdev->physbuf + ichdev->lvi_frag * ichdev->fragsize1);
#if 0
- printk(KERN_DEBUG "new: bdbar[%i] = 0x%x [0x%x], prefetch = %i, "
- "all = 0x%x, 0x%x\n",
- ichdev->lvi * 2, ichdev->bdbar[ichdev->lvi * 2],
- ichdev->bdbar[ichdev->lvi * 2 + 1], inb(ICH_REG_OFF_PIV + port),
- inl(port + 4), inb(port + ICH_REG_OFF_CR));
+ dev_dbg(chip->card->dev,
+ "new: bdbar[%i] = 0x%x [0x%x], prefetch = %i, all = 0x%x, 0x%x\n",
+ ichdev->lvi * 2, ichdev->bdbar[ichdev->lvi * 2],
+ ichdev->bdbar[ichdev->lvi * 2 + 1], inb(ICH_REG_OFF_PIV + port),
+ inl(port + 4), inb(port + ICH_REG_OFF_CR));
#endif
- if (--ichdev->ack == 0) {
- ichdev->ack = ichdev->ack_reload;
- ack = 1;
+ if (--ichdev->ack == 0) {
+ ichdev->ack = ichdev->ack_reload;
+ ack = 1;
+ }
}
}
- spin_unlock_irqrestore(&chip->reg_lock, flags);
if (ack && ichdev->substream) {
snd_pcm_period_elapsed(ichdev->substream);
}
@@ -847,7 +789,7 @@ static int snd_intel8x0_pcm_trigger(struct snd_pcm_substream *substream, int cmd
switch (cmd) {
case SNDRV_PCM_TRIGGER_RESUME:
ichdev->suspended = 0;
- /* fallthru */
+ fallthrough;
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
val = ICH_IOCE | ICH_STARTBM;
@@ -855,7 +797,7 @@ static int snd_intel8x0_pcm_trigger(struct snd_pcm_substream *substream, int cmd
break;
case SNDRV_PCM_TRIGGER_SUSPEND:
ichdev->suspended = 1;
- /* fallthru */
+ fallthrough;
case SNDRV_PCM_TRIGGER_STOP:
val = 0;
break;
@@ -880,7 +822,7 @@ static int snd_intel8x0_ali_trigger(struct snd_pcm_substream *substream, int cmd
struct intel8x0 *chip = snd_pcm_substream_chip(substream);
struct ichdev *ichdev = get_ichdev(substream);
unsigned long port = ichdev->reg_offset;
- static int fiforeg[] = {
+ static const int fiforeg[] = {
ICHREG(ALI_FIFOCR1), ICHREG(ALI_FIFOCR2), ICHREG(ALI_FIFOCR3)
};
unsigned int val, fifo;
@@ -889,7 +831,7 @@ static int snd_intel8x0_ali_trigger(struct snd_pcm_substream *substream, int cmd
switch (cmd) {
case SNDRV_PCM_TRIGGER_RESUME:
ichdev->suspended = 0;
- /* fallthru */
+ fallthrough;
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
@@ -906,7 +848,7 @@ static int snd_intel8x0_ali_trigger(struct snd_pcm_substream *substream, int cmd
break;
case SNDRV_PCM_TRIGGER_SUSPEND:
ichdev->suspended = 1;
- /* fallthru */
+ fallthrough;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
/* pause */
@@ -935,26 +877,13 @@ static int snd_intel8x0_hw_params(struct snd_pcm_substream *substream,
{
struct intel8x0 *chip = snd_pcm_substream_chip(substream);
struct ichdev *ichdev = get_ichdev(substream);
- struct snd_pcm_runtime *runtime = substream->runtime;
int dbl = params_rate(hw_params) > 48000;
int err;
- if (chip->fix_nocache && ichdev->page_attr_changed) {
- fill_nocache(runtime->dma_area, runtime->dma_bytes, 0); /* clear */
- ichdev->page_attr_changed = 0;
- }
- err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
- if (err < 0)
- return err;
- if (chip->fix_nocache) {
- if (runtime->dma_area && ! ichdev->page_attr_changed) {
- fill_nocache(runtime->dma_area, runtime->dma_bytes, 1);
- ichdev->page_attr_changed = 1;
- }
- }
if (ichdev->pcm_open_flag) {
snd_ac97_pcm_close(ichdev->pcm);
ichdev->pcm_open_flag = 0;
+ ichdev->prepared = 0;
}
err = snd_ac97_pcm_open(ichdev->pcm, params_rate(hw_params),
params_channels(hw_params),
@@ -971,18 +900,14 @@ static int snd_intel8x0_hw_params(struct snd_pcm_substream *substream,
static int snd_intel8x0_hw_free(struct snd_pcm_substream *substream)
{
- struct intel8x0 *chip = snd_pcm_substream_chip(substream);
struct ichdev *ichdev = get_ichdev(substream);
if (ichdev->pcm_open_flag) {
snd_ac97_pcm_close(ichdev->pcm);
ichdev->pcm_open_flag = 0;
+ ichdev->prepared = 0;
}
- if (chip->fix_nocache && ichdev->page_attr_changed) {
- fill_nocache(substream->runtime->dma_area, substream->runtime->dma_bytes, 0);
- ichdev->page_attr_changed = 0;
- }
- return snd_pcm_lib_free_pages(substream);
+ return 0;
}
static void snd_intel8x0_setup_pcm_out(struct intel8x0 *chip,
@@ -991,7 +916,7 @@ static void snd_intel8x0_setup_pcm_out(struct intel8x0 *chip,
unsigned int cnt;
int dbl = runtime->rate > 48000;
- spin_lock_irq(&chip->reg_lock);
+ guard(spinlock_irq)(&chip->reg_lock);
switch (chip->device_type) {
case DEVICE_ALI:
cnt = igetdword(chip, ICHREG(ALI_SCR));
@@ -1037,7 +962,6 @@ static void snd_intel8x0_setup_pcm_out(struct intel8x0 *chip,
iputdword(chip, ICHREG(GLOB_CNT), cnt);
break;
}
- spin_unlock_irq(&chip->reg_lock);
}
static int snd_intel8x0_pcm_prepare(struct snd_pcm_substream *substream)
@@ -1055,6 +979,7 @@ static int snd_intel8x0_pcm_prepare(struct snd_pcm_substream *substream)
ichdev->pos_shift = (runtime->sample_bits > 16) ? 2 : 1;
}
snd_intel8x0_setup_periods(chip, ichdev);
+ ichdev->prepared = 1;
return 0;
}
@@ -1066,7 +991,7 @@ static snd_pcm_uframes_t snd_intel8x0_pcm_pointer(struct snd_pcm_substream *subs
int civ, timeout = 10;
unsigned int position;
- spin_lock(&chip->reg_lock);
+ guard(spinlock)(&chip->reg_lock);
do {
civ = igetbyte(chip, ichdev->reg_offset + ICH_REG_OFF_CIV);
ptr1 = igetword(chip, ichdev->reg_offset + ichdev->roff_picb);
@@ -1106,13 +1031,12 @@ static snd_pcm_uframes_t snd_intel8x0_pcm_pointer(struct snd_pcm_substream *subs
}
}
ichdev->last_pos = ptr;
- spin_unlock(&chip->reg_lock);
if (ptr >= ichdev->size)
return 0;
return bytes_to_frames(substream->runtime, ptr);
}
-static struct snd_pcm_hardware snd_intel8x0_stream =
+static const struct snd_pcm_hardware snd_intel8x0_stream =
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -1133,31 +1057,31 @@ static struct snd_pcm_hardware snd_intel8x0_stream =
.fifo_size = 0,
};
-static unsigned int channels4[] = {
+static const unsigned int channels4[] = {
2, 4,
};
-static struct snd_pcm_hw_constraint_list hw_constraints_channels4 = {
+static const struct snd_pcm_hw_constraint_list hw_constraints_channels4 = {
.count = ARRAY_SIZE(channels4),
.list = channels4,
.mask = 0,
};
-static unsigned int channels6[] = {
+static const unsigned int channels6[] = {
2, 4, 6,
};
-static struct snd_pcm_hw_constraint_list hw_constraints_channels6 = {
+static const struct snd_pcm_hw_constraint_list hw_constraints_channels6 = {
.count = ARRAY_SIZE(channels6),
.list = channels6,
.mask = 0,
};
-static unsigned int channels8[] = {
+static const unsigned int channels8[] = {
2, 4, 6, 8,
};
-static struct snd_pcm_hw_constraint_list hw_constraints_channels8 = {
+static const struct snd_pcm_hw_constraint_list hw_constraints_channels8 = {
.count = ARRAY_SIZE(channels8),
.list = channels8,
.mask = 0,
@@ -1177,7 +1101,8 @@ static int snd_intel8x0_pcm_open(struct snd_pcm_substream *substream, struct ich
runtime->hw.buffer_bytes_max = 64*1024;
runtime->hw.period_bytes_max = 64*1024;
}
- if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
+ err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
+ if (err < 0)
return err;
runtime->private_data = ichdev;
return 0;
@@ -1307,12 +1232,12 @@ static int snd_intel8x0_ali_ac97spdifout_open(struct snd_pcm_substream *substrea
struct intel8x0 *chip = snd_pcm_substream_chip(substream);
unsigned int val;
- spin_lock_irq(&chip->reg_lock);
- val = igetdword(chip, ICHREG(ALI_INTERFACECR));
- val |= ICH_ALI_IF_AC97SP;
- iputdword(chip, ICHREG(ALI_INTERFACECR), val);
- /* also needs to set ALI_SC_CODEC_SPDF correctly */
- spin_unlock_irq(&chip->reg_lock);
+ scoped_guard(spinlock_irq, &chip->reg_lock) {
+ val = igetdword(chip, ICHREG(ALI_INTERFACECR));
+ val |= ICH_ALI_IF_AC97SP;
+ iputdword(chip, ICHREG(ALI_INTERFACECR), val);
+ /* also needs to set ALI_SC_CODEC_SPDF correctly */
+ }
return snd_intel8x0_pcm_open(substream, &chip->ichd[ALID_AC97SPDIFOUT]);
}
@@ -1323,11 +1248,10 @@ static int snd_intel8x0_ali_ac97spdifout_close(struct snd_pcm_substream *substre
unsigned int val;
chip->ichd[ALID_AC97SPDIFOUT].substream = NULL;
- spin_lock_irq(&chip->reg_lock);
+ guard(spinlock_irq)(&chip->reg_lock);
val = igetdword(chip, ICHREG(ALI_INTERFACECR));
val &= ~ICH_ALI_IF_AC97SP;
iputdword(chip, ICHREG(ALI_INTERFACECR), val);
- spin_unlock_irq(&chip->reg_lock);
return 0;
}
@@ -1364,10 +1288,9 @@ static int snd_intel8x0_ali_spdifout_close(struct snd_pcm_substream *substream)
}
#endif
-static struct snd_pcm_ops snd_intel8x0_playback_ops = {
+static const struct snd_pcm_ops snd_intel8x0_playback_ops = {
.open = snd_intel8x0_playback_open,
.close = snd_intel8x0_playback_close,
- .ioctl = snd_pcm_lib_ioctl,
.hw_params = snd_intel8x0_hw_params,
.hw_free = snd_intel8x0_hw_free,
.prepare = snd_intel8x0_pcm_prepare,
@@ -1375,10 +1298,9 @@ static struct snd_pcm_ops snd_intel8x0_playback_ops = {
.pointer = snd_intel8x0_pcm_pointer,
};
-static struct snd_pcm_ops snd_intel8x0_capture_ops = {
+static const struct snd_pcm_ops snd_intel8x0_capture_ops = {
.open = snd_intel8x0_capture_open,
.close = snd_intel8x0_capture_close,
- .ioctl = snd_pcm_lib_ioctl,
.hw_params = snd_intel8x0_hw_params,
.hw_free = snd_intel8x0_hw_free,
.prepare = snd_intel8x0_pcm_prepare,
@@ -1386,10 +1308,9 @@ static struct snd_pcm_ops snd_intel8x0_capture_ops = {
.pointer = snd_intel8x0_pcm_pointer,
};
-static struct snd_pcm_ops snd_intel8x0_capture_mic_ops = {
+static const struct snd_pcm_ops snd_intel8x0_capture_mic_ops = {
.open = snd_intel8x0_mic_open,
.close = snd_intel8x0_mic_close,
- .ioctl = snd_pcm_lib_ioctl,
.hw_params = snd_intel8x0_hw_params,
.hw_free = snd_intel8x0_hw_free,
.prepare = snd_intel8x0_pcm_prepare,
@@ -1397,10 +1318,9 @@ static struct snd_pcm_ops snd_intel8x0_capture_mic_ops = {
.pointer = snd_intel8x0_pcm_pointer,
};
-static struct snd_pcm_ops snd_intel8x0_capture_mic2_ops = {
+static const struct snd_pcm_ops snd_intel8x0_capture_mic2_ops = {
.open = snd_intel8x0_mic2_open,
.close = snd_intel8x0_mic2_close,
- .ioctl = snd_pcm_lib_ioctl,
.hw_params = snd_intel8x0_hw_params,
.hw_free = snd_intel8x0_hw_free,
.prepare = snd_intel8x0_pcm_prepare,
@@ -1408,10 +1328,9 @@ static struct snd_pcm_ops snd_intel8x0_capture_mic2_ops = {
.pointer = snd_intel8x0_pcm_pointer,
};
-static struct snd_pcm_ops snd_intel8x0_capture2_ops = {
+static const struct snd_pcm_ops snd_intel8x0_capture2_ops = {
.open = snd_intel8x0_capture2_open,
.close = snd_intel8x0_capture2_close,
- .ioctl = snd_pcm_lib_ioctl,
.hw_params = snd_intel8x0_hw_params,
.hw_free = snd_intel8x0_hw_free,
.prepare = snd_intel8x0_pcm_prepare,
@@ -1419,10 +1338,9 @@ static struct snd_pcm_ops snd_intel8x0_capture2_ops = {
.pointer = snd_intel8x0_pcm_pointer,
};
-static struct snd_pcm_ops snd_intel8x0_spdif_ops = {
+static const struct snd_pcm_ops snd_intel8x0_spdif_ops = {
.open = snd_intel8x0_spdif_open,
.close = snd_intel8x0_spdif_close,
- .ioctl = snd_pcm_lib_ioctl,
.hw_params = snd_intel8x0_hw_params,
.hw_free = snd_intel8x0_hw_free,
.prepare = snd_intel8x0_pcm_prepare,
@@ -1430,10 +1348,9 @@ static struct snd_pcm_ops snd_intel8x0_spdif_ops = {
.pointer = snd_intel8x0_pcm_pointer,
};
-static struct snd_pcm_ops snd_intel8x0_ali_playback_ops = {
+static const struct snd_pcm_ops snd_intel8x0_ali_playback_ops = {
.open = snd_intel8x0_playback_open,
.close = snd_intel8x0_playback_close,
- .ioctl = snd_pcm_lib_ioctl,
.hw_params = snd_intel8x0_hw_params,
.hw_free = snd_intel8x0_hw_free,
.prepare = snd_intel8x0_pcm_prepare,
@@ -1441,10 +1358,9 @@ static struct snd_pcm_ops snd_intel8x0_ali_playback_ops = {
.pointer = snd_intel8x0_pcm_pointer,
};
-static struct snd_pcm_ops snd_intel8x0_ali_capture_ops = {
+static const struct snd_pcm_ops snd_intel8x0_ali_capture_ops = {
.open = snd_intel8x0_capture_open,
.close = snd_intel8x0_capture_close,
- .ioctl = snd_pcm_lib_ioctl,
.hw_params = snd_intel8x0_hw_params,
.hw_free = snd_intel8x0_hw_free,
.prepare = snd_intel8x0_pcm_prepare,
@@ -1452,10 +1368,9 @@ static struct snd_pcm_ops snd_intel8x0_ali_capture_ops = {
.pointer = snd_intel8x0_pcm_pointer,
};
-static struct snd_pcm_ops snd_intel8x0_ali_capture_mic_ops = {
+static const struct snd_pcm_ops snd_intel8x0_ali_capture_mic_ops = {
.open = snd_intel8x0_mic_open,
.close = snd_intel8x0_mic_close,
- .ioctl = snd_pcm_lib_ioctl,
.hw_params = snd_intel8x0_hw_params,
.hw_free = snd_intel8x0_hw_free,
.prepare = snd_intel8x0_pcm_prepare,
@@ -1463,10 +1378,9 @@ static struct snd_pcm_ops snd_intel8x0_ali_capture_mic_ops = {
.pointer = snd_intel8x0_pcm_pointer,
};
-static struct snd_pcm_ops snd_intel8x0_ali_ac97spdifout_ops = {
+static const struct snd_pcm_ops snd_intel8x0_ali_ac97spdifout_ops = {
.open = snd_intel8x0_ali_ac97spdifout_open,
.close = snd_intel8x0_ali_ac97spdifout_close,
- .ioctl = snd_pcm_lib_ioctl,
.hw_params = snd_intel8x0_hw_params,
.hw_free = snd_intel8x0_hw_free,
.prepare = snd_intel8x0_pcm_prepare,
@@ -1478,7 +1392,6 @@ static struct snd_pcm_ops snd_intel8x0_ali_ac97spdifout_ops = {
static struct snd_pcm_ops snd_intel8x0_ali_spdifin_ops = {
.open = snd_intel8x0_ali_spdifin_open,
.close = snd_intel8x0_ali_spdifin_close,
- .ioctl = snd_pcm_lib_ioctl,
.hw_params = snd_intel8x0_hw_params,
.hw_free = snd_intel8x0_hw_free,
.prepare = snd_intel8x0_pcm_prepare,
@@ -1489,7 +1402,6 @@ static struct snd_pcm_ops snd_intel8x0_ali_spdifin_ops = {
static struct snd_pcm_ops snd_intel8x0_ali_spdifout_ops = {
.open = snd_intel8x0_ali_spdifout_open,
.close = snd_intel8x0_ali_spdifout_close,
- .ioctl = snd_pcm_lib_ioctl,
.hw_params = snd_intel8x0_hw_params,
.hw_free = snd_intel8x0_hw_free,
.prepare = snd_intel8x0_pcm_prepare,
@@ -1500,15 +1412,18 @@ static struct snd_pcm_ops snd_intel8x0_ali_spdifout_ops = {
struct ich_pcm_table {
char *suffix;
- struct snd_pcm_ops *playback_ops;
- struct snd_pcm_ops *capture_ops;
+ const struct snd_pcm_ops *playback_ops;
+ const struct snd_pcm_ops *capture_ops;
size_t prealloc_size;
size_t prealloc_max_size;
int ac97_idx;
};
+#define intel8x0_dma_type(chip) \
+ ((chip)->fix_nocache ? SNDRV_DMA_TYPE_DEV_WC : SNDRV_DMA_TYPE_DEV)
+
static int snd_intel8x0_pcm1(struct intel8x0 *chip, int device,
- struct ich_pcm_table *rec)
+ const struct ich_pcm_table *rec)
{
struct snd_pcm *pcm;
int err;
@@ -1517,7 +1432,7 @@ static int snd_intel8x0_pcm1(struct intel8x0 *chip, int device,
if (rec->suffix)
sprintf(name, "Intel ICH - %s", rec->suffix);
else
- strcpy(name, "Intel ICH");
+ strscpy(name, "Intel ICH");
err = snd_pcm_new(chip->card, name, device,
rec->playback_ops ? 1 : 0,
rec->capture_ops ? 1 : 0, &pcm);
@@ -1534,24 +1449,23 @@ static int snd_intel8x0_pcm1(struct intel8x0 *chip, int device,
if (rec->suffix)
sprintf(pcm->name, "%s - %s", chip->card->shortname, rec->suffix);
else
- strcpy(pcm->name, chip->card->shortname);
+ strscpy(pcm->name, chip->card->shortname);
chip->pcm[device] = pcm;
- snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
- snd_dma_pci_data(chip->pci),
- rec->prealloc_size, rec->prealloc_max_size);
+ snd_pcm_set_managed_buffer_all(pcm, intel8x0_dma_type(chip),
+ &chip->pci->dev,
+ rec->prealloc_size, rec->prealloc_max_size);
- if (rec->ac97_idx == ICHD_PCMOUT && rec->playback_ops) {
+ if (rec->playback_ops &&
+ rec->playback_ops->open == snd_intel8x0_playback_open) {
struct snd_pcm_chmap *chmap;
int chs = 2;
- if (rec->ac97_idx == ICHD_PCMOUT) {
- if (chip->multi8)
- chs = 8;
- else if (chip->multi6)
- chs = 6;
- else if (chip->multi4)
- chs = 4;
- }
+ if (chip->multi8)
+ chs = 8;
+ else if (chip->multi6)
+ chs = 6;
+ else if (chip->multi4)
+ chs = 4;
err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK,
snd_pcm_alt_chmaps, chs, 0,
&chmap);
@@ -1564,7 +1478,7 @@ static int snd_intel8x0_pcm1(struct intel8x0 *chip, int device,
return 0;
}
-static struct ich_pcm_table intel_pcms[] = {
+static const struct ich_pcm_table intel_pcms[] = {
{
.playback_ops = &snd_intel8x0_playback_ops,
.capture_ops = &snd_intel8x0_capture_ops,
@@ -1601,7 +1515,7 @@ static struct ich_pcm_table intel_pcms[] = {
},
};
-static struct ich_pcm_table nforce_pcms[] = {
+static const struct ich_pcm_table nforce_pcms[] = {
{
.playback_ops = &snd_intel8x0_playback_ops,
.capture_ops = &snd_intel8x0_capture_ops,
@@ -1624,7 +1538,7 @@ static struct ich_pcm_table nforce_pcms[] = {
},
};
-static struct ich_pcm_table ali_pcms[] = {
+static const struct ich_pcm_table ali_pcms[] = {
{
.playback_ops = &snd_intel8x0_ali_playback_ops,
.capture_ops = &snd_intel8x0_ali_capture_ops,
@@ -1659,7 +1573,7 @@ static struct ich_pcm_table ali_pcms[] = {
static int snd_intel8x0_pcm(struct intel8x0 *chip)
{
int i, tblsize, device, err;
- struct ich_pcm_table *tbl, *rec;
+ const struct ich_pcm_table *tbl, *rec;
switch (chip->device_type) {
case DEVICE_INTEL_ICH4:
@@ -1719,7 +1633,7 @@ static void snd_intel8x0_mixer_free_ac97(struct snd_ac97 *ac97)
chip->ac97[ac97->num] = NULL;
}
-static struct ac97_pcm ac97_pcm_defs[] = {
+static const struct ac97_pcm ac97_pcm_defs[] = {
/* front PCM */
{
.exclusive = 1,
@@ -1789,7 +1703,7 @@ static struct ac97_pcm ac97_pcm_defs[] = {
},
};
-static struct ac97_quirk ac97_quirks[] = {
+static const struct ac97_quirk ac97_quirks[] = {
{
.subvendor = 0x0e11,
.subdevice = 0x000e,
@@ -2204,12 +2118,12 @@ static int snd_intel8x0_mixer(struct intel8x0 *chip, int ac97_clock,
int err;
unsigned int i, codecs;
unsigned int glob_sta = 0;
- struct snd_ac97_bus_ops *ops;
- static struct snd_ac97_bus_ops standard_bus_ops = {
+ const struct snd_ac97_bus_ops *ops;
+ static const struct snd_ac97_bus_ops standard_bus_ops = {
.write = snd_intel8x0_codec_write,
.read = snd_intel8x0_codec_read,
};
- static struct snd_ac97_bus_ops ali_bus_ops = {
+ static const struct snd_ac97_bus_ops ali_bus_ops = {
.write = snd_intel8x0_ali_codec_write,
.read = snd_intel8x0_ali_codec_read,
};
@@ -2272,7 +2186,8 @@ static int snd_intel8x0_mixer(struct intel8x0 *chip, int ac97_clock,
udelay(1);
}
}
- if ((err = snd_ac97_bus(chip->card, 0, ops, chip, &pbus)) < 0)
+ err = snd_ac97_bus(chip->card, 0, ops, chip, &pbus);
+ if (err < 0)
goto __err;
pbus->private_free = snd_intel8x0_mixer_free_ac97_bus;
if (ac97_clock >= 8000 && ac97_clock <= 48000)
@@ -2288,9 +2203,11 @@ static int snd_intel8x0_mixer(struct intel8x0 *chip, int ac97_clock,
ac97.pci = chip->pci;
for (i = 0; i < codecs; i++) {
ac97.num = i;
- if ((err = snd_ac97_mixer(pbus, &ac97, &chip->ac97[i])) < 0) {
+ err = snd_ac97_mixer(pbus, &ac97, &chip->ac97[i]);
+ if (err < 0) {
if (err != -EACCES)
- snd_printk(KERN_ERR "Unable to initialize codec #%d\n", i);
+ dev_err(chip->card->dev,
+ "Unable to initialize codec #%d\n", i);
if (i == 0)
goto __err;
}
@@ -2328,7 +2245,7 @@ static int snd_intel8x0_mixer(struct intel8x0 *chip, int ac97_clock,
tmp |= chip->ac97_sdin[0] << ICH_DI1L_SHIFT;
for (i = 1; i < 4; i++) {
if (pcm->r[0].codec[i]) {
- tmp |= chip->ac97_sdin[pcm->r[0].codec[1]->num] << ICH_DI2L_SHIFT;
+ tmp |= chip->ac97_sdin[pcm->r[0].codec[i]->num] << ICH_DI2L_SHIFT;
break;
}
}
@@ -2393,7 +2310,7 @@ static void do_ali_reset(struct intel8x0 *chip)
}
#ifdef CONFIG_SND_AC97_POWER_SAVE
-static struct snd_pci_quirk ich_chip_reset_mode[] = {
+static const struct snd_pci_quirk ich_chip_reset_mode[] = {
SND_PCI_QUIRK(0x1014, 0x051f, "Thinkpad R32", 1),
{ } /* end */
};
@@ -2442,7 +2359,7 @@ static int snd_intel8x0_ich_chip_reset(struct intel8x0 *chip)
return 0;
schedule_timeout_uninterruptible(1);
} while (time_after_eq(end_time, jiffies));
- snd_printk(KERN_ERR "AC'97 warm reset still in progress? [0x%x]\n",
+ dev_err(chip->card->dev, "AC'97 warm reset still in progress? [0x%x]\n",
igetdword(chip, ICHREG(GLOB_CNT)));
return -EIO;
}
@@ -2484,7 +2401,8 @@ static int snd_intel8x0_ich_chip_init(struct intel8x0 *chip, int probing)
} while (time_after_eq(end_time, jiffies));
if (! status) {
/* no codec is found */
- snd_printk(KERN_ERR "codec_ready: codec is not ready [0x%x]\n",
+ dev_err(chip->card->dev,
+ "codec_ready: codec is not ready [0x%x]\n",
igetdword(chip, ICHREG(GLOB_STA)));
return -EIO;
}
@@ -2548,7 +2466,7 @@ static int snd_intel8x0_ali_chip_init(struct intel8x0 *chip, int probing)
goto __ok;
schedule_timeout_uninterruptible(1);
}
- snd_printk(KERN_ERR "AC'97 reset failed.\n");
+ dev_err(chip->card->dev, "AC'97 reset failed.\n");
if (probing)
return -EIO;
@@ -2571,11 +2489,13 @@ static int snd_intel8x0_chip_init(struct intel8x0 *chip, int probing)
int err;
if (chip->device_type != DEVICE_ALI) {
- if ((err = snd_intel8x0_ich_chip_init(chip, probing)) < 0)
+ err = snd_intel8x0_ich_chip_init(chip, probing);
+ if (err < 0)
return err;
iagetword(chip, 0); /* clear semaphore flag */
} else {
- if ((err = snd_intel8x0_ali_chip_init(chip, probing)) < 0)
+ err = snd_intel8x0_ali_chip_init(chip, probing);
+ if (err < 0)
return err;
}
@@ -2592,7 +2512,7 @@ static int snd_intel8x0_chip_init(struct intel8x0 *chip, int probing)
break;
}
if (timeout == 0)
- printk(KERN_ERR "intel8x0: reset of registers failed?\n");
+ dev_err(chip->card->dev, "reset of registers failed?\n");
}
/* initialize Buffer Descriptor Lists */
for (i = 0; i < chip->bdbars_count; i++)
@@ -2601,8 +2521,9 @@ static int snd_intel8x0_chip_init(struct intel8x0 *chip, int probing)
return 0;
}
-static int snd_intel8x0_free(struct intel8x0 *chip)
+static void snd_intel8x0_free(struct snd_card *card)
{
+ struct intel8x0 *chip = card->private_data;
unsigned int i;
if (chip->irq < 0)
@@ -2625,46 +2546,18 @@ static int snd_intel8x0_free(struct intel8x0 *chip)
__hw_end:
if (chip->irq >= 0)
free_irq(chip->irq, chip);
- if (chip->bdbars.area) {
- if (chip->fix_nocache)
- fill_nocache(chip->bdbars.area, chip->bdbars.bytes, 0);
- snd_dma_free_pages(&chip->bdbars);
- }
- if (chip->addr)
- pci_iounmap(chip->pci, chip->addr);
- if (chip->bmaddr)
- pci_iounmap(chip->pci, chip->bmaddr);
- pci_release_regions(chip->pci);
- pci_disable_device(chip->pci);
- kfree(chip);
- return 0;
}
-#ifdef CONFIG_PM_SLEEP
/*
* power management
*/
static int intel8x0_suspend(struct device *dev)
{
- struct pci_dev *pci = to_pci_dev(dev);
struct snd_card *card = dev_get_drvdata(dev);
struct intel8x0 *chip = card->private_data;
int i;
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
- for (i = 0; i < chip->pcm_devs; i++)
- snd_pcm_suspend_all(chip->pcm[i]);
- /* clear nocache */
- if (chip->fix_nocache) {
- for (i = 0; i < chip->bdbars_count; i++) {
- struct ichdev *ichdev = &chip->ichd[i];
- if (ichdev->substream && ichdev->page_attr_changed) {
- struct snd_pcm_runtime *runtime = ichdev->substream->runtime;
- if (runtime->dma_area)
- fill_nocache(runtime->dma_area, runtime->dma_bytes, 0);
- }
- }
- }
for (i = 0; i < chip->ncodecs; i++)
snd_ac97_suspend(chip->ac97[i]);
if (chip->device_type == DEVICE_INTEL_ICH4)
@@ -2673,13 +2566,8 @@ static int intel8x0_suspend(struct device *dev)
if (chip->irq >= 0) {
free_irq(chip->irq, chip);
chip->irq = -1;
+ card->sync_irq = -1;
}
- pci_disable_device(pci);
- pci_save_state(pci);
- /* The call below may disable built-in speaker on some laptops
- * after S2RAM. So, don't touch it.
- */
- /* pci_set_power_state(pci, PCI_D3hot); */
return 0;
}
@@ -2690,25 +2578,16 @@ static int intel8x0_resume(struct device *dev)
struct intel8x0 *chip = card->private_data;
int i;
- pci_set_power_state(pci, PCI_D0);
- pci_restore_state(pci);
- if (pci_enable_device(pci) < 0) {
- printk(KERN_ERR "intel8x0: pci_enable_device failed, "
- "disabling device\n");
- snd_card_disconnect(card);
- return -EIO;
- }
- pci_set_master(pci);
snd_intel8x0_chip_init(chip, 0);
if (request_irq(pci->irq, snd_intel8x0_interrupt,
IRQF_SHARED, KBUILD_MODNAME, chip)) {
- printk(KERN_ERR "intel8x0: unable to grab IRQ %d, "
- "disabling device\n", pci->irq);
+ dev_err(dev, "unable to grab IRQ %d, disabling device\n",
+ pci->irq);
snd_card_disconnect(card);
return -EIO;
}
chip->irq = pci->irq;
- synchronize_irq(chip->irq);
+ card->sync_irq = chip->irq;
/* re-initialize mixer stuff */
if (chip->device_type == DEVICE_INTEL_ICH4 && !spdif_aclink) {
@@ -2720,25 +2599,9 @@ static int intel8x0_resume(struct device *dev)
ICH_PCM_SPDIF_1011);
}
- /* refill nocache */
- if (chip->fix_nocache)
- fill_nocache(chip->bdbars.area, chip->bdbars.bytes, 1);
-
for (i = 0; i < chip->ncodecs; i++)
snd_ac97_resume(chip->ac97[i]);
- /* refill nocache */
- if (chip->fix_nocache) {
- for (i = 0; i < chip->bdbars_count; i++) {
- struct ichdev *ichdev = &chip->ichd[i];
- if (ichdev->substream && ichdev->page_attr_changed) {
- struct snd_pcm_runtime *runtime = ichdev->substream->runtime;
- if (runtime->dma_area)
- fill_nocache(runtime->dma_area, runtime->dma_bytes, 1);
- }
- }
- }
-
/* resume status */
for (i = 0; i < chip->bdbars_count; i++) {
struct ichdev *ichdev = &chip->ichd[i];
@@ -2757,11 +2620,7 @@ static int intel8x0_resume(struct device *dev)
return 0;
}
-static SIMPLE_DEV_PM_OPS(intel8x0_pm, intel8x0_suspend, intel8x0_resume);
-#define INTEL8X0_PM_OPS &intel8x0_pm
-#else
-#define INTEL8X0_PM_OPS NULL
-#endif /* CONFIG_PM_SLEEP */
+static DEFINE_SIMPLE_DEV_PM_OPS(intel8x0_pm, intel8x0_suspend, intel8x0_resume);
#define INTEL8X0_TESTBUF_SIZE 32768 /* enough large for one shot */
@@ -2772,15 +2631,18 @@ static void intel8x0_measure_ac97_clock(struct intel8x0 *chip)
unsigned long port;
unsigned long pos, pos1, t;
int civ, timeout = 1000, attempt = 1;
- struct timespec start_time, stop_time;
+ ktime_t start_time, stop_time;
if (chip->ac97_bus->clock != 48000)
return; /* specified in module option */
+ if (chip->inside_vm && !ac97_clock)
+ return; /* no measurement on VM */
__again:
subs = chip->pcm[0]->streams[0].substream;
if (! subs || subs->dma_buffer.bytes < INTEL8X0_TESTBUF_SIZE) {
- snd_printk(KERN_WARNING "no playback buffer allocated - aborting measure ac97 clock\n");
+ dev_warn(chip->card->dev,
+ "no playback buffer allocated - aborting measure ac97 clock\n");
return;
}
ichdev = &chip->ichd[ICHD_PCMOUT];
@@ -2790,61 +2652,63 @@ static void intel8x0_measure_ac97_clock(struct intel8x0 *chip)
/* set rate */
if (snd_ac97_set_rate(chip->ac97[0], AC97_PCM_FRONT_DAC_RATE, 48000) < 0) {
- snd_printk(KERN_ERR "cannot set ac97 rate: clock = %d\n", chip->ac97_bus->clock);
+ dev_err(chip->card->dev, "cannot set ac97 rate: clock = %d\n",
+ chip->ac97_bus->clock);
return;
}
snd_intel8x0_setup_periods(chip, ichdev);
port = ichdev->reg_offset;
- spin_lock_irq(&chip->reg_lock);
- chip->in_measurement = 1;
- /* trigger */
- if (chip->device_type != DEVICE_ALI)
- iputbyte(chip, port + ICH_REG_OFF_CR, ICH_IOCE | ICH_STARTBM);
- else {
- iputbyte(chip, port + ICH_REG_OFF_CR, ICH_IOCE);
- iputdword(chip, ICHREG(ALI_DMACR), 1 << ichdev->ali_slot);
+ scoped_guard(spinlock_irq, &chip->reg_lock) {
+ chip->in_measurement = 1;
+ /* trigger */
+ if (chip->device_type != DEVICE_ALI)
+ iputbyte(chip, port + ICH_REG_OFF_CR, ICH_IOCE | ICH_STARTBM);
+ else {
+ iputbyte(chip, port + ICH_REG_OFF_CR, ICH_IOCE);
+ iputdword(chip, ICHREG(ALI_DMACR), 1 << ichdev->ali_slot);
+ }
+ start_time = ktime_get();
}
- do_posix_clock_monotonic_gettime(&start_time);
- spin_unlock_irq(&chip->reg_lock);
msleep(50);
- spin_lock_irq(&chip->reg_lock);
- /* check the position */
- do {
- civ = igetbyte(chip, ichdev->reg_offset + ICH_REG_OFF_CIV);
- pos1 = igetword(chip, ichdev->reg_offset + ichdev->roff_picb);
- if (pos1 == 0) {
- udelay(10);
- continue;
+ scoped_guard(spinlock_irq, &chip->reg_lock) {
+ /* check the position */
+ do {
+ civ = igetbyte(chip, ichdev->reg_offset + ICH_REG_OFF_CIV);
+ pos1 = igetword(chip, ichdev->reg_offset + ichdev->roff_picb);
+ if (pos1 == 0) {
+ udelay(10);
+ continue;
+ }
+ if (civ == igetbyte(chip, ichdev->reg_offset + ICH_REG_OFF_CIV) &&
+ pos1 == igetword(chip, ichdev->reg_offset + ichdev->roff_picb))
+ break;
+ } while (timeout--);
+ if (pos1 == 0) { /* oops, this value is not reliable */
+ pos = 0;
+ } else {
+ pos = ichdev->fragsize1;
+ pos -= pos1 << ichdev->pos_shift;
+ pos += ichdev->position;
}
- if (civ == igetbyte(chip, ichdev->reg_offset + ICH_REG_OFF_CIV) &&
- pos1 == igetword(chip, ichdev->reg_offset + ichdev->roff_picb))
- break;
- } while (timeout--);
- if (pos1 == 0) { /* oops, this value is not reliable */
- pos = 0;
- } else {
- pos = ichdev->fragsize1;
- pos -= pos1 << ichdev->pos_shift;
- pos += ichdev->position;
- }
- chip->in_measurement = 0;
- do_posix_clock_monotonic_gettime(&stop_time);
- /* stop */
- if (chip->device_type == DEVICE_ALI) {
- iputdword(chip, ICHREG(ALI_DMACR), 1 << (ichdev->ali_slot + 16));
- iputbyte(chip, port + ICH_REG_OFF_CR, 0);
- while (igetbyte(chip, port + ICH_REG_OFF_CR))
- ;
- } else {
- iputbyte(chip, port + ICH_REG_OFF_CR, 0);
- while (!(igetbyte(chip, port + ichdev->roff_sr) & ICH_DCH))
- ;
+ chip->in_measurement = 0;
+ stop_time = ktime_get();
+ /* stop */
+ if (chip->device_type == DEVICE_ALI) {
+ iputdword(chip, ICHREG(ALI_DMACR), 1 << (ichdev->ali_slot + 16));
+ iputbyte(chip, port + ICH_REG_OFF_CR, 0);
+ while (igetbyte(chip, port + ICH_REG_OFF_CR))
+ ;
+ } else {
+ iputbyte(chip, port + ICH_REG_OFF_CR, 0);
+ while (!(igetbyte(chip, port + ichdev->roff_sr) & ICH_DCH))
+ ;
+ }
+ iputbyte(chip, port + ICH_REG_OFF_CR, ICH_RESETREGS);
}
- iputbyte(chip, port + ICH_REG_OFF_CR, ICH_RESETREGS);
- spin_unlock_irq(&chip->reg_lock);
if (pos == 0) {
- snd_printk(KERN_ERR "intel8x0: measure - unreliable DMA position..\n");
+ dev_err(chip->card->dev,
+ "measure - unreliable DMA position..\n");
__retry:
if (attempt < 3) {
msleep(300);
@@ -2855,19 +2719,18 @@ static void intel8x0_measure_ac97_clock(struct intel8x0 *chip)
}
pos /= 4;
- t = stop_time.tv_sec - start_time.tv_sec;
- t *= 1000000;
- t += (stop_time.tv_nsec - start_time.tv_nsec) / 1000;
- printk(KERN_INFO "%s: measured %lu usecs (%lu samples)\n", __func__, t, pos);
+ t = ktime_us_delta(stop_time, start_time);
+ dev_info(chip->card->dev,
+ "%s: measured %lu usecs (%lu samples)\n", __func__, t, pos);
if (t == 0) {
- snd_printk(KERN_ERR "intel8x0: ?? calculation error..\n");
+ dev_err(chip->card->dev, "?? calculation error..\n");
goto __retry;
}
pos *= 1000;
pos = (pos / t) * 1000 + ((pos % t) * 1000) / t;
if (pos < 40000 || pos >= 60000) {
/* abnormal value. hw problem? */
- printk(KERN_INFO "intel8x0: measured clock %ld rejected\n", pos);
+ dev_info(chip->card->dev, "measured clock %ld rejected\n", pos);
goto __retry;
} else if (pos > 40500 && pos < 41500)
/* first exception - 41000Hz reference clock */
@@ -2879,12 +2742,13 @@ static void intel8x0_measure_ac97_clock(struct intel8x0 *chip)
/* not 48000Hz, tuning the clock.. */
chip->ac97_bus->clock = (chip->ac97_bus->clock * 48000) / pos;
__end:
- printk(KERN_INFO "intel8x0: clocking to %d\n", chip->ac97_bus->clock);
+ dev_info(chip->card->dev, "clocking to %d\n", chip->ac97_bus->clock);
snd_ac97_update_power(chip->ac97[0], AC97_PCM_FRONT_DAC_RATE, 0);
}
-static struct snd_pci_quirk intel8x0_clock_list[] = {
+static const struct snd_pci_quirk intel8x0_clock_list[] = {
SND_PCI_QUIRK(0x0e11, 0x008a, "AD1885", 41000),
+ SND_PCI_QUIRK(0x1014, 0x0581, "AD1981B", 48000),
SND_PCI_QUIRK(0x1028, 0x00be, "AD1885", 44100),
SND_PCI_QUIRK(0x1028, 0x0177, "AD1980", 48000),
SND_PCI_QUIRK(0x1028, 0x01ad, "AD1981B", 48000),
@@ -2900,13 +2764,12 @@ static int intel8x0_in_clock_list(struct intel8x0 *chip)
wl = snd_pci_quirk_lookup(pci, intel8x0_clock_list);
if (!wl)
return 0;
- printk(KERN_INFO "intel8x0: white list rate for %04x:%04x is %i\n",
+ dev_info(chip->card->dev, "allow list rate for %04x:%04x is %i\n",
pci->subsystem_vendor, pci->subsystem_device, wl->value);
chip->ac97_bus->clock = wl->value;
return 1;
}
-#ifdef CONFIG_PROC_FS
static void snd_intel8x0_proc_read(struct snd_info_entry * entry,
struct snd_info_buffer *buffer)
{
@@ -2943,19 +2806,8 @@ static void snd_intel8x0_proc_read(struct snd_info_entry * entry,
static void snd_intel8x0_proc_init(struct intel8x0 *chip)
{
- struct snd_info_entry *entry;
-
- if (! snd_card_proc_new(chip->card, "intel8x0", &entry))
- snd_info_set_text_ops(entry, chip, snd_intel8x0_proc_read);
-}
-#else
-#define snd_intel8x0_proc_init(x)
-#endif
-
-static int snd_intel8x0_dev_free(struct snd_device *device)
-{
- struct intel8x0 *chip = device->device_data;
- return snd_intel8x0_free(chip);
+ snd_card_ro_proc_new(chip->card, "intel8x0", chip,
+ snd_intel8x0_proc_read);
}
struct ich_reg_info {
@@ -2963,10 +2815,10 @@ struct ich_reg_info {
unsigned int offset;
};
-static unsigned int ich_codec_bits[3] = {
+static const unsigned int ich_codec_bits[3] = {
ICH_PCR, ICH_SCR, ICH_TCR
};
-static unsigned int sis_codec_bits[3] = {
+static const unsigned int sis_codec_bits[3] = {
ICH_PCR, ICH_SCR, ICH_SIS_TCR
};
@@ -2981,56 +2833,44 @@ static int snd_intel8x0_inside_vm(struct pci_dev *pci)
goto fini;
}
- /* detect KVM and Parallels virtual environments */
- result = kvm_para_available();
-#ifdef X86_FEATURE_HYPERVISOR
- result = result || boot_cpu_has(X86_FEATURE_HYPERVISOR);
-#endif
- if (!result)
- goto fini;
-
/* check for known (emulated) devices */
- if (pci->subsystem_vendor == 0x1af4 &&
- pci->subsystem_device == 0x1100) {
+ result = 0;
+ if (pci->subsystem_vendor == PCI_SUBVENDOR_ID_REDHAT_QUMRANET &&
+ pci->subsystem_device == PCI_SUBDEVICE_ID_QEMU) {
/* KVM emulated sound, PCI SSID: 1af4:1100 */
msg = "enable KVM";
+ result = 1;
} else if (pci->subsystem_vendor == 0x1ab8) {
/* Parallels VM emulated sound, PCI SSID: 1ab8:xxxx */
msg = "enable Parallels VM";
- } else {
- msg = "disable (unknown or VT-d) VM";
- result = 0;
+ result = 1;
}
fini:
if (msg != NULL)
- printk(KERN_INFO "intel8x0: %s optimization\n", msg);
+ dev_info(&pci->dev, "%s optimization\n", msg);
return result;
}
-static int snd_intel8x0_create(struct snd_card *card,
- struct pci_dev *pci,
- unsigned long device_type,
- struct intel8x0 **r_intel8x0)
+static int snd_intel8x0_init(struct snd_card *card,
+ struct pci_dev *pci,
+ unsigned long device_type)
{
- struct intel8x0 *chip;
+ struct intel8x0 *chip = card->private_data;
int err;
unsigned int i;
unsigned int int_sta_masks;
struct ichdev *ichdev;
- static struct snd_device_ops ops = {
- .dev_free = snd_intel8x0_dev_free,
- };
- static unsigned int bdbars[] = {
+ static const unsigned int bdbars[] = {
3, /* DEVICE_INTEL */
6, /* DEVICE_INTEL_ICH4 */
3, /* DEVICE_SIS */
6, /* DEVICE_ALI */
4, /* DEVICE_NFORCE */
};
- static struct ich_reg_info intel_regs[6] = {
+ static const struct ich_reg_info intel_regs[6] = {
{ ICH_PIINT, 0 },
{ ICH_POINT, 0x10 },
{ ICH_MCINT, 0x20 },
@@ -3038,13 +2878,13 @@ static int snd_intel8x0_create(struct snd_card *card,
{ ICH_P2INT, 0x50 },
{ ICH_SPINT, 0x60 },
};
- static struct ich_reg_info nforce_regs[4] = {
+ static const struct ich_reg_info nforce_regs[4] = {
{ ICH_PIINT, 0 },
{ ICH_POINT, 0x10 },
{ ICH_MCINT, 0x20 },
{ ICH_NVSPINT, 0x70 },
};
- static struct ich_reg_info ali_regs[6] = {
+ static const struct ich_reg_info ali_regs[6] = {
{ ALI_INT_PCMIN, 0x40 },
{ ALI_INT_PCMOUT, 0x50 },
{ ALI_INT_MICIN, 0x60 },
@@ -3052,18 +2892,12 @@ static int snd_intel8x0_create(struct snd_card *card,
{ ALI_INT_SPDIFIN, 0xa0 },
{ ALI_INT_SPDIFOUT, 0xb0 },
};
- struct ich_reg_info *tbl;
+ const struct ich_reg_info *tbl;
- *r_intel8x0 = NULL;
-
- if ((err = pci_enable_device(pci)) < 0)
+ err = pcim_enable_device(pci);
+ if (err < 0)
return err;
- chip = kzalloc(sizeof(*chip), GFP_KERNEL);
- if (chip == NULL) {
- pci_disable_device(pci);
- return -ENOMEM;
- }
spin_lock_init(&chip->reg_lock);
chip->device_type = device_type;
chip->card = card;
@@ -3078,42 +2912,34 @@ static int snd_intel8x0_create(struct snd_card *card,
chip->inside_vm = snd_intel8x0_inside_vm(pci);
+ /*
+ * Intel 82443MX running a 100MHz processor system bus has a hardware
+ * bug, which aborts PCI busmaster for audio transfer. A workaround
+ * is to set the pages as non-cached. For details, see the errata in
+ * http://download.intel.com/design/chipsets/specupdt/24505108.pdf
+ */
if (pci->vendor == PCI_VENDOR_ID_INTEL &&
pci->device == PCI_DEVICE_ID_INTEL_440MX)
chip->fix_nocache = 1; /* enable workaround */
- if ((err = pci_request_regions(pci, card->shortname)) < 0) {
- kfree(chip);
- pci_disable_device(pci);
+ err = pcim_request_all_regions(pci, card->shortname);
+ if (err < 0)
return err;
- }
if (device_type == DEVICE_ALI) {
/* ALI5455 has no ac97 region */
- chip->bmaddr = pci_iomap(pci, 0, 0);
- goto port_inited;
- }
-
- if (pci_resource_flags(pci, 2) & IORESOURCE_MEM) /* ICH4 and Nforce */
- chip->addr = pci_iomap(pci, 2, 0);
- else
- chip->addr = pci_iomap(pci, 0, 0);
- if (!chip->addr) {
- snd_printk(KERN_ERR "AC'97 space ioremap problem\n");
- snd_intel8x0_free(chip);
- return -EIO;
- }
- if (pci_resource_flags(pci, 3) & IORESOURCE_MEM) /* ICH4 */
- chip->bmaddr = pci_iomap(pci, 3, 0);
- else
- chip->bmaddr = pci_iomap(pci, 1, 0);
- if (!chip->bmaddr) {
- snd_printk(KERN_ERR "Controller space ioremap problem\n");
- snd_intel8x0_free(chip);
- return -EIO;
+ chip->bmaddr = pcim_iomap(pci, 0, 0);
+ } else {
+ if (pci_resource_flags(pci, 2) & IORESOURCE_MEM) /* ICH4 and Nforce */
+ chip->addr = pcim_iomap(pci, 2, 0);
+ else
+ chip->addr = pcim_iomap(pci, 0, 0);
+ if (pci_resource_flags(pci, 3) & IORESOURCE_MEM) /* ICH4 */
+ chip->bmaddr = pcim_iomap(pci, 3, 0);
+ else
+ chip->bmaddr = pcim_iomap(pci, 1, 0);
}
- port_inited:
chip->bdbars_count = bdbars[device_type];
/* initialize offsets */
@@ -3149,24 +2975,20 @@ static int snd_intel8x0_create(struct snd_card *card,
/* allocate buffer descriptor lists */
/* the start of each lists must be aligned to 8 bytes */
- if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
- chip->bdbars_count * sizeof(u32) * ICH_MAX_FRAGS * 2,
- &chip->bdbars) < 0) {
- snd_intel8x0_free(chip);
- snd_printk(KERN_ERR "intel8x0: cannot allocate buffer descriptors\n");
+ chip->bdbars = snd_devm_alloc_pages(&pci->dev, intel8x0_dma_type(chip),
+ chip->bdbars_count * sizeof(u32) *
+ ICH_MAX_FRAGS * 2);
+ if (!chip->bdbars)
return -ENOMEM;
- }
+
/* tables must be aligned to 8 bytes here, but the kernel pages
are much bigger, so we don't care (on i386) */
- /* workaround for 440MX */
- if (chip->fix_nocache)
- fill_nocache(chip->bdbars.area, chip->bdbars.bytes, 1);
int_sta_masks = 0;
for (i = 0; i < chip->bdbars_count; i++) {
ichdev = &chip->ichd[i];
- ichdev->bdbar = ((u32 *)chip->bdbars.area) +
+ ichdev->bdbar = ((__le32 *)chip->bdbars->area) +
(i * ICH_MAX_FRAGS * 2);
- ichdev->bdbar_addr = chip->bdbars.addr +
+ ichdev->bdbar_addr = chip->bdbars->addr +
(i * sizeof(u32) * ICH_MAX_FRAGS * 2);
int_sta_masks |= ichdev->int_sta_mask;
}
@@ -3199,28 +3021,25 @@ static int snd_intel8x0_create(struct snd_card *card,
for (i = 0; i < chip->max_codecs; i++)
chip->codec_isr_bits |= chip->codec_bit[i];
- if ((err = snd_intel8x0_chip_init(chip, 1)) < 0) {
- snd_intel8x0_free(chip);
+ err = snd_intel8x0_chip_init(chip, 1);
+ if (err < 0)
return err;
- }
/* request irq after initializaing int_sta_mask, etc */
+ /* NOTE: we don't use devm version here since it's released /
+ * re-acquired in PM callbacks.
+ * It's released explicitly in snd_intel8x0_free(), too.
+ */
if (request_irq(pci->irq, snd_intel8x0_interrupt,
IRQF_SHARED, KBUILD_MODNAME, chip)) {
- snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
- snd_intel8x0_free(chip);
+ dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
return -EBUSY;
}
chip->irq = pci->irq;
+ card->sync_irq = chip->irq;
- if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
- snd_intel8x0_free(chip);
- return err;
- }
+ card->private_free = snd_intel8x0_free;
- snd_card_set_dev(card, &pci->dev);
-
- *r_intel8x0 = chip;
return 0;
}
@@ -3253,12 +3072,12 @@ static struct shortname_table {
{ 0, NULL },
};
-static struct snd_pci_quirk spdif_aclink_defaults[] = {
+static const struct snd_pci_quirk spdif_aclink_defaults[] = {
SND_PCI_QUIRK(0x147b, 0x1c1a, "ASUS KN8", 1),
{ } /* end */
};
-/* look up white/black list for SPDIF over ac-link */
+/* look up allow/deny list for SPDIF over ac-link */
static int check_default_spdif_aclink(struct pci_dev *pci)
{
const struct snd_pci_quirk *w;
@@ -3266,48 +3085,50 @@ static int check_default_spdif_aclink(struct pci_dev *pci)
w = snd_pci_quirk_lookup(pci, spdif_aclink_defaults);
if (w) {
if (w->value)
- snd_printdd(KERN_INFO
- "intel8x0: Using SPDIF over AC-Link for %s\n",
+ dev_dbg(&pci->dev,
+ "Using SPDIF over AC-Link for %s\n",
snd_pci_quirk_name(w));
else
- snd_printdd(KERN_INFO
- "intel8x0: Using integrated SPDIF DMA for %s\n",
+ dev_dbg(&pci->dev,
+ "Using integrated SPDIF DMA for %s\n",
snd_pci_quirk_name(w));
return w->value;
}
return 0;
}
-static int snd_intel8x0_probe(struct pci_dev *pci,
- const struct pci_device_id *pci_id)
+static int __snd_intel8x0_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
{
struct snd_card *card;
struct intel8x0 *chip;
int err;
struct shortname_table *name;
- err = snd_card_create(index, id, THIS_MODULE, 0, &card);
+ err = snd_devm_card_new(&pci->dev, index, id, THIS_MODULE,
+ sizeof(*chip), &card);
if (err < 0)
return err;
+ chip = card->private_data;
if (spdif_aclink < 0)
spdif_aclink = check_default_spdif_aclink(pci);
- strcpy(card->driver, "ICH");
+ strscpy(card->driver, "ICH");
if (!spdif_aclink) {
switch (pci_id->driver_data) {
case DEVICE_NFORCE:
- strcpy(card->driver, "NFORCE");
+ strscpy(card->driver, "NFORCE");
break;
case DEVICE_INTEL_ICH4:
- strcpy(card->driver, "ICH4");
+ strscpy(card->driver, "ICH4");
}
}
- strcpy(card->shortname, "Intel ICH");
+ strscpy(card->shortname, "Intel ICH");
for (name = shortnames; name->id; name++) {
if (pci->device == name->id) {
- strcpy(card->shortname, name->s);
+ strscpy(card->shortname, name->s);
break;
}
}
@@ -3322,21 +3143,16 @@ static int snd_intel8x0_probe(struct pci_dev *pci,
buggy_irq = 0;
}
- if ((err = snd_intel8x0_create(card, pci, pci_id->driver_data,
- &chip)) < 0) {
- snd_card_free(card);
+ err = snd_intel8x0_init(card, pci, pci_id->driver_data);
+ if (err < 0)
return err;
- }
- card->private_data = chip;
- if ((err = snd_intel8x0_mixer(chip, ac97_clock, ac97_quirk)) < 0) {
- snd_card_free(card);
+ err = snd_intel8x0_mixer(chip, ac97_clock, ac97_quirk);
+ if (err < 0)
return err;
- }
- if ((err = snd_intel8x0_pcm(chip)) < 0) {
- snd_card_free(card);
+ err = snd_intel8x0_pcm(chip);
+ if (err < 0)
return err;
- }
snd_intel8x0_proc_init(chip);
@@ -3353,26 +3169,26 @@ static int snd_intel8x0_probe(struct pci_dev *pci,
}
}
- if ((err = snd_card_register(card)) < 0) {
- snd_card_free(card);
+ err = snd_card_register(card);
+ if (err < 0)
return err;
- }
+
pci_set_drvdata(pci, card);
return 0;
}
-static void snd_intel8x0_remove(struct pci_dev *pci)
+static int snd_intel8x0_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
{
- snd_card_free(pci_get_drvdata(pci));
+ return snd_card_free_on_error(&pci->dev, __snd_intel8x0_probe(pci, pci_id));
}
static struct pci_driver intel8x0_driver = {
.name = KBUILD_MODNAME,
.id_table = snd_intel8x0_ids,
.probe = snd_intel8x0_probe,
- .remove = snd_intel8x0_remove,
.driver = {
- .pm = INTEL8X0_PM_OPS,
+ .pm = &intel8x0_pm,
},
};