diff options
author | Takashi Iwai <tiwai@suse.de> | 2015-04-14 22:13:18 +0200 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2015-04-16 08:47:22 +0200 |
commit | a41d122449bea303ada415ef5fb2bf434f5481f9 (patch) | |
tree | e6f516f463dcf330567f226d4e9b1f43b2bc9e0e /sound/pci/hda | |
parent | ccc98865aa44184e34de8df96dc837726c978949 (diff) |
ALSA: hda - Embed bus into controller object
... and replace with the existing hda-core helper codes.
This reduces lots of lines, finally.
Since struct hda_bus is now embedded into struct azx,
snd_hda_bus_new() is moved and expanded from hda_codec.c to
hda_controller.c, accordingly. Also private_free bus ops and
private_data field are removed because we no longer need to point azx
object from bus (we can use container_of())
The spin locks are consolidated into the single one, bus->reg_lock.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda')
-rw-r--r-- | sound/pci/hda/hda_codec.c | 72 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.h | 3 | ||||
-rw-r--r-- | sound/pci/hda/hda_controller.c | 561 | ||||
-rw-r--r-- | sound/pci/hda/hda_controller.h | 65 | ||||
-rw-r--r-- | sound/pci/hda/hda_intel.c | 133 | ||||
-rw-r--r-- | sound/pci/hda/hda_intel.h | 1 | ||||
-rw-r--r-- | sound/pci/hda/hda_tegra.c | 43 |
7 files changed, 232 insertions, 646 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index ddebe7541390..2abf9f95dcbb 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -482,78 +482,6 @@ int snd_hda_get_devices(struct hda_codec *codec, hda_nid_t nid, } /* - * destructor - */ -static void snd_hda_bus_free(struct hda_bus *bus) -{ - if (!bus) - return; - if (bus->ops.private_free) - bus->ops.private_free(bus); - snd_hdac_bus_exit(&bus->core); - kfree(bus); -} - -static int snd_hda_bus_dev_free(struct snd_device *device) -{ - snd_hda_bus_free(device->device_data); - return 0; -} - -static int snd_hda_bus_dev_disconnect(struct snd_device *device) -{ - struct hda_bus *bus = device->device_data; - bus->shutdown = 1; - return 0; -} - -/** - * snd_hda_bus_new - create a HDA bus - * @card: the card entry - * @busp: the pointer to store the created bus instance - * - * Returns 0 if successful, or a negative error code. - */ -int snd_hda_bus_new(struct snd_card *card, - const struct hdac_bus_ops *ops, - const struct hdac_io_ops *io_ops, - struct hda_bus **busp) -{ - struct hda_bus *bus; - int err; - static struct snd_device_ops dev_ops = { - .dev_disconnect = snd_hda_bus_dev_disconnect, - .dev_free = snd_hda_bus_dev_free, - }; - - if (busp) - *busp = NULL; - - bus = kzalloc(sizeof(*bus), GFP_KERNEL); - if (!bus) - return -ENOMEM; - - err = snd_hdac_bus_init(&bus->core, card->dev, ops, io_ops); - if (err < 0) { - kfree(bus); - return err; - } - - bus->card = card; - mutex_init(&bus->prepare_mutex); - - err = snd_device_new(card, SNDRV_DEV_BUS, bus, &dev_ops); - if (err < 0) { - snd_hda_bus_free(bus); - return err; - } - if (busp) - *busp = bus; - return 0; -} -EXPORT_SYMBOL_GPL(snd_hda_bus_new); - -/* * read widget caps for each widget and store in cache */ static int read_widget_caps(struct hda_codec *codec, hda_nid_t fg_node) diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index c8031360de90..57b9aa0f36c1 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h @@ -42,8 +42,6 @@ struct hda_pcm_stream; /* bus operators */ struct hda_bus_ops { - /* free the private data */ - void (*private_free)(struct hda_bus *); /* attach a PCM stream */ int (*attach_pcm)(struct hda_bus *bus, struct hda_codec *codec, struct hda_pcm *pcm); @@ -73,7 +71,6 @@ struct hda_bus { struct snd_card *card; - void *private_data; struct pci_dev *pci; const char *modelname; struct hda_bus_ops ops; diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c index 32f98f71c1e6..21058b41b2c6 100644 --- a/sound/pci/hda/hda_controller.c +++ b/sound/pci/hda/hda_controller.c @@ -217,6 +217,7 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) { struct azx_pcm *apcm = snd_pcm_substream_chip(substream); struct azx *chip = apcm->chip; + struct hdac_bus *bus = azx_bus(chip); struct azx_dev *azx_dev; struct snd_pcm_substream *s; struct hdac_stream *hstr; @@ -257,7 +258,7 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) snd_pcm_trigger_done(s, substream); } - spin_lock(&chip->reg_lock); + spin_lock(&bus->reg_lock); /* first, set SYNC bits of corresponding streams */ snd_hdac_stream_sync_trigger(hstr, true, sbits, sync_reg); @@ -273,16 +274,16 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) snd_hdac_stream_stop(azx_stream(azx_dev)); } } - spin_unlock(&chip->reg_lock); + spin_unlock(&bus->reg_lock); snd_hdac_stream_sync(hstr, start, sbits); - spin_lock(&chip->reg_lock); + spin_lock(&bus->reg_lock); /* reset SYNC bits */ snd_hdac_stream_sync_trigger(hstr, false, sbits, sync_reg); if (start) snd_hdac_stream_timecounter_init(hstr, sbits); - spin_unlock(&chip->reg_lock); + spin_unlock(&bus->reg_lock); return 0; } @@ -522,10 +523,11 @@ static void azx_pcm_free(struct snd_pcm *pcm) #define MAX_PREALLOC_SIZE (32 * 1024 * 1024) -static int azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec, +static int azx_attach_pcm_stream(struct hda_bus *_bus, struct hda_codec *codec, struct hda_pcm *cpcm) { - struct azx *chip = bus->private_data; + struct hdac_bus *bus = &_bus->core; + struct azx *chip = bus_to_azx(bus); struct snd_pcm *pcm; struct azx_pcm *apcm; int pcm_dev = cpcm->device; @@ -573,89 +575,6 @@ static int azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec, return 0; } -/* - * CORB / RIRB interface - */ -static int azx_alloc_cmd_io(struct azx *chip) -{ - /* single page (at least 4096 bytes) must suffice for both ringbuffes */ - return chip->io_ops->dma_alloc_pages(azx_bus(chip), SNDRV_DMA_TYPE_DEV, - PAGE_SIZE, &chip->rb); -} - -static void azx_init_cmd_io(struct azx *chip) -{ - int timeout; - - spin_lock_irq(&chip->reg_lock); - /* CORB set up */ - chip->corb.addr = chip->rb.addr; - chip->corb.buf = (u32 *)chip->rb.area; - azx_writel(chip, CORBLBASE, (u32)chip->corb.addr); - azx_writel(chip, CORBUBASE, upper_32_bits(chip->corb.addr)); - - /* set the corb size to 256 entries (ULI requires explicitly) */ - azx_writeb(chip, CORBSIZE, 0x02); - /* set the corb write pointer to 0 */ - azx_writew(chip, CORBWP, 0); - - /* reset the corb hw read pointer */ - azx_writew(chip, CORBRP, AZX_CORBRP_RST); - if (!(chip->driver_caps & AZX_DCAPS_CORBRP_SELF_CLEAR)) { - for (timeout = 1000; timeout > 0; timeout--) { - if ((azx_readw(chip, CORBRP) & AZX_CORBRP_RST) == AZX_CORBRP_RST) - break; - udelay(1); - } - if (timeout <= 0) - dev_err(chip->card->dev, "CORB reset timeout#1, CORBRP = %d\n", - azx_readw(chip, CORBRP)); - - azx_writew(chip, CORBRP, 0); - for (timeout = 1000; timeout > 0; timeout--) { - if (azx_readw(chip, CORBRP) == 0) - break; - udelay(1); - } - if (timeout <= 0) - dev_err(chip->card->dev, "CORB reset timeout#2, CORBRP = %d\n", - azx_readw(chip, CORBRP)); - } - - /* enable corb dma */ - azx_writeb(chip, CORBCTL, AZX_CORBCTL_RUN); - - /* RIRB set up */ - chip->rirb.addr = chip->rb.addr + 2048; - chip->rirb.buf = (u32 *)(chip->rb.area + 2048); - chip->rirb.wp = chip->rirb.rp = 0; - memset(chip->rirb.cmds, 0, sizeof(chip->rirb.cmds)); - azx_writel(chip, RIRBLBASE, (u32)chip->rirb.addr); - azx_writel(chip, RIRBUBASE, upper_32_bits(chip->rirb.addr)); - - /* set the rirb size to 256 entries (ULI requires explicitly) */ - azx_writeb(chip, RIRBSIZE, 0x02); - /* reset the rirb hw write pointer */ - azx_writew(chip, RIRBWP, AZX_RIRBWP_RST); - /* set N=1, get RIRB response interrupt for new entry */ - if (chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND) - azx_writew(chip, RINTCNT, 0xc0); - else - azx_writew(chip, RINTCNT, 1); - /* enable rirb dma and response irq */ - azx_writeb(chip, RIRBCTL, AZX_RBCTL_DMA_EN | AZX_RBCTL_IRQ_EN); - spin_unlock_irq(&chip->reg_lock); -} - -static void azx_free_cmd_io(struct azx *chip) -{ - spin_lock_irq(&chip->reg_lock); - /* disable ringbuffer DMAs */ - azx_writeb(chip, RIRBCTL, 0); - azx_writeb(chip, CORBCTL, 0); - spin_unlock_irq(&chip->reg_lock); -} - static unsigned int azx_command_addr(u32 cmd) { unsigned int addr = cmd >> 28; @@ -668,92 +587,12 @@ static unsigned int azx_command_addr(u32 cmd) return addr; } -/* send a command */ -static int azx_corb_send_cmd(struct hda_bus *bus, u32 val) -{ - struct azx *chip = bus->private_data; - unsigned int addr = azx_command_addr(val); - unsigned int wp, rp; - - spin_lock_irq(&chip->reg_lock); - - /* add command to corb */ - wp = azx_readw(chip, CORBWP); - if (wp == 0xffff) { - /* something wrong, controller likely turned to D3 */ - spin_unlock_irq(&chip->reg_lock); - return -EIO; - } - wp++; - wp %= AZX_MAX_CORB_ENTRIES; - - rp = azx_readw(chip, CORBRP); - if (wp == rp) { - /* oops, it's full */ - spin_unlock_irq(&chip->reg_lock); - return -EAGAIN; - } - - chip->rirb.cmds[addr]++; - chip->corb.buf[wp] = cpu_to_le32(val); - azx_writew(chip, CORBWP, wp); - - spin_unlock_irq(&chip->reg_lock); - - return 0; -} - -#define AZX_RIRB_EX_UNSOL_EV (1<<4) - -/* retrieve RIRB entry - called from interrupt handler */ -static void azx_update_rirb(struct azx *chip) -{ - unsigned int rp, wp; - unsigned int addr; - u32 res, res_ex; - - wp = azx_readw(chip, RIRBWP); - if (wp == 0xffff) { - /* something wrong, controller likely turned to D3 */ - return; - } - - if (wp == chip->rirb.wp) - return; - chip->rirb.wp = wp; - - while (chip->rirb.rp != wp) { - chip->rirb.rp++; - chip->rirb.rp %= AZX_MAX_RIRB_ENTRIES; - - rp = chip->rirb.rp << 1; /* an RIRB entry is 8-bytes */ - res_ex = le32_to_cpu(chip->rirb.buf[rp + 1]); - res = le32_to_cpu(chip->rirb.buf[rp]); - addr = res_ex & 0xf; - if ((addr >= AZX_MAX_CODECS) || !(chip->codec_mask & (1 << addr))) { - dev_err(chip->card->dev, "spurious response %#x:%#x, rp = %d, wp = %d", - res, res_ex, - chip->rirb.rp, wp); - snd_BUG(); - } else if (res_ex & AZX_RIRB_EX_UNSOL_EV) - snd_hda_queue_unsol_event(chip->bus, res, res_ex); - else if (chip->rirb.cmds[addr]) { - chip->rirb.res[addr] = res; - smp_wmb(); - chip->rirb.cmds[addr]--; - } else if (printk_ratelimit()) { - dev_err(chip->card->dev, "spurious response %#x:%#x, last cmd=%#08x\n", - res, res_ex, - chip->last_cmd[addr]); - } - } -} - /* receive a response */ -static int azx_rirb_get_response(struct hda_bus *bus, unsigned int addr, +static int azx_rirb_get_response(struct hdac_bus *bus, unsigned int addr, unsigned int *res) { - struct azx *chip = bus->private_data; + struct azx *chip = bus_to_azx(bus); + struct hda_bus *hbus = &chip->bus; unsigned long timeout; unsigned long loopcounter; int do_poll = 0; @@ -762,23 +601,21 @@ static int azx_rirb_get_response(struct hda_bus *bus, unsigned int addr, timeout = jiffies + msecs_to_jiffies(1000); for (loopcounter = 0;; loopcounter++) { - if (chip->polling_mode || do_poll) { - spin_lock_irq(&chip->reg_lock); - azx_update_rirb(chip); - spin_unlock_irq(&chip->reg_lock); - } - if (!chip->rirb.cmds[addr]) { - smp_rmb(); - + spin_lock_irq(&bus->reg_lock); + if (chip->polling_mode || do_poll) + snd_hdac_bus_update_rirb(bus); + if (!bus->rirb.cmds[addr]) { if (!do_poll) chip->poll_count = 0; if (res) - *res = chip->rirb.res[addr]; /* the last value */ + *res = bus->rirb.res[addr]; /* the last value */ + spin_unlock_irq(&bus->reg_lock); return 0; } + spin_unlock_irq(&bus->reg_lock); if (time_after(jiffies, timeout)) break; - if (bus->needs_damn_long_delay || loopcounter > 3000) + if (hbus->needs_damn_long_delay || loopcounter > 3000) msleep(2); /* temporary workaround */ else { udelay(10); @@ -786,13 +623,13 @@ static int azx_rirb_get_response(struct hda_bus *bus, unsigned int addr, } } - if (bus->no_response_fallback) + if (hbus->no_response_fallback) return -EIO; if (!chip->polling_mode && chip->poll_count < 2) { dev_dbg(chip->card->dev, "azx_get_response timeout, polling the codec once: last cmd=0x%08x\n", - chip->last_cmd[addr]); + bus->last_cmd[addr]); do_poll = 1; chip->poll_count++; goto again; @@ -802,7 +639,7 @@ static int azx_rirb_get_response(struct hda_bus *bus, unsigned int addr, if (!chip->polling_mode) { dev_warn(chip->card->dev, "azx_get_response timeout, switching to polling mode: last cmd=0x%08x\n", - chip->last_cmd[addr]); + bus->last_cmd[addr]); chip->polling_mode = 1; goto again; } @@ -810,8 +647,8 @@ static int azx_rirb_get_response(struct hda_bus *bus, unsigned int addr, if (chip->msi) { dev_warn(chip->card->dev, "No response from codec, disabling MSI: last cmd=0x%08x\n", - chip->last_cmd[addr]); - if (chip->ops->disable_msi_reset_irq(chip) && + bus->last_cmd[addr]); + if (chip->ops->disable_msi_reset_irq && chip->ops->disable_msi_reset_irq(chip) < 0) return -EIO; goto again; @@ -828,20 +665,17 @@ static int azx_rirb_get_response(struct hda_bus *bus, unsigned int addr, /* a fatal communication error; need either to reset or to fallback * to the single_cmd mode */ - if (bus->allow_bus_reset && !bus->response_reset && !bus->in_reset) { - bus->response_reset = 1; + if (hbus->allow_bus_reset && !hbus->response_reset && !hbus->in_reset) { + hbus->response_reset = 1; return -EAGAIN; /* give a chance to retry */ } dev_err(chip->card->dev, "azx_get_response timeout, switching to single_cmd mode: last cmd=0x%08x\n", - chip->last_cmd[addr]); + bus->last_cmd[addr]); chip->single_cmd = 1; - bus->response_reset = 0; - /* release CORB/RIRB */ - azx_free_cmd_io(chip); - /* disable unsolicited responses */ - azx_writel(chip, GCTL, azx_readl(chip, GCTL) & ~AZX_GCTL_UNSOL); + hbus->response_reset = 0; + snd_hdac_bus_stop_cmd_io(bus); return -EIO; } @@ -864,7 +698,7 @@ static int azx_single_wait_for_response(struct azx *chip, unsigned int addr) /* check IRV busy bit */ if (azx_readw(chip, IRS) & AZX_IRS_VALID) { /* reuse rirb.res as the response return value */ - chip->rirb.res[addr] = azx_readl(chip, IR); + azx_bus(chip)->rirb.res[addr] = azx_readl(chip, IR); return 0; } udelay(1); @@ -872,17 +706,18 @@ static int azx_single_wait_for_response(struct azx *chip, unsigned int addr) if (printk_ratelimit()) dev_dbg(chip->card->dev, "get_response timeout: IRS=0x%x\n", azx_readw(chip, IRS)); - chip->rirb.res[addr] = -1; + azx_bus(chip)->rirb.res[addr] = -1; return -EIO; } /* send a command */ -static int azx_single_send_cmd(struct hda_bus *bus, u32 val) +static int azx_single_send_cmd(struct hdac_bus *bus, u32 val) { - struct azx *chip = bus->private_data; + struct azx *chip = bus_to_azx(bus); unsigned int addr = azx_command_addr(val); int timeout = 50; + bus->last_cmd[azx_command_addr(val)] = val; while (timeout--) { /* check ICB busy bit */ if (!((azx_readw(chip, IRS) & AZX_IRS_BUSY))) { @@ -904,13 +739,11 @@ static int azx_single_send_cmd(struct hda_bus *bus, u32 val) } /* receive a response */ -static int azx_single_get_response(struct hda_bus *bus, unsigned int addr, +static int azx_single_get_response(struct hdac_bus *bus, unsigned int addr, unsigned int *res) { - struct azx *chip = bus->private_data; - if (res) - *res = chip->rirb.res[addr]; + *res = bus->rirb.res[addr]; return 0; } @@ -922,26 +755,24 @@ static int azx_single_get_response(struct hda_bus *bus, unsigned int addr, */ /* send a command */ -static int azx_send_cmd(struct hdac_bus *_bus, unsigned int val) +static int azx_send_cmd(struct hdac_bus *bus, unsigned int val) { - struct hda_bus *bus = to_hda_bus(_bus); - struct azx *chip = bus->private_data; + struct azx *chip = bus_to_azx(bus); if (chip->disabled) return 0; - chip->last_cmd[azx_command_addr(val)] = val; if (chip->single_cmd) return azx_single_send_cmd(bus, val); else - return azx_corb_send_cmd(bus, val); + return snd_hdac_bus_send_cmd(bus, val); } /* get a response */ -static int azx_get_response(struct hdac_bus *_bus, unsigned int addr, +static int azx_get_response(struct hdac_bus *bus, unsigned int addr, unsigned int *res) { - struct hda_bus *bus = to_hda_bus(_bus); - struct azx *chip = bus->private_data; + struct azx *chip = bus_to_azx(bus); + if (chip->disabled) return 0; if (chip->single_cmd) @@ -974,11 +805,12 @@ azx_get_dsp_loader_dev(struct azx *chip) return NULL; } -static int azx_load_dsp_prepare(struct hda_bus *bus, unsigned int format, +static int azx_load_dsp_prepare(struct hda_bus *_bus, unsigned int format, unsigned int byte_size, struct snd_dma_buffer *bufp) { - struct azx *chip = bus->private_data; + struct hdac_bus *bus = &_bus->core; + struct azx *chip = bus_to_azx(bus); struct azx_dev *azx_dev; struct hdac_stream *hstr; bool saved = false; @@ -986,19 +818,19 @@ static int azx_load_dsp_prepare(struct hda_bus *bus, unsigned int format, azx_dev = azx_get_dsp_loader_dev(chip); hstr = azx_stream(azx_dev); - spin_lock_irq(&chip->reg_lock); + spin_lock_irq(&bus->reg_lock); if (hstr->opened) { chip->saved_azx_dev = *azx_dev; saved = true; } - spin_unlock_irq(&chip->reg_lock); + spin_unlock_irq(&bus->reg_lock); err = snd_hdac_dsp_prepare(hstr, format, byte_size, bufp); if (err < 0) { - spin_lock_irq(&chip->reg_lock); + spin_lock_irq(&bus->reg_lock); if (saved) *azx_dev = chip->saved_azx_dev; - spin_unlock_irq(&chip->reg_lock); + spin_unlock_irq(&bus->reg_lock); return err; } @@ -1006,18 +838,20 @@ static int azx_load_dsp_prepare(struct hda_bus *bus, unsigned int format, return err; } -static void azx_load_dsp_trigger(struct hda_bus *bus, bool start) +static void azx_load_dsp_trigger(struct hda_bus *_bus, bool start) { - struct azx *chip = bus->private_data; + struct hdac_bus *bus = &_bus->core; + struct azx *chip = bus_to_azx(bus); struct azx_dev *azx_dev = azx_get_dsp_loader_dev(chip); snd_hdac_dsp_trigger(azx_stream(azx_dev), start); } -static void azx_load_dsp_cleanup(struct hda_bus *bus, +static void azx_load_dsp_cleanup(struct hda_bus *_bus, struct snd_dma_buffer *dmab) { - struct azx *chip = bus->private_data; + struct hdac_bus *bus = &_bus->core; + struct azx *chip = bus_to_azx(bus); struct azx_dev *azx_dev = azx_get_dsp_loader_dev(chip); struct hdac_stream *hstr = azx_stream(azx_dev); @@ -1025,207 +859,24 @@ static void azx_load_dsp_cleanup(struct hda_bus *bus, return; snd_hdac_dsp_cleanup(hstr, dmab); - spin_lock_irq(&chip->reg_lock); + spin_lock_irq(&bus->reg_lock); if (hstr->opened) *azx_dev = chip->saved_azx_dev; hstr->locked = false; - spin_unlock_irq(&chip->reg_lock); + spin_unlock_irq(&bus->reg_lock); } #endif /* CONFIG_SND_HDA_DSP_LOADER */ -int azx_alloc_stream_pages(struct azx *chip) -{ - struct hdac_bus *bus = azx_bus(chip); - struct hdac_stream *s; - int err; - - list_for_each_entry(s, &bus->stream_list, list) { - /* allocate memory for the BDL for each stream */ - err = chip->io_ops->dma_alloc_pages(azx_bus(chip), SNDRV_DMA_TYPE_DEV, - BDL_SIZE, &s->bdl); - if (err < 0) - return -ENOMEM; - } - - /* allocate memory for the position buffer */ - err = chip->io_ops->dma_alloc_pages(azx_bus(chip), SNDRV_DMA_TYPE_DEV, - chip->num_streams * 8, &chip->posbuf); - if (err < 0) - return -ENOMEM; - - /* allocate CORB/RIRB */ - err = azx_alloc_cmd_io(chip); - if (err < 0) - return err; - return 0; -} -EXPORT_SYMBOL_GPL(azx_alloc_stream_pages); - -void azx_free_stream_pages(struct azx *chip) -{ - struct hdac_bus *bus = azx_bus(chip); - struct hdac_stream *s, *next; - - list_for_each_entry_safe(s, next, &bus->stream_list, list) { - if (s->bdl.area) - chip->io_ops->dma_free_pages(azx_bus(chip), &s->bdl); - kfree(s); - } - - if (chip->rb.area) - chip->io_ops->dma_free_pages(azx_bus(chip), &chip->rb); - if (chip->posbuf.area) - chip->io_ops->dma_free_pages(azx_bus(chip), &chip->posbuf); -} -EXPORT_SYMBOL_GPL(azx_free_stream_pages); - -/* - * Lowlevel interface - */ - -/* enter link reset */ -void azx_enter_link_reset(struct azx *chip) -{ - unsigned long timeout; - - /* reset controller */ - azx_writel(chip, GCTL, azx_readl(chip, GCTL) & ~AZX_GCTL_RESET); - - timeout = jiffies + msecs_to_jiffies(100); - while ((azx_readb(chip, GCTL) & AZX_GCTL_RESET) && - time_before(jiffies, timeout)) - usleep_range(500, 1000); -} -EXPORT_SYMBOL_GPL(azx_enter_link_reset); - -/* exit link reset */ -static void azx_exit_link_reset(struct azx *chip) -{ - unsigned long timeout; - - azx_writeb(chip, GCTL, azx_readb(chip, GCTL) | AZX_GCTL_RESET); - - timeout = jiffies + msecs_to_jiffies(100); - while (!azx_readb(chip, GCTL) && - time_before(jiffies, timeout)) - usleep_range(500, 1000); -} - -/* reset codec link */ -static int azx_reset(struct azx *chip, bool full_reset) -{ - if (!full_reset) - goto __skip; - - /* clear STATESTS */ - azx_writew(chip, STATESTS, STATESTS_INT_MASK); - - /* reset controller */ - azx_enter_link_reset(chip); - - /* delay for >= 100us for codec PLL to settle per spec - * Rev 0.9 section 5.5.1 - */ - usleep_range(500, 1000); - - /* Bring controller out of reset */ - azx_exit_link_reset(chip); - - /* Brent Chartrand said to wait >= 540us for codecs to initialize */ - usleep_range(1000, 1200); - - __skip: - /* check to see if controller is ready */ - if (!azx_readb(chip, GCTL)) { - dev_dbg(chip->card->dev, "azx_reset: controller not ready!\n"); - return -EBUSY; - } - - /* Accept unsolicited responses */ - if (!chip->single_cmd) - azx_writel(chip, GCTL, azx_readl(chip, GCTL) | - AZX_GCTL_UNSOL); - - /* detect codecs */ - if (!chip->codec_mask) { - chip->codec_mask = azx_readw(chip, STATESTS); - dev_dbg(chip->card->dev, "codec_mask = 0x%x\n", - chip->codec_mask); - } - - return 0; -} - -/* enable interrupts */ -static void azx_int_enable(struct azx *chip) -{ - /* enable controller CIE and GIE */ - azx_writel(chip, INTCTL, azx_readl(chip, INTCTL) | - AZX_INT_CTRL_EN | AZX_INT_GLOBAL_EN); -} - -/* disable interrupts */ -static void azx_int_disable(struct azx *chip) -{ - struct hdac_bus *bus = azx_bus(chip); - struct hdac_stream *s; - - /* disable interrupts in stream descriptor */ - list_for_each_entry(s, &bus->stream_list, list) - snd_hdac_stream_updateb(s, SD_CTL, SD_INT_MASK, 0); - - /* disable SIE for all streams */ - azx_writeb(chip, INTCTL, 0); - - /* disable controller CIE and GIE */ - azx_writel(chip, INTCTL, azx_readl(chip, INTCTL) & - ~(AZX_INT_CTRL_EN | AZX_INT_GLOBAL_EN)); -} - -/* clear interrupts */ -static void azx_int_clear(struct azx *chip) -{ - struct hdac_bus *bus = azx_bus(chip); - struct hdac_stream *s; - - /* clear stream status */ - list_for_each_entry(s, &bus->stream_list, list) - snd_hdac_stream_writeb(s, SD_STS, SD_INT_MASK); - - /* clear STATESTS */ - azx_writew(chip, STATESTS, STATESTS_INT_MASK); - - /* clear rirb status */ - azx_writeb(chip, RIRBSTS, RIRB_INT_MASK); - - /* clear int status */ - azx_writel(chip, INTSTS, AZX_INT_CTRL_EN | AZX_INT_ALL_STREAM); -} - /* * reset and start the controller registers */ void azx_init_chip(struct azx *chip, bool full_reset) { - if (chip->initialized) - return; - - /* reset controller */ - azx_reset(chip, full_reset); - - /* initialize interrupts */ - azx_int_clear(chip); - azx_int_enable(chip); - - /* initialize the codec command I/O */ - if (!chip->single_cmd) - azx_init_cmd_io(chip); - - /* program the position buffer */ - azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr); - azx_writel(chip, DPUBASE, upper_32_bits(chip->posbuf.addr)); - - chip->initialized = 1; + if (snd_hdac_bus_init_chip(azx_bus(chip), full_reset)) { + /* correct RINTCNT for CXT */ + if (chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND) + azx_writew(chip, RINTCNT, 0xc0); + } } EXPORT_SYMBOL_GPL(azx_init_chip); @@ -1241,21 +892,7 @@ EXPORT_SYMBOL_GPL(azx_stop_all_streams); void azx_stop_chip(struct azx *chip) { - if (!chip->initialized) - return; - - /* disable interrupts */ - azx_int_disable(chip); - azx_int_clear(chip); - - /* disable CORB/RIRB */ - azx_free_cmd_io(chip); - - /* disable position buffer */ - azx_writel(chip, DPLBASE, 0); - azx_writel(chip, DPUBASE, 0); - - chip->initialized = 0; + snd_hdac_bus_stop_chip(azx_bus(chip)); } EXPORT_SYMBOL_GPL(azx_stop_chip); @@ -1264,16 +901,15 @@ EXPORT_SYMBOL_GPL(azx_stop_chip); */ static void stream_update(struct hdac_bus *bus, struct hdac_stream *s) { - struct hda_bus *hbus = container_of(bus, struct hda_bus, core); - struct azx *chip = hbus->private_data; + struct azx *chip = bus_to_azx(bus); struct azx_dev *azx_dev = stream_to_azx_dev(s); /* check whether this IRQ is really acceptable */ if (!chip->ops->position_check || chip->ops->position_check(chip, azx_dev)) { - spin_unlock(&chip->reg_lock); - snd_pcm_period_elapsed(azx_dev->core.substream); - spin_lock(&chip->reg_lock); + spin_unlock(&bus->reg_lock); + snd_pcm_period_elapsed(azx_stream(azx_dev)->substream); + spin_lock(&bus->reg_lock); } } @@ -1289,16 +925,16 @@ irqreturn_t azx_interrupt(int irq, void *dev_id) return IRQ_NONE; #endif - spin_lock(&chip->reg_lock); + spin_lock(&bus->reg_lock); if (chip->disabled) { - spin_unlock(&chip->reg_lock); + spin_unlock(&bus->reg_lock); return IRQ_NONE; } status = azx_readl(chip, INTSTS); if (status == 0 || status == 0xffffffff) { - spin_unlock(&chip->reg_lock); + spin_unlock(&bus->reg_lock); return IRQ_NONE; } @@ -1310,12 +946,12 @@ irqreturn_t azx_interrupt(int irq, void *dev_id) if (status & RIRB_INT_RESPONSE) { if (chip->driver_caps & AZX_DCAPS_RIRB_PRE_DELAY) udelay(80); - azx_update_rirb(chip); + snd_hdac_bus_update_rirb(bus); } azx_writeb(chip, RIRBSTS, RIRB_INT_MASK); } - spin_unlock(&chip->reg_lock); + spin_unlock(&bus->reg_lock); return IRQ_HANDLED; } @@ -1334,7 +970,7 @@ static int probe_codec(struct azx *chip, int addr) (AC_VERB_PARAMETERS << 8) | AC_PAR_VENDOR_ID; struct hdac_bus *bus = azx_bus(chip); int err; - unsigned int res; + unsigned int res = -1; mutex_lock(&bus->cmd_mutex); chip->probing = 1; @@ -1350,13 +986,13 @@ static int probe_codec(struct azx *chip, int addr) static void azx_bus_reset(struct hda_bus *bus) { - struct azx *chip = bus->private_data; + struct azx *chip = bus_to_azx(&bus->core); bus->in_reset = 1; azx_stop_chip(chip); azx_init_chip(chip, true); - if (chip->initialized) - snd_hda_bus_reset(chip->bus); + if (bus->core.chip_init) + snd_hda_bus_reset(bus); bus->in_reset = 0; } @@ -1392,17 +1028,19 @@ static struct hda_bus_ops bus_ops = { }; /* HD-audio bus initialization */ -int azx_bus_create(struct azx *chip, const char *model) +int azx_bus_init(struct azx *chip, const char *model, + const struct hdac_io_ops *io_ops) { - struct hda_bus *bus; + struct hda_bus *bus = &chip->bus; int err; - err = snd_hda_bus_new(chip->card, &bus_core_ops, chip->io_ops, &bus); + err = snd_hdac_bus_init(&bus->core, chip->card->dev, &bus_core_ops, + io_ops); if (err < 0) return err; - chip->bus = bus; - bus->private_data = chip; + bus->card = chip->card; + mutex_init(&bus->prepare_mutex); bus->pci = chip->pci; bus->modelname = model; bus->ops = bus_ops; @@ -1412,6 +1050,8 @@ int azx_bus_create(struct azx *chip, const char *model) bus->core.use_posbuf = true; if (chip->bdl_pos_adj) bus->core.bdl_pos_adj = chip->bdl_pos_adj[chip->dev_index]; + if (chip->driver_caps & AZX_DCAPS_CORBRP_SELF_CLEAR) + bus->core.corbrp_self_clear = true; if (chip->driver_caps & AZX_DCAPS_RIRB_DELAY) { dev_dbg(chip->card->dev, "Enable delay in RIRB handling\n"); @@ -1430,12 +1070,12 @@ int azx_bus_create(struct azx *chip, const char *model) return 0; } -EXPORT_SYMBOL_GPL(azx_bus_create); +EXPORT_SYMBOL_GPL(azx_bus_init); /* Probe codecs */ int azx_probe_codecs(struct azx *chip, unsigned int max_slots) { - struct hda_bus *bus = chip->bus; + struct hdac_bus *bus = azx_bus(chip); int c, codecs, err; codecs = 0; @@ -1444,14 +1084,14 @@ int azx_probe_codecs(struct azx *chip, unsigned int max_slots) /* First try to probe all given codec slots */ for (c = 0; c < max_slots; c++) { - if ((chip->codec_mask & (1 << c)) & chip->codec_probe_mask) { + if ((bus->codec_mask & (1 << c)) & chip->codec_probe_mask) { if (probe_codec(chip, c) < 0) { /* Some BIOSen give you wrong codec addresses * that don't exist */ dev_warn(chip->card->dev, "Codec #%d probe error; disabling it...\n", c); - chip->codec_mask &= ~(1 << c); + bus->codec_mask &= ~(1 << c); /* More badly, accessing to a non-existing * codec often screws up the controller chip, * and disturbs the further communications. @@ -1467,9 +1107,9 @@ int azx_probe_codecs(struct azx *chip, unsigned int max_slots) /* Then create codec instances */ for (c = 0; c < max_slots; c++) { - if ((chip->codec_mask & (1 << c)) & chip->codec_probe_mask) { + if ((bus->codec_mask & (1 << c)) & chip->codec_probe_mask) { struct hda_codec *codec; - err = snd_hda_codec_new(bus, bus->card, c, &codec); + err = snd_hda_codec_new(&chip->bus, chip->card, c, &codec); if (err < 0) continue; codec->jackpoll_interval = get_jackpoll_interval(chip); @@ -1489,7 +1129,7 @@ EXPORT_SYMBOL_GPL(azx_probe_codecs); int azx_codec_configure(struct azx *chip) { struct hda_codec *codec; - list_for_each_codec(codec, chip->bus) { + list_for_each_codec(codec, &chip->bus) { snd_hda_codec_configure(codec); } return 0; @@ -1505,7 +1145,7 @@ static int stream_direction(struct azx *chip, unsigned char index) } /* initialize SD streams */ -int azx_init_stream(struct azx *chip) +int azx_init_streams(struct azx *chip) { int i; int stream_tags[2] = { 0, 0 }; @@ -1538,4 +1178,17 @@ int azx_init_stream(struct azx *chip) return 0; } -EXPORT_SYMBOL_GPL(azx_init_stream); +EXPORT_SYMBOL_GPL(azx_init_streams); + +void azx_free_streams(struct azx *chip) +{ + struct hdac_bus *bus = azx_bus(chip); + struct hdac_stream *s; + + while (!list_empty(&bus->stream_list)) { + s = list_first_entry(&bus->stream_list, struct hdac_stream, list); + list_del(&s->list); + kfree(stream_to_azx_dev(s)); + } +} +EXPORT_SYMBOL_GPL(azx_free_streams); diff --git a/sound/pci/hda/hda_controller.h b/sound/pci/hda/hda_controller.h index b45568d83860..e8edb02c12d3 100644 --- a/sound/pci/hda/hda_controller.h +++ b/sound/pci/hda/hda_controller.h @@ -75,18 +75,6 @@ struct azx_dev { #define azx_stream(dev) (&(dev)->core) #define stream_to_azx_dev(s) container_of(s, struct azx_dev, core) -/* CORB/RIRB */ -struct azx_rb { - u32 *buf; /* CORB/RIRB buffer - * Each CORB entry is 4byte, RIRB is 8byte - */ - dma_addr_t addr; /* physical address of CORB/RIRB buffer */ - /* for RIRB */ - unsigned short rp, wp; /* read/write pointers */ - int cmds[AZX_MAX_CODECS]; /* number of pending requests */ - u32 res[AZX_MAX_CODECS]; /* last read value */ -}; - struct azx; /* Functions to read/write to hda registers. */ @@ -116,6 +104,8 @@ typedef unsigned int (*azx_get_pos_callback_t)(struct azx *, struct azx_dev *); typedef int (*azx_get_delay_callback_t)(struct azx *, struct azx_dev *, unsigned int pos); struct azx { + struct hda_bus bus; + struct snd_card *card; struct pci_dev *pci; int dev_index; @@ -132,38 +122,21 @@ struct azx { /* Register interaction. */ const struct hda_controller_ops *ops; - const struct hdac_io_ops *io_ops; /* position adjustment callbacks */ azx_get_pos_callback_t get_position[2]; azx_get_delay_callback_t get_delay[2]; - /* pci resources */ - unsigned long addr; - void __iomem *remap_addr; - int irq; - /* locks */ - spinlock_t reg_lock; struct mutex open_mutex; /* Prevents concurrent open/close operations */ /* PCM */ struct list_head pcm_list; /* azx_pcm list */ /* HD codec */ - unsigned short codec_mask; int codec_probe_mask; /* copied from probe_mask option */ - struct hda_bus *bus; unsigned int beep_mode; - /* CORB/RIRB */ - struct azx_rb corb; - struct azx_rb rirb; - - /* CORB/RIRB and position buffers */ - struct snd_dma_buffer rb; - struct snd_dma_buffer posbuf; - #ifdef CONFIG_SND_HDA_PATCH_LOADER const struct firmware *fw; #endif @@ -172,7 +145,6 @@ struct azx { const int *bdl_pos_adj; int poll_count; unsigned int running:1; - unsigned int initialized:1; unsigned int single_cmd:1; unsigned int polling_mode:1; unsigned int msi:1; @@ -182,15 +154,13 @@ struct azx { unsigned int region_requested:1; unsigned int disabled:1; /* disabled by VGA-switcher */ - /* for debugging */ - unsigned int last_cmd[AZX_MAX_CODECS]; - #ifdef CONFIG_SND_HDA_DSP_LOADER struct azx_dev saved_azx_dev; #endif }; -#define azx_bus(chip) (&(chip)->bus->core) +#define azx_bus(chip) (&(chip)->bus.core) +#define bus_to_azx(_bus) container_of(_bus, struct azx, bus.core) #ifdef CONFIG_X86 #define azx_snoop(chip) ((chip)->snoop) @@ -203,17 +173,17 @@ struct azx { */ #define azx_writel(chip, reg, value) \ - ((chip)->io_ops->reg_writel(value, (chip)->remap_addr + AZX_REG_##reg)) + snd_hdac_chip_writel(azx_bus(chip), reg, value) #define azx_readl(chip, reg) \ - ((chip)->io_ops->reg_readl((chip)->remap_addr + AZX_REG_##reg)) + snd_hdac_chip_readl(azx_bus(chip), reg) #define azx_writew(chip, reg, value) \ - ((chip)->io_ops->reg_writew(value, (chip)->remap_addr + AZX_REG_##reg)) + snd_hdac_chip_writew(azx_bus(chip), reg, value) #define azx_readw(chip, reg) \ - ((chip)->io_ops->reg_readw((chip)->remap_addr + AZX_REG_##reg)) + snd_hdac_chip_readw(azx_bus(chip), reg) #define azx_writeb(chip, reg, value) \ - ((chip)->io_ops->reg_writeb(value, (chip)->remap_addr + AZX_REG_##reg)) + snd_hdac_chip_writeb(azx_bus(chip), reg, value) #define azx_readb(chip, reg) \ - ((chip)->io_ops->reg_readb((chip)->remap_addr + AZX_REG_##reg)) + snd_hdac_chip_readb(azx_bus(chip), reg) #define azx_sd_writel(chip, dev, reg, value) \ snd_hdac_stream_writel(&(dev)->core, reg, value) @@ -244,19 +214,24 @@ unsigned int azx_get_pos_posbuf(struct azx *chip, struct azx_dev *azx_dev); void azx_stop_all_streams(struct azx *chip); /* Allocation functions. */ -int azx_alloc_stream_pages(struct azx *chip); -void azx_free_stream_pages(struct azx *chip); +#define azx_alloc_stream_pages(chip) \ + snd_hdac_bus_alloc_stream_pages(azx_bus(chip)) +#define azx_free_stream_pages(chip) \ + snd_hdac_bus_free_stream_pages(azx_bus(chip)) /* Low level azx interface */ void azx_init_chip(struct azx *chip, bool full_reset); void azx_stop_chip(struct azx *chip); -void azx_enter_link_reset(struct azx *chip); +#define azx_enter_link_reset(chip) \ + snd_hdac_bus_enter_link_reset(azx_bus(chip)) irqreturn_t azx_interrupt(int irq, void *dev_id); /* Codec interface */ -int azx_bus_create(struct azx *chip, const char *model); +int azx_bus_init(struct azx *chip, const char *model, + const struct hdac_io_ops *io_ops); int azx_probe_codecs(struct azx *chip, unsigned int max_slots); int azx_codec_configure(struct azx *chip); -int azx_init_stream(struct azx *chip); +int azx_init_streams(struct azx *chip); +void azx_free_streams(struct azx *chip); #endif /* __SOUND_HDA_CONTROLLER_H */ diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index a55d8504fe00..9dff693005ea 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -614,7 +614,7 @@ static void azx_irq_pending_work(struct work_struct *work) for (;;) { pending = 0; - spin_lock_irq(&chip->reg_lock); + spin_lock_irq(&bus->reg_lock); list_for_each_entry(s, &bus->stream_list, list) { struct azx_dev *azx_dev = stream_to_azx_dev(s); if (!azx_dev->irq_pending || @@ -624,15 +624,15 @@ static void azx_irq_pending_work(struct work_struct *work) ok = azx_position_ok(chip, azx_dev); if (ok > 0) { azx_dev->irq_pending = 0; - spin_unlock(&chip->reg_lock); + spin_unlock(&bus->reg_lock); snd_pcm_period_elapsed(s->substream); - spin_lock(&chip->reg_lock); + spin_lock(&bus->reg_lock); } else if (ok < 0) { pending = 0; /* too early */ } else pending++; } - spin_unlock_irq(&chip->reg_lock); + spin_unlock_irq(&bus->reg_lock); if (!pending) return; msleep(1); @@ -645,16 +645,18 @@ static void azx_clear_irq_pending(struct azx *chip) struct hdac_bus *bus = azx_bus(chip); struct hdac_stream *s; - spin_lock_irq(&chip->reg_lock); + spin_lock_irq(&bus->reg_lock); list_for_each_entry(s, &bus->stream_list, list) { struct azx_dev *azx_dev = stream_to_azx_dev(s); azx_dev->irq_pending = 0; } - spin_unlock_irq(&chip->reg_lock); + spin_unlock_irq(&bus->reg_lock); } static int azx_acquire_irq(struct azx *chip, int do_disconnect) { + struct hdac_bus *bus = azx_bus(chip); + if (request_irq(chip->pci->irq, azx_interrupt, chip->msi ? 0 : IRQF_SHARED, KBUILD_MODNAME, chip)) { @@ -665,7 +667,7 @@ static int azx_acquire_irq(struct azx *chip, int do_disconnect) snd_card_disconnect(chip->card); return -1; } - chip->irq = chip->pci->irq; + bus->irq = chip->pci->irq; pci_intx(chip->pci, !chip->msi); return 0; } @@ -694,7 +696,8 @@ static unsigned int azx_via_get_position(struct azx *chip, /* azx_dev->fifo_size can't get FIFO size of in stream. * Get from base address + offset. */ - fifo_size = readw(chip->remap_addr + VIA_IN_STREAM0_FIFO_SIZE_OFFSET); + fifo_size = readw(azx_bus(chip)->remap_addr + + VIA_IN_STREAM0_FIFO_SIZE_OFFSET); if (azx_dev->insufficient) { /* Link position never gather than FIFO size */ @@ -760,9 +763,9 @@ static int param_set_xint(const char *val, const struct kernel_param *kp) mutex_lock(&card_list_lock); list_for_each_entry(hda, &card_list, list) { chip = &hda->chip; - if (!chip->bus || chip->disabled) + if (!hda->probe_continued || chip->disabled) continue; - snd_hda_set_power_save(chip->bus, power_save * 1000); + snd_hda_set_power_save(&chip->bus, power_save * 1000); } mutex_unlock(&card_list_lock); return 0; @@ -781,6 +784,7 @@ static int azx_suspend(struct device *dev) struct snd_card *card = dev_get_drvdata(dev); struct azx *chip; struct hda_intel *hda; + struct hdac_bus *bus; if (!card) return 0; @@ -790,13 +794,14 @@ static int azx_suspend(struct device *dev) if (chip->disabled || hda->init_failed) return 0; + bus = azx_bus(chip); snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); azx_clear_irq_pending(chip); azx_stop_chip(chip); azx_enter_link_reset(chip); - if (chip->irq >= 0) { - free_irq(chip->irq, chip); - chip->irq = -1; + if (bus->irq >= 0) { + free_irq(bus->irq, chip); + bus->irq = -1; } if (chip->msi) @@ -875,7 +880,6 @@ static int azx_runtime_resume(struct device *dev) struct snd_card *card = dev_get_drvdata(dev); struct azx *chip; struct hda_intel *hda; - struct hda_bus *bus; struct hda_codec *codec; int status; @@ -901,9 +905,8 @@ static int azx_runtime_resume(struct device *dev) azx_init_pci(chip); azx_init_chip(chip, true); - bus = chip->bus; - if (status && bus) { - list_for_each_codec(codec, bus) + if (status) { + list_for_each_codec(codec, &chip->bus) if (status & (1 << codec->addr)) schedule_delayed_work(&codec->jackpoll_work, codec->jackpoll_interval); @@ -931,7 +934,7 @@ static int azx_runtime_idle(struct device *dev) return 0; if (!power_save_controller || !azx_has_pm_runtime(chip) || - chip->bus->core.codec_powered) + azx_bus(chip)->codec_powered) return -EBUSY; return 0; @@ -969,7 +972,7 @@ static void azx_vs_set_state(struct pci_dev *pci, if (chip->disabled == disabled) return; - if (!chip->bus) { + if (!hda->probe_continued) { chip->disabled = disabled; if (!disabled) { dev_info(chip->card->dev, @@ -990,11 +993,11 @@ static void azx_vs_set_state(struct pci_dev *pci, * put ourselves there */ pci->current_state = PCI_D3cold; chip->disabled = true; - if (snd_hda_lock_devices(chip->bus)) + if (snd_hda_lock_devices(&chip->bus)) dev_warn(chip->card->dev, "Cannot lock devices!\n"); } else { - snd_hda_unlock_devices(chip->bus); + snd_hda_unlock_devices(&chip->bus); pm_runtime_get_noresume(card->dev); chip->disabled = false; azx_resume(card->dev); @@ -1011,11 +1014,11 @@ static bool azx_vs_can_switch(struct pci_dev *pci) wait_for_completion(&hda->probe_wait); if (hda->init_failed) return false; - if (chip->disabled || !chip->bus) + if (chip->disabled || !hda->probe_continued) return true; - if (snd_hda_lock_devices(chip->bus)) + if (snd_hda_lock_devices(&chip->bus)) return false; - snd_hda_unlock_devices(chip->bus); + snd_hda_unlock_devices(&chip->bus); return true; } @@ -1048,7 +1051,7 @@ static int register_vga_switcheroo(struct azx *chip) */ err = vga_switcheroo_register_audio_client(chip->pci, &azx_vs_ops, VGA_SWITCHEROO_DIS, - chip->bus != NULL); + hda->probe_continued); if (err < 0) return err; hda->vga_switcheroo_registered = 1; @@ -1071,6 +1074,7 @@ static int azx_free(struct azx *chip) { struct pci_dev *pci = chip->pci; struct hda_intel *hda = container_of(chip, struct hda_intel, chip); + struct hdac_bus *bus = azx_bus(chip); if (azx_has_pm_runtime(chip) && chip->running) pm_runtime_get_noresume(&pci->dev); @@ -1081,27 +1085,31 @@ static int azx_free(struct azx *chip) complete_all(&hda->probe_wait); if (use_vga_switcheroo(hda)) { - if (chip->disabled && chip->bus) - snd_hda_unlock_devices(chip->bus); + if (chip->disabled && hda->probe_continued) + snd_hda_unlock_devices(&chip->bus); if (hda->vga_switcheroo_registered) vga_switcheroo_unregister_client(chip->pci); } - if (chip->initialized) { + if (bus->chip_init) { azx_clear_irq_pending(chip); azx_stop_all_streams(chip); azx_stop_chip(chip); } - if (chip->irq >= 0) - free_irq(chip->irq, (void*)chip); + if (bus->irq >= 0) + free_irq(bus->irq, (void*)chip); if (chip->msi) pci_disable_msi(chip->pci); - iounmap(chip->remap_addr); + iounmap(bus->remap_addr); azx_free_stream_pages(chip); + azx_free_streams(chip); + snd_hdac_bus_exit(bus); + if (chip->region_requested) pci_release_regions(chip->pci); + pci_disable_device(chip->pci); #ifdef CONFIG_SND_HDA_PATCH_LOADER release_firmware(chip->fw); @@ -1115,6 +1123,14 @@ static int azx_free(struct azx *chip) return 0; } +static int azx_dev_disconnect(struct snd_device *device) +{ + struct azx *chip = device->device_data; + + chip->bus.shutdown = 1; + return 0; +} + static int azx_dev_free(struct snd_device *device) { return azx_free(device->device_data); @@ -1281,9 +1297,9 @@ static void check_probe_mask(struct azx *chip, int dev) /* check forced option */ if (chip->codec_probe_mask != -1 && (chip->codec_probe_mask & AZX_FORCE_CODEC_MASK)) { - chip->codec_mask = chip->codec_probe_mask & 0xff; + azx_bus(chip)->codec_mask = chip->codec_probe_mask & 0xff; dev_info(chip->card->dev, "codec_mask forced to 0x%x\n", - chip->codec_mask); + (int)azx_bus(chip)->codec_mask); } } @@ -1378,6 +1394,7 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci, struct azx **rchip) { static struct snd_device_ops ops = { + .dev_disconnect = azx_dev_disconnect, .dev_free = azx_dev_free, }; struct hda_intel *hda; @@ -1397,13 +1414,10 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci, } chip = &hda->chip; - spin_lock_init(&chip->reg_lock); mutex_init(&chip->open_mutex); chip->card = card; chip->pci = pci; chip->ops = &pci_hda_ops; - chip->io_ops = &pci_hda_io_ops; - chip->irq = -1; chip->driver_caps = driver_caps; chip->driver_type = driver_caps & 0xff; check_msi(chip); @@ -1435,6 +1449,13 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci, } chip->bdl_pos_adj = bdl_pos_adj; + err = azx_bus_init(chip, model[dev], &pci_hda_io_ops); + if (err < 0) { + kfree(hda); + pci_disable_device(pci); + return err; + } + err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); if (err < 0) { dev_err(card->dev, "Error creating device [card]!\n"); @@ -1455,6 +1476,7 @@ static int azx_first_init(struct azx *chip) int dev = chip->dev_index; struct pci_dev *pci = chip->pci; struct snd_card *card = chip->card; + struct hdac_bus *bus = azx_bus(chip); int err; unsigned short gcap; unsigned int dma_bits = 64; @@ -1474,13 +1496,12 @@ static int azx_first_init(struct azx *chip) return err; chip->region_requested = 1; - chip->addr = pci_resource_start(pci, 0); - chip->remap_addr = pci_ioremap_bar(pci, 0); - if (chip->remap_addr == NULL) { + bus->addr = pci_resource_start(pci, 0); + bus->remap_addr = pci_ioremap_bar(pci, 0); + if (bus->remap_addr == NULL) { dev_err(card->dev, "ioremap error\n"); return -ENXIO; } - azx_bus(chip)->remap_addr = chip->remap_addr; /* FIXME */ if (chip->msi) { if (chip->driver_caps & AZX_DCAPS_NO_MSI64) { @@ -1495,7 +1516,7 @@ static int azx_first_init(struct azx *chip) return -EBUSY; pci_set_master(pci); - synchronize_irq(chip->irq); + synchronize_irq(bus->irq); gcap = azx_readw(chip, GCAP); dev_dbg(card->dev, "chipset global capabilities = 0x%x\n", gcap); @@ -1573,12 +1594,14 @@ static int azx_first_init(struct azx *chip) chip->playback_index_offset = chip->capture_streams; chip->num_streams = chip->playback_streams + chip->capture_streams; - err = azx_alloc_stream_pages(chip); + /* initialize streams */ + err = azx_init_streams(chip); if (err < 0) return err; - /* initialize streams */ - azx_init_stream(chip); + err = azx_alloc_stream_pages(chip); + if (err < 0) + return err; /* initialize chip */ azx_init_pci(chip); @@ -1593,7 +1616,7 @@ static int azx_first_init(struct azx *chip) azx_init_chip(chip, (probe_only[dev] & 2) == 0); /* codec detection */ - if (!chip->codec_mask) { + if (!azx_bus(chip)->codec_mask) { dev_err(card->dev, "no codecs found!\n"); return -ENODEV; } @@ -1603,7 +1626,7 @@ static int azx_first_init(struct azx *chip) sizeof(card->shortname)); snprintf(card->longname, sizeof(card->longname), "%s at 0x%lx irq %i", - card->shortname, chip->addr, chip->irq); + card->shortname, bus->addr, bus->irq); return 0; } @@ -1672,10 +1695,11 @@ static u8 pci_azx_readb(u8 __iomem *addr) static int disable_msi_reset_irq(struct azx *chip) { + struct hdac_bus *bus = azx_bus(chip); int err; - free_irq(chip->irq, chip); - chip->irq = -1; + free_irq(bus->irq, chip); + bus->irq = -1; pci_disable_msi(chip->pci); chip->msi = 0; err = azx_acquire_irq(chip, 1); @@ -1691,7 +1715,7 @@ static int dma_alloc_pages(struct hdac_bus *bus, size_t size, struct snd_dma_buffer *buf) { - struct azx *chip = to_hda_bus(bus)->private_data; + struct azx *chip = bus_to_azx(bus); int err; err = snd_dma_alloc_pages(type, @@ -1705,7 +1729,7 @@ static int dma_alloc_pages(struct hdac_bus *bus, static void dma_free_pages(struct hdac_bus *bus, struct snd_dma_buffer *buf) { - struct azx *chip = to_hda_bus(bus)->private_data; + struct azx *chip = bus_to_azx(bus); mark_pages_wc(chip, buf, false); snd_dma_free_pages(buf); @@ -1857,6 +1881,7 @@ static int azx_probe_continue(struct azx *chip) int dev = chip->dev_index; int err; + hda->probe_continued = 1; /* Request power well for Haswell HDA controller and codec */ if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) { #ifdef CONFIG_SND_HDA_I915 @@ -1872,10 +1897,6 @@ static int azx_probe_continue(struct azx *chip) #endif } - err = azx_bus_create(chip, model[dev]); - if (err < 0) - goto out_free; - err = azx_first_init(chip); if (err < 0) goto out_free; @@ -1891,7 +1912,7 @@ static int azx_probe_continue(struct azx *chip) #ifdef CONFIG_SND_HDA_PATCH_LOADER if (chip->fw) { - err = snd_hda_load_patch(chip->bus, chip->fw->size, + err = snd_hda_load_patch(&chip->bus, chip->fw->size, chip->fw->data); if (err < 0) goto out_free; @@ -1913,7 +1934,7 @@ static int azx_probe_continue(struct azx *chip) chip->running = 1; azx_add_card_list(chip); - snd_hda_set_power_save(chip->bus, power_save * 1000); + snd_hda_set_power_save(&chip->bus, power_save * 1000); if (azx_has_pm_runtime(chip) || hda->use_vga_switcheroo) pm_runtime_put_noidle(&pci->dev); diff --git a/sound/pci/hda/hda_intel.h b/sound/pci/hda/hda_intel.h index d5231f7216a7..206989878bc6 100644 --- a/sound/pci/hda/hda_intel.h +++ b/sound/pci/hda/hda_intel.h @@ -34,6 +34,7 @@ struct hda_intel { /* extra flags */ unsigned int irq_pending_warned:1; + unsigned int probe_continued:1; /* VGA-switcheroo setup */ unsigned int use_vga_switcheroo:1; diff --git a/sound/pci/hda/hda_tegra.c b/sound/pci/hda/hda_tegra.c index c6fc96afbdc1..397e1821020f 100644 --- a/sound/pci/hda/hda_tegra.c +++ b/sound/pci/hda/hda_tegra.c @@ -285,6 +285,14 @@ static const struct dev_pm_ops hda_tegra_pm = { SET_SYSTEM_SLEEP_PM_OPS(hda_tegra_suspend, hda_tegra_resume) }; +static int hda_tegra_dev_disconnect(struct snd_device *device) +{ + struct azx *chip = device->device_data; + + chip->bus.shutdown = 1; + return 0; +} + /* * destructor */ @@ -292,12 +300,14 @@ static int hda_tegra_dev_free(struct snd_device *device) { struct azx *chip = device->device_data; - if (chip->initialized) { + if (azx_bus(chip)->chip_init) { azx_stop_all_streams(chip); azx_stop_chip(chip); } azx_free_stream_pages(chip); + azx_free_streams(chip); + snd_hdac_bus_exit(bus); return 0; } @@ -305,6 +315,7 @@ static int hda_tegra_dev_free(struct snd_device *device) static int hda_tegra_init_chip(struct azx *chip, struct platform_device *pdev) { struct hda_tegra *hda = container_of(chip, struct hda_tegra, chip); + struct hdac_bus *bus = azx_bus(chip); struct device *dev = hda->dev; struct resource *res; int err; @@ -324,9 +335,8 @@ static int hda_tegra_init_chip(struct azx *chip, struct platform_device *pdev) if (IS_ERR(hda->regs)) return PTR_ERR(hda->regs); - chip->remap_addr = hda->regs + HDA_BAR0; - azx_bus(chip)->remap_addr = chip->remap_addr; /* FIXME */ - chip->addr = res->start + HDA_BAR0; + bus->remap_addr = hda->regs + HDA_BAR0; + bus->addr = res->start + HDA_BAR0; err = hda_tegra_enable_clocks(hda); if (err) @@ -339,6 +349,7 @@ static int hda_tegra_init_chip(struct azx *chip, struct platform_device *pdev) static int hda_tegra_first_init(struct azx *chip, struct platform_device *pdev) { + struct hdac_bus *bus = azx_bus(chip); struct snd_card *card = chip->card; int err; unsigned short gcap; @@ -356,9 +367,9 @@ static int hda_tegra_first_init(struct azx *chip, struct platform_device *pdev) irq_id); return err; } - chip->irq = irq_id; + bus->irq = irq_id; - synchronize_irq(chip->irq); + synchronize_irq(bus->irq); gcap = azx_readw(chip, GCAP); dev_dbg(card->dev, "chipset global capabilities = 0x%x\n", gcap); @@ -377,18 +388,20 @@ static int hda_tegra_first_init(struct azx *chip, struct platform_device *pdev) chip->playback_index_offset = chip->capture_streams; chip->num_streams = chip->playback_streams + chip->capture_streams; - err = azx_alloc_stream_pages(chip); + /* initialize streams */ + err = azx_init_streams(chip); if (err < 0) return err; - /* initialize streams */ - azx_init_stream(chip); + err = azx_alloc_stream_pages(chip); + if (err < 0) + return err; /* initialize chip */ azx_init_chip(chip, 1); /* codec detection */ - if (!chip->codec_mask) { + if (!bus->codec_mask) { dev_err(card->dev, "no codecs found!\n"); return -ENODEV; } @@ -397,7 +410,7 @@ static int hda_tegra_first_init(struct azx *chip, struct platform_device *pdev) strcpy(card->shortname, "tegra-hda"); snprintf(card->longname, sizeof(card->longname), "%s at 0x%lx irq %i", - card->shortname, chip->addr, chip->irq); + card->shortname, bus->addr, bus->irq); return 0; } @@ -410,6 +423,7 @@ static int hda_tegra_create(struct snd_card *card, struct hda_tegra *hda) { static struct snd_device_ops ops = { + .dev_disconnect = hda_tegra_dev_disconnect, .dev_free = hda_tegra_dev_free, }; struct azx *chip; @@ -417,12 +431,9 @@ static int hda_tegra_create(struct snd_card *card, chip = &hda->chip; - spin_lock_init(&chip->reg_lock); mutex_init(&chip->open_mutex); chip->card = card; chip->ops = &hda_tegra_ops; - chip->io_ops = &hda_tegra_io_ops; - chip->irq = -1; chip->driver_caps = driver_caps; chip->driver_type = driver_caps & 0xff; chip->dev_index = 0; @@ -469,7 +480,7 @@ static int hda_tegra_probe(struct platform_device *pdev) return err; } - err = azx_bus_create(chip, NULL); + err = azx_bus_init(chip, NULL, &hda_tegra_io_ops); if (err < 0) goto out_free; @@ -498,7 +509,7 @@ static int hda_tegra_probe(struct platform_device *pdev) goto out_free; chip->running = 1; - snd_hda_set_power_save(chip->bus, power_save * 1000); + snd_hda_set_power_save(&chip->bus, power_save * 1000); return 0; |