diff options
Diffstat (limited to 'sound')
196 files changed, 3584 insertions, 4180 deletions
diff --git a/sound/Kconfig b/sound/Kconfig index 6a215a8c0490..d7d2aac9542e 100644 --- a/sound/Kconfig +++ b/sound/Kconfig @@ -56,7 +56,7 @@ config SOUND_OSS_CORE_PRECLAIM source "sound/oss/dmasound/Kconfig" -if !M68K && !UML +if !UML menuconfig SND tristate "Advanced Linux Sound Architecture" @@ -110,6 +110,8 @@ source "sound/soc/Kconfig" source "sound/x86/Kconfig" +source "sound/synth/Kconfig" + endif # SND menuconfig SOUND_PRIME @@ -125,7 +127,7 @@ source "sound/oss/Kconfig" endif # SOUND_PRIME -endif # !M68K +endif # !UML endif # SOUND diff --git a/sound/aoa/codecs/tas.c b/sound/aoa/codecs/tas.c index 78ed1ffbf786..733b6365dad6 100644 --- a/sound/aoa/codecs/tas.c +++ b/sound/aoa/codecs/tas.c @@ -271,7 +271,7 @@ static int tas_snd_vol_put(struct snd_kcontrol *kcontrol, return 1; } -static struct snd_kcontrol_new volume_control = { +static const struct snd_kcontrol_new volume_control = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Master Playback Volume", .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, @@ -314,7 +314,7 @@ static int tas_snd_mute_put(struct snd_kcontrol *kcontrol, return 1; } -static struct snd_kcontrol_new mute_control = { +static const struct snd_kcontrol_new mute_control = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Master Playback Switch", .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, @@ -426,7 +426,7 @@ static int tas_snd_drc_range_put(struct snd_kcontrol *kcontrol, return 1; } -static struct snd_kcontrol_new drc_range_control = { +static const struct snd_kcontrol_new drc_range_control = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "DRC Range", .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, @@ -466,7 +466,7 @@ static int tas_snd_drc_switch_put(struct snd_kcontrol *kcontrol, return 1; } -static struct snd_kcontrol_new drc_switch_control = { +static const struct snd_kcontrol_new drc_switch_control = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "DRC Range Switch", .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, @@ -524,7 +524,7 @@ static int tas_snd_capture_source_put(struct snd_kcontrol *kcontrol, return 1; } -static struct snd_kcontrol_new capture_source_control = { +static const struct snd_kcontrol_new capture_source_control = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, /* If we name this 'Input Source', it properly shows up in * alsamixer as a selection, * but it's shown under the @@ -586,7 +586,7 @@ static int tas_snd_treble_put(struct snd_kcontrol *kcontrol, return 1; } -static struct snd_kcontrol_new treble_control = { +static const struct snd_kcontrol_new treble_control = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Treble", .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, @@ -637,7 +637,7 @@ static int tas_snd_bass_put(struct snd_kcontrol *kcontrol, return 1; } -static struct snd_kcontrol_new bass_control = { +static const struct snd_kcontrol_new bass_control = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Bass", .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, diff --git a/sound/aoa/fabrics/layout.c b/sound/aoa/fabrics/layout.c index a0c4a5de809c..1eddf8fa188f 100644 --- a/sound/aoa/fabrics/layout.c +++ b/sound/aoa/fabrics/layout.c @@ -707,7 +707,7 @@ static int detect_choice_put(struct snd_kcontrol *kcontrol, return 1; } -static struct snd_kcontrol_new headphone_detect_choice = { +static const struct snd_kcontrol_new headphone_detect_choice = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Headphone Detect Autoswitch", .info = control_info, @@ -717,7 +717,7 @@ static struct snd_kcontrol_new headphone_detect_choice = { .private_value = 0, }; -static struct snd_kcontrol_new lineout_detect_choice = { +static const struct snd_kcontrol_new lineout_detect_choice = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Line-Out Detect Autoswitch", .info = control_info, @@ -749,7 +749,7 @@ static int detected_get(struct snd_kcontrol *kcontrol, return 0; } -static struct snd_kcontrol_new headphone_detected = { +static const struct snd_kcontrol_new headphone_detected = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Headphone Detected", .info = control_info, @@ -758,7 +758,7 @@ static struct snd_kcontrol_new headphone_detected = { .private_value = 0, }; -static struct snd_kcontrol_new lineout_detected = { +static const struct snd_kcontrol_new lineout_detected = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Line-Out Detected", .info = control_info, diff --git a/sound/atmel/Kconfig b/sound/atmel/Kconfig index 94de43a096f1..d789cbcb9106 100644 --- a/sound/atmel/Kconfig +++ b/sound/atmel/Kconfig @@ -1,18 +1,11 @@ -menu "Atmel devices (AVR32 and AT91)" - depends on AVR32 || ARCH_AT91 - -config SND_ATMEL_ABDAC - tristate "Atmel Audio Bitstream DAC (ABDAC) driver" - select SND_PCM - depends on DW_DMAC && AVR32 - help - ALSA sound driver for the Atmel Audio Bitstream DAC (ABDAC). +menu "Atmel devices (AT91)" + depends on ARCH_AT91 config SND_ATMEL_AC97C tristate "Atmel AC97 Controller (AC97C) driver" select SND_PCM select SND_AC97_CODEC - depends on (DW_DMAC && AVR32) || ARCH_AT91 + depends on ARCH_AT91 help ALSA sound driver for the Atmel AC97 controller. diff --git a/sound/atmel/Makefile b/sound/atmel/Makefile index 219dcfac6086..d4009d1430ed 100644 --- a/sound/atmel/Makefile +++ b/sound/atmel/Makefile @@ -1,5 +1,3 @@ -snd-atmel-abdac-objs := abdac.o snd-atmel-ac97c-objs := ac97c.o -obj-$(CONFIG_SND_ATMEL_ABDAC) += snd-atmel-abdac.o obj-$(CONFIG_SND_ATMEL_AC97C) += snd-atmel-ac97c.o diff --git a/sound/atmel/abdac.c b/sound/atmel/abdac.c deleted file mode 100644 index 558618802000..000000000000 --- a/sound/atmel/abdac.c +++ /dev/null @@ -1,610 +0,0 @@ -/* - * Driver for the Atmel on-chip Audio Bitstream DAC (ABDAC) - * - * Copyright (C) 2006-2009 Atmel Corporation - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - */ -#include <linux/clk.h> -#include <linux/bitmap.h> -#include <linux/dmaengine.h> -#include <linux/dma-mapping.h> -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/types.h> -#include <linux/io.h> - -#include <sound/core.h> -#include <sound/initval.h> -#include <sound/pcm.h> -#include <sound/pcm_params.h> -#include <sound/atmel-abdac.h> - -#include <linux/platform_data/dma-dw.h> -#include <linux/dma/dw.h> - -/* DAC register offsets */ -#define DAC_DATA 0x0000 -#define DAC_CTRL 0x0008 -#define DAC_INT_MASK 0x000c -#define DAC_INT_EN 0x0010 -#define DAC_INT_DIS 0x0014 -#define DAC_INT_CLR 0x0018 -#define DAC_INT_STATUS 0x001c - -/* Bitfields in CTRL */ -#define DAC_SWAP_OFFSET 30 -#define DAC_SWAP_SIZE 1 -#define DAC_EN_OFFSET 31 -#define DAC_EN_SIZE 1 - -/* Bitfields in INT_MASK/INT_EN/INT_DIS/INT_STATUS/INT_CLR */ -#define DAC_UNDERRUN_OFFSET 28 -#define DAC_UNDERRUN_SIZE 1 -#define DAC_TX_READY_OFFSET 29 -#define DAC_TX_READY_SIZE 1 - -/* Bit manipulation macros */ -#define DAC_BIT(name) \ - (1 << DAC_##name##_OFFSET) -#define DAC_BF(name, value) \ - (((value) & ((1 << DAC_##name##_SIZE) - 1)) \ - << DAC_##name##_OFFSET) -#define DAC_BFEXT(name, value) \ - (((value) >> DAC_##name##_OFFSET) \ - & ((1 << DAC_##name##_SIZE) - 1)) -#define DAC_BFINS(name, value, old) \ - (((old) & ~(((1 << DAC_##name##_SIZE) - 1) \ - << DAC_##name##_OFFSET)) \ - | DAC_BF(name, value)) - -/* Register access macros */ -#define dac_readl(port, reg) \ - __raw_readl((port)->regs + DAC_##reg) -#define dac_writel(port, reg, value) \ - __raw_writel((value), (port)->regs + DAC_##reg) - -/* - * ABDAC supports a maximum of 6 different rates from a generic clock. The - * generic clock has a power of two divider, which gives 6 steps from 192 kHz - * to 5112 Hz. - */ -#define MAX_NUM_RATES 6 -/* ALSA seems to use rates between 192000 Hz and 5112 Hz. */ -#define RATE_MAX 192000 -#define RATE_MIN 5112 - -enum { - DMA_READY = 0, -}; - -struct atmel_abdac_dma { - struct dma_chan *chan; - struct dw_cyclic_desc *cdesc; -}; - -struct atmel_abdac { - struct clk *pclk; - struct clk *sample_clk; - struct platform_device *pdev; - struct atmel_abdac_dma dma; - - struct snd_pcm_hw_constraint_list constraints_rates; - struct snd_pcm_substream *substream; - struct snd_card *card; - struct snd_pcm *pcm; - - void __iomem *regs; - unsigned long flags; - unsigned int rates[MAX_NUM_RATES]; - unsigned int rates_num; - int irq; -}; - -#define get_dac(card) ((struct atmel_abdac *)(card)->private_data) - -/* This function is called by the DMA driver. */ -static void atmel_abdac_dma_period_done(void *arg) -{ - struct atmel_abdac *dac = arg; - snd_pcm_period_elapsed(dac->substream); -} - -static int atmel_abdac_prepare_dma(struct atmel_abdac *dac, - struct snd_pcm_substream *substream, - enum dma_data_direction direction) -{ - struct dma_chan *chan = dac->dma.chan; - struct dw_cyclic_desc *cdesc; - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned long buffer_len, period_len; - - /* - * We don't do DMA on "complex" transfers, i.e. with - * non-halfword-aligned buffers or lengths. - */ - if (runtime->dma_addr & 1 || runtime->buffer_size & 1) { - dev_dbg(&dac->pdev->dev, "too complex transfer\n"); - return -EINVAL; - } - - buffer_len = frames_to_bytes(runtime, runtime->buffer_size); - period_len = frames_to_bytes(runtime, runtime->period_size); - - cdesc = dw_dma_cyclic_prep(chan, runtime->dma_addr, buffer_len, - period_len, DMA_MEM_TO_DEV); - if (IS_ERR(cdesc)) { - dev_dbg(&dac->pdev->dev, "could not prepare cyclic DMA\n"); - return PTR_ERR(cdesc); - } - - cdesc->period_callback = atmel_abdac_dma_period_done; - cdesc->period_callback_param = dac; - - dac->dma.cdesc = cdesc; - - set_bit(DMA_READY, &dac->flags); - - return 0; -} - -static struct snd_pcm_hardware atmel_abdac_hw = { - .info = (SNDRV_PCM_INFO_MMAP - | SNDRV_PCM_INFO_MMAP_VALID - | SNDRV_PCM_INFO_INTERLEAVED - | SNDRV_PCM_INFO_BLOCK_TRANSFER - | SNDRV_PCM_INFO_RESUME - | SNDRV_PCM_INFO_PAUSE), - .formats = (SNDRV_PCM_FMTBIT_S16_BE), - .rates = (SNDRV_PCM_RATE_KNOT), - .rate_min = RATE_MIN, - .rate_max = RATE_MAX, - .channels_min = 2, - .channels_max = 2, - .buffer_bytes_max = 64 * 4096, - .period_bytes_min = 4096, - .period_bytes_max = 4096, - .periods_min = 6, - .periods_max = 64, -}; - -static int atmel_abdac_open(struct snd_pcm_substream *substream) -{ - struct atmel_abdac *dac = snd_pcm_substream_chip(substream); - - dac->substream = substream; - atmel_abdac_hw.rate_max = dac->rates[dac->rates_num - 1]; - atmel_abdac_hw.rate_min = dac->rates[0]; - substream->runtime->hw = atmel_abdac_hw; - - return snd_pcm_hw_constraint_list(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, &dac->constraints_rates); -} - -static int atmel_abdac_close(struct snd_pcm_substream *substream) -{ - struct atmel_abdac *dac = snd_pcm_substream_chip(substream); - dac->substream = NULL; - return 0; -} - -static int atmel_abdac_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct atmel_abdac *dac = snd_pcm_substream_chip(substream); - int retval; - - retval = snd_pcm_lib_malloc_pages(substream, - params_buffer_bytes(hw_params)); - if (retval < 0) - return retval; - /* snd_pcm_lib_malloc_pages returns 1 if buffer is changed. */ - if (retval == 1) - if (test_and_clear_bit(DMA_READY, &dac->flags)) - dw_dma_cyclic_free(dac->dma.chan); - - return retval; -} - -static int atmel_abdac_hw_free(struct snd_pcm_substream *substream) -{ - struct atmel_abdac *dac = snd_pcm_substream_chip(substream); - if (test_and_clear_bit(DMA_READY, &dac->flags)) - dw_dma_cyclic_free(dac->dma.chan); - return snd_pcm_lib_free_pages(substream); -} - -static int atmel_abdac_prepare(struct snd_pcm_substream *substream) -{ - struct atmel_abdac *dac = snd_pcm_substream_chip(substream); - int retval; - - retval = clk_set_rate(dac->sample_clk, 256 * substream->runtime->rate); - if (retval) - return retval; - - if (!test_bit(DMA_READY, &dac->flags)) - retval = atmel_abdac_prepare_dma(dac, substream, DMA_TO_DEVICE); - - return retval; -} - -static int atmel_abdac_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct atmel_abdac *dac = snd_pcm_substream_chip(substream); - int retval = 0; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: /* fall through */ - case SNDRV_PCM_TRIGGER_RESUME: /* fall through */ - case SNDRV_PCM_TRIGGER_START: - clk_prepare_enable(dac->sample_clk); - retval = dw_dma_cyclic_start(dac->dma.chan); - if (retval) - goto out; - dac_writel(dac, CTRL, DAC_BIT(EN)); - break; - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: /* fall through */ - case SNDRV_PCM_TRIGGER_SUSPEND: /* fall through */ - case SNDRV_PCM_TRIGGER_STOP: - dw_dma_cyclic_stop(dac->dma.chan); - dac_writel(dac, DATA, 0); - dac_writel(dac, CTRL, 0); - clk_disable_unprepare(dac->sample_clk); - break; - default: - retval = -EINVAL; - break; - } -out: - return retval; -} - -static snd_pcm_uframes_t -atmel_abdac_pointer(struct snd_pcm_substream *substream) -{ - struct atmel_abdac *dac = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - snd_pcm_uframes_t frames; - unsigned long bytes; - - bytes = dw_dma_get_src_addr(dac->dma.chan); - bytes -= runtime->dma_addr; - - frames = bytes_to_frames(runtime, bytes); - if (frames >= runtime->buffer_size) - frames -= runtime->buffer_size; - - return frames; -} - -static irqreturn_t abdac_interrupt(int irq, void *dev_id) -{ - struct atmel_abdac *dac = dev_id; - u32 status; - - status = dac_readl(dac, INT_STATUS); - if (status & DAC_BIT(UNDERRUN)) { - dev_err(&dac->pdev->dev, "underrun detected\n"); - dac_writel(dac, INT_CLR, DAC_BIT(UNDERRUN)); - } else { - dev_err(&dac->pdev->dev, "spurious interrupt (status=0x%x)\n", - status); - dac_writel(dac, INT_CLR, status); - } - - return IRQ_HANDLED; -} - -static struct snd_pcm_ops atmel_abdac_ops = { - .open = atmel_abdac_open, - .close = atmel_abdac_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = atmel_abdac_hw_params, - .hw_free = atmel_abdac_hw_free, - .prepare = atmel_abdac_prepare, - .trigger = atmel_abdac_trigger, - .pointer = atmel_abdac_pointer, -}; - -static int atmel_abdac_pcm_new(struct atmel_abdac *dac) -{ - struct snd_pcm_hardware hw = atmel_abdac_hw; - struct snd_pcm *pcm; - int retval; - - retval = snd_pcm_new(dac->card, dac->card->shortname, - dac->pdev->id, 1, 0, &pcm); - if (retval) - return retval; - - strcpy(pcm->name, dac->card->shortname); - pcm->private_data = dac; - pcm->info_flags = 0; - dac->pcm = pcm; - - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &atmel_abdac_ops); - - retval = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - &dac->pdev->dev, hw.periods_min * hw.period_bytes_min, - hw.buffer_bytes_max); - - return retval; -} - -static bool filter(struct dma_chan *chan, void *slave) -{ - struct dw_dma_slave *dws = slave; - - if (dws->dma_dev == chan->device->dev) { - chan->private = dws; - return true; - } else - return false; -} - -static int set_sample_rates(struct atmel_abdac *dac) -{ - long new_rate = RATE_MAX; - int retval = -EINVAL; - int index = 0; - - /* we start at 192 kHz and work our way down to 5112 Hz */ - while (new_rate >= RATE_MIN && index < (MAX_NUM_RATES + 1)) { - new_rate = clk_round_rate(dac->sample_clk, 256 * new_rate); - if (new_rate <= 0) - break; - /* make sure we are below the ABDAC clock */ - if (index < MAX_NUM_RATES && - new_rate <= clk_get_rate(dac->pclk)) { - dac->rates[index] = new_rate / 256; - index++; - } - /* divide by 256 and then by two to get next rate */ - new_rate /= 256 * 2; - } - - if (index) { - int i; - - /* reverse array, smallest go first */ - for (i = 0; i < (index / 2); i++) { - unsigned int tmp = dac->rates[index - 1 - i]; - dac->rates[index - 1 - i] = dac->rates[i]; - dac->rates[i] = tmp; - } - - dac->constraints_rates.count = index; - dac->constraints_rates.list = dac->rates; - dac->constraints_rates.mask = 0; - dac->rates_num = index; - - retval = 0; - } - - return retval; -} - -static int atmel_abdac_probe(struct platform_device *pdev) -{ - struct snd_card *card; - struct atmel_abdac *dac; - struct resource *regs; - struct atmel_abdac_pdata *pdata; - struct clk *pclk; - struct clk *sample_clk; - int retval; - int irq; - - regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!regs) { - dev_dbg(&pdev->dev, "no memory resource\n"); - return -ENXIO; - } - - irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_dbg(&pdev->dev, "could not get IRQ number\n"); - return irq; - } - - pdata = pdev->dev.platform_data; - if (!pdata) { - dev_dbg(&pdev->dev, "no platform data\n"); - return -ENXIO; - } - - pclk = clk_get(&pdev->dev, "pclk"); - if (IS_ERR(pclk)) { - dev_dbg(&pdev->dev, "no peripheral clock\n"); - return PTR_ERR(pclk); - } - sample_clk = clk_get(&pdev->dev, "sample_clk"); - if (IS_ERR(sample_clk)) { - dev_dbg(&pdev->dev, "no sample clock\n"); - retval = PTR_ERR(sample_clk); - goto out_put_pclk; - } - clk_prepare_enable(pclk); - - retval = snd_card_new(&pdev->dev, SNDRV_DEFAULT_IDX1, - SNDRV_DEFAULT_STR1, THIS_MODULE, - sizeof(struct atmel_abdac), &card); - if (retval) { - dev_dbg(&pdev->dev, "could not create sound card device\n"); - goto out_put_sample_clk; - } - - dac = get_dac(card); - - dac->irq = irq; - dac->card = card; - dac->pclk = pclk; - dac->sample_clk = sample_clk; - dac->pdev = pdev; - - retval = set_sample_rates(dac); - if (retval < 0) { - dev_dbg(&pdev->dev, "could not set supported rates\n"); - goto out_free_card; - } - - dac->regs = ioremap(regs->start, resource_size(regs)); - if (!dac->regs) { - dev_dbg(&pdev->dev, "could not remap register memory\n"); - retval = -ENOMEM; - goto out_free_card; - } - - /* make sure the DAC is silent and disabled */ - dac_writel(dac, DATA, 0); - dac_writel(dac, CTRL, 0); - - retval = request_irq(irq, abdac_interrupt, 0, "abdac", dac); - if (retval) { - dev_dbg(&pdev->dev, "could not request irq\n"); - goto out_unmap_regs; - } - - if (pdata->dws.dma_dev) { - dma_cap_mask_t mask; - - dma_cap_zero(mask); - dma_cap_set(DMA_SLAVE, mask); - - dac->dma.chan = dma_request_channel(mask, filter, &pdata->dws); - if (dac->dma.chan) { - struct dma_slave_config dma_conf = { - .dst_addr = regs->start + DAC_DATA, - .dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES, - .src_maxburst = 1, - .dst_maxburst = 1, - .direction = DMA_MEM_TO_DEV, - .device_fc = false, - }; - - dmaengine_slave_config(dac->dma.chan, &dma_conf); - } - } - if (!pdata->dws.dma_dev || !dac->dma.chan) { - dev_dbg(&pdev->dev, "DMA not available\n"); - retval = -ENODEV; - goto out_unmap_regs; - } - - strcpy(card->driver, "Atmel ABDAC"); - strcpy(card->shortname, "Atmel ABDAC"); - sprintf(card->longname, "Atmel Audio Bitstream DAC"); - - retval = atmel_abdac_pcm_new(dac); - if (retval) { - dev_dbg(&pdev->dev, "could not register ABDAC pcm device\n"); - goto out_release_dma; - } - - retval = snd_card_register(card); - if (retval) { - dev_dbg(&pdev->dev, "could not register sound card\n"); - goto out_release_dma; - } - - platform_set_drvdata(pdev, card); - - dev_info(&pdev->dev, "Atmel ABDAC at 0x%p using %s\n", - dac->regs, dev_name(&dac->dma.chan->dev->device)); - - return retval; - -out_release_dma: - dma_release_channel(dac->dma.chan); - dac->dma.chan = NULL; -out_unmap_regs: - iounmap(dac->regs); -out_free_card: - snd_card_free(card); -out_put_sample_clk: - clk_put(sample_clk); - clk_disable_unprepare(pclk); -out_put_pclk: - clk_put(pclk); - return retval; -} - -#ifdef CONFIG_PM_SLEEP -static int atmel_abdac_suspend(struct device *pdev) -{ - struct snd_card *card = dev_get_drvdata(pdev); - struct atmel_abdac *dac = card->private_data; - - dw_dma_cyclic_stop(dac->dma.chan); - clk_disable_unprepare(dac->sample_clk); - clk_disable_unprepare(dac->pclk); - - return 0; -} - -static int atmel_abdac_resume(struct device *pdev) -{ - struct snd_card *card = dev_get_drvdata(pdev); - struct atmel_abdac *dac = card->private_data; - - clk_prepare_enable(dac->pclk); - clk_prepare_enable(dac->sample_clk); - if (test_bit(DMA_READY, &dac->flags)) - dw_dma_cyclic_start(dac->dma.chan); - - return 0; -} - -static SIMPLE_DEV_PM_OPS(atmel_abdac_pm, atmel_abdac_suspend, atmel_abdac_resume); -#define ATMEL_ABDAC_PM_OPS &atmel_abdac_pm -#else -#define ATMEL_ABDAC_PM_OPS NULL -#endif - -static int atmel_abdac_remove(struct platform_device *pdev) -{ - struct snd_card *card = platform_get_drvdata(pdev); - struct atmel_abdac *dac = get_dac(card); - - clk_put(dac->sample_clk); - clk_disable_unprepare(dac->pclk); - clk_put(dac->pclk); - - dma_release_channel(dac->dma.chan); - dac->dma.chan = NULL; - iounmap(dac->regs); - free_irq(dac->irq, dac); - snd_card_free(card); - - return 0; -} - -static struct platform_driver atmel_abdac_driver = { - .remove = atmel_abdac_remove, - .driver = { - .name = "atmel_abdac", - .pm = ATMEL_ABDAC_PM_OPS, - }, -}; - -static int __init atmel_abdac_init(void) -{ - return platform_driver_probe(&atmel_abdac_driver, - atmel_abdac_probe); -} -module_init(atmel_abdac_init); - -static void __exit atmel_abdac_exit(void) -{ - platform_driver_unregister(&atmel_abdac_driver); -} -module_exit(atmel_abdac_exit); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Driver for Atmel Audio Bitstream DAC (ABDAC)"); -MODULE_AUTHOR("Hans-Christian Egtvedt <egtvedt@samfundet.no>"); diff --git a/sound/atmel/ac97c.c b/sound/atmel/ac97c.c index 6dad042630d8..9d2c9d9af688 100644 --- a/sound/atmel/ac97c.c +++ b/sound/atmel/ac97c.c @@ -11,8 +11,6 @@ #include <linux/delay.h> #include <linux/bitmap.h> #include <linux/device.h> -#include <linux/dmaengine.h> -#include <linux/dma-mapping.h> #include <linux/atmel_pdc.h> #include <linux/init.h> #include <linux/interrupt.h> @@ -34,36 +32,14 @@ #include <sound/atmel-ac97c.h> #include <sound/memalloc.h> -#include <linux/platform_data/dma-dw.h> -#include <linux/dma/dw.h> - -#ifdef CONFIG_AVR32 -#include <mach/cpu.h> -#else -#define cpu_is_at32ap7000() 0 -#endif - #include "ac97c.h" -enum { - DMA_TX_READY = 0, - DMA_RX_READY, - DMA_TX_CHAN_PRESENT, - DMA_RX_CHAN_PRESENT, -}; - /* Serialize access to opened variable */ static DEFINE_MUTEX(opened_mutex); -struct atmel_ac97c_dma { - struct dma_chan *rx_chan; - struct dma_chan *tx_chan; -}; - struct atmel_ac97c { struct clk *pclk; struct platform_device *pdev; - struct atmel_ac97c_dma dma; struct snd_pcm_substream *playback_substream; struct snd_pcm_substream *capture_substream; @@ -74,7 +50,6 @@ struct atmel_ac97c { u64 cur_format; unsigned int cur_rate; - unsigned long flags; int playback_period, capture_period; /* Serialize access to opened variable */ spinlock_t lock; @@ -91,65 +66,6 @@ struct atmel_ac97c { #define ac97c_readl(chip, reg) \ __raw_readl((chip)->regs + AC97C_##reg) -/* This function is called by the DMA driver. */ -static void atmel_ac97c_dma_playback_period_done(void *arg) -{ - struct atmel_ac97c *chip = arg; - snd_pcm_period_elapsed(chip->playback_substream); -} - -static void atmel_ac97c_dma_capture_period_done(void *arg) -{ - struct atmel_ac97c *chip = arg; - snd_pcm_period_elapsed(chip->capture_substream); -} - -static int atmel_ac97c_prepare_dma(struct atmel_ac97c *chip, - struct snd_pcm_substream *substream, - enum dma_transfer_direction direction) -{ - struct dma_chan *chan; - struct dw_cyclic_desc *cdesc; - struct snd_pcm_runtime *runtime = substream->runtime; - unsigned long buffer_len, period_len; - - /* - * We don't do DMA on "complex" transfers, i.e. with - * non-halfword-aligned buffers or lengths. - */ - if (runtime->dma_addr & 1 || runtime->buffer_size & 1) { - dev_dbg(&chip->pdev->dev, "too complex transfer\n"); - return -EINVAL; - } - - if (direction == DMA_MEM_TO_DEV) - chan = chip->dma.tx_chan; - else - chan = chip->dma.rx_chan; - - buffer_len = frames_to_bytes(runtime, runtime->buffer_size); - period_len = frames_to_bytes(runtime, runtime->period_size); - - cdesc = dw_dma_cyclic_prep(chan, runtime->dma_addr, buffer_len, - period_len, direction); - if (IS_ERR(cdesc)) { - dev_dbg(&chip->pdev->dev, "could not prepare cyclic DMA\n"); - return PTR_ERR(cdesc); - } - - if (direction == DMA_MEM_TO_DEV) { - cdesc->period_callback = atmel_ac97c_dma_playback_period_done; - set_bit(DMA_TX_READY, &chip->flags); - } else { - cdesc->period_callback = atmel_ac97c_dma_capture_period_done; - set_bit(DMA_RX_READY, &chip->flags); - } - - cdesc->period_callback_param = chip; - - return 0; -} - static struct snd_pcm_hardware atmel_ac97c_hw = { .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID @@ -254,13 +170,7 @@ static int atmel_ac97c_playback_hw_params(struct snd_pcm_substream *substream, params_buffer_bytes(hw_params)); if (retval < 0) return retval; - /* snd_pcm_lib_malloc_pages returns 1 if buffer is changed. */ - if (cpu_is_at32ap7000()) { - /* snd_pcm_lib_malloc_pages returns 1 if buffer is changed. */ - if (retval == 1) - if (test_and_clear_bit(DMA_TX_READY, &chip->flags)) - dw_dma_cyclic_free(chip->dma.tx_chan); - } + /* Set restrictions to params. */ mutex_lock(&opened_mutex); chip->cur_rate = params_rate(hw_params); @@ -280,10 +190,6 @@ static int atmel_ac97c_capture_hw_params(struct snd_pcm_substream *substream, params_buffer_bytes(hw_params)); if (retval < 0) return retval; - /* snd_pcm_lib_malloc_pages returns 1 if buffer is changed. */ - if (cpu_is_at32ap7000() && retval == 1) - if (test_and_clear_bit(DMA_RX_READY, &chip->flags)) - dw_dma_cyclic_free(chip->dma.rx_chan); /* Set restrictions to params. */ mutex_lock(&opened_mutex); @@ -294,26 +200,6 @@ static int atmel_ac97c_capture_hw_params(struct snd_pcm_substream *substream, return retval; } -static int atmel_ac97c_playback_hw_free(struct snd_pcm_substream *substream) -{ - struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); - if (cpu_is_at32ap7000()) { - if (test_and_clear_bit(DMA_TX_READY, &chip->flags)) - dw_dma_cyclic_free(chip->dma.tx_chan); - } - return snd_pcm_lib_free_pages(substream); -} - -static int atmel_ac97c_capture_hw_free(struct snd_pcm_substream *substream) -{ - struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); - if (cpu_is_at32ap7000()) { - if (test_and_clear_bit(DMA_RX_READY, &chip->flags)) - dw_dma_cyclic_free(chip->dma.rx_chan); - } - return snd_pcm_lib_free_pages(substream); -} - static int atmel_ac97c_playback_prepare(struct snd_pcm_substream *substream) { struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); @@ -349,8 +235,6 @@ static int atmel_ac97c_playback_prepare(struct snd_pcm_substream *substream) switch (runtime->format) { case SNDRV_PCM_FORMAT_S16_LE: - if (cpu_is_at32ap7000()) - word |= AC97C_CMR_CEM_LITTLE; break; case SNDRV_PCM_FORMAT_S16_BE: /* fall through */ word &= ~(AC97C_CMR_CEM_LITTLE); @@ -389,18 +273,11 @@ static int atmel_ac97c_playback_prepare(struct snd_pcm_substream *substream) dev_dbg(&chip->pdev->dev, "could not set rate %d Hz\n", runtime->rate); - if (cpu_is_at32ap7000()) { - if (!test_bit(DMA_TX_READY, &chip->flags)) - retval = atmel_ac97c_prepare_dma(chip, substream, - DMA_MEM_TO_DEV); - } else { - /* Initialize and start the PDC */ - writel(runtime->dma_addr, chip->regs + ATMEL_PDC_TPR); - writel(block_size / 2, chip->regs + ATMEL_PDC_TCR); - writel(runtime->dma_addr + block_size, - chip->regs + ATMEL_PDC_TNPR); - writel(block_size / 2, chip->regs + ATMEL_PDC_TNCR); - } + /* Initialize and start the PDC */ + writel(runtime->dma_addr, chip->regs + ATMEL_PDC_TPR); + writel(block_size / 2, chip->regs + ATMEL_PDC_TCR); + writel(runtime->dma_addr + block_size, chip->regs + ATMEL_PDC_TNPR); + writel(block_size / 2, chip->regs + ATMEL_PDC_TNCR); return retval; } @@ -440,8 +317,6 @@ static int atmel_ac97c_capture_prepare(struct snd_pcm_substream *substream) switch (runtime->format) { case SNDRV_PCM_FORMAT_S16_LE: - if (cpu_is_at32ap7000()) - word |= AC97C_CMR_CEM_LITTLE; break; case SNDRV_PCM_FORMAT_S16_BE: /* fall through */ word &= ~(AC97C_CMR_CEM_LITTLE); @@ -480,18 +355,11 @@ static int atmel_ac97c_capture_prepare(struct snd_pcm_substream *substream) dev_dbg(&chip->pdev->dev, "could not set rate %d Hz\n", runtime->rate); - if (cpu_is_at32ap7000()) { - if (!test_bit(DMA_RX_READY, &chip->flags)) - retval = atmel_ac97c_prepare_dma(chip, substream, - DMA_DEV_TO_MEM); - } else { - /* Initialize and start the PDC */ - writel(runtime->dma_addr, chip->regs + ATMEL_PDC_RPR); - writel(block_size / 2, chip->regs + ATMEL_PDC_RCR); - writel(runtime->dma_addr + block_size, - chip->regs + ATMEL_PDC_RNPR); - writel(block_size / 2, chip->regs + ATMEL_PDC_RNCR); - } + /* Initialize and start the PDC */ + writel(runtime->dma_addr, chip->regs + ATMEL_PDC_RPR); + writel(block_size / 2, chip->regs + ATMEL_PDC_RCR); + writel(runtime->dma_addr + block_size, chip->regs + ATMEL_PDC_RNPR); + writel(block_size / 2, chip->regs + ATMEL_PDC_RNCR); return retval; } @@ -501,7 +369,6 @@ atmel_ac97c_playback_trigger(struct snd_pcm_substream *substream, int cmd) { struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); unsigned long camr, ptcr = 0; - int retval = 0; camr = ac97c_readl(chip, CAMR); @@ -509,35 +376,23 @@ atmel_ac97c_playback_trigger(struct snd_pcm_substream *substream, int cmd) case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: /* fall through */ case SNDRV_PCM_TRIGGER_RESUME: /* fall through */ case SNDRV_PCM_TRIGGER_START: - if (cpu_is_at32ap7000()) { - retval = dw_dma_cyclic_start(chip->dma.tx_chan); - if (retval) - goto out; - } else { - ptcr = ATMEL_PDC_TXTEN; - } + ptcr = ATMEL_PDC_TXTEN; camr |= AC97C_CMR_CENA | AC97C_CSR_ENDTX; break; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: /* fall through */ case SNDRV_PCM_TRIGGER_SUSPEND: /* fall through */ case SNDRV_PCM_TRIGGER_STOP: - if (cpu_is_at32ap7000()) - dw_dma_cyclic_stop(chip->dma.tx_chan); - else - ptcr |= ATMEL_PDC_TXTDIS; + ptcr |= ATMEL_PDC_TXTDIS; if (chip->opened <= 1) camr &= ~AC97C_CMR_CENA; break; default: - retval = -EINVAL; - goto out; + return -EINVAL; } ac97c_writel(chip, CAMR, camr); - if (!cpu_is_at32ap7000()) - writel(ptcr, chip->regs + ATMEL_PDC_PTCR); -out: - return retval; + writel(ptcr, chip->regs + ATMEL_PDC_PTCR); + return 0; } static int @@ -545,7 +400,6 @@ atmel_ac97c_capture_trigger(struct snd_pcm_substream *substream, int cmd) { struct atmel_ac97c *chip = snd_pcm_substream_chip(substream); unsigned long camr, ptcr = 0; - int retval = 0; camr = ac97c_readl(chip, CAMR); ptcr = readl(chip->regs + ATMEL_PDC_PTSR); @@ -554,35 +408,23 @@ atmel_ac97c_capture_trigger(struct snd_pcm_substream *substream, int cmd) case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: /* fall through */ case SNDRV_PCM_TRIGGER_RESUME: /* fall through */ case SNDRV_PCM_TRIGGER_START: - if (cpu_is_at32ap7000()) { - retval = dw_dma_cyclic_start(chip->dma.rx_chan); - if (retval) - goto out; - } else { - ptcr = ATMEL_PDC_RXTEN; - } + ptcr = ATMEL_PDC_RXTEN; camr |= AC97C_CMR_CENA | AC97C_CSR_ENDRX; break; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: /* fall through */ case SNDRV_PCM_TRIGGER_SUSPEND: /* fall through */ case SNDRV_PCM_TRIGGER_STOP: - if (cpu_is_at32ap7000()) - dw_dma_cyclic_stop(chip->dma.rx_chan); - else - ptcr |= (ATMEL_PDC_RXTDIS); + ptcr |= ATMEL_PDC_RXTDIS; if (chip->opened <= 1) camr &= ~AC97C_CMR_CENA; break; default: - retval = -EINVAL; - break; + return -EINVAL; } ac97c_writel(chip, CAMR, camr); - if (!cpu_is_at32ap7000()) - writel(ptcr, chip->regs + ATMEL_PDC_PTCR); -out: - return retval; + writel(ptcr, chip->regs + ATMEL_PDC_PTCR); + return 0; } static snd_pcm_uframes_t @@ -593,10 +435,7 @@ atmel_ac97c_playback_pointer(struct snd_pcm_substream *substream) snd_pcm_uframes_t frames; unsigned long bytes; - if (cpu_is_at32ap7000()) - bytes = dw_dma_get_src_addr(chip->dma.tx_chan); - else - bytes = readl(chip->regs + ATMEL_PDC_TPR); + bytes = readl(chip->regs + ATMEL_PDC_TPR); bytes -= runtime->dma_addr; frames = bytes_to_frames(runtime, bytes); @@ -613,10 +452,7 @@ atmel_ac97c_capture_pointer(struct snd_pcm_substream *substream) snd_pcm_uframes_t frames; unsigned long bytes; - if (cpu_is_at32ap7000()) - bytes = dw_dma_get_dst_addr(chip->dma.rx_chan); - else - bytes = readl(chip->regs + ATMEL_PDC_RPR); + bytes = readl(chip->regs + ATMEL_PDC_RPR); bytes -= runtime->dma_addr; frames = bytes_to_frames(runtime, bytes); @@ -630,7 +466,7 @@ static struct snd_pcm_ops atmel_ac97_playback_ops = { .close = atmel_ac97c_playback_close, .ioctl = snd_pcm_lib_ioctl, .hw_params = atmel_ac97c_playback_hw_params, - .hw_free = atmel_ac97c_playback_hw_free, + .hw_free = snd_pcm_lib_free_pages, .prepare = atmel_ac97c_playback_prepare, .trigger = atmel_ac97c_playback_trigger, .pointer = atmel_ac97c_playback_pointer, @@ -641,7 +477,7 @@ static struct snd_pcm_ops atmel_ac97_capture_ops = { .close = atmel_ac97c_capture_close, .ioctl = snd_pcm_lib_ioctl, .hw_params = atmel_ac97c_capture_hw_params, - .hw_free = atmel_ac97c_capture_hw_free, + .hw_free = snd_pcm_lib_free_pages, .prepare = atmel_ac97c_capture_prepare, .trigger = atmel_ac97c_capture_trigger, .pointer = atmel_ac97c_capture_pointer, @@ -666,49 +502,40 @@ static irqreturn_t atmel_ac97c_interrupt(int irq, void *dev) casr & AC97C_CSR_TXEMPTY ? " TXEMPTY" : "", casr & AC97C_CSR_TXRDY ? " TXRDY" : "", !casr ? " NONE" : ""); - if (!cpu_is_at32ap7000()) { - if ((casr & camr) & AC97C_CSR_ENDTX) { - runtime = chip->playback_substream->runtime; - block_size = frames_to_bytes(runtime, - runtime->period_size); - chip->playback_period++; - - if (chip->playback_period == runtime->periods) - chip->playback_period = 0; - next_period = chip->playback_period + 1; - if (next_period == runtime->periods) - next_period = 0; - - offset = block_size * next_period; - - writel(runtime->dma_addr + offset, - chip->regs + ATMEL_PDC_TNPR); - writel(block_size / 2, - chip->regs + ATMEL_PDC_TNCR); - - snd_pcm_period_elapsed( - chip->playback_substream); - } - if ((casr & camr) & AC97C_CSR_ENDRX) { - runtime = chip->capture_substream->runtime; - block_size = frames_to_bytes(runtime, - runtime->period_size); - chip->capture_period++; - - if (chip->capture_period == runtime->periods) - chip->capture_period = 0; - next_period = chip->capture_period + 1; - if (next_period == runtime->periods) - next_period = 0; - - offset = block_size * next_period; - - writel(runtime->dma_addr + offset, - chip->regs + ATMEL_PDC_RNPR); - writel(block_size / 2, - chip->regs + ATMEL_PDC_RNCR); - snd_pcm_period_elapsed(chip->capture_substream); - } + if ((casr & camr) & AC97C_CSR_ENDTX) { + runtime = chip->playback_substream->runtime; + block_size = frames_to_bytes(runtime, runtime->period_size); + chip->playback_period++; + + if (chip->playback_period == runtime->periods) + chip->playback_period = 0; + next_period = chip->playback_period + 1; + if (next_period == runtime->periods) + next_period = 0; + + offset = block_size * next_period; + + writel(runtime->dma_addr + offset, chip->regs + ATMEL_PDC_TNPR); + writel(block_size / 2, chip->regs + ATMEL_PDC_TNCR); + + snd_pcm_period_elapsed(chip->playback_substream); + } + if ((casr & camr) & AC97C_CSR_ENDRX) { + runtime = chip->capture_substream->runtime; + block_size = frames_to_bytes(runtime, runtime->period_size); + chip->capture_period++; + + if (chip->capture_period == runtime->periods) + chip->capture_period = 0; + next_period = chip->capture_period + 1; + if (next_period == runtime->periods) + next_period = 0; + + offset = block_size * next_period; + + writel(runtime->dma_addr + offset, chip->regs + ATMEL_PDC_RNPR); + writel(block_size / 2, chip->regs + ATMEL_PDC_RNCR); + snd_pcm_period_elapsed(chip->capture_substream); } retval = IRQ_HANDLED; } @@ -763,29 +590,20 @@ static int atmel_ac97c_pcm_new(struct atmel_ac97c *chip) { struct snd_pcm *pcm; struct snd_pcm_hardware hw = atmel_ac97c_hw; - int capture, playback, retval, err; + int retval; - capture = test_bit(DMA_RX_CHAN_PRESENT, &chip->flags); - playback = test_bit(DMA_TX_CHAN_PRESENT, &chip->flags); + retval = snd_ac97_pcm_assign(chip->ac97_bus, + ARRAY_SIZE(at91_ac97_pcm_defs), + at91_ac97_pcm_defs); + if (retval) + return retval; - if (!cpu_is_at32ap7000()) { - err = snd_ac97_pcm_assign(chip->ac97_bus, - ARRAY_SIZE(at91_ac97_pcm_defs), - at91_ac97_pcm_defs); - if (err) - return err; - } - retval = snd_pcm_new(chip->card, chip->card->shortname, - 0, playback, capture, &pcm); + retval = snd_pcm_new(chip->card, chip->card->shortname, 0, 1, 1, &pcm); if (retval) return retval; - if (capture) - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, - &atmel_ac97_capture_ops); - if (playback) - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, - &atmel_ac97_playback_ops); + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &atmel_ac97_capture_ops); + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &atmel_ac97_playback_ops); retval = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, &chip->pdev->dev, hw.periods_min * hw.period_bytes_min, @@ -875,17 +693,6 @@ timed_out: return 0xffff; } -static bool filter(struct dma_chan *chan, void *slave) -{ - struct dw_dma_slave *dws = slave; - - if (dws->dma_dev == chan->device->dev) { - chan->private = dws; - return true; - } else - return false; -} - static void atmel_ac97c_reset(struct atmel_ac97c *chip) { ac97c_writel(chip, MR, 0); @@ -967,16 +774,11 @@ static int atmel_ac97c_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) { - dev_dbg(&pdev->dev, "could not get irq\n"); - return -ENXIO; - } - - if (cpu_is_at32ap7000()) { - pclk = clk_get(&pdev->dev, "pclk"); - } else { - pclk = clk_get(&pdev->dev, "ac97_clk"); + dev_dbg(&pdev->dev, "could not get irq: %d\n", irq); + return irq; } + pclk = clk_get(&pdev->dev, "ac97_clk"); if (IS_ERR(pclk)) { dev_dbg(&pdev->dev, "no peripheral clock\n"); return PTR_ERR(pclk); @@ -1047,88 +849,16 @@ static int atmel_ac97c_probe(struct platform_device *pdev) goto err_ac97_bus; } - if (cpu_is_at32ap7000()) { - if (pdata->rx_dws.dma_dev) { - dma_cap_mask_t mask; - - dma_cap_zero(mask); - dma_cap_set(DMA_SLAVE, mask); - - chip->dma.rx_chan = dma_request_channel(mask, filter, - &pdata->rx_dws); - if (chip->dma.rx_chan) { - struct dma_slave_config dma_conf = { - .src_addr = regs->start + AC97C_CARHR + - 2, - .src_addr_width = - DMA_SLAVE_BUSWIDTH_2_BYTES, - .src_maxburst = 1, - .dst_maxburst = 1, - .direction = DMA_DEV_TO_MEM, - .device_fc = false, - }; - - dmaengine_slave_config(chip->dma.rx_chan, - &dma_conf); - } - - dev_info(&chip->pdev->dev, "using %s for DMA RX\n", - dev_name(&chip->dma.rx_chan->dev->device)); - set_bit(DMA_RX_CHAN_PRESENT, &chip->flags); - } - - if (pdata->tx_dws.dma_dev) { - dma_cap_mask_t mask; - - dma_cap_zero(mask); - dma_cap_set(DMA_SLAVE, mask); - - chip->dma.tx_chan = dma_request_channel(mask, filter, - &pdata->tx_dws); - if (chip->dma.tx_chan) { - struct dma_slave_config dma_conf = { - .dst_addr = regs->start + AC97C_CATHR + - 2, - .dst_addr_width = - DMA_SLAVE_BUSWIDTH_2_BYTES, - .src_maxburst = 1, - .dst_maxburst = 1, - .direction = DMA_MEM_TO_DEV, - .device_fc = false, - }; - - dmaengine_slave_config(chip->dma.tx_chan, - &dma_conf); - } - - dev_info(&chip->pdev->dev, "using %s for DMA TX\n", - dev_name(&chip->dma.tx_chan->dev->device)); - set_bit(DMA_TX_CHAN_PRESENT, &chip->flags); - } - - if (!test_bit(DMA_RX_CHAN_PRESENT, &chip->flags) && - !test_bit(DMA_TX_CHAN_PRESENT, &chip->flags)) { - dev_dbg(&pdev->dev, "DMA not available\n"); - retval = -ENODEV; - goto err_dma; - } - } else { - /* Just pretend that we have DMA channel(for at91 i is actually - * the PDC) */ - set_bit(DMA_RX_CHAN_PRESENT, &chip->flags); - set_bit(DMA_TX_CHAN_PRESENT, &chip->flags); - } - retval = atmel_ac97c_pcm_new(chip); if (retval) { dev_dbg(&pdev->dev, "could not register ac97 pcm device\n"); - goto err_dma; + goto err_ac97_bus; } retval = snd_card_register(card); if (retval) { dev_dbg(&pdev->dev, "could not register sound card\n"); - goto err_dma; + goto err_ac97_bus; } platform_set_drvdata(pdev, card); @@ -1138,17 +868,6 @@ static int atmel_ac97c_probe(struct platform_device *pdev) return 0; -err_dma: - if (cpu_is_at32ap7000()) { - if (test_bit(DMA_RX_CHAN_PRESENT, &chip->flags)) - dma_release_channel(chip->dma.rx_chan); - if (test_bit(DMA_TX_CHAN_PRESENT, &chip->flags)) - dma_release_channel(chip->dma.tx_chan); - clear_bit(DMA_RX_CHAN_PRESENT, &chip->flags); - clear_bit(DMA_TX_CHAN_PRESENT, &chip->flags); - chip->dma.rx_chan = NULL; - chip->dma.tx_chan = NULL; - } err_ac97_bus: if (gpio_is_valid(chip->reset_pin)) gpio_free(chip->reset_pin); @@ -1170,14 +889,7 @@ static int atmel_ac97c_suspend(struct device *pdev) struct snd_card *card = dev_get_drvdata(pdev); struct atmel_ac97c *chip = card->private_data; - if (cpu_is_at32ap7000()) { - if (test_bit(DMA_RX_READY, &chip->flags)) - dw_dma_cyclic_stop(chip->dma.rx_chan); - if (test_bit(DMA_TX_READY, &chip->flags)) - dw_dma_cyclic_stop(chip->dma.tx_chan); - } clk_disable_unprepare(chip->pclk); - return 0; } @@ -1187,12 +899,6 @@ static int atmel_ac97c_resume(struct device *pdev) struct atmel_ac97c *chip = card->private_data; clk_prepare_enable(chip->pclk); - if (cpu_is_at32ap7000()) { - if (test_bit(DMA_RX_READY, &chip->flags)) - dw_dma_cyclic_start(chip->dma.rx_chan); - if (test_bit(DMA_TX_READY, &chip->flags)) - dw_dma_cyclic_start(chip->dma.tx_chan); - } return 0; } @@ -1219,17 +925,6 @@ static int atmel_ac97c_remove(struct platform_device *pdev) iounmap(chip->regs); free_irq(chip->irq, chip); - if (cpu_is_at32ap7000()) { - if (test_bit(DMA_RX_CHAN_PRESENT, &chip->flags)) - dma_release_channel(chip->dma.rx_chan); - if (test_bit(DMA_TX_CHAN_PRESENT, &chip->flags)) - dma_release_channel(chip->dma.tx_chan); - clear_bit(DMA_RX_CHAN_PRESENT, &chip->flags); - clear_bit(DMA_TX_CHAN_PRESENT, &chip->flags); - chip->dma.rx_chan = NULL; - chip->dma.tx_chan = NULL; - } - snd_card_free(card); return 0; diff --git a/sound/core/Kconfig b/sound/core/Kconfig index 9749f9e8b45c..6e937a8146a1 100644 --- a/sound/core/Kconfig +++ b/sound/core/Kconfig @@ -18,8 +18,12 @@ config SND_DMAENGINE_PCM config SND_HWDEP tristate +config SND_SEQ_DEVICE + tristate + config SND_RAWMIDI tristate + select SND_SEQ_DEVICE if SND_SEQUENCER != n config SND_COMPRESS_OFFLOAD tristate @@ -33,38 +37,15 @@ config SND_JACK_INPUT_DEV depends on SND_JACK default y if INPUT=y || INPUT=SND -config SND_SEQUENCER - tristate "Sequencer support" - select SND_TIMER - help - Say Y or M to enable MIDI sequencer and router support. This - feature allows routing and enqueueing of MIDI events. Events - can be processed at a given time. - - Many programs require this feature, so you should enable it - unless you know what you're doing. - -config SND_SEQ_DUMMY - tristate "Sequencer dummy client" - depends on SND_SEQUENCER - help - Say Y here to enable the dummy sequencer client. This client - is a simple MIDI-through client: all normal input events are - redirected to the output port immediately. - - You don't need this unless you want to connect many MIDI - devices or applications together. - - To compile this driver as a module, choose M here: the module - will be called snd-seq-dummy. - config SND_OSSEMUL + bool "Enable OSS Emulation" select SOUND_OSS_CORE - bool + help + This option enables the build of OSS emulation layer. config SND_MIXER_OSS tristate "OSS Mixer API" - select SND_OSSEMUL + depends on SND_OSSEMUL help To enable OSS mixer API emulation (/dev/mixer*), say Y here and read <file:Documentation/sound/alsa/OSS-Emulation.txt>. @@ -76,7 +57,7 @@ config SND_MIXER_OSS config SND_PCM_OSS tristate "OSS PCM (digital audio) API" - select SND_OSSEMUL + depends on SND_OSSEMUL select SND_PCM help To enable OSS digital audio (PCM) emulation (/dev/dsp*), say Y @@ -107,20 +88,6 @@ config SND_PCM_TIMER For some embedded devices, we may disable it to reduce memory footprint, about 20KB on x86_64 platform. -config SND_SEQUENCER_OSS - bool "OSS Sequencer API" - depends on SND_SEQUENCER - select SND_OSSEMUL - help - Say Y here to enable OSS sequencer emulation (both - /dev/sequencer and /dev/music interfaces). - - Many programs still use the OSS API, so say Y. - - If you choose M in "Sequencer support" (SND_SEQUENCER), - this will be compiled as a module. The module will be called - snd-seq-oss. - config SND_HRTIMER tristate "HR-timer backend support" depends on HIGH_RES_TIMERS @@ -133,14 +100,6 @@ config SND_HRTIMER To compile this driver as a module, choose M here: the module will be called snd-hrtimer. -config SND_SEQ_HRTIMER_DEFAULT - bool "Use HR-timer as default sequencer timer" - depends on SND_HRTIMER && SND_SEQUENCER - default y - help - Say Y here to use the HR-timer backend as the default sequencer - timer. - config SND_DYNAMIC_MINORS bool "Dynamic device file minor numbers" help diff --git a/sound/core/Makefile b/sound/core/Makefile index e85d9dd12c2d..e2066e2ef9f8 100644 --- a/sound/core/Makefile +++ b/sound/core/Makefile @@ -22,6 +22,7 @@ snd-pcm-$(CONFIG_SND_PCM_IEC958) += pcm_iec958.o # for trace-points CFLAGS_pcm_lib.o := -I$(src) +CFLAGS_pcm_native.o := -I$(src) snd-pcm-dmaengine-objs := pcm_dmaengine.o @@ -30,6 +31,7 @@ snd-timer-objs := timer.o snd-hrtimer-objs := hrtimer.o snd-rtctimer-objs := rtctimer.o snd-hwdep-objs := hwdep.o +snd-seq-device-objs := seq_device.o snd-compress-objs := compress_offload.o @@ -39,6 +41,7 @@ obj-$(CONFIG_SND_TIMER) += snd-timer.o obj-$(CONFIG_SND_HRTIMER) += snd-hrtimer.o obj-$(CONFIG_SND_PCM) += snd-pcm.o obj-$(CONFIG_SND_DMAENGINE_PCM) += snd-pcm-dmaengine.o +obj-$(CONFIG_SND_SEQ_DEVICE) += snd-seq-device.o obj-$(CONFIG_SND_RAWMIDI) += snd-rawmidi.o obj-$(CONFIG_SND_OSSEMUL) += oss/ diff --git a/sound/core/control.c b/sound/core/control.c index c109b82eef4b..3c6be1452e35 100644 --- a/sound/core/control.c +++ b/sound/core/control.c @@ -747,65 +747,45 @@ static int snd_ctl_card_info(struct snd_card *card, struct snd_ctl_file * ctl, static int snd_ctl_elem_list(struct snd_card *card, struct snd_ctl_elem_list __user *_list) { - struct list_head *plist; struct snd_ctl_elem_list list; struct snd_kcontrol *kctl; - struct snd_ctl_elem_id *dst, *id; + struct snd_ctl_elem_id id; unsigned int offset, space, jidx; + int err = 0; if (copy_from_user(&list, _list, sizeof(list))) return -EFAULT; offset = list.offset; space = list.space; - /* try limit maximum space */ - if (space > 16384) - return -ENOMEM; + + down_read(&card->controls_rwsem); + list.count = card->controls_count; + list.used = 0; if (space > 0) { - /* allocate temporary buffer for atomic operation */ - dst = vmalloc(space * sizeof(struct snd_ctl_elem_id)); - if (dst == NULL) - return -ENOMEM; - down_read(&card->controls_rwsem); - list.count = card->controls_count; - plist = card->controls.next; - while (plist != &card->controls) { - if (offset == 0) - break; - kctl = snd_kcontrol(plist); - if (offset < kctl->count) - break; - offset -= kctl->count; - plist = plist->next; - } - list.used = 0; - id = dst; - while (space > 0 && plist != &card->controls) { - kctl = snd_kcontrol(plist); - for (jidx = offset; space > 0 && jidx < kctl->count; jidx++) { - snd_ctl_build_ioff(id, kctl, jidx); - id++; - space--; + list_for_each_entry(kctl, &card->controls, list) { + if (offset >= kctl->count) { + offset -= kctl->count; + continue; + } + for (jidx = offset; jidx < kctl->count; jidx++) { + snd_ctl_build_ioff(&id, kctl, jidx); + if (copy_to_user(list.pids + list.used, &id, + sizeof(id))) { + err = -EFAULT; + goto out; + } list.used++; + if (!--space) + goto out; } - plist = plist->next; offset = 0; } - up_read(&card->controls_rwsem); - if (list.used > 0 && - copy_to_user(list.pids, dst, - list.used * sizeof(struct snd_ctl_elem_id))) { - vfree(dst); - return -EFAULT; - } - vfree(dst); - } else { - down_read(&card->controls_rwsem); - list.count = card->controls_count; - up_read(&card->controls_rwsem); } - if (copy_to_user(_list, &list, sizeof(list))) - return -EFAULT; - return 0; + out: + up_read(&card->controls_rwsem); + if (!err && copy_to_user(_list, &list, sizeof(list))) + err = -EFAULT; + return err; } static bool validate_element_member_dimension(struct snd_ctl_elem_info *info) @@ -1577,7 +1557,7 @@ static ssize_t snd_ctl_read(struct file *file, char __user *buffer, struct snd_ctl_event ev; struct snd_kctl_event *kev; while (list_empty(&ctl->events)) { - wait_queue_t wait; + wait_queue_entry_t wait; if ((file->f_flags & O_NONBLOCK) != 0 || result > 0) { err = -EAGAIN; goto __end_lock; diff --git a/sound/core/ctljack.c b/sound/core/ctljack.c index 84a3cd683068..0249d5e6ac23 100644 --- a/sound/core/ctljack.c +++ b/sound/core/ctljack.c @@ -23,7 +23,7 @@ static int jack_detect_kctl_get(struct snd_kcontrol *kcontrol, return 0; } -static struct snd_kcontrol_new jack_detect_kctl = { +static const struct snd_kcontrol_new jack_detect_kctl = { /* name is filled later */ .iface = SNDRV_CTL_ELEM_IFACE_CARD, .access = SNDRV_CTL_ELEM_ACCESS_READ, diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c index 9602a7e38d8a..a73baa1242be 100644 --- a/sound/core/hwdep.c +++ b/sound/core/hwdep.c @@ -85,7 +85,7 @@ static int snd_hwdep_open(struct inode *inode, struct file * file) int major = imajor(inode); struct snd_hwdep *hw; int err; - wait_queue_t wait; + wait_queue_entry_t wait; if (major == snd_major) { hw = snd_lookup_minor_data(iminor(inode), diff --git a/sound/core/info.c b/sound/core/info.c index 8ab72e0f5932..bcf6a48cc70d 100644 --- a/sound/core/info.c +++ b/sound/core/info.c @@ -344,12 +344,12 @@ static ssize_t snd_info_text_entry_write(struct file *file, } } if (next > buf->len) { - char *nbuf = krealloc(buf->buffer, PAGE_ALIGN(next), - GFP_KERNEL | __GFP_ZERO); + char *nbuf = kvzalloc(PAGE_ALIGN(next), GFP_KERNEL); if (!nbuf) { err = -ENOMEM; goto error; } + kvfree(buf->buffer); buf->buffer = nbuf; buf->len = PAGE_ALIGN(next); } @@ -427,7 +427,7 @@ static int snd_info_text_entry_release(struct inode *inode, struct file *file) single_release(inode, file); kfree(data->rbuffer); if (data->wbuffer) { - kfree(data->wbuffer->buffer); + kvfree(data->wbuffer->buffer); kfree(data->wbuffer); } @@ -652,7 +652,6 @@ int snd_info_get_line(struct snd_info_buffer *buffer, char *line, int len) *line = '\0'; return 0; } - EXPORT_SYMBOL(snd_info_get_line); /** @@ -690,7 +689,6 @@ const char *snd_info_get_str(char *dest, const char *src, int len) src++; return src; } - EXPORT_SYMBOL(snd_info_get_str); /* @@ -748,7 +746,6 @@ struct snd_info_entry *snd_info_create_module_entry(struct module * module, entry->module = module; return entry; } - EXPORT_SYMBOL(snd_info_create_module_entry); /** @@ -772,7 +769,6 @@ struct snd_info_entry *snd_info_create_card_entry(struct snd_card *card, } return entry; } - EXPORT_SYMBOL(snd_info_create_card_entry); static void snd_info_disconnect(struct snd_info_entry *entry) @@ -815,7 +811,6 @@ void snd_info_free_entry(struct snd_info_entry * entry) entry->private_free(entry); kfree(entry); } - EXPORT_SYMBOL(snd_info_free_entry); /** @@ -858,7 +853,6 @@ int snd_info_register(struct snd_info_entry * entry) mutex_unlock(&info_mutex); return 0; } - EXPORT_SYMBOL(snd_info_register); /* diff --git a/sound/core/info_oss.c b/sound/core/info_oss.c index 1478c8dfd473..f479374b6bd8 100644 --- a/sound/core/info_oss.c +++ b/sound/core/info_oss.c @@ -61,7 +61,6 @@ int snd_oss_info_register(int dev, int num, char *string) mutex_unlock(&strings); return 0; } - EXPORT_SYMBOL(snd_oss_info_register); static int snd_sndstat_show_strings(struct snd_info_buffer *buf, char *id, int dev) diff --git a/sound/core/init.c b/sound/core/init.c index 6bda8436d765..b4365bcf28a7 100644 --- a/sound/core/init.c +++ b/sound/core/init.c @@ -452,7 +452,6 @@ int snd_card_disconnect(struct snd_card *card) #endif return 0; } - EXPORT_SYMBOL(snd_card_disconnect); static int snd_card_do_free(struct snd_card *card) @@ -718,7 +717,7 @@ int snd_card_add_dev_attr(struct snd_card *card, dev_err(card->dev, "Too many groups assigned\n"); return -ENOSPC; -}; +} EXPORT_SYMBOL_GPL(snd_card_add_dev_attr); /** @@ -775,7 +774,6 @@ int snd_card_register(struct snd_card *card) #endif return 0; } - EXPORT_SYMBOL(snd_card_register); #ifdef CONFIG_SND_PROC_FS @@ -895,7 +893,6 @@ int snd_component_add(struct snd_card *card, const char *component) strcat(card->components, component); return 0; } - EXPORT_SYMBOL(snd_component_add); /** @@ -930,7 +927,6 @@ int snd_card_file_add(struct snd_card *card, struct file *file) spin_unlock(&card->files_lock); return 0; } - EXPORT_SYMBOL(snd_card_file_add); /** @@ -972,7 +968,6 @@ int snd_card_file_remove(struct snd_card *card, struct file *file) put_device(&card->card_dev); return 0; } - EXPORT_SYMBOL(snd_card_file_remove); #ifdef CONFIG_PM @@ -989,7 +984,7 @@ EXPORT_SYMBOL(snd_card_file_remove); */ int snd_power_wait(struct snd_card *card, unsigned int power_state) { - wait_queue_t wait; + wait_queue_entry_t wait; int result = 0; /* fastpath */ @@ -1012,6 +1007,5 @@ int snd_power_wait(struct snd_card *card, unsigned int power_state) remove_wait_queue(&card->power_sleep, &wait); return result; } - EXPORT_SYMBOL(snd_power_wait); #endif /* CONFIG_PM */ diff --git a/sound/core/isadma.c b/sound/core/isadma.c index 31e8544d7f2d..7a8515abb5f9 100644 --- a/sound/core/isadma.c +++ b/sound/core/isadma.c @@ -55,7 +55,6 @@ void snd_dma_program(unsigned long dma, enable_dma(dma); release_dma_lock(flags); } - EXPORT_SYMBOL(snd_dma_program); /** @@ -73,7 +72,6 @@ void snd_dma_disable(unsigned long dma) disable_dma(dma); release_dma_lock(flags); } - EXPORT_SYMBOL(snd_dma_disable); /** @@ -113,5 +111,4 @@ unsigned int snd_dma_pointer(unsigned long dma, unsigned int size) else return size - result; } - EXPORT_SYMBOL(snd_dma_pointer); diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c index f05cb6a8cbe0..7f89d3c79a4b 100644 --- a/sound/core/memalloc.c +++ b/sound/core/memalloc.c @@ -54,6 +54,7 @@ void *snd_malloc_pages(size_t size, gfp_t gfp_flags) pg = get_order(size); return (void *) __get_free_pages(gfp_flags, pg); } +EXPORT_SYMBOL(snd_malloc_pages); /** * snd_free_pages - release the pages @@ -71,6 +72,7 @@ void snd_free_pages(void *ptr, size_t size) pg = get_order(size); free_pages((unsigned long) ptr, pg); } +EXPORT_SYMBOL(snd_free_pages); /* * @@ -217,6 +219,7 @@ int snd_dma_alloc_pages(int type, struct device *device, size_t size, dmab->bytes = size; return 0; } +EXPORT_SYMBOL(snd_dma_alloc_pages); /** * snd_dma_alloc_pages_fallback - allocate the buffer area according to the given type with fallback @@ -254,6 +257,7 @@ int snd_dma_alloc_pages_fallback(int type, struct device *device, size_t size, return -ENOMEM; return 0; } +EXPORT_SYMBOL(snd_dma_alloc_pages_fallback); /** @@ -287,13 +291,4 @@ void snd_dma_free_pages(struct snd_dma_buffer *dmab) pr_err("snd-malloc: invalid device type %d\n", dmab->dev.type); } } - -/* - * exports - */ -EXPORT_SYMBOL(snd_dma_alloc_pages); -EXPORT_SYMBOL(snd_dma_alloc_pages_fallback); EXPORT_SYMBOL(snd_dma_free_pages); - -EXPORT_SYMBOL(snd_malloc_pages); -EXPORT_SYMBOL(snd_free_pages); diff --git a/sound/core/memory.c b/sound/core/memory.c index 4cd664efad77..19c9ea90d9bf 100644 --- a/sound/core/memory.c +++ b/sound/core/memory.c @@ -55,7 +55,6 @@ int copy_to_user_fromio(void __user *dst, const volatile void __iomem *src, size return 0; #endif } - EXPORT_SYMBOL(copy_to_user_fromio); /** @@ -88,5 +87,4 @@ int copy_from_user_toio(volatile void __iomem *dst, const void __user *src, size return 0; #endif } - EXPORT_SYMBOL(copy_from_user_toio); diff --git a/sound/core/misc.c b/sound/core/misc.c index 21b228046e88..0f818d593c9e 100644 --- a/sound/core/misc.c +++ b/sound/core/misc.c @@ -48,7 +48,6 @@ void release_and_free_resource(struct resource *res) kfree(res); } } - EXPORT_SYMBOL(release_and_free_resource); #ifdef CONFIG_SND_VERBOSE_PRINTK diff --git a/sound/core/oss/io.c b/sound/core/oss/io.c index 6faa1d719206..d870b2d93135 100644 --- a/sound/core/oss/io.c +++ b/sound/core/oss/io.c @@ -26,9 +26,9 @@ #include "pcm_plugin.h" #define pcm_write(plug,buf,count) snd_pcm_oss_write3(plug,buf,count,1) -#define pcm_writev(plug,vec,count) snd_pcm_oss_writev3(plug,vec,count,1) +#define pcm_writev(plug,vec,count) snd_pcm_oss_writev3(plug,vec,count) #define pcm_read(plug,buf,count) snd_pcm_oss_read3(plug,buf,count,1) -#define pcm_readv(plug,vec,count) snd_pcm_oss_readv3(plug,vec,count,1) +#define pcm_readv(plug,vec,count) snd_pcm_oss_readv3(plug,vec,count) /* * Basic io plugin diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c index 2ff9c12d664a..379bf486ccc7 100644 --- a/sound/core/oss/mixer_oss.c +++ b/sound/core/oss/mixer_oss.c @@ -395,6 +395,7 @@ int snd_mixer_oss_ioctl_card(struct snd_card *card, unsigned int cmd, unsigned l fmixer.mixer = card->mixer_oss; return snd_mixer_oss_ioctl1(&fmixer, cmd, arg); } +EXPORT_SYMBOL(snd_mixer_oss_ioctl_card); #ifdef CONFIG_COMPAT /* all compatible */ @@ -1425,5 +1426,3 @@ static void __exit alsa_mixer_oss_exit(void) module_init(alsa_mixer_oss_init) module_exit(alsa_mixer_oss_exit) - -EXPORT_SYMBOL(snd_mixer_oss_ioctl_card); diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index 36baf962f9b0..e49f448ee04f 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -67,18 +67,6 @@ static int snd_pcm_oss_get_rate(struct snd_pcm_oss_file *pcm_oss_file); static int snd_pcm_oss_get_channels(struct snd_pcm_oss_file *pcm_oss_file); static int snd_pcm_oss_get_format(struct snd_pcm_oss_file *pcm_oss_file); -static inline mm_segment_t snd_enter_user(void) -{ - mm_segment_t fs = get_fs(); - set_fs(get_ds()); - return fs; -} - -static inline void snd_leave_user(mm_segment_t fs) -{ - set_fs(fs); -} - /* * helper functions to process hw_params */ @@ -799,7 +787,7 @@ static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream, static int choose_rate(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, unsigned int best_rate) { - struct snd_interval *it; + const struct snd_interval *it; struct snd_pcm_hw_params *save; unsigned int rate, prev; @@ -807,7 +795,7 @@ static int choose_rate(struct snd_pcm_substream *substream, if (save == NULL) return -ENOMEM; *save = *params; - it = hw_param_interval(save, SNDRV_PCM_HW_PARAM_RATE); + it = hw_param_interval_c(save, SNDRV_PCM_HW_PARAM_RATE); /* try multiples of the best rate */ rate = best_rate; @@ -848,7 +836,7 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream, int direct; snd_pcm_format_t format, sformat; int n; - struct snd_mask sformat_mask; + const struct snd_mask *sformat_mask; struct snd_mask mask; if (trylock) { @@ -891,18 +879,18 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream, format = snd_pcm_oss_format_from(runtime->oss.format); - sformat_mask = *hw_param_mask(sparams, SNDRV_PCM_HW_PARAM_FORMAT); + sformat_mask = hw_param_mask_c(sparams, SNDRV_PCM_HW_PARAM_FORMAT); if (direct) sformat = format; else - sformat = snd_pcm_plug_slave_format(format, &sformat_mask); + sformat = snd_pcm_plug_slave_format(format, sformat_mask); if ((__force int)sformat < 0 || - !snd_mask_test(&sformat_mask, (__force int)sformat)) { + !snd_mask_test(sformat_mask, (__force int)sformat)) { for (sformat = (__force snd_pcm_format_t)0; (__force int)sformat <= (__force int)SNDRV_PCM_FORMAT_LAST; sformat = (__force snd_pcm_format_t)((__force int)sformat + 1)) { - if (snd_mask_test(&sformat_mask, (__force int)sformat) && + if (snd_mask_test(sformat_mask, (__force int)sformat) && snd_pcm_oss_format_to(sformat) >= 0) break; } @@ -1191,14 +1179,8 @@ snd_pcm_sframes_t snd_pcm_oss_write3(struct snd_pcm_substream *substream, const if (ret < 0) break; } - if (in_kernel) { - mm_segment_t fs; - fs = snd_enter_user(); - ret = snd_pcm_lib_write(substream, (void __force __user *)ptr, frames); - snd_leave_user(fs); - } else { - ret = snd_pcm_lib_write(substream, (void __force __user *)ptr, frames); - } + ret = __snd_pcm_lib_xfer(substream, (void *)ptr, true, + frames, in_kernel); if (ret != -EPIPE && ret != -ESTRPIPE) break; /* test, if we can't store new data, because the stream */ @@ -1234,14 +1216,8 @@ snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream, char *p ret = snd_pcm_oss_capture_position_fixup(substream, &delay); if (ret < 0) break; - if (in_kernel) { - mm_segment_t fs; - fs = snd_enter_user(); - ret = snd_pcm_lib_read(substream, (void __force __user *)ptr, frames); - snd_leave_user(fs); - } else { - ret = snd_pcm_lib_read(substream, (void __force __user *)ptr, frames); - } + ret = __snd_pcm_lib_xfer(substream, (void *)ptr, true, + frames, in_kernel); if (ret == -EPIPE) { if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) { ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL); @@ -1256,7 +1232,8 @@ snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream, char *p return ret; } -snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, void **bufs, snd_pcm_uframes_t frames, int in_kernel) +#ifdef CONFIG_SND_PCM_OSS_PLUGINS +snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, void **bufs, snd_pcm_uframes_t frames) { struct snd_pcm_runtime *runtime = substream->runtime; int ret; @@ -1273,14 +1250,7 @@ snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, void if (ret < 0) break; } - if (in_kernel) { - mm_segment_t fs; - fs = snd_enter_user(); - ret = snd_pcm_lib_writev(substream, (void __user **)bufs, frames); - snd_leave_user(fs); - } else { - ret = snd_pcm_lib_writev(substream, (void __user **)bufs, frames); - } + ret = snd_pcm_kernel_writev(substream, bufs, frames); if (ret != -EPIPE && ret != -ESTRPIPE) break; @@ -1292,7 +1262,7 @@ snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, void return ret; } -snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream, void **bufs, snd_pcm_uframes_t frames, int in_kernel) +snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream, void **bufs, snd_pcm_uframes_t frames) { struct snd_pcm_runtime *runtime = substream->runtime; int ret; @@ -1313,19 +1283,13 @@ snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream, void * if (ret < 0) break; } - if (in_kernel) { - mm_segment_t fs; - fs = snd_enter_user(); - ret = snd_pcm_lib_readv(substream, (void __user **)bufs, frames); - snd_leave_user(fs); - } else { - ret = snd_pcm_lib_readv(substream, (void __user **)bufs, frames); - } + ret = snd_pcm_kernel_readv(substream, bufs, frames); if (ret != -EPIPE && ret != -ESTRPIPE) break; } return ret; } +#endif /* CONFIG_SND_PCM_OSS_PLUGINS */ static ssize_t snd_pcm_oss_write2(struct snd_pcm_substream *substream, const char *buf, size_t bytes, int in_kernel) { @@ -1554,7 +1518,7 @@ static int snd_pcm_oss_sync1(struct snd_pcm_substream *substream, size_t size) ssize_t result = 0; snd_pcm_state_t state; long res; - wait_queue_t wait; + wait_queue_entry_t wait; runtime = substream->runtime; init_waitqueue_entry(&wait, current); @@ -1650,27 +1614,10 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file) size = runtime->control->appl_ptr % runtime->period_size; if (size > 0) { size = runtime->period_size - size; - if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED) { - size = (runtime->frame_bits * size) / 8; - while (size > 0) { - mm_segment_t fs; - size_t size1 = size < runtime->oss.period_bytes ? size : runtime->oss.period_bytes; - size -= size1; - size1 *= 8; - size1 /= runtime->sample_bits; - snd_pcm_format_set_silence(runtime->format, - runtime->oss.buffer, - size1); - size1 /= runtime->channels; /* frames */ - fs = snd_enter_user(); - snd_pcm_lib_write(substream, (void __force __user *)runtime->oss.buffer, size1); - snd_leave_user(fs); - } - } else if (runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) { - void __user *buffers[runtime->channels]; - memset(buffers, 0, runtime->channels * sizeof(void *)); - snd_pcm_lib_writev(substream, buffers, size); - } + if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED) + snd_pcm_lib_write(substream, NULL, size); + else if (runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) + snd_pcm_lib_writev(substream, NULL, size); } mutex_unlock(&runtime->oss.params_lock); /* @@ -1780,7 +1727,7 @@ static int snd_pcm_oss_get_formats(struct snd_pcm_oss_file *pcm_oss_file) int direct; struct snd_pcm_hw_params *params; unsigned int formats = 0; - struct snd_mask format_mask; + const struct snd_mask *format_mask; int fmt; if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0) @@ -1802,12 +1749,12 @@ static int snd_pcm_oss_get_formats(struct snd_pcm_oss_file *pcm_oss_file) return -ENOMEM; _snd_pcm_hw_params_any(params); err = snd_pcm_hw_refine(substream, params); - format_mask = *hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); + format_mask = hw_param_mask_c(params, SNDRV_PCM_HW_PARAM_FORMAT); kfree(params); if (err < 0) return err; for (fmt = 0; fmt < 32; ++fmt) { - if (snd_mask_test(&format_mask, fmt)) { + if (snd_mask_test(format_mask, fmt)) { int f = snd_pcm_oss_format_to(fmt); if (f >= 0) formats |= f; @@ -2387,7 +2334,7 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file) struct snd_pcm_oss_file *pcm_oss_file; struct snd_pcm_oss_setup setup[2]; int nonblock; - wait_queue_t wait; + wait_queue_entry_t wait; err = nonseekable_open(inode, file); if (err < 0) diff --git a/sound/core/oss/pcm_plugin.c b/sound/core/oss/pcm_plugin.c index 727ac44d39f4..cadc93792868 100644 --- a/sound/core/oss/pcm_plugin.c +++ b/sound/core/oss/pcm_plugin.c @@ -266,7 +266,8 @@ snd_pcm_sframes_t snd_pcm_plug_slave_size(struct snd_pcm_substream *plug, snd_pc return frames; } -static int snd_pcm_plug_formats(struct snd_mask *mask, snd_pcm_format_t format) +static int snd_pcm_plug_formats(const struct snd_mask *mask, + snd_pcm_format_t format) { struct snd_mask formats = *mask; u64 linfmts = (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 | @@ -309,7 +310,7 @@ static snd_pcm_format_t preferred_formats[] = { }; snd_pcm_format_t snd_pcm_plug_slave_format(snd_pcm_format_t format, - struct snd_mask *format_mask) + const struct snd_mask *format_mask) { int i; diff --git a/sound/core/oss/pcm_plugin.h b/sound/core/oss/pcm_plugin.h index a5035c2369a6..c9cd29d86efd 100644 --- a/sound/core/oss/pcm_plugin.h +++ b/sound/core/oss/pcm_plugin.h @@ -126,7 +126,7 @@ int snd_pcm_plug_format_plugins(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *slave_params); snd_pcm_format_t snd_pcm_plug_slave_format(snd_pcm_format_t format, - struct snd_mask *format_mask); + const struct snd_mask *format_mask); int snd_pcm_plugin_append(struct snd_pcm_plugin *plugin); @@ -162,17 +162,15 @@ snd_pcm_sframes_t snd_pcm_oss_write3(struct snd_pcm_substream *substream, snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream, char *ptr, snd_pcm_uframes_t size, int in_kernel); snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, - void **bufs, snd_pcm_uframes_t frames, - int in_kernel); + void **bufs, snd_pcm_uframes_t frames); snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream, - void **bufs, snd_pcm_uframes_t frames, - int in_kernel); + void **bufs, snd_pcm_uframes_t frames); #else static inline snd_pcm_sframes_t snd_pcm_plug_client_size(struct snd_pcm_substream *handle, snd_pcm_uframes_t drv_size) { return drv_size; } static inline snd_pcm_sframes_t snd_pcm_plug_slave_size(struct snd_pcm_substream *handle, snd_pcm_uframes_t clt_size) { return clt_size; } -static inline int snd_pcm_plug_slave_format(int format, struct snd_mask *format_mask) { return format; } +static inline int snd_pcm_plug_slave_format(int format, const struct snd_mask *format_mask) { return format; } #endif diff --git a/sound/core/pcm.c b/sound/core/pcm.c index 8e980aa678d0..89c7485519cb 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -31,13 +31,17 @@ #include <sound/control.h> #include <sound/info.h> +#include "pcm_local.h" + MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, Abramo Bagnara <abramo@alsa-project.org>"); MODULE_DESCRIPTION("Midlevel PCM code for ALSA."); MODULE_LICENSE("GPL"); static LIST_HEAD(snd_pcm_devices); -static LIST_HEAD(snd_pcm_notify_list); static DEFINE_MUTEX(register_mutex); +#if IS_ENABLED(CONFIG_SND_PCM_OSS) +static LIST_HEAD(snd_pcm_notify_list); +#endif static int snd_pcm_free(struct snd_pcm *pcm); static int snd_pcm_dev_free(struct snd_device *device); @@ -884,16 +888,23 @@ static void snd_pcm_free_stream(struct snd_pcm_str * pstr) put_device(&pstr->dev); } +#if IS_ENABLED(CONFIG_SND_PCM_OSS) +#define pcm_call_notify(pcm, call) \ + do { \ + struct snd_pcm_notify *_notify; \ + list_for_each_entry(_notify, &snd_pcm_notify_list, list) \ + _notify->call(pcm); \ + } while (0) +#else +#define pcm_call_notify(pcm, call) do {} while (0) +#endif + static int snd_pcm_free(struct snd_pcm *pcm) { - struct snd_pcm_notify *notify; - if (!pcm) return 0; - if (!pcm->internal) { - list_for_each_entry(notify, &snd_pcm_notify_list, list) - notify->n_unregister(pcm); - } + if (!pcm->internal) + pcm_call_notify(pcm, n_unregister); if (pcm->private_free) pcm->private_free(pcm); snd_pcm_lib_preallocate_free_for_all(pcm); @@ -1056,7 +1067,7 @@ static struct attribute *pcm_dev_attrs[] = { NULL }; -static struct attribute_group pcm_dev_attr_group = { +static const struct attribute_group pcm_dev_attr_group = { .attrs = pcm_dev_attrs, }; @@ -1069,7 +1080,6 @@ static int snd_pcm_dev_register(struct snd_device *device) { int cidx, err; struct snd_pcm_substream *substream; - struct snd_pcm_notify *notify; struct snd_pcm *pcm; if (snd_BUG_ON(!device || !device->device_data)) @@ -1107,8 +1117,7 @@ static int snd_pcm_dev_register(struct snd_device *device) snd_pcm_timer_init(substream); } - list_for_each_entry(notify, &snd_pcm_notify_list, list) - notify->n_register(pcm); + pcm_call_notify(pcm, n_register); unlock: mutex_unlock(®ister_mutex); @@ -1118,7 +1127,6 @@ static int snd_pcm_dev_register(struct snd_device *device) static int snd_pcm_dev_disconnect(struct snd_device *device) { struct snd_pcm *pcm = device->device_data; - struct snd_pcm_notify *notify; struct snd_pcm_substream *substream; int cidx; @@ -1138,8 +1146,7 @@ static int snd_pcm_dev_disconnect(struct snd_device *device) } } if (!pcm->internal) { - list_for_each_entry(notify, &snd_pcm_notify_list, list) - notify->n_disconnect(pcm); + pcm_call_notify(pcm, n_disconnect); } for (cidx = 0; cidx < 2; cidx++) { if (!pcm->internal) @@ -1151,6 +1158,7 @@ static int snd_pcm_dev_disconnect(struct snd_device *device) return 0; } +#if IS_ENABLED(CONFIG_SND_PCM_OSS) /** * snd_pcm_notify - Add/remove the notify list * @notify: PCM notify list @@ -1183,6 +1191,7 @@ int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree) return 0; } EXPORT_SYMBOL(snd_pcm_notify); +#endif /* CONFIG_SND_PCM_OSS */ #ifdef CONFIG_SND_PROC_FS /* diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c index 1f64ab0c2a95..10f537f4d735 100644 --- a/sound/core/pcm_compat.c +++ b/sound/core/pcm_compat.c @@ -27,17 +27,13 @@ static int snd_pcm_ioctl_delay_compat(struct snd_pcm_substream *substream, s32 __user *src) { snd_pcm_sframes_t delay; - mm_segment_t fs; - int err; - fs = snd_enter_user(); - err = snd_pcm_delay(substream, &delay); - snd_leave_user(fs); - if (err < 0) - return err; + delay = snd_pcm_delay(substream); + if (delay < 0) + return delay; if (put_user(delay, src)) return -EFAULT; - return err; + return 0; } static int snd_pcm_ioctl_rewind_compat(struct snd_pcm_substream *substream, @@ -680,6 +676,7 @@ static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned l case SNDRV_PCM_IOCTL_INFO: case SNDRV_PCM_IOCTL_TSTAMP: case SNDRV_PCM_IOCTL_TTSTAMP: + case SNDRV_PCM_IOCTL_USER_PVERSION: case SNDRV_PCM_IOCTL_HWSYNC: case SNDRV_PCM_IOCTL_PREPARE: case SNDRV_PCM_IOCTL_RESET: diff --git a/sound/core/pcm_drm_eld.c b/sound/core/pcm_drm_eld.c index e70379fb63d0..9881d087756f 100644 --- a/sound/core/pcm_drm_eld.c +++ b/sound/core/pcm_drm_eld.c @@ -29,13 +29,13 @@ static int eld_limit_rates(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule) { struct snd_interval *r = hw_param_interval(params, rule->var); - struct snd_interval *c; + const struct snd_interval *c; unsigned int rate_mask = 7, i; const u8 *sad, *eld = rule->private; sad = drm_eld_sad(eld); if (sad) { - c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); + c = hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_CHANNELS); for (i = drm_eld_sad_count(eld); i > 0; i--, sad += 3) { unsigned max_channels = sad_max_channels(sad); @@ -57,7 +57,7 @@ static int eld_limit_channels(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule) { struct snd_interval *c = hw_param_interval(params, rule->var); - struct snd_interval *r; + const struct snd_interval *r; struct snd_interval t = { .min = 1, .max = 2, .integer = 1, }; unsigned int i; const u8 *sad, *eld = rule->private; @@ -67,7 +67,7 @@ static int eld_limit_channels(struct snd_pcm_hw_params *params, unsigned int rate_mask = 0; /* Convert the rate interval to a mask */ - r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); + r = hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_RATE); for (i = 0; i < ARRAY_SIZE(eld_rates); i++) if (r->min <= eld_rates[i] && r->max >= eld_rates[i]) rate_mask |= BIT(i); diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 009e6c98754e..a93a4235a332 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -33,6 +33,8 @@ #include <sound/pcm_params.h> #include <sound/timer.h> +#include "pcm_local.h" + #ifdef CONFIG_SND_PCM_XRUN_DEBUG #define CREATE_TRACE_POINTS #include "pcm_trace.h" @@ -40,8 +42,12 @@ #define trace_hwptr(substream, pos, in_interrupt) #define trace_xrun(substream) #define trace_hw_ptr_error(substream, reason) +#define trace_applptr(substream, prev, curr) #endif +static int fill_silence_frames(struct snd_pcm_substream *substream, + snd_pcm_uframes_t off, snd_pcm_uframes_t frames); + /* * fill ring buffer with silence * runtime->silence_start: starting pointer to silence area @@ -55,18 +61,20 @@ void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_ufram { struct snd_pcm_runtime *runtime = substream->runtime; snd_pcm_uframes_t frames, ofs, transfer; + int err; if (runtime->silence_size < runtime->boundary) { snd_pcm_sframes_t noise_dist, n; - if (runtime->silence_start != runtime->control->appl_ptr) { - n = runtime->control->appl_ptr - runtime->silence_start; + snd_pcm_uframes_t appl_ptr = READ_ONCE(runtime->control->appl_ptr); + if (runtime->silence_start != appl_ptr) { + n = appl_ptr - runtime->silence_start; if (n < 0) n += runtime->boundary; if ((snd_pcm_uframes_t)n < runtime->silence_filled) runtime->silence_filled -= n; else runtime->silence_filled = 0; - runtime->silence_start = runtime->control->appl_ptr; + runtime->silence_start = appl_ptr; } if (runtime->silence_filled >= runtime->buffer_size) return; @@ -107,33 +115,8 @@ void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_ufram ofs = runtime->silence_start % runtime->buffer_size; while (frames > 0) { transfer = ofs + frames > runtime->buffer_size ? runtime->buffer_size - ofs : frames; - if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED || - runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) { - if (substream->ops->silence) { - int err; - err = substream->ops->silence(substream, -1, ofs, transfer); - snd_BUG_ON(err < 0); - } else { - char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, ofs); - snd_pcm_format_set_silence(runtime->format, hwbuf, transfer * runtime->channels); - } - } else { - unsigned int c; - unsigned int channels = runtime->channels; - if (substream->ops->silence) { - for (c = 0; c < channels; ++c) { - int err; - err = substream->ops->silence(substream, c, ofs, transfer); - snd_BUG_ON(err < 0); - } - } else { - size_t dma_csize = runtime->dma_bytes / channels; - for (c = 0; c < channels; ++c) { - char *hwbuf = runtime->dma_area + (c * dma_csize) + samples_to_bytes(runtime, ofs); - snd_pcm_format_set_silence(runtime->format, hwbuf, transfer); - } - } - } + err = fill_silence_frames(substream, ofs, transfer); + snd_BUG_ON(err < 0); runtime->silence_filled += transfer; frames -= transfer; ofs = 0; @@ -508,7 +491,6 @@ void snd_pcm_set_ops(struct snd_pcm *pcm, int direction, for (substream = stream->substream; substream != NULL; substream = substream->next) substream->ops = ops; } - EXPORT_SYMBOL(snd_pcm_set_ops); /** @@ -526,7 +508,6 @@ void snd_pcm_set_sync(struct snd_pcm_substream *substream) runtime->sync.id32[2] = -1; runtime->sync.id32[3] = -1; } - EXPORT_SYMBOL(snd_pcm_set_sync); /* @@ -643,7 +624,6 @@ int snd_interval_refine(struct snd_interval *i, const struct snd_interval *v) } return changed; } - EXPORT_SYMBOL(snd_interval_refine); static int snd_interval_refine_first(struct snd_interval *i) @@ -906,7 +886,6 @@ int snd_interval_ratnum(struct snd_interval *i, } return err; } - EXPORT_SYMBOL(snd_interval_ratnum); /** @@ -1044,7 +1023,6 @@ int snd_interval_list(struct snd_interval *i, unsigned int count, } return snd_interval_refine(i, &list_range); } - EXPORT_SYMBOL(snd_interval_list); /** @@ -1183,7 +1161,6 @@ int snd_pcm_hw_rule_add(struct snd_pcm_runtime *runtime, unsigned int cond, va_end(args); return 0; } - EXPORT_SYMBOL(snd_pcm_hw_rule_add); /** @@ -1247,7 +1224,6 @@ int snd_pcm_hw_constraint_integer(struct snd_pcm_runtime *runtime, snd_pcm_hw_pa struct snd_pcm_hw_constraints *constrs = &runtime->hw_constraints; return snd_interval_setinteger(constrs_interval(constrs, var)); } - EXPORT_SYMBOL(snd_pcm_hw_constraint_integer); /** @@ -1273,7 +1249,6 @@ int snd_pcm_hw_constraint_minmax(struct snd_pcm_runtime *runtime, snd_pcm_hw_par t.integer = 0; return snd_interval_refine(constrs_interval(constrs, var), &t); } - EXPORT_SYMBOL(snd_pcm_hw_constraint_minmax); static int snd_pcm_hw_rule_list(struct snd_pcm_hw_params *params, @@ -1304,7 +1279,6 @@ int snd_pcm_hw_constraint_list(struct snd_pcm_runtime *runtime, snd_pcm_hw_rule_list, (void *)l, var, -1); } - EXPORT_SYMBOL(snd_pcm_hw_constraint_list); static int snd_pcm_hw_rule_ranges(struct snd_pcm_hw_params *params, @@ -1371,7 +1345,6 @@ int snd_pcm_hw_constraint_ratnums(struct snd_pcm_runtime *runtime, snd_pcm_hw_rule_ratnums, (void *)r, var, -1); } - EXPORT_SYMBOL(snd_pcm_hw_constraint_ratnums); static int snd_pcm_hw_rule_ratdens(struct snd_pcm_hw_params *params, @@ -1406,7 +1379,6 @@ int snd_pcm_hw_constraint_ratdens(struct snd_pcm_runtime *runtime, snd_pcm_hw_rule_ratdens, (void *)r, var, -1); } - EXPORT_SYMBOL(snd_pcm_hw_constraint_ratdens); static int snd_pcm_hw_rule_msbits(struct snd_pcm_hw_params *params, @@ -1415,7 +1387,8 @@ static int snd_pcm_hw_rule_msbits(struct snd_pcm_hw_params *params, unsigned int l = (unsigned long) rule->private; int width = l & 0xffff; unsigned int msbits = l >> 16; - struct snd_interval *i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS); + const struct snd_interval *i = + hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS); if (!snd_interval_single(i)) return 0; @@ -1452,7 +1425,6 @@ int snd_pcm_hw_constraint_msbits(struct snd_pcm_runtime *runtime, (void*) l, SNDRV_PCM_HW_PARAM_SAMPLE_BITS, -1); } - EXPORT_SYMBOL(snd_pcm_hw_constraint_msbits); static int snd_pcm_hw_rule_step(struct snd_pcm_hw_params *params, @@ -1480,7 +1452,6 @@ int snd_pcm_hw_constraint_step(struct snd_pcm_runtime *runtime, snd_pcm_hw_rule_step, (void *) step, var, -1); } - EXPORT_SYMBOL(snd_pcm_hw_constraint_step); static int snd_pcm_hw_rule_pow2(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule) @@ -1511,7 +1482,6 @@ int snd_pcm_hw_constraint_pow2(struct snd_pcm_runtime *runtime, snd_pcm_hw_rule_pow2, NULL, var, -1); } - EXPORT_SYMBOL(snd_pcm_hw_constraint_pow2); static int snd_pcm_hw_rule_noresample_func(struct snd_pcm_hw_params *params, @@ -1570,7 +1540,6 @@ void _snd_pcm_hw_params_any(struct snd_pcm_hw_params *params) _snd_pcm_hw_param_any(params, k); params->info = ~0U; } - EXPORT_SYMBOL(_snd_pcm_hw_params_any); /** @@ -1603,7 +1572,6 @@ int snd_pcm_hw_param_value(const struct snd_pcm_hw_params *params, } return -EINVAL; } - EXPORT_SYMBOL(snd_pcm_hw_param_value); void _snd_pcm_hw_param_setempty(struct snd_pcm_hw_params *params, @@ -1621,7 +1589,6 @@ void _snd_pcm_hw_param_setempty(struct snd_pcm_hw_params *params, snd_BUG(); } } - EXPORT_SYMBOL(_snd_pcm_hw_param_setempty); static int _snd_pcm_hw_param_first(struct snd_pcm_hw_params *params, @@ -1668,7 +1635,6 @@ int snd_pcm_hw_param_first(struct snd_pcm_substream *pcm, } return snd_pcm_hw_param_value(params, var, dir); } - EXPORT_SYMBOL(snd_pcm_hw_param_first); static int _snd_pcm_hw_param_last(struct snd_pcm_hw_params *params, @@ -1715,48 +1681,8 @@ int snd_pcm_hw_param_last(struct snd_pcm_substream *pcm, } return snd_pcm_hw_param_value(params, var, dir); } - EXPORT_SYMBOL(snd_pcm_hw_param_last); -/** - * snd_pcm_hw_param_choose - choose a configuration defined by @params - * @pcm: PCM instance - * @params: the hw_params instance - * - * Choose one configuration from configuration space defined by @params. - * The configuration chosen is that obtained fixing in this order: - * first access, first format, first subformat, min channels, - * min rate, min period time, max buffer size, min tick time - * - * Return: Zero if successful, or a negative error code on failure. - */ -int snd_pcm_hw_params_choose(struct snd_pcm_substream *pcm, - struct snd_pcm_hw_params *params) -{ - static int vars[] = { - SNDRV_PCM_HW_PARAM_ACCESS, - SNDRV_PCM_HW_PARAM_FORMAT, - SNDRV_PCM_HW_PARAM_SUBFORMAT, - SNDRV_PCM_HW_PARAM_CHANNELS, - SNDRV_PCM_HW_PARAM_RATE, - SNDRV_PCM_HW_PARAM_PERIOD_TIME, - SNDRV_PCM_HW_PARAM_BUFFER_SIZE, - SNDRV_PCM_HW_PARAM_TICK_TIME, - -1 - }; - int err, *v; - - for (v = vars; *v != -1; v++) { - if (*v != SNDRV_PCM_HW_PARAM_BUFFER_SIZE) - err = snd_pcm_hw_param_first(pcm, params, *v, NULL); - else - err = snd_pcm_hw_param_last(pcm, params, *v, NULL); - if (snd_BUG_ON(err < 0)) - return err; - } - return 0; -} - static int snd_pcm_lib_ioctl_reset(struct snd_pcm_substream *substream, void *arg) { @@ -1843,8 +1769,6 @@ int snd_pcm_lib_ioctl(struct snd_pcm_substream *substream, unsigned int cmd, void *arg) { switch (cmd) { - case SNDRV_PCM_IOCTL1_INFO: - return 0; case SNDRV_PCM_IOCTL1_RESET: return snd_pcm_lib_ioctl_reset(substream, arg); case SNDRV_PCM_IOCTL1_CHANNEL_INFO: @@ -1854,7 +1778,6 @@ int snd_pcm_lib_ioctl(struct snd_pcm_substream *substream, } return -ENXIO; } - EXPORT_SYMBOL(snd_pcm_lib_ioctl); /** @@ -1890,7 +1813,6 @@ void snd_pcm_period_elapsed(struct snd_pcm_substream *substream) kill_fasync(&runtime->fasync, SIGIO, POLL_IN); snd_pcm_stream_unlock_irqrestore(substream, flags); } - EXPORT_SYMBOL(snd_pcm_period_elapsed); /* @@ -1904,7 +1826,7 @@ static int wait_for_avail(struct snd_pcm_substream *substream, { struct snd_pcm_runtime *runtime = substream->runtime; int is_playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; - wait_queue_t wait; + wait_queue_entry_t wait; int err = 0; snd_pcm_uframes_t avail = 0; long wait_time, tout; @@ -1985,129 +1907,147 @@ static int wait_for_avail(struct snd_pcm_substream *substream, return err; } -static int snd_pcm_lib_write_transfer(struct snd_pcm_substream *substream, - unsigned int hwoff, - unsigned long data, unsigned int off, - snd_pcm_uframes_t frames) +typedef int (*pcm_transfer_f)(struct snd_pcm_substream *substream, + int channel, unsigned long hwoff, + void *buf, unsigned long bytes); + +typedef int (*pcm_copy_f)(struct snd_pcm_substream *, snd_pcm_uframes_t, void *, + snd_pcm_uframes_t, snd_pcm_uframes_t, pcm_transfer_f); + +/* calculate the target DMA-buffer position to be written/read */ +static void *get_dma_ptr(struct snd_pcm_runtime *runtime, + int channel, unsigned long hwoff) { - struct snd_pcm_runtime *runtime = substream->runtime; - int err; - char __user *buf = (char __user *) data + frames_to_bytes(runtime, off); - if (substream->ops->copy) { - if ((err = substream->ops->copy(substream, -1, hwoff, buf, frames)) < 0) - return err; - } else { - char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, hwoff); - if (copy_from_user(hwbuf, buf, frames_to_bytes(runtime, frames))) - return -EFAULT; - } + return runtime->dma_area + hwoff + + channel * (runtime->dma_bytes / runtime->channels); +} + +/* default copy_user ops for write; used for both interleaved and non- modes */ +static int default_write_copy(struct snd_pcm_substream *substream, + int channel, unsigned long hwoff, + void *buf, unsigned long bytes) +{ + if (copy_from_user(get_dma_ptr(substream->runtime, channel, hwoff), + (void __user *)buf, bytes)) + return -EFAULT; return 0; } - -typedef int (*transfer_f)(struct snd_pcm_substream *substream, unsigned int hwoff, - unsigned long data, unsigned int off, - snd_pcm_uframes_t size); -static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream, - unsigned long data, - snd_pcm_uframes_t size, - int nonblock, - transfer_f transfer) +/* default copy_kernel ops for write */ +static int default_write_copy_kernel(struct snd_pcm_substream *substream, + int channel, unsigned long hwoff, + void *buf, unsigned long bytes) +{ + memcpy(get_dma_ptr(substream->runtime, channel, hwoff), buf, bytes); + return 0; +} + +/* fill silence instead of copy data; called as a transfer helper + * from __snd_pcm_lib_write() or directly from noninterleaved_copy() when + * a NULL buffer is passed + */ +static int fill_silence(struct snd_pcm_substream *substream, int channel, + unsigned long hwoff, void *buf, unsigned long bytes) { struct snd_pcm_runtime *runtime = substream->runtime; - snd_pcm_uframes_t xfer = 0; - snd_pcm_uframes_t offset = 0; - snd_pcm_uframes_t avail; - int err = 0; - if (size == 0) + if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK) return 0; + if (substream->ops->fill_silence) + return substream->ops->fill_silence(substream, channel, + hwoff, bytes); - snd_pcm_stream_lock_irq(substream); - switch (runtime->status->state) { - case SNDRV_PCM_STATE_PREPARED: - case SNDRV_PCM_STATE_RUNNING: - case SNDRV_PCM_STATE_PAUSED: - break; - case SNDRV_PCM_STATE_XRUN: - err = -EPIPE; - goto _end_unlock; - case SNDRV_PCM_STATE_SUSPENDED: - err = -ESTRPIPE; - goto _end_unlock; - default: - err = -EBADFD; - goto _end_unlock; - } + snd_pcm_format_set_silence(runtime->format, + get_dma_ptr(runtime, channel, hwoff), + bytes_to_samples(runtime, bytes)); + return 0; +} - runtime->twake = runtime->control->avail_min ? : 1; - if (runtime->status->state == SNDRV_PCM_STATE_RUNNING) - snd_pcm_update_hw_ptr(substream); - avail = snd_pcm_playback_avail(runtime); - while (size > 0) { - snd_pcm_uframes_t frames, appl_ptr, appl_ofs; - snd_pcm_uframes_t cont; - if (!avail) { - if (nonblock) { - err = -EAGAIN; - goto _end_unlock; - } - runtime->twake = min_t(snd_pcm_uframes_t, size, - runtime->control->avail_min ? : 1); - err = wait_for_avail(substream, &avail); - if (err < 0) - goto _end_unlock; - } - frames = size > avail ? avail : size; - cont = runtime->buffer_size - runtime->control->appl_ptr % runtime->buffer_size; - if (frames > cont) - frames = cont; - if (snd_BUG_ON(!frames)) { - runtime->twake = 0; - snd_pcm_stream_unlock_irq(substream); - return -EINVAL; - } - appl_ptr = runtime->control->appl_ptr; - appl_ofs = appl_ptr % runtime->buffer_size; - snd_pcm_stream_unlock_irq(substream); - err = transfer(substream, appl_ofs, data, offset, frames); - snd_pcm_stream_lock_irq(substream); - if (err < 0) - goto _end_unlock; - switch (runtime->status->state) { - case SNDRV_PCM_STATE_XRUN: - err = -EPIPE; - goto _end_unlock; - case SNDRV_PCM_STATE_SUSPENDED: - err = -ESTRPIPE; - goto _end_unlock; - default: - break; - } - appl_ptr += frames; - if (appl_ptr >= runtime->boundary) - appl_ptr -= runtime->boundary; - runtime->control->appl_ptr = appl_ptr; - if (substream->ops->ack) - substream->ops->ack(substream); +/* default copy_user ops for read; used for both interleaved and non- modes */ +static int default_read_copy(struct snd_pcm_substream *substream, + int channel, unsigned long hwoff, + void *buf, unsigned long bytes) +{ + if (copy_to_user((void __user *)buf, + get_dma_ptr(substream->runtime, channel, hwoff), + bytes)) + return -EFAULT; + return 0; +} - offset += frames; - size -= frames; - xfer += frames; - avail -= frames; - if (runtime->status->state == SNDRV_PCM_STATE_PREPARED && - snd_pcm_playback_hw_avail(runtime) >= (snd_pcm_sframes_t)runtime->start_threshold) { - err = snd_pcm_start(substream); - if (err < 0) - goto _end_unlock; - } +/* default copy_kernel ops for read */ +static int default_read_copy_kernel(struct snd_pcm_substream *substream, + int channel, unsigned long hwoff, + void *buf, unsigned long bytes) +{ + memcpy(buf, get_dma_ptr(substream->runtime, channel, hwoff), bytes); + return 0; +} + +/* call transfer function with the converted pointers and sizes; + * for interleaved mode, it's one shot for all samples + */ +static int interleaved_copy(struct snd_pcm_substream *substream, + snd_pcm_uframes_t hwoff, void *data, + snd_pcm_uframes_t off, + snd_pcm_uframes_t frames, + pcm_transfer_f transfer) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + + /* convert to bytes */ + hwoff = frames_to_bytes(runtime, hwoff); + off = frames_to_bytes(runtime, off); + frames = frames_to_bytes(runtime, frames); + return transfer(substream, 0, hwoff, data + off, frames); +} + +/* call transfer function with the converted pointers and sizes for each + * non-interleaved channel; when buffer is NULL, silencing instead of copying + */ +static int noninterleaved_copy(struct snd_pcm_substream *substream, + snd_pcm_uframes_t hwoff, void *data, + snd_pcm_uframes_t off, + snd_pcm_uframes_t frames, + pcm_transfer_f transfer) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + int channels = runtime->channels; + void **bufs = data; + int c, err; + + /* convert to bytes; note that it's not frames_to_bytes() here. + * in non-interleaved mode, we copy for each channel, thus + * each copy is n_samples bytes x channels = whole frames. + */ + off = samples_to_bytes(runtime, off); + frames = samples_to_bytes(runtime, frames); + hwoff = samples_to_bytes(runtime, hwoff); + for (c = 0; c < channels; ++c, ++bufs) { + if (!data || !*bufs) + err = fill_silence(substream, c, hwoff, NULL, frames); + else + err = transfer(substream, c, hwoff, *bufs + off, + frames); + if (err < 0) + return err; } - _end_unlock: - runtime->twake = 0; - if (xfer > 0 && err >= 0) - snd_pcm_update_state(substream, runtime); - snd_pcm_stream_unlock_irq(substream); - return xfer > 0 ? (snd_pcm_sframes_t)xfer : err; + return 0; +} + +/* fill silence on the given buffer position; + * called from snd_pcm_playback_silence() + */ +static int fill_silence_frames(struct snd_pcm_substream *substream, + snd_pcm_uframes_t off, snd_pcm_uframes_t frames) +{ + if (substream->runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED || + substream->runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) + return interleaved_copy(substream, off, NULL, 0, frames, + fill_silence); + else + return noninterleaved_copy(substream, off, NULL, 0, frames, + fill_silence); } /* sanity-check for read/write methods */ @@ -2117,164 +2057,137 @@ static int pcm_sanity_check(struct snd_pcm_substream *substream) if (PCM_RUNTIME_CHECK(substream)) return -ENXIO; runtime = substream->runtime; - if (snd_BUG_ON(!substream->ops->copy && !runtime->dma_area)) + if (snd_BUG_ON(!substream->ops->copy_user && !runtime->dma_area)) return -EINVAL; if (runtime->status->state == SNDRV_PCM_STATE_OPEN) return -EBADFD; return 0; } -snd_pcm_sframes_t snd_pcm_lib_write(struct snd_pcm_substream *substream, const void __user *buf, snd_pcm_uframes_t size) +static int pcm_accessible_state(struct snd_pcm_runtime *runtime) { - struct snd_pcm_runtime *runtime; - int nonblock; - int err; - - err = pcm_sanity_check(substream); - if (err < 0) - return err; - runtime = substream->runtime; - nonblock = !!(substream->f_flags & O_NONBLOCK); - - if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED && - runtime->channels > 1) - return -EINVAL; - return snd_pcm_lib_write1(substream, (unsigned long)buf, size, nonblock, - snd_pcm_lib_write_transfer); + switch (runtime->status->state) { + case SNDRV_PCM_STATE_PREPARED: + case SNDRV_PCM_STATE_RUNNING: + case SNDRV_PCM_STATE_PAUSED: + return 0; + case SNDRV_PCM_STATE_XRUN: + return -EPIPE; + case SNDRV_PCM_STATE_SUSPENDED: + return -ESTRPIPE; + default: + return -EBADFD; + } } -EXPORT_SYMBOL(snd_pcm_lib_write); - -static int snd_pcm_lib_writev_transfer(struct snd_pcm_substream *substream, - unsigned int hwoff, - unsigned long data, unsigned int off, - snd_pcm_uframes_t frames) +/* update to the given appl_ptr and call ack callback if needed; + * when an error is returned, take back to the original value + */ +int pcm_lib_apply_appl_ptr(struct snd_pcm_substream *substream, + snd_pcm_uframes_t appl_ptr) { struct snd_pcm_runtime *runtime = substream->runtime; - int err; - void __user **bufs = (void __user **)data; - int channels = runtime->channels; - int c; - if (substream->ops->copy) { - if (snd_BUG_ON(!substream->ops->silence)) - return -EINVAL; - for (c = 0; c < channels; ++c, ++bufs) { - if (*bufs == NULL) { - if ((err = substream->ops->silence(substream, c, hwoff, frames)) < 0) - return err; - } else { - char __user *buf = *bufs + samples_to_bytes(runtime, off); - if ((err = substream->ops->copy(substream, c, hwoff, buf, frames)) < 0) - return err; - } - } - } else { - /* default transfer behaviour */ - size_t dma_csize = runtime->dma_bytes / channels; - for (c = 0; c < channels; ++c, ++bufs) { - char *hwbuf = runtime->dma_area + (c * dma_csize) + samples_to_bytes(runtime, hwoff); - if (*bufs == NULL) { - snd_pcm_format_set_silence(runtime->format, hwbuf, frames); - } else { - char __user *buf = *bufs + samples_to_bytes(runtime, off); - if (copy_from_user(hwbuf, buf, samples_to_bytes(runtime, frames))) - return -EFAULT; - } + snd_pcm_uframes_t old_appl_ptr = runtime->control->appl_ptr; + int ret; + + if (old_appl_ptr == appl_ptr) + return 0; + + runtime->control->appl_ptr = appl_ptr; + if (substream->ops->ack) { + ret = substream->ops->ack(substream); + if (ret < 0) { + runtime->control->appl_ptr = old_appl_ptr; + return ret; } } + + trace_applptr(substream, old_appl_ptr, appl_ptr); + return 0; } - -snd_pcm_sframes_t snd_pcm_lib_writev(struct snd_pcm_substream *substream, - void __user **bufs, - snd_pcm_uframes_t frames) + +/* the common loop for read/write data */ +snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream, + void *data, bool interleaved, + snd_pcm_uframes_t size, bool in_kernel) { - struct snd_pcm_runtime *runtime; - int nonblock; + struct snd_pcm_runtime *runtime = substream->runtime; + snd_pcm_uframes_t xfer = 0; + snd_pcm_uframes_t offset = 0; + snd_pcm_uframes_t avail; + pcm_copy_f writer; + pcm_transfer_f transfer; + bool nonblock; + bool is_playback; int err; err = pcm_sanity_check(substream); if (err < 0) return err; - runtime = substream->runtime; - nonblock = !!(substream->f_flags & O_NONBLOCK); - - if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) - return -EINVAL; - return snd_pcm_lib_write1(substream, (unsigned long)bufs, frames, - nonblock, snd_pcm_lib_writev_transfer); -} - -EXPORT_SYMBOL(snd_pcm_lib_writev); -static int snd_pcm_lib_read_transfer(struct snd_pcm_substream *substream, - unsigned int hwoff, - unsigned long data, unsigned int off, - snd_pcm_uframes_t frames) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - int err; - char __user *buf = (char __user *) data + frames_to_bytes(runtime, off); - if (substream->ops->copy) { - if ((err = substream->ops->copy(substream, -1, hwoff, buf, frames)) < 0) - return err; + is_playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; + if (interleaved) { + if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED && + runtime->channels > 1) + return -EINVAL; + writer = interleaved_copy; } else { - char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, hwoff); - if (copy_to_user(buf, hwbuf, frames_to_bytes(runtime, frames))) - return -EFAULT; + if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) + return -EINVAL; + writer = noninterleaved_copy; } - return 0; -} -static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream, - unsigned long data, - snd_pcm_uframes_t size, - int nonblock, - transfer_f transfer) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - snd_pcm_uframes_t xfer = 0; - snd_pcm_uframes_t offset = 0; - snd_pcm_uframes_t avail; - int err = 0; + if (!data) { + if (is_playback) + transfer = fill_silence; + else + return -EINVAL; + } else if (in_kernel) { + if (substream->ops->copy_kernel) + transfer = substream->ops->copy_kernel; + else + transfer = is_playback ? + default_write_copy_kernel : default_read_copy_kernel; + } else { + if (substream->ops->copy_user) + transfer = (pcm_transfer_f)substream->ops->copy_user; + else + transfer = is_playback ? + default_write_copy : default_read_copy; + } if (size == 0) return 0; + nonblock = !!(substream->f_flags & O_NONBLOCK); + snd_pcm_stream_lock_irq(substream); - switch (runtime->status->state) { - case SNDRV_PCM_STATE_PREPARED: - if (size >= runtime->start_threshold) { - err = snd_pcm_start(substream); - if (err < 0) - goto _end_unlock; - } - break; - case SNDRV_PCM_STATE_DRAINING: - case SNDRV_PCM_STATE_RUNNING: - case SNDRV_PCM_STATE_PAUSED: - break; - case SNDRV_PCM_STATE_XRUN: - err = -EPIPE; - goto _end_unlock; - case SNDRV_PCM_STATE_SUSPENDED: - err = -ESTRPIPE; - goto _end_unlock; - default: - err = -EBADFD; + err = pcm_accessible_state(runtime); + if (err < 0) goto _end_unlock; + + if (!is_playback && + runtime->status->state == SNDRV_PCM_STATE_PREPARED && + size >= runtime->start_threshold) { + err = snd_pcm_start(substream); + if (err < 0) + goto _end_unlock; } runtime->twake = runtime->control->avail_min ? : 1; if (runtime->status->state == SNDRV_PCM_STATE_RUNNING) snd_pcm_update_hw_ptr(substream); - avail = snd_pcm_capture_avail(runtime); + if (is_playback) + avail = snd_pcm_playback_avail(runtime); + else + avail = snd_pcm_capture_avail(runtime); while (size > 0) { snd_pcm_uframes_t frames, appl_ptr, appl_ofs; snd_pcm_uframes_t cont; if (!avail) { - if (runtime->status->state == - SNDRV_PCM_STATE_DRAINING) { + if (!is_playback && + runtime->status->state == SNDRV_PCM_STATE_DRAINING) { snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP); goto _end_unlock; } @@ -2291,7 +2204,9 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream, continue; /* draining */ } frames = size > avail ? avail : size; - cont = runtime->buffer_size - runtime->control->appl_ptr % runtime->buffer_size; + appl_ptr = READ_ONCE(runtime->control->appl_ptr); + appl_ofs = appl_ptr % runtime->buffer_size; + cont = runtime->buffer_size - appl_ofs; if (frames > cont) frames = cont; if (snd_BUG_ON(!frames)) { @@ -2299,34 +2214,33 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream, snd_pcm_stream_unlock_irq(substream); return -EINVAL; } - appl_ptr = runtime->control->appl_ptr; - appl_ofs = appl_ptr % runtime->buffer_size; snd_pcm_stream_unlock_irq(substream); - err = transfer(substream, appl_ofs, data, offset, frames); + err = writer(substream, appl_ofs, data, offset, frames, + transfer); snd_pcm_stream_lock_irq(substream); if (err < 0) goto _end_unlock; - switch (runtime->status->state) { - case SNDRV_PCM_STATE_XRUN: - err = -EPIPE; - goto _end_unlock; - case SNDRV_PCM_STATE_SUSPENDED: - err = -ESTRPIPE; + err = pcm_accessible_state(runtime); + if (err < 0) goto _end_unlock; - default: - break; - } appl_ptr += frames; if (appl_ptr >= runtime->boundary) appl_ptr -= runtime->boundary; - runtime->control->appl_ptr = appl_ptr; - if (substream->ops->ack) - substream->ops->ack(substream); + err = pcm_lib_apply_appl_ptr(substream, appl_ptr); + if (err < 0) + goto _end_unlock; offset += frames; size -= frames; xfer += frames; avail -= frames; + if (is_playback && + runtime->status->state == SNDRV_PCM_STATE_PREPARED && + snd_pcm_playback_hw_avail(runtime) >= (snd_pcm_sframes_t)runtime->start_threshold) { + err = snd_pcm_start(substream); + if (err < 0) + goto _end_unlock; + } } _end_unlock: runtime->twake = 0; @@ -2335,83 +2249,7 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream, snd_pcm_stream_unlock_irq(substream); return xfer > 0 ? (snd_pcm_sframes_t)xfer : err; } - -snd_pcm_sframes_t snd_pcm_lib_read(struct snd_pcm_substream *substream, void __user *buf, snd_pcm_uframes_t size) -{ - struct snd_pcm_runtime *runtime; - int nonblock; - int err; - - err = pcm_sanity_check(substream); - if (err < 0) - return err; - runtime = substream->runtime; - nonblock = !!(substream->f_flags & O_NONBLOCK); - if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED) - return -EINVAL; - return snd_pcm_lib_read1(substream, (unsigned long)buf, size, nonblock, snd_pcm_lib_read_transfer); -} - -EXPORT_SYMBOL(snd_pcm_lib_read); - -static int snd_pcm_lib_readv_transfer(struct snd_pcm_substream *substream, - unsigned int hwoff, - unsigned long data, unsigned int off, - snd_pcm_uframes_t frames) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - int err; - void __user **bufs = (void __user **)data; - int channels = runtime->channels; - int c; - if (substream->ops->copy) { - for (c = 0; c < channels; ++c, ++bufs) { - char __user *buf; - if (*bufs == NULL) - continue; - buf = *bufs + samples_to_bytes(runtime, off); - if ((err = substream->ops->copy(substream, c, hwoff, buf, frames)) < 0) - return err; - } - } else { - snd_pcm_uframes_t dma_csize = runtime->dma_bytes / channels; - for (c = 0; c < channels; ++c, ++bufs) { - char *hwbuf; - char __user *buf; - if (*bufs == NULL) - continue; - - hwbuf = runtime->dma_area + (c * dma_csize) + samples_to_bytes(runtime, hwoff); - buf = *bufs + samples_to_bytes(runtime, off); - if (copy_to_user(buf, hwbuf, samples_to_bytes(runtime, frames))) - return -EFAULT; - } - } - return 0; -} - -snd_pcm_sframes_t snd_pcm_lib_readv(struct snd_pcm_substream *substream, - void __user **bufs, - snd_pcm_uframes_t frames) -{ - struct snd_pcm_runtime *runtime; - int nonblock; - int err; - - err = pcm_sanity_check(substream); - if (err < 0) - return err; - runtime = substream->runtime; - if (runtime->status->state == SNDRV_PCM_STATE_OPEN) - return -EBADFD; - - nonblock = !!(substream->f_flags & O_NONBLOCK); - if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) - return -EINVAL; - return snd_pcm_lib_read1(substream, (unsigned long)bufs, frames, nonblock, snd_pcm_lib_readv_transfer); -} - -EXPORT_SYMBOL(snd_pcm_lib_readv); +EXPORT_SYMBOL(__snd_pcm_lib_xfer); /* * standard channel mapping helpers diff --git a/sound/core/pcm_local.h b/sound/core/pcm_local.h new file mode 100644 index 000000000000..16f254732b2a --- /dev/null +++ b/sound/core/pcm_local.h @@ -0,0 +1,50 @@ +/* + * pcm_local.h - a local header file for snd-pcm module. + * + * Copyright (c) Takashi Sakamoto <o-takashi@sakamocchi.jp> + * + * Licensed under the terms of the GNU General Public License, version 2. + */ + +#ifndef __SOUND_CORE_PCM_LOCAL_H +#define __SOUND_CORE_PCM_LOCAL_H + +extern const struct snd_pcm_hw_constraint_list snd_pcm_known_rates; + +void snd_interval_mul(const struct snd_interval *a, + const struct snd_interval *b, struct snd_interval *c); +void snd_interval_div(const struct snd_interval *a, + const struct snd_interval *b, struct snd_interval *c); +void snd_interval_muldivk(const struct snd_interval *a, + const struct snd_interval *b, + unsigned int k, struct snd_interval *c); +void snd_interval_mulkdiv(const struct snd_interval *a, unsigned int k, + const struct snd_interval *b, struct snd_interval *c); + +int snd_pcm_hw_constraints_init(struct snd_pcm_substream *substream); +int snd_pcm_hw_constraints_complete(struct snd_pcm_substream *substream); + +int snd_pcm_hw_constraint_mask(struct snd_pcm_runtime *runtime, + snd_pcm_hw_param_t var, u_int32_t mask); + +int pcm_lib_apply_appl_ptr(struct snd_pcm_substream *substream, + snd_pcm_uframes_t appl_ptr); +int snd_pcm_update_state(struct snd_pcm_substream *substream, + struct snd_pcm_runtime *runtime); +int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream); + +void snd_pcm_playback_silence(struct snd_pcm_substream *substream, + snd_pcm_uframes_t new_hw_ptr); + +#ifdef CONFIG_SND_PCM_TIMER +void snd_pcm_timer_resolution_change(struct snd_pcm_substream *substream); +void snd_pcm_timer_init(struct snd_pcm_substream *substream); +void snd_pcm_timer_done(struct snd_pcm_substream *substream); +#else +static inline void +snd_pcm_timer_resolution_change(struct snd_pcm_substream *substream) {} +static inline void snd_pcm_timer_init(struct snd_pcm_substream *substream) {} +static inline void snd_pcm_timer_done(struct snd_pcm_substream *substream) {} +#endif + +#endif /* __SOUND_CORE_PCM_LOCAL_H */ diff --git a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c index b45f6aa32264..ae33e456708c 100644 --- a/sound/core/pcm_memory.c +++ b/sound/core/pcm_memory.c @@ -120,7 +120,6 @@ int snd_pcm_lib_preallocate_free_for_all(struct snd_pcm *pcm) snd_pcm_lib_preallocate_free(substream); return 0; } - EXPORT_SYMBOL(snd_pcm_lib_preallocate_free_for_all); #ifdef CONFIG_SND_VERBOSE_PROCFS @@ -263,7 +262,6 @@ int snd_pcm_lib_preallocate_pages(struct snd_pcm_substream *substream, substream->dma_buffer.dev.dev = data; return snd_pcm_lib_preallocate_pages1(substream, size, max); } - EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages); /** @@ -292,7 +290,6 @@ int snd_pcm_lib_preallocate_pages_for_all(struct snd_pcm *pcm, return err; return 0; } - EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages_for_all); #ifdef CONFIG_SND_DMA_SGBUF @@ -314,7 +311,6 @@ struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream, unsigne return NULL; return sgbuf->page_table[idx]; } - EXPORT_SYMBOL(snd_pcm_sgbuf_ops_page); #endif /* CONFIG_SND_DMA_SGBUF */ @@ -370,7 +366,6 @@ int snd_pcm_lib_malloc_pages(struct snd_pcm_substream *substream, size_t size) runtime->dma_bytes = size; return 1; /* area was changed */ } - EXPORT_SYMBOL(snd_pcm_lib_malloc_pages); /** @@ -398,7 +393,6 @@ int snd_pcm_lib_free_pages(struct snd_pcm_substream *substream) snd_pcm_set_runtime_buffer(substream, NULL); return 0; } - EXPORT_SYMBOL(snd_pcm_lib_free_pages); int _snd_pcm_lib_alloc_vmalloc_buffer(struct snd_pcm_substream *substream, diff --git a/sound/core/pcm_misc.c b/sound/core/pcm_misc.c index 53dc37357bca..9be81025372f 100644 --- a/sound/core/pcm_misc.c +++ b/sound/core/pcm_misc.c @@ -23,6 +23,9 @@ #include <linux/export.h> #include <sound/core.h> #include <sound/pcm.h> + +#include "pcm_local.h" + #define SND_PCM_FORMAT_UNKNOWN (-1) /* NOTE: "signed" prefix must be given below since the default char is @@ -245,7 +248,6 @@ int snd_pcm_format_signed(snd_pcm_format_t format) return -EINVAL; return val; } - EXPORT_SYMBOL(snd_pcm_format_signed); /** @@ -264,7 +266,6 @@ int snd_pcm_format_unsigned(snd_pcm_format_t format) return val; return !val; } - EXPORT_SYMBOL(snd_pcm_format_unsigned); /** @@ -277,7 +278,6 @@ int snd_pcm_format_linear(snd_pcm_format_t format) { return snd_pcm_format_signed(format) >= 0; } - EXPORT_SYMBOL(snd_pcm_format_linear); /** @@ -296,7 +296,6 @@ int snd_pcm_format_little_endian(snd_pcm_format_t format) return -EINVAL; return val; } - EXPORT_SYMBOL(snd_pcm_format_little_endian); /** @@ -315,7 +314,6 @@ int snd_pcm_format_big_endian(snd_pcm_format_t format) return val; return !val; } - EXPORT_SYMBOL(snd_pcm_format_big_endian); /** @@ -334,7 +332,6 @@ int snd_pcm_format_width(snd_pcm_format_t format) return -EINVAL; return val; } - EXPORT_SYMBOL(snd_pcm_format_width); /** @@ -353,7 +350,6 @@ int snd_pcm_format_physical_width(snd_pcm_format_t format) return -EINVAL; return val; } - EXPORT_SYMBOL(snd_pcm_format_physical_width); /** @@ -371,7 +367,6 @@ ssize_t snd_pcm_format_size(snd_pcm_format_t format, size_t samples) return -EINVAL; return samples * phys_width / 8; } - EXPORT_SYMBOL(snd_pcm_format_size); /** @@ -388,7 +383,6 @@ const unsigned char *snd_pcm_format_silence_64(snd_pcm_format_t format) return NULL; return pcm_formats[(INT)format].silence; } - EXPORT_SYMBOL(snd_pcm_format_silence_64); /** @@ -459,7 +453,6 @@ int snd_pcm_format_set_silence(snd_pcm_format_t format, void *data, unsigned int #endif return 0; } - EXPORT_SYMBOL(snd_pcm_format_set_silence); /** @@ -488,7 +481,6 @@ int snd_pcm_limit_hw_rates(struct snd_pcm_runtime *runtime) } return 0; } - EXPORT_SYMBOL(snd_pcm_limit_hw_rates); /** diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 13dec5ec93f2..22995cb3bd44 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -37,6 +37,18 @@ #include <sound/minors.h> #include <linux/uio.h> +#include "pcm_local.h" + +#ifdef CONFIG_SND_DEBUG +#define CREATE_TRACE_POINTS +#include "pcm_param_trace.h" +#else +#define trace_hw_mask_param_enabled() 0 +#define trace_hw_interval_param_enabled() 0 +#define trace_hw_mask_param(substream, type, index, prev, curr) +#define trace_hw_interval_param(substream, type, index, prev, curr) +#endif + /* * Compatibility */ @@ -181,20 +193,6 @@ void snd_pcm_stream_unlock_irqrestore(struct snd_pcm_substream *substream, } EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock_irqrestore); -static inline mm_segment_t snd_enter_user(void) -{ - mm_segment_t fs = get_fs(); - set_fs(get_ds()); - return fs; -} - -static inline void snd_leave_user(mm_segment_t fs) -{ - set_fs(fs); -} - - - int snd_pcm_info(struct snd_pcm_substream *substream, struct snd_pcm_info *info) { struct snd_pcm_runtime *runtime; @@ -214,11 +212,7 @@ int snd_pcm_info(struct snd_pcm_substream *substream, struct snd_pcm_info *info) info->subdevices_avail = pstr->substream_count - pstr->substream_opened; strlcpy(info->subname, substream->name, sizeof(info->subname)); runtime = substream->runtime; - /* AB: FIXME!!! This is definitely nonsense */ - if (runtime) { - info->sync = runtime->sync; - substream->ops->ioctl(substream, SNDRV_PCM_IOCTL1_INFO, info); - } + return 0; } @@ -244,10 +238,8 @@ static bool hw_support_mmap(struct snd_pcm_substream *substream) { if (!(substream->runtime->hw.info & SNDRV_PCM_INFO_MMAP)) return false; - /* check architectures that return -EINVAL from dma_mmap_coherent() */ - /* FIXME: this should be some global flag */ -#if defined(CONFIG_C6X) || defined(CONFIG_FRV) || defined(CONFIG_MN10300) ||\ - defined(CONFIG_PARISC) || defined(CONFIG_XTENSA) + /* architecture supports dma_mmap_coherent()? */ +#if defined(CONFIG_ARCH_NO_COHERENT_DMA_MMAP) || !defined(CONFIG_HAS_DMA) if (!substream->ops->mmap && substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV) return false; @@ -255,205 +247,268 @@ static bool hw_support_mmap(struct snd_pcm_substream *substream) return true; } -#undef RULES_DEBUG - -#ifdef RULES_DEBUG -#define HW_PARAM(v) [SNDRV_PCM_HW_PARAM_##v] = #v -static const char * const snd_pcm_hw_param_names[] = { - HW_PARAM(ACCESS), - HW_PARAM(FORMAT), - HW_PARAM(SUBFORMAT), - HW_PARAM(SAMPLE_BITS), - HW_PARAM(FRAME_BITS), - HW_PARAM(CHANNELS), - HW_PARAM(RATE), - HW_PARAM(PERIOD_TIME), - HW_PARAM(PERIOD_SIZE), - HW_PARAM(PERIOD_BYTES), - HW_PARAM(PERIODS), - HW_PARAM(BUFFER_TIME), - HW_PARAM(BUFFER_SIZE), - HW_PARAM(BUFFER_BYTES), - HW_PARAM(TICK_TIME), -}; -#endif - -int snd_pcm_hw_refine(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) +static int constrain_mask_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) { + struct snd_pcm_hw_constraints *constrs = + &substream->runtime->hw_constraints; + struct snd_mask *m; unsigned int k; - struct snd_pcm_hardware *hw; - struct snd_interval *i = NULL; - struct snd_mask *m = NULL; - struct snd_pcm_hw_constraints *constrs = &substream->runtime->hw_constraints; - unsigned int rstamps[constrs->rules_num]; - unsigned int vstamps[SNDRV_PCM_HW_PARAM_LAST_INTERVAL + 1]; - unsigned int stamp = 2; - int changed, again; - - params->info = 0; - params->fifo_size = 0; - if (params->rmask & (1 << SNDRV_PCM_HW_PARAM_SAMPLE_BITS)) - params->msbits = 0; - if (params->rmask & (1 << SNDRV_PCM_HW_PARAM_RATE)) { - params->rate_num = 0; - params->rate_den = 0; - } + struct snd_mask old_mask; + int changed; for (k = SNDRV_PCM_HW_PARAM_FIRST_MASK; k <= SNDRV_PCM_HW_PARAM_LAST_MASK; k++) { m = hw_param_mask(params, k); if (snd_mask_empty(m)) return -EINVAL; + + /* This parameter is not requested to change by a caller. */ if (!(params->rmask & (1 << k))) continue; -#ifdef RULES_DEBUG - pr_debug("%s = ", snd_pcm_hw_param_names[k]); - pr_cont("%04x%04x%04x%04x -> ", m->bits[3], m->bits[2], m->bits[1], m->bits[0]); -#endif + + if (trace_hw_mask_param_enabled()) + old_mask = *m; + changed = snd_mask_refine(m, constrs_mask(constrs, k)); -#ifdef RULES_DEBUG - pr_cont("%04x%04x%04x%04x\n", m->bits[3], m->bits[2], m->bits[1], m->bits[0]); -#endif - if (changed) - params->cmask |= 1 << k; if (changed < 0) return changed; + if (changed == 0) + continue; + + /* Set corresponding flag so that the caller gets it. */ + trace_hw_mask_param(substream, k, 0, &old_mask, m); + params->cmask |= 1 << k; } + return 0; +} + +static int constrain_interval_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_pcm_hw_constraints *constrs = + &substream->runtime->hw_constraints; + struct snd_interval *i; + unsigned int k; + struct snd_interval old_interval; + int changed; + for (k = SNDRV_PCM_HW_PARAM_FIRST_INTERVAL; k <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; k++) { i = hw_param_interval(params, k); if (snd_interval_empty(i)) return -EINVAL; + + /* This parameter is not requested to change by a caller. */ if (!(params->rmask & (1 << k))) continue; -#ifdef RULES_DEBUG - pr_debug("%s = ", snd_pcm_hw_param_names[k]); - if (i->empty) - pr_cont("empty"); - else - pr_cont("%c%u %u%c", - i->openmin ? '(' : '[', i->min, - i->max, i->openmax ? ')' : ']'); - pr_cont(" -> "); -#endif + + if (trace_hw_interval_param_enabled()) + old_interval = *i; + changed = snd_interval_refine(i, constrs_interval(constrs, k)); -#ifdef RULES_DEBUG - if (i->empty) - pr_cont("empty\n"); - else - pr_cont("%c%u %u%c\n", - i->openmin ? '(' : '[', i->min, - i->max, i->openmax ? ')' : ']'); -#endif - if (changed) - params->cmask |= 1 << k; if (changed < 0) return changed; + if (changed == 0) + continue; + + /* Set corresponding flag so that the caller gets it. */ + trace_hw_interval_param(substream, k, 0, &old_interval, i); + params->cmask |= 1 << k; } + return 0; +} + +static int constrain_params_by_rules(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_pcm_hw_constraints *constrs = + &substream->runtime->hw_constraints; + unsigned int k; + unsigned int rstamps[constrs->rules_num]; + unsigned int vstamps[SNDRV_PCM_HW_PARAM_LAST_INTERVAL + 1]; + unsigned int stamp; + struct snd_pcm_hw_rule *r; + unsigned int d; + struct snd_mask old_mask; + struct snd_interval old_interval; + bool again; + int changed; + + /* + * Each application of rule has own sequence number. + * + * Each member of 'rstamps' array represents the sequence number of + * recent application of corresponding rule. + */ for (k = 0; k < constrs->rules_num; k++) rstamps[k] = 0; - for (k = 0; k <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; k++) + + /* + * Each member of 'vstamps' array represents the sequence number of + * recent application of rule in which corresponding parameters were + * changed. + * + * In initial state, elements corresponding to parameters requested by + * a caller is 1. For unrequested parameters, corresponding members + * have 0 so that the parameters are never changed anymore. + */ + for (k = 0; k <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; k++) vstamps[k] = (params->rmask & (1 << k)) ? 1 : 0; - do { - again = 0; - for (k = 0; k < constrs->rules_num; k++) { - struct snd_pcm_hw_rule *r = &constrs->rules[k]; - unsigned int d; - int doit = 0; - if (r->cond && !(r->cond & params->flags)) - continue; - for (d = 0; r->deps[d] >= 0; d++) { - if (vstamps[r->deps[d]] > rstamps[k]) { - doit = 1; - break; - } - } - if (!doit) - continue; -#ifdef RULES_DEBUG - pr_debug("Rule %d [%p]: ", k, r->func); - if (r->var >= 0) { - pr_cont("%s = ", snd_pcm_hw_param_names[r->var]); - if (hw_is_mask(r->var)) { - m = hw_param_mask(params, r->var); - pr_cont("%x", *m->bits); - } else { - i = hw_param_interval(params, r->var); - if (i->empty) - pr_cont("empty"); - else - pr_cont("%c%u %u%c", - i->openmin ? '(' : '[', i->min, - i->max, i->openmax ? ')' : ']'); - } - } -#endif - changed = r->func(params, r); -#ifdef RULES_DEBUG - if (r->var >= 0) { - pr_cont(" -> "); - if (hw_is_mask(r->var)) - pr_cont("%x", *m->bits); - else { - if (i->empty) - pr_cont("empty"); - else - pr_cont("%c%u %u%c", - i->openmin ? '(' : '[', i->min, - i->max, i->openmax ? ')' : ']'); - } + + /* Due to the above design, actual sequence number starts at 2. */ + stamp = 2; +retry: + /* Apply all rules in order. */ + again = false; + for (k = 0; k < constrs->rules_num; k++) { + r = &constrs->rules[k]; + + /* + * Check condition bits of this rule. When the rule has + * some condition bits, parameter without the bits is + * never processed. SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP + * is an example of the condition bits. + */ + if (r->cond && !(r->cond & params->flags)) + continue; + + /* + * The 'deps' array includes maximum three dependencies + * to SNDRV_PCM_HW_PARAM_XXXs for this rule. The fourth + * member of this array is a sentinel and should be + * negative value. + * + * This rule should be processed in this time when dependent + * parameters were changed at former applications of the other + * rules. + */ + for (d = 0; r->deps[d] >= 0; d++) { + if (vstamps[r->deps[d]] > rstamps[k]) + break; + } + if (r->deps[d] < 0) + continue; + + if (trace_hw_mask_param_enabled()) { + if (hw_is_mask(r->var)) + old_mask = *hw_param_mask(params, r->var); + } + if (trace_hw_interval_param_enabled()) { + if (hw_is_interval(r->var)) + old_interval = *hw_param_interval(params, r->var); + } + + changed = r->func(params, r); + if (changed < 0) + return changed; + + /* + * When the parameter is changed, notify it to the caller + * by corresponding returned bit, then preparing for next + * iteration. + */ + if (changed && r->var >= 0) { + if (hw_is_mask(r->var)) { + trace_hw_mask_param(substream, r->var, + k + 1, &old_mask, + hw_param_mask(params, r->var)); } - pr_cont("\n"); -#endif - rstamps[k] = stamp; - if (changed && r->var >= 0) { - params->cmask |= (1 << r->var); - vstamps[r->var] = stamp; - again = 1; + if (hw_is_interval(r->var)) { + trace_hw_interval_param(substream, r->var, + k + 1, &old_interval, + hw_param_interval(params, r->var)); } - if (changed < 0) - return changed; - stamp++; + + params->cmask |= (1 << r->var); + vstamps[r->var] = stamp; + again = true; } - } while (again); + + rstamps[k] = stamp++; + } + + /* Iterate to evaluate all rules till no parameters are changed. */ + if (again) + goto retry; + + return 0; +} + +static int fixup_unreferenced_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + const struct snd_interval *i; + const struct snd_mask *m; + int err; + if (!params->msbits) { - i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS); + i = hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS); if (snd_interval_single(i)) params->msbits = snd_interval_value(i); } if (!params->rate_den) { - i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); + i = hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_RATE); if (snd_interval_single(i)) { params->rate_num = snd_interval_value(i); params->rate_den = 1; } } - hw = &substream->runtime->hw; + if (!params->fifo_size) { + m = hw_param_mask_c(params, SNDRV_PCM_HW_PARAM_FORMAT); + i = hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_CHANNELS); + if (snd_mask_single(m) && snd_interval_single(i)) { + err = substream->ops->ioctl(substream, + SNDRV_PCM_IOCTL1_FIFO_SIZE, params); + if (err < 0) + return err; + } + } + if (!params->info) { - params->info = hw->info & ~(SNDRV_PCM_INFO_FIFO_IN_FRAMES | - SNDRV_PCM_INFO_DRAIN_TRIGGER); + params->info = substream->runtime->hw.info; + params->info &= ~(SNDRV_PCM_INFO_FIFO_IN_FRAMES | + SNDRV_PCM_INFO_DRAIN_TRIGGER); if (!hw_support_mmap(substream)) params->info &= ~(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID); } - if (!params->fifo_size) { - m = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); - i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); - if (snd_mask_min(m) == snd_mask_max(m) && - snd_interval_min(i) == snd_interval_max(i)) { - changed = substream->ops->ioctl(substream, - SNDRV_PCM_IOCTL1_FIFO_SIZE, params); - if (changed < 0) - return changed; - } + + return 0; +} + +int snd_pcm_hw_refine(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + int err; + + params->info = 0; + params->fifo_size = 0; + if (params->rmask & (1 << SNDRV_PCM_HW_PARAM_SAMPLE_BITS)) + params->msbits = 0; + if (params->rmask & (1 << SNDRV_PCM_HW_PARAM_RATE)) { + params->rate_num = 0; + params->rate_den = 0; } + + err = constrain_mask_params(substream, params); + if (err < 0) + return err; + + err = constrain_interval_params(substream, params); + if (err < 0) + return err; + + err = constrain_params_by_rules(substream, params); + if (err < 0) + return err; + params->rmask = 0; + return 0; } - EXPORT_SYMBOL(snd_pcm_hw_refine); static int snd_pcm_hw_refine_user(struct snd_pcm_substream *substream, @@ -467,11 +522,16 @@ static int snd_pcm_hw_refine_user(struct snd_pcm_substream *substream, return PTR_ERR(params); err = snd_pcm_hw_refine(substream, params); - if (copy_to_user(_params, params, sizeof(*params))) { - if (!err) - err = -EFAULT; - } + if (err < 0) + goto end; + + err = fixup_unreferenced_params(substream, params); + if (err < 0) + goto end; + if (copy_to_user(_params, params, sizeof(*params))) + err = -EFAULT; +end: kfree(params); return err; } @@ -509,6 +569,70 @@ static inline void snd_pcm_timer_notify(struct snd_pcm_substream *substream, #endif } +/** + * snd_pcm_hw_param_choose - choose a configuration defined by @params + * @pcm: PCM instance + * @params: the hw_params instance + * + * Choose one configuration from configuration space defined by @params. + * The configuration chosen is that obtained fixing in this order: + * first access, first format, first subformat, min channels, + * min rate, min period time, max buffer size, min tick time + * + * Return: Zero if successful, or a negative error code on failure. + */ +static int snd_pcm_hw_params_choose(struct snd_pcm_substream *pcm, + struct snd_pcm_hw_params *params) +{ + static const int vars[] = { + SNDRV_PCM_HW_PARAM_ACCESS, + SNDRV_PCM_HW_PARAM_FORMAT, + SNDRV_PCM_HW_PARAM_SUBFORMAT, + SNDRV_PCM_HW_PARAM_CHANNELS, + SNDRV_PCM_HW_PARAM_RATE, + SNDRV_PCM_HW_PARAM_PERIOD_TIME, + SNDRV_PCM_HW_PARAM_BUFFER_SIZE, + SNDRV_PCM_HW_PARAM_TICK_TIME, + -1 + }; + const int *v; + struct snd_mask old_mask; + struct snd_interval old_interval; + int changed; + + for (v = vars; *v != -1; v++) { + /* Keep old parameter to trace. */ + if (trace_hw_mask_param_enabled()) { + if (hw_is_mask(*v)) + old_mask = *hw_param_mask(params, *v); + } + if (trace_hw_interval_param_enabled()) { + if (hw_is_interval(*v)) + old_interval = *hw_param_interval(params, *v); + } + if (*v != SNDRV_PCM_HW_PARAM_BUFFER_SIZE) + changed = snd_pcm_hw_param_first(pcm, params, *v, NULL); + else + changed = snd_pcm_hw_param_last(pcm, params, *v, NULL); + if (snd_BUG_ON(changed < 0)) + return changed; + if (changed == 0) + continue; + + /* Trace the changed parameter. */ + if (hw_is_mask(*v)) { + trace_hw_mask_param(pcm, *v, 0, &old_mask, + hw_param_mask(params, *v)); + } + if (hw_is_interval(*v)) { + trace_hw_interval_param(pcm, *v, 0, &old_interval, + hw_param_interval(params, *v)); + } + } + + return 0; +} + static int snd_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { @@ -546,6 +670,10 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream, if (err < 0) goto _error; + err = fixup_unreferenced_params(substream, params); + if (err < 0) + goto _error; + if (substream->ops->hw_params != NULL) { err = substream->ops->hw_params(substream, params); if (err < 0) @@ -621,11 +749,12 @@ static int snd_pcm_hw_params_user(struct snd_pcm_substream *substream, return PTR_ERR(params); err = snd_pcm_hw_params(substream, params); - if (copy_to_user(_params, params, sizeof(*params))) { - if (!err) - err = -EFAULT; - } + if (err < 0) + goto end; + if (copy_to_user(_params, params, sizeof(*params))) + err = -EFAULT; +end: kfree(params); return err; } @@ -1081,6 +1210,7 @@ static const struct action_ops snd_pcm_action_start = { * @substream: the PCM substream instance * * Return: Zero if successful, or a negative error code. + * The stream lock must be acquired before calling this function. */ int snd_pcm_start(struct snd_pcm_substream *substream) { @@ -1088,6 +1218,13 @@ int snd_pcm_start(struct snd_pcm_substream *substream) SNDRV_PCM_STATE_RUNNING); } +/* take the stream lock and start the streams */ +static int snd_pcm_start_lock_irq(struct snd_pcm_substream *substream) +{ + return snd_pcm_action_lock_irq(&snd_pcm_action_start, substream, + SNDRV_PCM_STATE_RUNNING); +} + /* * stop callbacks */ @@ -1139,7 +1276,6 @@ int snd_pcm_stop(struct snd_pcm_substream *substream, snd_pcm_state_t state) { return snd_pcm_action(&snd_pcm_action_stop, substream, state); } - EXPORT_SYMBOL(snd_pcm_stop); /** @@ -1314,7 +1450,6 @@ int snd_pcm_suspend(struct snd_pcm_substream *substream) snd_pcm_stream_unlock_irqrestore(substream, flags); return err; } - EXPORT_SYMBOL(snd_pcm_suspend); /** @@ -1346,7 +1481,6 @@ int snd_pcm_suspend_all(struct snd_pcm *pcm) } return 0; } - EXPORT_SYMBOL(snd_pcm_suspend_all); /* resume */ @@ -1397,14 +1531,7 @@ static const struct action_ops snd_pcm_action_resume = { static int snd_pcm_resume(struct snd_pcm_substream *substream) { - struct snd_card *card = substream->pcm->card; - int res; - - snd_power_lock(card); - if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0)) >= 0) - res = snd_pcm_action_lock_irq(&snd_pcm_action_resume, substream, 0); - snd_power_unlock(card); - return res; + return snd_pcm_action_lock_irq(&snd_pcm_action_resume, substream, 0); } #else @@ -1423,17 +1550,9 @@ static int snd_pcm_resume(struct snd_pcm_substream *substream) */ static int snd_pcm_xrun(struct snd_pcm_substream *substream) { - struct snd_card *card = substream->pcm->card; struct snd_pcm_runtime *runtime = substream->runtime; int result; - snd_power_lock(card); - if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { - result = snd_power_wait(card, SNDRV_CTL_POWER_D0); - if (result < 0) - goto _unlock; - } - snd_pcm_stream_lock_irq(substream); switch (runtime->status->state) { case SNDRV_PCM_STATE_XRUN: @@ -1446,8 +1565,6 @@ static int snd_pcm_xrun(struct snd_pcm_substream *substream) result = -EBADFD; } snd_pcm_stream_unlock_irq(substream); - _unlock: - snd_power_unlock(card); return result; } @@ -1551,8 +1668,6 @@ static const struct action_ops snd_pcm_action_prepare = { static int snd_pcm_prepare(struct snd_pcm_substream *substream, struct file *file) { - int res; - struct snd_card *card = substream->pcm->card; int f_flags; if (file) @@ -1560,12 +1675,19 @@ static int snd_pcm_prepare(struct snd_pcm_substream *substream, else f_flags = substream->f_flags; - snd_power_lock(card); - if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0)) >= 0) - res = snd_pcm_action_nonatomic(&snd_pcm_action_prepare, - substream, f_flags); - snd_power_unlock(card); - return res; + snd_pcm_stream_lock_irq(substream); + switch (substream->runtime->status->state) { + case SNDRV_PCM_STATE_PAUSED: + snd_pcm_pause(substream, 0); + /* fallthru */ + case SNDRV_PCM_STATE_SUSPENDED: + snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP); + break; + } + snd_pcm_stream_unlock_irq(substream); + + return snd_pcm_action_nonatomic(&snd_pcm_action_prepare, + substream, f_flags); } /* @@ -1652,7 +1774,7 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream, struct snd_card *card; struct snd_pcm_runtime *runtime; struct snd_pcm_substream *s; - wait_queue_t wait; + wait_queue_entry_t wait; int result = 0; int nonblock = 0; @@ -1662,15 +1784,6 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream, if (runtime->status->state == SNDRV_PCM_STATE_OPEN) return -EBADFD; - snd_power_lock(card); - if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { - result = snd_power_wait(card, SNDRV_CTL_POWER_D0); - if (result < 0) { - snd_power_unlock(card); - return result; - } - } - if (file) { if (file->f_flags & O_NONBLOCK) nonblock = 1; @@ -1753,7 +1866,6 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream, unlock: snd_pcm_stream_unlock_irq(substream); up_read(&snd_pcm_link_rwsem); - snd_power_unlock(card); return result; } @@ -1773,8 +1885,7 @@ static int snd_pcm_drop(struct snd_pcm_substream *substream) runtime = substream->runtime; if (runtime->status->state == SNDRV_PCM_STATE_OPEN || - runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED || - runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) + runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED) return -EBADFD; snd_pcm_stream_lock_irq(substream); @@ -1940,7 +2051,8 @@ static int snd_pcm_hw_rule_format(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule) { unsigned int k; - struct snd_interval *i = hw_param_interval(params, rule->deps[0]); + const struct snd_interval *i = + hw_param_interval_c(params, rule->deps[0]); struct snd_mask m; struct snd_mask *mask = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); snd_mask_any(&m); @@ -1986,8 +2098,10 @@ static int snd_pcm_hw_rule_sample_bits(struct snd_pcm_hw_params *params, #error "Change this table" #endif -static unsigned int rates[] = { 5512, 8000, 11025, 16000, 22050, 32000, 44100, - 48000, 64000, 88200, 96000, 176400, 192000 }; +static const unsigned int rates[] = { + 5512, 8000, 11025, 16000, 22050, 32000, 44100, + 48000, 64000, 88200, 96000, 176400, 192000 +}; const struct snd_pcm_hw_constraint_list snd_pcm_known_rates = { .count = ARRAY_SIZE(rates), @@ -2250,7 +2364,6 @@ void snd_pcm_release_substream(struct snd_pcm_substream *substream) } snd_pcm_detach_substream(substream); } - EXPORT_SYMBOL(snd_pcm_release_substream); int snd_pcm_open_substream(struct snd_pcm *pcm, int stream, @@ -2292,7 +2405,6 @@ int snd_pcm_open_substream(struct snd_pcm *pcm, int stream, snd_pcm_release_substream(substream); return err; } - EXPORT_SYMBOL(snd_pcm_open_substream); static int snd_pcm_open_file(struct file *file, @@ -2353,7 +2465,7 @@ static int snd_pcm_capture_open(struct inode *inode, struct file *file) static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream) { int err; - wait_queue_t wait; + wait_queue_entry_t wait; if (pcm == NULL) { err = -ENODEV; @@ -2428,50 +2540,84 @@ static int snd_pcm_release(struct inode *inode, struct file *file) return 0; } -static snd_pcm_sframes_t snd_pcm_playback_rewind(struct snd_pcm_substream *substream, - snd_pcm_uframes_t frames) +/* check and update PCM state; return 0 or a negative error + * call this inside PCM lock + */ +static int do_pcm_hwsync(struct snd_pcm_substream *substream) { - struct snd_pcm_runtime *runtime = substream->runtime; - snd_pcm_sframes_t appl_ptr; - snd_pcm_sframes_t ret; - snd_pcm_sframes_t hw_avail; - - if (frames == 0) - return 0; - - snd_pcm_stream_lock_irq(substream); - switch (runtime->status->state) { - case SNDRV_PCM_STATE_PREPARED: - break; + switch (substream->runtime->status->state) { case SNDRV_PCM_STATE_DRAINING: - case SNDRV_PCM_STATE_RUNNING: - if (snd_pcm_update_hw_ptr(substream) >= 0) - break; + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) + return -EBADFD; /* Fall through */ - case SNDRV_PCM_STATE_XRUN: - ret = -EPIPE; - goto __end; + case SNDRV_PCM_STATE_RUNNING: + return snd_pcm_update_hw_ptr(substream); + case SNDRV_PCM_STATE_PREPARED: + case SNDRV_PCM_STATE_PAUSED: + return 0; case SNDRV_PCM_STATE_SUSPENDED: - ret = -ESTRPIPE; - goto __end; + return -ESTRPIPE; + case SNDRV_PCM_STATE_XRUN: + return -EPIPE; default: - ret = -EBADFD; - goto __end; + return -EBADFD; } +} - hw_avail = snd_pcm_playback_hw_avail(runtime); - if (hw_avail <= 0) { - ret = 0; - goto __end; - } - if (frames > (snd_pcm_uframes_t)hw_avail) - frames = hw_avail; +/* increase the appl_ptr; returns the processed frames or a negative error */ +static snd_pcm_sframes_t forward_appl_ptr(struct snd_pcm_substream *substream, + snd_pcm_uframes_t frames, + snd_pcm_sframes_t avail) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + snd_pcm_sframes_t appl_ptr; + int ret; + + if (avail <= 0) + return 0; + if (frames > (snd_pcm_uframes_t)avail) + frames = avail; + appl_ptr = runtime->control->appl_ptr + frames; + if (appl_ptr >= (snd_pcm_sframes_t)runtime->boundary) + appl_ptr -= runtime->boundary; + ret = pcm_lib_apply_appl_ptr(substream, appl_ptr); + return ret < 0 ? ret : frames; +} + +/* decrease the appl_ptr; returns the processed frames or a negative error */ +static snd_pcm_sframes_t rewind_appl_ptr(struct snd_pcm_substream *substream, + snd_pcm_uframes_t frames, + snd_pcm_sframes_t avail) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + snd_pcm_sframes_t appl_ptr; + int ret; + + if (avail <= 0) + return 0; + if (frames > (snd_pcm_uframes_t)avail) + frames = avail; appl_ptr = runtime->control->appl_ptr - frames; if (appl_ptr < 0) appl_ptr += runtime->boundary; - runtime->control->appl_ptr = appl_ptr; - ret = frames; - __end: + ret = pcm_lib_apply_appl_ptr(substream, appl_ptr); + return ret < 0 ? ret : frames; +} + +static snd_pcm_sframes_t snd_pcm_playback_rewind(struct snd_pcm_substream *substream, + snd_pcm_uframes_t frames) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + snd_pcm_sframes_t ret; + + if (frames == 0) + return 0; + + snd_pcm_stream_lock_irq(substream); + ret = do_pcm_hwsync(substream); + if (!ret) + ret = rewind_appl_ptr(substream, frames, + snd_pcm_playback_hw_avail(runtime)); snd_pcm_stream_unlock_irq(substream); return ret; } @@ -2480,46 +2626,16 @@ static snd_pcm_sframes_t snd_pcm_capture_rewind(struct snd_pcm_substream *substr snd_pcm_uframes_t frames) { struct snd_pcm_runtime *runtime = substream->runtime; - snd_pcm_sframes_t appl_ptr; snd_pcm_sframes_t ret; - snd_pcm_sframes_t hw_avail; if (frames == 0) return 0; snd_pcm_stream_lock_irq(substream); - switch (runtime->status->state) { - case SNDRV_PCM_STATE_PREPARED: - case SNDRV_PCM_STATE_DRAINING: - break; - case SNDRV_PCM_STATE_RUNNING: - if (snd_pcm_update_hw_ptr(substream) >= 0) - break; - /* Fall through */ - case SNDRV_PCM_STATE_XRUN: - ret = -EPIPE; - goto __end; - case SNDRV_PCM_STATE_SUSPENDED: - ret = -ESTRPIPE; - goto __end; - default: - ret = -EBADFD; - goto __end; - } - - hw_avail = snd_pcm_capture_hw_avail(runtime); - if (hw_avail <= 0) { - ret = 0; - goto __end; - } - if (frames > (snd_pcm_uframes_t)hw_avail) - frames = hw_avail; - appl_ptr = runtime->control->appl_ptr - frames; - if (appl_ptr < 0) - appl_ptr += runtime->boundary; - runtime->control->appl_ptr = appl_ptr; - ret = frames; - __end: + ret = do_pcm_hwsync(substream); + if (!ret) + ret = rewind_appl_ptr(substream, frames, + snd_pcm_capture_hw_avail(runtime)); snd_pcm_stream_unlock_irq(substream); return ret; } @@ -2528,47 +2644,16 @@ static snd_pcm_sframes_t snd_pcm_playback_forward(struct snd_pcm_substream *subs snd_pcm_uframes_t frames) { struct snd_pcm_runtime *runtime = substream->runtime; - snd_pcm_sframes_t appl_ptr; snd_pcm_sframes_t ret; - snd_pcm_sframes_t avail; if (frames == 0) return 0; snd_pcm_stream_lock_irq(substream); - switch (runtime->status->state) { - case SNDRV_PCM_STATE_PREPARED: - case SNDRV_PCM_STATE_PAUSED: - break; - case SNDRV_PCM_STATE_DRAINING: - case SNDRV_PCM_STATE_RUNNING: - if (snd_pcm_update_hw_ptr(substream) >= 0) - break; - /* Fall through */ - case SNDRV_PCM_STATE_XRUN: - ret = -EPIPE; - goto __end; - case SNDRV_PCM_STATE_SUSPENDED: - ret = -ESTRPIPE; - goto __end; - default: - ret = -EBADFD; - goto __end; - } - - avail = snd_pcm_playback_avail(runtime); - if (avail <= 0) { - ret = 0; - goto __end; - } - if (frames > (snd_pcm_uframes_t)avail) - frames = avail; - appl_ptr = runtime->control->appl_ptr + frames; - if (appl_ptr >= (snd_pcm_sframes_t)runtime->boundary) - appl_ptr -= runtime->boundary; - runtime->control->appl_ptr = appl_ptr; - ret = frames; - __end: + ret = do_pcm_hwsync(substream); + if (!ret) + ret = forward_appl_ptr(substream, frames, + snd_pcm_playback_avail(runtime)); snd_pcm_stream_unlock_irq(substream); return ret; } @@ -2577,123 +2662,47 @@ static snd_pcm_sframes_t snd_pcm_capture_forward(struct snd_pcm_substream *subst snd_pcm_uframes_t frames) { struct snd_pcm_runtime *runtime = substream->runtime; - snd_pcm_sframes_t appl_ptr; snd_pcm_sframes_t ret; - snd_pcm_sframes_t avail; if (frames == 0) return 0; snd_pcm_stream_lock_irq(substream); - switch (runtime->status->state) { - case SNDRV_PCM_STATE_PREPARED: - case SNDRV_PCM_STATE_DRAINING: - case SNDRV_PCM_STATE_PAUSED: - break; - case SNDRV_PCM_STATE_RUNNING: - if (snd_pcm_update_hw_ptr(substream) >= 0) - break; - /* Fall through */ - case SNDRV_PCM_STATE_XRUN: - ret = -EPIPE; - goto __end; - case SNDRV_PCM_STATE_SUSPENDED: - ret = -ESTRPIPE; - goto __end; - default: - ret = -EBADFD; - goto __end; - } - - avail = snd_pcm_capture_avail(runtime); - if (avail <= 0) { - ret = 0; - goto __end; - } - if (frames > (snd_pcm_uframes_t)avail) - frames = avail; - appl_ptr = runtime->control->appl_ptr + frames; - if (appl_ptr >= (snd_pcm_sframes_t)runtime->boundary) - appl_ptr -= runtime->boundary; - runtime->control->appl_ptr = appl_ptr; - ret = frames; - __end: + ret = do_pcm_hwsync(substream); + if (!ret) + ret = forward_appl_ptr(substream, frames, + snd_pcm_capture_avail(runtime)); snd_pcm_stream_unlock_irq(substream); return ret; } static int snd_pcm_hwsync(struct snd_pcm_substream *substream) { - struct snd_pcm_runtime *runtime = substream->runtime; int err; snd_pcm_stream_lock_irq(substream); - switch (runtime->status->state) { - case SNDRV_PCM_STATE_DRAINING: - if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) - goto __badfd; - /* Fall through */ - case SNDRV_PCM_STATE_RUNNING: - if ((err = snd_pcm_update_hw_ptr(substream)) < 0) - break; - /* Fall through */ - case SNDRV_PCM_STATE_PREPARED: - err = 0; - break; - case SNDRV_PCM_STATE_SUSPENDED: - err = -ESTRPIPE; - break; - case SNDRV_PCM_STATE_XRUN: - err = -EPIPE; - break; - default: - __badfd: - err = -EBADFD; - break; - } + err = do_pcm_hwsync(substream); snd_pcm_stream_unlock_irq(substream); return err; } -static int snd_pcm_delay(struct snd_pcm_substream *substream, - snd_pcm_sframes_t __user *res) +static snd_pcm_sframes_t snd_pcm_delay(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; int err; snd_pcm_sframes_t n = 0; snd_pcm_stream_lock_irq(substream); - switch (runtime->status->state) { - case SNDRV_PCM_STATE_DRAINING: - if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) - goto __badfd; - /* Fall through */ - case SNDRV_PCM_STATE_RUNNING: - if ((err = snd_pcm_update_hw_ptr(substream)) < 0) - break; - /* Fall through */ - case SNDRV_PCM_STATE_PREPARED: - case SNDRV_PCM_STATE_SUSPENDED: - err = 0; + err = do_pcm_hwsync(substream); + if (!err) { if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) n = snd_pcm_playback_hw_avail(runtime); else n = snd_pcm_capture_avail(runtime); n += runtime->delay; - break; - case SNDRV_PCM_STATE_XRUN: - err = -EPIPE; - break; - default: - __badfd: - err = -EBADFD; - break; } snd_pcm_stream_unlock_irq(substream); - if (!err) - if (put_user(n, res)) - err = -EFAULT; - return err; + return err < 0 ? err : n; } static int snd_pcm_sync_ptr(struct snd_pcm_substream *substream, @@ -2718,10 +2727,16 @@ static int snd_pcm_sync_ptr(struct snd_pcm_substream *substream, return err; } snd_pcm_stream_lock_irq(substream); - if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_APPL)) - control->appl_ptr = sync_ptr.c.control.appl_ptr; - else + if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_APPL)) { + err = pcm_lib_apply_appl_ptr(substream, + sync_ptr.c.control.appl_ptr); + if (err < 0) { + snd_pcm_stream_unlock_irq(substream); + return err; + } + } else { sync_ptr.c.control.appl_ptr = control->appl_ptr; + } if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN)) control->avail_min = sync_ptr.c.control.avail_min; else @@ -2749,10 +2764,12 @@ static int snd_pcm_tstamp(struct snd_pcm_substream *substream, int __user *_arg) return 0; } -static int snd_pcm_common_ioctl1(struct file *file, +static int snd_pcm_common_ioctl(struct file *file, struct snd_pcm_substream *substream, unsigned int cmd, void __user *arg) { + struct snd_pcm_file *pcm_file = file->private_data; + switch (cmd) { case SNDRV_PCM_IOCTL_PVERSION: return put_user(SNDRV_PCM_VERSION, (int __user *)arg) ? -EFAULT : 0; @@ -2762,6 +2779,11 @@ static int snd_pcm_common_ioctl1(struct file *file, return 0; case SNDRV_PCM_IOCTL_TTSTAMP: return snd_pcm_tstamp(substream, arg); + case SNDRV_PCM_IOCTL_USER_PVERSION: + if (get_user(pcm_file->user_pversion, + (unsigned int __user *)arg)) + return -EFAULT; + return 0; case SNDRV_PCM_IOCTL_HW_REFINE: return snd_pcm_hw_refine_user(substream, arg); case SNDRV_PCM_IOCTL_HW_PARAMS: @@ -2781,7 +2803,7 @@ static int snd_pcm_common_ioctl1(struct file *file, case SNDRV_PCM_IOCTL_RESET: return snd_pcm_reset(substream); case SNDRV_PCM_IOCTL_START: - return snd_pcm_action_lock_irq(&snd_pcm_action_start, substream, SNDRV_PCM_STATE_RUNNING); + return snd_pcm_start_lock_irq(substream); case SNDRV_PCM_IOCTL_LINK: return snd_pcm_link(substream, (int)(unsigned long) arg); case SNDRV_PCM_IOCTL_UNLINK: @@ -2793,7 +2815,16 @@ static int snd_pcm_common_ioctl1(struct file *file, case SNDRV_PCM_IOCTL_HWSYNC: return snd_pcm_hwsync(substream); case SNDRV_PCM_IOCTL_DELAY: - return snd_pcm_delay(substream, arg); + { + snd_pcm_sframes_t delay = snd_pcm_delay(substream); + snd_pcm_sframes_t __user *res = arg; + + if (delay < 0) + return delay; + if (put_user(delay, res)) + return -EFAULT; + return 0; + } case SNDRV_PCM_IOCTL_SYNC_PTR: return snd_pcm_sync_ptr(substream, arg); #ifdef CONFIG_SND_SUPPORT_OLD_API @@ -2807,23 +2838,34 @@ static int snd_pcm_common_ioctl1(struct file *file, case SNDRV_PCM_IOCTL_DROP: return snd_pcm_drop(substream); case SNDRV_PCM_IOCTL_PAUSE: - { - int res; - snd_pcm_stream_lock_irq(substream); - res = snd_pcm_pause(substream, (int)(unsigned long)arg); - snd_pcm_stream_unlock_irq(substream); - return res; - } + return snd_pcm_action_lock_irq(&snd_pcm_action_pause, + substream, + (int)(unsigned long)arg); } pcm_dbg(substream->pcm, "unknown ioctl = 0x%x\n", cmd); return -ENOTTY; } +static int snd_pcm_common_ioctl1(struct file *file, + struct snd_pcm_substream *substream, + unsigned int cmd, void __user *arg) +{ + struct snd_card *card = substream->pcm->card; + int res; + + snd_power_lock(card); + res = snd_power_wait(card, SNDRV_CTL_POWER_D0); + if (res >= 0) + res = snd_pcm_common_ioctl(file, substream, cmd, arg); + snd_power_unlock(card); + return res; +} + static int snd_pcm_playback_ioctl1(struct file *file, struct snd_pcm_substream *substream, unsigned int cmd, void __user *arg) { - if (snd_BUG_ON(!substream)) + if (PCM_RUNTIME_CHECK(substream)) return -ENXIO; if (snd_BUG_ON(substream->stream != SNDRV_PCM_STREAM_PLAYBACK)) return -EINVAL; @@ -2903,7 +2945,7 @@ static int snd_pcm_capture_ioctl1(struct file *file, struct snd_pcm_substream *substream, unsigned int cmd, void __user *arg) { - if (snd_BUG_ON(!substream)) + if (PCM_RUNTIME_CHECK(substream)) return -ENXIO; if (snd_BUG_ON(substream->stream != SNDRV_PCM_STREAM_CAPTURE)) return -EINVAL; @@ -3007,30 +3049,55 @@ static long snd_pcm_capture_ioctl(struct file *file, unsigned int cmd, (void __user *)arg); } +/** + * snd_pcm_kernel_ioctl - Execute PCM ioctl in the kernel-space + * @substream: PCM substream + * @cmd: IOCTL cmd + * @arg: IOCTL argument + * + * The function is provided primarily for OSS layer and USB gadget drivers, + * and it allows only the limited set of ioctls (hw_params, sw_params, + * prepare, start, drain, drop, forward). + */ int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream, unsigned int cmd, void *arg) { - mm_segment_t fs; - int result; + snd_pcm_uframes_t *frames = arg; + snd_pcm_sframes_t result; - fs = snd_enter_user(); - switch (substream->stream) { - case SNDRV_PCM_STREAM_PLAYBACK: - result = snd_pcm_playback_ioctl1(NULL, substream, cmd, - (void __user *)arg); - break; - case SNDRV_PCM_STREAM_CAPTURE: - result = snd_pcm_capture_ioctl1(NULL, substream, cmd, - (void __user *)arg); - break; + switch (cmd) { + case SNDRV_PCM_IOCTL_FORWARD: + { + /* provided only for OSS; capture-only and no value returned */ + if (substream->stream != SNDRV_PCM_STREAM_CAPTURE) + return -EINVAL; + result = snd_pcm_capture_forward(substream, *frames); + return result < 0 ? result : 0; + } + case SNDRV_PCM_IOCTL_HW_PARAMS: + return snd_pcm_hw_params(substream, arg); + case SNDRV_PCM_IOCTL_SW_PARAMS: + return snd_pcm_sw_params(substream, arg); + case SNDRV_PCM_IOCTL_PREPARE: + return snd_pcm_prepare(substream, NULL); + case SNDRV_PCM_IOCTL_START: + return snd_pcm_start_lock_irq(substream); + case SNDRV_PCM_IOCTL_DRAIN: + return snd_pcm_drain(substream, NULL); + case SNDRV_PCM_IOCTL_DROP: + return snd_pcm_drop(substream); + case SNDRV_PCM_IOCTL_DELAY: + { + result = snd_pcm_delay(substream); + if (result < 0) + return result; + *frames = result; + return 0; + } default: - result = -EINVAL; - break; + return -EINVAL; } - snd_leave_user(fs); - return result; } - EXPORT_SYMBOL(snd_pcm_kernel_ioctl); static ssize_t snd_pcm_read(struct file *file, char __user *buf, size_t count, @@ -3314,10 +3381,41 @@ static int snd_pcm_mmap_control(struct snd_pcm_substream *substream, struct file area->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP; return 0; } + +static bool pcm_status_mmap_allowed(struct snd_pcm_file *pcm_file) +{ + if (pcm_file->no_compat_mmap) + return false; + /* See pcm_control_mmap_allowed() below. + * Since older alsa-lib requires both status and control mmaps to be + * coupled, we have to disable the status mmap for old alsa-lib, too. + */ + if (pcm_file->user_pversion < SNDRV_PROTOCOL_VERSION(2, 0, 14) && + (pcm_file->substream->runtime->hw.info & SNDRV_PCM_INFO_SYNC_APPLPTR)) + return false; + return true; +} + +static bool pcm_control_mmap_allowed(struct snd_pcm_file *pcm_file) +{ + if (pcm_file->no_compat_mmap) + return false; + /* Disallow the control mmap when SYNC_APPLPTR flag is set; + * it enforces the user-space to fall back to snd_pcm_sync_ptr(), + * thus it effectively assures the manual update of appl_ptr. + */ + if (pcm_file->substream->runtime->hw.info & SNDRV_PCM_INFO_SYNC_APPLPTR) + return false; + return true; +} + #else /* ! coherent mmap */ /* * don't support mmap for status and control records. */ +#define pcm_status_mmap_allowed(pcm_file) false +#define pcm_control_mmap_allowed(pcm_file) false + static int snd_pcm_mmap_status(struct snd_pcm_substream *substream, struct file *file, struct vm_area_struct *area) { @@ -3402,7 +3500,7 @@ int snd_pcm_lib_default_mmap(struct snd_pcm_substream *substream, } #endif /* CONFIG_GENERIC_ALLOCATOR */ #ifndef CONFIG_X86 /* for avoiding warnings arch/x86/mm/pat.c */ - if (!substream->ops->page && + if (IS_ENABLED(CONFIG_HAS_DMA) && !substream->ops->page && substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV) return dma_mmap_coherent(substream->dma_buffer.dev.dev, area, @@ -3437,7 +3535,6 @@ int snd_pcm_lib_mmap_iomem(struct snd_pcm_substream *substream, area->vm_page_prot = pgprot_noncached(area->vm_page_prot); return vm_iomap_memory(area, runtime->dma_addr, runtime->dma_bytes); } - EXPORT_SYMBOL(snd_pcm_lib_mmap_iomem); #endif /* SNDRV_PCM_INFO_MMAP */ @@ -3486,7 +3583,6 @@ int snd_pcm_mmap_data(struct snd_pcm_substream *substream, struct file *file, atomic_inc(&substream->mmap_count); return err; } - EXPORT_SYMBOL(snd_pcm_mmap_data); static int snd_pcm_mmap(struct file *file, struct vm_area_struct *area) @@ -3503,11 +3599,11 @@ static int snd_pcm_mmap(struct file *file, struct vm_area_struct *area) offset = area->vm_pgoff << PAGE_SHIFT; switch (offset) { case SNDRV_PCM_MMAP_OFFSET_STATUS: - if (pcm_file->no_compat_mmap) + if (!pcm_status_mmap_allowed(pcm_file)) return -ENXIO; return snd_pcm_mmap_status(substream, file, area); case SNDRV_PCM_MMAP_OFFSET_CONTROL: - if (pcm_file->no_compat_mmap) + if (!pcm_control_mmap_allowed(pcm_file)) return -ENXIO; return snd_pcm_mmap_control(substream, file, area); default: @@ -3603,12 +3699,17 @@ static int snd_pcm_hw_refine_old_user(struct snd_pcm_substream *substream, } snd_pcm_hw_convert_from_old_params(params, oparams); err = snd_pcm_hw_refine(substream, params); - snd_pcm_hw_convert_to_old_params(oparams, params); - if (copy_to_user(_oparams, oparams, sizeof(*oparams))) { - if (!err) - err = -EFAULT; - } + if (err < 0) + goto out_old; + err = fixup_unreferenced_params(substream, params); + if (err < 0) + goto out_old; + + snd_pcm_hw_convert_to_old_params(oparams, params); + if (copy_to_user(_oparams, oparams, sizeof(*oparams))) + err = -EFAULT; +out_old: kfree(oparams); out: kfree(params); @@ -3631,14 +3732,16 @@ static int snd_pcm_hw_params_old_user(struct snd_pcm_substream *substream, err = PTR_ERR(oparams); goto out; } + snd_pcm_hw_convert_from_old_params(params, oparams); err = snd_pcm_hw_params(substream, params); - snd_pcm_hw_convert_to_old_params(oparams, params); - if (copy_to_user(_oparams, oparams, sizeof(*oparams))) { - if (!err) - err = -EFAULT; - } + if (err < 0) + goto out_old; + snd_pcm_hw_convert_to_old_params(oparams, params); + if (copy_to_user(_oparams, oparams, sizeof(*oparams))) + err = -EFAULT; +out_old: kfree(oparams); out: kfree(params); diff --git a/sound/core/pcm_param_trace.h b/sound/core/pcm_param_trace.h new file mode 100644 index 000000000000..86c8d658a25c --- /dev/null +++ b/sound/core/pcm_param_trace.h @@ -0,0 +1,142 @@ +#undef TRACE_SYSTEM +#define TRACE_SYSTEM snd_pcm + +#if !defined(_PCM_PARAMS_TRACE_H) || defined(TRACE_HEADER_MULTI_READ) +#define _PCM_PARAMS_TRACE_H + +#include <linux/tracepoint.h> + +#define HW_PARAM_ENTRY(param) {SNDRV_PCM_HW_PARAM_##param, #param} +#define hw_param_labels \ + HW_PARAM_ENTRY(ACCESS), \ + HW_PARAM_ENTRY(FORMAT), \ + HW_PARAM_ENTRY(SUBFORMAT), \ + HW_PARAM_ENTRY(SAMPLE_BITS), \ + HW_PARAM_ENTRY(FRAME_BITS), \ + HW_PARAM_ENTRY(CHANNELS), \ + HW_PARAM_ENTRY(RATE), \ + HW_PARAM_ENTRY(PERIOD_TIME), \ + HW_PARAM_ENTRY(PERIOD_SIZE), \ + HW_PARAM_ENTRY(PERIOD_BYTES), \ + HW_PARAM_ENTRY(PERIODS), \ + HW_PARAM_ENTRY(BUFFER_TIME), \ + HW_PARAM_ENTRY(BUFFER_SIZE), \ + HW_PARAM_ENTRY(BUFFER_BYTES), \ + HW_PARAM_ENTRY(TICK_TIME) + +TRACE_EVENT(hw_mask_param, + TP_PROTO(struct snd_pcm_substream *substream, snd_pcm_hw_param_t type, int index, const struct snd_mask *prev, const struct snd_mask *curr), + TP_ARGS(substream, type, index, prev, curr), + TP_STRUCT__entry( + __field(int, card) + __field(int, device) + __field(int, subdevice) + __field(int, direction) + __field(snd_pcm_hw_param_t, type) + __field(int, index) + __field(int, total) + __array(__u32, prev_bits, 8) + __array(__u32, curr_bits, 8) + ), + TP_fast_assign( + __entry->card = substream->pcm->card->number; + __entry->device = substream->pcm->device; + __entry->subdevice = substream->number; + __entry->direction = substream->stream; + __entry->type = type; + __entry->index = index; + __entry->total = substream->runtime->hw_constraints.rules_num; + memcpy(__entry->prev_bits, prev->bits, sizeof(__u32) * 8); + memcpy(__entry->curr_bits, curr->bits, sizeof(__u32) * 8); + ), + TP_printk("pcmC%dD%d%s:%d %03d/%03d %s %08x%08x%08x%08x %08x%08x%08x%08x", + __entry->card, + __entry->device, + __entry->direction ? "c" : "p", + __entry->subdevice, + __entry->index, + __entry->total, + __print_symbolic(__entry->type, hw_param_labels), + __entry->prev_bits[3], __entry->prev_bits[2], + __entry->prev_bits[1], __entry->prev_bits[0], + __entry->curr_bits[3], __entry->curr_bits[2], + __entry->curr_bits[1], __entry->curr_bits[0] + ) +); + +TRACE_EVENT(hw_interval_param, + TP_PROTO(struct snd_pcm_substream *substream, snd_pcm_hw_param_t type, int index, const struct snd_interval *prev, const struct snd_interval *curr), + TP_ARGS(substream, type, index, prev, curr), + TP_STRUCT__entry( + __field(int, card) + __field(int, device) + __field(int, subdevice) + __field(int, direction) + __field(snd_pcm_hw_param_t, type) + __field(int, index) + __field(int, total) + __field(unsigned int, prev_min) + __field(unsigned int, prev_max) + __field(unsigned int, prev_openmin) + __field(unsigned int, prev_openmax) + __field(unsigned int, prev_integer) + __field(unsigned int, prev_empty) + __field(unsigned int, curr_min) + __field(unsigned int, curr_max) + __field(unsigned int, curr_openmin) + __field(unsigned int, curr_openmax) + __field(unsigned int, curr_integer) + __field(unsigned int, curr_empty) + ), + TP_fast_assign( + __entry->card = substream->pcm->card->number; + __entry->device = substream->pcm->device; + __entry->subdevice = substream->number; + __entry->direction = substream->stream; + __entry->type = type; + __entry->index = index; + __entry->total = substream->runtime->hw_constraints.rules_num; + __entry->prev_min = prev->min; + __entry->prev_max = prev->max; + __entry->prev_openmin = prev->openmin; + __entry->prev_openmax = prev->openmax; + __entry->prev_integer = prev->integer; + __entry->prev_empty = prev->empty; + __entry->curr_min = curr->min; + __entry->curr_max = curr->max; + __entry->curr_openmin = curr->openmin; + __entry->curr_openmax = curr->openmax; + __entry->curr_integer = curr->integer; + __entry->curr_empty = curr->empty; + ), + TP_printk("pcmC%dD%d%s:%d %03d/%03d %s %d %d %s%u %u%s %d %d %s%u %u%s", + __entry->card, + __entry->device, + __entry->direction ? "c" : "p", + __entry->subdevice, + __entry->index, + __entry->total, + __print_symbolic(__entry->type, hw_param_labels), + __entry->prev_empty, + __entry->prev_integer, + __entry->prev_openmin ? "(" : "[", + __entry->prev_min, + __entry->prev_max, + __entry->prev_openmax ? ")" : "]", + __entry->curr_empty, + __entry->curr_integer, + __entry->curr_openmin ? "(" : "[", + __entry->curr_min, + __entry->curr_max, + __entry->curr_openmax ? ")" : "]" + ) +); + +#endif /* _PCM_PARAMS_TRACE_H */ + +/* This part must be outside protection */ +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH . +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_FILE pcm_param_trace +#include <trace/define_trace.h> diff --git a/sound/core/pcm_timer.c b/sound/core/pcm_timer.c index 20ecd8f18080..11389f13de73 100644 --- a/sound/core/pcm_timer.c +++ b/sound/core/pcm_timer.c @@ -25,6 +25,8 @@ #include <sound/pcm.h> #include <sound/timer.h> +#include "pcm_local.h" + /* * Timer functions */ @@ -33,8 +35,8 @@ void snd_pcm_timer_resolution_change(struct snd_pcm_substream *substream) { unsigned long rate, mult, fsize, l, post; struct snd_pcm_runtime *runtime = substream->runtime; - - mult = 1000000000; + + mult = 1000000000; rate = runtime->rate; if (snd_BUG_ON(!rate)) return; @@ -65,7 +67,7 @@ void snd_pcm_timer_resolution_change(struct snd_pcm_substream *substream) static unsigned long snd_pcm_timer_resolution(struct snd_timer * timer) { struct snd_pcm_substream *substream; - + substream = timer->private_data; return substream->runtime ? substream->runtime->timer_resolution : 0; } @@ -73,7 +75,7 @@ static unsigned long snd_pcm_timer_resolution(struct snd_timer * timer) static int snd_pcm_timer_start(struct snd_timer * timer) { struct snd_pcm_substream *substream; - + substream = snd_timer_chip(timer); substream->timer_running = 1; return 0; @@ -82,7 +84,7 @@ static int snd_pcm_timer_start(struct snd_timer * timer) static int snd_pcm_timer_stop(struct snd_timer * timer) { struct snd_pcm_substream *substream; - + substream = snd_timer_chip(timer); substream->timer_running = 0; return 0; @@ -112,7 +114,7 @@ void snd_pcm_timer_init(struct snd_pcm_substream *substream) { struct snd_timer_id tid; struct snd_timer *timer; - + tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE; tid.dev_class = SNDRV_TIMER_CLASS_PCM; tid.card = substream->pcm->card->number; diff --git a/sound/core/pcm_trace.h b/sound/core/pcm_trace.h index b63b654da5ff..3ddec1b8ae46 100644 --- a/sound/core/pcm_trace.h +++ b/sound/core/pcm_trace.h @@ -34,9 +34,9 @@ TRACE_EVENT(hwptr, __entry->old_hw_ptr = (substream)->runtime->status->hw_ptr; __entry->hw_ptr_base = (substream)->runtime->hw_ptr_base; ), - TP_printk("pcmC%dD%d%c/sub%d: %s: pos=%lu, old=%lu, base=%lu, period=%lu, buf=%lu", + TP_printk("pcmC%dD%d%s/sub%d: %s: pos=%lu, old=%lu, base=%lu, period=%lu, buf=%lu", __entry->card, __entry->device, - __entry->stream == SNDRV_PCM_STREAM_PLAYBACK ? 'p' : 'c', + __entry->stream == SNDRV_PCM_STREAM_PLAYBACK ? "p" : "c", __entry->number, __entry->in_interrupt ? "IRQ" : "POS", (unsigned long)__entry->pos, @@ -69,9 +69,9 @@ TRACE_EVENT(xrun, __entry->old_hw_ptr = (substream)->runtime->status->hw_ptr; __entry->hw_ptr_base = (substream)->runtime->hw_ptr_base; ), - TP_printk("pcmC%dD%d%c/sub%d: XRUN: old=%lu, base=%lu, period=%lu, buf=%lu", + TP_printk("pcmC%dD%d%s/sub%d: XRUN: old=%lu, base=%lu, period=%lu, buf=%lu", __entry->card, __entry->device, - __entry->stream == SNDRV_PCM_STREAM_PLAYBACK ? 'p' : 'c', + __entry->stream == SNDRV_PCM_STREAM_PLAYBACK ? "p" : "c", __entry->number, (unsigned long)__entry->old_hw_ptr, (unsigned long)__entry->hw_ptr_base, @@ -96,12 +96,50 @@ TRACE_EVENT(hw_ptr_error, __entry->stream = (substream)->stream; __entry->reason = (why); ), - TP_printk("pcmC%dD%d%c/sub%d: ERROR: %s", + TP_printk("pcmC%dD%d%s/sub%d: ERROR: %s", __entry->card, __entry->device, - __entry->stream == SNDRV_PCM_STREAM_PLAYBACK ? 'p' : 'c', + __entry->stream == SNDRV_PCM_STREAM_PLAYBACK ? "p" : "c", __entry->number, __entry->reason) ); +TRACE_EVENT(applptr, + TP_PROTO(struct snd_pcm_substream *substream, snd_pcm_uframes_t prev, snd_pcm_uframes_t curr), + TP_ARGS(substream, prev, curr), + TP_STRUCT__entry( + __field( unsigned int, card ) + __field( unsigned int, device ) + __field( unsigned int, number ) + __field( unsigned int, stream ) + __field( snd_pcm_uframes_t, prev ) + __field( snd_pcm_uframes_t, curr ) + __field( snd_pcm_uframes_t, avail ) + __field( snd_pcm_uframes_t, period_size ) + __field( snd_pcm_uframes_t, buffer_size ) + ), + TP_fast_assign( + __entry->card = (substream)->pcm->card->number; + __entry->device = (substream)->pcm->device; + __entry->number = (substream)->number; + __entry->stream = (substream)->stream; + __entry->prev = (prev); + __entry->curr = (curr); + __entry->avail = (substream)->stream ? snd_pcm_capture_avail(substream->runtime) : snd_pcm_playback_avail(substream->runtime); + __entry->period_size = (substream)->runtime->period_size; + __entry->buffer_size = (substream)->runtime->buffer_size; + ), + TP_printk("pcmC%dD%d%s/sub%d: prev=%lu, curr=%lu, avail=%lu, period=%lu, buf=%lu", + __entry->card, + __entry->device, + __entry->stream ? "c" : "p", + __entry->number, + __entry->prev, + __entry->curr, + __entry->avail, + __entry->period_size, + __entry->buffer_size + ) +); + #endif /* _PCM_TRACE_H */ /* This part must be outside protection */ diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index ab890336175f..b3b353d72527 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c @@ -368,7 +368,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) int err; struct snd_rawmidi *rmidi; struct snd_rawmidi_file *rawmidi_file = NULL; - wait_queue_t wait; + wait_queue_entry_t wait; if ((file->f_flags & O_APPEND) && !(file->f_flags & O_NONBLOCK)) return -EINVAL; /* invalid combination */ @@ -1002,7 +1002,7 @@ static ssize_t snd_rawmidi_read(struct file *file, char __user *buf, size_t coun while (count > 0) { spin_lock_irq(&runtime->lock); while (!snd_rawmidi_ready(substream)) { - wait_queue_t wait; + wait_queue_entry_t wait; if ((file->f_flags & O_NONBLOCK) != 0 || result > 0) { spin_unlock_irq(&runtime->lock); return result > 0 ? result : -EAGAIN; @@ -1306,7 +1306,7 @@ static ssize_t snd_rawmidi_write(struct file *file, const char __user *buf, while (count > 0) { spin_lock_irq(&runtime->lock); while (!snd_rawmidi_ready_append(substream, count)) { - wait_queue_t wait; + wait_queue_entry_t wait; if (file->f_flags & O_NONBLOCK) { spin_unlock_irq(&runtime->lock); return result > 0 ? result : -EAGAIN; @@ -1338,7 +1338,7 @@ static ssize_t snd_rawmidi_write(struct file *file, const char __user *buf, if (file->f_flags & O_DSYNC) { spin_lock_irq(&runtime->lock); while (runtime->avail != runtime->buffer_size) { - wait_queue_t wait; + wait_queue_entry_t wait; unsigned int last_avail = runtime->avail; init_waitqueue_entry(&wait, current); add_wait_queue(&runtime->sleep, &wait); @@ -1610,7 +1610,7 @@ static int snd_rawmidi_dev_free(struct snd_device *device) return snd_rawmidi_free(rmidi); } -#if IS_REACHABLE(CONFIG_SND_SEQUENCER) +#if IS_ENABLED(CONFIG_SND_SEQUENCER) static void snd_rawmidi_dev_seq_free(struct snd_seq_device *device) { struct snd_rawmidi *rmidi = device->private_data; @@ -1691,7 +1691,7 @@ static int snd_rawmidi_dev_register(struct snd_device *device) } } rmidi->proc_entry = entry; -#if IS_REACHABLE(CONFIG_SND_SEQUENCER) +#if IS_ENABLED(CONFIG_SND_SEQUENCER) if (!rmidi->ops || !rmidi->ops->dev_register) { /* own registration mechanism */ if (snd_seq_device_new(rmidi->card, rmidi->device, SNDRV_SEQ_DEV_ID_MIDISYNTH, 0, &rmidi->seq_dev) >= 0) { rmidi->seq_dev->private_data = rmidi; diff --git a/sound/core/seq/Kconfig b/sound/core/seq/Kconfig index b851fd890a89..a536760a94c2 100644 --- a/sound/core/seq/Kconfig +++ b/sound/core/seq/Kconfig @@ -1,16 +1,62 @@ -# define SND_XXX_SEQ to min(SND_SEQUENCER,SND_XXX) +config SND_SEQUENCER + tristate "Sequencer support" + select SND_TIMER + select SND_SEQ_DEVICE + help + Say Y or M to enable MIDI sequencer and router support. This + feature allows routing and enqueueing of MIDI events. Events + can be processed at a given time. -config SND_RAWMIDI_SEQ - def_tristate SND_SEQUENCER && SND_RAWMIDI + Many programs require this feature, so you should enable it + unless you know what you're doing. -config SND_OPL3_LIB_SEQ - def_tristate SND_SEQUENCER && SND_OPL3_LIB +if SND_SEQUENCER -config SND_OPL4_LIB_SEQ - def_tristate SND_SEQUENCER && SND_OPL4_LIB +config SND_SEQ_DUMMY + tristate "Sequencer dummy client" + help + Say Y here to enable the dummy sequencer client. This client + is a simple MIDI-through client: all normal input events are + redirected to the output port immediately. -config SND_SBAWE_SEQ - def_tristate SND_SEQUENCER && SND_SBAWE + You don't need this unless you want to connect many MIDI + devices or applications together. -config SND_EMU10K1_SEQ - def_tristate SND_SEQUENCER && SND_EMU10K1 + To compile this driver as a module, choose M here: the module + will be called snd-seq-dummy. + +config SND_SEQUENCER_OSS + tristate "OSS Sequencer API" + depends on SND_OSSEMUL + select SND_SEQ_MIDI_EVENT + help + Say Y here to enable OSS sequencer emulation (both + /dev/sequencer and /dev/music interfaces). + + Many programs still use the OSS API, so say Y. + + To compile this driver as a module, choose M here: the module + will be called snd-seq-oss. + +config SND_SEQ_HRTIMER_DEFAULT + bool "Use HR-timer as default sequencer timer" + depends on SND_HRTIMER + default y + help + Say Y here to use the HR-timer backend as the default sequencer + timer. + +config SND_SEQ_MIDI_EVENT + def_tristate SND_RAWMIDI + +config SND_SEQ_MIDI + tristate + select SND_SEQ_MIDI_EVENT + +config SND_SEQ_MIDI_EMUL + tristate + +config SND_SEQ_VIRMIDI + tristate + +endif # SND_SEQUENCER diff --git a/sound/core/seq/Makefile b/sound/core/seq/Makefile index b65fa5a1943b..68fd367ac39c 100644 --- a/sound/core/seq/Makefile +++ b/sound/core/seq/Makefile @@ -3,7 +3,6 @@ # Copyright (c) 1999 by Jaroslav Kysela <perex@perex.cz> # -snd-seq-device-objs := seq_device.o snd-seq-objs := seq.o seq_lock.o seq_clientmgr.o seq_memory.o seq_queue.o \ seq_fifo.o seq_prioq.o seq_timer.o \ seq_system.o seq_ports.o @@ -14,17 +13,11 @@ snd-seq-midi-event-objs := seq_midi_event.o snd-seq-dummy-objs := seq_dummy.o snd-seq-virmidi-objs := seq_virmidi.o -obj-$(CONFIG_SND_SEQUENCER) += snd-seq.o snd-seq-device.o -ifeq ($(CONFIG_SND_SEQUENCER_OSS),y) - obj-$(CONFIG_SND_SEQUENCER) += snd-seq-midi-event.o - obj-$(CONFIG_SND_SEQUENCER) += oss/ -endif -obj-$(CONFIG_SND_SEQ_DUMMY) += snd-seq-dummy.o +obj-$(CONFIG_SND_SEQUENCER) += snd-seq.o +obj-$(CONFIG_SND_SEQUENCER_OSS) += oss/ -# Toplevel Module Dependency -obj-$(CONFIG_SND_VIRMIDI) += snd-seq-virmidi.o snd-seq-midi-event.o -obj-$(CONFIG_SND_RAWMIDI_SEQ) += snd-seq-midi.o snd-seq-midi-event.o -obj-$(CONFIG_SND_OPL3_LIB_SEQ) += snd-seq-midi-event.o snd-seq-midi-emul.o -obj-$(CONFIG_SND_OPL4_LIB_SEQ) += snd-seq-midi-event.o snd-seq-midi-emul.o -obj-$(CONFIG_SND_SBAWE_SEQ) += snd-seq-midi-emul.o snd-seq-virmidi.o -obj-$(CONFIG_SND_EMU10K1_SEQ) += snd-seq-midi-emul.o snd-seq-virmidi.o +obj-$(CONFIG_SND_SEQ_DUMMY) += snd-seq-dummy.o +obj-$(CONFIG_SND_SEQ_MIDI) += snd-seq-midi.o +obj-$(CONFIG_SND_SEQ_MIDI_EMUL) += snd-seq-midi-emul.o +obj-$(CONFIG_SND_SEQ_MIDI_EVENT) += snd-seq-midi-event.o +obj-$(CONFIG_SND_SEQ_VIRMIDI) += snd-seq-virmidi.o diff --git a/sound/core/seq/oss/Makefile b/sound/core/seq/oss/Makefile index b38406b8463c..4ea4e3eea6b7 100644 --- a/sound/core/seq/oss/Makefile +++ b/sound/core/seq/oss/Makefile @@ -7,4 +7,4 @@ snd-seq-oss-objs := seq_oss.o seq_oss_init.o seq_oss_timer.o seq_oss_ioctl.o \ seq_oss_event.o seq_oss_rw.o seq_oss_synth.o \ seq_oss_midi.o seq_oss_readq.o seq_oss_writeq.o -obj-$(CONFIG_SND_SEQUENCER) += snd-seq-oss.o +obj-$(CONFIG_SND_SEQUENCER_OSS) += snd-seq-oss.o diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index f3b1d7f50b81..272c55fe17c8 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -1668,7 +1668,6 @@ int snd_seq_set_queue_tempo(int client, struct snd_seq_queue_tempo *tempo) return -EPERM; return snd_seq_queue_timer_set_tempo(tempo->queue, client, tempo); } - EXPORT_SYMBOL(snd_seq_set_queue_tempo); static int snd_seq_ioctl_set_queue_tempo(struct snd_seq_client *client, @@ -2200,7 +2199,6 @@ int snd_seq_create_kernel_client(struct snd_card *card, int client_index, /* return client number to caller */ return client->number; } - EXPORT_SYMBOL(snd_seq_create_kernel_client); /* exported to kernel modules */ @@ -2219,7 +2217,6 @@ int snd_seq_delete_kernel_client(int client) kfree(ptr); return 0; } - EXPORT_SYMBOL(snd_seq_delete_kernel_client); /* skeleton to enqueue event, called from snd_seq_kernel_client_enqueue @@ -2269,7 +2266,6 @@ int snd_seq_kernel_client_enqueue(int client, struct snd_seq_event * ev, { return kernel_client_enqueue(client, ev, NULL, 0, atomic, hop); } - EXPORT_SYMBOL(snd_seq_kernel_client_enqueue); /* @@ -2283,7 +2279,6 @@ int snd_seq_kernel_client_enqueue_blocking(int client, struct snd_seq_event * ev { return kernel_client_enqueue(client, ev, file, 1, atomic, hop); } - EXPORT_SYMBOL(snd_seq_kernel_client_enqueue_blocking); /* @@ -2321,7 +2316,6 @@ int snd_seq_kernel_client_dispatch(int client, struct snd_seq_event * ev, snd_seq_client_unlock(cptr); return result; } - EXPORT_SYMBOL(snd_seq_kernel_client_dispatch); /** @@ -2354,7 +2348,6 @@ int snd_seq_kernel_client_ctl(int clientid, unsigned int cmd, void *arg) cmd, _IOC_TYPE(cmd), _IOC_NR(cmd)); return -ENOTTY; } - EXPORT_SYMBOL(snd_seq_kernel_client_ctl); /* exported (for OSS emulator) */ @@ -2372,7 +2365,6 @@ int snd_seq_kernel_client_write_poll(int clientid, struct file *file, poll_table return 1; return 0; } - EXPORT_SYMBOL(snd_seq_kernel_client_write_poll); /*---------------------------------------------------------------------------*/ diff --git a/sound/core/seq/seq_fifo.c b/sound/core/seq/seq_fifo.c index 01c4cfe30c9f..a8c2822e0198 100644 --- a/sound/core/seq/seq_fifo.c +++ b/sound/core/seq/seq_fifo.c @@ -179,7 +179,7 @@ int snd_seq_fifo_cell_out(struct snd_seq_fifo *f, { struct snd_seq_event_cell *cell; unsigned long flags; - wait_queue_t wait; + wait_queue_entry_t wait; if (snd_BUG_ON(!f)) return -EINVAL; diff --git a/sound/core/seq/seq_lock.c b/sound/core/seq/seq_lock.c index 12ba83367b1b..0ff7926a5a69 100644 --- a/sound/core/seq/seq_lock.c +++ b/sound/core/seq/seq_lock.c @@ -40,7 +40,6 @@ void snd_use_lock_sync_helper(snd_use_lock_t *lockp, const char *file, int line) schedule_timeout_uninterruptible(1); } } - EXPORT_SYMBOL(snd_use_lock_sync_helper); #endif diff --git a/sound/core/seq/seq_memory.c b/sound/core/seq/seq_memory.c index d4c61ec9be13..f763682584a8 100644 --- a/sound/core/seq/seq_memory.c +++ b/sound/core/seq/seq_memory.c @@ -118,7 +118,6 @@ int snd_seq_dump_var_event(const struct snd_seq_event *event, } return 0; } - EXPORT_SYMBOL(snd_seq_dump_var_event); @@ -169,7 +168,6 @@ int snd_seq_expand_var_event(const struct snd_seq_event *event, int count, char &buf); return err < 0 ? err : newlen; } - EXPORT_SYMBOL(snd_seq_expand_var_event); /* @@ -227,7 +225,7 @@ static int snd_seq_cell_alloc(struct snd_seq_pool *pool, struct snd_seq_event_cell *cell; unsigned long flags; int err = -EAGAIN; - wait_queue_t wait; + wait_queue_entry_t wait; if (pool == NULL) return -EINVAL; diff --git a/sound/core/seq/seq_midi_emul.c b/sound/core/seq/seq_midi_emul.c index 7ba937399ac7..9e2912e3e80f 100644 --- a/sound/core/seq/seq_midi_emul.c +++ b/sound/core/seq/seq_midi_emul.c @@ -236,6 +236,7 @@ snd_midi_process_event(struct snd_midi_op *ops, break; } } +EXPORT_SYMBOL(snd_midi_process_event); /* @@ -409,6 +410,7 @@ snd_midi_channel_set_clear(struct snd_midi_channel_set *chset) chan->drum_channel = 0; } } +EXPORT_SYMBOL(snd_midi_channel_set_clear); /* * Process a rpn message. @@ -701,6 +703,7 @@ struct snd_midi_channel_set *snd_midi_channel_alloc_set(int n) } return chset; } +EXPORT_SYMBOL(snd_midi_channel_alloc_set); /* * Reset the midi controllers on a particular channel to default values. @@ -724,6 +727,7 @@ void snd_midi_channel_free_set(struct snd_midi_channel_set *chset) kfree(chset->channels); kfree(chset); } +EXPORT_SYMBOL(snd_midi_channel_free_set); static int __init alsa_seq_midi_emul_init(void) { @@ -736,8 +740,3 @@ static void __exit alsa_seq_midi_emul_exit(void) module_init(alsa_seq_midi_emul_init) module_exit(alsa_seq_midi_emul_exit) - -EXPORT_SYMBOL(snd_midi_process_event); -EXPORT_SYMBOL(snd_midi_channel_set_clear); -EXPORT_SYMBOL(snd_midi_channel_alloc_set); -EXPORT_SYMBOL(snd_midi_channel_free_set); diff --git a/sound/core/seq/seq_midi_event.c b/sound/core/seq/seq_midi_event.c index 37db7ba492a6..90bbbdbeba03 100644 --- a/sound/core/seq/seq_midi_event.c +++ b/sound/core/seq/seq_midi_event.c @@ -134,6 +134,7 @@ int snd_midi_event_new(int bufsize, struct snd_midi_event **rdev) *rdev = dev; return 0; } +EXPORT_SYMBOL(snd_midi_event_new); void snd_midi_event_free(struct snd_midi_event *dev) { @@ -142,6 +143,7 @@ void snd_midi_event_free(struct snd_midi_event *dev) kfree(dev); } } +EXPORT_SYMBOL(snd_midi_event_free); /* * initialize record @@ -161,6 +163,7 @@ void snd_midi_event_reset_encode(struct snd_midi_event *dev) reset_encode(dev); spin_unlock_irqrestore(&dev->lock, flags); } +EXPORT_SYMBOL(snd_midi_event_reset_encode); void snd_midi_event_reset_decode(struct snd_midi_event *dev) { @@ -170,6 +173,7 @@ void snd_midi_event_reset_decode(struct snd_midi_event *dev) dev->lastcmd = 0xff; spin_unlock_irqrestore(&dev->lock, flags); } +EXPORT_SYMBOL(snd_midi_event_reset_decode); #if 0 void snd_midi_event_init(struct snd_midi_event *dev) @@ -183,6 +187,7 @@ void snd_midi_event_no_status(struct snd_midi_event *dev, int on) { dev->nostat = on ? 1 : 0; } +EXPORT_SYMBOL(snd_midi_event_no_status); /* * resize buffer @@ -232,6 +237,7 @@ long snd_midi_event_encode(struct snd_midi_event *dev, unsigned char *buf, long return result; } +EXPORT_SYMBOL(snd_midi_event_encode); /* * read one byte and encode to sequencer event: @@ -307,6 +313,7 @@ int snd_midi_event_encode_byte(struct snd_midi_event *dev, int c, spin_unlock_irqrestore(&dev->lock, flags); return rc; } +EXPORT_SYMBOL(snd_midi_event_encode_byte); /* encode note event */ static void note_event(struct snd_midi_event *dev, struct snd_seq_event *ev) @@ -408,6 +415,7 @@ long snd_midi_event_decode(struct snd_midi_event *dev, unsigned char *buf, long return qlen; } } +EXPORT_SYMBOL(snd_midi_event_decode); /* decode note event */ @@ -524,19 +532,6 @@ static int extra_decode_xrpn(struct snd_midi_event *dev, unsigned char *buf, return idx; } -/* - * exports - */ - -EXPORT_SYMBOL(snd_midi_event_new); -EXPORT_SYMBOL(snd_midi_event_free); -EXPORT_SYMBOL(snd_midi_event_reset_encode); -EXPORT_SYMBOL(snd_midi_event_reset_decode); -EXPORT_SYMBOL(snd_midi_event_no_status); -EXPORT_SYMBOL(snd_midi_event_encode); -EXPORT_SYMBOL(snd_midi_event_encode_byte); -EXPORT_SYMBOL(snd_midi_event_decode); - static int __init alsa_seq_midi_event_init(void) { return 0; diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c index fe686ee41c6d..0a7020c82bfc 100644 --- a/sound/core/seq/seq_ports.c +++ b/sound/core/seq/seq_ports.c @@ -685,7 +685,6 @@ int snd_seq_event_port_attach(int client, return ret; } - EXPORT_SYMBOL(snd_seq_event_port_attach); /* @@ -706,5 +705,4 @@ int snd_seq_event_port_detach(int client, int port) return err; } - EXPORT_SYMBOL(snd_seq_event_port_detach); diff --git a/sound/core/seq/seq_virmidi.c b/sound/core/seq/seq_virmidi.c index 52f31f1498f9..8d93a4021c78 100644 --- a/sound/core/seq/seq_virmidi.c +++ b/sound/core/seq/seq_virmidi.c @@ -534,6 +534,7 @@ int snd_virmidi_new(struct snd_card *card, int device, struct snd_rawmidi **rrmi *rrmidi = rmidi; return 0; } +EXPORT_SYMBOL(snd_virmidi_new); /* * ENTRY functions @@ -550,5 +551,3 @@ static void __exit alsa_virmidi_exit(void) module_init(alsa_virmidi_init) module_exit(alsa_virmidi_exit) - -EXPORT_SYMBOL(snd_virmidi_new); diff --git a/sound/core/seq/seq_device.c b/sound/core/seq_device.c index c4acf17e9f5e..c4acf17e9f5e 100644 --- a/sound/core/seq/seq_device.c +++ b/sound/core/seq_device.c diff --git a/sound/core/sound.c b/sound/core/sound.c index 175f9e4e01c8..b30f027eb0fe 100644 --- a/sound/core/sound.c +++ b/sound/core/sound.c @@ -74,7 +74,6 @@ void snd_request_card(int card) return; request_module("snd-card-%i", card); } - EXPORT_SYMBOL(snd_request_card); static void snd_request_other(int minor) @@ -124,7 +123,6 @@ void *snd_lookup_minor_data(unsigned int minor, int type) mutex_unlock(&sound_mutex); return private_data; } - EXPORT_SYMBOL(snd_lookup_minor_data); #ifdef CONFIG_MODULES diff --git a/sound/core/sound_oss.c b/sound/core/sound_oss.c index 0ca9d72b2273..0a5c66229a22 100644 --- a/sound/core/sound_oss.c +++ b/sound/core/sound_oss.c @@ -55,7 +55,6 @@ void *snd_lookup_oss_minor_data(unsigned int minor, int type) mutex_unlock(&sound_oss_mutex); return private_data; } - EXPORT_SYMBOL(snd_lookup_oss_minor_data); static int snd_oss_kernel_minor(int type, struct snd_card *card, int dev) @@ -159,7 +158,6 @@ int snd_register_oss_device(int type, struct snd_card *card, int dev, kfree(preg); return -EBUSY; } - EXPORT_SYMBOL(snd_register_oss_device); int snd_unregister_oss_device(int type, struct snd_card *card, int dev) @@ -200,7 +198,6 @@ int snd_unregister_oss_device(int type, struct snd_card *card, int dev) kfree(mptr); return 0; } - EXPORT_SYMBOL(snd_unregister_oss_device); /* diff --git a/sound/core/timer.c b/sound/core/timer.c index cd67d1c12cf1..a9b9a277e00c 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -319,6 +319,7 @@ int snd_timer_open(struct snd_timer_instance **ti, *ti = timeri; return 0; } +EXPORT_SYMBOL(snd_timer_open); /* * close a timer instance @@ -384,6 +385,7 @@ int snd_timer_close(struct snd_timer_instance *timeri) mutex_unlock(®ister_mutex); return 0; } +EXPORT_SYMBOL(snd_timer_close); unsigned long snd_timer_resolution(struct snd_timer_instance *timeri) { @@ -398,6 +400,7 @@ unsigned long snd_timer_resolution(struct snd_timer_instance *timeri) } return 0; } +EXPORT_SYMBOL(snd_timer_resolution); static void snd_timer_notify1(struct snd_timer_instance *ti, int event) { @@ -589,6 +592,7 @@ int snd_timer_start(struct snd_timer_instance *timeri, unsigned int ticks) else return snd_timer_start1(timeri, true, ticks); } +EXPORT_SYMBOL(snd_timer_start); /* * stop the timer instance. @@ -602,6 +606,7 @@ int snd_timer_stop(struct snd_timer_instance *timeri) else return snd_timer_stop1(timeri, true); } +EXPORT_SYMBOL(snd_timer_stop); /* * start again.. the tick is kept. @@ -617,6 +622,7 @@ int snd_timer_continue(struct snd_timer_instance *timeri) else return snd_timer_start1(timeri, false, 0); } +EXPORT_SYMBOL(snd_timer_continue); /* * pause.. remember the ticks left @@ -628,6 +634,7 @@ int snd_timer_pause(struct snd_timer_instance * timeri) else return snd_timer_stop1(timeri, false); } +EXPORT_SYMBOL(snd_timer_pause); /* * reschedule the timer @@ -809,6 +816,7 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left) if (use_tasklet) tasklet_schedule(&timer->task_queue); } +EXPORT_SYMBOL(snd_timer_interrupt); /* @@ -859,6 +867,7 @@ int snd_timer_new(struct snd_card *card, char *id, struct snd_timer_id *tid, *rtimer = timer; return 0; } +EXPORT_SYMBOL(snd_timer_new); static int snd_timer_free(struct snd_timer *timer) { @@ -978,6 +987,7 @@ void snd_timer_notify(struct snd_timer *timer, int event, struct timespec *tstam } spin_unlock_irqrestore(&timer->lock, flags); } +EXPORT_SYMBOL(snd_timer_notify); /* * exported functions for global timers @@ -993,11 +1003,13 @@ int snd_timer_global_new(char *id, int device, struct snd_timer **rtimer) tid.subdevice = 0; return snd_timer_new(NULL, id, &tid, rtimer); } +EXPORT_SYMBOL(snd_timer_global_new); int snd_timer_global_free(struct snd_timer *timer) { return snd_timer_free(timer); } +EXPORT_SYMBOL(snd_timer_global_free); int snd_timer_global_register(struct snd_timer *timer) { @@ -1007,6 +1019,7 @@ int snd_timer_global_register(struct snd_timer *timer) dev.device_data = timer; return snd_timer_dev_register(&dev); } +EXPORT_SYMBOL(snd_timer_global_register); /* * System timer @@ -1327,6 +1340,33 @@ static void snd_timer_user_tinterrupt(struct snd_timer_instance *timeri, wake_up(&tu->qchange_sleep); } +static int realloc_user_queue(struct snd_timer_user *tu, int size) +{ + struct snd_timer_read *queue = NULL; + struct snd_timer_tread *tqueue = NULL; + + if (tu->tread) { + tqueue = kcalloc(size, sizeof(*tqueue), GFP_KERNEL); + if (!tqueue) + return -ENOMEM; + } else { + queue = kcalloc(size, sizeof(*queue), GFP_KERNEL); + if (!queue) + return -ENOMEM; + } + + spin_lock_irq(&tu->qlock); + kfree(tu->queue); + kfree(tu->tqueue); + tu->queue_size = size; + tu->queue = queue; + tu->tqueue = tqueue; + tu->qhead = tu->qtail = tu->qused = 0; + spin_unlock_irq(&tu->qlock); + + return 0; +} + static int snd_timer_user_open(struct inode *inode, struct file *file) { struct snd_timer_user *tu; @@ -1343,10 +1383,7 @@ static int snd_timer_user_open(struct inode *inode, struct file *file) init_waitqueue_head(&tu->qchange_sleep); mutex_init(&tu->ioctl_lock); tu->ticks = 1; - tu->queue_size = 128; - tu->queue = kmalloc(tu->queue_size * sizeof(struct snd_timer_read), - GFP_KERNEL); - if (tu->queue == NULL) { + if (realloc_user_queue(tu, 128) < 0) { kfree(tu); return -ENOMEM; } @@ -1618,34 +1655,12 @@ static int snd_timer_user_tselect(struct file *file, if (err < 0) goto __err; - tu->qhead = tu->qtail = tu->qused = 0; - kfree(tu->queue); - tu->queue = NULL; - kfree(tu->tqueue); - tu->tqueue = NULL; - if (tu->tread) { - tu->tqueue = kmalloc(tu->queue_size * sizeof(struct snd_timer_tread), - GFP_KERNEL); - if (tu->tqueue == NULL) - err = -ENOMEM; - } else { - tu->queue = kmalloc(tu->queue_size * sizeof(struct snd_timer_read), - GFP_KERNEL); - if (tu->queue == NULL) - err = -ENOMEM; - } - - if (err < 0) { - snd_timer_close(tu->timeri); - tu->timeri = NULL; - } else { - tu->timeri->flags |= SNDRV_TIMER_IFLG_FAST; - tu->timeri->callback = tu->tread + tu->timeri->flags |= SNDRV_TIMER_IFLG_FAST; + tu->timeri->callback = tu->tread ? snd_timer_user_tinterrupt : snd_timer_user_interrupt; - tu->timeri->ccallback = snd_timer_user_ccallback; - tu->timeri->callback_data = (void *)tu; - tu->timeri->disconnect = snd_timer_user_disconnect; - } + tu->timeri->ccallback = snd_timer_user_ccallback; + tu->timeri->callback_data = (void *)tu; + tu->timeri->disconnect = snd_timer_user_disconnect; __err: return err; @@ -1687,8 +1702,6 @@ static int snd_timer_user_params(struct file *file, struct snd_timer_user *tu; struct snd_timer_params params; struct snd_timer *t; - struct snd_timer_read *tr; - struct snd_timer_tread *ttr; int err; tu = file->private_data; @@ -1751,24 +1764,11 @@ static int snd_timer_user_params(struct file *file, spin_unlock_irq(&t->lock); if (params.queue_size > 0 && (unsigned int)tu->queue_size != params.queue_size) { - if (tu->tread) { - ttr = kmalloc(params.queue_size * sizeof(*ttr), - GFP_KERNEL); - if (ttr) { - kfree(tu->tqueue); - tu->queue_size = params.queue_size; - tu->tqueue = ttr; - } - } else { - tr = kmalloc(params.queue_size * sizeof(*tr), - GFP_KERNEL); - if (tr) { - kfree(tu->queue); - tu->queue_size = params.queue_size; - tu->queue = tr; - } - } + err = realloc_user_queue(tu, params.queue_size); + if (err < 0) + goto _end; } + spin_lock_irq(&tu->qlock); tu->qhead = tu->qtail = tu->qused = 0; if (tu->timeri->flags & SNDRV_TIMER_IFLG_EARLY_EVENT) { if (tu->tread) { @@ -1789,6 +1789,7 @@ static int snd_timer_user_params(struct file *file, } tu->filter = params.filter; tu->ticks = params.ticks; + spin_unlock_irq(&tu->qlock); err = 0; _end: if (copy_to_user(_params, ¶ms, sizeof(params))) @@ -1891,13 +1892,19 @@ static long __snd_timer_user_ioctl(struct file *file, unsigned int cmd, return snd_timer_user_next_device(argp); case SNDRV_TIMER_IOCTL_TREAD: { - int xarg; + int xarg, old_tread; if (tu->timeri) /* too late */ return -EBUSY; if (get_user(xarg, p)) return -EFAULT; + old_tread = tu->tread; tu->tread = xarg ? 1 : 0; + if (tu->tread != old_tread && + realloc_user_queue(tu, tu->queue_size) < 0) { + tu->tread = old_tread; + return -ENOMEM; + } return 0; } case SNDRV_TIMER_IOCTL_GINFO: @@ -1964,7 +1971,7 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer, spin_lock_irq(&tu->qlock); while ((long)count - result >= unit) { while (!tu->qused) { - wait_queue_t wait; + wait_queue_entry_t wait; if ((file->f_flags & O_NONBLOCK) != 0 || result > 0) { err = -EAGAIN; @@ -2030,10 +2037,12 @@ static unsigned int snd_timer_user_poll(struct file *file, poll_table * wait) poll_wait(file, &tu->qchange_sleep, wait); mask = 0; + spin_lock_irq(&tu->qlock); if (tu->qused) mask |= POLLIN | POLLRDNORM; if (tu->disconnected) mask |= POLLERR; + spin_unlock_irq(&tu->qlock); return mask; } @@ -2117,17 +2126,3 @@ static void __exit alsa_timer_exit(void) module_init(alsa_timer_init) module_exit(alsa_timer_exit) - -EXPORT_SYMBOL(snd_timer_open); -EXPORT_SYMBOL(snd_timer_close); -EXPORT_SYMBOL(snd_timer_resolution); -EXPORT_SYMBOL(snd_timer_start); -EXPORT_SYMBOL(snd_timer_stop); -EXPORT_SYMBOL(snd_timer_continue); -EXPORT_SYMBOL(snd_timer_pause); -EXPORT_SYMBOL(snd_timer_new); -EXPORT_SYMBOL(snd_timer_notify); -EXPORT_SYMBOL(snd_timer_global_new); -EXPORT_SYMBOL(snd_timer_global_free); -EXPORT_SYMBOL(snd_timer_global_register); -EXPORT_SYMBOL(snd_timer_interrupt); diff --git a/sound/drivers/Kconfig b/sound/drivers/Kconfig index 8545da99b183..7144cc36e8ae 100644 --- a/sound/drivers/Kconfig +++ b/sound/drivers/Kconfig @@ -6,11 +6,24 @@ config SND_OPL3_LIB tristate select SND_TIMER select SND_HWDEP + select SND_SEQ_DEVICE if SND_SEQUENCER != n config SND_OPL4_LIB tristate select SND_TIMER select SND_HWDEP + select SND_SEQ_DEVICE if SND_SEQUENCER != n + +# select SEQ stuff to min(SND_SEQUENCER,SND_XXX) +config SND_OPL3_LIB_SEQ + def_tristate SND_SEQUENCER && SND_OPL3_LIB + select SND_SEQ_MIDI_EMUL + select SND_SEQ_MIDI_EVENT + +config SND_OPL4_LIB_SEQ + def_tristate SND_SEQUENCER && SND_OPL4_LIB + select SND_SEQ_MIDI_EMUL + select SND_SEQ_MIDI_EVENT config SND_VX_LIB tristate @@ -99,6 +112,8 @@ config SND_VIRMIDI depends on SND_SEQUENCER select SND_TIMER select SND_RAWMIDI + select SND_SEQ_VIRMIDI + select SND_SEQ_MIDI_EVENT help Say Y here to include the virtual MIDI driver. This driver allows to connect applications using raw MIDI devices to diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c index 172dacd925f5..dd5ed037adf2 100644 --- a/sound/drivers/dummy.c +++ b/sound/drivers/dummy.c @@ -644,15 +644,22 @@ static int alloc_fake_buffer(void) } static int dummy_pcm_copy(struct snd_pcm_substream *substream, - int channel, snd_pcm_uframes_t pos, - void __user *dst, snd_pcm_uframes_t count) + int channel, unsigned long pos, + void __user *dst, unsigned long bytes) +{ + return 0; /* do nothing */ +} + +static int dummy_pcm_copy_kernel(struct snd_pcm_substream *substream, + int channel, unsigned long pos, + void *dst, unsigned long bytes) { return 0; /* do nothing */ } static int dummy_pcm_silence(struct snd_pcm_substream *substream, - int channel, snd_pcm_uframes_t pos, - snd_pcm_uframes_t count) + int channel, unsigned long pos, + unsigned long bytes) { return 0; /* do nothing */ } @@ -683,8 +690,9 @@ static struct snd_pcm_ops dummy_pcm_ops_no_buf = { .prepare = dummy_pcm_prepare, .trigger = dummy_pcm_trigger, .pointer = dummy_pcm_pointer, - .copy = dummy_pcm_copy, - .silence = dummy_pcm_silence, + .copy_user = dummy_pcm_copy, + .copy_kernel = dummy_pcm_copy_kernel, + .fill_silence = dummy_pcm_silence, .page = dummy_pcm_page, }; diff --git a/sound/drivers/opl3/Makefile b/sound/drivers/opl3/Makefile index 7f2c2a10c4e5..d72b1e7b51c4 100644 --- a/sound/drivers/opl3/Makefile +++ b/sound/drivers/opl3/Makefile @@ -5,7 +5,9 @@ snd-opl3-lib-objs := opl3_lib.o opl3_synth.o snd-opl3-synth-y := opl3_seq.o opl3_midi.o opl3_drums.o -snd-opl3-synth-$(CONFIG_SND_SEQUENCER_OSS) += opl3_oss.o +ifneq ($(CONFIG_SND_SEQUENCER_OSS),) +snd-opl3-synth-y += opl3_oss.o +endif obj-$(CONFIG_SND_OPL3_LIB) += snd-opl3-lib.o obj-$(CONFIG_SND_OPL4_LIB) += snd-opl3-lib.o diff --git a/sound/drivers/opl3/opl3_lib.c b/sound/drivers/opl3/opl3_lib.c index cd9e9f31720f..d5e5b4657b4b 100644 --- a/sound/drivers/opl3/opl3_lib.c +++ b/sound/drivers/opl3/opl3_lib.c @@ -528,7 +528,7 @@ int snd_opl3_hwdep_new(struct snd_opl3 * opl3, opl3->hwdep = hw; opl3->seq_dev_num = seq_device; -#if IS_REACHABLE(CONFIG_SND_SEQUENCER) +#if IS_ENABLED(CONFIG_SND_SEQUENCER) if (snd_seq_device_new(card, seq_device, SNDRV_SEQ_DEV_ID_OPL3, sizeof(struct snd_opl3 *), &opl3->seq_dev) >= 0) { strcpy(opl3->seq_dev->name, hw->name); diff --git a/sound/drivers/opl3/opl3_oss.c b/sound/drivers/opl3/opl3_oss.c index c1cb249acfaa..22c3e4bca220 100644 --- a/sound/drivers/opl3/opl3_oss.c +++ b/sound/drivers/opl3/opl3_oss.c @@ -27,20 +27,6 @@ static int snd_opl3_ioctl_seq_oss(struct snd_seq_oss_arg *arg, unsigned int cmd, static int snd_opl3_load_patch_seq_oss(struct snd_seq_oss_arg *arg, int format, const char __user *buf, int offs, int count); static int snd_opl3_reset_seq_oss(struct snd_seq_oss_arg *arg); -/* */ - -static inline mm_segment_t snd_enter_user(void) -{ - mm_segment_t fs = get_fs(); - set_fs(get_ds()); - return fs; -} - -static inline void snd_leave_user(mm_segment_t fs) -{ - set_fs(fs); -} - /* operators */ extern struct snd_midi_op opl3_ops; diff --git a/sound/drivers/opl3/opl3_seq.c b/sound/drivers/opl3/opl3_seq.c index fdae5d7f421f..d3e91be8b23a 100644 --- a/sound/drivers/opl3/opl3_seq.c +++ b/sound/drivers/opl3/opl3_seq.c @@ -252,7 +252,7 @@ static int snd_opl3_seq_probe(struct device *_dev) spin_lock_init(&opl3->sys_timer_lock); opl3->sys_timer_status = 0; -#ifdef CONFIG_SND_SEQUENCER_OSS +#if IS_ENABLED(CONFIG_SND_SEQUENCER_OSS) snd_opl3_init_seq_oss(opl3, name); #endif return 0; @@ -267,7 +267,7 @@ static int snd_opl3_seq_remove(struct device *_dev) if (opl3 == NULL) return -EINVAL; -#ifdef CONFIG_SND_SEQUENCER_OSS +#if IS_ENABLED(CONFIG_SND_SEQUENCER_OSS) snd_opl3_free_seq_oss(opl3); #endif if (opl3->seq_client >= 0) { diff --git a/sound/drivers/opl3/opl3_voice.h b/sound/drivers/opl3/opl3_voice.h index a371c075ac87..eaef435e0528 100644 --- a/sound/drivers/opl3/opl3_voice.h +++ b/sound/drivers/opl3/opl3_voice.h @@ -44,9 +44,12 @@ void snd_opl3_load_drums(struct snd_opl3 *opl3); void snd_opl3_drum_switch(struct snd_opl3 *opl3, int note, int on_off, int vel, struct snd_midi_channel *chan); /* Prototypes for opl3_oss.c */ -#ifdef CONFIG_SND_SEQUENCER_OSS +#if IS_ENABLED(CONFIG_SND_SEQUENCER_OSS) void snd_opl3_init_seq_oss(struct snd_opl3 *opl3, char *name); void snd_opl3_free_seq_oss(struct snd_opl3 *opl3); +#else +#define snd_opl3_init_seq_oss(opl3, name) /* NOP */ +#define snd_opl3_free_seq_oss(opl3) /* NOP */ #endif #endif diff --git a/sound/drivers/opl4/opl4_lib.c b/sound/drivers/opl4/opl4_lib.c index 89c7aa04b3bc..db76a5bf2bd2 100644 --- a/sound/drivers/opl4/opl4_lib.c +++ b/sound/drivers/opl4/opl4_lib.c @@ -29,7 +29,7 @@ MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>"); MODULE_DESCRIPTION("OPL4 driver"); MODULE_LICENSE("GPL"); -static void inline snd_opl4_wait(struct snd_opl4 *opl4) +static inline void snd_opl4_wait(struct snd_opl4 *opl4) { int timeout = 10; while ((inb(opl4->fm_port) & OPL4_STATUS_BUSY) && --timeout > 0) @@ -153,7 +153,7 @@ static int snd_opl4_detect(struct snd_opl4 *opl4) return 0; } -#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE)) +#if IS_ENABLED(CONFIG_SND_SEQUENCER) static void snd_opl4_seq_dev_free(struct snd_seq_device *seq_dev) { struct snd_opl4 *opl4 = seq_dev->private_data; @@ -249,7 +249,7 @@ int snd_opl4_create(struct snd_card *card, snd_opl4_create_mixer(opl4); snd_opl4_create_proc(opl4); -#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE)) +#if IS_ENABLED(CONFIG_SND_SEQUENCER) opl4->seq_client = -1; if (opl4->hardware < OPL3_HW_OPL4_ML) snd_opl4_create_seq_dev(opl4, seq_device); diff --git a/sound/drivers/opl4/opl4_local.h b/sound/drivers/opl4/opl4_local.h index 9a41bdebce6b..a16b4677c1e9 100644 --- a/sound/drivers/opl4/opl4_local.h +++ b/sound/drivers/opl4/opl4_local.h @@ -184,7 +184,7 @@ struct snd_opl4 { #endif struct mutex access_mutex; -#if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE) +#if IS_ENABLED(CONFIG_SND_SEQUENCER) int used; int seq_dev_num; diff --git a/sound/drivers/pcsp/pcsp_lib.c b/sound/drivers/pcsp/pcsp_lib.c index aca2d7d5f059..44b3632f6940 100644 --- a/sound/drivers/pcsp/pcsp_lib.c +++ b/sound/drivers/pcsp/pcsp_lib.c @@ -323,7 +323,7 @@ static int snd_pcsp_playback_open(struct snd_pcm_substream *substream) return 0; } -static struct snd_pcm_ops snd_pcsp_playback_ops = { +static const struct snd_pcm_ops snd_pcsp_playback_ops = { .open = snd_pcsp_playback_open, .close = snd_pcsp_playback_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/drivers/vx/vx_mixer.c b/sound/drivers/vx/vx_mixer.c index be9477e30739..98a41ac40b60 100644 --- a/sound/drivers/vx/vx_mixer.c +++ b/sound/drivers/vx/vx_mixer.c @@ -455,7 +455,7 @@ static int vx_output_level_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ele return 0; } -static struct snd_kcontrol_new vx_control_output_level = { +static const struct snd_kcontrol_new vx_control_output_level = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ), @@ -514,7 +514,7 @@ static int vx_audio_src_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v return 0; } -static struct snd_kcontrol_new vx_control_audio_src = { +static const struct snd_kcontrol_new vx_control_audio_src = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Capture Source", .info = vx_audio_src_info, @@ -558,7 +558,7 @@ static int vx_clock_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_ return 0; } -static struct snd_kcontrol_new vx_control_clock_mode = { +static const struct snd_kcontrol_new vx_control_clock_mode = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Clock Mode", .info = vx_clock_mode_info, @@ -717,7 +717,7 @@ static int vx_monitor_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_ static const DECLARE_TLV_DB_SCALE(db_scale_audio_gain, -10975, 25, 0); -static struct snd_kcontrol_new vx_control_audio_gain = { +static const struct snd_kcontrol_new vx_control_audio_gain = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ), @@ -727,14 +727,14 @@ static struct snd_kcontrol_new vx_control_audio_gain = { .put = vx_audio_gain_put, .tlv = { .p = db_scale_audio_gain }, }; -static struct snd_kcontrol_new vx_control_output_switch = { +static const struct snd_kcontrol_new vx_control_output_switch = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "PCM Playback Switch", .info = vx_audio_sw_info, .get = vx_audio_sw_get, .put = vx_audio_sw_put }; -static struct snd_kcontrol_new vx_control_monitor_gain = { +static const struct snd_kcontrol_new vx_control_monitor_gain = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Monitoring Volume", .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | @@ -744,7 +744,7 @@ static struct snd_kcontrol_new vx_control_monitor_gain = { .put = vx_audio_monitor_put, .tlv = { .p = db_scale_audio_gain }, }; -static struct snd_kcontrol_new vx_control_monitor_switch = { +static const struct snd_kcontrol_new vx_control_monitor_switch = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Monitoring Switch", .info = vx_audio_sw_info, /* shared */ @@ -805,7 +805,7 @@ static int vx_iec958_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_valu return 0; } -static struct snd_kcontrol_new vx_control_iec958_mask = { +static const struct snd_kcontrol_new vx_control_iec958_mask = { .access = SNDRV_CTL_ELEM_ACCESS_READ, .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK), @@ -813,7 +813,7 @@ static struct snd_kcontrol_new vx_control_iec958_mask = { .get = vx_iec958_mask_get, }; -static struct snd_kcontrol_new vx_control_iec958 = { +static const struct snd_kcontrol_new vx_control_iec958 = { .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), .info = vx_iec958_info, @@ -878,7 +878,7 @@ static int vx_saturation_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_ return 0; } -static struct snd_kcontrol_new vx_control_vu_meter = { +static const struct snd_kcontrol_new vx_control_vu_meter = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, /* name will be filled later */ @@ -886,7 +886,7 @@ static struct snd_kcontrol_new vx_control_vu_meter = { .get = vx_vu_meter_get, }; -static struct snd_kcontrol_new vx_control_peak_meter = { +static const struct snd_kcontrol_new vx_control_peak_meter = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, /* name will be filled later */ @@ -894,7 +894,7 @@ static struct snd_kcontrol_new vx_control_peak_meter = { .get = vx_peak_meter_get, }; -static struct snd_kcontrol_new vx_control_saturation = { +static const struct snd_kcontrol_new vx_control_saturation = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Input Saturation", .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, diff --git a/sound/drivers/vx/vx_pcm.c b/sound/drivers/vx/vx_pcm.c index ea7b377f0378..d318a33b6cfb 100644 --- a/sound/drivers/vx/vx_pcm.c +++ b/sound/drivers/vx/vx_pcm.c @@ -873,7 +873,7 @@ static int vx_pcm_prepare(struct snd_pcm_substream *subs) /* * operators for PCM playback */ -static struct snd_pcm_ops vx_pcm_playback_ops = { +static const struct snd_pcm_ops vx_pcm_playback_ops = { .open = vx_pcm_playback_open, .close = vx_pcm_playback_close, .ioctl = snd_pcm_lib_ioctl, @@ -1095,7 +1095,7 @@ static snd_pcm_uframes_t vx_pcm_capture_pointer(struct snd_pcm_substream *subs) /* * operators for PCM capture */ -static struct snd_pcm_ops vx_pcm_capture_ops = { +static const struct snd_pcm_ops vx_pcm_capture_ops = { .open = vx_pcm_capture_open, .close = vx_pcm_capture_close, .ioctl = snd_pcm_lib_ioctl, diff --git a/sound/firewire/amdtp-am824.c b/sound/firewire/amdtp-am824.c index bebddc60fde8..23ccddb20de1 100644 --- a/sound/firewire/amdtp-am824.c +++ b/sound/firewire/amdtp-am824.c @@ -38,10 +38,6 @@ struct amdtp_am824 { u8 pcm_positions[AM824_MAX_CHANNELS_FOR_PCM]; u8 midi_position; - void (*transfer_samples)(struct amdtp_stream *s, - struct snd_pcm_substream *pcm, - __be32 *buffer, unsigned int frames); - unsigned int frame_multiplier; }; @@ -177,32 +173,6 @@ static void write_pcm_s32(struct amdtp_stream *s, } } -static void write_pcm_s16(struct amdtp_stream *s, - struct snd_pcm_substream *pcm, - __be32 *buffer, unsigned int frames) -{ - struct amdtp_am824 *p = s->protocol; - struct snd_pcm_runtime *runtime = pcm->runtime; - unsigned int channels, remaining_frames, i, c; - const u16 *src; - - channels = p->pcm_channels; - src = (void *)runtime->dma_area + - frames_to_bytes(runtime, s->pcm_buffer_pointer); - remaining_frames = runtime->buffer_size - s->pcm_buffer_pointer; - - for (i = 0; i < frames; ++i) { - for (c = 0; c < channels; ++c) { - buffer[p->pcm_positions[c]] = - cpu_to_be32((*src << 8) | 0x42000000); - src++; - } - buffer += s->data_block_quadlets; - if (--remaining_frames == 0) - src = (void *)runtime->dma_area; - } -} - static void read_pcm_s32(struct amdtp_stream *s, struct snd_pcm_substream *pcm, __be32 *buffer, unsigned int frames) @@ -242,43 +212,6 @@ static void write_pcm_silence(struct amdtp_stream *s, } /** - * amdtp_am824_set_pcm_format - set the PCM format - * @s: the AMDTP stream to configure - * @format: the format of the ALSA PCM device - * - * The sample format must be set after the other parameters (rate/PCM channels/ - * MIDI) and before the stream is started, and must not be changed while the - * stream is running. - */ -void amdtp_am824_set_pcm_format(struct amdtp_stream *s, snd_pcm_format_t format) -{ - struct amdtp_am824 *p = s->protocol; - - if (WARN_ON(amdtp_stream_pcm_running(s))) - return; - - switch (format) { - default: - WARN_ON(1); - /* fall through */ - case SNDRV_PCM_FORMAT_S16: - if (s->direction == AMDTP_OUT_STREAM) { - p->transfer_samples = write_pcm_s16; - break; - } - WARN_ON(1); - /* fall through */ - case SNDRV_PCM_FORMAT_S32: - if (s->direction == AMDTP_OUT_STREAM) - p->transfer_samples = write_pcm_s32; - else - p->transfer_samples = read_pcm_s32; - break; - } -} -EXPORT_SYMBOL_GPL(amdtp_am824_set_pcm_format); - -/** * amdtp_am824_add_pcm_hw_constraints - add hw constraints for PCM substream * @s: the AMDTP stream for AM824 data block, must be initialized. * @runtime: the PCM substream runtime @@ -407,7 +340,7 @@ static unsigned int process_rx_data_blocks(struct amdtp_stream *s, __be32 *buffe unsigned int pcm_frames; if (pcm) { - p->transfer_samples(s, pcm, buffer, data_blocks); + write_pcm_s32(s, pcm, buffer, data_blocks); pcm_frames = data_blocks * p->frame_multiplier; } else { write_pcm_silence(s, buffer, data_blocks); @@ -428,7 +361,7 @@ static unsigned int process_tx_data_blocks(struct amdtp_stream *s, __be32 *buffe unsigned int pcm_frames; if (pcm) { - p->transfer_samples(s, pcm, buffer, data_blocks); + read_pcm_s32(s, pcm, buffer, data_blocks); pcm_frames = data_blocks * p->frame_multiplier; } else { pcm_frames = 0; diff --git a/sound/firewire/amdtp-am824.h b/sound/firewire/amdtp-am824.h index 73b07b3109db..b56e61fc997d 100644 --- a/sound/firewire/amdtp-am824.h +++ b/sound/firewire/amdtp-am824.h @@ -8,8 +8,7 @@ #define AM824_IN_PCM_FORMAT_BITS SNDRV_PCM_FMTBIT_S32 -#define AM824_OUT_PCM_FORMAT_BITS (SNDRV_PCM_FMTBIT_S16 | \ - SNDRV_PCM_FMTBIT_S32) +#define AM824_OUT_PCM_FORMAT_BITS SNDRV_PCM_FMTBIT_S32 /* * This module supports maximum 64 PCM channels for one PCM stream @@ -41,9 +40,6 @@ void amdtp_am824_set_midi_position(struct amdtp_stream *s, int amdtp_am824_add_pcm_hw_constraints(struct amdtp_stream *s, struct snd_pcm_runtime *runtime); -void amdtp_am824_set_pcm_format(struct amdtp_stream *s, - snd_pcm_format_t format); - void amdtp_am824_midi_trigger(struct amdtp_stream *s, unsigned int port, struct snd_rawmidi_substream *midi); diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index 1e26854b3425..3fc581a5ad62 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -148,8 +148,27 @@ EXPORT_SYMBOL(amdtp_rate_table); int amdtp_stream_add_pcm_hw_constraints(struct amdtp_stream *s, struct snd_pcm_runtime *runtime) { + struct snd_pcm_hardware *hw = &runtime->hw; int err; + hw->info = SNDRV_PCM_INFO_BATCH | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_JOINT_DUPLEX | + SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID; + + /* SNDRV_PCM_INFO_BATCH */ + hw->periods_min = 2; + hw->periods_max = UINT_MAX; + + /* bytes for a frame */ + hw->period_bytes_min = 4 * hw->channels_max; + + /* Just to prevent from allocating much pages. */ + hw->period_bytes_max = hw->period_bytes_min * 2048; + hw->buffer_bytes_max = hw->period_bytes_max * hw->periods_min; + /* * Currently firewire-lib processes 16 packets in one software * interrupt callback. This equals to 2msec but actually the @@ -933,6 +952,25 @@ unsigned long amdtp_stream_pcm_pointer(struct amdtp_stream *s) EXPORT_SYMBOL(amdtp_stream_pcm_pointer); /** + * amdtp_stream_pcm_ack - acknowledge queued PCM frames + * @s: the AMDTP stream that transfers the PCM frames + * + * Returns zero always. + */ +int amdtp_stream_pcm_ack(struct amdtp_stream *s) +{ + /* + * Process isochronous packets for recent isochronous cycle to handle + * queued PCM frames. + */ + if (amdtp_stream_running(s)) + fw_iso_context_flush_completions(s->context); + + return 0; +} +EXPORT_SYMBOL(amdtp_stream_pcm_ack); + +/** * amdtp_stream_update - update the stream after a bus reset * @s: the AMDTP stream */ diff --git a/sound/firewire/amdtp-stream.h b/sound/firewire/amdtp-stream.h index ea1a91e99875..ed6eafd10992 100644 --- a/sound/firewire/amdtp-stream.h +++ b/sound/firewire/amdtp-stream.h @@ -168,6 +168,7 @@ int amdtp_stream_add_pcm_hw_constraints(struct amdtp_stream *s, void amdtp_stream_pcm_prepare(struct amdtp_stream *s); unsigned long amdtp_stream_pcm_pointer(struct amdtp_stream *s); +int amdtp_stream_pcm_ack(struct amdtp_stream *s); void amdtp_stream_pcm_abort(struct amdtp_stream *s); extern const unsigned int amdtp_syt_intervals[CIP_SFC_COUNT]; diff --git a/sound/firewire/bebob/bebob_maudio.c b/sound/firewire/bebob/bebob_maudio.c index 07e5abdbceb5..d10208f92edf 100644 --- a/sound/firewire/bebob/bebob_maudio.c +++ b/sound/firewire/bebob/bebob_maudio.c @@ -396,7 +396,7 @@ static int special_clk_ctl_put(struct snd_kcontrol *kctl, return err; } -static struct snd_kcontrol_new special_clk_ctl = { +static const struct snd_kcontrol_new special_clk_ctl = { .name = "Clock Source", .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, @@ -429,7 +429,7 @@ static int special_sync_ctl_get(struct snd_kcontrol *kctl, return 0; } -static struct snd_kcontrol_new special_sync_ctl = { +static const struct snd_kcontrol_new special_sync_ctl = { .name = "Sync Status", .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .access = SNDRV_CTL_ELEM_ACCESS_READ, @@ -521,7 +521,7 @@ end: mutex_unlock(&bebob->mutex); return err; } -static struct snd_kcontrol_new special_dig_in_iface_ctl = { +static const struct snd_kcontrol_new special_dig_in_iface_ctl = { .name = "Digital Input Interface", .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, @@ -577,7 +577,7 @@ static int special_dig_out_iface_ctl_set(struct snd_kcontrol *kctl, mutex_unlock(&bebob->mutex); return err; } -static struct snd_kcontrol_new special_dig_out_iface_ctl = { +static const struct snd_kcontrol_new special_dig_out_iface_ctl = { .name = "Digital Output Interface", .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, diff --git a/sound/firewire/bebob/bebob_pcm.c b/sound/firewire/bebob/bebob_pcm.c index 9e27eb8e1dd4..e6adab3ef42e 100644 --- a/sound/firewire/bebob/bebob_pcm.c +++ b/sound/firewire/bebob/bebob_pcm.c @@ -92,19 +92,6 @@ limit_channels_and_rates(struct snd_pcm_hardware *hw, } } -static void -limit_period_and_buffer(struct snd_pcm_hardware *hw) -{ - hw->periods_min = 2; /* SNDRV_PCM_INFO_BATCH */ - hw->periods_max = UINT_MAX; - - hw->period_bytes_min = 4 * hw->channels_max; /* bytes for a frame */ - - /* Just to prevent from allocating much pages. */ - hw->period_bytes_max = hw->period_bytes_min * 2048; - hw->buffer_bytes_max = hw->period_bytes_max * hw->periods_min; -} - static int pcm_init_hw_params(struct snd_bebob *bebob, struct snd_pcm_substream *substream) @@ -114,13 +101,6 @@ pcm_init_hw_params(struct snd_bebob *bebob, struct snd_bebob_stream_formation *formations; int err; - runtime->hw.info = SNDRV_PCM_INFO_BATCH | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_JOINT_DUPLEX | - SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID; - if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { runtime->hw.formats = AM824_IN_PCM_FORMAT_BITS; s = &bebob->tx_stream; @@ -132,7 +112,6 @@ pcm_init_hw_params(struct snd_bebob *bebob, } limit_channels_and_rates(&runtime->hw, formations); - limit_period_and_buffer(&runtime->hw); err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, hw_rule_channels, formations, @@ -224,8 +203,6 @@ pcm_capture_hw_params(struct snd_pcm_substream *substream, mutex_unlock(&bebob->mutex); } - amdtp_am824_set_pcm_format(&bebob->tx_stream, params_format(hw_params)); - return 0; } static int @@ -246,8 +223,6 @@ pcm_playback_hw_params(struct snd_pcm_substream *substream, mutex_unlock(&bebob->mutex); } - amdtp_am824_set_pcm_format(&bebob->rx_stream, params_format(hw_params)); - return 0; } @@ -359,6 +334,20 @@ pcm_playback_pointer(struct snd_pcm_substream *sbstrm) return amdtp_stream_pcm_pointer(&bebob->rx_stream); } +static int pcm_capture_ack(struct snd_pcm_substream *substream) +{ + struct snd_bebob *bebob = substream->private_data; + + return amdtp_stream_pcm_ack(&bebob->tx_stream); +} + +static int pcm_playback_ack(struct snd_pcm_substream *substream) +{ + struct snd_bebob *bebob = substream->private_data; + + return amdtp_stream_pcm_ack(&bebob->rx_stream); +} + int snd_bebob_create_pcm_devices(struct snd_bebob *bebob) { static const struct snd_pcm_ops capture_ops = { @@ -370,6 +359,7 @@ int snd_bebob_create_pcm_devices(struct snd_bebob *bebob) .prepare = pcm_capture_prepare, .trigger = pcm_capture_trigger, .pointer = pcm_capture_pointer, + .ack = pcm_capture_ack, .page = snd_pcm_lib_get_vmalloc_page, }; static const struct snd_pcm_ops playback_ops = { @@ -381,6 +371,7 @@ int snd_bebob_create_pcm_devices(struct snd_bebob *bebob) .prepare = pcm_playback_prepare, .trigger = pcm_playback_trigger, .pointer = pcm_playback_pointer, + .ack = pcm_playback_ack, .page = snd_pcm_lib_get_vmalloc_page, .mmap = snd_pcm_lib_mmap_vmalloc, }; diff --git a/sound/firewire/dice/dice-pcm.c b/sound/firewire/dice/dice-pcm.c index 6074fe1f00f7..7cb9e9713ac3 100644 --- a/sound/firewire/dice/dice-pcm.c +++ b/sound/firewire/dice/dice-pcm.c @@ -51,18 +51,6 @@ static int limit_channels_and_rates(struct snd_dice *dice, return 0; } -static void limit_period_and_buffer(struct snd_pcm_hardware *hw) -{ - hw->periods_min = 2; /* SNDRV_PCM_INFO_BATCH */ - hw->periods_max = UINT_MAX; - - hw->period_bytes_min = 4 * hw->channels_max; /* byte for a frame */ - - /* Just to prevent from allocating much pages. */ - hw->period_bytes_max = hw->period_bytes_min * 2048; - hw->buffer_bytes_max = hw->period_bytes_max * hw->periods_min; -} - static int init_hw_info(struct snd_dice *dice, struct snd_pcm_substream *substream) { @@ -74,13 +62,6 @@ static int init_hw_info(struct snd_dice *dice, unsigned int count, size; int err; - hw->info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_BATCH | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_JOINT_DUPLEX | - SNDRV_PCM_INFO_BLOCK_TRANSFER; - if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { hw->formats = AM824_IN_PCM_FORMAT_BITS; dir = AMDTP_IN_STREAM; @@ -107,7 +88,6 @@ static int init_hw_info(struct snd_dice *dice, substream->pcm->device, size); if (err < 0) return err; - limit_period_and_buffer(hw); return amdtp_am824_add_pcm_hw_constraints(stream, runtime); } @@ -146,7 +126,6 @@ static int capture_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) { struct snd_dice *dice = substream->private_data; - struct amdtp_stream *stream = &dice->tx_stream[substream->pcm->device]; int err; err = snd_pcm_lib_alloc_vmalloc_buffer(substream, @@ -160,15 +139,12 @@ static int capture_hw_params(struct snd_pcm_substream *substream, mutex_unlock(&dice->mutex); } - amdtp_am824_set_pcm_format(stream, params_format(hw_params)); - return 0; } static int playback_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) { struct snd_dice *dice = substream->private_data; - struct amdtp_stream *stream = &dice->rx_stream[substream->pcm->device]; int err; err = snd_pcm_lib_alloc_vmalloc_buffer(substream, @@ -182,8 +158,6 @@ static int playback_hw_params(struct snd_pcm_substream *substream, mutex_unlock(&dice->mutex); } - amdtp_am824_set_pcm_format(stream, params_format(hw_params)); - return 0; } @@ -300,6 +274,22 @@ static snd_pcm_uframes_t playback_pointer(struct snd_pcm_substream *substream) return amdtp_stream_pcm_pointer(stream); } +static int capture_ack(struct snd_pcm_substream *substream) +{ + struct snd_dice *dice = substream->private_data; + struct amdtp_stream *stream = &dice->tx_stream[substream->pcm->device]; + + return amdtp_stream_pcm_ack(stream); +} + +static int playback_ack(struct snd_pcm_substream *substream) +{ + struct snd_dice *dice = substream->private_data; + struct amdtp_stream *stream = &dice->rx_stream[substream->pcm->device]; + + return amdtp_stream_pcm_ack(stream); +} + int snd_dice_create_pcm(struct snd_dice *dice) { static const struct snd_pcm_ops capture_ops = { @@ -311,6 +301,7 @@ int snd_dice_create_pcm(struct snd_dice *dice) .prepare = capture_prepare, .trigger = capture_trigger, .pointer = capture_pointer, + .ack = capture_ack, .page = snd_pcm_lib_get_vmalloc_page, .mmap = snd_pcm_lib_mmap_vmalloc, }; @@ -323,6 +314,7 @@ int snd_dice_create_pcm(struct snd_dice *dice) .prepare = playback_prepare, .trigger = playback_trigger, .pointer = playback_pointer, + .ack = playback_ack, .page = snd_pcm_lib_get_vmalloc_page, .mmap = snd_pcm_lib_mmap_vmalloc, }; diff --git a/sound/firewire/digi00x/amdtp-dot.c b/sound/firewire/digi00x/amdtp-dot.c index a4688545339c..1453c34ce99f 100644 --- a/sound/firewire/digi00x/amdtp-dot.c +++ b/sound/firewire/digi00x/amdtp-dot.c @@ -48,10 +48,6 @@ struct amdtp_dot { struct snd_rawmidi_substream *midi[MAX_MIDI_PORTS]; int midi_fifo_used[MAX_MIDI_PORTS]; int midi_fifo_limit; - - void (*transfer_samples)(struct amdtp_stream *s, - struct snd_pcm_substream *pcm, - __be32 *buffer, unsigned int frames); }; /* @@ -173,32 +169,6 @@ static void write_pcm_s32(struct amdtp_stream *s, struct snd_pcm_substream *pcm, } } -static void write_pcm_s16(struct amdtp_stream *s, struct snd_pcm_substream *pcm, - __be32 *buffer, unsigned int frames) -{ - struct amdtp_dot *p = s->protocol; - struct snd_pcm_runtime *runtime = pcm->runtime; - unsigned int channels, remaining_frames, i, c; - const u16 *src; - - channels = p->pcm_channels; - src = (void *)runtime->dma_area + - frames_to_bytes(runtime, s->pcm_buffer_pointer); - remaining_frames = runtime->buffer_size - s->pcm_buffer_pointer; - - buffer++; - for (i = 0; i < frames; ++i) { - for (c = 0; c < channels; ++c) { - buffer[c] = cpu_to_be32((*src << 8) | 0x40000000); - dot_encode_step(&p->state, &buffer[c]); - src++; - } - buffer += s->data_block_quadlets; - if (--remaining_frames == 0) - src = (void *)runtime->dma_area; - } -} - static void read_pcm_s32(struct amdtp_stream *s, struct snd_pcm_substream *pcm, __be32 *buffer, unsigned int frames) { @@ -351,33 +321,6 @@ int amdtp_dot_add_pcm_hw_constraints(struct amdtp_stream *s, return amdtp_stream_add_pcm_hw_constraints(s, runtime); } -void amdtp_dot_set_pcm_format(struct amdtp_stream *s, snd_pcm_format_t format) -{ - struct amdtp_dot *p = s->protocol; - - if (WARN_ON(amdtp_stream_pcm_running(s))) - return; - - switch (format) { - default: - WARN_ON(1); - /* fall through */ - case SNDRV_PCM_FORMAT_S16: - if (s->direction == AMDTP_OUT_STREAM) { - p->transfer_samples = write_pcm_s16; - break; - } - WARN_ON(1); - /* fall through */ - case SNDRV_PCM_FORMAT_S32: - if (s->direction == AMDTP_OUT_STREAM) - p->transfer_samples = write_pcm_s32; - else - p->transfer_samples = read_pcm_s32; - break; - } -} - void amdtp_dot_midi_trigger(struct amdtp_stream *s, unsigned int port, struct snd_rawmidi_substream *midi) { @@ -392,13 +335,12 @@ static unsigned int process_tx_data_blocks(struct amdtp_stream *s, unsigned int data_blocks, unsigned int *syt) { - struct amdtp_dot *p = (struct amdtp_dot *)s->protocol; struct snd_pcm_substream *pcm; unsigned int pcm_frames; pcm = ACCESS_ONCE(s->pcm); if (pcm) { - p->transfer_samples(s, pcm, buffer, data_blocks); + read_pcm_s32(s, pcm, buffer, data_blocks); pcm_frames = data_blocks; } else { pcm_frames = 0; @@ -414,13 +356,12 @@ static unsigned int process_rx_data_blocks(struct amdtp_stream *s, unsigned int data_blocks, unsigned int *syt) { - struct amdtp_dot *p = (struct amdtp_dot *)s->protocol; struct snd_pcm_substream *pcm; unsigned int pcm_frames; pcm = ACCESS_ONCE(s->pcm); if (pcm) { - p->transfer_samples(s, pcm, buffer, data_blocks); + write_pcm_s32(s, pcm, buffer, data_blocks); pcm_frames = data_blocks; } else { write_pcm_silence(s, buffer, data_blocks); diff --git a/sound/firewire/digi00x/digi00x-pcm.c b/sound/firewire/digi00x/digi00x-pcm.c index 68d1c52db051..796f4b4645f5 100644 --- a/sound/firewire/digi00x/digi00x-pcm.c +++ b/sound/firewire/digi00x/digi00x-pcm.c @@ -58,41 +58,29 @@ static int hw_rule_channels(struct snd_pcm_hw_params *params, static int pcm_init_hw_params(struct snd_dg00x *dg00x, struct snd_pcm_substream *substream) { - static const struct snd_pcm_hardware hardware = { - .info = SNDRV_PCM_INFO_BATCH | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_JOINT_DUPLEX | - SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID, - .rates = SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_88200 | - SNDRV_PCM_RATE_96000, - .rate_min = 44100, - .rate_max = 96000, - .channels_min = 10, - .channels_max = 18, - .period_bytes_min = 4 * 18, - .period_bytes_max = 4 * 18 * 2048, - .buffer_bytes_max = 4 * 18 * 2048 * 2, - .periods_min = 2, - .periods_max = UINT_MAX, - }; + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_pcm_hardware *hw = &runtime->hw; struct amdtp_stream *s; int err; - substream->runtime->hw = hardware; if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { substream->runtime->hw.formats = SNDRV_PCM_FMTBIT_S32; s = &dg00x->tx_stream; } else { - substream->runtime->hw.formats = SNDRV_PCM_FMTBIT_S16 | - SNDRV_PCM_FMTBIT_S32; + substream->runtime->hw.formats = SNDRV_PCM_FMTBIT_S32; s = &dg00x->rx_stream; } + hw->channels_min = 10; + hw->channels_max = 18; + + hw->rates = SNDRV_PCM_RATE_44100 | + SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_88200 | + SNDRV_PCM_RATE_96000; + snd_pcm_limit_hw_rates(runtime); + err = snd_pcm_hw_rule_add(substream->runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, hw_rule_channels, NULL, @@ -184,8 +172,6 @@ static int pcm_capture_hw_params(struct snd_pcm_substream *substream, mutex_unlock(&dg00x->mutex); } - amdtp_dot_set_pcm_format(&dg00x->tx_stream, params_format(hw_params)); - return 0; } @@ -206,8 +192,6 @@ static int pcm_playback_hw_params(struct snd_pcm_substream *substream, mutex_unlock(&dg00x->mutex); } - amdtp_dot_set_pcm_format(&dg00x->rx_stream, params_format(hw_params)); - return 0; } @@ -329,6 +313,20 @@ static snd_pcm_uframes_t pcm_playback_pointer(struct snd_pcm_substream *sbstrm) return amdtp_stream_pcm_pointer(&dg00x->rx_stream); } +static int pcm_capture_ack(struct snd_pcm_substream *substream) +{ + struct snd_dg00x *dg00x = substream->private_data; + + return amdtp_stream_pcm_ack(&dg00x->tx_stream); +} + +static int pcm_playback_ack(struct snd_pcm_substream *substream) +{ + struct snd_dg00x *dg00x = substream->private_data; + + return amdtp_stream_pcm_ack(&dg00x->rx_stream); +} + int snd_dg00x_create_pcm_devices(struct snd_dg00x *dg00x) { static const struct snd_pcm_ops capture_ops = { @@ -340,6 +338,7 @@ int snd_dg00x_create_pcm_devices(struct snd_dg00x *dg00x) .prepare = pcm_capture_prepare, .trigger = pcm_capture_trigger, .pointer = pcm_capture_pointer, + .ack = pcm_capture_ack, .page = snd_pcm_lib_get_vmalloc_page, }; static const struct snd_pcm_ops playback_ops = { @@ -351,6 +350,7 @@ int snd_dg00x_create_pcm_devices(struct snd_dg00x *dg00x) .prepare = pcm_playback_prepare, .trigger = pcm_playback_trigger, .pointer = pcm_playback_pointer, + .ack = pcm_playback_ack, .page = snd_pcm_lib_get_vmalloc_page, .mmap = snd_pcm_lib_mmap_vmalloc, }; diff --git a/sound/firewire/digi00x/digi00x.h b/sound/firewire/digi00x/digi00x.h index 1275a50956c0..4dd1bbf2ed3c 100644 --- a/sound/firewire/digi00x/digi00x.h +++ b/sound/firewire/digi00x/digi00x.h @@ -121,7 +121,6 @@ int amdtp_dot_set_parameters(struct amdtp_stream *s, unsigned int rate, void amdtp_dot_reset(struct amdtp_stream *s); int amdtp_dot_add_pcm_hw_constraints(struct amdtp_stream *s, struct snd_pcm_runtime *runtime); -void amdtp_dot_set_pcm_format(struct amdtp_stream *s, snd_pcm_format_t format); void amdtp_dot_midi_trigger(struct amdtp_stream *s, unsigned int port, struct snd_rawmidi_substream *midi); diff --git a/sound/firewire/fireface/ff-midi.c b/sound/firewire/fireface/ff-midi.c index 29ee0a7365c3..949ee56b4e0e 100644 --- a/sound/firewire/fireface/ff-midi.c +++ b/sound/firewire/fireface/ff-midi.c @@ -74,18 +74,6 @@ static void midi_playback_trigger(struct snd_rawmidi_substream *substream, spin_unlock_irqrestore(&ff->lock, flags); } -static struct snd_rawmidi_ops midi_capture_ops = { - .open = midi_capture_open, - .close = midi_capture_close, - .trigger = midi_capture_trigger, -}; - -static struct snd_rawmidi_ops midi_playback_ops = { - .open = midi_playback_open, - .close = midi_playback_close, - .trigger = midi_playback_trigger, -}; - static void set_midi_substream_names(struct snd_rawmidi_str *stream, const char *const name) { @@ -99,6 +87,16 @@ static void set_midi_substream_names(struct snd_rawmidi_str *stream, int snd_ff_create_midi_devices(struct snd_ff *ff) { + static const struct snd_rawmidi_ops midi_capture_ops = { + .open = midi_capture_open, + .close = midi_capture_close, + .trigger = midi_capture_trigger, + }; + static const struct snd_rawmidi_ops midi_playback_ops = { + .open = midi_playback_open, + .close = midi_playback_close, + .trigger = midi_playback_trigger, + }; struct snd_rawmidi *rmidi; struct snd_rawmidi_str *stream; int err; diff --git a/sound/firewire/fireface/ff-pcm.c b/sound/firewire/fireface/ff-pcm.c index 93cee1978e8e..d12a0e3a4219 100644 --- a/sound/firewire/fireface/ff-pcm.c +++ b/sound/firewire/fireface/ff-pcm.c @@ -91,18 +91,6 @@ static void limit_channels_and_rates(struct snd_pcm_hardware *hw, } } -static void limit_period_and_buffer(struct snd_pcm_hardware *hw) -{ - hw->periods_min = 2; /* SNDRV_PCM_INFO_BATCH */ - hw->periods_max = UINT_MAX; - - hw->period_bytes_min = 4 * hw->channels_max; /* bytes for a frame */ - - /* Just to prevent from allocating much pages. */ - hw->period_bytes_max = hw->period_bytes_min * 2048; - hw->buffer_bytes_max = hw->period_bytes_max * hw->periods_min; -} - static int pcm_init_hw_params(struct snd_ff *ff, struct snd_pcm_substream *substream) { @@ -111,13 +99,6 @@ static int pcm_init_hw_params(struct snd_ff *ff, const unsigned int *pcm_channels; int err; - runtime->hw.info = SNDRV_PCM_INFO_BATCH | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_JOINT_DUPLEX | - SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID; - if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { runtime->hw.formats = SNDRV_PCM_FMTBIT_S32; s = &ff->tx_stream; @@ -128,9 +109,7 @@ static int pcm_init_hw_params(struct snd_ff *ff, pcm_channels = ff->spec->pcm_playback_channels; } - /* limit rates */ limit_channels_and_rates(&runtime->hw, pcm_channels); - limit_period_and_buffer(&runtime->hw); err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, hw_rule_channels, (void *)pcm_channels, @@ -365,33 +344,47 @@ static snd_pcm_uframes_t pcm_playback_pointer(struct snd_pcm_substream *sbstrm) return amdtp_stream_pcm_pointer(&ff->rx_stream); } -static struct snd_pcm_ops pcm_capture_ops = { - .open = pcm_open, - .close = pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = pcm_capture_hw_params, - .hw_free = pcm_capture_hw_free, - .prepare = pcm_capture_prepare, - .trigger = pcm_capture_trigger, - .pointer = pcm_capture_pointer, - .page = snd_pcm_lib_get_vmalloc_page, -}; - -static struct snd_pcm_ops pcm_playback_ops = { - .open = pcm_open, - .close = pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = pcm_playback_hw_params, - .hw_free = pcm_playback_hw_free, - .prepare = pcm_playback_prepare, - .trigger = pcm_playback_trigger, - .pointer = pcm_playback_pointer, - .page = snd_pcm_lib_get_vmalloc_page, - .mmap = snd_pcm_lib_mmap_vmalloc, -}; +static int pcm_capture_ack(struct snd_pcm_substream *substream) +{ + struct snd_ff *ff = substream->private_data; + + return amdtp_stream_pcm_ack(&ff->tx_stream); +} + +static int pcm_playback_ack(struct snd_pcm_substream *substream) +{ + struct snd_ff *ff = substream->private_data; + + return amdtp_stream_pcm_ack(&ff->rx_stream); +} int snd_ff_create_pcm_devices(struct snd_ff *ff) { + static const struct snd_pcm_ops pcm_capture_ops = { + .open = pcm_open, + .close = pcm_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = pcm_capture_hw_params, + .hw_free = pcm_capture_hw_free, + .prepare = pcm_capture_prepare, + .trigger = pcm_capture_trigger, + .pointer = pcm_capture_pointer, + .ack = pcm_capture_ack, + .page = snd_pcm_lib_get_vmalloc_page, + }; + static const struct snd_pcm_ops pcm_playback_ops = { + .open = pcm_open, + .close = pcm_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = pcm_playback_hw_params, + .hw_free = pcm_playback_hw_free, + .prepare = pcm_playback_prepare, + .trigger = pcm_playback_trigger, + .pointer = pcm_playback_pointer, + .ack = pcm_playback_ack, + .page = snd_pcm_lib_get_vmalloc_page, + .mmap = snd_pcm_lib_mmap_vmalloc, + }; struct snd_pcm *pcm; int err; diff --git a/sound/firewire/fireworks/fireworks_pcm.c b/sound/firewire/fireworks/fireworks_pcm.c index 9171702f7d0b..40faed5e6968 100644 --- a/sound/firewire/fireworks/fireworks_pcm.c +++ b/sound/firewire/fireworks/fireworks_pcm.c @@ -129,19 +129,6 @@ limit_channels(struct snd_pcm_hardware *hw, unsigned int *pcm_channels) } } -static void -limit_period_and_buffer(struct snd_pcm_hardware *hw) -{ - hw->periods_min = 2; /* SNDRV_PCM_INFO_BATCH */ - hw->periods_max = UINT_MAX; - - hw->period_bytes_min = 4 * hw->channels_max; /* bytes for a frame */ - - /* Just to prevent from allocating much pages. */ - hw->period_bytes_max = hw->period_bytes_min * 2048; - hw->buffer_bytes_max = hw->period_bytes_max * hw->periods_min; -} - static int pcm_init_hw_params(struct snd_efw *efw, struct snd_pcm_substream *substream) @@ -151,13 +138,6 @@ pcm_init_hw_params(struct snd_efw *efw, unsigned int *pcm_channels; int err; - runtime->hw.info = SNDRV_PCM_INFO_BATCH | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_JOINT_DUPLEX | - SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID; - if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { runtime->hw.formats = AM824_IN_PCM_FORMAT_BITS; s = &efw->tx_stream; @@ -173,7 +153,6 @@ pcm_init_hw_params(struct snd_efw *efw, snd_pcm_limit_hw_rates(runtime); limit_channels(&runtime->hw, pcm_channels); - limit_period_and_buffer(&runtime->hw); err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, hw_rule_channels, pcm_channels, @@ -257,8 +236,6 @@ static int pcm_capture_hw_params(struct snd_pcm_substream *substream, mutex_unlock(&efw->mutex); } - amdtp_am824_set_pcm_format(&efw->tx_stream, params_format(hw_params)); - return 0; } static int pcm_playback_hw_params(struct snd_pcm_substream *substream, @@ -278,8 +255,6 @@ static int pcm_playback_hw_params(struct snd_pcm_substream *substream, mutex_unlock(&efw->mutex); } - amdtp_am824_set_pcm_format(&efw->rx_stream, params_format(hw_params)); - return 0; } @@ -383,6 +358,20 @@ static snd_pcm_uframes_t pcm_playback_pointer(struct snd_pcm_substream *sbstrm) return amdtp_stream_pcm_pointer(&efw->rx_stream); } +static int pcm_capture_ack(struct snd_pcm_substream *substream) +{ + struct snd_efw *efw = substream->private_data; + + return amdtp_stream_pcm_ack(&efw->tx_stream); +} + +static int pcm_playback_ack(struct snd_pcm_substream *substream) +{ + struct snd_efw *efw = substream->private_data; + + return amdtp_stream_pcm_ack(&efw->rx_stream); +} + int snd_efw_create_pcm_devices(struct snd_efw *efw) { static const struct snd_pcm_ops capture_ops = { @@ -394,6 +383,7 @@ int snd_efw_create_pcm_devices(struct snd_efw *efw) .prepare = pcm_capture_prepare, .trigger = pcm_capture_trigger, .pointer = pcm_capture_pointer, + .ack = pcm_capture_ack, .page = snd_pcm_lib_get_vmalloc_page, }; static const struct snd_pcm_ops playback_ops = { @@ -405,6 +395,7 @@ int snd_efw_create_pcm_devices(struct snd_efw *efw) .prepare = pcm_playback_prepare, .trigger = pcm_playback_trigger, .pointer = pcm_playback_pointer, + .ack = pcm_playback_ack, .page = snd_pcm_lib_get_vmalloc_page, .mmap = snd_pcm_lib_mmap_vmalloc, }; diff --git a/sound/firewire/motu/motu-pcm.c b/sound/firewire/motu/motu-pcm.c index 94558f3d218b..a2b50df70874 100644 --- a/sound/firewire/motu/motu-pcm.c +++ b/sound/firewire/motu/motu-pcm.c @@ -96,18 +96,6 @@ static void limit_channels_and_rates(struct snd_motu *motu, snd_pcm_limit_hw_rates(runtime); } -static void limit_period_and_buffer(struct snd_pcm_hardware *hw) -{ - hw->periods_min = 2; /* SNDRV_PCM_INFO_BATCH */ - hw->periods_max = UINT_MAX; - - hw->period_bytes_min = 4 * hw->channels_max; /* byte for a frame */ - - /* Just to prevent from allocating much pages. */ - hw->period_bytes_max = hw->period_bytes_min * 2048; - hw->buffer_bytes_max = hw->period_bytes_max * hw->periods_min; -} - static int init_hw_info(struct snd_motu *motu, struct snd_pcm_substream *substream) { @@ -117,13 +105,6 @@ static int init_hw_info(struct snd_motu *motu, struct snd_motu_packet_format *formats; int err; - hw->info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_BATCH | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_JOINT_DUPLEX | - SNDRV_PCM_INFO_BLOCK_TRANSFER; - if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { hw->formats = SNDRV_PCM_FMTBIT_S32; stream = &motu->tx_stream; @@ -135,7 +116,6 @@ static int init_hw_info(struct snd_motu *motu, } limit_channels_and_rates(motu, runtime, formats); - limit_period_and_buffer(hw); err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, motu_rate_constraint, formats, @@ -356,6 +336,20 @@ static snd_pcm_uframes_t playback_pointer(struct snd_pcm_substream *substream) return amdtp_stream_pcm_pointer(&motu->rx_stream); } +static int capture_ack(struct snd_pcm_substream *substream) +{ + struct snd_motu *motu = substream->private_data; + + return amdtp_stream_pcm_ack(&motu->tx_stream); +} + +static int playback_ack(struct snd_pcm_substream *substream) +{ + struct snd_motu *motu = substream->private_data; + + return amdtp_stream_pcm_ack(&motu->rx_stream); +} + int snd_motu_create_pcm_devices(struct snd_motu *motu) { static struct snd_pcm_ops capture_ops = { @@ -367,6 +361,7 @@ int snd_motu_create_pcm_devices(struct snd_motu *motu) .prepare = capture_prepare, .trigger = capture_trigger, .pointer = capture_pointer, + .ack = capture_ack, .page = snd_pcm_lib_get_vmalloc_page, .mmap = snd_pcm_lib_mmap_vmalloc, }; @@ -379,6 +374,7 @@ int snd_motu_create_pcm_devices(struct snd_motu *motu) .prepare = playback_prepare, .trigger = playback_trigger, .pointer = playback_pointer, + .ack = playback_ack, .page = snd_pcm_lib_get_vmalloc_page, .mmap = snd_pcm_lib_mmap_vmalloc, }; diff --git a/sound/firewire/oxfw/oxfw-pcm.c b/sound/firewire/oxfw/oxfw-pcm.c index f3530f89a025..3dd46285c0e2 100644 --- a/sound/firewire/oxfw/oxfw-pcm.c +++ b/sound/firewire/oxfw/oxfw-pcm.c @@ -106,18 +106,6 @@ static void limit_channels_and_rates(struct snd_pcm_hardware *hw, u8 **formats) } } -static void limit_period_and_buffer(struct snd_pcm_hardware *hw) -{ - hw->periods_min = 2; /* SNDRV_PCM_INFO_BATCH */ - hw->periods_max = UINT_MAX; - - hw->period_bytes_min = 4 * hw->channels_max; /* bytes for a frame */ - - /* Just to prevent from allocating much pages. */ - hw->period_bytes_max = hw->period_bytes_min * 2048; - hw->buffer_bytes_max = hw->period_bytes_max * hw->periods_min; -} - static int init_hw_params(struct snd_oxfw *oxfw, struct snd_pcm_substream *substream) { @@ -126,13 +114,6 @@ static int init_hw_params(struct snd_oxfw *oxfw, struct amdtp_stream *stream; int err; - runtime->hw.info = SNDRV_PCM_INFO_BATCH | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_JOINT_DUPLEX | - SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID; - if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { runtime->hw.formats = AM824_IN_PCM_FORMAT_BITS; stream = &oxfw->tx_stream; @@ -144,7 +125,6 @@ static int init_hw_params(struct snd_oxfw *oxfw, } limit_channels_and_rates(&runtime->hw, formats); - limit_period_and_buffer(&runtime->hw); err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, hw_rule_channels, formats, @@ -244,8 +224,6 @@ static int pcm_capture_hw_params(struct snd_pcm_substream *substream, mutex_unlock(&oxfw->mutex); } - amdtp_am824_set_pcm_format(&oxfw->tx_stream, params_format(hw_params)); - return 0; } static int pcm_playback_hw_params(struct snd_pcm_substream *substream, @@ -265,8 +243,6 @@ static int pcm_playback_hw_params(struct snd_pcm_substream *substream, mutex_unlock(&oxfw->mutex); } - amdtp_am824_set_pcm_format(&oxfw->rx_stream, params_format(hw_params)); - return 0; } @@ -386,6 +362,20 @@ static snd_pcm_uframes_t pcm_playback_pointer(struct snd_pcm_substream *sbstm) return amdtp_stream_pcm_pointer(&oxfw->rx_stream); } +static int pcm_capture_ack(struct snd_pcm_substream *substream) +{ + struct snd_oxfw *oxfw = substream->private_data; + + return amdtp_stream_pcm_ack(&oxfw->tx_stream); +} + +static int pcm_playback_ack(struct snd_pcm_substream *substream) +{ + struct snd_oxfw *oxfw = substream->private_data; + + return amdtp_stream_pcm_ack(&oxfw->rx_stream); +} + int snd_oxfw_create_pcm(struct snd_oxfw *oxfw) { static const struct snd_pcm_ops capture_ops = { @@ -397,6 +387,7 @@ int snd_oxfw_create_pcm(struct snd_oxfw *oxfw) .prepare = pcm_capture_prepare, .trigger = pcm_capture_trigger, .pointer = pcm_capture_pointer, + .ack = pcm_capture_ack, .page = snd_pcm_lib_get_vmalloc_page, .mmap = snd_pcm_lib_mmap_vmalloc, }; @@ -409,6 +400,7 @@ int snd_oxfw_create_pcm(struct snd_oxfw *oxfw) .prepare = pcm_playback_prepare, .trigger = pcm_playback_trigger, .pointer = pcm_playback_pointer, + .ack = pcm_playback_ack, .page = snd_pcm_lib_get_vmalloc_page, .mmap = snd_pcm_lib_mmap_vmalloc, }; diff --git a/sound/firewire/tascam/amdtp-tascam.c b/sound/firewire/tascam/amdtp-tascam.c index 9dd0fccd5ccc..6aff1fc1c72d 100644 --- a/sound/firewire/tascam/amdtp-tascam.c +++ b/sound/firewire/tascam/amdtp-tascam.c @@ -14,10 +14,6 @@ struct amdtp_tscm { unsigned int pcm_channels; - - void (*transfer_samples)(struct amdtp_stream *s, - struct snd_pcm_substream *pcm, - __be32 *buffer, unsigned int frames); }; int amdtp_tscm_set_parameters(struct amdtp_stream *s, unsigned int rate) @@ -62,31 +58,6 @@ static void write_pcm_s32(struct amdtp_stream *s, } } -static void write_pcm_s16(struct amdtp_stream *s, - struct snd_pcm_substream *pcm, - __be32 *buffer, unsigned int frames) -{ - struct amdtp_tscm *p = s->protocol; - struct snd_pcm_runtime *runtime = pcm->runtime; - unsigned int channels, remaining_frames, i, c; - const u16 *src; - - channels = p->pcm_channels; - src = (void *)runtime->dma_area + - frames_to_bytes(runtime, s->pcm_buffer_pointer); - remaining_frames = runtime->buffer_size - s->pcm_buffer_pointer; - - for (i = 0; i < frames; ++i) { - for (c = 0; c < channels; ++c) { - buffer[c] = cpu_to_be32(*src << 16); - src++; - } - buffer += s->data_block_quadlets; - if (--remaining_frames == 0) - src = (void *)runtime->dma_area; - } -} - static void read_pcm_s32(struct amdtp_stream *s, struct snd_pcm_substream *pcm, __be32 *buffer, unsigned int frames) @@ -146,44 +117,16 @@ int amdtp_tscm_add_pcm_hw_constraints(struct amdtp_stream *s, return amdtp_stream_add_pcm_hw_constraints(s, runtime); } -void amdtp_tscm_set_pcm_format(struct amdtp_stream *s, snd_pcm_format_t format) -{ - struct amdtp_tscm *p = s->protocol; - - if (WARN_ON(amdtp_stream_pcm_running(s))) - return; - - switch (format) { - default: - WARN_ON(1); - /* fall through */ - case SNDRV_PCM_FORMAT_S16: - if (s->direction == AMDTP_OUT_STREAM) { - p->transfer_samples = write_pcm_s16; - break; - } - WARN_ON(1); - /* fall through */ - case SNDRV_PCM_FORMAT_S32: - if (s->direction == AMDTP_OUT_STREAM) - p->transfer_samples = write_pcm_s32; - else - p->transfer_samples = read_pcm_s32; - break; - } -} - static unsigned int process_tx_data_blocks(struct amdtp_stream *s, __be32 *buffer, unsigned int data_blocks, unsigned int *syt) { - struct amdtp_tscm *p = (struct amdtp_tscm *)s->protocol; struct snd_pcm_substream *pcm; pcm = ACCESS_ONCE(s->pcm); if (data_blocks > 0 && pcm) - p->transfer_samples(s, pcm, buffer, data_blocks); + read_pcm_s32(s, pcm, buffer, data_blocks); /* A place holder for control messages. */ @@ -195,7 +138,6 @@ static unsigned int process_rx_data_blocks(struct amdtp_stream *s, unsigned int data_blocks, unsigned int *syt) { - struct amdtp_tscm *p = (struct amdtp_tscm *)s->protocol; struct snd_pcm_substream *pcm; /* This field is not used. */ @@ -203,7 +145,7 @@ static unsigned int process_rx_data_blocks(struct amdtp_stream *s, pcm = ACCESS_ONCE(s->pcm); if (pcm) - p->transfer_samples(s, pcm, buffer, data_blocks); + write_pcm_s32(s, pcm, buffer, data_blocks); else write_pcm_silence(s, buffer, data_blocks); diff --git a/sound/firewire/tascam/tascam-pcm.c b/sound/firewire/tascam/tascam-pcm.c index f5dd6ce6b6f1..6ec8ec634d4d 100644 --- a/sound/firewire/tascam/tascam-pcm.c +++ b/sound/firewire/tascam/tascam-pcm.c @@ -8,48 +8,20 @@ #include "tascam.h" -static void set_buffer_params(struct snd_pcm_hardware *hw) -{ - hw->period_bytes_min = 4 * hw->channels_min; - hw->period_bytes_max = hw->period_bytes_min * 2048; - hw->buffer_bytes_max = hw->period_bytes_max * 2; - - hw->periods_min = 2; - hw->periods_max = UINT_MAX; -} - static int pcm_init_hw_params(struct snd_tscm *tscm, struct snd_pcm_substream *substream) { - static const struct snd_pcm_hardware hardware = { - .info = SNDRV_PCM_INFO_BATCH | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_JOINT_DUPLEX | - SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID, - .rates = SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_88200 | - SNDRV_PCM_RATE_96000, - .rate_min = 44100, - .rate_max = 96000, - .channels_min = 10, - .channels_max = 18, - }; struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_pcm_hardware *hw = &runtime->hw; struct amdtp_stream *stream; unsigned int pcm_channels; - runtime->hw = hardware; - if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { runtime->hw.formats = SNDRV_PCM_FMTBIT_S32; stream = &tscm->tx_stream; pcm_channels = tscm->spec->pcm_capture_analog_channels; } else { - runtime->hw.formats = - SNDRV_PCM_FMTBIT_S16 | SNDRV_PCM_FMTBIT_S32; + runtime->hw.formats = SNDRV_PCM_FMTBIT_S32; stream = &tscm->rx_stream; pcm_channels = tscm->spec->pcm_playback_analog_channels; } @@ -60,7 +32,11 @@ static int pcm_init_hw_params(struct snd_tscm *tscm, pcm_channels += 2; runtime->hw.channels_min = runtime->hw.channels_max = pcm_channels; - set_buffer_params(&runtime->hw); + hw->rates = SNDRV_PCM_RATE_44100 | + SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_88200 | + SNDRV_PCM_RATE_96000; + snd_pcm_limit_hw_rates(runtime); return amdtp_tscm_add_pcm_hw_constraints(stream, runtime); } @@ -125,8 +101,6 @@ static int pcm_capture_hw_params(struct snd_pcm_substream *substream, mutex_unlock(&tscm->mutex); } - amdtp_tscm_set_pcm_format(&tscm->tx_stream, params_format(hw_params)); - return 0; } @@ -147,8 +121,6 @@ static int pcm_playback_hw_params(struct snd_pcm_substream *substream, mutex_unlock(&tscm->mutex); } - amdtp_tscm_set_pcm_format(&tscm->rx_stream, params_format(hw_params)); - return 0; } @@ -268,6 +240,20 @@ static snd_pcm_uframes_t pcm_playback_pointer(struct snd_pcm_substream *sbstrm) return amdtp_stream_pcm_pointer(&tscm->rx_stream); } +static int pcm_capture_ack(struct snd_pcm_substream *substream) +{ + struct snd_tscm *tscm = substream->private_data; + + return amdtp_stream_pcm_ack(&tscm->tx_stream); +} + +static int pcm_playback_ack(struct snd_pcm_substream *substream) +{ + struct snd_tscm *tscm = substream->private_data; + + return amdtp_stream_pcm_ack(&tscm->rx_stream); +} + int snd_tscm_create_pcm_devices(struct snd_tscm *tscm) { static const struct snd_pcm_ops capture_ops = { @@ -279,6 +265,7 @@ int snd_tscm_create_pcm_devices(struct snd_tscm *tscm) .prepare = pcm_capture_prepare, .trigger = pcm_capture_trigger, .pointer = pcm_capture_pointer, + .ack = pcm_capture_ack, .page = snd_pcm_lib_get_vmalloc_page, }; static const struct snd_pcm_ops playback_ops = { @@ -290,6 +277,7 @@ int snd_tscm_create_pcm_devices(struct snd_tscm *tscm) .prepare = pcm_playback_prepare, .trigger = pcm_playback_trigger, .pointer = pcm_playback_pointer, + .ack = pcm_playback_ack, .page = snd_pcm_lib_get_vmalloc_page, .mmap = snd_pcm_lib_mmap_vmalloc, }; diff --git a/sound/firewire/tascam/tascam.h b/sound/firewire/tascam/tascam.h index 08ecfae5c584..a5bd167eb5d9 100644 --- a/sound/firewire/tascam/tascam.h +++ b/sound/firewire/tascam/tascam.h @@ -131,7 +131,6 @@ int amdtp_tscm_init(struct amdtp_stream *s, struct fw_unit *unit, int amdtp_tscm_set_parameters(struct amdtp_stream *s, unsigned int rate); int amdtp_tscm_add_pcm_hw_constraints(struct amdtp_stream *s, struct snd_pcm_runtime *runtime); -void amdtp_tscm_set_pcm_format(struct amdtp_stream *s, snd_pcm_format_t format); int snd_tscm_stream_get_rate(struct snd_tscm *tscm, unsigned int *rate); int snd_tscm_stream_get_clock(struct snd_tscm *tscm, diff --git a/sound/hda/hdac_bus.c b/sound/hda/hdac_bus.c index 0e81ea89a596..714a51721a31 100644 --- a/sound/hda/hdac_bus.c +++ b/sound/hda/hdac_bus.c @@ -212,5 +212,6 @@ void snd_hdac_bus_remove_device(struct hdac_bus *bus, bus->caddr_tbl[codec->addr] = NULL; clear_bit(codec->addr, &bus->codec_powered); bus->num_codecs--; + flush_work(&bus->unsol_work); } EXPORT_SYMBOL_GPL(snd_hdac_bus_remove_device); diff --git a/sound/hda/hdac_device.c b/sound/hda/hdac_device.c index 03c9872c31cf..19deb306facb 100644 --- a/sound/hda/hdac_device.c +++ b/sound/hda/hdac_device.c @@ -159,6 +159,7 @@ void snd_hdac_device_unregister(struct hdac_device *codec) if (device_is_registered(&codec->dev)) { hda_widget_sysfs_exit(codec); device_del(&codec->dev); + snd_hdac_bus_remove_device(codec->bus, codec); } } EXPORT_SYMBOL_GPL(snd_hdac_device_unregister); diff --git a/sound/i2c/other/ak4113.c b/sound/i2c/other/ak4113.c index 2183e9ebaa6d..4099e6062d3c 100644 --- a/sound/i2c/other/ak4113.c +++ b/sound/i2c/other/ak4113.c @@ -199,12 +199,11 @@ static int snd_ak4113_in_error_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct ak4113 *chip = snd_kcontrol_chip(kcontrol); - long *ptr; spin_lock_irq(&chip->lock); - ptr = (long *)(((char *)chip) + kcontrol->private_value); - ucontrol->value.integer.value[0] = *ptr; - *ptr = 0; + ucontrol->value.integer.value[0] = + chip->errors[kcontrol->private_value]; + chip->errors[kcontrol->private_value] = 0; spin_unlock_irq(&chip->lock); return 0; } @@ -373,7 +372,7 @@ static struct snd_kcontrol_new snd_ak4113_iec958_controls[] = { SNDRV_CTL_ELEM_ACCESS_VOLATILE, .info = snd_ak4113_in_error_info, .get = snd_ak4113_in_error_get, - .private_value = offsetof(struct ak4113, parity_errors), + .private_value = AK4113_PARITY_ERRORS, }, { .iface = SNDRV_CTL_ELEM_IFACE_PCM, @@ -382,7 +381,7 @@ static struct snd_kcontrol_new snd_ak4113_iec958_controls[] = { SNDRV_CTL_ELEM_ACCESS_VOLATILE, .info = snd_ak4113_in_error_info, .get = snd_ak4113_in_error_get, - .private_value = offsetof(struct ak4113, v_bit_errors), + .private_value = AK4113_V_BIT_ERRORS, }, { .iface = SNDRV_CTL_ELEM_IFACE_PCM, @@ -391,7 +390,7 @@ static struct snd_kcontrol_new snd_ak4113_iec958_controls[] = { SNDRV_CTL_ELEM_ACCESS_VOLATILE, .info = snd_ak4113_in_error_info, .get = snd_ak4113_in_error_get, - .private_value = offsetof(struct ak4113, ccrc_errors), + .private_value = AK4113_CCRC_ERRORS, }, { .iface = SNDRV_CTL_ELEM_IFACE_PCM, @@ -400,7 +399,7 @@ static struct snd_kcontrol_new snd_ak4113_iec958_controls[] = { SNDRV_CTL_ELEM_ACCESS_VOLATILE, .info = snd_ak4113_in_error_info, .get = snd_ak4113_in_error_get, - .private_value = offsetof(struct ak4113, qcrc_errors), + .private_value = AK4113_QCRC_ERRORS, }, { .iface = SNDRV_CTL_ELEM_IFACE_PCM, @@ -551,13 +550,13 @@ int snd_ak4113_check_rate_and_errors(struct ak4113 *ak4113, unsigned int flags) rcs2 = reg_read(ak4113, AK4113_REG_RCS2); spin_lock_irqsave(&ak4113->lock, _flags); if (rcs0 & AK4113_PAR) - ak4113->parity_errors++; + ak4113->errors[AK4113_PARITY_ERRORS]++; if (rcs0 & AK4113_V) - ak4113->v_bit_errors++; + ak4113->errors[AK4113_V_BIT_ERRORS]++; if (rcs2 & AK4113_CCRC) - ak4113->ccrc_errors++; + ak4113->errors[AK4113_CCRC_ERRORS]++; if (rcs2 & AK4113_QCRC) - ak4113->qcrc_errors++; + ak4113->errors[AK4113_QCRC_ERRORS]++; c0 = (ak4113->rcs0 & (AK4113_QINT | AK4113_CINT | AK4113_STC | AK4113_AUDION | AK4113_AUTO | AK4113_UNLCK)) ^ (rcs0 & (AK4113_QINT | AK4113_CINT | AK4113_STC | diff --git a/sound/i2c/other/ak4114.c b/sound/i2c/other/ak4114.c index d53c9bb36281..7fb1aeb46915 100644 --- a/sound/i2c/other/ak4114.c +++ b/sound/i2c/other/ak4114.c @@ -194,12 +194,11 @@ static int snd_ak4114_in_error_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct ak4114 *chip = snd_kcontrol_chip(kcontrol); - long *ptr; spin_lock_irq(&chip->lock); - ptr = (long *)(((char *)chip) + kcontrol->private_value); - ucontrol->value.integer.value[0] = *ptr; - *ptr = 0; + ucontrol->value.integer.value[0] = + chip->errors[kcontrol->private_value]; + chip->errors[kcontrol->private_value] = 0; spin_unlock_irq(&chip->lock); return 0; } @@ -341,7 +340,7 @@ static struct snd_kcontrol_new snd_ak4114_iec958_controls[] = { .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, .info = snd_ak4114_in_error_info, .get = snd_ak4114_in_error_get, - .private_value = offsetof(struct ak4114, parity_errors), + .private_value = AK4114_PARITY_ERRORS, }, { .iface = SNDRV_CTL_ELEM_IFACE_PCM, @@ -349,7 +348,7 @@ static struct snd_kcontrol_new snd_ak4114_iec958_controls[] = { .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, .info = snd_ak4114_in_error_info, .get = snd_ak4114_in_error_get, - .private_value = offsetof(struct ak4114, v_bit_errors), + .private_value = AK4114_V_BIT_ERRORS, }, { .iface = SNDRV_CTL_ELEM_IFACE_PCM, @@ -357,7 +356,7 @@ static struct snd_kcontrol_new snd_ak4114_iec958_controls[] = { .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, .info = snd_ak4114_in_error_info, .get = snd_ak4114_in_error_get, - .private_value = offsetof(struct ak4114, ccrc_errors), + .private_value = AK4114_CCRC_ERRORS, }, { .iface = SNDRV_CTL_ELEM_IFACE_PCM, @@ -365,7 +364,7 @@ static struct snd_kcontrol_new snd_ak4114_iec958_controls[] = { .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, .info = snd_ak4114_in_error_info, .get = snd_ak4114_in_error_get, - .private_value = offsetof(struct ak4114, qcrc_errors), + .private_value = AK4114_QCRC_ERRORS, }, { .iface = SNDRV_CTL_ELEM_IFACE_PCM, @@ -581,13 +580,13 @@ int snd_ak4114_check_rate_and_errors(struct ak4114 *ak4114, unsigned int flags) rcs0 = reg_read(ak4114, AK4114_REG_RCS0); spin_lock_irqsave(&ak4114->lock, _flags); if (rcs0 & AK4114_PAR) - ak4114->parity_errors++; + ak4114->errors[AK4114_PARITY_ERRORS]++; if (rcs1 & AK4114_V) - ak4114->v_bit_errors++; + ak4114->errors[AK4114_V_BIT_ERRORS]++; if (rcs1 & AK4114_CCRC) - ak4114->ccrc_errors++; + ak4114->errors[AK4114_CCRC_ERRORS]++; if (rcs1 & AK4114_QCRC) - ak4114->qcrc_errors++; + ak4114->errors[AK4114_QCRC_ERRORS]++; c0 = (ak4114->rcs0 & (AK4114_QINT | AK4114_CINT | AK4114_PEM | AK4114_AUDION | AK4114_AUTO | AK4114_UNLCK)) ^ (rcs0 & (AK4114_QINT | AK4114_CINT | AK4114_PEM | AK4114_AUDION | AK4114_AUTO | AK4114_UNLCK)); c1 = (ak4114->rcs1 & 0xf0) ^ (rcs1 & 0xf0); diff --git a/sound/i2c/other/ak4117.c b/sound/i2c/other/ak4117.c index 0702f0552d19..3ab099fb8c15 100644 --- a/sound/i2c/other/ak4117.c +++ b/sound/i2c/other/ak4117.c @@ -168,12 +168,11 @@ static int snd_ak4117_in_error_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct ak4117 *chip = snd_kcontrol_chip(kcontrol); - long *ptr; spin_lock_irq(&chip->lock); - ptr = (long *)(((char *)chip) + kcontrol->private_value); - ucontrol->value.integer.value[0] = *ptr; - *ptr = 0; + ucontrol->value.integer.value[0] = + chip->errors[kcontrol->private_value]; + chip->errors[kcontrol->private_value] = 0; spin_unlock_irq(&chip->lock); return 0; } @@ -328,7 +327,7 @@ static struct snd_kcontrol_new snd_ak4117_iec958_controls[] = { .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, .info = snd_ak4117_in_error_info, .get = snd_ak4117_in_error_get, - .private_value = offsetof(struct ak4117, parity_errors), + .private_value = AK4117_PARITY_ERRORS, }, { .iface = SNDRV_CTL_ELEM_IFACE_PCM, @@ -336,7 +335,7 @@ static struct snd_kcontrol_new snd_ak4117_iec958_controls[] = { .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, .info = snd_ak4117_in_error_info, .get = snd_ak4117_in_error_get, - .private_value = offsetof(struct ak4117, v_bit_errors), + .private_value = AK4117_V_BIT_ERRORS, }, { .iface = SNDRV_CTL_ELEM_IFACE_PCM, @@ -344,7 +343,7 @@ static struct snd_kcontrol_new snd_ak4117_iec958_controls[] = { .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, .info = snd_ak4117_in_error_info, .get = snd_ak4117_in_error_get, - .private_value = offsetof(struct ak4117, ccrc_errors), + .private_value = AK4117_CCRC_ERRORS, }, { .iface = SNDRV_CTL_ELEM_IFACE_PCM, @@ -352,7 +351,7 @@ static struct snd_kcontrol_new snd_ak4117_iec958_controls[] = { .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, .info = snd_ak4117_in_error_info, .get = snd_ak4117_in_error_get, - .private_value = offsetof(struct ak4117, qcrc_errors), + .private_value = AK4117_QCRC_ERRORS, }, { .iface = SNDRV_CTL_ELEM_IFACE_PCM, @@ -470,13 +469,13 @@ int snd_ak4117_check_rate_and_errors(struct ak4117 *ak4117, unsigned int flags) // printk(KERN_DEBUG "AK IRQ: rcs0 = 0x%x, rcs1 = 0x%x, rcs2 = 0x%x\n", rcs0, rcs1, rcs2); spin_lock_irqsave(&ak4117->lock, _flags); if (rcs0 & AK4117_PAR) - ak4117->parity_errors++; + ak4117->errors[AK4117_PARITY_ERRORS]++; if (rcs0 & AK4117_V) - ak4117->v_bit_errors++; + ak4117->errors[AK4117_V_BIT_ERRORS]++; if (rcs2 & AK4117_CCRC) - ak4117->ccrc_errors++; + ak4117->errors[AK4117_CCRC_ERRORS]++; if (rcs2 & AK4117_QCRC) - ak4117->qcrc_errors++; + ak4117->errors[AK4117_QCRC_ERRORS]++; c0 = (ak4117->rcs0 & (AK4117_QINT | AK4117_CINT | AK4117_STC | AK4117_AUDION | AK4117_AUTO | AK4117_UNLCK)) ^ (rcs0 & (AK4117_QINT | AK4117_CINT | AK4117_STC | AK4117_AUDION | AK4117_AUTO | AK4117_UNLCK)); c1 = (ak4117->rcs1 & (AK4117_DTSCD | AK4117_NPCM | AK4117_PEM | 0x0f)) ^ diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig index 37adcc6cbe6b..cb54d9c0a77f 100644 --- a/sound/isa/Kconfig +++ b/sound/isa/Kconfig @@ -377,6 +377,7 @@ config SND_SBAWE select SND_OPL3_LIB select SND_MPU401_UART select SND_SB16_DSP + select SND_SEQ_DEVICE if SND_SEQUENCER != n help Say Y here to include support for Sound Blaster AWE soundcards (including the Plug and Play version). @@ -384,6 +385,13 @@ config SND_SBAWE To compile this driver as a module, choose M here: the module will be called snd-sbawe. +# select SEQ stuff to min(SND_SEQUENCER,SND_XXX) +config SND_SBAWE_SEQ + def_tristate SND_SEQUENCER && SND_SBAWE + select SND_SEQ_MIDI_EMUL + select SND_SEQ_VIRMIDI + select SND_SYNTH_EMUX + config SND_SB16_CSP bool "Sound Blaster 16/AWE CSP support" depends on (SND_SB16 || SND_SBAWE) && (BROKEN || !PPC) diff --git a/sound/isa/cmi8328.c b/sound/isa/cmi8328.c index 8e1756c3b9bb..d09e456107ad 100644 --- a/sound/isa/cmi8328.c +++ b/sound/isa/cmi8328.c @@ -26,7 +26,7 @@ MODULE_AUTHOR("Ondrej Zary <linux@rainbow-software.org>"); MODULE_DESCRIPTION("C-Media CMI8328"); MODULE_LICENSE("GPL"); -#if defined(CONFIG_GAMEPORT) || defined(CONFIG_GAMEPORT_MODULE) +#if IS_ENABLED(CONFIG_GAMEPORT) #define SUPPORT_JOYSTICK 1 #endif diff --git a/sound/isa/cs423x/cs4236_lib.c b/sound/isa/cs423x/cs4236_lib.c index 2b7cc596f4c6..2012936f6756 100644 --- a/sound/isa/cs423x/cs4236_lib.c +++ b/sound/isa/cs423x/cs4236_lib.c @@ -138,7 +138,7 @@ static unsigned char snd_cs4236_ctrl_in(struct snd_wss *chip, unsigned char reg) #define CLOCKS 8 -static struct snd_ratnum clocks[CLOCKS] = { +static const struct snd_ratnum clocks[CLOCKS] = { { .num = 16934400, .den_min = 353, .den_max = 353, .den_step = 1 }, { .num = 16934400, .den_min = 529, .den_max = 529, .den_step = 1 }, { .num = 16934400, .den_min = 617, .den_max = 617, .den_step = 1 }, @@ -149,7 +149,7 @@ static struct snd_ratnum clocks[CLOCKS] = { { .num = 16934400/16, .den_min = 21, .den_max = 192, .den_step = 1 } }; -static struct snd_pcm_hw_constraint_ratnums hw_constraints_clocks = { +static const struct snd_pcm_hw_constraint_ratnums hw_constraints_clocks = { .nrats = CLOCKS, .rats = clocks, }; diff --git a/sound/isa/es1688/es1688_lib.c b/sound/isa/es1688/es1688_lib.c index 81cf26fa28d6..5d3df96c5e5b 100644 --- a/sound/isa/es1688/es1688_lib.c +++ b/sound/isa/es1688/es1688_lib.c @@ -290,7 +290,7 @@ static int snd_es1688_init(struct snd_es1688 * chip, int enable) */ -static struct snd_ratnum clocks[2] = { +static const struct snd_ratnum clocks[2] = { { .num = 795444, .den_min = 1, @@ -305,7 +305,7 @@ static struct snd_ratnum clocks[2] = { } }; -static struct snd_pcm_hw_constraint_ratnums hw_constraints_clocks = { +static const struct snd_pcm_hw_constraint_ratnums hw_constraints_clocks = { .nrats = 2, .rats = clocks, }; diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c index 0cabe2b8974f..ae17a6584061 100644 --- a/sound/isa/es18xx.c +++ b/sound/isa/es18xx.c @@ -369,7 +369,7 @@ static int snd_es18xx_reset_fifo(struct snd_es18xx *chip) return 0; } -static struct snd_ratnum new_clocks[2] = { +static const struct snd_ratnum new_clocks[2] = { { .num = 793800, .den_min = 1, @@ -384,12 +384,12 @@ static struct snd_ratnum new_clocks[2] = { } }; -static struct snd_pcm_hw_constraint_ratnums new_hw_constraints_clocks = { +static const struct snd_pcm_hw_constraint_ratnums new_hw_constraints_clocks = { .nrats = 2, .rats = new_clocks, }; -static struct snd_ratnum old_clocks[2] = { +static const struct snd_ratnum old_clocks[2] = { { .num = 795444, .den_min = 1, @@ -404,7 +404,7 @@ static struct snd_ratnum old_clocks[2] = { } }; -static struct snd_pcm_hw_constraint_ratnums old_hw_constraints_clocks = { +static const struct snd_pcm_hw_constraint_ratnums old_hw_constraints_clocks = { .nrats = 2, .rats = old_clocks, }; diff --git a/sound/isa/gus/gus_main.c b/sound/isa/gus/gus_main.c index 4490ee442ff4..3cf9b13c780a 100644 --- a/sound/isa/gus/gus_main.c +++ b/sound/isa/gus/gus_main.c @@ -82,7 +82,7 @@ static int snd_gus_joystick_put(struct snd_kcontrol *kcontrol, struct snd_ctl_el return change; } -static struct snd_kcontrol_new snd_gus_joystick_control = { +static const struct snd_kcontrol_new snd_gus_joystick_control = { .iface = SNDRV_CTL_ELEM_IFACE_CARD, .name = "Joystick Speed", .info = snd_gus_joystick_info, diff --git a/sound/isa/gus/gus_pcm.c b/sound/isa/gus/gus_pcm.c index 06505999155f..6b3da01a93b7 100644 --- a/sound/isa/gus/gus_pcm.c +++ b/sound/isa/gus/gus_pcm.c @@ -61,8 +61,6 @@ struct gus_pcm_private { int final_volume; }; -static int snd_gf1_pcm_use_dma = 1; - static void snd_gf1_pcm_block_change_ack(struct snd_gus_card * gus, void *private_data) { struct gus_pcm_private *pcmp = private_data; @@ -355,66 +353,83 @@ static int snd_gf1_pcm_poke_block(struct snd_gus_card *gus, unsigned char *buf, return 0; } -static int snd_gf1_pcm_playback_copy(struct snd_pcm_substream *substream, - int voice, - snd_pcm_uframes_t pos, - void __user *src, - snd_pcm_uframes_t count) +static int get_bpos(struct gus_pcm_private *pcmp, int voice, unsigned int pos, + unsigned int len) { - struct snd_pcm_runtime *runtime = substream->runtime; - struct gus_pcm_private *pcmp = runtime->private_data; - unsigned int bpos, len; - - bpos = samples_to_bytes(runtime, pos) + (voice * (pcmp->dma_size / 2)); - len = samples_to_bytes(runtime, count); + unsigned int bpos = pos + (voice * (pcmp->dma_size / 2)); if (snd_BUG_ON(bpos > pcmp->dma_size)) return -EIO; if (snd_BUG_ON(bpos + len > pcmp->dma_size)) return -EIO; + return bpos; +} + +static int playback_copy_ack(struct snd_pcm_substream *substream, + unsigned int bpos, unsigned int len) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct gus_pcm_private *pcmp = runtime->private_data; + struct snd_gus_card *gus = pcmp->gus; + int w16, invert; + + if (len > 32) + return snd_gf1_pcm_block_change(substream, bpos, + pcmp->memory + bpos, len); + + w16 = (snd_pcm_format_width(runtime->format) == 16); + invert = snd_pcm_format_unsigned(runtime->format); + return snd_gf1_pcm_poke_block(gus, runtime->dma_area + bpos, + pcmp->memory + bpos, len, w16, invert); +} + +static int snd_gf1_pcm_playback_copy(struct snd_pcm_substream *substream, + int voice, unsigned long pos, + void __user *src, unsigned long count) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct gus_pcm_private *pcmp = runtime->private_data; + unsigned int len = count; + int bpos; + + bpos = get_bpos(pcmp, voice, pos, len); + if (bpos < 0) + return pos; if (copy_from_user(runtime->dma_area + bpos, src, len)) return -EFAULT; - if (snd_gf1_pcm_use_dma && len > 32) { - return snd_gf1_pcm_block_change(substream, bpos, pcmp->memory + bpos, len); - } else { - struct snd_gus_card *gus = pcmp->gus; - int err, w16, invert; + return playback_copy_ack(substream, bpos, len); +} - w16 = (snd_pcm_format_width(runtime->format) == 16); - invert = snd_pcm_format_unsigned(runtime->format); - if ((err = snd_gf1_pcm_poke_block(gus, runtime->dma_area + bpos, pcmp->memory + bpos, len, w16, invert)) < 0) - return err; - } - return 0; +static int snd_gf1_pcm_playback_copy_kernel(struct snd_pcm_substream *substream, + int voice, unsigned long pos, + void *src, unsigned long count) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct gus_pcm_private *pcmp = runtime->private_data; + unsigned int len = count; + int bpos; + + bpos = get_bpos(pcmp, voice, pos, len); + if (bpos < 0) + return pos; + memcpy(runtime->dma_area + bpos, src, len); + return playback_copy_ack(substream, bpos, len); } static int snd_gf1_pcm_playback_silence(struct snd_pcm_substream *substream, - int voice, - snd_pcm_uframes_t pos, - snd_pcm_uframes_t count) + int voice, unsigned long pos, + unsigned long count) { struct snd_pcm_runtime *runtime = substream->runtime; struct gus_pcm_private *pcmp = runtime->private_data; - unsigned int bpos, len; + unsigned int len = count; + int bpos; - bpos = samples_to_bytes(runtime, pos) + (voice * (pcmp->dma_size / 2)); - len = samples_to_bytes(runtime, count); - if (snd_BUG_ON(bpos > pcmp->dma_size)) - return -EIO; - if (snd_BUG_ON(bpos + len > pcmp->dma_size)) - return -EIO; - snd_pcm_format_set_silence(runtime->format, runtime->dma_area + bpos, count); - if (snd_gf1_pcm_use_dma && len > 32) { - return snd_gf1_pcm_block_change(substream, bpos, pcmp->memory + bpos, len); - } else { - struct snd_gus_card *gus = pcmp->gus; - int err, w16, invert; - - w16 = (snd_pcm_format_width(runtime->format) == 16); - invert = snd_pcm_format_unsigned(runtime->format); - if ((err = snd_gf1_pcm_poke_block(gus, runtime->dma_area + bpos, pcmp->memory + bpos, len, w16, invert)) < 0) - return err; - } - return 0; + bpos = get_bpos(pcmp, voice, pos, len); + if (bpos < 0) + return pos; + snd_pcm_format_set_silence(runtime->format, runtime->dma_area + bpos, + bytes_to_samples(runtime, count)); + return playback_copy_ack(substream, bpos, len); } static int snd_gf1_pcm_playback_hw_params(struct snd_pcm_substream *substream, @@ -547,14 +562,14 @@ static snd_pcm_uframes_t snd_gf1_pcm_playback_pointer(struct snd_pcm_substream * return pos; } -static struct snd_ratnum clock = { +static const struct snd_ratnum clock = { .num = 9878400/16, .den_min = 2, .den_max = 257, .den_step = 1, }; -static struct snd_pcm_hw_constraint_ratnums hw_constraints_clocks = { +static const struct snd_pcm_hw_constraint_ratnums hw_constraints_clocks = { .nrats = 1, .rats = &clock, }; @@ -809,7 +824,7 @@ static int snd_gf1_pcm_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ return change; } -static struct snd_kcontrol_new snd_gf1_pcm_volume_control = +static const struct snd_kcontrol_new snd_gf1_pcm_volume_control = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "PCM Playback Volume", @@ -818,7 +833,7 @@ static struct snd_kcontrol_new snd_gf1_pcm_volume_control = .put = snd_gf1_pcm_volume_put }; -static struct snd_kcontrol_new snd_gf1_pcm_volume_control1 = +static const struct snd_kcontrol_new snd_gf1_pcm_volume_control1 = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "GPCM Playback Volume", @@ -836,8 +851,9 @@ static struct snd_pcm_ops snd_gf1_pcm_playback_ops = { .prepare = snd_gf1_pcm_playback_prepare, .trigger = snd_gf1_pcm_playback_trigger, .pointer = snd_gf1_pcm_playback_pointer, - .copy = snd_gf1_pcm_playback_copy, - .silence = snd_gf1_pcm_playback_silence, + .copy_user = snd_gf1_pcm_playback_copy, + .copy_kernel = snd_gf1_pcm_playback_copy_kernel, + .fill_silence = snd_gf1_pcm_playback_silence, }; static struct snd_pcm_ops snd_gf1_pcm_capture_ops = { diff --git a/sound/isa/msnd/msnd_midi.c b/sound/isa/msnd/msnd_midi.c index 912b5a9ccbab..013d8d1170fe 100644 --- a/sound/isa/msnd/msnd_midi.c +++ b/sound/isa/msnd/msnd_midi.c @@ -120,24 +120,24 @@ void snd_msndmidi_input_read(void *mpuv) unsigned long flags; struct snd_msndmidi *mpu = mpuv; void *pwMIDQData = mpu->dev->mappedbase + MIDQ_DATA_BUFF; + u16 head, tail, size; spin_lock_irqsave(&mpu->input_lock, flags); - while (readw(mpu->dev->MIDQ + JQS_wTail) != - readw(mpu->dev->MIDQ + JQS_wHead)) { - u16 wTmp, val; - val = readw(pwMIDQData + 2 * readw(mpu->dev->MIDQ + JQS_wHead)); - - if (test_bit(MSNDMIDI_MODE_BIT_INPUT_TRIGGER, - &mpu->mode)) - snd_rawmidi_receive(mpu->substream_input, - (unsigned char *)&val, 1); - - wTmp = readw(mpu->dev->MIDQ + JQS_wHead) + 1; - if (wTmp > readw(mpu->dev->MIDQ + JQS_wSize)) - writew(0, mpu->dev->MIDQ + JQS_wHead); - else - writew(wTmp, mpu->dev->MIDQ + JQS_wHead); + head = readw(mpu->dev->MIDQ + JQS_wHead); + tail = readw(mpu->dev->MIDQ + JQS_wTail); + size = readw(mpu->dev->MIDQ + JQS_wSize); + if (head > size || tail > size) + goto out; + while (head != tail) { + unsigned char val = readw(pwMIDQData + 2 * head); + + if (test_bit(MSNDMIDI_MODE_BIT_INPUT_TRIGGER, &mpu->mode)) + snd_rawmidi_receive(mpu->substream_input, &val, 1); + if (++head > size) + head = 0; + writew(head, mpu->dev->MIDQ + JQS_wHead); } + out: spin_unlock_irqrestore(&mpu->input_lock, flags); } EXPORT_SYMBOL(snd_msndmidi_input_read); diff --git a/sound/isa/msnd/msnd_pinnacle.c b/sound/isa/msnd/msnd_pinnacle.c index ad4897337df5..fc4fb1904aef 100644 --- a/sound/isa/msnd/msnd_pinnacle.c +++ b/sound/isa/msnd/msnd_pinnacle.c @@ -170,23 +170,24 @@ static irqreturn_t snd_msnd_interrupt(int irq, void *dev_id) { struct snd_msnd *chip = dev_id; void *pwDSPQData = chip->mappedbase + DSPQ_DATA_BUFF; + u16 head, tail, size; /* Send ack to DSP */ /* inb(chip->io + HP_RXL); */ /* Evaluate queued DSP messages */ - while (readw(chip->DSPQ + JQS_wTail) != readw(chip->DSPQ + JQS_wHead)) { - u16 wTmp; - - snd_msnd_eval_dsp_msg(chip, - readw(pwDSPQData + 2 * readw(chip->DSPQ + JQS_wHead))); - - wTmp = readw(chip->DSPQ + JQS_wHead) + 1; - if (wTmp > readw(chip->DSPQ + JQS_wSize)) - writew(0, chip->DSPQ + JQS_wHead); - else - writew(wTmp, chip->DSPQ + JQS_wHead); + head = readw(chip->DSPQ + JQS_wHead); + tail = readw(chip->DSPQ + JQS_wTail); + size = readw(chip->DSPQ + JQS_wSize); + if (head > size || tail > size) + goto out; + while (head != tail) { + snd_msnd_eval_dsp_msg(chip, readw(pwDSPQData + 2 * head)); + if (++head > size) + head = 0; + writew(head, chip->DSPQ + JQS_wHead); } + out: /* Send ack to DSP */ inb(chip->io + HP_RXL); return IRQ_HANDLED; diff --git a/sound/isa/sb/emu8000.c b/sound/isa/sb/emu8000.c index ec180708f160..d56973b770c7 100644 --- a/sound/isa/sb/emu8000.c +++ b/sound/isa/sb/emu8000.c @@ -1138,7 +1138,7 @@ snd_emu8000_new(struct snd_card *card, int index, long port, int seq_ports, snd_emu8000_free(hw); return err; } -#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE)) +#if IS_ENABLED(CONFIG_SND_SEQUENCER) if (snd_seq_device_new(card, index, SNDRV_SEQ_DEV_ID_EMU8000, sizeof(struct snd_emu8000*), &awe) >= 0) { strcpy(awe->name, "EMU-8000"); diff --git a/sound/isa/sb/emu8000_callback.c b/sound/isa/sb/emu8000_callback.c index 72a9ac5efb40..d28d712f99f4 100644 --- a/sound/isa/sb/emu8000_callback.c +++ b/sound/isa/sb/emu8000_callback.c @@ -36,7 +36,7 @@ static void reset_voice(struct snd_emux *emu, int ch); static void terminate_voice(struct snd_emux_voice *vp); static void sysex(struct snd_emux *emu, char *buf, int len, int parsed, struct snd_midi_channel_set *chset); -#ifdef CONFIG_SND_SEQUENCER_OSS +#if IS_ENABLED(CONFIG_SND_SEQUENCER_OSS) static int oss_ioctl(struct snd_emux *emu, int cmd, int p1, int p2); #endif static int load_fx(struct snd_emux *emu, int type, int mode, @@ -76,7 +76,7 @@ static struct snd_emux_operators emu8000_ops = { .sample_reset = snd_emu8000_sample_reset, .load_fx = load_fx, .sysex = sysex, -#ifdef CONFIG_SND_SEQUENCER_OSS +#if IS_ENABLED(CONFIG_SND_SEQUENCER_OSS) .oss_ioctl = oss_ioctl, #endif }; @@ -477,7 +477,7 @@ sysex(struct snd_emux *emu, char *buf, int len, int parsed, struct snd_midi_chan } -#ifdef CONFIG_SND_SEQUENCER_OSS +#if IS_ENABLED(CONFIG_SND_SEQUENCER_OSS) /* * OSS ioctl callback */ diff --git a/sound/isa/sb/emu8000_pcm.c b/sound/isa/sb/emu8000_pcm.c index 32f234f494e5..2ee8d67871ec 100644 --- a/sound/isa/sb/emu8000_pcm.c +++ b/sound/isa/sb/emu8000_pcm.c @@ -422,143 +422,148 @@ do { \ return -EAGAIN;\ } while (0) +enum { + COPY_USER, COPY_KERNEL, FILL_SILENCE, +}; + +#define GET_VAL(sval, buf, mode) \ + do { \ + switch (mode) { \ + case FILL_SILENCE: \ + sval = 0; \ + break; \ + case COPY_KERNEL: \ + sval = *buf++; \ + break; \ + default: \ + if (get_user(sval, (unsigned short __user *)buf)) \ + return -EFAULT; \ + buf++; \ + break; \ + } \ + } while (0) #ifdef USE_NONINTERLEAVE + +#define LOOP_WRITE(rec, offset, _buf, count, mode) \ + do { \ + struct snd_emu8000 *emu = (rec)->emu; \ + unsigned short *buf = (unsigned short *)(_buf); \ + snd_emu8000_write_wait(emu, 1); \ + EMU8000_SMALW_WRITE(emu, offset); \ + while (count > 0) { \ + unsigned short sval; \ + CHECK_SCHEDULER(); \ + GET_VAL(sval, buf, mode); \ + EMU8000_SMLD_WRITE(emu, sval); \ + count--; \ + } \ + } while (0) + /* copy one channel block */ -static int emu8k_transfer_block(struct snd_emu8000 *emu, int offset, unsigned short *buf, int count) +static int emu8k_pcm_copy(struct snd_pcm_substream *subs, + int voice, unsigned long pos, + void __user *src, unsigned long count) { - EMU8000_SMALW_WRITE(emu, offset); - while (count > 0) { - unsigned short sval; - CHECK_SCHEDULER(); - if (get_user(sval, buf)) - return -EFAULT; - EMU8000_SMLD_WRITE(emu, sval); - buf++; - count--; - } + struct snd_emu8k_pcm *rec = subs->runtime->private_data; + + /* convert to word unit */ + pos = (pos << 1) + rec->loop_start[voice]; + count <<= 1; + LOOP_WRITE(rec, pos, src, count, COPY_UESR); return 0; } -static int emu8k_pcm_copy(struct snd_pcm_substream *subs, - int voice, - snd_pcm_uframes_t pos, - void *src, - snd_pcm_uframes_t count) +static int emu8k_pcm_copy_kernel(struct snd_pcm_substream *subs, + int voice, unsigned long pos, + void *src, unsigned long count) { struct snd_emu8k_pcm *rec = subs->runtime->private_data; - struct snd_emu8000 *emu = rec->emu; - - snd_emu8000_write_wait(emu, 1); - if (voice == -1) { - unsigned short *buf = src; - int i, err; - count /= rec->voices; - for (i = 0; i < rec->voices; i++) { - err = emu8k_transfer_block(emu, pos + rec->loop_start[i], buf, count); - if (err < 0) - return err; - buf += count; - } - return 0; - } else { - return emu8k_transfer_block(emu, pos + rec->loop_start[voice], src, count); - } -} -/* make a channel block silence */ -static int emu8k_silence_block(struct snd_emu8000 *emu, int offset, int count) -{ - EMU8000_SMALW_WRITE(emu, offset); - while (count > 0) { - CHECK_SCHEDULER(); - EMU8000_SMLD_WRITE(emu, 0); - count--; - } + /* convert to word unit */ + pos = (pos << 1) + rec->loop_start[voice]; + count <<= 1; + LOOP_WRITE(rec, pos, src, count, COPY_KERNEL); return 0; } +/* make a channel block silence */ static int emu8k_pcm_silence(struct snd_pcm_substream *subs, - int voice, - snd_pcm_uframes_t pos, - snd_pcm_uframes_t count) + int voice, unsigned long pos, unsigned long count) { struct snd_emu8k_pcm *rec = subs->runtime->private_data; - struct snd_emu8000 *emu = rec->emu; - - snd_emu8000_write_wait(emu, 1); - if (voice == -1 && rec->voices == 1) - voice = 0; - if (voice == -1) { - int err; - err = emu8k_silence_block(emu, pos + rec->loop_start[0], count / 2); - if (err < 0) - return err; - return emu8k_silence_block(emu, pos + rec->loop_start[1], count / 2); - } else { - return emu8k_silence_block(emu, pos + rec->loop_start[voice], count); - } + + /* convert to word unit */ + pos = (pos << 1) + rec->loop_start[voice]; + count <<= 1; + LOOP_WRITE(rec, pos, NULL, count, FILL_SILENCE); + return 0; } #else /* interleave */ +#define LOOP_WRITE(rec, pos, _buf, count, mode) \ + do { \ + struct snd_emu8000 *emu = rec->emu; \ + unsigned short *buf = (unsigned short *)(_buf); \ + snd_emu8000_write_wait(emu, 1); \ + EMU8000_SMALW_WRITE(emu, pos + rec->loop_start[0]); \ + if (rec->voices > 1) \ + EMU8000_SMARW_WRITE(emu, pos + rec->loop_start[1]); \ + while (count > 0) { \ + unsigned short sval; \ + CHECK_SCHEDULER(); \ + GET_VAL(sval, buf, mode); \ + EMU8000_SMLD_WRITE(emu, sval); \ + if (rec->voices > 1) { \ + CHECK_SCHEDULER(); \ + GET_VAL(sval, buf, mode); \ + EMU8000_SMRD_WRITE(emu, sval); \ + } \ + count--; \ + } \ + } while (0) + + /* * copy the interleaved data can be done easily by using * DMA "left" and "right" channels on emu8k engine. */ static int emu8k_pcm_copy(struct snd_pcm_substream *subs, - int voice, - snd_pcm_uframes_t pos, - void __user *src, - snd_pcm_uframes_t count) + int voice, unsigned long pos, + void __user *src, unsigned long count) { struct snd_emu8k_pcm *rec = subs->runtime->private_data; - struct snd_emu8000 *emu = rec->emu; - unsigned short __user *buf = src; - snd_emu8000_write_wait(emu, 1); - EMU8000_SMALW_WRITE(emu, pos + rec->loop_start[0]); - if (rec->voices > 1) - EMU8000_SMARW_WRITE(emu, pos + rec->loop_start[1]); - - while (count-- > 0) { - unsigned short sval; - CHECK_SCHEDULER(); - if (get_user(sval, buf)) - return -EFAULT; - EMU8000_SMLD_WRITE(emu, sval); - buf++; - if (rec->voices > 1) { - CHECK_SCHEDULER(); - if (get_user(sval, buf)) - return -EFAULT; - EMU8000_SMRD_WRITE(emu, sval); - buf++; - } - } + /* convert to frames */ + pos = bytes_to_frames(subs->runtime, pos); + count = bytes_to_frames(subs->runtime, count); + LOOP_WRITE(rec, pos, src, count, COPY_USER); + return 0; +} + +static int emu8k_pcm_copy_kernel(struct snd_pcm_substream *subs, + int voice, unsigned long pos, + void *src, unsigned long count) +{ + struct snd_emu8k_pcm *rec = subs->runtime->private_data; + + /* convert to frames */ + pos = bytes_to_frames(subs->runtime, pos); + count = bytes_to_frames(subs->runtime, count); + LOOP_WRITE(rec, pos, src, count, COPY_KERNEL); return 0; } static int emu8k_pcm_silence(struct snd_pcm_substream *subs, - int voice, - snd_pcm_uframes_t pos, - snd_pcm_uframes_t count) + int voice, unsigned long pos, unsigned long count) { struct snd_emu8k_pcm *rec = subs->runtime->private_data; - struct snd_emu8000 *emu = rec->emu; - snd_emu8000_write_wait(emu, 1); - EMU8000_SMALW_WRITE(emu, rec->loop_start[0] + pos); - if (rec->voices > 1) - EMU8000_SMARW_WRITE(emu, rec->loop_start[1] + pos); - while (count-- > 0) { - CHECK_SCHEDULER(); - EMU8000_SMLD_WRITE(emu, 0); - if (rec->voices > 1) { - CHECK_SCHEDULER(); - EMU8000_SMRD_WRITE(emu, 0); - } - } + /* convert to frames */ + pos = bytes_to_frames(subs->runtime, pos); + count = bytes_to_frames(subs->runtime, count); + LOOP_WRITE(rec, pos, NULL, count, FILL_SILENCE); return 0; } #endif @@ -674,8 +679,9 @@ static struct snd_pcm_ops emu8k_pcm_ops = { .prepare = emu8k_pcm_prepare, .trigger = emu8k_pcm_trigger, .pointer = emu8k_pcm_pointer, - .copy = emu8k_pcm_copy, - .silence = emu8k_pcm_silence, + .copy_user = emu8k_pcm_copy, + .copy_kernel = emu8k_pcm_copy_kernel, + .fill_silence = emu8k_pcm_silence, }; diff --git a/sound/isa/sb/sb16.c b/sound/isa/sb/sb16.c index 3b2e4f405ff2..917a93d696c3 100644 --- a/sound/isa/sb/sb16.c +++ b/sound/isa/sb/sb16.c @@ -62,7 +62,7 @@ MODULE_SUPPORTED_DEVICE("{{Creative Labs,SB AWE 32}," #define SNDRV_DEBUG_IRQ #endif -#if defined(SNDRV_SBAWE) && (defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))) +#if defined(SNDRV_SBAWE) && IS_ENABLED(CONFIG_SND_SEQUENCER) #define SNDRV_SBAWE_EMU8000 #endif diff --git a/sound/isa/sb/sb16_csp.c b/sound/isa/sb/sb16_csp.c index 48da2276683d..fa5780bb0c68 100644 --- a/sound/isa/sb/sb16_csp.c +++ b/sound/isa/sb/sb16_csp.c @@ -1029,7 +1029,7 @@ static int snd_sb_qsound_space_put(struct snd_kcontrol *kcontrol, struct snd_ctl return change; } -static struct snd_kcontrol_new snd_sb_qsound_switch = { +static const struct snd_kcontrol_new snd_sb_qsound_switch = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "3D Control - Switch", .info = snd_sb_qsound_switch_info, @@ -1037,7 +1037,7 @@ static struct snd_kcontrol_new snd_sb_qsound_switch = { .put = snd_sb_qsound_switch_put }; -static struct snd_kcontrol_new snd_sb_qsound_space = { +static const struct snd_kcontrol_new snd_sb_qsound_space = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "3D Control - Space", .info = snd_sb_qsound_space_info, diff --git a/sound/isa/sb/sb16_main.c b/sound/isa/sb/sb16_main.c index 8b2d6c6bfe97..4be1350f6649 100644 --- a/sound/isa/sb/sb16_main.c +++ b/sound/isa/sb/sb16_main.c @@ -737,7 +737,7 @@ static int snd_sb16_dma_control_put(struct snd_kcontrol *kcontrol, struct snd_ct return change; } -static struct snd_kcontrol_new snd_sb16_dma_control = { +static const struct snd_kcontrol_new snd_sb16_dma_control = { .iface = SNDRV_CTL_ELEM_IFACE_CARD, .name = "16-bit DMA Allocation", .info = snd_sb16_dma_control_info, diff --git a/sound/isa/sb/sb8_main.c b/sound/isa/sb/sb8_main.c index 9043397fe62f..0f302be4fb6d 100644 --- a/sound/isa/sb/sb8_main.c +++ b/sound/isa/sb/sb8_main.c @@ -46,19 +46,19 @@ MODULE_LICENSE("GPL"); #define SB8_DEN(v) ((SB8_CLOCK + (v) / 2) / (v)) #define SB8_RATE(v) (SB8_CLOCK / SB8_DEN(v)) -static struct snd_ratnum clock = { +static const struct snd_ratnum clock = { .num = SB8_CLOCK, .den_min = 1, .den_max = 256, .den_step = 1, }; -static struct snd_pcm_hw_constraint_ratnums hw_constraints_clock = { +static const struct snd_pcm_hw_constraint_ratnums hw_constraints_clock = { .nrats = 1, .rats = &clock, }; -static struct snd_ratnum stereo_clocks[] = { +static const struct snd_ratnum stereo_clocks[] = { { .num = SB8_CLOCK, .den_min = SB8_DEN(22050), diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c index 54f5758a1bb3..1cd2908e4f12 100644 --- a/sound/isa/sscape.c +++ b/sound/isa/sscape.c @@ -671,7 +671,7 @@ __skip_change: return change; } -static struct snd_kcontrol_new midi_mixer_ctl = { +static const struct snd_kcontrol_new midi_mixer_ctl = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "MIDI", .info = sscape_midi_info, diff --git a/sound/isa/wavefront/wavefront_synth.c b/sound/isa/wavefront/wavefront_synth.c index 4dae9ff9ef5a..0b1e4b34b299 100644 --- a/sound/isa/wavefront/wavefront_synth.c +++ b/sound/isa/wavefront/wavefront_synth.c @@ -1782,7 +1782,7 @@ wavefront_should_cause_interrupt (snd_wavefront_t *dev, int val, int port, unsigned long timeout) { - wait_queue_t wait; + wait_queue_entry_t wait; init_waitqueue_entry(&wait, current); spin_lock_irq(&dev->irq_lock); diff --git a/sound/isa/wss/wss_lib.c b/sound/isa/wss/wss_lib.c index 913b731d2236..9f4e2e34cbe1 100644 --- a/sound/isa/wss/wss_lib.c +++ b/sound/isa/wss/wss_lib.c @@ -69,12 +69,12 @@ static unsigned char freq_bits[14] = { /* 48000 */ 0x0C | CS4231_XTAL1 }; -static unsigned int rates[14] = { +static const unsigned int rates[14] = { 5510, 6620, 8000, 9600, 11025, 16000, 18900, 22050, 27042, 32000, 33075, 37800, 44100, 48000 }; -static struct snd_pcm_hw_constraint_list hw_constraints_rates = { +static const struct snd_pcm_hw_constraint_list hw_constraints_rates = { .count = ARRAY_SIZE(rates), .list = rates, .mask = 0, diff --git a/sound/mips/hal2.c b/sound/mips/hal2.c index 00fc9241d266..3318c15e324a 100644 --- a/sound/mips/hal2.c +++ b/sound/mips/hal2.c @@ -264,7 +264,7 @@ static int hal2_gain_put(struct snd_kcontrol *kcontrol, return old != new; } -static struct snd_kcontrol_new hal2_ctrl_headphone = { +static const struct snd_kcontrol_new hal2_ctrl_headphone = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Headphone Playback Volume", .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, @@ -274,7 +274,7 @@ static struct snd_kcontrol_new hal2_ctrl_headphone = { .put = hal2_gain_put, }; -static struct snd_kcontrol_new hal2_ctrl_mic = { +static const struct snd_kcontrol_new hal2_ctrl_mic = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Mic Capture Volume", .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, @@ -461,15 +461,15 @@ static int hal2_alloc_dmabuf(struct hal2_codec *codec) int count = H2_BUF_SIZE / H2_BLOCK_SIZE; int i; - codec->buffer = dma_alloc_noncoherent(NULL, H2_BUF_SIZE, - &buffer_dma, GFP_KERNEL); + codec->buffer = dma_alloc_attrs(NULL, H2_BUF_SIZE, &buffer_dma, + GFP_KERNEL, DMA_ATTR_NON_CONSISTENT); if (!codec->buffer) return -ENOMEM; - desc = dma_alloc_noncoherent(NULL, count * sizeof(struct hal2_desc), - &desc_dma, GFP_KERNEL); + desc = dma_alloc_attrs(NULL, count * sizeof(struct hal2_desc), + &desc_dma, GFP_KERNEL, DMA_ATTR_NON_CONSISTENT); if (!desc) { - dma_free_noncoherent(NULL, H2_BUF_SIZE, - codec->buffer, buffer_dma); + dma_free_attrs(NULL, H2_BUF_SIZE, codec->buffer, buffer_dma, + DMA_ATTR_NON_CONSISTENT); return -ENOMEM; } codec->buffer_dma = buffer_dma; @@ -490,10 +490,10 @@ static int hal2_alloc_dmabuf(struct hal2_codec *codec) static void hal2_free_dmabuf(struct hal2_codec *codec) { - dma_free_noncoherent(NULL, codec->desc_count * sizeof(struct hal2_desc), - codec->desc, codec->desc_dma); - dma_free_noncoherent(NULL, H2_BUF_SIZE, codec->buffer, - codec->buffer_dma); + dma_free_attrs(NULL, codec->desc_count * sizeof(struct hal2_desc), + codec->desc, codec->desc_dma, DMA_ATTR_NON_CONSISTENT); + dma_free_attrs(NULL, H2_BUF_SIZE, codec->buffer, codec->buffer_dma, + DMA_ATTR_NON_CONSISTENT); } static struct snd_pcm_hardware hal2_pcm_hw = { @@ -616,10 +616,9 @@ static int hal2_playback_ack(struct snd_pcm_substream *substream) struct hal2_codec *dac = &hal2->dac; dac->pcm_indirect.hw_queue_size = H2_BUF_SIZE / 2; - snd_pcm_indirect_playback_transfer(substream, - &dac->pcm_indirect, - hal2_playback_transfer); - return 0; + return snd_pcm_indirect_playback_transfer(substream, + &dac->pcm_indirect, + hal2_playback_transfer); } static int hal2_capture_open(struct snd_pcm_substream *substream) @@ -707,10 +706,9 @@ static int hal2_capture_ack(struct snd_pcm_substream *substream) struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream); struct hal2_codec *adc = &hal2->adc; - snd_pcm_indirect_capture_transfer(substream, - &adc->pcm_indirect, - hal2_capture_transfer); - return 0; + return snd_pcm_indirect_capture_transfer(substream, + &adc->pcm_indirect, + hal2_capture_transfer); } static struct snd_pcm_ops hal2_playback_ops = { diff --git a/sound/mips/sgio2audio.c b/sound/mips/sgio2audio.c index f07aa3993f83..0ebc1c3727df 100644 --- a/sound/mips/sgio2audio.c +++ b/sound/mips/sgio2audio.c @@ -230,7 +230,7 @@ static int sgio2audio_source_put(struct snd_kcontrol *kcontrol, } /* dac1/pcm0 mixer control */ -static struct snd_kcontrol_new sgio2audio_ctrl_pcm0 = { +static const struct snd_kcontrol_new sgio2audio_ctrl_pcm0 = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "PCM Playback Volume", .index = 0, @@ -242,7 +242,7 @@ static struct snd_kcontrol_new sgio2audio_ctrl_pcm0 = { }; /* dac2/pcm1 mixer control */ -static struct snd_kcontrol_new sgio2audio_ctrl_pcm1 = { +static const struct snd_kcontrol_new sgio2audio_ctrl_pcm1 = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "PCM Playback Volume", .index = 1, @@ -254,7 +254,7 @@ static struct snd_kcontrol_new sgio2audio_ctrl_pcm1 = { }; /* record level mixer control */ -static struct snd_kcontrol_new sgio2audio_ctrl_reclevel = { +static const struct snd_kcontrol_new sgio2audio_ctrl_reclevel = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Capture Volume", .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, @@ -265,7 +265,7 @@ static struct snd_kcontrol_new sgio2audio_ctrl_reclevel = { }; /* record level source control */ -static struct snd_kcontrol_new sgio2audio_ctrl_recsource = { +static const struct snd_kcontrol_new sgio2audio_ctrl_recsource = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Capture Source", .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, @@ -275,7 +275,7 @@ static struct snd_kcontrol_new sgio2audio_ctrl_recsource = { }; /* line mixer control */ -static struct snd_kcontrol_new sgio2audio_ctrl_line = { +static const struct snd_kcontrol_new sgio2audio_ctrl_line = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Line Playback Volume", .index = 0, @@ -287,7 +287,7 @@ static struct snd_kcontrol_new sgio2audio_ctrl_line = { }; /* cd mixer control */ -static struct snd_kcontrol_new sgio2audio_ctrl_cd = { +static const struct snd_kcontrol_new sgio2audio_ctrl_cd = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Line Playback Volume", .index = 1, @@ -299,7 +299,7 @@ static struct snd_kcontrol_new sgio2audio_ctrl_cd = { }; /* mic mixer control */ -static struct snd_kcontrol_new sgio2audio_ctrl_mic = { +static const struct snd_kcontrol_new sgio2audio_ctrl_mic = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Mic Playback Volume", .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, diff --git a/sound/parisc/harmony.c b/sound/parisc/harmony.c index 99b64cb3cef8..5911eb35c2a3 100644 --- a/sound/parisc/harmony.c +++ b/sound/parisc/harmony.c @@ -83,14 +83,14 @@ MODULE_DEVICE_TABLE(parisc, snd_harmony_devtable); #define NAME "harmony" #define PFX NAME ": " -static unsigned int snd_harmony_rates[] = { +static const unsigned int snd_harmony_rates[] = { 5512, 6615, 8000, 9600, 11025, 16000, 18900, 22050, 27428, 32000, 33075, 37800, 44100, 48000 }; -static unsigned int rate_bits[14] = { +static const unsigned int rate_bits[14] = { HARMONY_SR_5KHZ, HARMONY_SR_6KHZ, HARMONY_SR_8KHZ, HARMONY_SR_9KHZ, HARMONY_SR_11KHZ, HARMONY_SR_16KHZ, HARMONY_SR_18KHZ, HARMONY_SR_22KHZ, HARMONY_SR_27KHZ, @@ -98,7 +98,7 @@ static unsigned int rate_bits[14] = { HARMONY_SR_44KHZ, HARMONY_SR_48KHZ }; -static struct snd_pcm_hw_constraint_list hw_constraint_rates = { +static const struct snd_pcm_hw_constraint_list hw_constraint_rates = { .count = ARRAY_SIZE(snd_harmony_rates), .list = snd_harmony_rates, .mask = 0, diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig index 32151d8c6bb8..d9f3fdb777e4 100644 --- a/sound/pci/Kconfig +++ b/sound/pci/Kconfig @@ -465,6 +465,7 @@ config SND_EMU10K1 select SND_RAWMIDI select SND_AC97_CODEC select SND_TIMER + select SND_SEQ_DEVICE if SND_SEQUENCER != n depends on ZONE_DMA help Say Y to include support for Sound Blaster PCI 512, Live!, @@ -477,6 +478,13 @@ config SND_EMU10K1 To compile this driver as a module, choose M here: the module will be called snd-emu10k1. +# select SEQ stuff to min(SND_SEQUENCER,SND_XXX) +config SND_EMU10K1_SEQ + def_tristate SND_SEQUENCER && SND_EMU10K1 + select SND_SEQ_MIDI_EMUL + select SND_SEQ_VIRMIDI + select SND_SYNTH_EMUX + config SND_EMU10K1X tristate "Emu10k1X (Dell OEM Version)" select SND_AC97_CODEC diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c index 34bbc2e730a6..8567f1e5b9cf 100644 --- a/sound/pci/ali5451/ali5451.c +++ b/sound/pci/ali5451/ali5451.c @@ -1602,8 +1602,8 @@ static struct snd_pcm_hardware snd_ali_modem = static int snd_ali_modem_open(struct snd_pcm_substream *substream, int rec, int channel) { - static unsigned int rates[] = {8000, 9600, 12000, 16000}; - static struct snd_pcm_hw_constraint_list hw_constraint_rates = { + static const unsigned int rates[] = {8000, 9600, 12000, 16000}; + static const struct snd_pcm_hw_constraint_list hw_constraint_rates = { .count = ARRAY_SIZE(rates), .list = rates, .mask = 0, diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c index 40152feef1e7..52e0ea7b9b80 100644 --- a/sound/pci/atiixp_modem.c +++ b/sound/pci/atiixp_modem.c @@ -860,8 +860,8 @@ static int snd_atiixp_pcm_open(struct snd_pcm_substream *substream, struct atiixp_modem *chip = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; int err; - static unsigned int rates[] = { 8000, 9600, 12000, 16000 }; - static struct snd_pcm_hw_constraint_list hw_constraints_rates = { + static const unsigned int rates[] = { 8000, 9600, 12000, 16000 }; + static const struct snd_pcm_hw_constraint_list hw_constraints_rates = { .count = ARRAY_SIZE(rates), .list = rates, .mask = 0, diff --git a/sound/pci/au88x0/au88x0_pcm.c b/sound/pci/au88x0/au88x0_pcm.c index 335979a753fe..1aa97012451d 100644 --- a/sound/pci/au88x0/au88x0_pcm.c +++ b/sound/pci/au88x0/au88x0_pcm.c @@ -112,11 +112,11 @@ static struct snd_pcm_hardware snd_vortex_playback_hw_wt = { }; #endif #ifdef CHIP_AU8830 -static unsigned int au8830_channels[3] = { +static const unsigned int au8830_channels[3] = { 1, 2, 4, }; -static struct snd_pcm_hw_constraint_list hw_constraints_au8830_channels = { +static const struct snd_pcm_hw_constraint_list hw_constraints_au8830_channels = { .count = ARRAY_SIZE(au8830_channels), .list = au8830_channels, .mask = 0, diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c index 79b2e6b7d88b..fc18c29a8173 100644 --- a/sound/pci/azt3328.c +++ b/sound/pci/azt3328.c @@ -2014,7 +2014,7 @@ static const struct snd_pcm_hardware snd_azf3328_hardware = }; -static unsigned int snd_azf3328_fixed_rates[] = { +static const unsigned int snd_azf3328_fixed_rates[] = { AZF_FREQ_4000, AZF_FREQ_4800, AZF_FREQ_5512, @@ -2031,7 +2031,7 @@ static unsigned int snd_azf3328_fixed_rates[] = { AZF_FREQ_66200 }; -static struct snd_pcm_hw_constraint_list snd_azf3328_hw_constraints_rates = { +static const struct snd_pcm_hw_constraint_list snd_azf3328_hw_constraints_rates = { .count = ARRAY_SIZE(snd_azf3328_fixed_rates), .list = snd_azf3328_fixed_rates, .mask = 0, diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c index 099efb046b1c..de0234294c25 100644 --- a/sound/pci/bt87x.c +++ b/sound/pci/bt87x.c @@ -401,13 +401,13 @@ static int snd_bt87x_set_digital_hw(struct snd_bt87x *chip, struct snd_pcm_runti static int snd_bt87x_set_analog_hw(struct snd_bt87x *chip, struct snd_pcm_runtime *runtime) { - static struct snd_ratnum analog_clock = { + static const struct snd_ratnum analog_clock = { .num = ANALOG_CLOCK, .den_min = CLOCK_DIV_MIN, .den_max = CLOCK_DIV_MAX, .den_step = 1 }; - static struct snd_pcm_hw_constraint_ratnums constraint_rates = { + static const struct snd_pcm_hw_constraint_ratnums constraint_rates = { .nrats = 1, .rats = &analog_clock }; diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c index 745a0a3743b4..a460cb63e971 100644 --- a/sound/pci/cmipci.c +++ b/sound/pci/cmipci.c @@ -719,18 +719,18 @@ static int snd_cmipci_hw_free(struct snd_pcm_substream *substream) /* */ -static unsigned int hw_channels[] = {1, 2, 4, 6, 8}; -static struct snd_pcm_hw_constraint_list hw_constraints_channels_4 = { +static const unsigned int hw_channels[] = {1, 2, 4, 6, 8}; +static const struct snd_pcm_hw_constraint_list hw_constraints_channels_4 = { .count = 3, .list = hw_channels, .mask = 0, }; -static struct snd_pcm_hw_constraint_list hw_constraints_channels_6 = { +static const struct snd_pcm_hw_constraint_list hw_constraints_channels_6 = { .count = 4, .list = hw_channels, .mask = 0, }; -static struct snd_pcm_hw_constraint_list hw_constraints_channels_8 = { +static const struct snd_pcm_hw_constraint_list hw_constraints_channels_8 = { .count = 5, .list = hw_channels, .mask = 0, @@ -1597,9 +1597,9 @@ static struct snd_pcm_hardware snd_cmipci_capture_spdif = .fifo_size = 0, }; -static unsigned int rate_constraints[] = { 5512, 8000, 11025, 16000, 22050, +static const unsigned int rate_constraints[] = { 5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200, 96000, 128000 }; -static struct snd_pcm_hw_constraint_list hw_constraints_rates = { +static const struct snd_pcm_hw_constraint_list hw_constraints_rates = { .count = ARRAY_SIZE(rate_constraints), .list = rate_constraints, .mask = 0, diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c index f870697aca67..ee7ba4b0b47b 100644 --- a/sound/pci/cs4281.c +++ b/sound/pci/cs4281.c @@ -1296,7 +1296,7 @@ static void snd_cs4281_free_gameport(struct cs4281 *chip) #else static inline int snd_cs4281_create_gameport(struct cs4281 *chip) { return -ENOSYS; } static inline void snd_cs4281_free_gameport(struct cs4281 *chip) { } -#endif /* CONFIG_GAMEPORT || (MODULE && CONFIG_GAMEPORT_MODULE) */ +#endif /* IS_REACHABLE(CONFIG_GAMEPORT) */ static int snd_cs4281_free(struct cs4281 *chip) { diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c index e4cf3187b4dd..709fb1a503b7 100644 --- a/sound/pci/cs46xx/cs46xx_lib.c +++ b/sound/pci/cs46xx/cs46xx_lib.c @@ -887,8 +887,8 @@ static int snd_cs46xx_playback_transfer(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct snd_cs46xx_pcm * cpcm = runtime->private_data; - snd_pcm_indirect_playback_transfer(substream, &cpcm->pcm_rec, snd_cs46xx_pb_trans_copy); - return 0; + return snd_pcm_indirect_playback_transfer(substream, &cpcm->pcm_rec, + snd_cs46xx_pb_trans_copy); } static void snd_cs46xx_cp_trans_copy(struct snd_pcm_substream *substream, @@ -903,8 +903,8 @@ static void snd_cs46xx_cp_trans_copy(struct snd_pcm_substream *substream, static int snd_cs46xx_capture_transfer(struct snd_pcm_substream *substream) { struct snd_cs46xx *chip = snd_pcm_substream_chip(substream); - snd_pcm_indirect_capture_transfer(substream, &chip->capt.pcm_rec, snd_cs46xx_cp_trans_copy); - return 0; + return snd_pcm_indirect_capture_transfer(substream, &chip->capt.pcm_rec, + snd_cs46xx_cp_trans_copy); } static snd_pcm_uframes_t snd_cs46xx_playback_direct_pointer(struct snd_pcm_substream *substream) @@ -1482,9 +1482,9 @@ static struct snd_pcm_hardware snd_cs46xx_capture = #ifdef CONFIG_SND_CS46XX_NEW_DSP -static unsigned int period_sizes[] = { 32, 64, 128, 256, 512, 1024, 2048 }; +static const unsigned int period_sizes[] = { 32, 64, 128, 256, 512, 1024, 2048 }; -static struct snd_pcm_hw_constraint_list hw_constraints_period_sizes = { +static const struct snd_pcm_hw_constraint_list hw_constraints_period_sizes = { .count = ARRAY_SIZE(period_sizes), .list = period_sizes, .mask = 0 @@ -2371,7 +2371,7 @@ static int snd_cs46xx_front_dup_put(struct snd_kcontrol *kcontrol, ucontrol->value.integer.value[0] ? 0 : 0x200); } -static struct snd_kcontrol_new snd_cs46xx_front_dup_ctl = { +static const struct snd_kcontrol_new snd_cs46xx_front_dup_ctl = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Duplicate Front", .info = snd_mixer_boolean_info, diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c index 6a0e49ac5273..d3203df50a1a 100644 --- a/sound/pci/emu10k1/emu10k1.c +++ b/sound/pci/emu10k1/emu10k1.c @@ -37,7 +37,7 @@ MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("{{Creative Labs,SB Live!/PCI512/E-mu APS}," "{Creative Labs,SB Audigy}}"); -#if IS_REACHABLE(CONFIG_SND_SEQUENCER) +#if IS_ENABLED(CONFIG_SND_SEQUENCER) #define ENABLE_SYNTH #include <sound/emu10k1_synth.h> #endif diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c index 56fc47bd6dba..dc585959ca32 100644 --- a/sound/pci/emu10k1/emufx.c +++ b/sound/pci/emu10k1/emufx.c @@ -311,21 +311,6 @@ static const u32 onoff_table[2] = { }; /* - */ - -static inline mm_segment_t snd_enter_user(void) -{ - mm_segment_t fs = get_fs(); - set_fs(get_ds()); - return fs; -} - -static inline void snd_leave_user(mm_segment_t fs) -{ - set_fs(fs); -} - -/* * controls */ @@ -538,7 +523,8 @@ unsigned int snd_emu10k1_efx_read(struct snd_emu10k1 *emu, unsigned int pc) } static int snd_emu10k1_gpr_poke(struct snd_emu10k1 *emu, - struct snd_emu10k1_fx8010_code *icode) + struct snd_emu10k1_fx8010_code *icode, + bool in_kernel) { int gpr; u32 val; @@ -546,7 +532,9 @@ static int snd_emu10k1_gpr_poke(struct snd_emu10k1 *emu, for (gpr = 0; gpr < (emu->audigy ? 0x200 : 0x100); gpr++) { if (!test_bit(gpr, icode->gpr_valid)) continue; - if (get_user(val, &icode->gpr_map[gpr])) + if (in_kernel) + val = *(u32 *)&icode->gpr_map[gpr]; + else if (get_user(val, &icode->gpr_map[gpr])) return -EFAULT; snd_emu10k1_ptr_write(emu, emu->gpr_base + gpr, 0, val); } @@ -569,7 +557,8 @@ static int snd_emu10k1_gpr_peek(struct snd_emu10k1 *emu, } static int snd_emu10k1_tram_poke(struct snd_emu10k1 *emu, - struct snd_emu10k1_fx8010_code *icode) + struct snd_emu10k1_fx8010_code *icode, + bool in_kernel) { int tram; u32 addr, val; @@ -577,9 +566,14 @@ static int snd_emu10k1_tram_poke(struct snd_emu10k1 *emu, for (tram = 0; tram < (emu->audigy ? 0x100 : 0xa0); tram++) { if (!test_bit(tram, icode->tram_valid)) continue; - if (get_user(val, &icode->tram_data_map[tram]) || - get_user(addr, &icode->tram_addr_map[tram])) - return -EFAULT; + if (in_kernel) { + val = *(u32 *)&icode->tram_data_map[tram]; + addr = *(u32 *)&icode->tram_addr_map[tram]; + } else { + if (get_user(val, &icode->tram_data_map[tram]) || + get_user(addr, &icode->tram_addr_map[tram])) + return -EFAULT; + } snd_emu10k1_ptr_write(emu, TANKMEMDATAREGBASE + tram, 0, val); if (!emu->audigy) { snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + tram, 0, addr); @@ -615,16 +609,22 @@ static int snd_emu10k1_tram_peek(struct snd_emu10k1 *emu, } static int snd_emu10k1_code_poke(struct snd_emu10k1 *emu, - struct snd_emu10k1_fx8010_code *icode) + struct snd_emu10k1_fx8010_code *icode, + bool in_kernel) { u32 pc, lo, hi; for (pc = 0; pc < (emu->audigy ? 2*1024 : 2*512); pc += 2) { if (!test_bit(pc / 2, icode->code_valid)) continue; - if (get_user(lo, &icode->code[pc + 0]) || - get_user(hi, &icode->code[pc + 1])) - return -EFAULT; + if (in_kernel) { + lo = *(u32 *)&icode->code[pc + 0]; + hi = *(u32 *)&icode->code[pc + 1]; + } else { + if (get_user(lo, &icode->code[pc + 0]) || + get_user(hi, &icode->code[pc + 1])) + return -EFAULT; + } snd_emu10k1_efx_write(emu, pc + 0, lo); snd_emu10k1_efx_write(emu, pc + 1, hi); } @@ -665,14 +665,16 @@ snd_emu10k1_look_for_ctl(struct snd_emu10k1 *emu, struct snd_ctl_elem_id *id) #define MAX_TLV_SIZE 256 -static unsigned int *copy_tlv(const unsigned int __user *_tlv) +static unsigned int *copy_tlv(const unsigned int __user *_tlv, bool in_kernel) { unsigned int data[2]; unsigned int *tlv; if (!_tlv) return NULL; - if (copy_from_user(data, _tlv, sizeof(data))) + if (in_kernel) + memcpy(data, (void *)_tlv, sizeof(data)); + else if (copy_from_user(data, _tlv, sizeof(data))) return NULL; if (data[1] >= MAX_TLV_SIZE) return NULL; @@ -680,7 +682,9 @@ static unsigned int *copy_tlv(const unsigned int __user *_tlv) if (!tlv) return NULL; memcpy(tlv, data, sizeof(data)); - if (copy_from_user(tlv + 2, _tlv + 2, data[1])) { + if (in_kernel) { + memcpy(tlv + 2, (void *)(_tlv + 2), data[1]); + } else if (copy_from_user(tlv + 2, _tlv + 2, data[1])) { kfree(tlv); return NULL; } @@ -690,7 +694,7 @@ static unsigned int *copy_tlv(const unsigned int __user *_tlv) static int copy_gctl(struct snd_emu10k1 *emu, struct snd_emu10k1_fx8010_control_gpr *gctl, struct snd_emu10k1_fx8010_control_gpr __user *_gctl, - int idx) + int idx, bool in_kernel) { struct snd_emu10k1_fx8010_control_old_gpr __user *octl; @@ -718,7 +722,8 @@ static int copy_gctl_to_user(struct snd_emu10k1 *emu, } static int snd_emu10k1_verify_controls(struct snd_emu10k1 *emu, - struct snd_emu10k1_fx8010_code *icode) + struct snd_emu10k1_fx8010_code *icode, + bool in_kernel) { unsigned int i; struct snd_ctl_elem_id __user *_id; @@ -728,7 +733,9 @@ static int snd_emu10k1_verify_controls(struct snd_emu10k1 *emu, for (i = 0, _id = icode->gpr_del_controls; i < icode->gpr_del_control_count; i++, _id++) { - if (copy_from_user(&id, _id, sizeof(id))) + if (in_kernel) + id = *(struct snd_ctl_elem_id *)_id; + else if (copy_from_user(&id, _id, sizeof(id))) return -EFAULT; if (snd_emu10k1_look_for_ctl(emu, &id) == NULL) return -ENOENT; @@ -738,7 +745,8 @@ static int snd_emu10k1_verify_controls(struct snd_emu10k1 *emu, return -ENOMEM; err = 0; for (i = 0; i < icode->gpr_add_control_count; i++) { - if (copy_gctl(emu, gctl, icode->gpr_add_controls, i)) { + if (copy_gctl(emu, gctl, icode->gpr_add_controls, i, + in_kernel)) { err = -EFAULT; goto __error; } @@ -759,7 +767,8 @@ static int snd_emu10k1_verify_controls(struct snd_emu10k1 *emu, } for (i = 0; i < icode->gpr_list_control_count; i++) { /* FIXME: we need to check the WRITE access */ - if (copy_gctl(emu, gctl, icode->gpr_list_controls, i)) { + if (copy_gctl(emu, gctl, icode->gpr_list_controls, i, + in_kernel)) { err = -EFAULT; goto __error; } @@ -781,7 +790,8 @@ static void snd_emu10k1_ctl_private_free(struct snd_kcontrol *kctl) } static int snd_emu10k1_add_controls(struct snd_emu10k1 *emu, - struct snd_emu10k1_fx8010_code *icode) + struct snd_emu10k1_fx8010_code *icode, + bool in_kernel) { unsigned int i, j; struct snd_emu10k1_fx8010_control_gpr *gctl; @@ -800,7 +810,8 @@ static int snd_emu10k1_add_controls(struct snd_emu10k1 *emu, } for (i = 0; i < icode->gpr_add_control_count; i++) { - if (copy_gctl(emu, gctl, icode->gpr_add_controls, i)) { + if (copy_gctl(emu, gctl, icode->gpr_add_controls, i, + in_kernel)) { err = -EFAULT; goto __error; } @@ -821,7 +832,7 @@ static int snd_emu10k1_add_controls(struct snd_emu10k1 *emu, knew.device = gctl->id.device; knew.subdevice = gctl->id.subdevice; knew.info = snd_emu10k1_gpr_ctl_info; - knew.tlv.p = copy_tlv(gctl->tlv); + knew.tlv.p = copy_tlv(gctl->tlv, in_kernel); if (knew.tlv.p) knew.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ; @@ -873,7 +884,8 @@ static int snd_emu10k1_add_controls(struct snd_emu10k1 *emu, } static int snd_emu10k1_del_controls(struct snd_emu10k1 *emu, - struct snd_emu10k1_fx8010_code *icode) + struct snd_emu10k1_fx8010_code *icode, + bool in_kernel) { unsigned int i; struct snd_ctl_elem_id id; @@ -883,7 +895,9 @@ static int snd_emu10k1_del_controls(struct snd_emu10k1 *emu, for (i = 0, _id = icode->gpr_del_controls; i < icode->gpr_del_control_count; i++, _id++) { - if (copy_from_user(&id, _id, sizeof(id))) + if (in_kernel) + id = *(struct snd_ctl_elem_id *)_id; + else if (copy_from_user(&id, _id, sizeof(id))) return -EFAULT; down_write(&card->controls_rwsem); ctl = snd_emu10k1_look_for_ctl(emu, &id); @@ -941,12 +955,14 @@ static int snd_emu10k1_list_controls(struct snd_emu10k1 *emu, } static int snd_emu10k1_icode_poke(struct snd_emu10k1 *emu, - struct snd_emu10k1_fx8010_code *icode) + struct snd_emu10k1_fx8010_code *icode, + bool in_kernel) { int err = 0; mutex_lock(&emu->fx8010.lock); - if ((err = snd_emu10k1_verify_controls(emu, icode)) < 0) + err = snd_emu10k1_verify_controls(emu, icode, in_kernel); + if (err < 0) goto __error; strlcpy(emu->fx8010.name, icode->name, sizeof(emu->fx8010.name)); /* stop FX processor - this may be dangerous, but it's better to miss @@ -956,11 +972,20 @@ static int snd_emu10k1_icode_poke(struct snd_emu10k1 *emu, else snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg | EMU10K1_DBG_SINGLE_STEP); /* ok, do the main job */ - if ((err = snd_emu10k1_del_controls(emu, icode)) < 0 || - (err = snd_emu10k1_gpr_poke(emu, icode)) < 0 || - (err = snd_emu10k1_tram_poke(emu, icode)) < 0 || - (err = snd_emu10k1_code_poke(emu, icode)) < 0 || - (err = snd_emu10k1_add_controls(emu, icode)) < 0) + err = snd_emu10k1_del_controls(emu, icode, in_kernel); + if (err < 0) + goto __error; + err = snd_emu10k1_gpr_poke(emu, icode, in_kernel); + if (err < 0) + goto __error; + err = snd_emu10k1_tram_poke(emu, icode, in_kernel); + if (err < 0) + goto __error; + err = snd_emu10k1_code_poke(emu, icode, in_kernel); + if (err < 0) + goto __error; + err = snd_emu10k1_add_controls(emu, icode, in_kernel); + if (err < 0) goto __error; /* start FX processor when the DSP code is updated */ if (emu->audigy) @@ -1179,7 +1204,6 @@ static int _snd_emu10k1_audigy_init_efx(struct snd_emu10k1 *emu) struct snd_emu10k1_fx8010_code *icode = NULL; struct snd_emu10k1_fx8010_control_gpr *controls = NULL, *ctl; u32 *gpr_map; - mm_segment_t seg; err = -ENOMEM; icode = kzalloc(sizeof(*icode), GFP_KERNEL); @@ -1739,13 +1763,11 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) while (ptr < 0x400) A_OP(icode, &ptr, 0x0f, 0xc0, 0xc0, 0xcf, 0xc0); - seg = snd_enter_user(); icode->gpr_add_control_count = nctl; icode->gpr_add_controls = (struct snd_emu10k1_fx8010_control_gpr __user *)controls; emu->support_tlv = 1; /* support TLV */ - err = snd_emu10k1_icode_poke(emu, icode); + err = snd_emu10k1_icode_poke(emu, icode, true); emu->support_tlv = 0; /* clear again */ - snd_leave_user(seg); __err: kfree(controls); @@ -1817,7 +1839,6 @@ static int _snd_emu10k1_init_efx(struct snd_emu10k1 *emu) struct snd_emu10k1_fx8010_pcm_rec *ipcm = NULL; struct snd_emu10k1_fx8010_control_gpr *controls = NULL, *ctl; u32 *gpr_map; - mm_segment_t seg; err = -ENOMEM; icode = kzalloc(sizeof(*icode), GFP_KERNEL); @@ -2368,13 +2389,11 @@ static int _snd_emu10k1_init_efx(struct snd_emu10k1 *emu) if ((err = snd_emu10k1_fx8010_tram_setup(emu, ipcm->buffer_size)) < 0) goto __err; - seg = snd_enter_user(); icode->gpr_add_control_count = i; icode->gpr_add_controls = (struct snd_emu10k1_fx8010_control_gpr __user *)controls; emu->support_tlv = 1; /* support TLV */ - err = snd_emu10k1_icode_poke(emu, icode); + err = snd_emu10k1_icode_poke(emu, icode, true); emu->support_tlv = 0; /* clear again */ - snd_leave_user(seg); if (err >= 0) err = snd_emu10k1_ipcm_poke(emu, ipcm); __err: @@ -2537,7 +2556,7 @@ static int snd_emu10k1_fx8010_ioctl(struct snd_hwdep * hw, struct file *file, un icode = memdup_user(argp, sizeof(*icode)); if (IS_ERR(icode)) return PTR_ERR(icode); - res = snd_emu10k1_icode_poke(emu, icode); + res = snd_emu10k1_icode_poke(emu, icode, false); kfree(icode); return res; case SNDRV_EMU10K1_IOCTL_CODE_PEEK: diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c index ef1cf530c929..5c9054a9f69e 100644 --- a/sound/pci/emu10k1/emupcm.c +++ b/sound/pci/emu10k1/emupcm.c @@ -164,7 +164,7 @@ static int snd_emu10k1_pcm_channel_alloc(struct snd_emu10k1_pcm * epcm, int voic return 0; } -static unsigned int capture_period_sizes[31] = { +static const unsigned int capture_period_sizes[31] = { 384, 448, 512, 640, 384*2, 448*2, 512*2, 640*2, 384*4, 448*4, 512*4, 640*4, @@ -175,17 +175,17 @@ static unsigned int capture_period_sizes[31] = { 384*128,448*128,512*128 }; -static struct snd_pcm_hw_constraint_list hw_constraints_capture_period_sizes = { +static const struct snd_pcm_hw_constraint_list hw_constraints_capture_period_sizes = { .count = 31, .list = capture_period_sizes, .mask = 0 }; -static unsigned int capture_rates[8] = { +static const unsigned int capture_rates[8] = { 8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000 }; -static struct snd_pcm_hw_constraint_list hw_constraints_capture_rates = { +static const struct snd_pcm_hw_constraint_list hw_constraints_capture_rates = { .count = 8, .list = capture_rates, .mask = 0 @@ -1632,8 +1632,8 @@ static int snd_emu10k1_fx8010_playback_transfer(struct snd_pcm_substream *substr struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); struct snd_emu10k1_fx8010_pcm *pcm = &emu->fx8010.pcm[substream->number]; - snd_pcm_indirect_playback_transfer(substream, &pcm->pcm_rec, fx8010_pb_trans_copy); - return 0; + return snd_pcm_indirect_playback_transfer(substream, &pcm->pcm_rec, + fx8010_pb_trans_copy); } static int snd_emu10k1_fx8010_playback_hw_params(struct snd_pcm_substream *substream, diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c index 09a63ef41ef2..f0d978e3b274 100644 --- a/sound/pci/ens1370.c +++ b/sound/pci/ens1370.c @@ -467,41 +467,41 @@ MODULE_DEVICE_TABLE(pci, snd_audiopci_ids); #define POLL_COUNT 0xa000 #ifdef CHIP1370 -static unsigned int snd_es1370_fixed_rates[] = +static const unsigned int snd_es1370_fixed_rates[] = {5512, 11025, 22050, 44100}; -static struct snd_pcm_hw_constraint_list snd_es1370_hw_constraints_rates = { +static const struct snd_pcm_hw_constraint_list snd_es1370_hw_constraints_rates = { .count = 4, .list = snd_es1370_fixed_rates, .mask = 0, }; -static struct snd_ratnum es1370_clock = { +static const struct snd_ratnum es1370_clock = { .num = ES_1370_SRCLOCK, .den_min = 29, .den_max = 353, .den_step = 1, }; -static struct snd_pcm_hw_constraint_ratnums snd_es1370_hw_constraints_clock = { +static const struct snd_pcm_hw_constraint_ratnums snd_es1370_hw_constraints_clock = { .nrats = 1, .rats = &es1370_clock, }; #else -static struct snd_ratden es1371_dac_clock = { +static const struct snd_ratden es1371_dac_clock = { .num_min = 3000 * (1 << 15), .num_max = 48000 * (1 << 15), .num_step = 3000, .den = 1 << 15, }; -static struct snd_pcm_hw_constraint_ratdens snd_es1371_hw_constraints_dac_clock = { +static const struct snd_pcm_hw_constraint_ratdens snd_es1371_hw_constraints_dac_clock = { .nrats = 1, .rats = &es1371_dac_clock, }; -static struct snd_ratnum es1371_adc_clock = { +static const struct snd_ratnum es1371_adc_clock = { .num = 48000 << 15, .den_min = 32768, .den_max = 393216, .den_step = 1, }; -static struct snd_pcm_hw_constraint_ratnums snd_es1371_hw_constraints_adc_clock = { +static const struct snd_pcm_hw_constraint_ratnums snd_es1371_hw_constraints_adc_clock = { .nrats = 1, .rats = &es1371_adc_clock, }; diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c index e8d943071a8c..069902a06f00 100644 --- a/sound/pci/es1938.c +++ b/sound/pci/es1938.c @@ -436,7 +436,7 @@ static void snd_es1938_reset_fifo(struct es1938 *chip) outb(0, SLSB_REG(chip, RESET)); } -static struct snd_ratnum clocks[2] = { +static const struct snd_ratnum clocks[2] = { { .num = 793800, .den_min = 1, @@ -451,7 +451,7 @@ static struct snd_ratnum clocks[2] = { } }; -static struct snd_pcm_hw_constraint_ratnums hw_constraints_clocks = { +static const struct snd_pcm_hw_constraint_ratnums hw_constraints_clocks = { .nrats = 2, .rats = clocks, }; @@ -839,15 +839,12 @@ static snd_pcm_uframes_t snd_es1938_playback_pointer(struct snd_pcm_substream *s } static int snd_es1938_capture_copy(struct snd_pcm_substream *substream, - int channel, - snd_pcm_uframes_t pos, - void __user *dst, - snd_pcm_uframes_t count) + int channel, unsigned long pos, + void __user *dst, unsigned long count) { struct snd_pcm_runtime *runtime = substream->runtime; struct es1938 *chip = snd_pcm_substream_chip(substream); - pos <<= chip->dma1_shift; - count <<= chip->dma1_shift; + if (snd_BUG_ON(pos + count > chip->dma1_size)) return -EINVAL; if (pos + count < chip->dma1_size) { @@ -856,12 +853,31 @@ static int snd_es1938_capture_copy(struct snd_pcm_substream *substream, } else { if (copy_to_user(dst, runtime->dma_area + pos + 1, count - 1)) return -EFAULT; - if (put_user(runtime->dma_area[0], ((unsigned char __user *)dst) + count - 1)) + if (put_user(runtime->dma_area[0], + ((unsigned char __user *)dst) + count - 1)) return -EFAULT; } return 0; } +static int snd_es1938_capture_copy_kernel(struct snd_pcm_substream *substream, + int channel, unsigned long pos, + void *dst, unsigned long count) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct es1938 *chip = snd_pcm_substream_chip(substream); + + if (snd_BUG_ON(pos + count > chip->dma1_size)) + return -EINVAL; + if (pos + count < chip->dma1_size) { + memcpy(dst, runtime->dma_area + pos + 1, count); + } else { + memcpy(dst, runtime->dma_area + pos + 1, count - 1); + runtime->dma_area[0] = *((unsigned char *)dst + count - 1); + } + return 0; +} + /* * buffer management */ @@ -1012,7 +1028,8 @@ static const struct snd_pcm_ops snd_es1938_capture_ops = { .prepare = snd_es1938_capture_prepare, .trigger = snd_es1938_capture_trigger, .pointer = snd_es1938_capture_pointer, - .copy = snd_es1938_capture_copy, + .copy_user = snd_es1938_capture_copy, + .copy_kernel = snd_es1938_capture_copy_kernel, }; static int snd_es1938_new_pcm(struct es1938 *chip, int device) diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c index c47287d79306..8e6b04b39dcc 100644 --- a/sound/pci/fm801.c +++ b/sound/pci/fm801.c @@ -334,23 +334,23 @@ static unsigned short snd_fm801_codec_read(struct snd_ac97 *ac97, unsigned short return fm801_readw(chip, AC97_DATA); } -static unsigned int rates[] = { +static const unsigned int rates[] = { 5500, 8000, 9600, 11025, 16000, 19200, 22050, 32000, 38400, 44100, 48000 }; -static struct snd_pcm_hw_constraint_list hw_constraints_rates = { +static const struct snd_pcm_hw_constraint_list hw_constraints_rates = { .count = ARRAY_SIZE(rates), .list = rates, .mask = 0, }; -static unsigned int channels[] = { +static const unsigned int channels[] = { 2, 4, 6 }; -static struct snd_pcm_hw_constraint_list hw_constraints_channels = { +static const struct snd_pcm_hw_constraint_list hw_constraints_channels = { .count = ARRAY_SIZE(channels), .list = channels, .mask = 0, @@ -1235,8 +1235,6 @@ static int snd_fm801_create(struct snd_card *card, } } - snd_fm801_chip_init(chip); - if ((chip->tea575x_tuner & TUNER_ONLY) == 0) { if (devm_request_irq(&pci->dev, pci->irq, snd_fm801_interrupt, IRQF_SHARED, KBUILD_MODNAME, chip)) { @@ -1248,6 +1246,8 @@ static int snd_fm801_create(struct snd_card *card, pci_set_master(pci); } + snd_fm801_chip_init(chip); + if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { snd_fm801_free(chip); return err; diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 70bb365a08d2..821aad374a06 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -19,13 +19,11 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include <linux/mm.h> #include <linux/init.h> #include <linux/delay.h> #include <linux/slab.h> #include <linux/mutex.h> #include <linux/module.h> -#include <linux/async.h> #include <linux/pm.h> #include <linux/pm_runtime.h> #include <sound/core.h> @@ -1477,18 +1475,8 @@ int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol, } EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_volume_put); -/** - * snd_hda_mixer_amp_volume_put - TLV callback for a standard AMP mixer volume - * @kcontrol: ctl element - * @op_flag: operation flag - * @size: byte size of input TLV - * @_tlv: TLV data - * - * The control element is supposed to have the private_value field - * set up via HDA_COMPOSE_AMP_VAL*() or related macros. - */ -int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag, - unsigned int size, unsigned int __user *_tlv) +/* inquiry the amp caps and convert to TLV */ +static void get_ctl_amp_tlv(struct snd_kcontrol *kcontrol, unsigned int *tlv) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); hda_nid_t nid = get_amp_nid(kcontrol); @@ -1497,8 +1485,6 @@ int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag, bool min_mute = get_amp_min_mute(kcontrol); u32 caps, val1, val2; - if (size < 4 * sizeof(unsigned int)) - return -ENOMEM; caps = query_amp_caps(codec, nid, dir); val2 = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT; val2 = (val2 + 1) * 25; @@ -1507,13 +1493,31 @@ int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag, val1 = ((int)val1) * ((int)val2); if (min_mute || (caps & AC_AMPCAP_MIN_MUTE)) val2 |= TLV_DB_SCALE_MUTE; - if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv)) - return -EFAULT; - if (put_user(2 * sizeof(unsigned int), _tlv + 1)) - return -EFAULT; - if (put_user(val1, _tlv + 2)) - return -EFAULT; - if (put_user(val2, _tlv + 3)) + tlv[0] = SNDRV_CTL_TLVT_DB_SCALE; + tlv[1] = 2 * sizeof(unsigned int); + tlv[2] = val1; + tlv[3] = val2; +} + +/** + * snd_hda_mixer_amp_tlv - TLV callback for a standard AMP mixer volume + * @kcontrol: ctl element + * @op_flag: operation flag + * @size: byte size of input TLV + * @_tlv: TLV data + * + * The control element is supposed to have the private_value field + * set up via HDA_COMPOSE_AMP_VAL*() or related macros. + */ +int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag, + unsigned int size, unsigned int __user *_tlv) +{ + unsigned int tlv[4]; + + if (size < 4 * sizeof(unsigned int)) + return -ENOMEM; + get_ctl_amp_tlv(kcontrol, tlv); + if (copy_to_user(_tlv, tlv, sizeof(tlv))) return -EFAULT; return 0; } @@ -1807,13 +1811,10 @@ static int get_kctl_0dB_offset(struct hda_codec *codec, const int *tlv = NULL; int val = -1; - if (kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) { - /* FIXME: set_fs() hack for obtaining user-space TLV data */ - mm_segment_t fs = get_fs(); - set_fs(get_ds()); - if (!kctl->tlv.c(kctl, 0, sizeof(_tlv), _tlv)) - tlv = _tlv; - set_fs(fs); + if ((kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) && + kctl->tlv.c == snd_hda_mixer_amp_tlv) { + get_ctl_amp_tlv(kctl, _tlv); + tlv = _tlv; } else if (kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_READ) tlv = kctl->tlv.p; if (tlv && tlv[0] == SNDRV_CTL_TLVT_DB_SCALE) { @@ -2118,196 +2119,6 @@ int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol, EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_switch_put); /* - * bound volume controls - * - * bind multiple volumes (# indices, from 0) - */ - -#define AMP_VAL_IDX_SHIFT 19 -#define AMP_VAL_IDX_MASK (0x0f<<19) - -/** - * snd_hda_mixer_bind_switch_get - Get callback for a bound volume control - * @kcontrol: ctl element - * @ucontrol: pointer to get/store the data - * - * The control element is supposed to have the private_value field - * set up via HDA_BIND_MUTE*() macros. - */ -int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - unsigned long pval; - int err; - - mutex_lock(&codec->control_mutex); - pval = kcontrol->private_value; - kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */ - err = snd_hda_mixer_amp_switch_get(kcontrol, ucontrol); - kcontrol->private_value = pval; - mutex_unlock(&codec->control_mutex); - return err; -} -EXPORT_SYMBOL_GPL(snd_hda_mixer_bind_switch_get); - -/** - * snd_hda_mixer_bind_switch_put - Put callback for a bound volume control - * @kcontrol: ctl element - * @ucontrol: pointer to get/store the data - * - * The control element is supposed to have the private_value field - * set up via HDA_BIND_MUTE*() macros. - */ -int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - unsigned long pval; - int i, indices, err = 0, change = 0; - - mutex_lock(&codec->control_mutex); - pval = kcontrol->private_value; - indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT; - for (i = 0; i < indices; i++) { - kcontrol->private_value = (pval & ~AMP_VAL_IDX_MASK) | - (i << AMP_VAL_IDX_SHIFT); - err = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); - if (err < 0) - break; - change |= err; - } - kcontrol->private_value = pval; - mutex_unlock(&codec->control_mutex); - return err < 0 ? err : change; -} -EXPORT_SYMBOL_GPL(snd_hda_mixer_bind_switch_put); - -/** - * snd_hda_mixer_bind_ctls_info - Info callback for a generic bound control - * @kcontrol: referred ctl element - * @uinfo: pointer to get/store the data - * - * The control element is supposed to have the private_value field - * set up via HDA_BIND_VOL() or HDA_BIND_SW() macros. - */ -int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct hda_bind_ctls *c; - int err; - - mutex_lock(&codec->control_mutex); - c = (struct hda_bind_ctls *)kcontrol->private_value; - kcontrol->private_value = *c->values; - err = c->ops->info(kcontrol, uinfo); - kcontrol->private_value = (long)c; - mutex_unlock(&codec->control_mutex); - return err; -} -EXPORT_SYMBOL_GPL(snd_hda_mixer_bind_ctls_info); - -/** - * snd_hda_mixer_bind_ctls_get - Get callback for a generic bound control - * @kcontrol: ctl element - * @ucontrol: pointer to get/store the data - * - * The control element is supposed to have the private_value field - * set up via HDA_BIND_VOL() or HDA_BIND_SW() macros. - */ -int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct hda_bind_ctls *c; - int err; - - mutex_lock(&codec->control_mutex); - c = (struct hda_bind_ctls *)kcontrol->private_value; - kcontrol->private_value = *c->values; - err = c->ops->get(kcontrol, ucontrol); - kcontrol->private_value = (long)c; - mutex_unlock(&codec->control_mutex); - return err; -} -EXPORT_SYMBOL_GPL(snd_hda_mixer_bind_ctls_get); - -/** - * snd_hda_mixer_bind_ctls_put - Put callback for a generic bound control - * @kcontrol: ctl element - * @ucontrol: pointer to get/store the data - * - * The control element is supposed to have the private_value field - * set up via HDA_BIND_VOL() or HDA_BIND_SW() macros. - */ -int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct hda_bind_ctls *c; - unsigned long *vals; - int err = 0, change = 0; - - mutex_lock(&codec->control_mutex); - c = (struct hda_bind_ctls *)kcontrol->private_value; - for (vals = c->values; *vals; vals++) { - kcontrol->private_value = *vals; - err = c->ops->put(kcontrol, ucontrol); - if (err < 0) - break; - change |= err; - } - kcontrol->private_value = (long)c; - mutex_unlock(&codec->control_mutex); - return err < 0 ? err : change; -} -EXPORT_SYMBOL_GPL(snd_hda_mixer_bind_ctls_put); - -/** - * snd_hda_mixer_bind_tlv - TLV callback for a generic bound control - * @kcontrol: ctl element - * @op_flag: operation flag - * @size: byte size of input TLV - * @tlv: TLV data - * - * The control element is supposed to have the private_value field - * set up via HDA_BIND_VOL() macro. - */ -int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag, - unsigned int size, unsigned int __user *tlv) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct hda_bind_ctls *c; - int err; - - mutex_lock(&codec->control_mutex); - c = (struct hda_bind_ctls *)kcontrol->private_value; - kcontrol->private_value = *c->values; - err = c->ops->tlv(kcontrol, op_flag, size, tlv); - kcontrol->private_value = (long)c; - mutex_unlock(&codec->control_mutex); - return err; -} -EXPORT_SYMBOL_GPL(snd_hda_mixer_bind_tlv); - -struct hda_ctl_ops snd_hda_bind_vol = { - .info = snd_hda_mixer_amp_volume_info, - .get = snd_hda_mixer_amp_volume_get, - .put = snd_hda_mixer_amp_volume_put, - .tlv = snd_hda_mixer_amp_tlv -}; -EXPORT_SYMBOL_GPL(snd_hda_bind_vol); - -struct hda_ctl_ops snd_hda_bind_sw = { - .info = snd_hda_mixer_amp_switch_info, - .get = snd_hda_mixer_amp_switch_get, - .put = snd_hda_mixer_amp_switch_put, - .tlv = snd_hda_mixer_amp_tlv -}; -EXPORT_SYMBOL_GPL(snd_hda_bind_sw); - -/* * SPDIF out controls */ diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c index 1c60beb5b70a..d1eb14842340 100644 --- a/sound/pci/hda/hda_controller.c +++ b/sound/pci/hda/hda_controller.c @@ -1345,6 +1345,9 @@ int azx_codec_configure(struct azx *chip) list_for_each_codec_safe(codec, next, &chip->bus) { snd_hda_codec_configure(codec); } + + if (!azx_bus(chip)->num_codecs) + return -ENODEV; return 0; } EXPORT_SYMBOL_GPL(azx_codec_configure); diff --git a/sound/pci/hda/hda_controller.h b/sound/pci/hda/hda_controller.h index 35a9ab2cac46..a68e75b00ea3 100644 --- a/sound/pci/hda/hda_controller.h +++ b/sound/pci/hda/hda_controller.h @@ -32,7 +32,11 @@ #define AZX_DCAPS_NO_MSI (1 << 9) /* No MSI support */ #define AZX_DCAPS_SNOOP_MASK (3 << 10) /* snoop type mask */ #define AZX_DCAPS_SNOOP_OFF (1 << 12) /* snoop default off */ -/* 13 unused */ +#ifdef CONFIG_SND_HDA_I915 +#define AZX_DCAPS_I915_COMPONENT (1 << 13) /* bind with i915 gfx */ +#else +#define AZX_DCAPS_I915_COMPONENT 0 /* NOP */ +#endif /* 14 unused */ #define AZX_DCAPS_CTX_WORKAROUND (1 << 15) /* X-Fi workaround */ #define AZX_DCAPS_POSFIX_LPIB (1 << 16) /* Use LPIB as default */ diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index 71545b56b4c8..28e265a88383 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c @@ -948,6 +948,8 @@ static void resume_path_from_idx(struct hda_codec *codec, int path_idx) static int hda_gen_mixer_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); +static int hda_gen_bind_mute_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol); static int hda_gen_bind_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); @@ -970,7 +972,7 @@ static const struct snd_kcontrol_new control_templates[] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .info = snd_hda_mixer_amp_switch_info, - .get = snd_hda_mixer_bind_switch_get, + .get = hda_gen_bind_mute_get, .put = hda_gen_bind_mute_put, /* replaced */ .private_value = HDA_COMPOSE_AMP_VAL(0, 3, 0, 0), }, @@ -1101,11 +1103,51 @@ static int hda_gen_mixer_mute_put(struct snd_kcontrol *kcontrol, return snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); } +/* + * Bound mute controls + */ +#define AMP_VAL_IDX_SHIFT 19 +#define AMP_VAL_IDX_MASK (0x0f<<19) + +static int hda_gen_bind_mute_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + unsigned long pval; + int err; + + mutex_lock(&codec->control_mutex); + pval = kcontrol->private_value; + kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */ + err = snd_hda_mixer_amp_switch_get(kcontrol, ucontrol); + kcontrol->private_value = pval; + mutex_unlock(&codec->control_mutex); + return err; +} + static int hda_gen_bind_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + unsigned long pval; + int i, indices, err = 0, change = 0; + sync_auto_mute_bits(kcontrol, ucontrol); - return snd_hda_mixer_bind_switch_put(kcontrol, ucontrol); + + mutex_lock(&codec->control_mutex); + pval = kcontrol->private_value; + indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT; + for (i = 0; i < indices; i++) { + kcontrol->private_value = (pval & ~AMP_VAL_IDX_MASK) | + (i << AMP_VAL_IDX_SHIFT); + err = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); + if (err < 0) + break; + change |= err; + } + kcontrol->private_value = pval; + mutex_unlock(&codec->control_mutex); + return err < 0 ? err : change; } /* any ctl assigned to the path with the given index? */ diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 01eb1dc7b5b3..5ae8ddab6412 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -263,6 +263,7 @@ enum { AZX_DRIVER_ICH, AZX_DRIVER_PCH, AZX_DRIVER_SCH, + AZX_DRIVER_SKL, AZX_DRIVER_HDMI, AZX_DRIVER_ATI, AZX_DRIVER_ATIHDMI, @@ -292,38 +293,43 @@ enum { (AZX_DCAPS_NO_ALIGN_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY |\ AZX_DCAPS_SNOOP_TYPE(SCH)) -/* PCH up to IVB; no runtime PM */ +/* PCH up to IVB; no runtime PM; bind with i915 gfx */ #define AZX_DCAPS_INTEL_PCH_NOPM \ - (AZX_DCAPS_INTEL_PCH_BASE) + (AZX_DCAPS_INTEL_PCH_BASE | AZX_DCAPS_I915_COMPONENT) /* PCH for HSW/BDW; with runtime PM */ +/* no i915 binding for this as HSW/BDW has another controller for HDMI */ #define AZX_DCAPS_INTEL_PCH \ (AZX_DCAPS_INTEL_PCH_BASE | AZX_DCAPS_PM_RUNTIME) /* HSW HDMI */ #define AZX_DCAPS_INTEL_HASWELL \ (/*AZX_DCAPS_ALIGN_BUFSIZE |*/ AZX_DCAPS_COUNT_LPIB_DELAY |\ - AZX_DCAPS_PM_RUNTIME | AZX_DCAPS_I915_POWERWELL |\ - AZX_DCAPS_SNOOP_TYPE(SCH)) + AZX_DCAPS_PM_RUNTIME | AZX_DCAPS_I915_COMPONENT |\ + AZX_DCAPS_I915_POWERWELL | AZX_DCAPS_SNOOP_TYPE(SCH)) /* Broadwell HDMI can't use position buffer reliably, force to use LPIB */ #define AZX_DCAPS_INTEL_BROADWELL \ (/*AZX_DCAPS_ALIGN_BUFSIZE |*/ AZX_DCAPS_POSFIX_LPIB |\ - AZX_DCAPS_PM_RUNTIME | AZX_DCAPS_I915_POWERWELL |\ - AZX_DCAPS_SNOOP_TYPE(SCH)) + AZX_DCAPS_PM_RUNTIME | AZX_DCAPS_I915_COMPONENT |\ + AZX_DCAPS_I915_POWERWELL | AZX_DCAPS_SNOOP_TYPE(SCH)) #define AZX_DCAPS_INTEL_BAYTRAIL \ - (AZX_DCAPS_INTEL_PCH_NOPM | AZX_DCAPS_I915_POWERWELL) + (AZX_DCAPS_INTEL_PCH_BASE | AZX_DCAPS_I915_COMPONENT |\ + AZX_DCAPS_I915_POWERWELL) #define AZX_DCAPS_INTEL_BRASWELL \ - (AZX_DCAPS_INTEL_PCH | AZX_DCAPS_I915_POWERWELL) + (AZX_DCAPS_INTEL_PCH_BASE | AZX_DCAPS_PM_RUNTIME |\ + AZX_DCAPS_I915_COMPONENT | AZX_DCAPS_I915_POWERWELL) #define AZX_DCAPS_INTEL_SKYLAKE \ - (AZX_DCAPS_INTEL_PCH | AZX_DCAPS_SEPARATE_STREAM_TAG |\ + (AZX_DCAPS_INTEL_PCH_BASE | AZX_DCAPS_PM_RUNTIME |\ + AZX_DCAPS_SEPARATE_STREAM_TAG | AZX_DCAPS_I915_COMPONENT |\ AZX_DCAPS_I915_POWERWELL) #define AZX_DCAPS_INTEL_BROXTON \ - (AZX_DCAPS_INTEL_PCH | AZX_DCAPS_SEPARATE_STREAM_TAG |\ + (AZX_DCAPS_INTEL_PCH_BASE | AZX_DCAPS_PM_RUNTIME |\ + AZX_DCAPS_SEPARATE_STREAM_TAG | AZX_DCAPS_I915_COMPONENT |\ AZX_DCAPS_I915_POWERWELL) /* quirks for ATI SB / AMD Hudson */ @@ -364,23 +370,13 @@ enum { ((pci)->device == 0x0d0c) || \ ((pci)->device == 0x160c)) -#define IS_SKL(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa170) -#define IS_SKL_LP(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x9d70) -#define IS_KBL(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa171) -#define IS_KBL_LP(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x9d71) -#define IS_KBL_H(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa2f0) #define IS_BXT(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x5a98) -#define IS_BXT_T(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x1a98) -#define IS_GLK(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x3198) -#define IS_CFL(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa348) -#define IS_SKL_PLUS(pci) (IS_SKL(pci) || IS_SKL_LP(pci) || IS_BXT(pci) || \ - IS_BXT_T(pci) || IS_KBL(pci) || IS_KBL_LP(pci) || \ - IS_KBL_H(pci) || IS_GLK(pci) || IS_CFL(pci)) static char *driver_short_names[] = { [AZX_DRIVER_ICH] = "HDA Intel", [AZX_DRIVER_PCH] = "HDA Intel PCH", [AZX_DRIVER_SCH] = "HDA Intel MID", + [AZX_DRIVER_SKL] = "HDA Intel PCH", /* kept old name for compatibility */ [AZX_DRIVER_HDMI] = "HDA Intel HDMI", [AZX_DRIVER_ATI] = "HDA ATI SB", [AZX_DRIVER_ATIHDMI] = "HDA ATI HDMI", @@ -644,13 +640,13 @@ static void hda_intel_init_chip(struct azx *chip, bool full_reset) if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) snd_hdac_set_codec_wakeup(bus, true); - if (IS_SKL_PLUS(pci)) { + if (chip->driver_type == AZX_DRIVER_SKL) { pci_read_config_dword(pci, INTEL_HDA_CGCTL, &val); val = val & ~INTEL_HDA_CGCTL_MISCBDCGE; pci_write_config_dword(pci, INTEL_HDA_CGCTL, val); } azx_init_chip(chip, full_reset); - if (IS_SKL_PLUS(pci)) { + if (chip->driver_type == AZX_DRIVER_SKL) { pci_read_config_dword(pci, INTEL_HDA_CGCTL, &val); val = val | INTEL_HDA_CGCTL_MISCBDCGE; pci_write_config_dword(pci, INTEL_HDA_CGCTL, val); @@ -1017,7 +1013,7 @@ static int azx_suspend(struct device *dev) if (chip->msi) pci_disable_msi(chip->pci); - if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL + if ((chip->driver_caps & AZX_DCAPS_I915_POWERWELL) && hda->need_i915_power) snd_hdac_display_power(bus, false); @@ -1075,9 +1071,11 @@ static int azx_resume(struct device *dev) */ static int azx_freeze_noirq(struct device *dev) { + struct snd_card *card = dev_get_drvdata(dev); + struct azx *chip = card->private_data; struct pci_dev *pci = to_pci_dev(dev); - if (IS_SKL_PLUS(pci)) + if (chip->driver_type == AZX_DRIVER_SKL) pci_set_power_state(pci, PCI_D3hot); return 0; @@ -1085,9 +1083,11 @@ static int azx_freeze_noirq(struct device *dev) static int azx_thaw_noirq(struct device *dev) { + struct snd_card *card = dev_get_drvdata(dev); + struct azx *chip = card->private_data; struct pci_dev *pci = to_pci_dev(dev); - if (IS_SKL_PLUS(pci)) + if (chip->driver_type == AZX_DRIVER_SKL) pci_set_power_state(pci, PCI_D0); return 0; @@ -1119,7 +1119,7 @@ static int azx_runtime_suspend(struct device *dev) azx_stop_chip(chip); azx_enter_link_reset(chip); azx_clear_irq_pending(chip); - if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL + if ((chip->driver_caps & AZX_DCAPS_I915_POWERWELL) && hda->need_i915_power) snd_hdac_display_power(azx_bus(chip), false); @@ -1384,8 +1384,9 @@ static int azx_free(struct azx *chip) if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) { if (hda->need_i915_power) snd_hdac_display_power(bus, false); - snd_hdac_i915_exit(bus); } + if (chip->driver_caps & AZX_DCAPS_I915_COMPONENT) + snd_hdac_i915_exit(bus); kfree(hda); return 0; @@ -1497,7 +1498,7 @@ static int check_position_fix(struct azx *chip, int fix) dev_dbg(chip->card->dev, "Using LPIB position fix\n"); return POS_FIX_LPIB; } - if (IS_SKL_PLUS(chip->pci)) { + if (chip->driver_type == AZX_DRIVER_SKL) { dev_dbg(chip->card->dev, "Using SKL position fix\n"); return POS_FIX_SKL; } @@ -1798,7 +1799,7 @@ static int azx_first_init(struct azx *chip) return -ENXIO; } - if (IS_SKL_PLUS(pci)) + if (chip->driver_type == AZX_DRIVER_SKL) snd_hdac_bus_parse_capabilities(bus); /* @@ -2201,16 +2202,8 @@ static int azx_probe_continue(struct azx *chip) hda->probe_continued = 1; - /* Request display power well for the HDA controller or codec. For - * Haswell/Broadwell, both the display HDA controller and codec need - * this power. For other platforms, like Baytrail/Braswell, only the - * display codec needs the power and it can be released after probe. - */ - if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) { - /* HSW/BDW controllers need this power */ - if (CONTROLLER_IN_GPU(pci)) - hda->need_i915_power = 1; - + /* bind with i915 if needed */ + if (chip->driver_caps & AZX_DCAPS_I915_COMPONENT) { err = snd_hdac_i915_init(bus); if (err < 0) { /* if the controller is bound only with HDMI/DP @@ -2222,9 +2215,23 @@ static int azx_probe_continue(struct azx *chip) dev_err(chip->card->dev, "HSW/BDW HD-audio HDMI/DP requires binding with gfx driver\n"); goto out_free; - } else - goto skip_i915; + } else { + /* don't bother any longer */ + chip->driver_caps &= + ~(AZX_DCAPS_I915_COMPONENT | AZX_DCAPS_I915_POWERWELL); + } } + } + + /* Request display power well for the HDA controller or codec. For + * Haswell/Broadwell, both the display HDA controller and codec need + * this power. For other platforms, like Baytrail/Braswell, only the + * display codec needs the power and it can be released after probe. + */ + if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) { + /* HSW/BDW controllers need this power */ + if (CONTROLLER_IN_GPU(pci)) + hda->need_i915_power = 1; err = snd_hdac_display_power(bus, true); if (err < 0) { @@ -2234,7 +2241,6 @@ static int azx_probe_continue(struct azx *chip) } } - skip_i915: err = azx_first_init(chip); if (err < 0) goto out_free; @@ -2277,7 +2283,7 @@ static int azx_probe_continue(struct azx *chip) pm_runtime_put_autosuspend(&pci->dev); out_free: - if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL + if ((chip->driver_caps & AZX_DCAPS_I915_POWERWELL) && !hda->need_i915_power) snd_hdac_display_power(bus, false); @@ -2367,31 +2373,31 @@ static const struct pci_device_id azx_ids[] = { .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, /* Sunrise Point */ { PCI_DEVICE(0x8086, 0xa170), - .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_SKYLAKE }, + .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE }, /* Sunrise Point-LP */ { PCI_DEVICE(0x8086, 0x9d70), - .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_SKYLAKE }, + .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE }, /* Kabylake */ { PCI_DEVICE(0x8086, 0xa171), - .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_SKYLAKE }, + .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE }, /* Kabylake-LP */ { PCI_DEVICE(0x8086, 0x9d71), - .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_SKYLAKE }, + .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE }, /* Kabylake-H */ { PCI_DEVICE(0x8086, 0xa2f0), - .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_SKYLAKE }, + .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE }, /* Coffelake */ { PCI_DEVICE(0x8086, 0xa348), - .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_SKYLAKE}, + .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, /* Broxton-P(Apollolake) */ { PCI_DEVICE(0x8086, 0x5a98), - .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_BROXTON }, + .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_BROXTON }, /* Broxton-T */ { PCI_DEVICE(0x8086, 0x1a98), - .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_BROXTON }, + .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_BROXTON }, /* Gemini-Lake */ { PCI_DEVICE(0x8086, 0x3198), - .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_BROXTON }, + .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_BROXTON }, /* Haswell */ { PCI_DEVICE(0x8086, 0x0a0c), .driver_data = AZX_DRIVER_HDMI | AZX_DCAPS_INTEL_HASWELL }, diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index d0e066e4c985..5b5c324c99b9 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h @@ -178,67 +178,6 @@ void snd_hda_sync_vmaster_hook(struct hda_vmaster_mute_hook *hook); #define HDA_AMP_UNMUTE 0x00 #define HDA_AMP_VOLMASK 0x7f -/* mono switch binding multiple inputs */ -#define HDA_BIND_MUTE_MONO(xname, nid, channel, indices, direction) \ - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ - .info = snd_hda_mixer_amp_switch_info, \ - .get = snd_hda_mixer_bind_switch_get, \ - .put = snd_hda_mixer_bind_switch_put, \ - .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, indices, direction) } - -/* stereo switch binding multiple inputs */ -#define HDA_BIND_MUTE(xname,nid,indices,dir) \ - HDA_BIND_MUTE_MONO(xname,nid,3,indices,dir) - -int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); -int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); - -/* more generic bound controls */ -struct hda_ctl_ops { - snd_kcontrol_info_t *info; - snd_kcontrol_get_t *get; - snd_kcontrol_put_t *put; - snd_kcontrol_tlv_rw_t *tlv; -}; - -extern struct hda_ctl_ops snd_hda_bind_vol; /* for bind-volume with TLV */ -extern struct hda_ctl_ops snd_hda_bind_sw; /* for bind-switch */ - -struct hda_bind_ctls { - struct hda_ctl_ops *ops; - unsigned long values[]; -}; - -int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo); -int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); -int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); -int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag, - unsigned int size, unsigned int __user *tlv); - -#define HDA_BIND_VOL(xname, bindrec) \ - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\ - SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ - SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK,\ - .info = snd_hda_mixer_bind_ctls_info,\ - .get = snd_hda_mixer_bind_ctls_get,\ - .put = snd_hda_mixer_bind_ctls_put,\ - .tlv = { .c = snd_hda_mixer_bind_tlv },\ - .private_value = (long) (bindrec) } -#define HDA_BIND_SW(xname, bindrec) \ - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,\ - .name = xname, \ - .info = snd_hda_mixer_bind_ctls_info,\ - .get = snd_hda_mixer_bind_ctls_get,\ - .put = snd_hda_mixer_bind_ctls_put,\ - .private_value = (long) (bindrec) } - /* * SPDIF I/O */ diff --git a/sound/pci/hda/hda_sysfs.c b/sound/pci/hda/hda_sysfs.c index 9739fce9e032..9b7efece4484 100644 --- a/sound/pci/hda/hda_sysfs.c +++ b/sound/pci/hda/hda_sysfs.c @@ -761,7 +761,7 @@ static struct attribute *hda_dev_attrs[] = { NULL }; -static struct attribute_group hda_dev_attr_group = { +static const struct attribute_group hda_dev_attr_group = { .attrs = hda_dev_attrs, }; diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 63bc894ddf5e..8c1289963c80 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -933,6 +933,7 @@ static const struct snd_pci_quirk cxt5066_fixups[] = { SND_PCI_QUIRK(0x103c, 0x8174, "HP Spectre x360", CXT_FIXUP_HP_SPECTRE), SND_PCI_QUIRK(0x103c, 0x8115, "HP Z1 Gen3", CXT_FIXUP_HP_GATE_MIC), SND_PCI_QUIRK(0x103c, 0x814f, "HP ZBook 15u G3", CXT_FIXUP_MUTE_LED_GPIO), + SND_PCI_QUIRK(0x103c, 0x822e, "HP ProBook 440 G4", CXT_FIXUP_MUTE_LED_GPIO), SND_PCI_QUIRK(0x1043, 0x138d, "Asus", CXT_FIXUP_HEADPHONE_MIC_PIN), SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT_FIXUP_OLPC_XO), SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400", CXT_PINCFG_LENOVO_TP410), diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 90e4ff87445e..53f9311370de 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -53,9 +53,11 @@ MODULE_PARM_DESC(static_hdmi_pcm, "Don't restrict PCM parameters per ELD info"); #define is_skylake(codec) ((codec)->core.vendor_id == 0x80862809) #define is_broxton(codec) ((codec)->core.vendor_id == 0x8086280a) #define is_kabylake(codec) ((codec)->core.vendor_id == 0x8086280b) +#define is_geminilake(codec) (((codec)->core.vendor_id == 0x8086280d) || \ + ((codec)->core.vendor_id == 0x80862800)) #define is_haswell_plus(codec) (is_haswell(codec) || is_broadwell(codec) \ || is_skylake(codec) || is_broxton(codec) \ - || is_kabylake(codec)) + || is_kabylake(codec)) || is_geminilake(codec) #define is_valleyview(codec) ((codec)->core.vendor_id == 0x80862882) #define is_cherryview(codec) ((codec)->core.vendor_id == 0x80862883) @@ -174,7 +176,6 @@ struct hdmi_spec { /* i915/powerwell (Haswell+/Valleyview+) specific */ bool use_acomp_notifier; /* use i915 eld_notify callback for hotplug */ struct i915_audio_component_audio_ops i915_audio_ops; - bool i915_bound; /* was i915 bound in this driver? */ struct hdac_chmap chmap; hda_nid_t vendor_nid; @@ -2234,8 +2235,6 @@ static void generic_spec_free(struct hda_codec *codec) struct hdmi_spec *spec = codec->spec; if (spec) { - if (spec->i915_bound) - snd_hdac_i915_exit(&codec->bus->core); hdmi_array_free(spec); kfree(spec); codec->spec = NULL; @@ -2506,19 +2505,41 @@ static void i915_pin_cvt_fixup(struct hda_codec *codec, } } -/* Intel Haswell and onwards; audio component with eld notifier */ -static int intel_hsw_common_init(struct hda_codec *codec, hda_nid_t vendor_nid) +/* precondition and allocation for Intel codecs */ +static int alloc_intel_hdmi(struct hda_codec *codec) { - struct hdmi_spec *spec; - int err; - - /* HSW+ requires i915 binding */ + /* requires i915 binding */ if (!codec->bus->core.audio_component) { codec_info(codec, "No i915 binding for Intel HDMI/DP codec\n"); return -ENODEV; } - err = alloc_generic_hdmi(codec); + return alloc_generic_hdmi(codec); +} + +/* parse and post-process for Intel codecs */ +static int parse_intel_hdmi(struct hda_codec *codec) +{ + int err; + + err = hdmi_parse_codec(codec); + if (err < 0) { + generic_spec_free(codec); + return err; + } + + generic_hdmi_init_per_pins(codec); + register_i915_notifier(codec); + return 0; +} + +/* Intel Haswell and onwards; audio component with eld notifier */ +static int intel_hsw_common_init(struct hda_codec *codec, hda_nid_t vendor_nid) +{ + struct hdmi_spec *spec; + int err; + + err = alloc_intel_hdmi(codec); if (err < 0) return err; spec = codec->spec; @@ -2542,15 +2563,7 @@ static int intel_hsw_common_init(struct hda_codec *codec, hda_nid_t vendor_nid) spec->ops.setup_stream = i915_hsw_setup_stream; spec->ops.pin_cvt_fixup = i915_pin_cvt_fixup; - err = hdmi_parse_codec(codec); - if (err < 0) { - generic_spec_free(codec); - return err; - } - - generic_hdmi_init_per_pins(codec); - register_i915_notifier(codec); - return 0; + return parse_intel_hdmi(codec); } static int patch_i915_hsw_hdmi(struct hda_codec *codec) @@ -2569,13 +2582,7 @@ static int patch_i915_byt_hdmi(struct hda_codec *codec) struct hdmi_spec *spec; int err; - /* requires i915 binding */ - if (!codec->bus->core.audio_component) { - codec_info(codec, "No i915 binding for Intel HDMI/DP codec\n"); - return -ENODEV; - } - - err = alloc_generic_hdmi(codec); + err = alloc_intel_hdmi(codec); if (err < 0) return err; spec = codec->spec; @@ -2590,49 +2597,18 @@ static int patch_i915_byt_hdmi(struct hda_codec *codec) spec->ops.pin_cvt_fixup = i915_pin_cvt_fixup; - err = hdmi_parse_codec(codec); - if (err < 0) { - generic_spec_free(codec); - return err; - } - - generic_hdmi_init_per_pins(codec); - register_i915_notifier(codec); - return 0; + return parse_intel_hdmi(codec); } /* Intel IronLake, SandyBridge and IvyBridge; with eld notifier */ static int patch_i915_cpt_hdmi(struct hda_codec *codec) { - struct hdmi_spec *spec; int err; - /* no i915 component should have been bound before this */ - if (WARN_ON(codec->bus->core.audio_component)) - return -EBUSY; - - err = alloc_generic_hdmi(codec); + err = alloc_intel_hdmi(codec); if (err < 0) return err; - spec = codec->spec; - - /* Try to bind with i915 now */ - err = snd_hdac_i915_init(&codec->bus->core); - if (err < 0) - goto error; - spec->i915_bound = true; - - err = hdmi_parse_codec(codec); - if (err < 0) - goto error; - - generic_hdmi_init_per_pins(codec); - register_i915_notifier(codec); - return 0; - - error: - generic_spec_free(codec); - return err; + return parse_intel_hdmi(codec); } /* @@ -2782,21 +2758,21 @@ static int nvhdmi_7x_init_8ch(struct hda_codec *codec) return 0; } -static unsigned int channels_2_6_8[] = { +static const unsigned int channels_2_6_8[] = { 2, 6, 8 }; -static unsigned int channels_2_8[] = { +static const unsigned int channels_2_8[] = { 2, 8 }; -static struct snd_pcm_hw_constraint_list hw_constraints_2_6_8_channels = { +static const struct snd_pcm_hw_constraint_list hw_constraints_2_6_8_channels = { .count = ARRAY_SIZE(channels_2_6_8), .list = channels_2_6_8, .mask = 0, }; -static struct snd_pcm_hw_constraint_list hw_constraints_2_8_channels = { +static const struct snd_pcm_hw_constraint_list hw_constraints_2_8_channels = { .count = ARRAY_SIZE(channels_2_8), .list = channels_2_8, .mask = 0, @@ -2807,7 +2783,7 @@ static int simple_playback_pcm_open(struct hda_pcm_stream *hinfo, struct snd_pcm_substream *substream) { struct hdmi_spec *spec = codec->spec; - struct snd_pcm_hw_constraint_list *hw_constraints_channels = NULL; + const struct snd_pcm_hw_constraint_list *hw_constraints_channels = NULL; switch (codec->preset->vendor_id) { case 0x10de0002: @@ -3757,11 +3733,15 @@ HDA_CODEC_ENTRY(0x1002aa01, "R6xx HDMI", patch_atihdmi), HDA_CODEC_ENTRY(0x10951390, "SiI1390 HDMI", patch_generic_hdmi), HDA_CODEC_ENTRY(0x10951392, "SiI1392 HDMI", patch_generic_hdmi), HDA_CODEC_ENTRY(0x17e80047, "Chrontel HDMI", patch_generic_hdmi), +HDA_CODEC_ENTRY(0x10de0001, "MCP73 HDMI", patch_nvhdmi_2ch), HDA_CODEC_ENTRY(0x10de0002, "MCP77/78 HDMI", patch_nvhdmi_8ch_7x), HDA_CODEC_ENTRY(0x10de0003, "MCP77/78 HDMI", patch_nvhdmi_8ch_7x), +HDA_CODEC_ENTRY(0x10de0004, "GPU 04 HDMI", patch_nvhdmi_8ch_7x), HDA_CODEC_ENTRY(0x10de0005, "MCP77/78 HDMI", patch_nvhdmi_8ch_7x), HDA_CODEC_ENTRY(0x10de0006, "MCP77/78 HDMI", patch_nvhdmi_8ch_7x), HDA_CODEC_ENTRY(0x10de0007, "MCP79/7A HDMI", patch_nvhdmi_8ch_7x), +HDA_CODEC_ENTRY(0x10de0008, "GPU 08 HDMI/DP", patch_nvhdmi), +HDA_CODEC_ENTRY(0x10de0009, "GPU 09 HDMI/DP", patch_nvhdmi), HDA_CODEC_ENTRY(0x10de000a, "GPU 0a HDMI/DP", patch_nvhdmi), HDA_CODEC_ENTRY(0x10de000b, "GPU 0b HDMI/DP", patch_nvhdmi), HDA_CODEC_ENTRY(0x10de000c, "MCP89 HDMI", patch_nvhdmi), @@ -3788,17 +3768,40 @@ HDA_CODEC_ENTRY(0x10de0041, "GPU 41 HDMI/DP", patch_nvhdmi), HDA_CODEC_ENTRY(0x10de0042, "GPU 42 HDMI/DP", patch_nvhdmi), HDA_CODEC_ENTRY(0x10de0043, "GPU 43 HDMI/DP", patch_nvhdmi), HDA_CODEC_ENTRY(0x10de0044, "GPU 44 HDMI/DP", patch_nvhdmi), +HDA_CODEC_ENTRY(0x10de0045, "GPU 45 HDMI/DP", patch_nvhdmi), +HDA_CODEC_ENTRY(0x10de0050, "GPU 50 HDMI/DP", patch_nvhdmi), HDA_CODEC_ENTRY(0x10de0051, "GPU 51 HDMI/DP", patch_nvhdmi), +HDA_CODEC_ENTRY(0x10de0052, "GPU 52 HDMI/DP", patch_nvhdmi), HDA_CODEC_ENTRY(0x10de0060, "GPU 60 HDMI/DP", patch_nvhdmi), +HDA_CODEC_ENTRY(0x10de0061, "GPU 61 HDMI/DP", patch_nvhdmi), +HDA_CODEC_ENTRY(0x10de0062, "GPU 62 HDMI/DP", patch_nvhdmi), HDA_CODEC_ENTRY(0x10de0067, "MCP67 HDMI", patch_nvhdmi_2ch), HDA_CODEC_ENTRY(0x10de0070, "GPU 70 HDMI/DP", patch_nvhdmi), HDA_CODEC_ENTRY(0x10de0071, "GPU 71 HDMI/DP", patch_nvhdmi), HDA_CODEC_ENTRY(0x10de0072, "GPU 72 HDMI/DP", patch_nvhdmi), +HDA_CODEC_ENTRY(0x10de0073, "GPU 73 HDMI/DP", patch_nvhdmi), +HDA_CODEC_ENTRY(0x10de0074, "GPU 74 HDMI/DP", patch_nvhdmi), +HDA_CODEC_ENTRY(0x10de0076, "GPU 76 HDMI/DP", patch_nvhdmi), +HDA_CODEC_ENTRY(0x10de007b, "GPU 7b HDMI/DP", patch_nvhdmi), +HDA_CODEC_ENTRY(0x10de007c, "GPU 7c HDMI/DP", patch_nvhdmi), HDA_CODEC_ENTRY(0x10de007d, "GPU 7d HDMI/DP", patch_nvhdmi), +HDA_CODEC_ENTRY(0x10de007e, "GPU 7e HDMI/DP", patch_nvhdmi), HDA_CODEC_ENTRY(0x10de0080, "GPU 80 HDMI/DP", patch_nvhdmi), +HDA_CODEC_ENTRY(0x10de0081, "GPU 81 HDMI/DP", patch_nvhdmi), HDA_CODEC_ENTRY(0x10de0082, "GPU 82 HDMI/DP", patch_nvhdmi), HDA_CODEC_ENTRY(0x10de0083, "GPU 83 HDMI/DP", patch_nvhdmi), +HDA_CODEC_ENTRY(0x10de0084, "GPU 84 HDMI/DP", patch_nvhdmi), +HDA_CODEC_ENTRY(0x10de0090, "GPU 90 HDMI/DP", patch_nvhdmi), +HDA_CODEC_ENTRY(0x10de0091, "GPU 91 HDMI/DP", patch_nvhdmi), +HDA_CODEC_ENTRY(0x10de0092, "GPU 92 HDMI/DP", patch_nvhdmi), +HDA_CODEC_ENTRY(0x10de0093, "GPU 93 HDMI/DP", patch_nvhdmi), +HDA_CODEC_ENTRY(0x10de0094, "GPU 94 HDMI/DP", patch_nvhdmi), +HDA_CODEC_ENTRY(0x10de0095, "GPU 95 HDMI/DP", patch_nvhdmi), +HDA_CODEC_ENTRY(0x10de0097, "GPU 97 HDMI/DP", patch_nvhdmi), +HDA_CODEC_ENTRY(0x10de0098, "GPU 98 HDMI/DP", patch_nvhdmi), +HDA_CODEC_ENTRY(0x10de0099, "GPU 99 HDMI/DP", patch_nvhdmi), HDA_CODEC_ENTRY(0x10de8001, "MCP73 HDMI", patch_nvhdmi_2ch), +HDA_CODEC_ENTRY(0x10de8067, "MCP67/68 HDMI", patch_nvhdmi_2ch), HDA_CODEC_ENTRY(0x11069f80, "VX900 HDMI/DP", patch_via_hdmi), HDA_CODEC_ENTRY(0x11069f81, "VX900 HDMI/DP", patch_via_hdmi), HDA_CODEC_ENTRY(0x11069f84, "VX11 HDMI/DP", patch_generic_hdmi), @@ -3816,6 +3819,7 @@ HDA_CODEC_ENTRY(0x80862809, "Skylake HDMI", patch_i915_hsw_hdmi), HDA_CODEC_ENTRY(0x8086280a, "Broxton HDMI", patch_i915_hsw_hdmi), HDA_CODEC_ENTRY(0x8086280b, "Kabylake HDMI", patch_i915_hsw_hdmi), HDA_CODEC_ENTRY(0x8086280d, "Geminilake HDMI", patch_i915_glk_hdmi), +HDA_CODEC_ENTRY(0x80862800, "Geminilake HDMI", patch_i915_glk_hdmi), HDA_CODEC_ENTRY(0x80862880, "CedarTrail HDMI", patch_generic_hdmi), HDA_CODEC_ENTRY(0x80862882, "Valleyview2 HDMI", patch_i915_byt_hdmi), HDA_CODEC_ENTRY(0x80862883, "Braswell HDMI", patch_i915_byt_hdmi), diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index cbeebc0a9711..443a45eaec32 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -41,9 +41,6 @@ /* keep halting ALC5505 DSP, for power saving */ #define HALT_REALTEK_ALC5505 -/* for GPIO Poll */ -#define GPIO_MASK 0x03 - /* extra amp-initialization sequence types */ enum { ALC_INIT_NONE, @@ -327,6 +324,7 @@ static void alc_fill_eapd_coef(struct hda_codec *codec) case 0x10ec0292: alc_update_coef_idx(codec, 0x4, 1<<15, 0); break; + case 0x10ec0215: case 0x10ec0225: case 0x10ec0233: case 0x10ec0255: @@ -335,12 +333,13 @@ static void alc_fill_eapd_coef(struct hda_codec *codec) case 0x10ec0283: case 0x10ec0286: case 0x10ec0288: + case 0x10ec0285: case 0x10ec0295: case 0x10ec0298: + case 0x10ec0289: case 0x10ec0299: alc_update_coef_idx(codec, 0x10, 1<<9, 0); break; - case 0x10ec0285: case 0x10ec0293: alc_update_coef_idx(codec, 0xa, 1<<13, 0); break; @@ -380,6 +379,7 @@ static void alc_fill_eapd_coef(struct hda_codec *codec) break; case 0x10ec0899: case 0x10ec0900: + case 0x10ec1168: case 0x10ec1220: alc_update_coef_idx(codec, 0x7, 1<<1, 0); break; @@ -2575,18 +2575,37 @@ static int patch_alc262(struct hda_codec *codec) * ALC268 */ /* bind Beep switches of both NID 0x0f and 0x10 */ -static const struct hda_bind_ctls alc268_bind_beep_sw = { - .ops = &snd_hda_bind_sw, - .values = { - HDA_COMPOSE_AMP_VAL(0x0f, 3, 1, HDA_INPUT), - HDA_COMPOSE_AMP_VAL(0x10, 3, 1, HDA_INPUT), - 0 - }, -}; +static int alc268_beep_switch_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + unsigned long pval; + int err; + + mutex_lock(&codec->control_mutex); + pval = kcontrol->private_value; + kcontrol->private_value = (pval & ~0xff) | 0x0f; + err = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); + if (err >= 0) { + kcontrol->private_value = (pval & ~0xff) | 0x10; + err = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); + } + kcontrol->private_value = pval; + mutex_unlock(&codec->control_mutex); + return err; +} static const struct snd_kcontrol_new alc268_beep_mixer[] = { HDA_CODEC_VOLUME("Beep Playback Volume", 0x1d, 0x0, HDA_INPUT), - HDA_BIND_SW("Beep Playback Switch", &alc268_bind_beep_sw), + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Beep Playback Switch", + .subdevice = HDA_SUBDEV_AMP_FLAG, + .info = snd_hda_mixer_amp_switch_info, + .get = snd_hda_mixer_amp_switch_get, + .put = alc268_beep_switch_put, + .private_value = HDA_COMPOSE_AMP_VAL(0x0f, 3, 1, HDA_INPUT) + }, { } }; @@ -2719,11 +2738,12 @@ enum { ALC269_TYPE_ALC282, ALC269_TYPE_ALC283, ALC269_TYPE_ALC284, - ALC269_TYPE_ALC285, + ALC269_TYPE_ALC293, ALC269_TYPE_ALC286, ALC269_TYPE_ALC298, ALC269_TYPE_ALC255, ALC269_TYPE_ALC256, + ALC269_TYPE_ALC215, ALC269_TYPE_ALC225, ALC269_TYPE_ALC294, ALC269_TYPE_ALC700, @@ -2745,7 +2765,7 @@ static int alc269_parse_auto_config(struct hda_codec *codec) case ALC269_TYPE_ALC269VC: case ALC269_TYPE_ALC280: case ALC269_TYPE_ALC284: - case ALC269_TYPE_ALC285: + case ALC269_TYPE_ALC293: ssids = alc269va_ssids; break; case ALC269_TYPE_ALC269VB: @@ -2756,6 +2776,7 @@ static int alc269_parse_auto_config(struct hda_codec *codec) case ALC269_TYPE_ALC298: case ALC269_TYPE_ALC255: case ALC269_TYPE_ALC256: + case ALC269_TYPE_ALC215: case ALC269_TYPE_ALC225: case ALC269_TYPE_ALC294: case ALC269_TYPE_ALC700: @@ -3043,6 +3064,135 @@ static void alc283_shutup(struct hda_codec *codec) alc_write_coef_idx(codec, 0x43, 0x9614); } +static void alc256_init(struct hda_codec *codec) +{ + struct alc_spec *spec = codec->spec; + hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0]; + bool hp_pin_sense; + + if (!hp_pin) + return; + + msleep(30); + + hp_pin_sense = snd_hda_jack_detect(codec, hp_pin); + + if (hp_pin_sense) + msleep(2); + + alc_update_coefex_idx(codec, 0x57, 0x04, 0x0007, 0x1); /* Low power */ + + snd_hda_codec_write(codec, hp_pin, 0, + AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); + + if (hp_pin_sense) + msleep(85); + + snd_hda_codec_write(codec, hp_pin, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); + + if (hp_pin_sense) + msleep(100); + + alc_update_coef_idx(codec, 0x46, 3 << 12, 0); + alc_update_coefex_idx(codec, 0x57, 0x04, 0x0007, 0x4); /* Hight power */ +} + +static void alc256_shutup(struct hda_codec *codec) +{ + struct alc_spec *spec = codec->spec; + hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0]; + bool hp_pin_sense; + + if (!hp_pin) { + alc269_shutup(codec); + return; + } + + hp_pin_sense = snd_hda_jack_detect(codec, hp_pin); + + if (hp_pin_sense) + msleep(2); + + snd_hda_codec_write(codec, hp_pin, 0, + AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); + + if (hp_pin_sense) + msleep(85); + + snd_hda_codec_write(codec, hp_pin, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0); + + alc_update_coef_idx(codec, 0x46, 0, 3 << 12); /* 3k pull low control for Headset jack. */ + + if (hp_pin_sense) + msleep(100); + + alc_auto_setup_eapd(codec, false); + snd_hda_shutup_pins(codec); +} + +static void alc_default_init(struct hda_codec *codec) +{ + struct alc_spec *spec = codec->spec; + hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0]; + bool hp_pin_sense; + + if (!hp_pin) + return; + + msleep(30); + + hp_pin_sense = snd_hda_jack_detect(codec, hp_pin); + + if (hp_pin_sense) + msleep(2); + + snd_hda_codec_write(codec, hp_pin, 0, + AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); + + if (hp_pin_sense) + msleep(85); + + snd_hda_codec_write(codec, hp_pin, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); + + if (hp_pin_sense) + msleep(100); +} + +static void alc_default_shutup(struct hda_codec *codec) +{ + struct alc_spec *spec = codec->spec; + hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0]; + bool hp_pin_sense; + + if (!hp_pin) { + alc269_shutup(codec); + return; + } + + hp_pin_sense = snd_hda_jack_detect(codec, hp_pin); + + if (hp_pin_sense) + msleep(2); + + snd_hda_codec_write(codec, hp_pin, 0, + AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); + + if (hp_pin_sense) + msleep(85); + + snd_hda_codec_write(codec, hp_pin, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0); + + if (hp_pin_sense) + msleep(100); + + alc_auto_setup_eapd(codec, false); + snd_hda_shutup_pins(codec); +} + static void alc5505_coef_set(struct hda_codec *codec, unsigned int index_reg, unsigned int val) { @@ -3688,6 +3838,17 @@ static void alc269_fixup_hp_line1_mic1_led(struct hda_codec *codec, } } +static struct coef_fw alc225_pre_hsmode[] = { + UPDATE_COEF(0x4a, 1<<8, 0), + UPDATE_COEFEX(0x57, 0x05, 1<<14, 0), + UPDATE_COEF(0x63, 3<<14, 3<<14), + UPDATE_COEF(0x4a, 3<<4, 2<<4), + UPDATE_COEF(0x4a, 3<<10, 3<<10), + UPDATE_COEF(0x45, 0x3f<<10, 0x34<<10), + UPDATE_COEF(0x4a, 3<<10, 0), + {} +}; + static void alc_headset_mode_unplugged(struct hda_codec *codec) { static struct coef_fw coef0255[] = { @@ -3723,6 +3884,10 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec) UPDATE_COEF(0x67, 0x2000, 0), {} }; + static struct coef_fw coef0298[] = { + UPDATE_COEF(0x19, 0x1300, 0x0300), + {} + }; static struct coef_fw coef0292[] = { WRITE_COEF(0x76, 0x000e), WRITE_COEF(0x6c, 0x2400), @@ -3745,13 +3910,17 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec) {} }; static struct coef_fw coef0225[] = { - UPDATE_COEF(0x4a, 1<<8, 0), - UPDATE_COEFEX(0x57, 0x05, 1<<14, 0), - UPDATE_COEF(0x63, 3<<14, 3<<14), - UPDATE_COEF(0x4a, 3<<4, 2<<4), - UPDATE_COEF(0x4a, 3<<10, 3<<10), - UPDATE_COEF(0x45, 0x3f<<10, 0x34<<10), - UPDATE_COEF(0x4a, 3<<10, 0), + UPDATE_COEF(0x63, 3<<14, 0), + {} + }; + static struct coef_fw coef0274[] = { + UPDATE_COEF(0x4a, 0x0100, 0), + UPDATE_COEFEX(0x57, 0x05, 0x4000, 0), + UPDATE_COEF(0x6b, 0xf000, 0x5000), + UPDATE_COEF(0x4a, 0x0010, 0), + UPDATE_COEF(0x4a, 0x0c00, 0x0c00), + WRITE_COEF(0x45, 0x5289), + UPDATE_COEF(0x4a, 0x0c00, 0), {} }; @@ -3764,13 +3933,21 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec) alc_process_coef_fw(codec, coef0256); alc_process_coef_fw(codec, coef0255); break; + case 0x10ec0234: + case 0x10ec0274: + case 0x10ec0294: + alc_process_coef_fw(codec, coef0274); + break; case 0x10ec0233: case 0x10ec0283: alc_process_coef_fw(codec, coef0233); break; case 0x10ec0286: case 0x10ec0288: + alc_process_coef_fw(codec, coef0288); + break; case 0x10ec0298: + alc_process_coef_fw(codec, coef0298); alc_process_coef_fw(codec, coef0288); break; case 0x10ec0292: @@ -3811,6 +3988,7 @@ static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin, {} }; static struct coef_fw coef0288[] = { + UPDATE_COEF(0x4f, 0x00c0, 0), UPDATE_COEF(0x50, 0x2000, 0), UPDATE_COEF(0x56, 0x0006, 0), UPDATE_COEF(0x4f, 0xfcc0, 0xc400), @@ -3841,7 +4019,12 @@ static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin, UPDATE_COEF(0x63, 3<<14, 0), {} }; - + static struct coef_fw coef0274[] = { + UPDATE_COEFEX(0x57, 0x05, 0x4000, 0x4000), + UPDATE_COEF(0x4a, 0x0010, 0), + UPDATE_COEF(0x6b, 0xf000, 0), + {} + }; switch (codec->core.vendor_id) { case 0x10ec0255: @@ -3851,6 +4034,14 @@ static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin, alc_process_coef_fw(codec, coef0255); snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50); break; + case 0x10ec0234: + case 0x10ec0274: + case 0x10ec0294: + alc_write_coef_idx(codec, 0x45, 0x4689); + snd_hda_set_pin_ctl_cache(codec, hp_pin, 0); + alc_process_coef_fw(codec, coef0274); + snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50); + break; case 0x10ec0233: case 0x10ec0283: alc_write_coef_idx(codec, 0x45, 0xc429); @@ -3861,7 +4052,6 @@ static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin, case 0x10ec0286: case 0x10ec0288: case 0x10ec0298: - alc_update_coef_idx(codec, 0x4f, 0x000c, 0); snd_hda_set_pin_ctl_cache(codec, hp_pin, 0); alc_process_coef_fw(codec, coef0288); snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50); @@ -3894,6 +4084,7 @@ static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin, case 0x10ec0225: case 0x10ec0295: case 0x10ec0299: + alc_process_coef_fw(codec, alc225_pre_hsmode); alc_update_coef_idx(codec, 0x45, 0x3f<<10, 0x31<<10); snd_hda_set_pin_ctl_cache(codec, hp_pin, 0); alc_process_coef_fw(codec, coef0225); @@ -3906,7 +4097,12 @@ static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin, static void alc_headset_mode_default(struct hda_codec *codec) { static struct coef_fw coef0225[] = { - UPDATE_COEF(0x45, 0x3f<<10, 0x34<<10), + UPDATE_COEF(0x45, 0x3f<<10, 0x30<<10), + UPDATE_COEF(0x45, 0x3f<<10, 0x31<<10), + UPDATE_COEF(0x49, 3<<8, 0<<8), + UPDATE_COEF(0x4a, 3<<4, 3<<4), + UPDATE_COEF(0x63, 3<<14, 0), + UPDATE_COEF(0x67, 0xf000, 0x3000), {} }; static struct coef_fw coef0255[] = { @@ -3948,17 +4144,30 @@ static void alc_headset_mode_default(struct hda_codec *codec) WRITE_COEF(0xb7, 0x802b), {} }; + static struct coef_fw coef0274[] = { + WRITE_COEF(0x45, 0x4289), + UPDATE_COEF(0x4a, 0x0010, 0x0010), + UPDATE_COEF(0x6b, 0x0f00, 0), + UPDATE_COEF(0x49, 0x0300, 0x0300), + {} + }; switch (codec->core.vendor_id) { case 0x10ec0225: case 0x10ec0295: case 0x10ec0299: + alc_process_coef_fw(codec, alc225_pre_hsmode); alc_process_coef_fw(codec, coef0225); break; case 0x10ec0255: case 0x10ec0256: alc_process_coef_fw(codec, coef0255); break; + case 0x10ec0234: + case 0x10ec0274: + case 0x10ec0294: + alc_process_coef_fw(codec, coef0274); + break; case 0x10ec0233: case 0x10ec0283: alc_process_coef_fw(codec, coef0233); @@ -3987,6 +4196,8 @@ static void alc_headset_mode_default(struct hda_codec *codec) /* Iphone type */ static void alc_headset_mode_ctia(struct hda_codec *codec) { + int val; + static struct coef_fw coef0255[] = { WRITE_COEF(0x45, 0xd489), /* Set to CTIA type */ WRITE_COEF(0x1b, 0x0c2b), @@ -4029,11 +4240,14 @@ static void alc_headset_mode_ctia(struct hda_codec *codec) WRITE_COEF(0xc3, 0x0000), {} }; - static struct coef_fw coef0225[] = { + static struct coef_fw coef0225_1[] = { UPDATE_COEF(0x45, 0x3f<<10, 0x35<<10), - UPDATE_COEF(0x49, 1<<8, 1<<8), - UPDATE_COEF(0x4a, 7<<6, 7<<6), - UPDATE_COEF(0x4a, 3<<4, 3<<4), + UPDATE_COEF(0x63, 3<<14, 2<<14), + {} + }; + static struct coef_fw coef0225_2[] = { + UPDATE_COEF(0x45, 0x3f<<10, 0x35<<10), + UPDATE_COEF(0x63, 3<<14, 1<<14), {} }; @@ -4044,13 +4258,27 @@ static void alc_headset_mode_ctia(struct hda_codec *codec) case 0x10ec0256: alc_process_coef_fw(codec, coef0256); break; + case 0x10ec0234: + case 0x10ec0274: + case 0x10ec0294: + alc_write_coef_idx(codec, 0x45, 0xd689); + break; case 0x10ec0233: case 0x10ec0283: alc_process_coef_fw(codec, coef0233); break; case 0x10ec0298: - alc_update_coef_idx(codec, 0x8e, 0x0070, 0x0020);/* Headset output enable */ - /* ALC298 jack type setting is the same with ALC286/ALC288 */ + val = alc_read_coef_idx(codec, 0x50); + if (val & (1 << 12)) { + alc_update_coef_idx(codec, 0x8e, 0x0070, 0x0020); + alc_update_coef_idx(codec, 0x4f, 0xfcc0, 0xd400); + msleep(300); + } else { + alc_update_coef_idx(codec, 0x8e, 0x0070, 0x0010); + alc_update_coef_idx(codec, 0x4f, 0xfcc0, 0xd400); + msleep(300); + } + break; case 0x10ec0286: case 0x10ec0288: alc_update_coef_idx(codec, 0x4f, 0xfcc0, 0xd400); @@ -4069,7 +4297,11 @@ static void alc_headset_mode_ctia(struct hda_codec *codec) case 0x10ec0225: case 0x10ec0295: case 0x10ec0299: - alc_process_coef_fw(codec, coef0225); + val = alc_read_coef_idx(codec, 0x45); + if (val & (1 << 9)) + alc_process_coef_fw(codec, coef0225_2); + else + alc_process_coef_fw(codec, coef0225_1); break; case 0x10ec0867: alc_update_coefex_idx(codec, 0x57, 0x5, 1<<14, 0); @@ -4125,9 +4357,7 @@ static void alc_headset_mode_omtp(struct hda_codec *codec) }; static struct coef_fw coef0225[] = { UPDATE_COEF(0x45, 0x3f<<10, 0x39<<10), - UPDATE_COEF(0x49, 1<<8, 1<<8), - UPDATE_COEF(0x4a, 7<<6, 7<<6), - UPDATE_COEF(0x4a, 3<<4, 3<<4), + UPDATE_COEF(0x63, 3<<14, 2<<14), {} }; @@ -4138,13 +4368,20 @@ static void alc_headset_mode_omtp(struct hda_codec *codec) case 0x10ec0256: alc_process_coef_fw(codec, coef0256); break; + case 0x10ec0234: + case 0x10ec0274: + case 0x10ec0294: + alc_write_coef_idx(codec, 0x45, 0xe689); + break; case 0x10ec0233: case 0x10ec0283: alc_process_coef_fw(codec, coef0233); break; case 0x10ec0298: alc_update_coef_idx(codec, 0x8e, 0x0070, 0x0010);/* Headset output enable */ - /* ALC298 jack type setting is the same with ALC286/ALC288 */ + alc_update_coef_idx(codec, 0x4f, 0xfcc0, 0xe400); + msleep(300); + break; case 0x10ec0286: case 0x10ec0288: alc_update_coef_idx(codec, 0x4f, 0xfcc0, 0xe400); @@ -4184,6 +4421,14 @@ static void alc_determine_headset_type(struct hda_codec *codec) UPDATE_COEF(0x4f, 0xfcc0, 0xd400), /* Check Type */ {} }; + static struct coef_fw coef0298[] = { + UPDATE_COEF(0x50, 0x2000, 0x2000), + UPDATE_COEF(0x56, 0x0006, 0x0006), + UPDATE_COEF(0x66, 0x0008, 0), + UPDATE_COEF(0x67, 0x2000, 0), + UPDATE_COEF(0x19, 0x1300, 0x1300), + {} + }; static struct coef_fw coef0293[] = { UPDATE_COEF(0x4a, 0x000f, 0x0008), /* Combo Jack auto detect */ WRITE_COEF(0x45, 0xD429), /* Set to ctia type */ @@ -4196,9 +4441,11 @@ static void alc_determine_headset_type(struct hda_codec *codec) WRITE_COEF(0xc3, 0x0c00), {} }; - static struct coef_fw coef0225[] = { - UPDATE_COEF(0x45, 0x3f<<10, 0x34<<10), - UPDATE_COEF(0x49, 1<<8, 1<<8), + static struct coef_fw coef0274[] = { + UPDATE_COEF(0x4a, 0x0010, 0), + UPDATE_COEF(0x4a, 0x8000, 0), + WRITE_COEF(0x45, 0xd289), + UPDATE_COEF(0x49, 0x0300, 0x0300), {} }; @@ -4210,6 +4457,14 @@ static void alc_determine_headset_type(struct hda_codec *codec) val = alc_read_coef_idx(codec, 0x46); is_ctia = (val & 0x0070) == 0x0070; break; + case 0x10ec0234: + case 0x10ec0274: + case 0x10ec0294: + alc_process_coef_fw(codec, coef0274); + msleep(80); + val = alc_read_coef_idx(codec, 0x46); + is_ctia = (val & 0x00f0) == 0x00f0; + break; case 0x10ec0233: case 0x10ec0283: alc_write_coef_idx(codec, 0x45, 0xd029); @@ -4218,8 +4473,34 @@ static void alc_determine_headset_type(struct hda_codec *codec) is_ctia = (val & 0x0070) == 0x0070; break; case 0x10ec0298: - alc_update_coef_idx(codec, 0x8e, 0x0070, 0x0020); /* Headset output enable */ - /* ALC298 check jack type is the same with ALC286/ALC288 */ + snd_hda_codec_write(codec, 0x21, 0, + AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); + msleep(100); + snd_hda_codec_write(codec, 0x21, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0); + msleep(200); + + val = alc_read_coef_idx(codec, 0x50); + if (val & (1 << 12)) { + alc_update_coef_idx(codec, 0x8e, 0x0070, 0x0020); + alc_process_coef_fw(codec, coef0288); + msleep(350); + val = alc_read_coef_idx(codec, 0x50); + is_ctia = (val & 0x0070) == 0x0070; + } else { + alc_update_coef_idx(codec, 0x8e, 0x0070, 0x0010); + alc_process_coef_fw(codec, coef0288); + msleep(350); + val = alc_read_coef_idx(codec, 0x50); + is_ctia = (val & 0x0070) == 0x0070; + } + alc_process_coef_fw(codec, coef0298); + snd_hda_codec_write(codec, 0x21, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP); + msleep(75); + snd_hda_codec_write(codec, 0x21, 0, + AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); + break; case 0x10ec0286: case 0x10ec0288: alc_process_coef_fw(codec, coef0288); @@ -4248,10 +4529,25 @@ static void alc_determine_headset_type(struct hda_codec *codec) case 0x10ec0225: case 0x10ec0295: case 0x10ec0299: - alc_process_coef_fw(codec, coef0225); - msleep(800); - val = alc_read_coef_idx(codec, 0x46); - is_ctia = (val & 0x00f0) == 0x00f0; + alc_process_coef_fw(codec, alc225_pre_hsmode); + alc_update_coef_idx(codec, 0x67, 0xf000, 0x1000); + val = alc_read_coef_idx(codec, 0x45); + if (val & (1 << 9)) { + alc_update_coef_idx(codec, 0x45, 0x3f<<10, 0x34<<10); + alc_update_coef_idx(codec, 0x49, 3<<8, 2<<8); + msleep(800); + val = alc_read_coef_idx(codec, 0x46); + is_ctia = (val & 0x00f0) == 0x00f0; + } else { + alc_update_coef_idx(codec, 0x45, 0x3f<<10, 0x34<<10); + alc_update_coef_idx(codec, 0x49, 3<<8, 1<<8); + msleep(800); + val = alc_read_coef_idx(codec, 0x46); + is_ctia = (val & 0x00f0) == 0x00f0; + } + alc_update_coef_idx(codec, 0x4a, 7<<6, 7<<6); + alc_update_coef_idx(codec, 0x4a, 3<<4, 3<<4); + alc_update_coef_idx(codec, 0x67, 0xf000, 0x3000); break; case 0x10ec0867: is_ctia = true; @@ -4892,6 +5188,7 @@ enum { ALC269_FIXUP_DELL1_MIC_NO_PRESENCE, ALC269_FIXUP_DELL2_MIC_NO_PRESENCE, ALC269_FIXUP_DELL3_MIC_NO_PRESENCE, + ALC269_FIXUP_DELL4_MIC_NO_PRESENCE, ALC269_FIXUP_HEADSET_MODE, ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC, ALC269_FIXUP_ASPIRE_HEADSET_MIC, @@ -4964,6 +5261,7 @@ enum { ALC233_FIXUP_ASUS_MIC_NO_PRESENCE, ALC233_FIXUP_EAPD_COEF_AND_MIC_NO_PRESENCE, ALC233_FIXUP_LENOVO_MULTI_CODECS, + ALC294_FIXUP_LENOVO_MIC_LOCATION, }; static const struct hda_fixup alc269_fixups[] = { @@ -5192,6 +5490,16 @@ static const struct hda_fixup alc269_fixups[] = { .chained = true, .chain_id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC }, + [ALC269_FIXUP_DELL4_MIC_NO_PRESENCE] = { + .type = HDA_FIXUP_PINS, + .v.pins = (const struct hda_pintbl[]) { + { 0x19, 0x01a1913c }, /* use as headset mic, without its own jack detect */ + { 0x1b, 0x01a1913d }, /* use as headphone mic, without its own jack detect */ + { } + }, + .chained = true, + .chain_id = ALC269_FIXUP_HEADSET_MODE + }, [ALC269_FIXUP_HEADSET_MODE] = { .type = HDA_FIXUP_FUNC, .v.func = alc_fixup_headset_mode, @@ -5737,6 +6045,18 @@ static const struct hda_fixup alc269_fixups[] = { .type = HDA_FIXUP_FUNC, .v.func = alc233_alc662_fixup_lenovo_dual_codecs, }, + [ALC294_FIXUP_LENOVO_MIC_LOCATION] = { + .type = HDA_FIXUP_PINS, + .v.pins = (const struct hda_pintbl[]) { + /* Change the mic location from front to right, otherwise there are + two front mics with the same name, pulseaudio can't handle them. + This is just a temporary workaround, after applying this fixup, + there will be one "Front Mic" and one "Mic" in this machine. + */ + { 0x1a, 0x04a19040 }, + { } + }, + }, }; static const struct snd_pci_quirk alc269_fixup_tbl[] = { @@ -5918,6 +6238,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x17aa, 0x2233, "Thinkpad", ALC292_FIXUP_TPT460), SND_PCI_QUIRK(0x17aa, 0x30bb, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY), SND_PCI_QUIRK(0x17aa, 0x30e2, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY), + SND_PCI_QUIRK(0x17aa, 0x310c, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION), SND_PCI_QUIRK(0x17aa, 0x3112, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY), SND_PCI_QUIRK(0x17aa, 0x3902, "Lenovo E50-80", ALC269_FIXUP_DMIC_THINKPAD_ACPI), SND_PCI_QUIRK(0x17aa, 0x3977, "IdeaPad S210", ALC283_FIXUP_INT_MIC), @@ -6322,6 +6643,11 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = { {0x17, 0x90170110}, {0x1a, 0x03011020}, {0x21, 0x03211030}), + SND_HDA_PIN_QUIRK(0x10ec0299, 0x1028, "Dell", ALC269_FIXUP_DELL4_MIC_NO_PRESENCE, + ALC225_STANDARD_PINS, + {0x12, 0xb7a60130}, + {0x13, 0xb8a61140}, + {0x17, 0x90170110}), {} }; @@ -6384,7 +6710,8 @@ static int patch_alc269(struct hda_codec *codec) codec->patch_ops.suspend = alc269_suspend; codec->patch_ops.resume = alc269_resume; #endif - spec->shutup = alc269_shutup; + spec->shutup = alc_default_shutup; + spec->init_hook = alc_default_init; snd_hda_pick_fixup(codec, alc269_fixup_models, alc269_fixup_tbl, alc269_fixups); @@ -6424,6 +6751,7 @@ static int patch_alc269(struct hda_codec *codec) } if (err < 0) goto error; + spec->shutup = alc269_shutup; spec->init_hook = alc269_fill_coef; alc269_fill_coef(codec); break; @@ -6447,9 +6775,8 @@ static int patch_alc269(struct hda_codec *codec) case 0x10ec0292: spec->codec_variant = ALC269_TYPE_ALC284; break; - case 0x10ec0285: case 0x10ec0293: - spec->codec_variant = ALC269_TYPE_ALC285; + spec->codec_variant = ALC269_TYPE_ALC293; break; case 0x10ec0286: case 0x10ec0288: @@ -6464,12 +6791,21 @@ static int patch_alc269(struct hda_codec *codec) break; case 0x10ec0256: spec->codec_variant = ALC269_TYPE_ALC256; + spec->shutup = alc256_shutup; + spec->init_hook = alc256_init; spec->gen.mixer_nid = 0; /* ALC256 does not have any loopback mixer path */ alc_update_coef_idx(codec, 0x36, 1 << 13, 1 << 5); /* Switch pcbeep path to Line in path*/ break; + case 0x10ec0215: + case 0x10ec0285: + case 0x10ec0289: + spec->codec_variant = ALC269_TYPE_ALC215; + spec->gen.mixer_nid = 0; + break; case 0x10ec0225: case 0x10ec0295: spec->codec_variant = ALC269_TYPE_ALC225; + spec->gen.mixer_nid = 0; /* no loopback on ALC225 ALC295 */ break; case 0x10ec0299: spec->codec_variant = ALC269_TYPE_ALC225; @@ -6479,6 +6815,8 @@ static int patch_alc269(struct hda_codec *codec) case 0x10ec0274: case 0x10ec0294: spec->codec_variant = ALC269_TYPE_ALC294; + spec->gen.mixer_nid = 0; /* ALC2x4 does not have any loopback mixer path */ + alc_update_coef_idx(codec, 0x6b, 0x0018, (1<<4) | (1<<3)); /* UAJ MIC Vref control by verb */ break; case 0x10ec0700: case 0x10ec0701: @@ -7495,6 +7833,7 @@ static int patch_alc680(struct hda_codec *codec) * patch entries */ static const struct hda_device_id snd_hda_id_realtek[] = { + HDA_CODEC_ENTRY(0x10ec0215, "ALC215", patch_alc269), HDA_CODEC_ENTRY(0x10ec0221, "ALC221", patch_alc269), HDA_CODEC_ENTRY(0x10ec0225, "ALC225", patch_alc269), HDA_CODEC_ENTRY(0x10ec0231, "ALC231", patch_alc269), @@ -7520,6 +7859,7 @@ static const struct hda_device_id snd_hda_id_realtek[] = { HDA_CODEC_ENTRY(0x10ec0285, "ALC285", patch_alc269), HDA_CODEC_ENTRY(0x10ec0286, "ALC286", patch_alc269), HDA_CODEC_ENTRY(0x10ec0288, "ALC288", patch_alc269), + HDA_CODEC_ENTRY(0x10ec0289, "ALC289", patch_alc269), HDA_CODEC_ENTRY(0x10ec0290, "ALC290", patch_alc269), HDA_CODEC_ENTRY(0x10ec0292, "ALC292", patch_alc269), HDA_CODEC_ENTRY(0x10ec0293, "ALC293", patch_alc269), @@ -7558,6 +7898,7 @@ static const struct hda_device_id snd_hda_id_realtek[] = { HDA_CODEC_ENTRY(0x10ec0892, "ALC892", patch_alc662), HDA_CODEC_ENTRY(0x10ec0899, "ALC898", patch_alc882), HDA_CODEC_ENTRY(0x10ec0900, "ALC1150", patch_alc882), + HDA_CODEC_ENTRY(0x10ec1168, "ALC1220", patch_alc882), HDA_CODEC_ENTRY(0x10ec1220, "ALC1220", patch_alc882), {} /* terminator */ }; diff --git a/sound/pci/hda/patch_si3054.c b/sound/pci/hda/patch_si3054.c index ffda38c45509..f63acb1b965c 100644 --- a/sound/pci/hda/patch_si3054.c +++ b/sound/pci/hda/patch_si3054.c @@ -169,8 +169,8 @@ static int si3054_pcm_open(struct hda_pcm_stream *hinfo, struct hda_codec *codec, struct snd_pcm_substream *substream) { - static unsigned int rates[] = { 8000, 9600, 16000 }; - static struct snd_pcm_hw_constraint_list hw_constraints_rates = { + static const unsigned int rates[] = { 8000, 9600, 16000 }; + static const struct snd_pcm_hw_constraint_list hw_constraints_rates = { .count = ARRAY_SIZE(rates), .list = rates, .mask = 0, diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c index 1d8612cabb9e..0e66afa403a3 100644 --- a/sound/pci/ice1712/ice1712.c +++ b/sound/pci/ice1712/ice1712.c @@ -932,10 +932,10 @@ static int snd_ice1712_pcm_ds(struct snd_ice1712 *ice, int device) * PCM code - professional part (multitrack) */ -static unsigned int rates[] = { 8000, 9600, 11025, 12000, 16000, 22050, 24000, +static const unsigned int rates[] = { 8000, 9600, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000, 64000, 88200, 96000 }; -static struct snd_pcm_hw_constraint_list hw_constraints_rates = { +static const struct snd_pcm_hw_constraint_list hw_constraints_rates = { .count = ARRAY_SIZE(rates), .list = rates, .mask = 0, @@ -1401,7 +1401,7 @@ static struct snd_kcontrol_new snd_ice1712_multi_playback_ctrls[] = { }, }; -static struct snd_kcontrol_new snd_ice1712_multi_capture_analog_switch = { +static const struct snd_kcontrol_new snd_ice1712_multi_capture_analog_switch = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "H/W Multi Capture Switch", .info = snd_ice1712_pro_mixer_switch_info, @@ -1420,7 +1420,7 @@ static const struct snd_kcontrol_new snd_ice1712_multi_capture_spdif_switch = { .count = 2, }; -static struct snd_kcontrol_new snd_ice1712_multi_capture_analog_volume = { +static const struct snd_kcontrol_new snd_ice1712_multi_capture_analog_volume = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ), @@ -2165,7 +2165,7 @@ static int snd_ice1712_pro_route_spdif_put(struct snd_kcontrol *kcontrol, return change; } -static struct snd_kcontrol_new snd_ice1712_mixer_pro_analog_route = { +static const struct snd_kcontrol_new snd_ice1712_mixer_pro_analog_route = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "H/W Playback Route", .info = snd_ice1712_pro_route_info, diff --git a/sound/pci/ice1712/ice1712.h b/sound/pci/ice1712/ice1712.h index 58f8f2ae758d..5cfba09c9761 100644 --- a/sound/pci/ice1712/ice1712.h +++ b/sound/pci/ice1712/ice1712.h @@ -348,7 +348,7 @@ struct snd_ice1712 { struct mutex open_mutex; struct snd_pcm_substream *pcm_reserved[4]; - struct snd_pcm_hw_constraint_list *hw_rates; /* card-specific rate constraints */ + const struct snd_pcm_hw_constraint_list *hw_rates; /* card-specific rate constraints */ unsigned int akm_codecs; struct snd_akm4xxx *akm; diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c index 9cd6e55c0642..057c2f394ea7 100644 --- a/sound/pci/ice1712/ice1724.c +++ b/sound/pci/ice1712/ice1724.c @@ -521,25 +521,25 @@ static irqreturn_t snd_vt1724_interrupt(int irq, void *dev_id) * PCM code - professional part (multitrack) */ -static unsigned int rates[] = { +static const unsigned int rates[] = { 8000, 9600, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000, 64000, 88200, 96000, 176400, 192000, }; -static struct snd_pcm_hw_constraint_list hw_constraints_rates_96 = { +static const struct snd_pcm_hw_constraint_list hw_constraints_rates_96 = { .count = ARRAY_SIZE(rates) - 2, /* up to 96000 */ .list = rates, .mask = 0, }; -static struct snd_pcm_hw_constraint_list hw_constraints_rates_48 = { +static const struct snd_pcm_hw_constraint_list hw_constraints_rates_48 = { .count = ARRAY_SIZE(rates) - 5, /* up to 48000 */ .list = rates, .mask = 0, }; -static struct snd_pcm_hw_constraint_list hw_constraints_rates_192 = { +static const struct snd_pcm_hw_constraint_list hw_constraints_rates_192 = { .count = ARRAY_SIZE(rates), .list = rates, .mask = 0, @@ -2142,7 +2142,7 @@ static int snd_vt1724_pro_route_spdif_put(struct snd_kcontrol *kcontrol, digital_route_shift(idx)); } -static struct snd_kcontrol_new snd_vt1724_mixer_pro_analog_route = +static const struct snd_kcontrol_new snd_vt1724_mixer_pro_analog_route = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "H/W Playback Route", diff --git a/sound/pci/ice1712/juli.c b/sound/pci/ice1712/juli.c index 4f0213427152..5bb146703738 100644 --- a/sound/pci/ice1712/juli.c +++ b/sound/pci/ice1712/juli.c @@ -133,19 +133,19 @@ struct juli_spec { /* * Initial setup of the conversion array GPIO <-> rate */ -static unsigned int juli_rates[] = { +static const unsigned int juli_rates[] = { 16000, 22050, 24000, 32000, 44100, 48000, 64000, 88200, 96000, 176400, 192000, }; -static unsigned int gpio_vals[] = { +static const unsigned int gpio_vals[] = { GPIO_RATE_16000, GPIO_RATE_22050, GPIO_RATE_24000, GPIO_RATE_32000, GPIO_RATE_44100, GPIO_RATE_48000, GPIO_RATE_64000, GPIO_RATE_88200, GPIO_RATE_96000, GPIO_RATE_176400, GPIO_RATE_192000, }; -static struct snd_pcm_hw_constraint_list juli_rates_info = { +static const struct snd_pcm_hw_constraint_list juli_rates_info = { .count = ARRAY_SIZE(juli_rates), .list = juli_rates, .mask = 0, diff --git a/sound/pci/ice1712/maya44.c b/sound/pci/ice1712/maya44.c index 7de25c4807fd..0e30419f6bbd 100644 --- a/sound/pci/ice1712/maya44.c +++ b/sound/pci/ice1712/maya44.c @@ -661,12 +661,12 @@ static void set_rate(struct snd_ice1712 *ice, unsigned int rate) * supported sample rates (to override the default one) */ -static unsigned int rates[] = { +static const unsigned int rates[] = { 32000, 44100, 48000, 64000, 88200, 96000, 176400, 192000 }; /* playback rates: 32..192 kHz */ -static struct snd_pcm_hw_constraint_list dac_rates = { +static const struct snd_pcm_hw_constraint_list dac_rates = { .count = ARRAY_SIZE(rates), .list = rates, .mask = 0 diff --git a/sound/pci/ice1712/quartet.c b/sound/pci/ice1712/quartet.c index 7c387b04067e..f1b3732cc6d2 100644 --- a/sound/pci/ice1712/quartet.c +++ b/sound/pci/ice1712/quartet.c @@ -231,17 +231,17 @@ static char *get_binary(char *buffer, int value) /* * Initial setup of the conversion array GPIO <-> rate */ -static unsigned int qtet_rates[] = { +static const unsigned int qtet_rates[] = { 44100, 48000, 88200, 96000, 176400, 192000, }; -static unsigned int cks_vals[] = { +static const unsigned int cks_vals[] = { CPLD_CKS_44100HZ, CPLD_CKS_48000HZ, CPLD_CKS_88200HZ, CPLD_CKS_96000HZ, CPLD_CKS_176400HZ, CPLD_CKS_192000HZ, }; -static struct snd_pcm_hw_constraint_list qtet_rates_info = { +static const struct snd_pcm_hw_constraint_list qtet_rates_info = { .count = ARRAY_SIZE(qtet_rates), .list = qtet_rates, .mask = 0, diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 6d17b171c17b..a8d7092e93dd 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -1136,31 +1136,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, diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c index 1bc98c867133..18ff668ce7a5 100644 --- a/sound/pci/intel8x0m.c +++ b/sound/pci/intel8x0m.c @@ -635,8 +635,8 @@ static struct snd_pcm_hardware snd_intel8x0m_stream = static int snd_intel8x0m_pcm_open(struct snd_pcm_substream *substream, struct ichdev *ichdev) { - static unsigned int rates[] = { 8000, 9600, 12000, 16000 }; - static struct snd_pcm_hw_constraint_list hw_constraints_rates = { + static const unsigned int rates[] = { 8000, 9600, 12000, 16000 }; + static const struct snd_pcm_hw_constraint_list hw_constraints_rates = { .count = ARRAY_SIZE(rates), .list = rates, .mask = 0, diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c index 1e25095fd144..b28fe4914d6b 100644 --- a/sound/pci/korg1212/korg1212.c +++ b/sound/pci/korg1212/korg1212.c @@ -1299,13 +1299,21 @@ static int snd_korg1212_silence(struct snd_korg1212 *korg1212, int pos, int coun return 0; } -static int snd_korg1212_copy_to(struct snd_korg1212 *korg1212, void __user *dst, int pos, int count, int offset, int size) +static int snd_korg1212_copy_to(struct snd_pcm_substream *substream, + void __user *dst, int pos, int count, + bool in_kernel) { - struct KorgAudioFrame * src = korg1212->recordDataBufsPtr[0].bufferData + pos; - int i, rc; - - K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_copy_to pos=%d offset=%d size=%d\n", - pos, offset, size); + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream); + struct KorgAudioFrame *src; + int i, size; + + pos = bytes_to_frames(runtime, pos); + count = bytes_to_frames(runtime, count); + size = korg1212->channels * 2; + src = korg1212->recordDataBufsPtr[0].bufferData + pos; + K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_copy_to pos=%d size=%d count=%d\n", + pos, size, count); if (snd_BUG_ON(pos + count > K1212_MAX_SAMPLES)) return -EINVAL; @@ -1317,11 +1325,10 @@ static int snd_korg1212_copy_to(struct snd_korg1212 *korg1212, void __user *dst, return -EFAULT; } #endif - rc = copy_to_user(dst + offset, src, size); - if (rc) { - K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_copy_to USER EFAULT src=%p dst=%p iter=%d\n", src, dst, i); + if (in_kernel) + memcpy((void *)dst, src, size); + else if (copy_to_user(dst, src, size)) return -EFAULT; - } src++; dst += size; } @@ -1329,13 +1336,22 @@ static int snd_korg1212_copy_to(struct snd_korg1212 *korg1212, void __user *dst, return 0; } -static int snd_korg1212_copy_from(struct snd_korg1212 *korg1212, void __user *src, int pos, int count, int offset, int size) +static int snd_korg1212_copy_from(struct snd_pcm_substream *substream, + void __user *src, int pos, int count, + bool in_kernel) { - struct KorgAudioFrame * dst = korg1212->playDataBufsPtr[0].bufferData + pos; - int i, rc; + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream); + struct KorgAudioFrame *dst; + int i, size; - K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_copy_from pos=%d offset=%d size=%d count=%d\n", - pos, offset, size, count); + pos = bytes_to_frames(runtime, pos); + count = bytes_to_frames(runtime, count); + size = korg1212->channels * 2; + dst = korg1212->playDataBufsPtr[0].bufferData + pos; + + K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_copy_from pos=%d size=%d count=%d\n", + pos, size, count); if (snd_BUG_ON(pos + count > K1212_MAX_SAMPLES)) return -EINVAL; @@ -1348,11 +1364,10 @@ static int snd_korg1212_copy_from(struct snd_korg1212 *korg1212, void __user *sr return -EFAULT; } #endif - rc = copy_from_user((void*) dst + offset, src, size); - if (rc) { - K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_copy_from USER EFAULT src=%p dst=%p iter=%d\n", src, dst, i); + if (in_kernel) + memcpy((void *)dst, src, size); + else if (copy_from_user(dst, src, size)) return -EFAULT; - } dst++; src += size; } @@ -1640,45 +1655,46 @@ static snd_pcm_uframes_t snd_korg1212_capture_pointer(struct snd_pcm_substream * } static int snd_korg1212_playback_copy(struct snd_pcm_substream *substream, - int channel, /* not used (interleaved data) */ - snd_pcm_uframes_t pos, - void __user *src, - snd_pcm_uframes_t count) + int channel, unsigned long pos, + void __user *src, unsigned long count) { - struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream); - - K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_playback_copy [%s] %ld %ld\n", - stateName[korg1212->cardState], pos, count); - - return snd_korg1212_copy_from(korg1212, src, pos, count, 0, korg1212->channels * 2); + return snd_korg1212_copy_from(substream, src, pos, count, false); +} +static int snd_korg1212_playback_copy_kernel(struct snd_pcm_substream *substream, + int channel, unsigned long pos, + void *src, unsigned long count) +{ + return snd_korg1212_copy_from(substream, (void __user *)src, + pos, count, true); } static int snd_korg1212_playback_silence(struct snd_pcm_substream *substream, int channel, /* not used (interleaved data) */ - snd_pcm_uframes_t pos, - snd_pcm_uframes_t count) + unsigned long pos, + unsigned long count) { + struct snd_pcm_runtime *runtime = substream->runtime; struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream); - K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_playback_silence [%s]\n", - stateName[korg1212->cardState]); - - return snd_korg1212_silence(korg1212, pos, count, 0, korg1212->channels * 2); + return snd_korg1212_silence(korg1212, bytes_to_frames(runtime, pos), + bytes_to_frames(runtime, count), + 0, korg1212->channels * 2); } static int snd_korg1212_capture_copy(struct snd_pcm_substream *substream, - int channel, /* not used (interleaved data) */ - snd_pcm_uframes_t pos, - void __user *dst, - snd_pcm_uframes_t count) + int channel, unsigned long pos, + void __user *dst, unsigned long count) { - struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream); - - K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_capture_copy [%s] %ld %ld\n", - stateName[korg1212->cardState], pos, count); + return snd_korg1212_copy_to(substream, dst, pos, count, false); +} - return snd_korg1212_copy_to(korg1212, dst, pos, count, 0, korg1212->channels * 2); +static int snd_korg1212_capture_copy_kernel(struct snd_pcm_substream *substream, + int channel, unsigned long pos, + void *dst, unsigned long count) +{ + return snd_korg1212_copy_to(substream, (void __user *)dst, + pos, count, true); } static const struct snd_pcm_ops snd_korg1212_playback_ops = { @@ -1689,8 +1705,9 @@ static const struct snd_pcm_ops snd_korg1212_playback_ops = { .prepare = snd_korg1212_prepare, .trigger = snd_korg1212_trigger, .pointer = snd_korg1212_playback_pointer, - .copy = snd_korg1212_playback_copy, - .silence = snd_korg1212_playback_silence, + .copy_user = snd_korg1212_playback_copy, + .copy_kernel = snd_korg1212_playback_copy_kernel, + .fill_silence = snd_korg1212_playback_silence, }; static const struct snd_pcm_ops snd_korg1212_capture_ops = { @@ -1701,7 +1718,8 @@ static const struct snd_pcm_ops snd_korg1212_capture_ops = { .prepare = snd_korg1212_prepare, .trigger = snd_korg1212_trigger, .pointer = snd_korg1212_capture_pointer, - .copy = snd_korg1212_capture_copy, + .copy_user = snd_korg1212_capture_copy, + .copy_kernel = snd_korg1212_capture_copy_kernel, }; /* diff --git a/sound/pci/mixart/mixart_core.c b/sound/pci/mixart/mixart_core.c index dccf3db48fe0..8bf2ce32d4a8 100644 --- a/sound/pci/mixart/mixart_core.c +++ b/sound/pci/mixart/mixart_core.c @@ -239,7 +239,7 @@ int snd_mixart_send_msg(struct mixart_mgr *mgr, struct mixart_msg *request, int struct mixart_msg resp; u32 msg_frame = 0; /* set to 0, so it's no notification to wait for, but the answer */ int err; - wait_queue_t wait; + wait_queue_entry_t wait; long timeout; init_waitqueue_entry(&wait, current); @@ -284,7 +284,7 @@ int snd_mixart_send_msg_wait_notif(struct mixart_mgr *mgr, struct mixart_msg *request, u32 notif_event) { int err; - wait_queue_t wait; + wait_queue_entry_t wait; long timeout; if (snd_BUG_ON(!notif_event)) diff --git a/sound/pci/mixart/mixart_mixer.c b/sound/pci/mixart/mixart_mixer.c index 4a4616aac787..2b9496a66c77 100644 --- a/sound/pci/mixart/mixart_mixer.c +++ b/sound/pci/mixart/mixart_mixer.c @@ -404,7 +404,7 @@ static int mixart_analog_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e static const DECLARE_TLV_DB_SCALE(db_scale_analog, -9600, 50, 0); -static struct snd_kcontrol_new mixart_control_analog_level = { +static const struct snd_kcontrol_new mixart_control_analog_level = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ), @@ -897,7 +897,7 @@ static int mixart_pcm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem static const DECLARE_TLV_DB_SCALE(db_scale_digital, -10950, 50, 0); -static struct snd_kcontrol_new snd_mixart_pcm_vol = +static const struct snd_kcontrol_new snd_mixart_pcm_vol = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | @@ -951,7 +951,7 @@ static int mixart_pcm_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_ return changed; } -static struct snd_kcontrol_new mixart_control_pcm_switch = { +static const struct snd_kcontrol_new mixart_control_pcm_switch = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, /* name will be filled later */ .count = MIXART_PLAYBACK_STREAMS, diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c index 103fe311e5a9..0ef8054c3936 100644 --- a/sound/pci/nm256/nm256.c +++ b/sound/pci/nm256/nm256.c @@ -398,10 +398,10 @@ snd_nm256_load_coefficient(struct nm256 *chip, int stream, int number) /* The actual rates supported by the card. */ -static unsigned int samplerates[8] = { +static const unsigned int samplerates[8] = { 8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000, }; -static struct snd_pcm_hw_constraint_list constraints_rates = { +static const struct snd_pcm_hw_constraint_list constraints_rates = { .count = ARRAY_SIZE(samplerates), .list = samplerates, .mask = 0, @@ -695,53 +695,68 @@ snd_nm256_capture_pointer(struct snd_pcm_substream *substream) */ static int snd_nm256_playback_silence(struct snd_pcm_substream *substream, - int channel, /* not used (interleaved data) */ - snd_pcm_uframes_t pos, - snd_pcm_uframes_t count) + int channel, unsigned long pos, unsigned long count) { struct snd_pcm_runtime *runtime = substream->runtime; struct nm256_stream *s = runtime->private_data; - count = frames_to_bytes(runtime, count); - pos = frames_to_bytes(runtime, pos); + memset_io(s->bufptr + pos, 0, count); return 0; } static int snd_nm256_playback_copy(struct snd_pcm_substream *substream, - int channel, /* not used (interleaved data) */ - snd_pcm_uframes_t pos, - void __user *src, - snd_pcm_uframes_t count) + int channel, unsigned long pos, + void __user *src, unsigned long count) { struct snd_pcm_runtime *runtime = substream->runtime; struct nm256_stream *s = runtime->private_data; - count = frames_to_bytes(runtime, count); - pos = frames_to_bytes(runtime, pos); + if (copy_from_user_toio(s->bufptr + pos, src, count)) return -EFAULT; return 0; } +static int +snd_nm256_playback_copy_kernel(struct snd_pcm_substream *substream, + int channel, unsigned long pos, + void *src, unsigned long count) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct nm256_stream *s = runtime->private_data; + + memcpy_toio(s->bufptr + pos, src, count); + return 0; +} + /* * copy to user */ static int snd_nm256_capture_copy(struct snd_pcm_substream *substream, - int channel, /* not used (interleaved data) */ - snd_pcm_uframes_t pos, - void __user *dst, - snd_pcm_uframes_t count) + int channel, unsigned long pos, + void __user *dst, unsigned long count) { struct snd_pcm_runtime *runtime = substream->runtime; struct nm256_stream *s = runtime->private_data; - count = frames_to_bytes(runtime, count); - pos = frames_to_bytes(runtime, pos); + if (copy_to_user_fromio(dst, s->bufptr + pos, count)) return -EFAULT; return 0; } +static int +snd_nm256_capture_copy_kernel(struct snd_pcm_substream *substream, + int channel, unsigned long pos, + void *dst, unsigned long count) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct nm256_stream *s = runtime->private_data; + + memcpy_fromio(dst, s->bufptr + pos, count); + return 0; +} + #endif /* !__i386__ */ @@ -911,8 +926,9 @@ static const struct snd_pcm_ops snd_nm256_playback_ops = { .trigger = snd_nm256_playback_trigger, .pointer = snd_nm256_playback_pointer, #ifndef __i386__ - .copy = snd_nm256_playback_copy, - .silence = snd_nm256_playback_silence, + .copy_user = snd_nm256_playback_copy, + .copy_kernel = snd_nm256_playback_copy_kernel, + .fill_silence = snd_nm256_playback_silence, #endif .mmap = snd_pcm_lib_mmap_iomem, }; @@ -926,7 +942,8 @@ static const struct snd_pcm_ops snd_nm256_capture_ops = { .trigger = snd_nm256_capture_trigger, .pointer = snd_nm256_capture_pointer, #ifndef __i386__ - .copy = snd_nm256_capture_copy, + .copy_user = snd_nm256_capture_copy, + .copy_kernel = snd_nm256_capture_copy_kernel, #endif .mmap = snd_pcm_lib_mmap_iomem, }; diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c index 96d15db65dfd..e4cdef94e4a2 100644 --- a/sound/pci/rme32.c +++ b/sound/pci/rme32.c @@ -254,39 +254,46 @@ static inline unsigned int snd_rme32_pcm_byteptr(struct rme32 * rme32) } /* silence callback for halfduplex mode */ -static int snd_rme32_playback_silence(struct snd_pcm_substream *substream, int channel, /* not used (interleaved data) */ - snd_pcm_uframes_t pos, - snd_pcm_uframes_t count) +static int snd_rme32_playback_silence(struct snd_pcm_substream *substream, + int channel, unsigned long pos, + unsigned long count) { struct rme32 *rme32 = snd_pcm_substream_chip(substream); - count <<= rme32->playback_frlog; - pos <<= rme32->playback_frlog; + memset_io(rme32->iobase + RME32_IO_DATA_BUFFER + pos, 0, count); return 0; } /* copy callback for halfduplex mode */ -static int snd_rme32_playback_copy(struct snd_pcm_substream *substream, int channel, /* not used (interleaved data) */ - snd_pcm_uframes_t pos, - void __user *src, snd_pcm_uframes_t count) +static int snd_rme32_playback_copy(struct snd_pcm_substream *substream, + int channel, unsigned long pos, + void __user *src, unsigned long count) { struct rme32 *rme32 = snd_pcm_substream_chip(substream); - count <<= rme32->playback_frlog; - pos <<= rme32->playback_frlog; + if (copy_from_user_toio(rme32->iobase + RME32_IO_DATA_BUFFER + pos, - src, count)) + src, count)) return -EFAULT; return 0; } +static int snd_rme32_playback_copy_kernel(struct snd_pcm_substream *substream, + int channel, unsigned long pos, + void *src, unsigned long count) +{ + struct rme32 *rme32 = snd_pcm_substream_chip(substream); + + memcpy_toio(rme32->iobase + RME32_IO_DATA_BUFFER + pos, src, count); + return 0; +} + /* copy callback for halfduplex mode */ -static int snd_rme32_capture_copy(struct snd_pcm_substream *substream, int channel, /* not used (interleaved data) */ - snd_pcm_uframes_t pos, - void __user *dst, snd_pcm_uframes_t count) +static int snd_rme32_capture_copy(struct snd_pcm_substream *substream, + int channel, unsigned long pos, + void __user *dst, unsigned long count) { struct rme32 *rme32 = snd_pcm_substream_chip(substream); - count <<= rme32->capture_frlog; - pos <<= rme32->capture_frlog; + if (copy_to_user_fromio(dst, rme32->iobase + RME32_IO_DATA_BUFFER + pos, count)) @@ -294,6 +301,16 @@ static int snd_rme32_capture_copy(struct snd_pcm_substream *substream, int chann return 0; } +static int snd_rme32_capture_copy_kernel(struct snd_pcm_substream *substream, + int channel, unsigned long pos, + void *dst, unsigned long count) +{ + struct rme32 *rme32 = snd_pcm_substream_chip(substream); + + memcpy_fromio(dst, rme32->iobase + RME32_IO_DATA_BUFFER + pos, count); + return 0; +} + /* * SPDIF I/O capabilities (half-duplex mode) */ @@ -819,10 +836,9 @@ static irqreturn_t snd_rme32_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -static unsigned int period_bytes[] = { RME32_BLOCK_SIZE }; - +static const unsigned int period_bytes[] = { RME32_BLOCK_SIZE }; -static struct snd_pcm_hw_constraint_list hw_constraints_period_bytes = { +static const struct snd_pcm_hw_constraint_list hw_constraints_period_bytes = { .count = ARRAY_SIZE(period_bytes), .list = period_bytes, .mask = 0 @@ -1157,9 +1173,8 @@ static int snd_rme32_playback_fd_ack(struct snd_pcm_substream *substream) if (rme32->running & (1 << SNDRV_PCM_STREAM_CAPTURE)) rec->hw_queue_size -= cprec->hw_ready; spin_unlock(&rme32->lock); - snd_pcm_indirect_playback_transfer(substream, rec, - snd_rme32_pb_trans_copy); - return 0; + return snd_pcm_indirect_playback_transfer(substream, rec, + snd_rme32_pb_trans_copy); } static void snd_rme32_cp_trans_copy(struct snd_pcm_substream *substream, @@ -1174,9 +1189,8 @@ static void snd_rme32_cp_trans_copy(struct snd_pcm_substream *substream, static int snd_rme32_capture_fd_ack(struct snd_pcm_substream *substream) { struct rme32 *rme32 = snd_pcm_substream_chip(substream); - snd_pcm_indirect_capture_transfer(substream, &rme32->capture_pcm, - snd_rme32_cp_trans_copy); - return 0; + return snd_pcm_indirect_capture_transfer(substream, &rme32->capture_pcm, + snd_rme32_cp_trans_copy); } static snd_pcm_uframes_t @@ -1205,8 +1219,9 @@ static const struct snd_pcm_ops snd_rme32_playback_spdif_ops = { .prepare = snd_rme32_playback_prepare, .trigger = snd_rme32_pcm_trigger, .pointer = snd_rme32_playback_pointer, - .copy = snd_rme32_playback_copy, - .silence = snd_rme32_playback_silence, + .copy_user = snd_rme32_playback_copy, + .copy_kernel = snd_rme32_playback_copy_kernel, + .fill_silence = snd_rme32_playback_silence, .mmap = snd_pcm_lib_mmap_iomem, }; @@ -1219,7 +1234,8 @@ static const struct snd_pcm_ops snd_rme32_capture_spdif_ops = { .prepare = snd_rme32_capture_prepare, .trigger = snd_rme32_pcm_trigger, .pointer = snd_rme32_capture_pointer, - .copy = snd_rme32_capture_copy, + .copy_user = snd_rme32_capture_copy, + .copy_kernel = snd_rme32_capture_copy_kernel, .mmap = snd_pcm_lib_mmap_iomem, }; @@ -1231,8 +1247,9 @@ static const struct snd_pcm_ops snd_rme32_playback_adat_ops = { .prepare = snd_rme32_playback_prepare, .trigger = snd_rme32_pcm_trigger, .pointer = snd_rme32_playback_pointer, - .copy = snd_rme32_playback_copy, - .silence = snd_rme32_playback_silence, + .copy_user = snd_rme32_playback_copy, + .copy_kernel = snd_rme32_playback_copy_kernel, + .fill_silence = snd_rme32_playback_silence, .mmap = snd_pcm_lib_mmap_iomem, }; @@ -1244,7 +1261,8 @@ static const struct snd_pcm_ops snd_rme32_capture_adat_ops = { .prepare = snd_rme32_capture_prepare, .trigger = snd_rme32_pcm_trigger, .pointer = snd_rme32_capture_pointer, - .copy = snd_rme32_capture_copy, + .copy_user = snd_rme32_capture_copy, + .copy_kernel = snd_rme32_capture_copy_kernel, .mmap = snd_pcm_lib_mmap_iomem, }; diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c index 05b9da30990d..2e19ba55e754 100644 --- a/sound/pci/rme96.c +++ b/sound/pci/rme96.c @@ -327,13 +327,10 @@ snd_rme96_capture_ptr(struct rme96 *rme96) static int snd_rme96_playback_silence(struct snd_pcm_substream *substream, - int channel, /* not used (interleaved data) */ - snd_pcm_uframes_t pos, - snd_pcm_uframes_t count) + int channel, unsigned long pos, unsigned long count) { struct rme96 *rme96 = snd_pcm_substream_chip(substream); - count <<= rme96->playback_frlog; - pos <<= rme96->playback_frlog; + memset_io(rme96->iobase + RME96_IO_PLAY_BUFFER + pos, 0, count); return 0; @@ -341,32 +338,49 @@ snd_rme96_playback_silence(struct snd_pcm_substream *substream, static int snd_rme96_playback_copy(struct snd_pcm_substream *substream, - int channel, /* not used (interleaved data) */ - snd_pcm_uframes_t pos, - void __user *src, - snd_pcm_uframes_t count) + int channel, unsigned long pos, + void __user *src, unsigned long count) { struct rme96 *rme96 = snd_pcm_substream_chip(substream); - count <<= rme96->playback_frlog; - pos <<= rme96->playback_frlog; - return copy_from_user_toio(rme96->iobase + RME96_IO_PLAY_BUFFER + pos, src, - count); + + return copy_from_user_toio(rme96->iobase + RME96_IO_PLAY_BUFFER + pos, + src, count); +} + +static int +snd_rme96_playback_copy_kernel(struct snd_pcm_substream *substream, + int channel, unsigned long pos, + void *src, unsigned long count) +{ + struct rme96 *rme96 = snd_pcm_substream_chip(substream); + + memcpy_toio(rme96->iobase + RME96_IO_PLAY_BUFFER + pos, src, count); + return 0; } static int snd_rme96_capture_copy(struct snd_pcm_substream *substream, - int channel, /* not used (interleaved data) */ - snd_pcm_uframes_t pos, - void __user *dst, - snd_pcm_uframes_t count) + int channel, unsigned long pos, + void __user *dst, unsigned long count) { struct rme96 *rme96 = snd_pcm_substream_chip(substream); - count <<= rme96->capture_frlog; - pos <<= rme96->capture_frlog; - return copy_to_user_fromio(dst, rme96->iobase + RME96_IO_REC_BUFFER + pos, + + return copy_to_user_fromio(dst, + rme96->iobase + RME96_IO_REC_BUFFER + pos, count); } +static int +snd_rme96_capture_copy_kernel(struct snd_pcm_substream *substream, + int channel, unsigned long pos, + void *dst, unsigned long count) +{ + struct rme96 *rme96 = snd_pcm_substream_chip(substream); + + memcpy_fromio(dst, rme96->iobase + RME96_IO_REC_BUFFER + pos, count); + return 0; +} + /* * Digital output capabilities (S/PDIF) */ @@ -1149,9 +1163,9 @@ snd_rme96_interrupt(int irq, return IRQ_HANDLED; } -static unsigned int period_bytes[] = { RME96_SMALL_BLOCK_SIZE, RME96_LARGE_BLOCK_SIZE }; +static const unsigned int period_bytes[] = { RME96_SMALL_BLOCK_SIZE, RME96_LARGE_BLOCK_SIZE }; -static struct snd_pcm_hw_constraint_list hw_constraints_period_bytes = { +static const struct snd_pcm_hw_constraint_list hw_constraints_period_bytes = { .count = ARRAY_SIZE(period_bytes), .list = period_bytes, .mask = 0 @@ -1513,8 +1527,9 @@ static const struct snd_pcm_ops snd_rme96_playback_spdif_ops = { .prepare = snd_rme96_playback_prepare, .trigger = snd_rme96_playback_trigger, .pointer = snd_rme96_playback_pointer, - .copy = snd_rme96_playback_copy, - .silence = snd_rme96_playback_silence, + .copy_user = snd_rme96_playback_copy, + .copy_kernel = snd_rme96_playback_copy_kernel, + .fill_silence = snd_rme96_playback_silence, .mmap = snd_pcm_lib_mmap_iomem, }; @@ -1526,7 +1541,8 @@ static const struct snd_pcm_ops snd_rme96_capture_spdif_ops = { .prepare = snd_rme96_capture_prepare, .trigger = snd_rme96_capture_trigger, .pointer = snd_rme96_capture_pointer, - .copy = snd_rme96_capture_copy, + .copy_user = snd_rme96_capture_copy, + .copy_kernel = snd_rme96_capture_copy_kernel, .mmap = snd_pcm_lib_mmap_iomem, }; @@ -1538,8 +1554,9 @@ static const struct snd_pcm_ops snd_rme96_playback_adat_ops = { .prepare = snd_rme96_playback_prepare, .trigger = snd_rme96_playback_trigger, .pointer = snd_rme96_playback_pointer, - .copy = snd_rme96_playback_copy, - .silence = snd_rme96_playback_silence, + .copy_user = snd_rme96_playback_copy, + .copy_kernel = snd_rme96_playback_copy_kernel, + .fill_silence = snd_rme96_playback_silence, .mmap = snd_pcm_lib_mmap_iomem, }; @@ -1551,7 +1568,8 @@ static const struct snd_pcm_ops snd_rme96_capture_adat_ops = { .prepare = snd_rme96_capture_prepare, .trigger = snd_rme96_capture_trigger, .pointer = snd_rme96_capture_pointer, - .copy = snd_rme96_capture_copy, + .copy_user = snd_rme96_capture_copy, + .copy_kernel = snd_rme96_capture_copy_kernel, .mmap = snd_pcm_lib_mmap_iomem, }; diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c index fc0face6cdc6..fe36d44d16c6 100644 --- a/sound/pci/rme9652/hdsp.c +++ b/sound/pci/rme9652/hdsp.c @@ -3913,42 +3913,73 @@ static char *hdsp_channel_buffer_location(struct hdsp *hdsp, return hdsp->playback_buffer + (mapped_channel * HDSP_CHANNEL_BUFFER_BYTES); } -static int snd_hdsp_playback_copy(struct snd_pcm_substream *substream, int channel, - snd_pcm_uframes_t pos, void __user *src, snd_pcm_uframes_t count) +static int snd_hdsp_playback_copy(struct snd_pcm_substream *substream, + int channel, unsigned long pos, + void __user *src, unsigned long count) { struct hdsp *hdsp = snd_pcm_substream_chip(substream); char *channel_buf; - if (snd_BUG_ON(pos + count > HDSP_CHANNEL_BUFFER_BYTES / 4)) + if (snd_BUG_ON(pos + count > HDSP_CHANNEL_BUFFER_BYTES)) return -EINVAL; channel_buf = hdsp_channel_buffer_location (hdsp, substream->pstr->stream, channel); if (snd_BUG_ON(!channel_buf)) return -EIO; - if (copy_from_user(channel_buf + pos * 4, src, count * 4)) + if (copy_from_user(channel_buf + pos, src, count)) return -EFAULT; - return count; + return 0; } -static int snd_hdsp_capture_copy(struct snd_pcm_substream *substream, int channel, - snd_pcm_uframes_t pos, void __user *dst, snd_pcm_uframes_t count) +static int snd_hdsp_playback_copy_kernel(struct snd_pcm_substream *substream, + int channel, unsigned long pos, + void *src, unsigned long count) { struct hdsp *hdsp = snd_pcm_substream_chip(substream); char *channel_buf; - if (snd_BUG_ON(pos + count > HDSP_CHANNEL_BUFFER_BYTES / 4)) + channel_buf = hdsp_channel_buffer_location(hdsp, substream->pstr->stream, channel); + if (snd_BUG_ON(!channel_buf)) + return -EIO; + memcpy(channel_buf + pos, src, count); + return 0; +} + +static int snd_hdsp_capture_copy(struct snd_pcm_substream *substream, + int channel, unsigned long pos, + void __user *dst, unsigned long count) +{ + struct hdsp *hdsp = snd_pcm_substream_chip(substream); + char *channel_buf; + + if (snd_BUG_ON(pos + count > HDSP_CHANNEL_BUFFER_BYTES)) return -EINVAL; channel_buf = hdsp_channel_buffer_location (hdsp, substream->pstr->stream, channel); if (snd_BUG_ON(!channel_buf)) return -EIO; - if (copy_to_user(dst, channel_buf + pos * 4, count * 4)) + if (copy_to_user(dst, channel_buf + pos, count)) return -EFAULT; - return count; + return 0; } -static int snd_hdsp_hw_silence(struct snd_pcm_substream *substream, int channel, - snd_pcm_uframes_t pos, snd_pcm_uframes_t count) +static int snd_hdsp_capture_copy_kernel(struct snd_pcm_substream *substream, + int channel, unsigned long pos, + void *dst, unsigned long count) +{ + struct hdsp *hdsp = snd_pcm_substream_chip(substream); + char *channel_buf; + + channel_buf = hdsp_channel_buffer_location(hdsp, substream->pstr->stream, channel); + if (snd_BUG_ON(!channel_buf)) + return -EIO; + memcpy(dst, channel_buf + pos, count); + return 0; +} + +static int snd_hdsp_hw_silence(struct snd_pcm_substream *substream, + int channel, unsigned long pos, + unsigned long count) { struct hdsp *hdsp = snd_pcm_substream_chip(substream); char *channel_buf; @@ -3956,8 +3987,8 @@ static int snd_hdsp_hw_silence(struct snd_pcm_substream *substream, int channel, channel_buf = hdsp_channel_buffer_location (hdsp, substream->pstr->stream, channel); if (snd_BUG_ON(!channel_buf)) return -EIO; - memset(channel_buf + pos * 4, 0, count * 4); - return count; + memset(channel_buf + pos, 0, count); + return 0; } static int snd_hdsp_reset(struct snd_pcm_substream *substream) @@ -4239,17 +4270,17 @@ static struct snd_pcm_hardware snd_hdsp_capture_subinfo = .fifo_size = 0 }; -static unsigned int hdsp_period_sizes[] = { 64, 128, 256, 512, 1024, 2048, 4096, 8192 }; +static const unsigned int hdsp_period_sizes[] = { 64, 128, 256, 512, 1024, 2048, 4096, 8192 }; -static struct snd_pcm_hw_constraint_list hdsp_hw_constraints_period_sizes = { +static const struct snd_pcm_hw_constraint_list hdsp_hw_constraints_period_sizes = { .count = ARRAY_SIZE(hdsp_period_sizes), .list = hdsp_period_sizes, .mask = 0 }; -static unsigned int hdsp_9632_sample_rates[] = { 32000, 44100, 48000, 64000, 88200, 96000, 128000, 176400, 192000 }; +static const unsigned int hdsp_9632_sample_rates[] = { 32000, 44100, 48000, 64000, 88200, 96000, 128000, 176400, 192000 }; -static struct snd_pcm_hw_constraint_list hdsp_hw_constraints_9632_sample_rates = { +static const struct snd_pcm_hw_constraint_list hdsp_hw_constraints_9632_sample_rates = { .count = ARRAY_SIZE(hdsp_9632_sample_rates), .list = hdsp_9632_sample_rates, .mask = 0 @@ -4869,8 +4900,9 @@ static const struct snd_pcm_ops snd_hdsp_playback_ops = { .prepare = snd_hdsp_prepare, .trigger = snd_hdsp_trigger, .pointer = snd_hdsp_hw_pointer, - .copy = snd_hdsp_playback_copy, - .silence = snd_hdsp_hw_silence, + .copy_user = snd_hdsp_playback_copy, + .copy_kernel = snd_hdsp_playback_copy_kernel, + .fill_silence = snd_hdsp_hw_silence, }; static const struct snd_pcm_ops snd_hdsp_capture_ops = { @@ -4881,7 +4913,8 @@ static const struct snd_pcm_ops snd_hdsp_capture_ops = { .prepare = snd_hdsp_prepare, .trigger = snd_hdsp_trigger, .pointer = snd_hdsp_hw_pointer, - .copy = snd_hdsp_capture_copy, + .copy_user = snd_hdsp_capture_copy, + .copy_kernel = snd_hdsp_capture_copy_kernel, }; static int snd_hdsp_create_hwdep(struct snd_card *card, struct hdsp *hdsp) diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index c48acdb0e186..254c3d040118 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c @@ -6040,11 +6040,11 @@ static int snd_hdspm_hw_rule_out_channels(struct snd_pcm_hw_params *params, } -static unsigned int hdspm_aes32_sample_rates[] = { +static const unsigned int hdspm_aes32_sample_rates[] = { 32000, 44100, 48000, 64000, 88200, 96000, 128000, 176400, 192000 }; -static struct snd_pcm_hw_constraint_list +static const struct snd_pcm_hw_constraint_list hdspm_hw_constraints_aes32_sample_rates = { .count = ARRAY_SIZE(hdspm_aes32_sample_rates), .list = hdspm_aes32_sample_rates, diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c index 55172c689991..150d08898db8 100644 --- a/sound/pci/rme9652/rme9652.c +++ b/sound/pci/rme9652/rme9652.c @@ -1883,13 +1883,14 @@ static char *rme9652_channel_buffer_location(struct snd_rme9652 *rme9652, } } -static int snd_rme9652_playback_copy(struct snd_pcm_substream *substream, int channel, - snd_pcm_uframes_t pos, void __user *src, snd_pcm_uframes_t count) +static int snd_rme9652_playback_copy(struct snd_pcm_substream *substream, + int channel, unsigned long pos, + void __user *src, unsigned long count) { struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream); char *channel_buf; - if (snd_BUG_ON(pos + count > RME9652_CHANNEL_BUFFER_BYTES / 4)) + if (snd_BUG_ON(pos + count > RME9652_CHANNEL_BUFFER_BYTES)) return -EINVAL; channel_buf = rme9652_channel_buffer_location (rme9652, @@ -1897,18 +1898,35 @@ static int snd_rme9652_playback_copy(struct snd_pcm_substream *substream, int ch channel); if (snd_BUG_ON(!channel_buf)) return -EIO; - if (copy_from_user(channel_buf + pos * 4, src, count * 4)) + if (copy_from_user(channel_buf + pos, src, count)) return -EFAULT; - return count; + return 0; } -static int snd_rme9652_capture_copy(struct snd_pcm_substream *substream, int channel, - snd_pcm_uframes_t pos, void __user *dst, snd_pcm_uframes_t count) +static int snd_rme9652_playback_copy_kernel(struct snd_pcm_substream *substream, + int channel, unsigned long pos, + void *src, unsigned long count) { struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream); char *channel_buf; - if (snd_BUG_ON(pos + count > RME9652_CHANNEL_BUFFER_BYTES / 4)) + channel_buf = rme9652_channel_buffer_location(rme9652, + substream->pstr->stream, + channel); + if (snd_BUG_ON(!channel_buf)) + return -EIO; + memcpy(channel_buf + pos, src, count); + return 0; +} + +static int snd_rme9652_capture_copy(struct snd_pcm_substream *substream, + int channel, unsigned long pos, + void __user *dst, unsigned long count) +{ + struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream); + char *channel_buf; + + if (snd_BUG_ON(pos + count > RME9652_CHANNEL_BUFFER_BYTES)) return -EINVAL; channel_buf = rme9652_channel_buffer_location (rme9652, @@ -1916,13 +1934,30 @@ static int snd_rme9652_capture_copy(struct snd_pcm_substream *substream, int cha channel); if (snd_BUG_ON(!channel_buf)) return -EIO; - if (copy_to_user(dst, channel_buf + pos * 4, count * 4)) + if (copy_to_user(dst, channel_buf + pos, count)) return -EFAULT; - return count; + return 0; } -static int snd_rme9652_hw_silence(struct snd_pcm_substream *substream, int channel, - snd_pcm_uframes_t pos, snd_pcm_uframes_t count) +static int snd_rme9652_capture_copy_kernel(struct snd_pcm_substream *substream, + int channel, unsigned long pos, + void *dst, unsigned long count) +{ + struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream); + char *channel_buf; + + channel_buf = rme9652_channel_buffer_location(rme9652, + substream->pstr->stream, + channel); + if (snd_BUG_ON(!channel_buf)) + return -EIO; + memcpy(dst, channel_buf + pos, count); + return 0; +} + +static int snd_rme9652_hw_silence(struct snd_pcm_substream *substream, + int channel, unsigned long pos, + unsigned long count) { struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream); char *channel_buf; @@ -1932,8 +1967,8 @@ static int snd_rme9652_hw_silence(struct snd_pcm_substream *substream, int chann channel); if (snd_BUG_ON(!channel_buf)) return -EIO; - memset(channel_buf + pos * 4, 0, count * 4); - return count; + memset(channel_buf + pos, 0, count); + return 0; } static int snd_rme9652_reset(struct snd_pcm_substream *substream) @@ -2193,9 +2228,9 @@ static struct snd_pcm_hardware snd_rme9652_capture_subinfo = .fifo_size = 0, }; -static unsigned int period_sizes[] = { 64, 128, 256, 512, 1024, 2048, 4096, 8192 }; +static const unsigned int period_sizes[] = { 64, 128, 256, 512, 1024, 2048, 4096, 8192 }; -static struct snd_pcm_hw_constraint_list hw_constraints_period_sizes = { +static const struct snd_pcm_hw_constraint_list hw_constraints_period_sizes = { .count = ARRAY_SIZE(period_sizes), .list = period_sizes, .mask = 0 @@ -2376,8 +2411,9 @@ static const struct snd_pcm_ops snd_rme9652_playback_ops = { .prepare = snd_rme9652_prepare, .trigger = snd_rme9652_trigger, .pointer = snd_rme9652_hw_pointer, - .copy = snd_rme9652_playback_copy, - .silence = snd_rme9652_hw_silence, + .copy_user = snd_rme9652_playback_copy, + .copy_kernel = snd_rme9652_playback_copy_kernel, + .fill_silence = snd_rme9652_hw_silence, }; static const struct snd_pcm_ops snd_rme9652_capture_ops = { @@ -2388,7 +2424,8 @@ static const struct snd_pcm_ops snd_rme9652_capture_ops = { .prepare = snd_rme9652_prepare, .trigger = snd_rme9652_trigger, .pointer = snd_rme9652_hw_pointer, - .copy = snd_rme9652_capture_copy, + .copy_user = snd_rme9652_capture_copy, + .copy_kernel = snd_rme9652_capture_copy_kernel, }; static int snd_rme9652_create_pcm(struct snd_card *card, diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c index 8e3d4ec39c35..784d762f18a7 100644 --- a/sound/pci/sonicvibes.c +++ b/sound/pci/sonicvibes.c @@ -248,13 +248,13 @@ static const struct pci_device_id snd_sonic_ids[] = { MODULE_DEVICE_TABLE(pci, snd_sonic_ids); -static struct snd_ratden sonicvibes_adc_clock = { +static const struct snd_ratden sonicvibes_adc_clock = { .num_min = 4000 * 65536, .num_max = 48000UL * 65536, .num_step = 1, .den = 65536, }; -static struct snd_pcm_hw_constraint_ratdens snd_sonicvibes_hw_constraints_adc_clock = { +static const struct snd_pcm_hw_constraint_ratdens snd_sonicvibes_hw_constraints_adc_clock = { .nrats = 1, .rats = &sonicvibes_adc_clock, }; diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index b6c84d15b10b..c767b8664359 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c @@ -1286,10 +1286,10 @@ static int snd_via8233_multi_open(struct snd_pcm_substream *substream) /* channels constraint for VIA8233A * 3 and 5 channels are not supported */ - static unsigned int channels[] = { + static const unsigned int channels[] = { 1, 2, 4, 6 }; - static struct snd_pcm_hw_constraint_list hw_constraints_channels = { + static const struct snd_pcm_hw_constraint_list hw_constraints_channels = { .count = ARRAY_SIZE(channels), .list = channels, .mask = 0, diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c index 2f6d40f10618..55f79b2599e7 100644 --- a/sound/pci/via82xx_modem.c +++ b/sound/pci/via82xx_modem.c @@ -744,8 +744,8 @@ static int snd_via82xx_modem_pcm_open(struct via82xx_modem *chip, struct viadev { struct snd_pcm_runtime *runtime = substream->runtime; int err; - static unsigned int rates[] = { 8000, 9600, 12000, 16000 }; - static struct snd_pcm_hw_constraint_list hw_constraints_rates = { + static const unsigned int rates[] = { 8000, 9600, 12000, 16000 }; + static const struct snd_pcm_hw_constraint_list hw_constraints_rates = { .count = ARRAY_SIZE(rates), .list = rates, .mask = 0, diff --git a/sound/pci/vx222/vx222.c b/sound/pci/vx222/vx222.c index ecbaf473fc1e..55861849d7df 100644 --- a/sound/pci/vx222/vx222.c +++ b/sound/pci/vx222/vx222.c @@ -116,7 +116,7 @@ static struct snd_vx_hardware vx222_mic_hw = { */ static int snd_vx222_free(struct vx_core *chip) { - struct snd_vx222 *vx = (struct snd_vx222 *)chip; + struct snd_vx222 *vx = to_vx222(chip); if (chip->irq >= 0) free_irq(chip->irq, (void*)chip); @@ -158,7 +158,7 @@ static int snd_vx222_create(struct snd_card *card, struct pci_dev *pci, pci_disable_device(pci); return -ENOMEM; } - vx = (struct snd_vx222 *)chip; + vx = to_vx222(chip); vx->pci = pci; if ((err = pci_request_regions(pci, CARD_NAME)) < 0) { diff --git a/sound/pci/vx222/vx222.h b/sound/pci/vx222/vx222.h index 2f0d78f609a6..cae355c8ed28 100644 --- a/sound/pci/vx222/vx222.h +++ b/sound/pci/vx222/vx222.h @@ -39,6 +39,8 @@ struct snd_vx222 { int mic_level; /* mic level for vx222 mic */ }; +#define to_vx222(x) container_of(x, struct snd_vx222, core) + /* we use a lookup table with 148 values, see vx_mixer.c */ #define VX2_AKM_LEVEL_MAX 0x93 diff --git a/sound/pci/vx222/vx222_ops.c b/sound/pci/vx222/vx222_ops.c index 7df1663ea510..d4298af6d3ee 100644 --- a/sound/pci/vx222/vx222_ops.c +++ b/sound/pci/vx222/vx222_ops.c @@ -86,7 +86,7 @@ static int vx2_reg_index[VX_REG_MAX] = { static inline unsigned long vx2_reg_addr(struct vx_core *_chip, int reg) { - struct snd_vx222 *chip = (struct snd_vx222 *)_chip; + struct snd_vx222 *chip = to_vx222(_chip); return chip->port[vx2_reg_index[reg]] + vx2_reg_offset[reg]; } @@ -159,7 +159,7 @@ static void vx2_outl(struct vx_core *chip, int offset, unsigned int val) static void vx2_reset_dsp(struct vx_core *_chip) { - struct snd_vx222 *chip = (struct snd_vx222 *)_chip; + struct snd_vx222 *chip = to_vx222(_chip); /* set the reset dsp bit to 0 */ vx_outl(chip, CDSP, chip->regCDSP & ~VX_CDSP_DSP_RESET_MASK); @@ -174,7 +174,7 @@ static void vx2_reset_dsp(struct vx_core *_chip) static int vx2_test_xilinx(struct vx_core *_chip) { - struct snd_vx222 *chip = (struct snd_vx222 *)_chip; + struct snd_vx222 *chip = to_vx222(_chip); unsigned int data; dev_dbg(_chip->card->dev, "testing xilinx...\n"); @@ -479,7 +479,7 @@ static int vx2_test_and_ack(struct vx_core *chip) */ static void vx2_validate_irq(struct vx_core *_chip, int enable) { - struct snd_vx222 *chip = (struct snd_vx222 *)_chip; + struct snd_vx222 *chip = to_vx222(_chip); /* Set the interrupt enable bit to 1 in CDSP register */ if (enable) { @@ -730,7 +730,7 @@ static void vx2_old_write_codec_bit(struct vx_core *chip, int codec, unsigned in */ static void vx2_reset_codec(struct vx_core *_chip) { - struct snd_vx222 *chip = (struct snd_vx222 *)_chip; + struct snd_vx222 *chip = to_vx222(_chip); /* Set the reset CODEC bit to 0. */ vx_outl(chip, CDSP, chip->regCDSP &~ VX_CDSP_CODEC_RESET_MASK); @@ -772,7 +772,7 @@ static void vx2_reset_codec(struct vx_core *_chip) */ static void vx2_change_audio_source(struct vx_core *_chip, int src) { - struct snd_vx222 *chip = (struct snd_vx222 *)_chip; + struct snd_vx222 *chip = to_vx222(_chip); switch (src) { case VX_AUDIO_SRC_DIGITAL: @@ -791,7 +791,7 @@ static void vx2_change_audio_source(struct vx_core *_chip, int src) */ static void vx2_set_clock_source(struct vx_core *_chip, int source) { - struct snd_vx222 *chip = (struct snd_vx222 *)_chip; + struct snd_vx222 *chip = to_vx222(_chip); if (source == INTERNAL_QUARTZ) chip->regCFG &= ~VX_CFG_CLOCKIN_SEL_MASK; @@ -805,7 +805,7 @@ static void vx2_set_clock_source(struct vx_core *_chip, int source) */ static void vx2_reset_board(struct vx_core *_chip, int cold_reset) { - struct snd_vx222 *chip = (struct snd_vx222 *)_chip; + struct snd_vx222 *chip = to_vx222(_chip); /* initialize the register values */ chip->regCDSP = VX_CDSP_CODEC_RESET_MASK | VX_CDSP_DSP_RESET_MASK ; @@ -878,7 +878,7 @@ static int vx_input_level_info(struct snd_kcontrol *kcontrol, struct snd_ctl_ele static int vx_input_level_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct vx_core *_chip = snd_kcontrol_chip(kcontrol); - struct snd_vx222 *chip = (struct snd_vx222 *)_chip; + struct snd_vx222 *chip = to_vx222(_chip); mutex_lock(&_chip->mixer_mutex); ucontrol->value.integer.value[0] = chip->input_level[0]; ucontrol->value.integer.value[1] = chip->input_level[1]; @@ -889,7 +889,7 @@ static int vx_input_level_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem static int vx_input_level_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct vx_core *_chip = snd_kcontrol_chip(kcontrol); - struct snd_vx222 *chip = (struct snd_vx222 *)_chip; + struct snd_vx222 *chip = to_vx222(_chip); if (ucontrol->value.integer.value[0] < 0 || ucontrol->value.integer.value[0] > MIC_LEVEL_MAX) return -EINVAL; @@ -922,7 +922,7 @@ static int vx_mic_level_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_ static int vx_mic_level_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct vx_core *_chip = snd_kcontrol_chip(kcontrol); - struct snd_vx222 *chip = (struct snd_vx222 *)_chip; + struct snd_vx222 *chip = to_vx222(_chip); ucontrol->value.integer.value[0] = chip->mic_level; return 0; } @@ -930,7 +930,7 @@ static int vx_mic_level_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v static int vx_mic_level_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct vx_core *_chip = snd_kcontrol_chip(kcontrol); - struct snd_vx222 *chip = (struct snd_vx222 *)_chip; + struct snd_vx222 *chip = to_vx222(_chip); if (ucontrol->value.integer.value[0] < 0 || ucontrol->value.integer.value[0] > MIC_LEVEL_MAX) return -EINVAL; @@ -973,7 +973,7 @@ static const struct snd_kcontrol_new vx_control_mic_level = { static int vx2_add_mic_controls(struct vx_core *_chip) { - struct snd_vx222 *chip = (struct snd_vx222 *)_chip; + struct snd_vx222 *chip = to_vx222(_chip); int err; if (_chip->type != VX_TYPE_MIC) diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c index fe4ba463b57c..1114166c685c 100644 --- a/sound/pci/ymfpci/ymfpci_main.c +++ b/sound/pci/ymfpci/ymfpci_main.c @@ -781,7 +781,7 @@ static snd_pcm_uframes_t snd_ymfpci_capture_pointer(struct snd_pcm_substream *su static void snd_ymfpci_irq_wait(struct snd_ymfpci *chip) { - wait_queue_t wait; + wait_queue_entry_t wait; int loops = 4; while (loops-- > 0) { diff --git a/sound/pcmcia/vx/vxp_mixer.c b/sound/pcmcia/vx/vxp_mixer.c index a4a664259f0d..304b153005a5 100644 --- a/sound/pcmcia/vx/vxp_mixer.c +++ b/sound/pcmcia/vx/vxp_mixer.c @@ -43,7 +43,7 @@ static int vx_mic_level_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_ static int vx_mic_level_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct vx_core *_chip = snd_kcontrol_chip(kcontrol); - struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip; + struct snd_vxpocket *chip = to_vxpocket(_chip); ucontrol->value.integer.value[0] = chip->mic_level; return 0; } @@ -51,7 +51,7 @@ static int vx_mic_level_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v static int vx_mic_level_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct vx_core *_chip = snd_kcontrol_chip(kcontrol); - struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip; + struct snd_vxpocket *chip = to_vxpocket(_chip); unsigned int val = ucontrol->value.integer.value[0]; if (val > MIC_LEVEL_MAX) @@ -69,7 +69,7 @@ static int vx_mic_level_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v static const DECLARE_TLV_DB_SCALE(db_scale_mic, -21, 3, 0); -static struct snd_kcontrol_new vx_control_mic_level = { +static const struct snd_kcontrol_new vx_control_mic_level = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ), @@ -88,7 +88,7 @@ static struct snd_kcontrol_new vx_control_mic_level = { static int vx_mic_boost_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct vx_core *_chip = snd_kcontrol_chip(kcontrol); - struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip; + struct snd_vxpocket *chip = to_vxpocket(_chip); ucontrol->value.integer.value[0] = chip->mic_level; return 0; } @@ -96,7 +96,7 @@ static int vx_mic_boost_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v static int vx_mic_boost_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct vx_core *_chip = snd_kcontrol_chip(kcontrol); - struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip; + struct snd_vxpocket *chip = to_vxpocket(_chip); int val = !!ucontrol->value.integer.value[0]; mutex_lock(&_chip->mixer_mutex); if (chip->mic_level != val) { @@ -109,7 +109,7 @@ static int vx_mic_boost_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v return 0; } -static struct snd_kcontrol_new vx_control_mic_boost = { +static const struct snd_kcontrol_new vx_control_mic_boost = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Mic Boost", .info = vx_mic_boost_info, @@ -120,7 +120,7 @@ static struct snd_kcontrol_new vx_control_mic_boost = { int vxp_add_mic_controls(struct vx_core *_chip) { - struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip; + struct snd_vxpocket *chip = to_vxpocket(_chip); int err; /* mute input levels */ diff --git a/sound/pcmcia/vx/vxp_ops.c b/sound/pcmcia/vx/vxp_ops.c index 5f97791f00d7..8cde40226355 100644 --- a/sound/pcmcia/vx/vxp_ops.c +++ b/sound/pcmcia/vx/vxp_ops.c @@ -50,7 +50,7 @@ static int vxp_reg_offset[VX_REG_MAX] = { static inline unsigned long vxp_reg_addr(struct vx_core *_chip, int reg) { - struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip; + struct snd_vxpocket *chip = to_vxpocket(_chip); return chip->port + vxp_reg_offset[reg]; } @@ -110,7 +110,7 @@ static int vx_check_magic(struct vx_core *chip) static void vxp_reset_dsp(struct vx_core *_chip) { - struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip; + struct snd_vxpocket *chip = to_vxpocket(_chip); /* set the reset dsp bit to 1 */ vx_outb(chip, CDSP, chip->regCDSP | VXP_CDSP_DSP_RESET_MASK); @@ -128,7 +128,7 @@ static void vxp_reset_dsp(struct vx_core *_chip) */ static void vxp_reset_codec(struct vx_core *_chip) { - struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip; + struct snd_vxpocket *chip = to_vxpocket(_chip); /* Set the reset CODEC bit to 1. */ vx_outb(chip, CDSP, chip->regCDSP | VXP_CDSP_CODEC_RESET_MASK); @@ -147,7 +147,7 @@ static void vxp_reset_codec(struct vx_core *_chip) */ static int vxp_load_xilinx_binary(struct vx_core *_chip, const struct firmware *fw) { - struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip; + struct snd_vxpocket *chip = to_vxpocket(_chip); unsigned int i; int c; int regCSUER, regRUER; @@ -280,7 +280,7 @@ static int vxp_load_dsp(struct vx_core *vx, int index, const struct firmware *fw */ static int vxp_test_and_ack(struct vx_core *_chip) { - struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip; + struct snd_vxpocket *chip = to_vxpocket(_chip); /* not booted yet? */ if (! (_chip->chip_status & VX_STAT_XILINX_LOADED)) @@ -307,7 +307,7 @@ static int vxp_test_and_ack(struct vx_core *_chip) */ static void vxp_validate_irq(struct vx_core *_chip, int enable) { - struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip; + struct snd_vxpocket *chip = to_vxpocket(_chip); /* Set the interrupt enable bit to 1 in CDSP register */ if (enable) @@ -323,7 +323,7 @@ static void vxp_validate_irq(struct vx_core *_chip, int enable) */ static void vx_setup_pseudo_dma(struct vx_core *_chip, int do_write) { - struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip; + struct snd_vxpocket *chip = to_vxpocket(_chip); /* Interrupt mode and HREQ pin enabled for host transmit / receive data transfers */ vx_outb(chip, ICR, do_write ? ICR_TREQ : ICR_RREQ); @@ -343,7 +343,7 @@ static void vx_setup_pseudo_dma(struct vx_core *_chip, int do_write) */ static void vx_release_pseudo_dma(struct vx_core *_chip) { - struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip; + struct snd_vxpocket *chip = to_vxpocket(_chip); /* Disable DMA and 16-bit accesses */ chip->regDIALOG &= ~(VXP_DLG_DMAWRITE_SEL_MASK| @@ -403,7 +403,7 @@ static void vxp_dma_write(struct vx_core *chip, struct snd_pcm_runtime *runtime, static void vxp_dma_read(struct vx_core *chip, struct snd_pcm_runtime *runtime, struct vx_pipe *pipe, int count) { - struct snd_vxpocket *pchip = (struct snd_vxpocket *)chip; + struct snd_vxpocket *pchip = to_vxpocket(chip); long port = vxp_reg_addr(chip, VX_DMA); int offset = pipe->hw_ptr; unsigned short *addr = (unsigned short *)(runtime->dma_area + offset); @@ -467,7 +467,7 @@ static void vxp_write_codec_reg(struct vx_core *chip, int codec, unsigned int da */ void vx_set_mic_boost(struct vx_core *chip, int boost) { - struct snd_vxpocket *pchip = (struct snd_vxpocket *)chip; + struct snd_vxpocket *pchip = to_vxpocket(chip); if (chip->chip_status & VX_STAT_IS_STALE) return; @@ -509,7 +509,7 @@ static int vx_compute_mic_level(int level) */ void vx_set_mic_level(struct vx_core *chip, int level) { - struct snd_vxpocket *pchip = (struct snd_vxpocket *)chip; + struct snd_vxpocket *pchip = to_vxpocket(chip); if (chip->chip_status & VX_STAT_IS_STALE) return; @@ -528,7 +528,7 @@ void vx_set_mic_level(struct vx_core *chip, int level) */ static void vxp_change_audio_source(struct vx_core *_chip, int src) { - struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip; + struct snd_vxpocket *chip = to_vxpocket(_chip); switch (src) { case VX_AUDIO_SRC_DIGITAL: @@ -568,7 +568,7 @@ static void vxp_change_audio_source(struct vx_core *_chip, int src) */ static void vxp_set_clock_source(struct vx_core *_chip, int source) { - struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip; + struct snd_vxpocket *chip = to_vxpocket(_chip); if (source == INTERNAL_QUARTZ) chip->regCDSP &= ~VXP_CDSP_CLOCKIN_SEL_MASK; @@ -583,7 +583,7 @@ static void vxp_set_clock_source(struct vx_core *_chip, int source) */ static void vxp_reset_board(struct vx_core *_chip, int cold_reset) { - struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip; + struct snd_vxpocket *chip = to_vxpocket(_chip); chip->regCDSP = 0; chip->regDIALOG = 0; diff --git a/sound/pcmcia/vx/vxpocket.c b/sound/pcmcia/vx/vxpocket.c index b16f42deed67..ca0d19e723fd 100644 --- a/sound/pcmcia/vx/vxpocket.c +++ b/sound/pcmcia/vx/vxpocket.c @@ -155,7 +155,7 @@ static int snd_vxpocket_new(struct snd_card *card, int ibl, } chip->ibl.size = ibl; - vxp = (struct snd_vxpocket *)chip; + vxp = to_vxpocket(chip); vxp->p_dev = link; link->priv = chip; @@ -187,7 +187,7 @@ static int snd_vxpocket_assign_resources(struct vx_core *chip, int port, int irq { int err; struct snd_card *card = chip->card; - struct snd_vxpocket *vxp = (struct snd_vxpocket *)chip; + struct snd_vxpocket *vxp = to_vxpocket(chip); snd_printdd(KERN_DEBUG "vxpocket assign resources: port = 0x%x, irq = %d\n", port, irq); vxp->port = port; diff --git a/sound/pcmcia/vx/vxpocket.h b/sound/pcmcia/vx/vxpocket.h index 13d658c1a216..26f4255e132e 100644 --- a/sound/pcmcia/vx/vxpocket.h +++ b/sound/pcmcia/vx/vxpocket.h @@ -43,6 +43,8 @@ struct snd_vxpocket { struct pcmcia_device *p_dev; }; +#define to_vxpocket(x) container_of(x, struct snd_vxpocket, core) + extern struct snd_vx_ops snd_vxpocket_ops; void vx_set_mic_boost(struct vx_core *chip, int boost); diff --git a/sound/ppc/awacs.c b/sound/ppc/awacs.c index 1468e4b7bf93..d1e4ef1c5c30 100644 --- a/sound/ppc/awacs.c +++ b/sound/ppc/awacs.c @@ -514,7 +514,7 @@ static struct snd_kcontrol_new snd_pmac_awacs_amp_vol[] = { }, }; -static struct snd_kcontrol_new snd_pmac_awacs_amp_hp_sw = { +static const struct snd_kcontrol_new snd_pmac_awacs_amp_hp_sw = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Headphone Playback Switch", .info = snd_pmac_boolean_stereo_info, @@ -523,7 +523,7 @@ static struct snd_kcontrol_new snd_pmac_awacs_amp_hp_sw = { .private_value = AMP_CH_HD, }; -static struct snd_kcontrol_new snd_pmac_awacs_amp_spk_sw = { +static const struct snd_kcontrol_new snd_pmac_awacs_amp_spk_sw = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Speaker Playback Switch", .info = snd_pmac_boolean_stereo_info, diff --git a/sound/ppc/beep.c b/sound/ppc/beep.c index d3524f9fa05d..f19eb3e39937 100644 --- a/sound/ppc/beep.c +++ b/sound/ppc/beep.c @@ -206,7 +206,7 @@ static int snd_pmac_put_beep(struct snd_kcontrol *kcontrol, return oval != chip->beep->volume; } -static struct snd_kcontrol_new snd_pmac_beep_mixer = { +static const struct snd_kcontrol_new snd_pmac_beep_mixer = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Beep Playback Volume", .info = snd_pmac_info_beep, diff --git a/sound/ppc/tumbler.c b/sound/ppc/tumbler.c index 58ee8089bbf9..0779a2912237 100644 --- a/sound/ppc/tumbler.c +++ b/sound/ppc/tumbler.c @@ -897,7 +897,7 @@ static struct snd_kcontrol_new snapper_mixers[] = { }, }; -static struct snd_kcontrol_new tumbler_hp_sw = { +static const struct snd_kcontrol_new tumbler_hp_sw = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Headphone Playback Switch", .info = snd_pmac_boolean_mono_info, @@ -905,7 +905,7 @@ static struct snd_kcontrol_new tumbler_hp_sw = { .put = tumbler_put_mute_switch, .private_value = TUMBLER_MUTE_HP, }; -static struct snd_kcontrol_new tumbler_speaker_sw = { +static const struct snd_kcontrol_new tumbler_speaker_sw = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Speaker Playback Switch", .info = snd_pmac_boolean_mono_info, @@ -913,7 +913,7 @@ static struct snd_kcontrol_new tumbler_speaker_sw = { .put = tumbler_put_mute_switch, .private_value = TUMBLER_MUTE_AMP, }; -static struct snd_kcontrol_new tumbler_lineout_sw = { +static const struct snd_kcontrol_new tumbler_lineout_sw = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Line Out Playback Switch", .info = snd_pmac_boolean_mono_info, @@ -921,7 +921,7 @@ static struct snd_kcontrol_new tumbler_lineout_sw = { .put = tumbler_put_mute_switch, .private_value = TUMBLER_MUTE_LINE, }; -static struct snd_kcontrol_new tumbler_drc_sw = { +static const struct snd_kcontrol_new tumbler_drc_sw = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "DRC Switch", .info = snd_pmac_boolean_mono_info, diff --git a/sound/sh/aica.c b/sound/sh/aica.c index fbbc25279559..ab4802df62e1 100644 --- a/sound/sh/aica.c +++ b/sound/sh/aica.c @@ -535,7 +535,7 @@ static int aica_pcmvolume_put(struct snd_kcontrol *kcontrol, return 1; } -static struct snd_kcontrol_new snd_aica_pcmswitch_control = { +static const struct snd_kcontrol_new snd_aica_pcmswitch_control = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "PCM Playback Switch", .index = 0, @@ -544,7 +544,7 @@ static struct snd_kcontrol_new snd_aica_pcmswitch_control = { .put = aica_pcmswitch_put }; -static struct snd_kcontrol_new snd_aica_pcmvolume_control = { +static const struct snd_kcontrol_new snd_aica_pcmvolume_control = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "PCM Playback Volume", .index = 0, diff --git a/sound/sh/sh_dac_audio.c b/sound/sh/sh_dac_audio.c index 461b310c7872..c1e00ed715ee 100644 --- a/sound/sh/sh_dac_audio.c +++ b/sound/sh/sh_dac_audio.c @@ -184,23 +184,36 @@ static int snd_sh_dac_pcm_trigger(struct snd_pcm_substream *substream, int cmd) return 0; } -static int snd_sh_dac_pcm_copy(struct snd_pcm_substream *substream, int channel, - snd_pcm_uframes_t pos, void __user *src, snd_pcm_uframes_t count) +static int snd_sh_dac_pcm_copy(struct snd_pcm_substream *substream, + int channel, unsigned long pos, + void __user *src, unsigned long count) { /* channel is not used (interleaved data) */ struct snd_sh_dac *chip = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; - ssize_t b_count = frames_to_bytes(runtime , count); - ssize_t b_pos = frames_to_bytes(runtime , pos); - if (count < 0) - return -EINVAL; + if (copy_from_user_toio(chip->data_buffer + pos, src, count)) + return -EFAULT; + chip->buffer_end = chip->data_buffer + pos + count; - if (!count) - return 0; + if (chip->empty) { + chip->empty = 0; + dac_audio_start_timer(chip); + } + + return 0; +} - memcpy_toio(chip->data_buffer + b_pos, src, b_count); - chip->buffer_end = chip->data_buffer + b_pos + b_count; +static int snd_sh_dac_pcm_copy_kernel(struct snd_pcm_substream *substream, + int channel, unsigned long pos, + void *src, unsigned long count) +{ + /* channel is not used (interleaved data) */ + struct snd_sh_dac *chip = snd_pcm_substream_chip(substream); + struct snd_pcm_runtime *runtime = substream->runtime; + + memcpy_toio(chip->data_buffer + pos, src, count); + chip->buffer_end = chip->data_buffer + pos + count; if (chip->empty) { chip->empty = 0; @@ -211,23 +224,15 @@ static int snd_sh_dac_pcm_copy(struct snd_pcm_substream *substream, int channel, } static int snd_sh_dac_pcm_silence(struct snd_pcm_substream *substream, - int channel, snd_pcm_uframes_t pos, - snd_pcm_uframes_t count) + int channel, unsigned long pos, + unsigned long count) { /* channel is not used (interleaved data) */ struct snd_sh_dac *chip = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; - ssize_t b_count = frames_to_bytes(runtime , count); - ssize_t b_pos = frames_to_bytes(runtime , pos); - - if (count < 0) - return -EINVAL; - - if (!count) - return 0; - memset_io(chip->data_buffer + b_pos, 0, b_count); - chip->buffer_end = chip->data_buffer + b_pos + b_count; + memset_io(chip->data_buffer + pos, 0, count); + chip->buffer_end = chip->data_buffer + pos + count; if (chip->empty) { chip->empty = 0; @@ -256,8 +261,9 @@ static struct snd_pcm_ops snd_sh_dac_pcm_ops = { .prepare = snd_sh_dac_pcm_prepare, .trigger = snd_sh_dac_pcm_trigger, .pointer = snd_sh_dac_pcm_pointer, - .copy = snd_sh_dac_pcm_copy, - .silence = snd_sh_dac_pcm_silence, + .copy_user = snd_sh_dac_pcm_copy, + .copy_kernel = snd_sh_dac_pcm_copy_kernel, + .fill_silence = snd_sh_dac_pcm_silence, .mmap = snd_pcm_lib_mmap_iomem, }; diff --git a/sound/soc/blackfin/bf5xx-ac97-pcm.c b/sound/soc/blackfin/bf5xx-ac97-pcm.c index 02ad2606fa19..913e29275f4e 100644 --- a/sound/soc/blackfin/bf5xx-ac97-pcm.c +++ b/sound/soc/blackfin/bf5xx-ac97-pcm.c @@ -279,23 +279,33 @@ static int bf5xx_pcm_mmap(struct snd_pcm_substream *substream, return 0 ; } #else -static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel, - snd_pcm_uframes_t pos, - void __user *buf, snd_pcm_uframes_t count) +static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, + int channel, unsigned long pos, + void *buf, unsigned long count) { struct snd_pcm_runtime *runtime = substream->runtime; unsigned int chan_mask = ac97_chan_mask[runtime->channels - 1]; + struct ac97_frame *dst; + pr_debug("%s copy pos:0x%lx count:0x%lx\n", substream->stream ? "Capture" : "Playback", pos, count); + dst = (struct ac97_frame *)runtime->dma_area + + bytes_to_frames(runtime, pos); + count = bytes_to_frames(runtime, count); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - bf5xx_pcm_to_ac97((struct ac97_frame *)runtime->dma_area + pos, - (__u16 *)buf, count, chan_mask); + bf5xx_pcm_to_ac97(dst, buf, count, chan_mask); else - bf5xx_ac97_to_pcm((struct ac97_frame *)runtime->dma_area + pos, - (__u16 *)buf, count); + bf5xx_ac97_to_pcm(dst, buf, count); return 0; } + +static int bf5xx_pcm_copy_user(struct snd_pcm_substream *substream, + int channel, unsigned long pos, + void __user *buf, unsigned long count) +{ + return bf5xx_pcm_copy(substream, channel, pos, (void *)buf, count); +} #endif static struct snd_pcm_ops bf5xx_pcm_ac97_ops = { @@ -309,7 +319,8 @@ static struct snd_pcm_ops bf5xx_pcm_ac97_ops = { #if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT) .mmap = bf5xx_pcm_mmap, #else - .copy = bf5xx_pcm_copy, + .copy_user = bf5xx_pcm_copy_user, + .copy_kernel = bf5xx_pcm_copy, #endif }; diff --git a/sound/soc/blackfin/bf5xx-i2s-pcm.c b/sound/soc/blackfin/bf5xx-i2s-pcm.c index 6cba211da32e..470d99abf6f6 100644 --- a/sound/soc/blackfin/bf5xx-i2s-pcm.c +++ b/sound/soc/blackfin/bf5xx-i2s-pcm.c @@ -225,8 +225,9 @@ static int bf5xx_pcm_mmap(struct snd_pcm_substream *substream, return 0 ; } -static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel, - snd_pcm_uframes_t pos, void *buf, snd_pcm_uframes_t count) +static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, + int channel, unsigned long pos, + void *buf, unsigned long count) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_pcm_runtime *runtime = substream->runtime; @@ -238,6 +239,8 @@ static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel, dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); if (dma_data->tdm_mode) { + pos = bytes_to_frames(runtime, pos); + count = bytes_to_frames(runtime, count); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { src = buf; dst = runtime->dma_area; @@ -269,21 +272,29 @@ static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel, if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { src = buf; dst = runtime->dma_area; - dst += frames_to_bytes(runtime, pos); + dst += pos; } else { src = runtime->dma_area; - src += frames_to_bytes(runtime, pos); + src += pos; dst = buf; } - memcpy(dst, src, frames_to_bytes(runtime, count)); + memcpy(dst, src, count); } return 0; } +static int bf5xx_pcm_copy_user(struct snd_pcm_substream *substream, + int channel, unsigned long pos, + void __user *buf, unsigned long count) +{ + return bf5xx_pcm_copy(substream, channel, pos, (void *)buf, count); +} + static int bf5xx_pcm_silence(struct snd_pcm_substream *substream, - int channel, snd_pcm_uframes_t pos, snd_pcm_uframes_t count) + int channel, unsigned long pos, + unsigned long count) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_pcm_runtime *runtime = substream->runtime; @@ -295,11 +306,11 @@ static int bf5xx_pcm_silence(struct snd_pcm_substream *substream, dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); if (dma_data->tdm_mode) { - offset = pos * 8 * sample_size; - samples = count * 8; + offset = bytes_to_frames(runtime, pos) * 8 * sample_size; + samples = bytes_to_frames(runtime, count) * 8; } else { - offset = frames_to_bytes(runtime, pos); - samples = count * runtime->channels; + offset = pos; + samples = bytes_to_samples(runtime, count); } snd_pcm_format_set_silence(runtime->format, buf + offset, samples); @@ -316,8 +327,9 @@ static struct snd_pcm_ops bf5xx_pcm_i2s_ops = { .trigger = bf5xx_pcm_trigger, .pointer = bf5xx_pcm_pointer, .mmap = bf5xx_pcm_mmap, - .copy = bf5xx_pcm_copy, - .silence = bf5xx_pcm_silence, + .copy_user = bf5xx_pcm_copy_user, + .copy_kernel = bf5xx_pcm_copy, + .fill_silence = bf5xx_pcm_silence, }; static int bf5xx_pcm_i2s_new(struct snd_soc_pcm_runtime *rtd) diff --git a/sound/soc/codecs/msm8916-wcd-analog.c b/sound/soc/codecs/msm8916-wcd-analog.c index a78802920c3c..5710fd440bcd 100644 --- a/sound/soc/codecs/msm8916-wcd-analog.c +++ b/sound/soc/codecs/msm8916-wcd-analog.c @@ -36,7 +36,7 @@ #define CDC_D_CDC_DIG_CLK_CTL (0xf04A) #define DIG_CLK_CTL_RXD1_CLK_EN BIT(0) #define DIG_CLK_CTL_RXD2_CLK_EN BIT(1) -#define DIG_CLK_CTL_RXD3_CLK_EN BIT(3) +#define DIG_CLK_CTL_RXD3_CLK_EN BIT(2) #define DIG_CLK_CTL_TXD_CLK_EN BIT(4) #define DIG_CLK_CTL_NCP_CLK_EN_MASK BIT(6) #define DIG_CLK_CTL_NCP_CLK_EN BIT(6) diff --git a/sound/soc/fsl/imx-ssi.c b/sound/soc/fsl/imx-ssi.c index b95132e2f9dc..06790615e04e 100644 --- a/sound/soc/fsl/imx-ssi.c +++ b/sound/soc/fsl/imx-ssi.c @@ -527,6 +527,10 @@ static int imx_ssi_probe(struct platform_device *pdev) } ssi->irq = platform_get_irq(pdev, 0); + if (ssi->irq < 0) { + dev_err(&pdev->dev, "Failed to get IRQ: %d\n", ssi->irq); + return ssi->irq; + } ssi->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(ssi->clk)) { diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c index 105ec3a6e30d..de2550c7a96b 100644 --- a/sound/soc/generic/audio-graph-card.c +++ b/sound/soc/generic/audio-graph-card.c @@ -224,9 +224,11 @@ static int asoc_graph_card_parse_of(struct graph_card_data *priv) of_for_each_phandle(&it, rc, node, "dais", NULL, 0) { ret = asoc_graph_card_dai_link_of(it.node, priv, idx++); - of_node_put(it.node); - if (ret < 0) + if (ret < 0) { + of_node_put(it.node); + return ret; + } } return asoc_simple_card_parse_card_name(card, NULL); @@ -239,10 +241,8 @@ static int asoc_graph_get_dais_count(struct device *dev) int count = 0; int rc; - of_for_each_phandle(&it, rc, node, "dais", NULL, 0) { + of_for_each_phandle(&it, rc, node, "dais", NULL, 0) count++; - of_node_put(it.node); - } return count; } diff --git a/sound/soc/generic/audio-graph-scu-card.c b/sound/soc/generic/audio-graph-scu-card.c index dcd2df37bc3b..758ac06f3a99 100644 --- a/sound/soc/generic/audio-graph-scu-card.c +++ b/sound/soc/generic/audio-graph-scu-card.c @@ -215,7 +215,6 @@ static int asoc_graph_card_parse_of(struct graph_card_data *priv) codec_ep = of_graph_get_remote_endpoint(cpu_ep); rcpu_ep = of_graph_get_remote_endpoint(codec_ep); - of_node_put(cpu_port); of_node_put(cpu_ep); of_node_put(codec_ep); of_node_put(rcpu_ep); @@ -232,8 +231,10 @@ static int asoc_graph_card_parse_of(struct graph_card_data *priv) ret = asoc_simple_card_parse_daifmt(dev, cpu_ep, codec_ep, NULL, &daifmt); - if (ret < 0) + if (ret < 0) { + of_node_put(cpu_port); goto parse_of_err; + } } dai_idx = 0; @@ -250,7 +251,6 @@ static int asoc_graph_card_parse_of(struct graph_card_data *priv) codec_ep = of_graph_get_remote_endpoint(cpu_ep); codec_port = of_graph_get_port_parent(codec_ep); - of_node_put(cpu_port); of_node_put(cpu_ep); of_node_put(codec_ep); of_node_put(codec_port); @@ -266,13 +266,17 @@ static int asoc_graph_card_parse_of(struct graph_card_data *priv) /* Back-End (= Codec) */ ret = asoc_graph_card_dai_link_of(codec_ep, priv, daifmt, dai_idx++, 0); - if (ret < 0) + if (ret < 0) { + of_node_put(cpu_port); goto parse_of_err; + } } else { /* Front-End (= CPU) */ ret = asoc_graph_card_dai_link_of(cpu_ep, priv, daifmt, dai_idx++, 1); - if (ret < 0) + if (ret < 0) { + of_node_put(cpu_port); goto parse_of_err; + } } } } @@ -306,7 +310,6 @@ static int asoc_graph_get_dais_count(struct device *dev) codec_ep = of_graph_get_remote_endpoint(cpu_ep); codec_port = of_graph_get_port_parent(codec_ep); - of_node_put(cpu_port); of_node_put(cpu_ep); of_node_put(codec_ep); of_node_put(codec_port); diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index 26d64fa40c9c..7d7ab4aee42e 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -263,6 +263,9 @@ static int asoc_simple_card_get_dai_id(struct device_node *ep) id = i; i++; } + + of_node_put(node); + if (id < 0) return -ENODEV; @@ -282,11 +285,6 @@ int asoc_simple_card_parse_graph_dai(struct device_node *ep, if (!dai_name) return 0; - /* - * of_graph_get_port_parent() will call - * of_node_put(). So, call of_node_get() here - */ - of_node_get(ep); node = of_graph_get_port_parent(ep); /* Get dai->name */ diff --git a/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c b/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c index 3fe4a0807095..cfd89ca6a18d 100644 --- a/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c +++ b/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c @@ -319,7 +319,9 @@ static int kabylake_rt5663_hw_params(struct snd_pcm_substream *substream, int ret; /* use ASRC for internal clocks, as PLL rate isn't multiple of BCLK */ - rt5663_sel_asrc_clk_src(codec_dai->codec, RT5663_DA_STEREO_FILTER, 1); + rt5663_sel_asrc_clk_src(codec_dai->codec, + RT5663_DA_STEREO_FILTER | RT5663_AD_STEREO_FILTER, + RT5663_CLK_SEL_I2S1_ASRC); ret = snd_soc_dai_set_sysclk(codec_dai, RT5663_SCLK_S_MCLK, 24576000, SND_SOC_CLOCK_IN); @@ -349,19 +351,10 @@ static int kabylake_ssp0_hw_params(struct snd_pcm_substream *substream, return ret; } - ret = snd_soc_dai_set_pll(codec_dai, 0, - RT5514_PLL1_S_BCLK, RT5514_AIF1_BCLK_FREQ, - RT5514_AIF1_SYSCLK_FREQ); - if (ret < 0) { - dev_err(rtd->dev, "set bclk err: %d\n", ret); - return ret; - } - ret = snd_soc_dai_set_sysclk(codec_dai, - RT5514_SCLK_S_PLL1, RT5514_AIF1_SYSCLK_FREQ, - SND_SOC_CLOCK_IN); + RT5514_SCLK_S_MCLK, 24576000, SND_SOC_CLOCK_IN); if (ret < 0) { - dev_err(rtd->dev, "set sclk err: %d\n", ret); + dev_err(rtd->dev, "set sysclk err: %d\n", ret); return ret; } } diff --git a/sound/soc/intel/skylake/skl-messages.c b/sound/soc/intel/skylake/skl-messages.c index eca85827dbd2..fb2f1f603f3c 100644 --- a/sound/soc/intel/skylake/skl-messages.c +++ b/sound/soc/intel/skylake/skl-messages.c @@ -540,6 +540,14 @@ static void skl_setup_cpr_gateway_cfg(struct skl_sst *ctx, cpr_mconfig->gtw_cfg.dma_buffer_size = mconfig->dma_buffer_size * dma_io_buf; + /* fallback to 2ms default value */ + if (!cpr_mconfig->gtw_cfg.dma_buffer_size) { + if (mconfig->hw_conn_type == SKL_CONN_SOURCE) + cpr_mconfig->gtw_cfg.dma_buffer_size = 2 * mconfig->obs; + else + cpr_mconfig->gtw_cfg.dma_buffer_size = 2 * mconfig->ibs; + } + cpr_mconfig->cpr_feature_mask = 0; cpr_mconfig->gtw_cfg.config_length = 0; diff --git a/sound/soc/intel/skylake/skl-nhlt.c b/sound/soc/intel/skylake/skl-nhlt.c index e3f06672fd6d..e7d766d56c8e 100644 --- a/sound/soc/intel/skylake/skl-nhlt.c +++ b/sound/soc/intel/skylake/skl-nhlt.c @@ -21,8 +21,9 @@ #include "skl.h" /* Unique identification for getting NHLT blobs */ -static u8 OSC_UUID[16] = {0x6E, 0x88, 0x9F, 0xA6, 0xEB, 0x6C, 0x94, 0x45, - 0xA4, 0x1F, 0x7B, 0x5D, 0xCE, 0x24, 0xC5, 0x53}; +static guid_t osc_guid = + GUID_INIT(0xA69F886E, 0x6CEB, 0x4594, + 0xA4, 0x1F, 0x7B, 0x5D, 0xCE, 0x24, 0xC5, 0x53); struct nhlt_acpi_table *skl_nhlt_init(struct device *dev) { @@ -37,7 +38,7 @@ struct nhlt_acpi_table *skl_nhlt_init(struct device *dev) return NULL; } - obj = acpi_evaluate_dsm(handle, OSC_UUID, 1, 1, NULL); + obj = acpi_evaluate_dsm(handle, &osc_guid, 1, 1, NULL); if (obj && obj->type == ACPI_TYPE_BUFFER) { nhlt_ptr = (struct nhlt_resource_desc *)obj->buffer.pointer; nhlt_table = (struct nhlt_acpi_table *) diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c index 334917ee41cf..9e3f8c04dd32 100644 --- a/sound/soc/intel/skylake/skl.c +++ b/sound/soc/intel/skylake/skl.c @@ -941,6 +941,7 @@ static struct sst_acpi_mach sst_bxtp_devdata[] = { .machine_quirk = sst_acpi_codec_list, .quirk_data = &bxt_codecs, }, + {} }; static struct sst_acpi_mach sst_kbl_devdata[] = { @@ -991,6 +992,7 @@ static struct sst_acpi_mach sst_glk_devdata[] = { .drv_name = "glk_alc298s_i2s", .fw_filename = "intel/dsp_fw_glk.bin", }, + {} }; /* PCI IDs */ diff --git a/sound/soc/sh/siu_dai.c b/sound/soc/sh/siu_dai.c index 76b2ab8c2b4a..4a22aadac294 100644 --- a/sound/soc/sh/siu_dai.c +++ b/sound/soc/sh/siu_dai.c @@ -441,7 +441,7 @@ static int siu_dai_put_volume(struct snd_kcontrol *kctrl, return 0; } -static struct snd_kcontrol_new playback_controls = { +static const struct snd_kcontrol_new playback_controls = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "PCM Playback Volume", .index = 0, @@ -451,7 +451,7 @@ static struct snd_kcontrol_new playback_controls = { .private_value = VOLUME_PLAYBACK, }; -static struct snd_kcontrol_new capture_controls = { +static const struct snd_kcontrol_new capture_controls = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "PCM Capture Volume", .index = 0, diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 921622a01944..13c875e2392a 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -3171,8 +3171,6 @@ static int snd_soc_component_initialize(struct snd_soc_component *component, component->remove = component->driver->remove; component->suspend = component->driver->suspend; component->resume = component->driver->resume; - component->pcm_new = component->driver->pcm_new; - component->pcm_free = component->driver->pcm_free; dapm = &component->dapm; dapm->dev = dev; @@ -3360,25 +3358,6 @@ static void snd_soc_platform_drv_remove(struct snd_soc_component *component) platform->driver->remove(platform); } -static int snd_soc_platform_drv_pcm_new(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_platform *platform = rtd->platform; - - if (platform->driver->pcm_new) - return platform->driver->pcm_new(rtd); - else - return 0; -} - -static void snd_soc_platform_drv_pcm_free(struct snd_pcm *pcm) -{ - struct snd_soc_pcm_runtime *rtd = pcm->private_data; - struct snd_soc_platform *platform = rtd->platform; - - if (platform->driver->pcm_free) - platform->driver->pcm_free(pcm); -} - /** * snd_soc_add_platform - Add a platform to the ASoC core * @dev: The parent device for the platform @@ -3402,10 +3381,6 @@ int snd_soc_add_platform(struct device *dev, struct snd_soc_platform *platform, platform->component.probe = snd_soc_platform_drv_probe; if (platform_drv->remove) platform->component.remove = snd_soc_platform_drv_remove; - if (platform_drv->pcm_new) - platform->component.pcm_new = snd_soc_platform_drv_pcm_new; - if (platform_drv->pcm_free) - platform->component.pcm_free = snd_soc_platform_drv_pcm_free; #ifdef CONFIG_DEBUG_FS platform->component.debugfs_prefix = "platform"; @@ -4113,6 +4088,8 @@ int snd_soc_get_dai_id(struct device_node *ep) } mutex_unlock(&client_mutex); + of_node_put(node); + return ret; } EXPORT_SYMBOL_GPL(snd_soc_get_dai_id); diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index efc5831f205d..7d3859e1a7b9 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -181,6 +181,10 @@ int dpcm_dapm_stream_event(struct snd_soc_pcm_runtime *fe, int dir, dev_dbg(be->dev, "ASoC: BE %s event %d dir %d\n", be->dai_link->name, event, dir); + if ((event == SND_SOC_DAPM_STREAM_STOP) && + (be->dpcm[dir].users >= 1)) + continue; + snd_soc_dapm_stream_event(be, dir, event); } @@ -2628,25 +2632,12 @@ static int dpcm_fe_dai_close(struct snd_pcm_substream *fe_substream) return ret; } -static void soc_pcm_free(struct snd_pcm *pcm) -{ - struct snd_soc_pcm_runtime *rtd = pcm->private_data; - struct snd_soc_component *component; - - list_for_each_entry(component, &rtd->card->component_dev_list, - card_list) { - if (component->pcm_free) - component->pcm_free(pcm); - } -} - /* create a new pcm */ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) { struct snd_soc_platform *platform = rtd->platform; struct snd_soc_dai *codec_dai; struct snd_soc_dai *cpu_dai = rtd->cpu_dai; - struct snd_soc_component *component; struct snd_pcm *pcm; char new_name[64]; int ret = 0, playback = 0, capture = 0; @@ -2743,8 +2734,9 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) if (platform->driver->ops) { rtd->ops.ack = platform->driver->ops->ack; - rtd->ops.copy = platform->driver->ops->copy; - rtd->ops.silence = platform->driver->ops->silence; + rtd->ops.copy_user = platform->driver->ops->copy_user; + rtd->ops.copy_kernel = platform->driver->ops->copy_kernel; + rtd->ops.fill_silence = platform->driver->ops->fill_silence; rtd->ops.page = platform->driver->ops->page; rtd->ops.mmap = platform->driver->ops->mmap; } @@ -2755,18 +2747,17 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) if (capture) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &rtd->ops); - list_for_each_entry(component, &rtd->card->component_dev_list, card_list) { - if (component->pcm_new) { - ret = component->pcm_new(rtd); - if (ret < 0) { - dev_err(component->dev, - "ASoC: pcm constructor failed: %d\n", - ret); - return ret; - } + if (platform->driver->pcm_new) { + ret = platform->driver->pcm_new(rtd); + if (ret < 0) { + dev_err(platform->dev, + "ASoC: pcm constructor failed: %d\n", + ret); + return ret; } } - pcm->private_free = soc_pcm_free; + + pcm->private_free = platform->driver->pcm_free; out: dev_info(rtd->card->dev, "%s <-> %s mapping ok\n", (rtd->num_codecs > 1) ? "multicodec" : rtd->codec_dai->name, diff --git a/sound/soc/ux500/mop500.c b/sound/soc/ux500/mop500.c index b50f68a439ce..ba9fc099cf67 100644 --- a/sound/soc/ux500/mop500.c +++ b/sound/soc/ux500/mop500.c @@ -33,6 +33,7 @@ static struct snd_soc_dai_link mop500_dai_links[] = { .stream_name = "ab8500_0", .cpu_dai_name = "ux500-msp-i2s.1", .codec_dai_name = "ab8500-codec-dai.0", + .platform_name = "ux500-msp-i2s.1", .codec_name = "ab8500-codec.0", .init = mop500_ab8500_machine_init, .ops = mop500_ab8500_ops, @@ -42,6 +43,7 @@ static struct snd_soc_dai_link mop500_dai_links[] = { .stream_name = "ab8500_1", .cpu_dai_name = "ux500-msp-i2s.3", .codec_dai_name = "ab8500-codec-dai.1", + .platform_name = "ux500-msp-i2s.3", .codec_name = "ab8500-codec.0", .init = NULL, .ops = mop500_ab8500_ops, @@ -85,6 +87,8 @@ static int mop500_of_probe(struct platform_device *pdev, for (i = 0; i < 2; i++) { mop500_dai_links[i].cpu_of_node = msp_np[i]; mop500_dai_links[i].cpu_dai_name = NULL; + mop500_dai_links[i].platform_of_node = msp_np[i]; + mop500_dai_links[i].platform_name = NULL; mop500_dai_links[i].codec_of_node = codec_np; mop500_dai_links[i].codec_name = NULL; } diff --git a/sound/sparc/cs4231.c b/sound/sparc/cs4231.c index 30bdc971883b..3d7d425fbd24 100644 --- a/sound/sparc/cs4231.c +++ b/sound/sparc/cs4231.c @@ -200,12 +200,12 @@ static unsigned char freq_bits[14] = { /* 48000 */ 0x0C | CS4231_XTAL1 }; -static unsigned int rates[14] = { +static const unsigned int rates[14] = { 5510, 6620, 8000, 9600, 11025, 16000, 18900, 22050, 27042, 32000, 33075, 37800, 44100, 48000 }; -static struct snd_pcm_hw_constraint_list hw_constraints_rates = { +static const struct snd_pcm_hw_constraint_list hw_constraints_rates = { .count = ARRAY_SIZE(rates), .list = rates, }; diff --git a/sound/synth/Kconfig b/sound/synth/Kconfig new file mode 100644 index 000000000000..dfe8950e0556 --- /dev/null +++ b/sound/synth/Kconfig @@ -0,0 +1,2 @@ +config SND_SYNTH_EMUX + tristate diff --git a/sound/synth/emux/Makefile b/sound/synth/emux/Makefile index fb761c2c2b50..d1bac923eb1b 100644 --- a/sound/synth/emux/Makefile +++ b/sound/synth/emux/Makefile @@ -6,8 +6,8 @@ snd-emux-synth-objs := emux.o emux_synth.o emux_seq.o emux_nrpn.o \ emux_effect.o emux_hwdep.o soundfont.o snd-emux-synth-$(CONFIG_SND_PROC_FS) += emux_proc.o -snd-emux-synth-$(CONFIG_SND_SEQUENCER_OSS) += emux_oss.o +ifneq ($(CONFIG_SND_SEQUENCER_OSS),) +snd-emux-synth-y += emux_oss.o +endif -# Toplevel Module Dependencies -obj-$(CONFIG_SND_SBAWE_SEQ) += snd-emux-synth.o -obj-$(CONFIG_SND_EMU10K1_SEQ) += snd-emux-synth.o +obj-$(CONFIG_SND_SYNTH_EMUX) += snd-emux-synth.o diff --git a/sound/synth/emux/emux.c b/sound/synth/emux/emux.c index 9312cd8a6fdd..b9981e8c0027 100644 --- a/sound/synth/emux/emux.c +++ b/sound/synth/emux/emux.c @@ -47,7 +47,7 @@ int snd_emux_new(struct snd_emux **remu) mutex_init(&emu->register_mutex); emu->client = -1; -#ifdef CONFIG_SND_SEQUENCER_OSS +#if IS_ENABLED(CONFIG_SND_SEQUENCER_OSS) emu->oss_synth = NULL; #endif emu->max_voices = 0; @@ -123,7 +123,7 @@ int snd_emux_register(struct snd_emux *emu, struct snd_card *card, int index, ch snd_emux_init_voices(emu); snd_emux_init_seq(emu, card, index); -#ifdef CONFIG_SND_SEQUENCER_OSS +#if IS_ENABLED(CONFIG_SND_SEQUENCER_OSS) snd_emux_init_seq_oss(emu); #endif snd_emux_init_virmidi(emu, card); @@ -150,7 +150,7 @@ int snd_emux_free(struct snd_emux *emu) snd_emux_proc_free(emu); snd_emux_delete_virmidi(emu); -#ifdef CONFIG_SND_SEQUENCER_OSS +#if IS_ENABLED(CONFIG_SND_SEQUENCER_OSS) snd_emux_detach_seq_oss(emu); #endif snd_emux_detach_seq(emu); diff --git a/sound/synth/emux/emux_effect.c b/sound/synth/emux/emux_effect.c index a447218b6160..9ac0bf531b4b 100644 --- a/sound/synth/emux/emux_effect.c +++ b/sound/synth/emux/emux_effect.c @@ -150,7 +150,7 @@ effect_get_offset(struct snd_midi_channel *chan, int lo, int hi, int mode) return addr; } -#ifdef CONFIG_SND_SEQUENCER_OSS +#if IS_ENABLED(CONFIG_SND_SEQUENCER_OSS) /* change effects - for OSS sequencer compatibility */ void snd_emux_send_effect_oss(struct snd_emux_port *port, diff --git a/sound/synth/emux/emux_oss.c b/sound/synth/emux/emux_oss.c index 850fab4a8f3b..de19e108974a 100644 --- a/sound/synth/emux/emux_oss.c +++ b/sound/synth/emux/emux_oss.c @@ -23,8 +23,6 @@ */ -#ifdef CONFIG_SND_SEQUENCER_OSS - #include <linux/export.h> #include <linux/uaccess.h> #include <sound/core.h> @@ -505,5 +503,3 @@ fake_event(struct snd_emux *emu, struct snd_emux_port *port, int ch, int param, ev.data.control.value = val; snd_emux_event_input(&ev, 0, port, atomic, hop); } - -#endif /* CONFIG_SND_SEQUENCER_OSS */ diff --git a/sound/usb/Kconfig b/sound/usb/Kconfig index a452ad7cec40..f61b5662bb89 100644 --- a/sound/usb/Kconfig +++ b/sound/usb/Kconfig @@ -91,7 +91,7 @@ config SND_USB_CAIAQ_INPUT config SND_USB_US122L tristate "Tascam US-122L USB driver" - depends on X86 + depends on X86 || COMPILE_TEST select SND_HWDEP select SND_RAWMIDI help diff --git a/sound/usb/line6/driver.h b/sound/usb/line6/driver.h index a5c2e9ae5f17..dc97895547be 100644 --- a/sound/usb/line6/driver.h +++ b/sound/usb/line6/driver.h @@ -117,6 +117,8 @@ enum { LINE6_CAP_IN_NEEDS_OUT = 1 << 3, /* device uses raw MIDI via USB (data endpoints) */ LINE6_CAP_CONTROL_MIDI = 1 << 4, + /* device provides low-level information */ + LINE6_CAP_CONTROL_INFO = 1 << 5, }; /* diff --git a/sound/usb/line6/podhd.c b/sound/usb/line6/podhd.c index 6ab23e5aee71..956f847a96e4 100644 --- a/sound/usb/line6/podhd.c +++ b/sound/usb/line6/podhd.c @@ -3,6 +3,7 @@ * * Copyright (C) 2011 Stefan Hajnoczi <stefanha@gmail.com> * Copyright (C) 2015 Andrej Krutak <dev@andree.sk> + * Copyright (C) 2017 Hans P. Moller <hmoller@uc.cl> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -37,7 +38,8 @@ enum { LINE6_PODHD500_0, LINE6_PODHD500_1, LINE6_PODX3, - LINE6_PODX3LIVE + LINE6_PODX3LIVE, + LINE6_PODHD500X }; struct usb_line6_podhd { @@ -291,7 +293,7 @@ static void podhd_disconnect(struct usb_line6 *line6) { struct usb_line6_podhd *pod = (struct usb_line6_podhd *)line6; - if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL) { + if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL_INFO) { struct usb_interface *intf; del_timer_sync(&pod->startup_timer); @@ -331,7 +333,9 @@ static int podhd_init(struct usb_line6 *line6, pod->line6.properties->ctrl_if, err); return err; } + } + if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL_INFO) { /* create sysfs entries: */ err = snd_card_add_dev_attr(line6->card, &podhd_dev_attr_group); if (err < 0) @@ -348,7 +352,7 @@ static int podhd_init(struct usb_line6 *line6, return err; } - if (!(pod->line6.properties->capabilities & LINE6_CAP_CONTROL)) { + if (!(pod->line6.properties->capabilities & LINE6_CAP_CONTROL_INFO)) { /* register USB audio system directly */ return podhd_startup_finalize(pod); } @@ -372,6 +376,7 @@ static const struct usb_device_id podhd_id_table[] = { { LINE6_IF_NUM(0x414D, 1), .driver_info = LINE6_PODHD500_1 }, { LINE6_IF_NUM(0x414A, 0), .driver_info = LINE6_PODX3 }, { LINE6_IF_NUM(0x414B, 0), .driver_info = LINE6_PODX3LIVE }, + { LINE6_IF_NUM(0x4159, 0), .driver_info = LINE6_PODHD500X }, {} }; @@ -425,7 +430,7 @@ static const struct line6_properties podhd_properties_table[] = { [LINE6_PODX3] = { .id = "PODX3", .name = "POD X3", - .capabilities = LINE6_CAP_CONTROL + .capabilities = LINE6_CAP_CONTROL | LINE6_CAP_CONTROL_INFO | LINE6_CAP_PCM | LINE6_CAP_HWMON | LINE6_CAP_IN_NEEDS_OUT, .altsetting = 1, .ep_ctrl_r = 0x81, @@ -437,7 +442,7 @@ static const struct line6_properties podhd_properties_table[] = { [LINE6_PODX3LIVE] = { .id = "PODX3LIVE", .name = "POD X3 LIVE", - .capabilities = LINE6_CAP_CONTROL + .capabilities = LINE6_CAP_CONTROL | LINE6_CAP_CONTROL_INFO | LINE6_CAP_PCM | LINE6_CAP_HWMON | LINE6_CAP_IN_NEEDS_OUT, .altsetting = 1, .ep_ctrl_r = 0x81, @@ -446,6 +451,18 @@ static const struct line6_properties podhd_properties_table[] = { .ep_audio_r = 0x86, .ep_audio_w = 0x02, }, + [LINE6_PODHD500X] = { + .id = "PODHD500X", + .name = "POD HD500X", + .capabilities = LINE6_CAP_CONTROL + | LINE6_CAP_PCM | LINE6_CAP_HWMON, + .altsetting = 1, + .ep_ctrl_r = 0x81, + .ep_ctrl_w = 0x01, + .ctrl_if = 1, + .ep_audio_r = 0x86, + .ep_audio_w = 0x02, + }, }; /* diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index 4fa0053a40af..e3d1dec48ee4 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -362,7 +362,7 @@ static int snd_audigy2nx_led_resume(struct usb_mixer_elem_list *list) } /* name and private_value are set dynamically */ -static struct snd_kcontrol_new snd_audigy2nx_control = { +static const struct snd_kcontrol_new snd_audigy2nx_control = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .info = snd_audigy2nx_led_info, .get = snd_audigy2nx_led_get, diff --git a/sound/usb/usx2y/us122l.c b/sound/usb/usx2y/us122l.c index e118bdca983d..a33e31b2fc2f 100644 --- a/sound/usb/usx2y/us122l.c +++ b/sound/usb/usx2y/us122l.c @@ -46,8 +46,10 @@ MODULE_PARM_DESC(id, "ID string for "NAME_ALLCAPS"."); module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "Enable "NAME_ALLCAPS"."); -static int snd_us122l_card_used[SNDRV_CARDS]; +/* driver_info flags */ +#define US122L_FLAG_US144 BIT(0) +static int snd_us122l_card_used[SNDRV_CARDS]; static int us122l_create_usbmidi(struct snd_card *card) { @@ -198,8 +200,7 @@ static int usb_stream_hwdep_open(struct snd_hwdep *hw, struct file *file) if (!us122l->first) us122l->first = file; - if (us122l->dev->descriptor.idProduct == USB_ID_US144 || - us122l->dev->descriptor.idProduct == USB_ID_US144MKII) { + if (us122l->is_us144) { iface = usb_ifnum_to_if(us122l->dev, 0); usb_autopm_get_interface(iface); } @@ -214,8 +215,7 @@ static int usb_stream_hwdep_release(struct snd_hwdep *hw, struct file *file) struct usb_interface *iface; snd_printdd(KERN_DEBUG "%p %p\n", hw, file); - if (us122l->dev->descriptor.idProduct == USB_ID_US144 || - us122l->dev->descriptor.idProduct == USB_ID_US144MKII) { + if (us122l->is_us144) { iface = usb_ifnum_to_if(us122l->dev, 0); usb_autopm_put_interface(iface); } @@ -483,8 +483,7 @@ static bool us122l_create_card(struct snd_card *card) int err; struct us122l *us122l = US122L(card); - if (us122l->dev->descriptor.idProduct == USB_ID_US144 || - us122l->dev->descriptor.idProduct == USB_ID_US144MKII) { + if (us122l->is_us144) { err = usb_set_interface(us122l->dev, 0, 1); if (err) { snd_printk(KERN_ERR "usb_set_interface error \n"); @@ -503,8 +502,7 @@ static bool us122l_create_card(struct snd_card *card) if (!us122l_start(us122l, 44100, 256)) return false; - if (us122l->dev->descriptor.idProduct == USB_ID_US144 || - us122l->dev->descriptor.idProduct == USB_ID_US144MKII) + if (us122l->is_us144) err = us144_create_usbmidi(card); else err = us122l_create_usbmidi(card); @@ -536,7 +534,8 @@ static void snd_us122l_free(struct snd_card *card) static int usx2y_create_card(struct usb_device *device, struct usb_interface *intf, - struct snd_card **cardp) + struct snd_card **cardp, + unsigned long flags) { int dev; struct snd_card *card; @@ -556,6 +555,7 @@ static int usx2y_create_card(struct usb_device *device, US122L(card)->dev = device; mutex_init(&US122L(card)->mutex); init_waitqueue_head(&US122L(card)->sk.sleep); + US122L(card)->is_us144 = flags & US122L_FLAG_US144; INIT_LIST_HEAD(&US122L(card)->midi_list); strcpy(card->driver, "USB "NAME_ALLCAPS""); sprintf(card->shortname, "TASCAM "NAME_ALLCAPS""); @@ -579,7 +579,7 @@ static int us122l_usb_probe(struct usb_interface *intf, struct snd_card *card; int err; - err = usx2y_create_card(device, intf, &card); + err = usx2y_create_card(device, intf, &card, device_id->driver_info); if (err < 0) return err; @@ -607,9 +607,8 @@ static int snd_us122l_probe(struct usb_interface *intf, struct snd_card *card; int err; - if ((device->descriptor.idProduct == USB_ID_US144 || - device->descriptor.idProduct == USB_ID_US144MKII) - && device->speed == USB_SPEED_HIGH) { + if (id->driver_info & US122L_FLAG_US144 && + device->speed == USB_SPEED_HIGH) { snd_printk(KERN_ERR "disable ehci-hcd to run US-144 \n"); return -ENODEV; } @@ -703,8 +702,7 @@ static int snd_us122l_resume(struct usb_interface *intf) mutex_lock(&us122l->mutex); /* needed, doesn't restart without: */ - if (us122l->dev->descriptor.idProduct == USB_ID_US144 || - us122l->dev->descriptor.idProduct == USB_ID_US144MKII) { + if (us122l->is_us144) { err = usb_set_interface(us122l->dev, 0, 1); if (err) { snd_printk(KERN_ERR "usb_set_interface error \n"); @@ -747,7 +745,8 @@ static struct usb_device_id snd_us122l_usb_id_table[] = { { /* US-144 only works at USB1.1! Disable module ehci-hcd. */ .match_flags = USB_DEVICE_ID_MATCH_DEVICE, .idVendor = 0x0644, - .idProduct = USB_ID_US144 + .idProduct = USB_ID_US144, + .driver_info = US122L_FLAG_US144 }, { .match_flags = USB_DEVICE_ID_MATCH_DEVICE, @@ -757,7 +756,8 @@ static struct usb_device_id snd_us122l_usb_id_table[] = { { .match_flags = USB_DEVICE_ID_MATCH_DEVICE, .idVendor = 0x0644, - .idProduct = USB_ID_US144MKII + .idProduct = USB_ID_US144MKII, + .driver_info = US122L_FLAG_US144 }, { /* terminator */ } }; diff --git a/sound/usb/usx2y/us122l.h b/sound/usb/usx2y/us122l.h index f263b3f96c86..3e2a2d0041ee 100644 --- a/sound/usb/usx2y/us122l.h +++ b/sound/usb/usx2y/us122l.h @@ -16,6 +16,8 @@ struct us122l { struct list_head midi_list; atomic_t mmap_count; + + bool is_us144; }; diff --git a/sound/x86/intel_hdmi_audio.c b/sound/x86/intel_hdmi_audio.c index b11d3920b9a5..a0951505c7f5 100644 --- a/sound/x86/intel_hdmi_audio.c +++ b/sound/x86/intel_hdmi_audio.c @@ -42,6 +42,11 @@ #include <drm/intel_lpe_audio.h> #include "intel_hdmi_audio.h" +#define for_each_pipe(card_ctx, pipe) \ + for ((pipe) = 0; (pipe) < (card_ctx)->num_pipes; (pipe)++) +#define for_each_port(card_ctx, port) \ + for ((port) = 0; (port) < (card_ctx)->num_ports; (port)++) + /*standard module options for ALSA. This module supports only one card*/ static int hdmi_card_index = SNDRV_DEFAULT_IDX1; static char *hdmi_card_id = SNDRV_DEFAULT_STR1; @@ -189,15 +194,30 @@ static void had_substream_put(struct snd_intelhad *intelhaddata) spin_unlock_irqrestore(&intelhaddata->had_spinlock, flags); } +static u32 had_config_offset(int pipe) +{ + switch (pipe) { + default: + case 0: + return AUDIO_HDMI_CONFIG_A; + case 1: + return AUDIO_HDMI_CONFIG_B; + case 2: + return AUDIO_HDMI_CONFIG_C; + } +} + /* Register access functions */ -static u32 had_read_register_raw(struct snd_intelhad *ctx, u32 reg) +static u32 had_read_register_raw(struct snd_intelhad_card *card_ctx, + int pipe, u32 reg) { - return ioread32(ctx->mmio_start + ctx->had_config_offset + reg); + return ioread32(card_ctx->mmio_start + had_config_offset(pipe) + reg); } -static void had_write_register_raw(struct snd_intelhad *ctx, u32 reg, u32 val) +static void had_write_register_raw(struct snd_intelhad_card *card_ctx, + int pipe, u32 reg, u32 val) { - iowrite32(val, ctx->mmio_start + ctx->had_config_offset + reg); + iowrite32(val, card_ctx->mmio_start + had_config_offset(pipe) + reg); } static void had_read_register(struct snd_intelhad *ctx, u32 reg, u32 *val) @@ -205,13 +225,13 @@ static void had_read_register(struct snd_intelhad *ctx, u32 reg, u32 *val) if (!ctx->connected) *val = 0; else - *val = had_read_register_raw(ctx, reg); + *val = had_read_register_raw(ctx->card_ctx, ctx->pipe, reg); } static void had_write_register(struct snd_intelhad *ctx, u32 reg, u32 val) { if (ctx->connected) - had_write_register_raw(ctx, reg, val); + had_write_register_raw(ctx->card_ctx, ctx->pipe, reg, val); } /* @@ -1358,6 +1378,9 @@ static void had_process_hot_plug(struct snd_intelhad *intelhaddata) return; } + /* Disable Audio */ + had_enable_audio(intelhaddata, false); + intelhaddata->connected = true; dev_dbg(intelhaddata->dev, "%s @ %d:DEBUG PLUG/UNPLUG : HAD_DRV_CONNECTED\n", @@ -1519,22 +1542,32 @@ static const struct snd_kcontrol_new had_controls[] = { */ static irqreturn_t display_pipe_interrupt_handler(int irq, void *dev_id) { - struct snd_intelhad *ctx = dev_id; - u32 audio_stat; + struct snd_intelhad_card *card_ctx = dev_id; + u32 audio_stat[3] = {}; + int pipe, port; + + for_each_pipe(card_ctx, pipe) { + /* use raw register access to ack IRQs even while disconnected */ + audio_stat[pipe] = had_read_register_raw(card_ctx, pipe, + AUD_HDMI_STATUS) & + (HDMI_AUDIO_UNDERRUN | HDMI_AUDIO_BUFFER_DONE); + + if (audio_stat[pipe]) + had_write_register_raw(card_ctx, pipe, + AUD_HDMI_STATUS, audio_stat[pipe]); + } - /* use raw register access to ack IRQs even while disconnected */ - audio_stat = had_read_register_raw(ctx, AUD_HDMI_STATUS); + for_each_port(card_ctx, port) { + struct snd_intelhad *ctx = &card_ctx->pcm_ctx[port]; + int pipe = ctx->pipe; - if (audio_stat & HDMI_AUDIO_UNDERRUN) { - had_write_register_raw(ctx, AUD_HDMI_STATUS, - HDMI_AUDIO_UNDERRUN); - had_process_buffer_underrun(ctx); - } + if (pipe < 0) + continue; - if (audio_stat & HDMI_AUDIO_BUFFER_DONE) { - had_write_register_raw(ctx, AUD_HDMI_STATUS, - HDMI_AUDIO_BUFFER_DONE); - had_process_buffer_done(ctx); + if (audio_stat[pipe] & HDMI_AUDIO_BUFFER_DONE) + had_process_buffer_done(ctx); + if (audio_stat[pipe] & HDMI_AUDIO_UNDERRUN) + had_process_buffer_underrun(ctx); } return IRQ_HANDLED; @@ -1543,9 +1576,10 @@ static irqreturn_t display_pipe_interrupt_handler(int irq, void *dev_id) /* * monitor plug/unplug notification from i915; just kick off the work */ -static void notify_audio_lpe(struct platform_device *pdev) +static void notify_audio_lpe(struct platform_device *pdev, int port) { - struct snd_intelhad *ctx = platform_get_drvdata(pdev); + struct snd_intelhad_card *card_ctx = platform_get_drvdata(pdev); + struct snd_intelhad *ctx = &card_ctx->pcm_ctx[port]; schedule_work(&ctx->hdmi_audio_wq); } @@ -1556,47 +1590,51 @@ static void had_audio_wq(struct work_struct *work) struct snd_intelhad *ctx = container_of(work, struct snd_intelhad, hdmi_audio_wq); struct intel_hdmi_lpe_audio_pdata *pdata = ctx->dev->platform_data; + struct intel_hdmi_lpe_audio_port_pdata *ppdata = &pdata->port[ctx->port]; pm_runtime_get_sync(ctx->dev); mutex_lock(&ctx->mutex); - if (!pdata->hdmi_connected) { - dev_dbg(ctx->dev, "%s: Event: HAD_NOTIFY_HOT_UNPLUG\n", - __func__); + if (ppdata->pipe < 0) { + dev_dbg(ctx->dev, "%s: Event: HAD_NOTIFY_HOT_UNPLUG : port = %d\n", + __func__, ctx->port); + memset(ctx->eld, 0, sizeof(ctx->eld)); /* clear the old ELD */ + + ctx->dp_output = false; + ctx->tmds_clock_speed = 0; + ctx->link_rate = 0; + + /* Shut down the stream */ had_process_hot_unplug(ctx); - } else { - struct intel_hdmi_lpe_audio_eld *eld = &pdata->eld; + ctx->pipe = -1; + } else { dev_dbg(ctx->dev, "%s: HAD_NOTIFY_ELD : port = %d, tmds = %d\n", - __func__, eld->port_id, pdata->tmds_clock_speed); - - switch (eld->pipe_id) { - case 0: - ctx->had_config_offset = AUDIO_HDMI_CONFIG_A; - break; - case 1: - ctx->had_config_offset = AUDIO_HDMI_CONFIG_B; - break; - case 2: - ctx->had_config_offset = AUDIO_HDMI_CONFIG_C; - break; - default: - dev_dbg(ctx->dev, "Invalid pipe %d\n", - eld->pipe_id); - break; - } + __func__, ctx->port, ppdata->ls_clock); - memcpy(ctx->eld, eld->eld_data, sizeof(ctx->eld)); + memcpy(ctx->eld, ppdata->eld, sizeof(ctx->eld)); - ctx->dp_output = pdata->dp_output; - ctx->tmds_clock_speed = pdata->tmds_clock_speed; - ctx->link_rate = pdata->link_rate; + ctx->dp_output = ppdata->dp_output; + if (ctx->dp_output) { + ctx->tmds_clock_speed = 0; + ctx->link_rate = ppdata->ls_clock; + } else { + ctx->tmds_clock_speed = ppdata->ls_clock; + ctx->link_rate = 0; + } + /* + * Shut down the stream before we change + * the pipe assignment for this pcm device + */ had_process_hot_plug(ctx); - /* Process mode change if stream is active */ + ctx->pipe = ppdata->pipe; + + /* Restart the stream if necessary */ had_process_mode_change(ctx); } + mutex_unlock(&ctx->mutex); pm_runtime_mark_last_busy(ctx->dev); pm_runtime_put_autosuspend(ctx->dev); @@ -1605,11 +1643,17 @@ static void had_audio_wq(struct work_struct *work) /* * Jack interface */ -static int had_create_jack(struct snd_intelhad *ctx) +static int had_create_jack(struct snd_intelhad *ctx, + struct snd_pcm *pcm) { + char hdmi_str[32]; int err; - err = snd_jack_new(ctx->card, "HDMI/DP", SND_JACK_AVOUT, &ctx->jack, + snprintf(hdmi_str, sizeof(hdmi_str), + "HDMI/DP,pcm=%d", pcm->device); + + err = snd_jack_new(ctx->card_ctx->card, hdmi_str, + SND_JACK_AVOUT, &ctx->jack, true, false); if (err < 0) return err; @@ -1623,13 +1667,18 @@ static int had_create_jack(struct snd_intelhad *ctx) static int hdmi_lpe_audio_runtime_suspend(struct device *dev) { - struct snd_intelhad *ctx = dev_get_drvdata(dev); - struct snd_pcm_substream *substream; + struct snd_intelhad_card *card_ctx = dev_get_drvdata(dev); + int port; - substream = had_substream_get(ctx); - if (substream) { - snd_pcm_suspend(substream); - had_substream_put(ctx); + for_each_port(card_ctx, port) { + struct snd_intelhad *ctx = &card_ctx->pcm_ctx[port]; + struct snd_pcm_substream *substream; + + substream = had_substream_get(ctx); + if (substream) { + snd_pcm_suspend(substream); + had_substream_put(ctx); + } } return 0; @@ -1637,12 +1686,12 @@ static int hdmi_lpe_audio_runtime_suspend(struct device *dev) static int __maybe_unused hdmi_lpe_audio_suspend(struct device *dev) { - struct snd_intelhad *ctx = dev_get_drvdata(dev); + struct snd_intelhad_card *card_ctx = dev_get_drvdata(dev); int err; err = hdmi_lpe_audio_runtime_suspend(dev); if (!err) - snd_power_change_state(ctx->card, SNDRV_CTL_POWER_D3hot); + snd_power_change_state(card_ctx->card, SNDRV_CTL_POWER_D3hot); return err; } @@ -1654,24 +1703,34 @@ static int hdmi_lpe_audio_runtime_resume(struct device *dev) static int __maybe_unused hdmi_lpe_audio_resume(struct device *dev) { - struct snd_intelhad *ctx = dev_get_drvdata(dev); + struct snd_intelhad_card *card_ctx = dev_get_drvdata(dev); hdmi_lpe_audio_runtime_resume(dev); - snd_power_change_state(ctx->card, SNDRV_CTL_POWER_D0); + snd_power_change_state(card_ctx->card, SNDRV_CTL_POWER_D0); return 0; } /* release resources */ static void hdmi_lpe_audio_free(struct snd_card *card) { - struct snd_intelhad *ctx = card->private_data; + struct snd_intelhad_card *card_ctx = card->private_data; + struct intel_hdmi_lpe_audio_pdata *pdata = card_ctx->dev->platform_data; + int port; + + spin_lock_irq(&pdata->lpe_audio_slock); + pdata->notify_audio_lpe = NULL; + spin_unlock_irq(&pdata->lpe_audio_slock); - cancel_work_sync(&ctx->hdmi_audio_wq); + for_each_port(card_ctx, port) { + struct snd_intelhad *ctx = &card_ctx->pcm_ctx[port]; - if (ctx->mmio_start) - iounmap(ctx->mmio_start); - if (ctx->irq >= 0) - free_irq(ctx->irq, ctx); + cancel_work_sync(&ctx->hdmi_audio_wq); + } + + if (card_ctx->mmio_start) + iounmap(card_ctx->mmio_start); + if (card_ctx->irq >= 0) + free_irq(card_ctx->irq, card_ctx); } /* @@ -1683,12 +1742,12 @@ static void hdmi_lpe_audio_free(struct snd_card *card) static int hdmi_lpe_audio_probe(struct platform_device *pdev) { struct snd_card *card; - struct snd_intelhad *ctx; + struct snd_intelhad_card *card_ctx; struct snd_pcm *pcm; struct intel_hdmi_lpe_audio_pdata *pdata; int irq; struct resource *res_mmio; - int i, ret; + int port, ret; pdata = pdev->dev.platform_data; if (!pdata) { @@ -1699,8 +1758,8 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev) /* get resources */ irq = platform_get_irq(pdev, 0); if (irq < 0) { - dev_err(&pdev->dev, "Could not get irq resource\n"); - return -ENODEV; + dev_err(&pdev->dev, "Could not get irq resource: %d\n", irq); + return irq; } res_mmio = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -1711,39 +1770,30 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev) /* create a card instance with ALSA framework */ ret = snd_card_new(&pdev->dev, hdmi_card_index, hdmi_card_id, - THIS_MODULE, sizeof(*ctx), &card); + THIS_MODULE, sizeof(*card_ctx), &card); if (ret) return ret; - ctx = card->private_data; - spin_lock_init(&ctx->had_spinlock); - mutex_init(&ctx->mutex); - ctx->connected = false; - ctx->dev = &pdev->dev; - ctx->card = card; - ctx->aes_bits = SNDRV_PCM_DEFAULT_CON_SPDIF; + card_ctx = card->private_data; + card_ctx->dev = &pdev->dev; + card_ctx->card = card; strcpy(card->driver, INTEL_HAD); strcpy(card->shortname, "Intel HDMI/DP LPE Audio"); strcpy(card->longname, "Intel HDMI/DP LPE Audio"); - ctx->irq = -1; - ctx->tmds_clock_speed = DIS_SAMPLE_RATE_148_5; - INIT_WORK(&ctx->hdmi_audio_wq, had_audio_wq); + card_ctx->irq = -1; card->private_free = hdmi_lpe_audio_free; - /* assume pipe A as default */ - ctx->had_config_offset = AUDIO_HDMI_CONFIG_A; - - platform_set_drvdata(pdev, ctx); + platform_set_drvdata(pdev, card_ctx); dev_dbg(&pdev->dev, "%s: mmio_start = 0x%x, mmio_end = 0x%x\n", __func__, (unsigned int)res_mmio->start, (unsigned int)res_mmio->end); - ctx->mmio_start = ioremap_nocache(res_mmio->start, - (size_t)(resource_size(res_mmio))); - if (!ctx->mmio_start) { + card_ctx->mmio_start = ioremap_nocache(res_mmio->start, + (size_t)(resource_size(res_mmio))); + if (!card_ctx->mmio_start) { dev_err(&pdev->dev, "Could not get ioremap\n"); ret = -EACCES; goto err; @@ -1751,54 +1801,79 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev) /* setup interrupt handler */ ret = request_irq(irq, display_pipe_interrupt_handler, 0, - pdev->name, ctx); + pdev->name, card_ctx); if (ret < 0) { dev_err(&pdev->dev, "request_irq failed\n"); goto err; } - ctx->irq = irq; - - ret = snd_pcm_new(card, INTEL_HAD, PCM_INDEX, MAX_PB_STREAMS, - MAX_CAP_STREAMS, &pcm); - if (ret) - goto err; - - /* setup private data which can be retrieved when required */ - pcm->private_data = ctx; - pcm->info_flags = 0; - strncpy(pcm->name, card->shortname, strlen(card->shortname)); - /* setup the ops for playabck */ - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &had_pcm_ops); + card_ctx->irq = irq; /* only 32bit addressable */ dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); - /* allocate dma pages; - * try to allocate 600k buffer as default which is large enough - */ - snd_pcm_lib_preallocate_pages_for_all(pcm, - SNDRV_DMA_TYPE_DEV, NULL, - HAD_DEFAULT_BUFFER, HAD_MAX_BUFFER); + init_channel_allocations(); - /* create controls */ - for (i = 0; i < ARRAY_SIZE(had_controls); i++) { - ret = snd_ctl_add(card, snd_ctl_new1(&had_controls[i], ctx)); - if (ret < 0) + card_ctx->num_pipes = pdata->num_pipes; + card_ctx->num_ports = pdata->num_ports; + + for_each_port(card_ctx, port) { + struct snd_intelhad *ctx = &card_ctx->pcm_ctx[port]; + int i; + + ctx->card_ctx = card_ctx; + ctx->dev = card_ctx->dev; + ctx->port = port; + ctx->pipe = -1; + + INIT_WORK(&ctx->hdmi_audio_wq, had_audio_wq); + + ret = snd_pcm_new(card, INTEL_HAD, port, MAX_PB_STREAMS, + MAX_CAP_STREAMS, &pcm); + if (ret) goto err; - } - init_channel_allocations(); + /* setup private data which can be retrieved when required */ + pcm->private_data = ctx; + pcm->info_flags = 0; + strncpy(pcm->name, card->shortname, strlen(card->shortname)); + /* setup the ops for playabck */ + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &had_pcm_ops); - /* Register channel map controls */ - ret = had_register_chmap_ctls(ctx, pcm); - if (ret < 0) - goto err; + /* allocate dma pages; + * try to allocate 600k buffer as default which is large enough + */ + snd_pcm_lib_preallocate_pages_for_all(pcm, + SNDRV_DMA_TYPE_DEV, NULL, + HAD_DEFAULT_BUFFER, HAD_MAX_BUFFER); + + /* create controls */ + for (i = 0; i < ARRAY_SIZE(had_controls); i++) { + struct snd_kcontrol *kctl; + + kctl = snd_ctl_new1(&had_controls[i], ctx); + if (!kctl) { + ret = -ENOMEM; + goto err; + } - ret = had_create_jack(ctx); - if (ret < 0) - goto err; + kctl->id.device = pcm->device; + + ret = snd_ctl_add(card, kctl); + if (ret < 0) + goto err; + } + + /* Register channel map controls */ + ret = had_register_chmap_ctls(ctx, pcm); + if (ret < 0) + goto err; + + ret = had_create_jack(ctx, pcm); + if (ret < 0) + goto err; + } ret = snd_card_register(card); if (ret) @@ -1806,7 +1881,6 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev) spin_lock_irq(&pdata->lpe_audio_slock); pdata->notify_audio_lpe = notify_audio_lpe; - pdata->notify_pending = false; spin_unlock_irq(&pdata->lpe_audio_slock); pm_runtime_use_autosuspend(&pdev->dev); @@ -1814,7 +1888,11 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev) pm_runtime_set_active(&pdev->dev); dev_dbg(&pdev->dev, "%s: handle pending notification\n", __func__); - schedule_work(&ctx->hdmi_audio_wq); + for_each_port(card_ctx, port) { + struct snd_intelhad *ctx = &card_ctx->pcm_ctx[port]; + + schedule_work(&ctx->hdmi_audio_wq); + } return 0; @@ -1830,9 +1908,9 @@ err: */ static int hdmi_lpe_audio_remove(struct platform_device *pdev) { - struct snd_intelhad *ctx = platform_get_drvdata(pdev); + struct snd_intelhad_card *card_ctx = platform_get_drvdata(pdev); - snd_card_free(ctx->card); + snd_card_free(card_ctx->card); return 0; } diff --git a/sound/x86/intel_hdmi_audio.h b/sound/x86/intel_hdmi_audio.h index 2d3e389f76b3..0d91bb5dbab7 100644 --- a/sound/x86/intel_hdmi_audio.h +++ b/sound/x86/intel_hdmi_audio.h @@ -32,7 +32,6 @@ #include "intel_hdmi_lpe_audio.h" -#define PCM_INDEX 0 #define MAX_PB_STREAMS 1 #define MAX_CAP_STREAMS 0 #define BYTES_PER_WORD 0x4 @@ -101,7 +100,7 @@ struct pcm_stream_info { * @chmap: holds channel map info */ struct snd_intelhad { - struct snd_card *card; + struct snd_intelhad_card *card_ctx; bool connected; struct pcm_stream_info stream_info; unsigned char eld[HDMI_MAX_ELD_BYTES]; @@ -112,6 +111,8 @@ struct snd_intelhad { struct snd_pcm_chmap *chmap; int tmds_clock_speed; int link_rate; + int port; /* fixed */ + int pipe; /* can change dynamically */ /* ring buffer (BD) position index */ unsigned int bd_head; @@ -123,9 +124,6 @@ struct snd_intelhad { unsigned int period_bytes; /* PCM period size in bytes */ /* internal stuff */ - int irq; - void __iomem *mmio_start; - unsigned int had_config_offset; union aud_cfg aud_config; /* AUD_CONFIG reg value cache */ struct work_struct hdmi_audio_wq; struct mutex mutex; /* for protecting chmap and eld */ @@ -133,4 +131,16 @@ struct snd_intelhad { struct snd_jack *jack; }; +struct snd_intelhad_card { + struct snd_card *card; + struct device *dev; + + /* internal stuff */ + int irq; + void __iomem *mmio_start; + int num_pipes; + int num_ports; + struct snd_intelhad pcm_ctx[3]; /* one for each port */ +}; + #endif /* _INTEL_HDMI_AUDIO_ */ |