Merge branch 'for-next' into for-linus

This commit is contained in:
Takashi Iwai
2022-10-03 08:48:26 +02:00
95 changed files with 1107 additions and 1090 deletions

View File

@@ -3565,13 +3565,17 @@ given size.
The second argument (type) and the third argument (device pointer) are
dependent on the bus. For normal devices, pass the device pointer
(typically identical as ``card->dev``) to the third argument with
``SNDRV_DMA_TYPE_DEV`` type. For the continuous buffer unrelated to the
``SNDRV_DMA_TYPE_DEV`` type.
For the continuous buffer unrelated to the
bus can be pre-allocated with ``SNDRV_DMA_TYPE_CONTINUOUS`` type.
You can pass NULL to the device pointer in that case, which is the
default mode implying to allocate with ``GFP_KERNEL`` flag.
If you need a different GFP flag, you can pass it by encoding the flag
into the device pointer via a special macro
:c:func:`snd_dma_continuous_data()`.
If you need a restricted (lower) address, set up the coherent DMA mask
bits for the device, and pass the device pointer, like the normal
device memory allocations. For this type, it's still allowed to pass
NULL to the device pointer, too, if no address restriction is needed.
For the scatter-gather buffers, use ``SNDRV_DMA_TYPE_DEV_SG`` with the
device pointer (see the `Non-Contiguous Buffers`_ section).
@@ -3811,15 +3815,6 @@ arguments here. Since each vmalloc call should succeed at any time,
we don't need to pre-allocate the buffers like other continuous
pages.
If you need the 32bit DMA allocation, pass the device pointer encoded
by :c:func:`snd_dma_continuous_data()` with ``GFP_KERNEL|__GFP_DMA32``
argument.
::
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC,
snd_dma_continuous_data(GFP_KERNEL | __GFP_DMA32), 0, 0);
Proc Interface
==============

View File

@@ -158,8 +158,8 @@ size_t u_audio_playback(struct gaudio *card, void *buf, size_t count)
snd_pcm_sframes_t frames;
try_again:
if (runtime->status->state == SNDRV_PCM_STATE_XRUN ||
runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
if (runtime->state == SNDRV_PCM_STATE_XRUN ||
runtime->state == SNDRV_PCM_STATE_SUSPENDED) {
result = snd_pcm_kernel_ioctl(substream,
SNDRV_PCM_IOCTL_PREPARE, NULL);
if (result < 0) {

View File

@@ -258,7 +258,6 @@ struct hda_codec {
unsigned int link_down_at_suspend:1; /* link down at runtime suspend */
unsigned int relaxed_resume:1; /* don't resume forcibly for jack */
unsigned int forced_resume:1; /* forced resume for jack */
unsigned int mst_no_extra_pcms:1; /* no backup PCMs for DP-MST */
#ifdef CONFIG_PM
unsigned long power_on_acct;
@@ -293,8 +292,6 @@ struct hda_codec {
#define dev_to_hda_codec(_dev) container_of(_dev, struct hda_codec, core.dev)
#define hda_codec_dev(_dev) (&(_dev)->core.dev)
#define hdac_to_hda_priv(_hdac) \
container_of(_hdac, struct hdac_hda_priv, codec.core)
#define hdac_to_hda_codec(_hdac) container_of(_hdac, struct hda_codec, core)
#define list_for_each_codec(c, bus) \

View File

@@ -260,7 +260,18 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
#define AZX_REG_ML_LCAP 0x00
#define AZX_REG_ML_LCTL 0x04
#define AZX_ML_LCTL_CPA BIT(23)
#define AZX_ML_LCTL_CPA_SHIFT 23
#define AZX_ML_LCTL_SPA BIT(16)
#define AZX_ML_LCTL_SPA_SHIFT 16
#define AZX_ML_LCTL_SCF GENMASK(3, 0)
#define AZX_REG_ML_LOSIDV 0x08
/* bit0 is reserved, with BIT(1) mapping to stream1 */
#define AZX_ML_LOSIDV_STREAM_MASK 0xFFFE
#define AZX_REG_ML_LSDIID 0x0C
#define AZX_REG_ML_LPSOO 0x10
#define AZX_REG_ML_LPSIO 0x12
@@ -268,15 +279,6 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
#define AZX_REG_ML_LOUTPAY 0x20
#define AZX_REG_ML_LINPAY 0x30
/* bit0 is reserved, with BIT(1) mapping to stream1 */
#define ML_LOSIDV_STREAM_MASK 0xFFFE
#define ML_LCTL_SCF_MASK 0xF
#define AZX_MLCTL_SPA (0x1 << 16)
#define AZX_MLCTL_CPA (0x1 << 23)
#define AZX_MLCTL_SPA_SHIFT 16
#define AZX_MLCTL_CPA_SHIFT 23
/* registers for DMA Resume Capability Structure */
#define AZX_DRSM_CAP_ID 0x5
#define AZX_REG_DRSM_CTL 0x4

View File

@@ -10,6 +10,7 @@
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/io-64-nonatomic-lo-hi.h>
#include <linux/iopoll.h>
#include <linux/pm_runtime.h>
#include <linux/timecounter.h>
#include <sound/core.h>
@@ -550,6 +551,7 @@ void snd_hdac_stream_init(struct hdac_bus *bus, struct hdac_stream *azx_dev,
int idx, int direction, int tag);
struct hdac_stream *snd_hdac_stream_assign(struct hdac_bus *bus,
struct snd_pcm_substream *substream);
void snd_hdac_stream_release_locked(struct hdac_stream *azx_dev);
void snd_hdac_stream_release(struct hdac_stream *azx_dev);
struct hdac_stream *snd_hdac_get_stream(struct hdac_bus *bus,
int dir, int stream_tag);
@@ -560,8 +562,8 @@ int snd_hdac_stream_setup_periods(struct hdac_stream *azx_dev);
int snd_hdac_stream_set_params(struct hdac_stream *azx_dev,
unsigned int format_val);
void snd_hdac_stream_start(struct hdac_stream *azx_dev, bool fresh_start);
void snd_hdac_stream_clear(struct hdac_stream *azx_dev);
void snd_hdac_stream_stop(struct hdac_stream *azx_dev);
void snd_hdac_stop_streams(struct hdac_bus *bus);
void snd_hdac_stop_streams_and_chip(struct hdac_bus *bus);
void snd_hdac_stream_reset(struct hdac_stream *azx_dev);
void snd_hdac_stream_sync_trigger(struct hdac_stream *azx_dev, bool set,
@@ -589,6 +591,12 @@ int snd_hdac_get_stream_stripe_ctl(struct hdac_bus *bus,
snd_hdac_reg_readw((dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg)
#define snd_hdac_stream_readb(dev, reg) \
snd_hdac_reg_readb((dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg)
#define snd_hdac_stream_readb_poll(dev, reg, val, cond, delay_us, timeout_us) \
readb_poll_timeout((dev)->sd_addr + AZX_REG_ ## reg, val, cond, \
delay_us, timeout_us)
#define snd_hdac_stream_readl_poll(dev, reg, val, cond, delay_us, timeout_us) \
readl_poll_timeout((dev)->sd_addr + AZX_REG_ ## reg, val, cond, \
delay_us, timeout_us)
/* update a register, pass without AZX_REG_ prefix */
#define snd_hdac_stream_updatel(dev, reg, mask, val) \

View File

@@ -11,9 +11,6 @@ int snd_hdac_ext_bus_init(struct hdac_bus *bus, struct device *dev,
const struct hdac_ext_bus_ops *ext_ops);
void snd_hdac_ext_bus_exit(struct hdac_bus *bus);
int snd_hdac_ext_bus_device_init(struct hdac_bus *bus, int addr,
struct hdac_device *hdev, int type);
void snd_hdac_ext_bus_device_exit(struct hdac_device *hdev);
void snd_hdac_ext_bus_device_remove(struct hdac_bus *bus);
#define HDA_CODEC_REV_EXT_ENTRY(_vid, _rev, _name, drv_data) \
@@ -80,12 +77,9 @@ struct hdac_ext_stream {
#define stream_to_hdac_ext_stream(s) \
container_of(s, struct hdac_ext_stream, hstream)
void snd_hdac_ext_stream_init(struct hdac_bus *bus,
struct hdac_ext_stream *hext_stream, int idx,
int direction, int tag);
int snd_hdac_ext_stream_init_all(struct hdac_bus *bus, int start_idx,
int num_stream, int dir);
void snd_hdac_stream_free_all(struct hdac_bus *bus);
void snd_hdac_ext_stream_free_all(struct hdac_bus *bus);
void snd_hdac_link_free_all(struct hdac_bus *bus);
struct hdac_ext_stream *snd_hdac_ext_stream_assign(struct hdac_bus *bus,
struct snd_pcm_substream *substream,
@@ -188,12 +182,6 @@ void snd_hdac_ext_bus_link_power(struct hdac_device *codec, bool enable);
#define snd_hdac_adsp_readq_poll(chip, reg, val, cond, delay_us, timeout_us) \
readq_poll_timeout((chip)->dsp_ba + (reg), val, cond, \
delay_us, timeout_us)
#define snd_hdac_stream_readb_poll(strm, reg, val, cond, delay_us, timeout_us) \
readb_poll_timeout((strm)->sd_addr + AZX_REG_ ## reg, val, cond, \
delay_us, timeout_us)
#define snd_hdac_stream_readl_poll(strm, reg, val, cond, delay_us, timeout_us) \
readl_poll_timeout((strm)->sd_addr + AZX_REG_ ## reg, val, cond, \
delay_us, timeout_us)
struct hdac_ext_device;

View File

@@ -26,9 +26,6 @@ struct snd_dma_device {
struct device *dev; /* generic device */
};
#define snd_dma_continuous_data(x) ((struct device *)(__force unsigned long)(x))
/*
* buffer types
*/

View File

@@ -346,6 +346,8 @@ static inline void snd_pcm_pack_audio_tstamp_report(__u32 *data, __u32 *accuracy
struct snd_pcm_runtime {
/* -- Status -- */
snd_pcm_state_t state; /* stream state */
snd_pcm_state_t suspended_state; /* suspended stream state */
struct snd_pcm_substream *trigger_master;
struct timespec64 trigger_tstamp; /* trigger timestamp */
bool trigger_tstamp_latched; /* trigger timestamp latched in low-level driver/hardware */
@@ -678,11 +680,25 @@ void snd_pcm_stream_unlock_irqrestore(struct snd_pcm_substream *substream,
*/
static inline int snd_pcm_running(struct snd_pcm_substream *substream)
{
return (substream->runtime->status->state == SNDRV_PCM_STATE_RUNNING ||
(substream->runtime->status->state == SNDRV_PCM_STATE_DRAINING &&
return (substream->runtime->state == SNDRV_PCM_STATE_RUNNING ||
(substream->runtime->state == SNDRV_PCM_STATE_DRAINING &&
substream->stream == SNDRV_PCM_STREAM_PLAYBACK));
}
/**
* __snd_pcm_set_state - Change the current PCM state
* @runtime: PCM runtime to set
* @state: the current state to set
*
* Call within the stream lock
*/
static inline void __snd_pcm_set_state(struct snd_pcm_runtime *runtime,
snd_pcm_state_t state)
{
runtime->state = state;
runtime->status->state = state; /* copy for mmap */
}
/**
* bytes_to_samples - Unit conversion of the size from bytes to samples
* @runtime: PCM runtime instance

View File

@@ -3,22 +3,6 @@
* Main header file for the ALSA sequencer
* Copyright (c) 1998-1999 by Frank van de Pol <fvdpol@coil.demon.nl>
* (c) 1998-1999 by Jaroslav Kysela <perex@perex.cz>
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#ifndef _UAPI__SOUND_ASEQUENCER_H
#define _UAPI__SOUND_ASEQUENCER_H

View File

@@ -5,10 +5,6 @@
* Copyright (C) 2012 Texas Instruments Inc.
* Copyright (C) 2015 Intel 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.
*
* Simple file API to load FW that includes mixers, coefficients, DAPM graphs,
* algorithms, equalisers, DAIs, widgets etc.
*/

View File

@@ -3,22 +3,6 @@
* Advanced Linux Sound Architecture - ALSA - Driver
* Copyright (c) 1994-2003 by Jaroslav Kysela <perex@perex.cz>,
* Abramo Bagnara <abramo@alsa-project.org>
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#ifndef _UAPI__SOUND_ASOUND_H

View File

@@ -10,21 +10,6 @@
* 4Front Technologies
*
* Direct FM control
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#define SNDRV_DM_FM_MODE_OPL2 0x00

View File

@@ -5,23 +5,6 @@
* Copyright (C) 2011 Intel Corporation
* Authors: Vinod Koul <vinod.koul@linux.intel.com>
* Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
*/
#ifndef __COMPRESS_OFFLOAD_H
#define __COMPRESS_OFFLOAD_H

View File

@@ -7,47 +7,13 @@
* Authors: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
* Vinod Koul <vinod.koul@linux.intel.com>
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* The definitions in this file are derived from the OpenMAX AL version 1.1
* and OpenMAX IL v 1.1.2 header files which contain the copyright notice below.
* and OpenMAX IL v 1.1.2 header files which contain the copyright notice below
* and are licensed under the MIT license.
*
* Copyright (c) 2007-2010 The Khronos Group Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and/or associated documentation files (the
* "Materials "), to deal in the Materials without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Materials, and to
* permit persons to whom the Materials are furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Materials.
*
* THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
*
*/
#ifndef __SND_COMPRESS_PARAMS_H
#define __SND_COMPRESS_PARAMS_H

View File

@@ -3,22 +3,6 @@
* Copyright (c) by Jaroslav Kysela <perex@perex.cz>,
* Creative Labs, Inc.
* Definitions for EMU10K1 (SB Live!) chips
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#ifndef _UAPI__SOUND_EMU10K1_H
#define _UAPI__SOUND_EMU10K1_H

View File

@@ -4,20 +4,6 @@
/*
* Copyright (C) 2003 Thomas Charbonnel (thomas@undata.org)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifdef __linux__

View File

@@ -4,21 +4,6 @@
/*
* Copyright (C) 2003 Winfried Ritsch (IEM)
* based on hdsp.h from Thomas Charbonnel (thomas@undata.org)
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifdef __linux__

View File

@@ -4,21 +4,6 @@
* Takashi Iwai <tiwai@suse.de>
*
* SB16ASP/AWE32 CSP control
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#ifndef _UAPI__SOUND_SB16_CSP_H
#define _UAPI__SOUND_SB16_CSP_H

View File

@@ -6,21 +6,6 @@
* Patch record compatible with AWE driver on OSS
*
* Copyright (C) 1999-2000 Takashi Iwai
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <sound/asound.h>

View File

@@ -4,16 +4,6 @@
*
* Copyright (C) 2016 Intel Corp
* Author: Shreyas NC <shreyas.nc@intel.com>
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as version 2, as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*/
#ifndef __SND_SST_TOKENS_H__
#define __SND_SST_TOKENS_H__

View File

@@ -1,15 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef __UAPI_SOUND_TLV_H
#define __UAPI_SOUND_TLV_H

View File

@@ -1,20 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
/*
* Copyright (C) 2007, 2008 Karsten Wiese <fzu@wemgehoertderstaat.de>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef _UAPI__SOUND_USB_STREAM_H

View File

@@ -18,25 +18,18 @@
#include <sound/memalloc.h>
#include "memalloc_local.h"
#define DEFAULT_GFP \
(GFP_KERNEL | \
__GFP_COMP | /* compound page lets parts be mapped */ \
__GFP_RETRY_MAYFAIL | /* don't trigger OOM-killer */ \
__GFP_NOWARN) /* no stack trace print - this call is non-critical */
static const struct snd_malloc_ops *snd_dma_get_ops(struct snd_dma_buffer *dmab);
#ifdef CONFIG_SND_DMA_SGBUF
static void *do_alloc_fallback_pages(struct device *dev, size_t size,
dma_addr_t *addr, bool wc);
static void do_free_fallback_pages(void *p, size_t size, bool wc);
static void *snd_dma_sg_fallback_alloc(struct snd_dma_buffer *dmab, size_t size);
#endif
/* a cast to gfp flag from the dev pointer; for CONTINUOUS and VMALLOC types */
static inline gfp_t snd_mem_get_gfp_flags(const struct snd_dma_buffer *dmab,
gfp_t default_gfp)
{
if (!dmab->dev.dev)
return default_gfp;
else
return (__force gfp_t)(unsigned long)dmab->dev.dev;
}
static void *__snd_dma_alloc_pages(struct snd_dma_buffer *dmab, size_t size)
{
const struct snd_malloc_ops *ops = snd_dma_get_ops(dmab);
@@ -284,24 +277,54 @@ EXPORT_SYMBOL(snd_sgbuf_get_chunk_size);
/*
* Continuous pages allocator
*/
static void *do_alloc_pages(size_t size, dma_addr_t *addr, gfp_t gfp)
static void *do_alloc_pages(struct device *dev, size_t size, dma_addr_t *addr,
bool wc)
{
void *p = alloc_pages_exact(size, gfp);
void *p;
gfp_t gfp = GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN;
if (p)
*addr = page_to_phys(virt_to_page(p));
again:
p = alloc_pages_exact(size, gfp);
if (!p)
return NULL;
*addr = page_to_phys(virt_to_page(p));
if (!dev)
return p;
if ((*addr + size - 1) & ~dev->coherent_dma_mask) {
if (IS_ENABLED(CONFIG_ZONE_DMA32) && !(gfp & GFP_DMA32)) {
gfp |= GFP_DMA32;
goto again;
}
if (IS_ENABLED(CONFIG_ZONE_DMA) && !(gfp & GFP_DMA)) {
gfp = (gfp & ~GFP_DMA32) | GFP_DMA;
goto again;
}
}
#ifdef CONFIG_X86
if (wc)
set_memory_wc((unsigned long)(p), size >> PAGE_SHIFT);
#endif
return p;
}
static void do_free_pages(void *p, size_t size, bool wc)
{
#ifdef CONFIG_X86
if (wc)
set_memory_wb((unsigned long)(p), size >> PAGE_SHIFT);
#endif
free_pages_exact(p, size);
}
static void *snd_dma_continuous_alloc(struct snd_dma_buffer *dmab, size_t size)
{
return do_alloc_pages(size, &dmab->addr,
snd_mem_get_gfp_flags(dmab, GFP_KERNEL));
return do_alloc_pages(dmab->dev.dev, size, &dmab->addr, false);
}
static void snd_dma_continuous_free(struct snd_dma_buffer *dmab)
{
free_pages_exact(dmab->area, dmab->bytes);
do_free_pages(dmab->area, dmab->bytes, false);
}
static int snd_dma_continuous_mmap(struct snd_dma_buffer *dmab,
@@ -324,9 +347,7 @@ static const struct snd_malloc_ops snd_dma_continuous_ops = {
*/
static void *snd_dma_vmalloc_alloc(struct snd_dma_buffer *dmab, size_t size)
{
gfp_t gfp = snd_mem_get_gfp_flags(dmab, GFP_KERNEL | __GFP_HIGHMEM);
return __vmalloc(size, gfp);
return vmalloc(size);
}
static void snd_dma_vmalloc_free(struct snd_dma_buffer *dmab)
@@ -440,12 +461,6 @@ static const struct snd_malloc_ops snd_dma_iram_ops = {
};
#endif /* CONFIG_GENERIC_ALLOCATOR */
#define DEFAULT_GFP \
(GFP_KERNEL | \
__GFP_COMP | /* compound page lets parts be mapped */ \
__GFP_NORETRY | /* don't trigger OOM-killer */ \
__GFP_NOWARN) /* no stack trace print - this call is non-critical */
/*
* Coherent device pages allocator
*/
@@ -479,12 +494,12 @@ static const struct snd_malloc_ops snd_dma_dev_ops = {
#ifdef CONFIG_SND_DMA_SGBUF
static void *snd_dma_wc_alloc(struct snd_dma_buffer *dmab, size_t size)
{
return do_alloc_fallback_pages(dmab->dev.dev, size, &dmab->addr, true);
return do_alloc_pages(dmab->dev.dev, size, &dmab->addr, true);
}
static void snd_dma_wc_free(struct snd_dma_buffer *dmab)
{
do_free_fallback_pages(dmab->area, dmab->bytes, true);
do_free_pages(dmab->area, dmab->bytes, true);
}
static int snd_dma_wc_mmap(struct snd_dma_buffer *dmab,
@@ -700,37 +715,6 @@ static const struct snd_malloc_ops snd_dma_sg_wc_ops = {
.get_chunk_size = snd_dma_noncontig_get_chunk_size,
};
/* manual page allocations with wc setup */
static void *do_alloc_fallback_pages(struct device *dev, size_t size,
dma_addr_t *addr, bool wc)
{
gfp_t gfp = GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN;
void *p;
again:
p = do_alloc_pages(size, addr, gfp);
if (!p || (*addr + size - 1) & ~dev->coherent_dma_mask) {
if (IS_ENABLED(CONFIG_ZONE_DMA32) && !(gfp & GFP_DMA32)) {
gfp |= GFP_DMA32;
goto again;
}
if (IS_ENABLED(CONFIG_ZONE_DMA) && !(gfp & GFP_DMA)) {
gfp = (gfp & ~GFP_DMA32) | GFP_DMA;
goto again;
}
}
if (p && wc)
set_memory_wc((unsigned long)(p), size >> PAGE_SHIFT);
return p;
}
static void do_free_fallback_pages(void *p, size_t size, bool wc)
{
if (wc)
set_memory_wb((unsigned long)(p), size >> PAGE_SHIFT);
free_pages_exact(p, size);
}
/* Fallback SG-buffer allocations for x86 */
struct snd_dma_sg_fallback {
size_t count;
@@ -745,7 +729,7 @@ static void __snd_dma_sg_fallback_free(struct snd_dma_buffer *dmab,
size_t i;
for (i = 0; i < sgbuf->count && sgbuf->pages[i]; i++)
do_free_fallback_pages(page_address(sgbuf->pages[i]), PAGE_SIZE, wc);
do_free_pages(page_address(sgbuf->pages[i]), PAGE_SIZE, wc);
kvfree(sgbuf->pages);
kvfree(sgbuf->addrs);
kfree(sgbuf);
@@ -772,8 +756,7 @@ static void *snd_dma_sg_fallback_alloc(struct snd_dma_buffer *dmab, size_t size)
goto error;
for (i = 0; i < count; sgbuf->count++, i++) {
p = do_alloc_fallback_pages(dmab->dev.dev, PAGE_SIZE,
&sgbuf->addrs[i], wc);
p = do_alloc_pages(dmab->dev.dev, PAGE_SIZE, &sgbuf->addrs[i], wc);
if (!p)
goto error;
sgbuf->pages[i] = virt_to_page(p);

View File

@@ -13,8 +13,4 @@ struct snd_malloc_ops {
void (*sync)(struct snd_dma_buffer *dmab, enum snd_dma_sync_mode mode);
};
#ifdef CONFIG_SND_DMA_SGBUF
extern const struct snd_malloc_ops snd_dma_sg_ops;
#endif
#endif /* __MEMALLOC_LOCAL_H */

View File

@@ -1237,12 +1237,12 @@ snd_pcm_sframes_t snd_pcm_oss_write3(struct snd_pcm_substream *substream, const
struct snd_pcm_runtime *runtime = substream->runtime;
int ret;
while (1) {
if (runtime->status->state == SNDRV_PCM_STATE_XRUN ||
runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
if (runtime->state == SNDRV_PCM_STATE_XRUN ||
runtime->state == SNDRV_PCM_STATE_SUSPENDED) {
#ifdef OSS_DEBUG
pcm_dbg(substream->pcm,
"pcm_oss: write: recovering from %s\n",
runtime->status->state == SNDRV_PCM_STATE_XRUN ?
runtime->state == SNDRV_PCM_STATE_XRUN ?
"XRUN" : "SUSPEND");
#endif
ret = snd_pcm_oss_prepare(substream);
@@ -1257,7 +1257,7 @@ snd_pcm_sframes_t snd_pcm_oss_write3(struct snd_pcm_substream *substream, const
break;
/* test, if we can't store new data, because the stream */
/* has not been started */
if (runtime->status->state == SNDRV_PCM_STATE_PREPARED)
if (runtime->state == SNDRV_PCM_STATE_PREPARED)
return -EAGAIN;
}
return ret;
@@ -1269,18 +1269,18 @@ snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream, char *p
snd_pcm_sframes_t delay;
int ret;
while (1) {
if (runtime->status->state == SNDRV_PCM_STATE_XRUN ||
runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
if (runtime->state == SNDRV_PCM_STATE_XRUN ||
runtime->state == SNDRV_PCM_STATE_SUSPENDED) {
#ifdef OSS_DEBUG
pcm_dbg(substream->pcm,
"pcm_oss: read: recovering from %s\n",
runtime->status->state == SNDRV_PCM_STATE_XRUN ?
runtime->state == SNDRV_PCM_STATE_XRUN ?
"XRUN" : "SUSPEND");
#endif
ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL);
if (ret < 0)
break;
} else if (runtime->status->state == SNDRV_PCM_STATE_SETUP) {
} else if (runtime->state == SNDRV_PCM_STATE_SETUP) {
ret = snd_pcm_oss_prepare(substream);
if (ret < 0)
break;
@@ -1293,7 +1293,7 @@ snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream, char *p
frames, in_kernel);
mutex_lock(&runtime->oss.params_lock);
if (ret == -EPIPE) {
if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
if (runtime->state == SNDRV_PCM_STATE_DRAINING) {
ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
if (ret < 0)
break;
@@ -1312,12 +1312,12 @@ snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, void
struct snd_pcm_runtime *runtime = substream->runtime;
int ret;
while (1) {
if (runtime->status->state == SNDRV_PCM_STATE_XRUN ||
runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
if (runtime->state == SNDRV_PCM_STATE_XRUN ||
runtime->state == SNDRV_PCM_STATE_SUSPENDED) {
#ifdef OSS_DEBUG
pcm_dbg(substream->pcm,
"pcm_oss: writev: recovering from %s\n",
runtime->status->state == SNDRV_PCM_STATE_XRUN ?
runtime->state == SNDRV_PCM_STATE_XRUN ?
"XRUN" : "SUSPEND");
#endif
ret = snd_pcm_oss_prepare(substream);
@@ -1330,7 +1330,7 @@ snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, void
/* test, if we can't store new data, because the stream */
/* has not been started */
if (runtime->status->state == SNDRV_PCM_STATE_PREPARED)
if (runtime->state == SNDRV_PCM_STATE_PREPARED)
return -EAGAIN;
}
return ret;
@@ -1341,18 +1341,18 @@ snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream, void *
struct snd_pcm_runtime *runtime = substream->runtime;
int ret;
while (1) {
if (runtime->status->state == SNDRV_PCM_STATE_XRUN ||
runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
if (runtime->state == SNDRV_PCM_STATE_XRUN ||
runtime->state == SNDRV_PCM_STATE_SUSPENDED) {
#ifdef OSS_DEBUG
pcm_dbg(substream->pcm,
"pcm_oss: readv: recovering from %s\n",
runtime->status->state == SNDRV_PCM_STATE_XRUN ?
runtime->state == SNDRV_PCM_STATE_XRUN ?
"XRUN" : "SUSPEND");
#endif
ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL);
if (ret < 0)
break;
} else if (runtime->status->state == SNDRV_PCM_STATE_SETUP) {
} else if (runtime->state == SNDRV_PCM_STATE_SETUP) {
ret = snd_pcm_oss_prepare(substream);
if (ret < 0)
break;
@@ -1635,7 +1635,7 @@ static int snd_pcm_oss_sync1(struct snd_pcm_substream *substream, size_t size)
result = 0;
set_current_state(TASK_INTERRUPTIBLE);
snd_pcm_stream_lock_irq(substream);
state = runtime->status->state;
state = runtime->state;
snd_pcm_stream_unlock_irq(substream);
if (state != SNDRV_PCM_STATE_RUNNING) {
set_current_state(TASK_RUNNING);
@@ -2854,8 +2854,8 @@ static __poll_t snd_pcm_oss_poll(struct file *file, poll_table * wait)
struct snd_pcm_runtime *runtime = psubstream->runtime;
poll_wait(file, &runtime->sleep, wait);
snd_pcm_stream_lock_irq(psubstream);
if (runtime->status->state != SNDRV_PCM_STATE_DRAINING &&
(runtime->status->state != SNDRV_PCM_STATE_RUNNING ||
if (runtime->state != SNDRV_PCM_STATE_DRAINING &&
(runtime->state != SNDRV_PCM_STATE_RUNNING ||
snd_pcm_oss_playback_ready(psubstream)))
mask |= EPOLLOUT | EPOLLWRNORM;
snd_pcm_stream_unlock_irq(psubstream);
@@ -2865,7 +2865,7 @@ static __poll_t snd_pcm_oss_poll(struct file *file, poll_table * wait)
snd_pcm_state_t ostate;
poll_wait(file, &runtime->sleep, wait);
snd_pcm_stream_lock_irq(csubstream);
ostate = runtime->status->state;
ostate = runtime->state;
if (ostate != SNDRV_PCM_STATE_RUNNING ||
snd_pcm_oss_capture_ready(csubstream))
mask |= EPOLLIN | EPOLLRDNORM;

View File

@@ -387,7 +387,7 @@ static void snd_pcm_substream_proc_hw_params_read(struct snd_info_entry *entry,
snd_iprintf(buffer, "closed\n");
goto unlock;
}
if (runtime->status->state == SNDRV_PCM_STATE_OPEN) {
if (runtime->state == SNDRV_PCM_STATE_OPEN) {
snd_iprintf(buffer, "no setup\n");
goto unlock;
}
@@ -424,7 +424,7 @@ static void snd_pcm_substream_proc_sw_params_read(struct snd_info_entry *entry,
snd_iprintf(buffer, "closed\n");
goto unlock;
}
if (runtime->status->state == SNDRV_PCM_STATE_OPEN) {
if (runtime->state == SNDRV_PCM_STATE_OPEN) {
snd_iprintf(buffer, "no setup\n");
goto unlock;
}
@@ -970,7 +970,7 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,
init_waitqueue_head(&runtime->sleep);
init_waitqueue_head(&runtime->tsleep);
runtime->status->state = SNDRV_PCM_STATE_OPEN;
__snd_pcm_set_state(runtime, SNDRV_PCM_STATE_OPEN);
mutex_init(&runtime->buffer_mutex);
atomic_set(&runtime->buffer_accessing, 0);
@@ -1112,7 +1112,8 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)
if (snd_pcm_running(substream))
snd_pcm_stop(substream, SNDRV_PCM_STATE_DISCONNECTED);
/* to be sure, set the state unconditionally */
substream->runtime->status->state = SNDRV_PCM_STATE_DISCONNECTED;
__snd_pcm_set_state(substream->runtime,
SNDRV_PCM_STATE_DISCONNECTED);
wake_up(&substream->runtime->sleep);
wake_up(&substream->runtime->tsleep);
}

View File

@@ -295,7 +295,7 @@ static int snd_pcm_ioctl_xferi_compat(struct snd_pcm_substream *substream,
return -ENOTTY;
if (substream->stream != dir)
return -EINVAL;
if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN)
if (substream->runtime->state == SNDRV_PCM_STATE_OPEN)
return -EBADFD;
if (get_user(buf, &data32->buf) ||
@@ -341,7 +341,7 @@ static int snd_pcm_ioctl_xfern_compat(struct snd_pcm_substream *substream,
return -ENOTTY;
if (substream->stream != dir)
return -EINVAL;
if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN)
if (substream->runtime->state == SNDRV_PCM_STATE_OPEN)
return -EBADFD;
ch = substream->runtime->channels;

View File

@@ -133,12 +133,14 @@ EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_set_config_from_dai_data);
static void dmaengine_pcm_dma_complete(void *arg)
{
unsigned int new_pos;
struct snd_pcm_substream *substream = arg;
struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
prtd->pos += snd_pcm_lib_period_bytes(substream);
if (prtd->pos >= snd_pcm_lib_buffer_bytes(substream))
prtd->pos = 0;
new_pos = prtd->pos + snd_pcm_lib_period_bytes(substream);
if (new_pos >= snd_pcm_lib_buffer_bytes(substream))
new_pos = 0;
prtd->pos = new_pos;
snd_pcm_period_elapsed(substream);
}

View File

@@ -186,7 +186,7 @@ int snd_pcm_update_state(struct snd_pcm_substream *substream,
avail = snd_pcm_avail(substream);
if (avail > runtime->avail_max)
runtime->avail_max = avail;
if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
if (runtime->state == SNDRV_PCM_STATE_DRAINING) {
if (avail >= runtime->buffer_size) {
snd_pcm_drain_done(substream);
return -EPIPE;
@@ -1911,7 +1911,7 @@ static int wait_for_avail(struct snd_pcm_substream *substream,
snd_pcm_stream_lock_irq(substream);
set_current_state(TASK_INTERRUPTIBLE);
switch (runtime->status->state) {
switch (runtime->state) {
case SNDRV_PCM_STATE_SUSPENDED:
err = -ESTRPIPE;
goto _endloop;
@@ -2099,14 +2099,14 @@ static int pcm_sanity_check(struct snd_pcm_substream *substream)
runtime = substream->runtime;
if (snd_BUG_ON(!substream->ops->copy_user && !runtime->dma_area))
return -EINVAL;
if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
if (runtime->state == SNDRV_PCM_STATE_OPEN)
return -EBADFD;
return 0;
}
static int pcm_accessible_state(struct snd_pcm_runtime *runtime)
{
switch (runtime->status->state) {
switch (runtime->state) {
case SNDRV_PCM_STATE_PREPARED:
case SNDRV_PCM_STATE_RUNNING:
case SNDRV_PCM_STATE_PAUSED:
@@ -2225,7 +2225,7 @@ snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream,
goto _end_unlock;
runtime->twake = runtime->control->avail_min ? : 1;
if (runtime->status->state == SNDRV_PCM_STATE_RUNNING)
if (runtime->state == SNDRV_PCM_STATE_RUNNING)
snd_pcm_update_hw_ptr(substream);
/*
@@ -2233,7 +2233,7 @@ snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream,
* thread may start capture
*/
if (!is_playback &&
runtime->status->state == SNDRV_PCM_STATE_PREPARED &&
runtime->state == SNDRV_PCM_STATE_PREPARED &&
size >= runtime->start_threshold) {
err = snd_pcm_start(substream);
if (err < 0)
@@ -2247,7 +2247,7 @@ snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream,
snd_pcm_uframes_t cont;
if (!avail) {
if (!is_playback &&
runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
runtime->state == SNDRV_PCM_STATE_DRAINING) {
snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
goto _end_unlock;
}
@@ -2303,7 +2303,7 @@ snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream,
xfer += frames;
avail -= frames;
if (is_playback &&
runtime->status->state == SNDRV_PCM_STATE_PREPARED &&
runtime->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)

View File

@@ -595,8 +595,8 @@ static void snd_pcm_set_state(struct snd_pcm_substream *substream,
snd_pcm_state_t state)
{
snd_pcm_stream_lock_irq(substream);
if (substream->runtime->status->state != SNDRV_PCM_STATE_DISCONNECTED)
substream->runtime->status->state = state;
if (substream->runtime->state != SNDRV_PCM_STATE_DISCONNECTED)
__snd_pcm_set_state(substream->runtime, state);
snd_pcm_stream_unlock_irq(substream);
}
@@ -724,7 +724,7 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
if (err < 0)
return err;
snd_pcm_stream_lock_irq(substream);
switch (runtime->status->state) {
switch (runtime->state) {
case SNDRV_PCM_STATE_OPEN:
case SNDRV_PCM_STATE_SETUP:
case SNDRV_PCM_STATE_PREPARED:
@@ -889,7 +889,7 @@ static int snd_pcm_hw_free(struct snd_pcm_substream *substream)
if (result < 0)
return result;
snd_pcm_stream_lock_irq(substream);
switch (runtime->status->state) {
switch (runtime->state) {
case SNDRV_PCM_STATE_SETUP:
case SNDRV_PCM_STATE_PREPARED:
if (atomic_read(&substream->mmap_count))
@@ -920,7 +920,7 @@ static int snd_pcm_sw_params(struct snd_pcm_substream *substream,
return -ENXIO;
runtime = substream->runtime;
snd_pcm_stream_lock_irq(substream);
if (runtime->status->state == SNDRV_PCM_STATE_OPEN) {
if (runtime->state == SNDRV_PCM_STATE_OPEN) {
snd_pcm_stream_unlock_irq(substream);
return -EBADFD;
}
@@ -1013,8 +1013,8 @@ int snd_pcm_status64(struct snd_pcm_substream *substream,
} else
runtime->audio_tstamp_report.valid = 1;
status->state = runtime->status->state;
status->suspended_state = runtime->status->suspended_state;
status->state = runtime->state;
status->suspended_state = runtime->suspended_state;
if (status->state == SNDRV_PCM_STATE_OPEN)
goto _end;
status->trigger_tstamp_sec = runtime->trigger_tstamp.tv_sec;
@@ -1148,7 +1148,7 @@ static int snd_pcm_channel_info(struct snd_pcm_substream *substream,
channel = info->channel;
runtime = substream->runtime;
snd_pcm_stream_lock_irq(substream);
if (runtime->status->state == SNDRV_PCM_STATE_OPEN) {
if (runtime->state == SNDRV_PCM_STATE_OPEN) {
snd_pcm_stream_unlock_irq(substream);
return -EBADFD;
}
@@ -1411,7 +1411,7 @@ static int snd_pcm_pre_start(struct snd_pcm_substream *substream,
snd_pcm_state_t state)
{
struct snd_pcm_runtime *runtime = substream->runtime;
if (runtime->status->state != SNDRV_PCM_STATE_PREPARED)
if (runtime->state != SNDRV_PCM_STATE_PREPARED)
return -EBADFD;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
!snd_pcm_playback_data(substream))
@@ -1444,7 +1444,7 @@ static void snd_pcm_post_start(struct snd_pcm_substream *substream,
runtime->hw_ptr_jiffies = jiffies;
runtime->hw_ptr_buffer_jiffies = (runtime->buffer_size * HZ) /
runtime->rate;
runtime->status->state = state;
__snd_pcm_set_state(runtime, state);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
runtime->silence_size > 0)
snd_pcm_playback_silence(substream, ULONG_MAX);
@@ -1485,7 +1485,7 @@ static int snd_pcm_pre_stop(struct snd_pcm_substream *substream,
snd_pcm_state_t state)
{
struct snd_pcm_runtime *runtime = substream->runtime;
if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
if (runtime->state == SNDRV_PCM_STATE_OPEN)
return -EBADFD;
runtime->trigger_master = substream;
return 0;
@@ -1506,9 +1506,9 @@ static void snd_pcm_post_stop(struct snd_pcm_substream *substream,
snd_pcm_state_t state)
{
struct snd_pcm_runtime *runtime = substream->runtime;
if (runtime->status->state != state) {
if (runtime->state != state) {
snd_pcm_trigger_tstamp(substream);
runtime->status->state = state;
__snd_pcm_set_state(runtime, state);
snd_pcm_timer_notify(substream, SNDRV_TIMER_EVENT_MSTOP);
}
wake_up(&runtime->sleep);
@@ -1584,9 +1584,9 @@ static int snd_pcm_pre_pause(struct snd_pcm_substream *substream,
if (!(runtime->info & SNDRV_PCM_INFO_PAUSE))
return -ENOSYS;
if (pause_pushed(state)) {
if (runtime->status->state != SNDRV_PCM_STATE_RUNNING)
if (runtime->state != SNDRV_PCM_STATE_RUNNING)
return -EBADFD;
} else if (runtime->status->state != SNDRV_PCM_STATE_PAUSED)
} else if (runtime->state != SNDRV_PCM_STATE_PAUSED)
return -EBADFD;
runtime->trigger_master = substream;
return 0;
@@ -1628,12 +1628,12 @@ static void snd_pcm_post_pause(struct snd_pcm_substream *substream,
struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_trigger_tstamp(substream);
if (pause_pushed(state)) {
runtime->status->state = SNDRV_PCM_STATE_PAUSED;
__snd_pcm_set_state(runtime, SNDRV_PCM_STATE_PAUSED);
snd_pcm_timer_notify(substream, SNDRV_TIMER_EVENT_MPAUSE);
wake_up(&runtime->sleep);
wake_up(&runtime->tsleep);
} else {
runtime->status->state = SNDRV_PCM_STATE_RUNNING;
__snd_pcm_set_state(runtime, SNDRV_PCM_STATE_RUNNING);
snd_pcm_timer_notify(substream, SNDRV_TIMER_EVENT_MCONTINUE);
}
}
@@ -1668,7 +1668,7 @@ static int snd_pcm_pre_suspend(struct snd_pcm_substream *substream,
snd_pcm_state_t state)
{
struct snd_pcm_runtime *runtime = substream->runtime;
switch (runtime->status->state) {
switch (runtime->state) {
case SNDRV_PCM_STATE_SUSPENDED:
return -EBUSY;
/* unresumable PCM state; return -EBUSY for skipping suspend */
@@ -1699,8 +1699,9 @@ static void snd_pcm_post_suspend(struct snd_pcm_substream *substream,
{
struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_trigger_tstamp(substream);
runtime->status->suspended_state = runtime->status->state;
runtime->status->state = SNDRV_PCM_STATE_SUSPENDED;
runtime->suspended_state = runtime->state;
runtime->status->suspended_state = runtime->suspended_state;
__snd_pcm_set_state(runtime, SNDRV_PCM_STATE_SUSPENDED);
snd_pcm_timer_notify(substream, SNDRV_TIMER_EVENT_MSUSPEND);
wake_up(&runtime->sleep);
wake_up(&runtime->tsleep);
@@ -1791,8 +1792,8 @@ static int snd_pcm_do_resume(struct snd_pcm_substream *substream,
if (runtime->trigger_master != substream)
return 0;
/* DMA not running previously? */
if (runtime->status->suspended_state != SNDRV_PCM_STATE_RUNNING &&
(runtime->status->suspended_state != SNDRV_PCM_STATE_DRAINING ||
if (runtime->suspended_state != SNDRV_PCM_STATE_RUNNING &&
(runtime->suspended_state != SNDRV_PCM_STATE_DRAINING ||
substream->stream != SNDRV_PCM_STREAM_PLAYBACK))
return 0;
return substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_RESUME);
@@ -1811,7 +1812,7 @@ static void snd_pcm_post_resume(struct snd_pcm_substream *substream,
{
struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_trigger_tstamp(substream);
runtime->status->state = runtime->status->suspended_state;
__snd_pcm_set_state(runtime, runtime->suspended_state);
snd_pcm_timer_notify(substream, SNDRV_TIMER_EVENT_MRESUME);
}
@@ -1848,7 +1849,7 @@ static int snd_pcm_xrun(struct snd_pcm_substream *substream)
int result;
snd_pcm_stream_lock_irq(substream);
switch (runtime->status->state) {
switch (runtime->state) {
case SNDRV_PCM_STATE_XRUN:
result = 0; /* already there */
break;
@@ -1871,7 +1872,7 @@ static int snd_pcm_pre_reset(struct snd_pcm_substream *substream,
snd_pcm_state_t state)
{
struct snd_pcm_runtime *runtime = substream->runtime;
switch (runtime->status->state) {
switch (runtime->state) {
case SNDRV_PCM_STATE_RUNNING:
case SNDRV_PCM_STATE_PREPARED:
case SNDRV_PCM_STATE_PAUSED:
@@ -1933,8 +1934,8 @@ static int snd_pcm_pre_prepare(struct snd_pcm_substream *substream,
struct snd_pcm_runtime *runtime = substream->runtime;
int f_flags = (__force int)state;
if (runtime->status->state == SNDRV_PCM_STATE_OPEN ||
runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED)
if (runtime->state == SNDRV_PCM_STATE_OPEN ||
runtime->state == SNDRV_PCM_STATE_DISCONNECTED)
return -EBADFD;
if (snd_pcm_running(substream))
return -EBUSY;
@@ -1985,7 +1986,7 @@ static int snd_pcm_prepare(struct snd_pcm_substream *substream,
f_flags = substream->f_flags;
snd_pcm_stream_lock_irq(substream);
switch (substream->runtime->status->state) {
switch (substream->runtime->state) {
case SNDRV_PCM_STATE_PAUSED:
snd_pcm_pause(substream, false);
fallthrough;
@@ -2009,7 +2010,7 @@ static int snd_pcm_pre_drain_init(struct snd_pcm_substream *substream,
snd_pcm_state_t state)
{
struct snd_pcm_runtime *runtime = substream->runtime;
switch (runtime->status->state) {
switch (runtime->state) {
case SNDRV_PCM_STATE_OPEN:
case SNDRV_PCM_STATE_DISCONNECTED:
case SNDRV_PCM_STATE_SUSPENDED:
@@ -2024,28 +2025,28 @@ static int snd_pcm_do_drain_init(struct snd_pcm_substream *substream,
{
struct snd_pcm_runtime *runtime = substream->runtime;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
switch (runtime->status->state) {
switch (runtime->state) {
case SNDRV_PCM_STATE_PREPARED:
/* start playback stream if possible */
if (! snd_pcm_playback_empty(substream)) {
snd_pcm_do_start(substream, SNDRV_PCM_STATE_DRAINING);
snd_pcm_post_start(substream, SNDRV_PCM_STATE_DRAINING);
} else {
runtime->status->state = SNDRV_PCM_STATE_SETUP;
__snd_pcm_set_state(runtime, SNDRV_PCM_STATE_SETUP);
}
break;
case SNDRV_PCM_STATE_RUNNING:
runtime->status->state = SNDRV_PCM_STATE_DRAINING;
__snd_pcm_set_state(runtime, SNDRV_PCM_STATE_DRAINING);
break;
case SNDRV_PCM_STATE_XRUN:
runtime->status->state = SNDRV_PCM_STATE_SETUP;
__snd_pcm_set_state(runtime, SNDRV_PCM_STATE_SETUP);
break;
default:
break;
}
} else {
/* stop running stream */
if (runtime->status->state == SNDRV_PCM_STATE_RUNNING) {
if (runtime->state == SNDRV_PCM_STATE_RUNNING) {
snd_pcm_state_t new_state;
new_state = snd_pcm_capture_avail(runtime) > 0 ?
@@ -2055,7 +2056,7 @@ static int snd_pcm_do_drain_init(struct snd_pcm_substream *substream,
}
}
if (runtime->status->state == SNDRV_PCM_STATE_DRAINING &&
if (runtime->state == SNDRV_PCM_STATE_DRAINING &&
runtime->trigger_master == substream &&
(runtime->hw.info & SNDRV_PCM_INFO_DRAIN_TRIGGER))
return substream->ops->trigger(substream,
@@ -2096,7 +2097,7 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,
card = substream->pcm->card;
runtime = substream->runtime;
if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
if (runtime->state == SNDRV_PCM_STATE_OPEN)
return -EBADFD;
if (file) {
@@ -2107,7 +2108,7 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,
snd_pcm_stream_lock_irq(substream);
/* resume pause */
if (runtime->status->state == SNDRV_PCM_STATE_PAUSED)
if (runtime->state == SNDRV_PCM_STATE_PAUSED)
snd_pcm_pause(substream, false);
/* pre-start/stop - all running streams are changed to DRAINING state */
@@ -2135,7 +2136,7 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,
if (s->stream != SNDRV_PCM_STREAM_PLAYBACK)
continue;
runtime = s->runtime;
if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
if (runtime->state == SNDRV_PCM_STATE_DRAINING) {
to_check = runtime;
break;
}
@@ -2174,7 +2175,7 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,
break;
}
if (tout == 0) {
if (substream->runtime->status->state == SNDRV_PCM_STATE_SUSPENDED)
if (substream->runtime->state == SNDRV_PCM_STATE_SUSPENDED)
result = -ESTRPIPE;
else {
dev_dbg(substream->pcm->card->dev,
@@ -2206,13 +2207,13 @@ static int snd_pcm_drop(struct snd_pcm_substream *substream)
return -ENXIO;
runtime = substream->runtime;
if (runtime->status->state == SNDRV_PCM_STATE_OPEN ||
runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED)
if (runtime->state == SNDRV_PCM_STATE_OPEN ||
runtime->state == SNDRV_PCM_STATE_DISCONNECTED)
return -EBADFD;
snd_pcm_stream_lock_irq(substream);
/* resume pause */
if (runtime->status->state == SNDRV_PCM_STATE_PAUSED)
if (runtime->state == SNDRV_PCM_STATE_PAUSED)
snd_pcm_pause(substream, false);
snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
@@ -2275,8 +2276,8 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
snd_pcm_group_init(group);
down_write(&snd_pcm_link_rwsem);
if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN ||
substream->runtime->status->state != substream1->runtime->status->state ||
if (substream->runtime->state == SNDRV_PCM_STATE_OPEN ||
substream->runtime->state != substream1->runtime->state ||
substream->pcm->nonatomic != substream1->pcm->nonatomic) {
res = -EBADFD;
goto _end;
@@ -2700,7 +2701,7 @@ void snd_pcm_release_substream(struct snd_pcm_substream *substream)
snd_pcm_drop(substream);
if (substream->hw_opened) {
if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
if (substream->runtime->state != SNDRV_PCM_STATE_OPEN)
do_hw_free(substream);
substream->ops->close(substream);
substream->hw_opened = 0;
@@ -2904,7 +2905,7 @@ static int snd_pcm_release(struct inode *inode, struct file *file)
*/
static int do_pcm_hwsync(struct snd_pcm_substream *substream)
{
switch (substream->runtime->status->state) {
switch (substream->runtime->state) {
case SNDRV_PCM_STATE_DRAINING:
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
return -EBADFD;
@@ -3203,7 +3204,7 @@ static int snd_pcm_xferi_frames_ioctl(struct snd_pcm_substream *substream,
struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_sframes_t result;
if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
if (runtime->state == SNDRV_PCM_STATE_OPEN)
return -EBADFD;
if (put_user(0, &_xferi->result))
return -EFAULT;
@@ -3226,7 +3227,7 @@ static int snd_pcm_xfern_frames_ioctl(struct snd_pcm_substream *substream,
void *bufs;
snd_pcm_sframes_t result;
if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
if (runtime->state == SNDRV_PCM_STATE_OPEN)
return -EBADFD;
if (runtime->channels > 128)
return -EINVAL;
@@ -3290,7 +3291,7 @@ static int snd_pcm_common_ioctl(struct file *file,
if (PCM_RUNTIME_CHECK(substream))
return -ENXIO;
if (substream->runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED)
if (substream->runtime->state == SNDRV_PCM_STATE_DISCONNECTED)
return -EBADFD;
res = snd_power_wait(substream->pcm->card);
@@ -3421,7 +3422,7 @@ int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream,
snd_pcm_uframes_t *frames = arg;
snd_pcm_sframes_t result;
if (substream->runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED)
if (substream->runtime->state == SNDRV_PCM_STATE_DISCONNECTED)
return -EBADFD;
switch (cmd) {
@@ -3466,8 +3467,8 @@ static ssize_t snd_pcm_read(struct file *file, char __user *buf, size_t count,
if (PCM_RUNTIME_CHECK(substream))
return -ENXIO;
runtime = substream->runtime;
if (runtime->status->state == SNDRV_PCM_STATE_OPEN ||
runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED)
if (runtime->state == SNDRV_PCM_STATE_OPEN ||
runtime->state == SNDRV_PCM_STATE_DISCONNECTED)
return -EBADFD;
if (!frame_aligned(runtime, count))
return -EINVAL;
@@ -3491,8 +3492,8 @@ static ssize_t snd_pcm_write(struct file *file, const char __user *buf,
if (PCM_RUNTIME_CHECK(substream))
return -ENXIO;
runtime = substream->runtime;
if (runtime->status->state == SNDRV_PCM_STATE_OPEN ||
runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED)
if (runtime->state == SNDRV_PCM_STATE_OPEN ||
runtime->state == SNDRV_PCM_STATE_DISCONNECTED)
return -EBADFD;
if (!frame_aligned(runtime, count))
return -EINVAL;
@@ -3518,8 +3519,8 @@ static ssize_t snd_pcm_readv(struct kiocb *iocb, struct iov_iter *to)
if (PCM_RUNTIME_CHECK(substream))
return -ENXIO;
runtime = substream->runtime;
if (runtime->status->state == SNDRV_PCM_STATE_OPEN ||
runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED)
if (runtime->state == SNDRV_PCM_STATE_OPEN ||
runtime->state == SNDRV_PCM_STATE_DISCONNECTED)
return -EBADFD;
if (!iter_is_iovec(to))
return -EINVAL;
@@ -3555,8 +3556,8 @@ static ssize_t snd_pcm_writev(struct kiocb *iocb, struct iov_iter *from)
if (PCM_RUNTIME_CHECK(substream))
return -ENXIO;
runtime = substream->runtime;
if (runtime->status->state == SNDRV_PCM_STATE_OPEN ||
runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED)
if (runtime->state == SNDRV_PCM_STATE_OPEN ||
runtime->state == SNDRV_PCM_STATE_DISCONNECTED)
return -EBADFD;
if (!iter_is_iovec(from))
return -EINVAL;
@@ -3595,7 +3596,7 @@ static __poll_t snd_pcm_poll(struct file *file, poll_table *wait)
return ok | EPOLLERR;
runtime = substream->runtime;
if (runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED)
if (runtime->state == SNDRV_PCM_STATE_DISCONNECTED)
return ok | EPOLLERR;
poll_wait(file, &runtime->sleep, wait);
@@ -3603,7 +3604,7 @@ static __poll_t snd_pcm_poll(struct file *file, poll_table *wait)
mask = 0;
snd_pcm_stream_lock_irq(substream);
avail = snd_pcm_avail(substream);
switch (runtime->status->state) {
switch (runtime->state) {
case SNDRV_PCM_STATE_RUNNING:
case SNDRV_PCM_STATE_PREPARED:
case SNDRV_PCM_STATE_PAUSED:
@@ -3667,6 +3668,7 @@ static int snd_pcm_mmap_status(struct snd_pcm_substream *substream, struct file
area->vm_ops = &snd_pcm_vm_ops_status;
area->vm_private_data = substream;
area->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
area->vm_flags &= ~(VM_WRITE | VM_MAYWRITE);
return 0;
}
@@ -3874,7 +3876,7 @@ int snd_pcm_mmap_data(struct snd_pcm_substream *substream, struct file *file,
return -EINVAL;
}
runtime = substream->runtime;
if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
if (runtime->state == SNDRV_PCM_STATE_OPEN)
return -EBADFD;
if (!(runtime->info & SNDRV_PCM_INFO_MMAP))
return -ENXIO;
@@ -3911,7 +3913,7 @@ static int snd_pcm_mmap(struct file *file, struct vm_area_struct *area)
substream = pcm_file->substream;
if (PCM_RUNTIME_CHECK(substream))
return -ENXIO;
if (substream->runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED)
if (substream->runtime->state == SNDRV_PCM_STATE_DISCONNECTED)
return -EBADFD;
offset = area->vm_pgoff << PAGE_SHIFT;
@@ -3949,7 +3951,7 @@ static int snd_pcm_fasync(int fd, struct file * file, int on)
if (PCM_RUNTIME_CHECK(substream))
return -ENXIO;
runtime = substream->runtime;
if (runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED)
if (runtime->state == SNDRV_PCM_STATE_DISCONNECTED)
return -EBADFD;
return snd_fasync_helper(fd, file, on, &runtime->fasync);
}

View File

@@ -535,7 +535,7 @@ static void copy_play_buf(struct loopback_pcm *play,
/* check if playback is draining, trim the capture copy size
* when our pointer is at the end of playback ring buffer */
if (runtime->status->state == SNDRV_PCM_STATE_DRAINING &&
if (runtime->state == SNDRV_PCM_STATE_DRAINING &&
snd_pcm_playback_hw_avail(runtime) < runtime->buffer_size) {
snd_pcm_uframes_t appl_ptr, appl_ptr1, diff;
appl_ptr = appl_ptr1 = runtime->control->appl_ptr;
@@ -730,7 +730,7 @@ static void loopback_snd_timer_period_elapsed(struct loopback_cable *cable,
if (event == SNDRV_TIMER_EVENT_MSTOP) {
if (!dpcm_play ||
dpcm_play->substream->runtime->status->state !=
dpcm_play->substream->runtime->state !=
SNDRV_PCM_STATE_DRAINING) {
spin_unlock_irqrestore(&cable->lock, flags);
return;

View File

@@ -42,6 +42,8 @@ MODULE_LICENSE("GPL");
#define USE_CHANNELS_MAX 2
#define USE_PERIODS_MIN 1
#define USE_PERIODS_MAX 1024
#define USE_MIXER_VOLUME_LEVEL_MIN -50
#define USE_MIXER_VOLUME_LEVEL_MAX 100
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
@@ -50,6 +52,8 @@ static char *model[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = NULL};
static int pcm_devs[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};
static int pcm_substreams[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 8};
//static int midi_devs[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2};
static int mixer_volume_level_min = USE_MIXER_VOLUME_LEVEL_MIN;
static int mixer_volume_level_max = USE_MIXER_VOLUME_LEVEL_MAX;
#ifdef CONFIG_HIGH_RES_TIMERS
static bool hrtimer = 1;
#endif
@@ -69,6 +73,10 @@ module_param_array(pcm_substreams, int, NULL, 0444);
MODULE_PARM_DESC(pcm_substreams, "PCM substreams # (1-128) for dummy driver.");
//module_param_array(midi_devs, int, NULL, 0444);
//MODULE_PARM_DESC(midi_devs, "MIDI devices # (0-2) for dummy driver.");
module_param(mixer_volume_level_min, int, 0444);
MODULE_PARM_DESC(mixer_volume_level_min, "Minimum mixer volume level for dummy driver. Default: -50");
module_param(mixer_volume_level_max, int, 0444);
MODULE_PARM_DESC(mixer_volume_level_max, "Maximum mixer volume level for dummy driver. Default: 100");
module_param(fake_buffer, bool, 0444);
MODULE_PARM_DESC(fake_buffer, "Fake buffer allocations.");
#ifdef CONFIG_HIGH_RES_TIMERS
@@ -296,7 +304,7 @@ static void dummy_systimer_callback(struct timer_list *t)
struct dummy_systimer_pcm *dpcm = from_timer(dpcm, t, timer);
unsigned long flags;
int elapsed = 0;
spin_lock_irqsave(&dpcm->lock, flags);
dummy_systimer_update(dpcm);
dummy_systimer_rearm(dpcm);
@@ -713,11 +721,11 @@ static int snd_dummy_volume_info(struct snd_kcontrol *kcontrol,
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 2;
uinfo->value.integer.min = -50;
uinfo->value.integer.max = 100;
uinfo->value.integer.min = mixer_volume_level_min;
uinfo->value.integer.max = mixer_volume_level_max;
return 0;
}
static int snd_dummy_volume_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -739,15 +747,15 @@ static int snd_dummy_volume_put(struct snd_kcontrol *kcontrol,
int left, right;
left = ucontrol->value.integer.value[0];
if (left < -50)
left = -50;
if (left > 100)
left = 100;
if (left < mixer_volume_level_min)
left = mixer_volume_level_min;
if (left > mixer_volume_level_max)
left = mixer_volume_level_max;
right = ucontrol->value.integer.value[1];
if (right < -50)
right = -50;
if (right > 100)
right = 100;
if (right < mixer_volume_level_min)
right = mixer_volume_level_min;
if (right > mixer_volume_level_max)
right = mixer_volume_level_max;
spin_lock_irq(&dummy->mixer_lock);
change = dummy->mixer_volume[addr][0] != left ||
dummy->mixer_volume[addr][1] != right;
@@ -766,7 +774,7 @@ static const DECLARE_TLV_DB_SCALE(db_scale_dummy, -4500, 30, 0);
.private_value = addr }
#define snd_dummy_capsrc_info snd_ctl_boolean_stereo_info
static int snd_dummy_capsrc_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -1076,6 +1084,12 @@ static int snd_dummy_probe(struct platform_device *devptr)
dummy->pcm_hw.channels_max = m->channels_max;
}
if (mixer_volume_level_min > mixer_volume_level_max) {
pr_warn("snd-dummy: Invalid mixer volume level: min=%d, max=%d. Fall back to default value.\n",
mixer_volume_level_min, mixer_volume_level_max);
mixer_volume_level_min = USE_MIXER_VOLUME_LEVEL_MIN;
mixer_volume_level_max = USE_MIXER_VOLUME_LEVEL_MAX;
}
err = snd_card_dummy_new_mixer(dummy);
if (err < 0)
return err;
@@ -1100,7 +1114,7 @@ static int snd_dummy_suspend(struct device *pdev)
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
return 0;
}
static int snd_dummy_resume(struct device *pdev)
{
struct snd_card *card = dev_get_drvdata(pdev);

View File

@@ -1215,8 +1215,7 @@ int snd_vx_pcm_new(struct vx_core *chip)
if (ins)
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &vx_pcm_capture_ops);
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC,
snd_dma_continuous_data(GFP_KERNEL | GFP_DMA32),
0, 0);
NULL, 0, 0);
pcm->private_data = chip;
pcm->private_free = snd_vx_pcm_free;

View File

@@ -214,7 +214,7 @@ static int pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_bebob *bebob = substream->private_data;
int err = 0;
if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
if (substream->runtime->state == SNDRV_PCM_STATE_OPEN) {
unsigned int rate = params_rate(hw_params);
unsigned int frames_per_period = params_period_size(hw_params);
unsigned int frames_per_buffer = params_buffer_size(hw_params);
@@ -236,7 +236,7 @@ static int pcm_hw_free(struct snd_pcm_substream *substream)
mutex_lock(&bebob->mutex);
if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
if (substream->runtime->state != SNDRV_PCM_STATE_OPEN)
bebob->substreams_counter--;
snd_bebob_stream_stop_duplex(bebob);

View File

@@ -2,8 +2,6 @@
// dice-harman.c - a part of driver for DICE based devices
//
// Copyright (c) 2021 Takashi Sakamoto
//
// Licensed under the terms of the GNU General Public License, version 2.
#include "dice.h"

View File

@@ -266,7 +266,7 @@ static int pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_dice *dice = substream->private_data;
int err = 0;
if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
if (substream->runtime->state == SNDRV_PCM_STATE_OPEN) {
unsigned int rate = params_rate(hw_params);
unsigned int events_per_period = params_period_size(hw_params);
unsigned int events_per_buffer = params_buffer_size(hw_params);
@@ -293,7 +293,7 @@ static int pcm_hw_free(struct snd_pcm_substream *substream)
mutex_lock(&dice->mutex);
if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
if (substream->runtime->state != SNDRV_PCM_STATE_OPEN)
--dice->substreams_counter;
snd_dice_stream_stop_duplex(dice);

View File

@@ -2,8 +2,6 @@
// dice-presonus.c - a part of driver for DICE based devices
//
// Copyright (c) 2019 Takashi Sakamoto
//
// Licensed under the terms of the GNU General Public License, version 2.
#include "dice.h"

View File

@@ -190,7 +190,7 @@ static int pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_dg00x *dg00x = substream->private_data;
int err = 0;
if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
if (substream->runtime->state == SNDRV_PCM_STATE_OPEN) {
unsigned int rate = params_rate(hw_params);
unsigned int frames_per_period = params_period_size(hw_params);
unsigned int frames_per_buffer = params_buffer_size(hw_params);
@@ -212,7 +212,7 @@ static int pcm_hw_free(struct snd_pcm_substream *substream)
mutex_lock(&dg00x->mutex);
if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
if (substream->runtime->state != SNDRV_PCM_STATE_OPEN)
--dg00x->substreams_counter;
snd_dg00x_stream_stop_duplex(dg00x);

View File

@@ -230,7 +230,7 @@ static int pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_ff *ff = substream->private_data;
int err = 0;
if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
if (substream->runtime->state == SNDRV_PCM_STATE_OPEN) {
unsigned int rate = params_rate(hw_params);
unsigned int frames_per_period = params_period_size(hw_params);
unsigned int frames_per_buffer = params_buffer_size(hw_params);
@@ -252,7 +252,7 @@ static int pcm_hw_free(struct snd_pcm_substream *substream)
mutex_lock(&ff->mutex);
if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
if (substream->runtime->state != SNDRV_PCM_STATE_OPEN)
--ff->substreams_counter;
snd_ff_stream_stop_duplex(ff);

View File

@@ -2,8 +2,6 @@
// ff-protocol-former.c - a part of driver for RME Fireface series
//
// Copyright (c) 2019 Takashi Sakamoto
//
// Licensed under the terms of the GNU General Public License, version 2.
#include <linux/delay.h>

View File

@@ -1,9 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
// ff-protocol-latter - a part of driver for RME Fireface series
// ff-protocol-latter.c - a part of driver for RME Fireface series
//
// Copyright (c) 2019 Takashi Sakamoto
//
// Licensed under the terms of the GNU General Public License, version 2.
#include <linux/delay.h>

View File

@@ -250,7 +250,7 @@ static int pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_efw *efw = substream->private_data;
int err = 0;
if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
if (substream->runtime->state == SNDRV_PCM_STATE_OPEN) {
unsigned int rate = params_rate(hw_params);
unsigned int frames_per_period = params_period_size(hw_params);
unsigned int frames_per_buffer = params_buffer_size(hw_params);
@@ -272,7 +272,7 @@ static int pcm_hw_free(struct snd_pcm_substream *substream)
mutex_lock(&efw->mutex);
if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
if (substream->runtime->state != SNDRV_PCM_STATE_OPEN)
--efw->substreams_counter;
snd_efw_stream_stop_duplex(efw);

View File

@@ -210,7 +210,7 @@ static int pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_motu *motu = substream->private_data;
int err = 0;
if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
if (substream->runtime->state == SNDRV_PCM_STATE_OPEN) {
unsigned int rate = params_rate(hw_params);
unsigned int frames_per_period = params_period_size(hw_params);
unsigned int frames_per_buffer = params_buffer_size(hw_params);
@@ -232,7 +232,7 @@ static int pcm_hw_free(struct snd_pcm_substream *substream)
mutex_lock(&motu->mutex);
if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
if (substream->runtime->state != SNDRV_PCM_STATE_OPEN)
--motu->substreams_counter;
snd_motu_stream_stop_duplex(motu);

View File

@@ -1,10 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
// motu-protocol-v1.c - a part of driver for MOTU FireWire series
//
// Copyright (c) 2021 Takashi Sakamoto <o-takashi@sakamocchi.jp>
//
// Licensed under the terms of the GNU General Public License, version 2.
#include "motu.h"

View File

@@ -239,7 +239,7 @@ static int pcm_capture_hw_params(struct snd_pcm_substream *substream,
struct snd_oxfw *oxfw = substream->private_data;
int err = 0;
if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
if (substream->runtime->state == SNDRV_PCM_STATE_OPEN) {
unsigned int rate = params_rate(hw_params);
unsigned int channels = params_channels(hw_params);
unsigned int frames_per_period = params_period_size(hw_params);
@@ -262,7 +262,7 @@ static int pcm_playback_hw_params(struct snd_pcm_substream *substream,
struct snd_oxfw *oxfw = substream->private_data;
int err = 0;
if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
if (substream->runtime->state == SNDRV_PCM_STATE_OPEN) {
unsigned int rate = params_rate(hw_params);
unsigned int channels = params_channels(hw_params);
unsigned int frames_per_period = params_period_size(hw_params);
@@ -286,7 +286,7 @@ static int pcm_capture_hw_free(struct snd_pcm_substream *substream)
mutex_lock(&oxfw->mutex);
if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
if (substream->runtime->state != SNDRV_PCM_STATE_OPEN)
--oxfw->substreams_count;
snd_oxfw_stream_stop_duplex(oxfw);
@@ -301,7 +301,7 @@ static int pcm_playback_hw_free(struct snd_pcm_substream *substream)
mutex_lock(&oxfw->mutex);
if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
if (substream->runtime->state != SNDRV_PCM_STATE_OPEN)
--oxfw->substreams_count;
snd_oxfw_stream_stop_duplex(oxfw);

View File

@@ -119,7 +119,7 @@ static int pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_tscm *tscm = substream->private_data;
int err = 0;
if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
if (substream->runtime->state == SNDRV_PCM_STATE_OPEN) {
unsigned int rate = params_rate(hw_params);
unsigned int frames_per_period = params_period_size(hw_params);
unsigned int frames_per_buffer = params_buffer_size(hw_params);
@@ -141,7 +141,7 @@ static int pcm_hw_free(struct snd_pcm_substream *substream)
mutex_lock(&tscm->mutex);
if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
if (substream->runtime->state != SNDRV_PCM_STATE_OPEN)
--tscm->substreams_counter;
snd_tscm_stream_stop_duplex(tscm);

View File

@@ -60,59 +60,6 @@ void snd_hdac_ext_bus_exit(struct hdac_bus *bus)
}
EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_exit);
static void default_release(struct device *dev)
{
snd_hdac_ext_bus_device_exit(dev_to_hdac_dev(dev));
}
/**
* snd_hdac_ext_bus_device_init - initialize the HDA extended codec base device
* @bus: hdac bus to attach to
* @addr: codec address
* @hdev: hdac device to init
* @type: codec type (HDAC_DEV_*) to use for this device
*
* Returns zero for success or a negative error code.
*/
int snd_hdac_ext_bus_device_init(struct hdac_bus *bus, int addr,
struct hdac_device *hdev, int type)
{
char name[15];
int ret;
hdev->bus = bus;
snprintf(name, sizeof(name), "ehdaudio%dD%d", bus->idx, addr);
ret = snd_hdac_device_init(hdev, bus, name, addr);
if (ret < 0) {
dev_err(bus->dev, "device init failed for hdac device\n");
return ret;
}
hdev->type = type;
hdev->dev.release = default_release;
ret = snd_hdac_device_register(hdev);
if (ret) {
dev_err(bus->dev, "failed to register hdac device\n");
snd_hdac_ext_bus_device_exit(hdev);
return ret;
}
return 0;
}
EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_device_init);
/**
* snd_hdac_ext_bus_device_exit - clean up a HD-audio extended codec base device
* @hdev: hdac device to clean up
*/
void snd_hdac_ext_bus_device_exit(struct hdac_device *hdev)
{
snd_hdac_device_exit(hdev);
}
EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_device_exit);
/**
* snd_hdac_ext_bus_device_remove - remove HD-audio extended codec base devices
*

View File

@@ -170,7 +170,7 @@ static int check_hdac_link_power_active(struct hdac_ext_link *link, bool enable)
{
int timeout;
u32 val;
int mask = (1 << AZX_MLCTL_CPA_SHIFT);
int mask = (1 << AZX_ML_LCTL_CPA_SHIFT);
udelay(3);
timeout = 150;
@@ -178,10 +178,10 @@ static int check_hdac_link_power_active(struct hdac_ext_link *link, bool enable)
do {
val = readl(link->ml_addr + AZX_REG_ML_LCTL);
if (enable) {
if (((val & mask) >> AZX_MLCTL_CPA_SHIFT))
if (((val & mask) >> AZX_ML_LCTL_CPA_SHIFT))
return 0;
} else {
if (!((val & mask) >> AZX_MLCTL_CPA_SHIFT))
if (!((val & mask) >> AZX_ML_LCTL_CPA_SHIFT))
return 0;
}
udelay(3);
@@ -197,7 +197,7 @@ static int check_hdac_link_power_active(struct hdac_ext_link *link, bool enable)
int snd_hdac_ext_bus_link_power_up(struct hdac_ext_link *link)
{
snd_hdac_updatel(link->ml_addr, AZX_REG_ML_LCTL,
AZX_MLCTL_SPA, AZX_MLCTL_SPA);
AZX_ML_LCTL_SPA, AZX_ML_LCTL_SPA);
return check_hdac_link_power_active(link, true);
}
@@ -209,7 +209,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_link_power_up);
*/
int snd_hdac_ext_bus_link_power_down(struct hdac_ext_link *link)
{
snd_hdac_updatel(link->ml_addr, AZX_REG_ML_LCTL, AZX_MLCTL_SPA, 0);
snd_hdac_updatel(link->ml_addr, AZX_REG_ML_LCTL, AZX_ML_LCTL_SPA, 0);
return check_hdac_link_power_active(link, false);
}
@@ -226,7 +226,7 @@ int snd_hdac_ext_bus_link_power_up_all(struct hdac_bus *bus)
list_for_each_entry(hlink, &bus->hlink_list, list) {
snd_hdac_updatel(hlink->ml_addr, AZX_REG_ML_LCTL,
AZX_MLCTL_SPA, AZX_MLCTL_SPA);
AZX_ML_LCTL_SPA, AZX_ML_LCTL_SPA);
ret = check_hdac_link_power_active(hlink, true);
if (ret < 0)
return ret;
@@ -247,7 +247,7 @@ int snd_hdac_ext_bus_link_power_down_all(struct hdac_bus *bus)
list_for_each_entry(hlink, &bus->hlink_list, list) {
snd_hdac_updatel(hlink->ml_addr, AZX_REG_ML_LCTL,
AZX_MLCTL_SPA, 0);
AZX_ML_LCTL_SPA, 0);
ret = check_hdac_link_power_active(hlink, false);
if (ret < 0)
return ret;
@@ -281,7 +281,7 @@ int snd_hdac_ext_bus_link_get(struct hdac_bus *bus,
* clear the register to invalidate all the output streams
*/
snd_hdac_updatew(link->ml_addr, AZX_REG_ML_LOSIDV,
ML_LOSIDV_STREAM_MASK, 0);
AZX_ML_LOSIDV_STREAM_MASK, 0);
/*
* wait for 521usec for codec to report status
* HDA spec section 4.3 - Codec Discovery

View File

@@ -26,9 +26,9 @@
* initialize the stream, if ppcap is enabled then init those and then
* invoke hdac stream initialization routine
*/
void snd_hdac_ext_stream_init(struct hdac_bus *bus,
struct hdac_ext_stream *hext_stream,
int idx, int direction, int tag)
static void snd_hdac_ext_stream_init(struct hdac_bus *bus,
struct hdac_ext_stream *hext_stream,
int idx, int direction, int tag)
{
if (bus->ppcap) {
hext_stream->pphc_addr = bus->ppcap + AZX_PPHC_BASE +
@@ -56,7 +56,6 @@ void snd_hdac_ext_stream_init(struct hdac_bus *bus,
hext_stream->decoupled = false;
snd_hdac_stream_init(bus, &hext_stream->hstream, idx, direction, tag);
}
EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_init);
/**
* snd_hdac_ext_stream_init_all - create and initialize the stream objects
@@ -88,11 +87,11 @@ int snd_hdac_ext_stream_init_all(struct hdac_bus *bus, int start_idx,
EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_init_all);
/**
* snd_hdac_stream_free_all - free hdac extended stream objects
* snd_hdac_ext_stream_free_all - free hdac extended stream objects
*
* @bus: HD-audio core bus
*/
void snd_hdac_stream_free_all(struct hdac_bus *bus)
void snd_hdac_ext_stream_free_all(struct hdac_bus *bus)
{
struct hdac_stream *s, *_s;
struct hdac_ext_stream *hext_stream;
@@ -104,7 +103,7 @@ void snd_hdac_stream_free_all(struct hdac_bus *bus)
kfree(hext_stream);
}
}
EXPORT_SYMBOL_GPL(snd_hdac_stream_free_all);
EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_free_all);
void snd_hdac_ext_stream_decouple_locked(struct hdac_bus *bus,
struct hdac_ext_stream *hext_stream,
@@ -268,19 +267,15 @@ hdac_ext_link_stream_assign(struct hdac_bus *bus,
if (hstream->direction != substream->stream)
continue;
/* check if decoupled stream and not in use is available */
if (hext_stream->decoupled && !hext_stream->link_locked) {
/* check if link stream is available */
if (!hext_stream->link_locked) {
res = hext_stream;
break;
}
if (!hext_stream->link_locked) {
snd_hdac_ext_stream_decouple_locked(bus, hext_stream, true);
res = hext_stream;
break;
}
}
if (res) {
snd_hdac_ext_stream_decouple_locked(bus, res, true);
res->link_locked = 1;
res->link_substream = substream;
}
@@ -309,13 +304,12 @@ hdac_ext_host_stream_assign(struct hdac_bus *bus,
continue;
if (!hstream->opened) {
if (!hext_stream->decoupled)
snd_hdac_ext_stream_decouple_locked(bus, hext_stream, true);
res = hext_stream;
break;
}
}
if (res) {
snd_hdac_ext_stream_decouple_locked(bus, res, true);
res->hstream.opened = 1;
res->hstream.running = 0;
res->hstream.substream = substream;
@@ -388,15 +382,17 @@ void snd_hdac_ext_stream_release(struct hdac_ext_stream *hext_stream, int type)
case HDAC_EXT_STREAM_TYPE_HOST:
spin_lock_irq(&bus->reg_lock);
if (hext_stream->decoupled && !hext_stream->link_locked)
/* couple link only if not in use */
if (!hext_stream->link_locked)
snd_hdac_ext_stream_decouple_locked(bus, hext_stream, false);
snd_hdac_stream_release_locked(&hext_stream->hstream);
spin_unlock_irq(&bus->reg_lock);
snd_hdac_stream_release(&hext_stream->hstream);
break;
case HDAC_EXT_STREAM_TYPE_LINK:
spin_lock_irq(&bus->reg_lock);
if (hext_stream->decoupled && !hext_stream->hstream.opened)
/* couple host only if not in use */
if (!hext_stream->hstream.opened)
snd_hdac_ext_stream_decouple_locked(bus, hext_stream, false);
hext_stream->link_locked = 0;
hext_stream->link_substream = NULL;

View File

@@ -13,6 +13,39 @@
#include <sound/hda_register.h>
#include "trace.h"
/*
* the hdac_stream library is intended to be used with the following
* transitions. The states are not formally defined in the code but loosely
* inspired by boolean variables. Note that the 'prepared' field is not used
* in this library but by the callers during the hw_params/prepare transitions
*
* |
* stream_init() |
* v
* +--+-------+
* | unused |
* +--+----+--+
* | ^
* stream_assign() | | stream_release()
* v |
* +--+----+--+
* | opened |
* +--+----+--+
* | ^
* stream_reset() | |
* stream_setup() | | stream_cleanup()
* v |
* +--+----+--+
* | prepared |
* +--+----+--+
* | ^
* stream_start() | | stream_stop()
* v |
* +--+----+--+
* | running |
* +----------+
*/
/**
* snd_hdac_get_stream_stripe_ctl - get stripe control value
* @bus: HD-audio core bus
@@ -112,10 +145,10 @@ void snd_hdac_stream_start(struct hdac_stream *azx_dev, bool fresh_start)
EXPORT_SYMBOL_GPL(snd_hdac_stream_start);
/**
* snd_hdac_stream_clear - stop a stream DMA
* snd_hdac_stream_clear - helper to clear stream registers and stop DMA transfers
* @azx_dev: HD-audio core stream to stop
*/
void snd_hdac_stream_clear(struct hdac_stream *azx_dev)
static void snd_hdac_stream_clear(struct hdac_stream *azx_dev)
{
snd_hdac_stream_updateb(azx_dev, SD_CTL,
SD_CTL_DMA_START | SD_INT_MASK, 0);
@@ -124,7 +157,6 @@ void snd_hdac_stream_clear(struct hdac_stream *azx_dev)
snd_hdac_stream_updateb(azx_dev, SD_CTL_3B, SD_CTL_STRIPE_MASK, 0);
azx_dev->running = false;
}
EXPORT_SYMBOL_GPL(snd_hdac_stream_clear);
/**
* snd_hdac_stream_stop - stop a stream
@@ -142,17 +174,28 @@ void snd_hdac_stream_stop(struct hdac_stream *azx_dev)
}
EXPORT_SYMBOL_GPL(snd_hdac_stream_stop);
/**
* snd_hdac_stop_streams - stop all streams
* @bus: HD-audio core bus
*/
void snd_hdac_stop_streams(struct hdac_bus *bus)
{
struct hdac_stream *stream;
list_for_each_entry(stream, &bus->stream_list, list)
snd_hdac_stream_stop(stream);
}
EXPORT_SYMBOL_GPL(snd_hdac_stop_streams);
/**
* snd_hdac_stop_streams_and_chip - stop all streams and chip if running
* @bus: HD-audio core bus
*/
void snd_hdac_stop_streams_and_chip(struct hdac_bus *bus)
{
struct hdac_stream *stream;
if (bus->chip_init) {
list_for_each_entry(stream, &bus->stream_list, list)
snd_hdac_stream_stop(stream);
snd_hdac_stop_streams(bus);
snd_hdac_bus_stop_chip(bus);
}
}
@@ -165,7 +208,6 @@ EXPORT_SYMBOL_GPL(snd_hdac_stop_streams_and_chip);
void snd_hdac_stream_reset(struct hdac_stream *azx_dev)
{
unsigned char val;
int timeout;
int dma_run_state;
snd_hdac_stream_clear(azx_dev);
@@ -173,30 +215,17 @@ void snd_hdac_stream_reset(struct hdac_stream *azx_dev)
dma_run_state = snd_hdac_stream_readb(azx_dev, SD_CTL) & SD_CTL_DMA_START;
snd_hdac_stream_updateb(azx_dev, SD_CTL, 0, SD_CTL_STREAM_RESET);
udelay(3);
timeout = 300;
do {
val = snd_hdac_stream_readb(azx_dev, SD_CTL) &
SD_CTL_STREAM_RESET;
if (val)
break;
} while (--timeout);
/* wait for hardware to report that the stream entered reset */
snd_hdac_stream_readb_poll(azx_dev, SD_CTL, val, (val & SD_CTL_STREAM_RESET), 3, 300);
if (azx_dev->bus->dma_stop_delay && dma_run_state)
udelay(azx_dev->bus->dma_stop_delay);
val &= ~SD_CTL_STREAM_RESET;
snd_hdac_stream_writeb(azx_dev, SD_CTL, val);
udelay(3);
snd_hdac_stream_updateb(azx_dev, SD_CTL, SD_CTL_STREAM_RESET, 0);
timeout = 300;
/* waiting for hardware to report that the stream is out of reset */
do {
val = snd_hdac_stream_readb(azx_dev, SD_CTL) &
SD_CTL_STREAM_RESET;
if (!val)
break;
} while (--timeout);
/* wait for hardware to report that the stream is out of reset */
snd_hdac_stream_readb_poll(azx_dev, SD_CTL, val, !(val & SD_CTL_STREAM_RESET), 3, 300);
/* reset first position - may not be synced with hw at this time */
if (azx_dev->posbuf)
@@ -336,6 +365,21 @@ struct hdac_stream *snd_hdac_stream_assign(struct hdac_bus *bus,
}
EXPORT_SYMBOL_GPL(snd_hdac_stream_assign);
/**
* snd_hdac_stream_release_locked - release the assigned stream
* @azx_dev: HD-audio core stream to release
*
* Release the stream that has been assigned by snd_hdac_stream_assign().
* The bus->reg_lock needs to be taken at a higher level
*/
void snd_hdac_stream_release_locked(struct hdac_stream *azx_dev)
{
azx_dev->opened = 0;
azx_dev->running = 0;
azx_dev->substream = NULL;
}
EXPORT_SYMBOL_GPL(snd_hdac_stream_release_locked);
/**
* snd_hdac_stream_release - release the assigned stream
* @azx_dev: HD-audio core stream to release
@@ -347,9 +391,7 @@ void snd_hdac_stream_release(struct hdac_stream *azx_dev)
struct hdac_bus *bus = azx_dev->bus;
spin_lock_irq(&bus->reg_lock);
azx_dev->opened = 0;
azx_dev->running = 0;
azx_dev->substream = NULL;
snd_hdac_stream_release_locked(azx_dev);
spin_unlock_irq(&bus->reg_lock);
}
EXPORT_SYMBOL_GPL(snd_hdac_stream_release);

View File

@@ -774,7 +774,7 @@ static int hdmi_chmap_ctl_put(struct snd_kcontrol *kcontrol,
substream = snd_pcm_chmap_substream(info, ctl_idx);
if (!substream || !substream->runtime)
return 0; /* just for avoiding error from alsactl restore */
switch (substream->runtime->status->state) {
switch (substream->runtime->state) {
case SNDRV_PCM_STATE_OPEN:
case SNDRV_PCM_STATE_SETUP:
break;

View File

@@ -1344,11 +1344,8 @@ ES18XX_SINGLE("GPO1 Switch", 0, ES18XX_PM, 1, 1, ES18XX_FL_PMPORT),
static int snd_es18xx_config_read(struct snd_es18xx *chip, unsigned char reg)
{
int data;
outb(reg, chip->ctrl_port);
data = inb(chip->ctrl_port + 1);
return data;
return inb(chip->ctrl_port + 1);
}
static void snd_es18xx_config_write(struct snd_es18xx *chip,

View File

@@ -236,7 +236,7 @@ static int emu8k_pcm_open(struct snd_pcm_substream *subs)
/* use timer to update periods.. (specified in msec) */
snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME,
(1000000 + HZ - 1) / HZ, UINT_MAX);
DIV_ROUND_UP(1000000, HZ), UINT_MAX);
return 0;
}

View File

@@ -250,7 +250,4 @@ extern int dmasound_catchRadius;
#define SW_INPUT_VOLUME_SCALE 4
#define SW_INPUT_VOLUME_DEFAULT (128 / SW_INPUT_VOLUME_SCALE)
extern int expand_read_bal; /* Balance factor for reading */
extern uint software_input_volume; /* software implemented recording volume! */
#endif /* _dmasound_h_ */

View File

@@ -632,7 +632,7 @@ static int snd_card_asihpi_trigger(struct snd_pcm_substream *substream,
/*? workaround linked streams don't
transition to SETUP 20070706*/
s->runtime->status->state = SNDRV_PCM_STATE_SETUP;
__snd_pcm_set_state(s->runtime, SNDRV_PCM_STATE_SETUP);
if (card->support_grouping) {
snd_printdd("%d group\n", s->number);

View File

@@ -2020,7 +2020,6 @@ u16 hpi_meter_get_peak(u32 h_control, short an_peakdB[HPI_MAX_CHANNELS]
HPI_CONTROL_GET_STATE);
if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index))
return HPI_ERROR_INVALID_HANDLE;
hm.obj_index = hm.obj_index;
hm.u.c.attribute = HPI_METER_PEAK;
hpi_send_recv(&hm, &hr);

View File

@@ -93,11 +93,6 @@ static void HPIMSGX__cleanup(u16 adapter_index, void *h_owner);
#pragma pack(push, 1)
#endif
struct hpi_subsys_response {
struct hpi_response_header h;
struct hpi_subsys_res s;
};
struct hpi_adapter_response {
struct hpi_response_header h;
struct hpi_adapter_res a;

View File

@@ -842,8 +842,8 @@ static int cs35l41_hda_bind(struct device *dev, struct device *master, void *mas
comps->dev = dev;
if (!cs35l41->acpi_subsystem_id)
cs35l41->acpi_subsystem_id = devm_kasprintf(dev, GFP_KERNEL, "%.8x",
comps->codec->core.subsystem_id);
cs35l41->acpi_subsystem_id = kasprintf(GFP_KERNEL, "%.8x",
comps->codec->core.subsystem_id);
cs35l41->codec = comps->codec;
strscpy(comps->name, dev_name(dev), sizeof(comps->name));
@@ -1048,36 +1048,6 @@ static int cs35l41_hda_apply_properties(struct cs35l41_hda *cs35l41)
return cs35l41_hda_channel_map(cs35l41->dev, 0, NULL, 1, &hw_cfg->spk_pos);
}
static int cs35l41_get_acpi_sub_string(struct device *dev, struct acpi_device *adev,
const char **subsysid)
{
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
union acpi_object *obj;
acpi_status status;
int ret = 0;
status = acpi_evaluate_object(adev->handle, "_SUB", NULL, &buffer);
if (ACPI_SUCCESS(status)) {
obj = buffer.pointer;
if (obj->type == ACPI_TYPE_STRING) {
*subsysid = devm_kstrdup(dev, obj->string.pointer, GFP_KERNEL);
if (*subsysid == NULL) {
dev_err(dev, "Cannot allocate Subsystem ID");
ret = -ENOMEM;
}
} else {
dev_warn(dev, "Warning ACPI _SUB did not return a string\n");
ret = -ENODEV;
}
acpi_os_free(buffer.pointer);
} else {
dev_dbg(dev, "Warning ACPI _SUB failed: %#x\n", status);
ret = -ENODEV;
}
return ret;
}
static int cs35l41_get_speaker_id(struct device *dev, int amp_index,
int num_amps, int fixed_gpio_id)
{
@@ -1154,7 +1124,6 @@ static int cs35l41_no_acpi_dsd(struct cs35l41_hda *cs35l41, struct device *physd
hw_cfg->gpio2.func = CS35L41_INTERRUPT;
hw_cfg->gpio2.valid = true;
hw_cfg->valid = true;
put_device(physdev);
if (strncmp(hid, "CLSA0100", 8) == 0) {
hw_cfg->bst_type = CS35L41_EXT_BOOST_NO_VSPK_SWITCH;
@@ -1183,6 +1152,7 @@ static int cs35l41_hda_read_acpi(struct cs35l41_hda *cs35l41, const char *hid, i
u32 values[HDA_MAX_COMPONENTS];
struct acpi_device *adev;
struct device *physdev;
const char *sub;
char *property;
size_t nval;
int i, ret;
@@ -1196,17 +1166,17 @@ static int cs35l41_hda_read_acpi(struct cs35l41_hda *cs35l41, const char *hid, i
physdev = get_device(acpi_get_first_physical_node(adev));
acpi_dev_put(adev);
ret = cs35l41_get_acpi_sub_string(cs35l41->dev, adev, &cs35l41->acpi_subsystem_id);
if (ret)
dev_info(cs35l41->dev, "No Subsystem ID found in ACPI: %d", ret);
else
dev_dbg(cs35l41->dev, "Subsystem ID %s found", cs35l41->acpi_subsystem_id);
sub = acpi_get_subsystem_id(ACPI_HANDLE(physdev));
if (IS_ERR(sub))
sub = NULL;
cs35l41->acpi_subsystem_id = sub;
property = "cirrus,dev-index";
ret = device_property_count_u32(physdev, property);
if (ret <= 0)
return cs35l41_no_acpi_dsd(cs35l41, physdev, id, hid);
if (ret <= 0) {
ret = cs35l41_no_acpi_dsd(cs35l41, physdev, id, hid);
goto err_put_physdev;
}
if (ret > ARRAY_SIZE(values)) {
ret = -EINVAL;
goto err;
@@ -1295,8 +1265,9 @@ static int cs35l41_hda_read_acpi(struct cs35l41_hda *cs35l41, const char *hid, i
return 0;
err:
put_device(physdev);
dev_err(cs35l41->dev, "Failed property %s: %d\n", property, ret);
err_put_physdev:
put_device(physdev);
return ret;
}
@@ -1433,6 +1404,7 @@ int cs35l41_hda_probe(struct device *dev, const char *device_name, int id, int i
if (cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type))
gpiod_set_value_cansleep(cs35l41->reset_gpio, 0);
gpiod_put(cs35l41->reset_gpio);
kfree(cs35l41->acpi_subsystem_id);
return ret;
}
@@ -1455,6 +1427,7 @@ void cs35l41_hda_remove(struct device *dev)
if (cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type))
gpiod_set_value_cansleep(cs35l41->reset_gpio, 0);
gpiod_put(cs35l41->reset_gpio);
kfree(cs35l41->acpi_subsystem_id);
}
EXPORT_SYMBOL_NS_GPL(cs35l41_hda_remove, SND_HDA_SCODEC_CS35L41);

View File

@@ -118,6 +118,12 @@ static int snd_hda_beep_event(struct input_dev *dev, unsigned int type,
return 0;
}
static void turn_on_beep(struct hda_beep *beep)
{
if (beep->keep_power_at_enable)
snd_hda_power_up_pm(beep->codec);
}
static void turn_off_beep(struct hda_beep *beep)
{
cancel_work_sync(&beep->beep_work);
@@ -125,6 +131,8 @@ static void turn_off_beep(struct hda_beep *beep)
/* turn off beep */
generate_tone(beep, 0);
}
if (beep->keep_power_at_enable)
snd_hda_power_down_pm(beep->codec);
}
/**
@@ -140,7 +148,9 @@ int snd_hda_enable_beep_device(struct hda_codec *codec, int enable)
enable = !!enable;
if (beep->enabled != enable) {
beep->enabled = enable;
if (!enable)
if (enable)
turn_on_beep(beep);
else
turn_off_beep(beep);
return 1;
}
@@ -167,7 +177,8 @@ static int beep_dev_disconnect(struct snd_device *device)
input_unregister_device(beep->dev);
else
input_free_device(beep->dev);
turn_off_beep(beep);
if (beep->enabled)
turn_off_beep(beep);
return 0;
}

View File

@@ -25,6 +25,7 @@ struct hda_beep {
unsigned int enabled:1;
unsigned int linear_tone:1; /* linear tone for IDT/STAC codec */
unsigned int playing:1;
unsigned int keep_power_at_enable:1; /* set by driver */
struct work_struct beep_work; /* scheduled task for beep event */
struct mutex mutex;
void (*power_hook)(struct hda_beep *beep, bool on);

View File

@@ -883,13 +883,7 @@ static void snd_hda_codec_dev_release(struct device *dev)
snd_hda_sysfs_clear(codec);
kfree(codec->modelname);
kfree(codec->wcaps);
/*
* In the case of ASoC HD-audio, hda_codec is device managed.
* It will be freed when the ASoC device is removed.
*/
if (codec->core.type == HDA_DEV_LEGACY)
kfree(codec);
kfree(codec);
}
#define DEV_NAME_LEN 31
@@ -931,8 +925,28 @@ snd_hda_codec_device_init(struct hda_bus *bus, unsigned int codec_addr,
}
codec->bus = bus;
codec->depop_delay = -1;
codec->fixup_id = HDA_FIXUP_ID_NOT_SET;
codec->core.dev.release = snd_hda_codec_dev_release;
codec->core.exec_verb = codec_exec_verb;
codec->core.type = HDA_DEV_LEGACY;
mutex_init(&codec->spdif_mutex);
mutex_init(&codec->control_mutex);
snd_array_init(&codec->mixers, sizeof(struct hda_nid_item), 32);
snd_array_init(&codec->nids, sizeof(struct hda_nid_item), 32);
snd_array_init(&codec->init_pins, sizeof(struct hda_pincfg), 16);
snd_array_init(&codec->driver_pins, sizeof(struct hda_pincfg), 16);
snd_array_init(&codec->cvt_setups, sizeof(struct hda_cvt_setup), 8);
snd_array_init(&codec->spdif_out, sizeof(struct hda_spdif_out), 16);
snd_array_init(&codec->jacktbl, sizeof(struct hda_jack_tbl), 16);
snd_array_init(&codec->verbs, sizeof(struct hda_verb *), 8);
INIT_LIST_HEAD(&codec->conn_list);
INIT_LIST_HEAD(&codec->pcm_list_head);
INIT_DELAYED_WORK(&codec->jackpoll_work, hda_jackpoll_work);
refcount_set(&codec->pcm_ref, 1);
init_waitqueue_head(&codec->remove_sleep);
return codec;
}
EXPORT_SYMBOL_GPL(snd_hda_codec_device_init);
@@ -985,29 +999,8 @@ int snd_hda_codec_device_new(struct hda_bus *bus, struct snd_card *card,
if (snd_BUG_ON(codec_addr > HDA_MAX_CODEC_ADDRESS))
return -EINVAL;
codec->core.dev.release = snd_hda_codec_dev_release;
codec->core.exec_verb = codec_exec_verb;
codec->card = card;
codec->addr = codec_addr;
mutex_init(&codec->spdif_mutex);
mutex_init(&codec->control_mutex);
snd_array_init(&codec->mixers, sizeof(struct hda_nid_item), 32);
snd_array_init(&codec->nids, sizeof(struct hda_nid_item), 32);
snd_array_init(&codec->init_pins, sizeof(struct hda_pincfg), 16);
snd_array_init(&codec->driver_pins, sizeof(struct hda_pincfg), 16);
snd_array_init(&codec->cvt_setups, sizeof(struct hda_cvt_setup), 8);
snd_array_init(&codec->spdif_out, sizeof(struct hda_spdif_out), 16);
snd_array_init(&codec->jacktbl, sizeof(struct hda_jack_tbl), 16);
snd_array_init(&codec->verbs, sizeof(struct hda_verb *), 8);
INIT_LIST_HEAD(&codec->conn_list);
INIT_LIST_HEAD(&codec->pcm_list_head);
refcount_set(&codec->pcm_ref, 1);
init_waitqueue_head(&codec->remove_sleep);
INIT_DELAYED_WORK(&codec->jackpoll_work, hda_jackpoll_work);
codec->depop_delay = -1;
codec->fixup_id = HDA_FIXUP_ID_NOT_SET;
#ifdef CONFIG_PM
codec->power_jiffies = jiffies;

View File

@@ -1033,10 +1033,8 @@ EXPORT_SYMBOL_GPL(azx_init_chip);
void azx_stop_all_streams(struct azx *chip)
{
struct hdac_bus *bus = azx_bus(chip);
struct hdac_stream *s;
list_for_each_entry(s, &bus->stream_list, list)
snd_hdac_stream_stop(s);
snd_hdac_stop_streams(bus);
}
EXPORT_SYMBOL_GPL(azx_stop_all_streams);

View File

@@ -440,7 +440,8 @@ static void hdmi_print_sad_info(int i, struct cea_sad *a,
}
void snd_hdmi_print_eld_info(struct hdmi_eld *eld,
struct snd_info_buffer *buffer)
struct snd_info_buffer *buffer,
hda_nid_t pin_nid, int dev_id, hda_nid_t cvt_nid)
{
struct parsed_hdmi_eld *e = &eld->info;
char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE];
@@ -462,6 +463,9 @@ void snd_hdmi_print_eld_info(struct hdmi_eld *eld,
snd_iprintf(buffer, "monitor_present\t\t%d\n", eld->monitor_present);
snd_iprintf(buffer, "eld_valid\t\t%d\n", eld->eld_valid);
snd_iprintf(buffer, "codec_pin_nid\t\t0x%x\n", pin_nid);
snd_iprintf(buffer, "codec_dev_id\t\t0x%x\n", dev_id);
snd_iprintf(buffer, "codec_cvt_nid\t\t0x%x\n", cvt_nid);
if (!eld->eld_valid)
return;
snd_iprintf(buffer, "monitor_name\t\t%s\n", e->monitor_name);

View File

@@ -86,9 +86,6 @@ enum {
#define INTEL_SCH_HDA_DEVC 0x78
#define INTEL_SCH_HDA_DEVC_NOSNOOP (0x1<<11)
/* Define VIA HD Audio Device ID*/
#define VIA_HDAC_DEVICE_ID 0x3288
/* max number of SDs */
/* ICH, ATI and VIA have 4 playback and 4 capture */
#define ICH6_NUM_CAPTURE 4
@@ -102,10 +99,6 @@ enum {
#define ATIHDMI_NUM_CAPTURE 0
#define ATIHDMI_NUM_PLAYBACK 8
/* TERA has 4 playback and 3 capture */
#define TERA_NUM_CAPTURE 3
#define TERA_NUM_PLAYBACK 4
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
@@ -496,14 +489,14 @@ static int intel_ml_lctl_set_power(struct azx *chip, int state)
* If other links are enabled for stream, they need similar fix
*/
val = readl(bus->mlcap + AZX_ML_BASE + AZX_REG_ML_LCTL);
val &= ~AZX_MLCTL_SPA;
val |= state << AZX_MLCTL_SPA_SHIFT;
val &= ~AZX_ML_LCTL_SPA;
val |= state << AZX_ML_LCTL_SPA_SHIFT;
writel(val, bus->mlcap + AZX_ML_BASE + AZX_REG_ML_LCTL);
/* wait for CPA */
timeout = 50;
while (timeout) {
if (((readl(bus->mlcap + AZX_ML_BASE + AZX_REG_ML_LCTL)) &
AZX_MLCTL_CPA) == (state << AZX_MLCTL_CPA_SHIFT))
AZX_ML_LCTL_CPA) == (state << AZX_ML_LCTL_CPA_SHIFT))
return 0;
timeout--;
udelay(10);
@@ -521,15 +514,15 @@ static void intel_init_lctl(struct azx *chip)
/* 0. check lctl register value is correct or not */
val = readl(bus->mlcap + AZX_ML_BASE + AZX_REG_ML_LCTL);
/* if SCF is already set, let's use it */
if ((val & ML_LCTL_SCF_MASK) != 0)
if ((val & AZX_ML_LCTL_SCF) != 0)
return;
/*
* Before operating on SPA, CPA must match SPA.
* Any deviation may result in undefined behavior.
*/
if (((val & AZX_MLCTL_SPA) >> AZX_MLCTL_SPA_SHIFT) !=
((val & AZX_MLCTL_CPA) >> AZX_MLCTL_CPA_SHIFT))
if (((val & AZX_ML_LCTL_SPA) >> AZX_ML_LCTL_SPA_SHIFT) !=
((val & AZX_ML_LCTL_CPA) >> AZX_ML_LCTL_CPA_SHIFT))
return;
/* 1. turn link down: set SPA to 0 and wait CPA to 0 */
@@ -539,7 +532,7 @@ static void intel_init_lctl(struct azx *chip)
goto set_spa;
/* 2. update SCF to select a properly audio clock*/
val &= ~ML_LCTL_SCF_MASK;
val &= ~AZX_ML_LCTL_SCF;
val |= intel_get_lctl_scf(chip);
writel(val, bus->mlcap + AZX_ML_BASE + AZX_REG_ML_LCTL);
@@ -2554,7 +2547,8 @@ static const struct pci_device_id azx_ids[] = {
.driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH_NOPM },
/* Poulsbo */
{ PCI_DEVICE(0x8086, 0x811b),
.driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH_BASE },
.driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH_BASE |
AZX_DCAPS_POSFIX_LPIB },
/* Oaktrail */
{ PCI_DEVICE(0x8086, 0x080a),
.driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH_BASE },

View File

@@ -712,7 +712,8 @@ int snd_hdmi_get_eld_ati(struct hda_codec *codec, hda_nid_t nid,
#ifdef CONFIG_SND_PROC_FS
void snd_hdmi_print_eld_info(struct hdmi_eld *eld,
struct snd_info_buffer *buffer);
struct snd_info_buffer *buffer,
hda_nid_t pin_nid, int dev_id, hda_nid_t cvt_nid);
void snd_hdmi_write_eld_info(struct hdmi_eld *eld,
struct snd_info_buffer *buffer);
#endif

View File

@@ -375,8 +375,6 @@ static ssize_t user_pin_configs_show(struct device *dev,
return pin_configs_show(codec, &codec->user_pins, buf);
}
#define MAX_PIN_CONFIGS 32
static int parse_user_pin_configs(struct hda_codec *codec, const char *buf)
{
int nid, cfg, err;

View File

@@ -2962,7 +2962,6 @@ static int dsp_allocate_ports_format(struct hda_codec *codec,
const unsigned short fmt,
unsigned int *port_map)
{
int status;
unsigned int num_chans;
unsigned int sample_rate_div = ((get_hdafmt_rate(fmt) >> 0) & 3) + 1;
@@ -2976,9 +2975,7 @@ static int dsp_allocate_ports_format(struct hda_codec *codec,
num_chans = get_hdafmt_chs(fmt) + 1;
status = dsp_allocate_ports(codec, num_chans, rate_multi, port_map);
return status;
return dsp_allocate_ports(codec, num_chans, rate_multi, port_map);
}
/*

View File

@@ -53,7 +53,8 @@ MODULE_PARM_DESC(enable_all_pins, "Forcibly enable all pins");
struct hdmi_spec_per_cvt {
hda_nid_t cvt_nid;
int assigned;
bool assigned; /* the stream has been assigned */
bool silent_stream; /* silent stream activated */
unsigned int channels_min;
unsigned int channels_max;
u32 rates;
@@ -150,7 +151,7 @@ struct hdmi_spec {
*/
int dev_num;
struct snd_array pins; /* struct hdmi_spec_per_pin */
struct hdmi_pcm pcm_rec[16];
struct hdmi_pcm pcm_rec[8];
struct mutex pcm_lock;
struct mutex bind_lock; /* for audio component binding */
/* pcm_bitmap means which pcms have been assigned to pins*/
@@ -166,8 +167,6 @@ struct hdmi_spec {
struct hdmi_ops ops;
bool dyn_pin_out;
bool dyn_pcm_assign;
bool dyn_pcm_no_legacy;
/* hdmi interrupt trigger control flag for Nvidia codec */
bool hdmi_intr_trig_ctrl;
bool nv_dp_workaround; /* workaround DP audio infoframe for Nvidia */
@@ -231,7 +230,7 @@ struct dp_audio_infoframe {
union audio_infoframe {
struct hdmi_audio_infoframe hdmi;
struct dp_audio_infoframe dp;
u8 bytes[0];
DECLARE_FLEX_ARRAY(u8, bytes);
};
/*
@@ -495,7 +494,8 @@ static void print_eld_info(struct snd_info_entry *entry,
struct hdmi_spec_per_pin *per_pin = entry->private_data;
mutex_lock(&per_pin->lock);
snd_hdmi_print_eld_info(&per_pin->sink_eld, buffer);
snd_hdmi_print_eld_info(&per_pin->sink_eld, buffer, per_pin->pin_nid,
per_pin->dev_id, per_pin->cvt_nid);
mutex_unlock(&per_pin->lock);
}
@@ -988,7 +988,8 @@ static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid,
* of the pin.
*/
static int hdmi_choose_cvt(struct hda_codec *codec,
int pin_idx, int *cvt_id)
int pin_idx, int *cvt_id,
bool silent)
{
struct hdmi_spec *spec = codec->spec;
struct hdmi_spec_per_pin *per_pin;
@@ -1003,6 +1004,9 @@ static int hdmi_choose_cvt(struct hda_codec *codec,
if (per_pin && per_pin->silent_stream) {
cvt_idx = cvt_nid_to_cvt_index(codec, per_pin->cvt_nid);
per_cvt = get_cvt(spec, cvt_idx);
if (per_cvt->assigned && !silent)
return -EBUSY;
if (cvt_id)
*cvt_id = cvt_idx;
return 0;
@@ -1013,7 +1017,7 @@ static int hdmi_choose_cvt(struct hda_codec *codec,
per_cvt = get_cvt(spec, cvt_idx);
/* Must not already be assigned */
if (per_cvt->assigned)
if (per_cvt->assigned || per_cvt->silent_stream)
continue;
if (per_pin == NULL)
break;
@@ -1182,9 +1186,7 @@ static void pin_cvt_fixup(struct hda_codec *codec,
spec->ops.pin_cvt_fixup(codec, per_pin, cvt_nid);
}
/* called in hdmi_pcm_open when no pin is assigned to the PCM
* in dyn_pcm_assign mode.
*/
/* called in hdmi_pcm_open when no pin is assigned to the PCM */
static int hdmi_pcm_open_no_pin(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
struct snd_pcm_substream *substream)
@@ -1199,12 +1201,12 @@ static int hdmi_pcm_open_no_pin(struct hda_pcm_stream *hinfo,
if (pcm_idx < 0)
return -EINVAL;
err = hdmi_choose_cvt(codec, -1, &cvt_idx);
err = hdmi_choose_cvt(codec, -1, &cvt_idx, false);
if (err)
return err;
per_cvt = get_cvt(spec, cvt_idx);
per_cvt->assigned = 1;
per_cvt->assigned = true;
hinfo->nid = per_cvt->cvt_nid;
pin_cvt_fixup(codec, NULL, per_cvt->cvt_nid);
@@ -1252,33 +1254,25 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo,
mutex_lock(&spec->pcm_lock);
pin_idx = hinfo_to_pin_index(codec, hinfo);
if (!spec->dyn_pcm_assign) {
if (snd_BUG_ON(pin_idx < 0)) {
err = -EINVAL;
goto unlock;
}
} else {
/* no pin is assigned to the PCM
* PA need pcm open successfully when probe
*/
if (pin_idx < 0) {
err = hdmi_pcm_open_no_pin(hinfo, codec, substream);
goto unlock;
}
/* no pin is assigned to the PCM
* PA need pcm open successfully when probe
*/
if (pin_idx < 0) {
err = hdmi_pcm_open_no_pin(hinfo, codec, substream);
goto unlock;
}
err = hdmi_choose_cvt(codec, pin_idx, &cvt_idx);
err = hdmi_choose_cvt(codec, pin_idx, &cvt_idx, false);
if (err < 0)
goto unlock;
per_cvt = get_cvt(spec, cvt_idx);
/* Claim converter */
per_cvt->assigned = 1;
per_cvt->assigned = true;
set_bit(pcm_idx, &spec->pcm_in_use);
per_pin = get_pin(spec, pin_idx);
per_pin->cvt_nid = per_cvt->cvt_nid;
per_pin->silent_stream = false;
hinfo->nid = per_cvt->cvt_nid;
/* flip stripe flag for the assigned stream if supported */
@@ -1308,7 +1302,7 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo,
snd_hdmi_eld_update_pcm_info(&eld->info, hinfo);
if (hinfo->channels_min > hinfo->channels_max ||
!hinfo->rates || !hinfo->formats) {
per_cvt->assigned = 0;
per_cvt->assigned = false;
hinfo->nid = 0;
snd_hda_spdif_ctls_unassign(codec, pcm_idx);
err = -ENODEV;
@@ -1370,43 +1364,6 @@ static int hdmi_find_pcm_slot(struct hdmi_spec *spec,
{
int i;
/* on the new machines, try to assign the pcm slot dynamically,
* not use the preferred fixed map (legacy way) anymore.
*/
if (spec->dyn_pcm_no_legacy)
goto last_try;
/*
* generic_hdmi_build_pcms() may allocate extra PCMs on some
* platforms (with maximum of 'num_nids + dev_num - 1')
*
* The per_pin of pin_nid_idx=n and dev_id=m prefers to get pcm-n
* if m==0. This guarantees that dynamic pcm assignments are compatible
* with the legacy static per_pin-pcm assignment that existed in the
* days before DP-MST.
*
* Intel DP-MST prefers this legacy behavior for compatibility, too.
*
* per_pin of m!=0 prefers to get pcm=(num_nids + (m - 1)).
*/
if (per_pin->dev_id == 0 || spec->intel_hsw_fixup) {
if (!test_bit(per_pin->pin_nid_idx, &spec->pcm_bitmap))
return per_pin->pin_nid_idx;
} else {
i = spec->num_nids + (per_pin->dev_id - 1);
if (i < spec->pcm_used && !(test_bit(i, &spec->pcm_bitmap)))
return i;
}
/* have a second try; check the area over num_nids */
for (i = spec->num_nids; i < spec->pcm_used; i++) {
if (!test_bit(i, &spec->pcm_bitmap))
return i;
}
last_try:
/* the last try; check the empty slots in pins */
for (i = 0; i < spec->pcm_used; i++) {
if (!test_bit(i, &spec->pcm_bitmap))
return i;
@@ -1468,10 +1425,9 @@ static void hdmi_pcm_setup_pin(struct hdmi_spec *spec,
int mux_idx;
bool non_pcm;
if (per_pin->pcm_idx >= 0 && per_pin->pcm_idx < spec->pcm_used)
pcm = get_pcm_rec(spec, per_pin->pcm_idx);
else
if (per_pin->pcm_idx < 0 || per_pin->pcm_idx >= spec->pcm_used)
return;
pcm = get_pcm_rec(spec, per_pin->pcm_idx);
if (!pcm->pcm)
return;
if (!test_bit(per_pin->pcm_idx, &spec->pcm_in_use))
@@ -1569,14 +1525,12 @@ static void update_eld(struct hda_codec *codec,
*/
pcm_jack = pin_idx_to_pcm_jack(codec, per_pin);
if (spec->dyn_pcm_assign) {
if (eld->eld_valid) {
hdmi_attach_hda_pcm(spec, per_pin);
hdmi_pcm_setup_pin(spec, per_pin);
} else {
hdmi_pcm_reset_pin(spec, per_pin);
hdmi_detach_hda_pcm(spec, per_pin);
}
if (eld->eld_valid) {
hdmi_attach_hda_pcm(spec, per_pin);
hdmi_pcm_setup_pin(spec, per_pin);
} else {
hdmi_pcm_reset_pin(spec, per_pin);
hdmi_detach_hda_pcm(spec, per_pin);
}
/* if pcm_idx == -1, it means this is in monitor connection event
* we can get the correct pcm_idx now.
@@ -1760,14 +1714,14 @@ static void silent_stream_enable(struct hda_codec *codec,
}
pin_idx = pin_id_to_pin_index(codec, per_pin->pin_nid, per_pin->dev_id);
err = hdmi_choose_cvt(codec, pin_idx, &cvt_idx);
err = hdmi_choose_cvt(codec, pin_idx, &cvt_idx, true);
if (err) {
codec_err(codec, "hdmi: no free converter to enable silent mode\n");
goto unlock_out;
}
per_cvt = get_cvt(spec, cvt_idx);
per_cvt->assigned = 1;
per_cvt->silent_stream = true;
per_pin->cvt_nid = per_cvt->cvt_nid;
per_pin->silent_stream = true;
@@ -1827,7 +1781,7 @@ static void silent_stream_disable(struct hda_codec *codec,
cvt_idx = cvt_nid_to_cvt_index(codec, per_pin->cvt_nid);
if (cvt_idx >= 0 && cvt_idx < spec->num_cvts) {
per_cvt = get_cvt(spec, cvt_idx);
per_cvt->assigned = 0;
per_cvt->silent_stream = false;
}
if (spec->silent_stream_type == SILENT_STREAM_I915) {
@@ -1938,7 +1892,7 @@ static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
* structures based on worst case.
*/
dev_num = spec->dev_num;
} else if (spec->dyn_pcm_assign && codec->dp_mst) {
} else if (codec->dp_mst) {
dev_num = snd_hda_get_num_devices(codec, pin_nid) + 1;
/*
* spec->dev_num is the maxinum number of device entries
@@ -1963,13 +1917,8 @@ static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
if (!per_pin)
return -ENOMEM;
if (spec->dyn_pcm_assign) {
per_pin->pcm = NULL;
per_pin->pcm_idx = -1;
} else {
per_pin->pcm = get_hdmi_pcm(spec, pin_idx);
per_pin->pcm_idx = pin_idx;
}
per_pin->pcm = NULL;
per_pin->pcm_idx = -1;
per_pin->pin_nid = pin_nid;
per_pin->pin_nid_idx = spec->num_nids;
per_pin->dev_id = i;
@@ -1978,6 +1927,8 @@ static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
err = hdmi_read_pin_conn(codec, pin_idx);
if (err < 0)
return err;
if (!is_jack_detectable(codec, pin_nid))
codec_warn(codec, "HDMI: pin NID 0x%x - jack not detectable\n", pin_nid);
spec->num_pins++;
}
spec->num_nids++;
@@ -2125,10 +2076,9 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
mutex_lock(&spec->pcm_lock);
pin_idx = hinfo_to_pin_index(codec, hinfo);
if (spec->dyn_pcm_assign && pin_idx < 0) {
/* when dyn_pcm_assign and pcm is not bound to a pin
* skip pin setup and return 0 to make audio playback
* be ongoing
if (pin_idx < 0) {
/* when pcm is not bound to a pin skip pin setup and return 0
* to make audio playback be ongoing
*/
pin_cvt_fixup(codec, NULL, cvt_nid);
snd_hda_codec_setup_stream(codec, cvt_nid,
@@ -2223,7 +2173,7 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo,
goto unlock;
}
per_cvt = get_cvt(spec, cvt_idx);
per_cvt->assigned = 0;
per_cvt->assigned = false;
hinfo->nid = 0;
azx_stream(get_azx_dev(substream))->stripe = 0;
@@ -2231,7 +2181,7 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo,
snd_hda_spdif_ctls_unassign(codec, pcm_idx);
clear_bit(pcm_idx, &spec->pcm_in_use);
pin_idx = hinfo_to_pin_index(codec, hinfo);
if (spec->dyn_pcm_assign && pin_idx < 0)
if (pin_idx < 0)
goto unlock;
if (snd_BUG_ON(pin_idx < 0)) {
@@ -2329,21 +2279,8 @@ static int generic_hdmi_build_pcms(struct hda_codec *codec)
struct hdmi_spec *spec = codec->spec;
int idx, pcm_num;
/*
* for non-mst mode, pcm number is the same as before
* for DP MST mode without extra PCM, pcm number is same
* for DP MST mode with extra PCMs, pcm number is
* (nid number + dev_num - 1)
* dev_num is the device entry number in a pin
*/
if (spec->dyn_pcm_no_legacy && codec->mst_no_extra_pcms)
pcm_num = spec->num_cvts;
else if (codec->mst_no_extra_pcms)
pcm_num = spec->num_nids;
else
pcm_num = spec->num_nids + spec->dev_num - 1;
/* limit the PCM devices to the codec converters */
pcm_num = spec->num_cvts;
codec_dbg(codec, "hdmi: pcm_num set to %d\n", pcm_num);
for (idx = 0; idx < pcm_num; idx++) {
@@ -2362,8 +2299,8 @@ static int generic_hdmi_build_pcms(struct hda_codec *codec)
pstr = &info->stream[SNDRV_PCM_STREAM_PLAYBACK];
pstr->substreams = 1;
pstr->ops = generic_ops;
/* pcm number is less than 16 */
if (spec->pcm_used >= 16)
/* pcm number is less than pcm_rec array size */
if (spec->pcm_used >= ARRAY_SIZE(spec->pcm_rec))
break;
/* other pstr fields are set in open */
}
@@ -2382,17 +2319,12 @@ static int generic_hdmi_build_jack(struct hda_codec *codec, int pcm_idx)
{
char hdmi_str[32] = "HDMI/DP";
struct hdmi_spec *spec = codec->spec;
struct hdmi_spec_per_pin *per_pin = get_pin(spec, pcm_idx);
struct snd_jack *jack;
int pcmdev = get_pcm_rec(spec, pcm_idx)->device;
int err;
if (pcmdev > 0)
sprintf(hdmi_str + strlen(hdmi_str), ",pcm=%d", pcmdev);
if (!spec->dyn_pcm_assign &&
!is_jack_detectable(codec, per_pin->pin_nid))
strncat(hdmi_str, " Phantom",
sizeof(hdmi_str) - strlen(hdmi_str) - 1);
err = snd_jack_new(codec->card, hdmi_str, SND_JACK_AVOUT, &jack,
true, false);
@@ -2425,18 +2357,9 @@ static int generic_hdmi_build_controls(struct hda_codec *codec)
/* create the spdif for each pcm
* pin will be bound when monitor is connected
*/
if (spec->dyn_pcm_assign)
err = snd_hda_create_dig_out_ctls(codec,
err = snd_hda_create_dig_out_ctls(codec,
0, spec->cvt_nids[0],
HDA_PCM_TYPE_HDMI);
else {
struct hdmi_spec_per_pin *per_pin =
get_pin(spec, pcm_idx);
err = snd_hda_create_dig_out_ctls(codec,
per_pin->pin_nid,
per_pin->mux_nids[0],
HDA_PCM_TYPE_HDMI);
}
if (err < 0)
return err;
snd_hda_spdif_ctls_unassign(codec, pcm_idx);
@@ -2556,11 +2479,7 @@ static void generic_hdmi_free(struct hda_codec *codec)
for (pcm_idx = 0; pcm_idx < spec->pcm_used; pcm_idx++) {
if (spec->pcm_rec[pcm_idx].jack == NULL)
continue;
if (spec->dyn_pcm_assign)
snd_device_free(codec->card,
spec->pcm_rec[pcm_idx].jack);
else
spec->pcm_rec[pcm_idx].jack = NULL;
snd_device_free(codec->card, spec->pcm_rec[pcm_idx].jack);
}
generic_spec_free(codec);
@@ -2747,9 +2666,6 @@ static void generic_acomp_pin_eld_notify(void *audio_ptr, int port, int dev_id)
*/
if (codec->core.dev.power.power_state.event == PM_EVENT_SUSPEND)
return;
/* ditto during suspend/resume process itself */
if (snd_hdac_is_in_pm(&codec->core))
return;
check_presence_and_report(codec, pin_nid, dev_id);
}
@@ -2933,9 +2849,6 @@ static void intel_pin_eld_notify(void *audio_ptr, int port, int pipe)
*/
if (codec->core.dev.power.power_state.event == PM_EVENT_SUSPEND)
return;
/* ditto during suspend/resume process itself */
if (snd_hdac_is_in_pm(&codec->core))
return;
snd_hdac_i915_set_bclk(&codec->bus->core);
check_presence_and_report(codec, pin_nid, dev_id);
@@ -3040,7 +2953,6 @@ static int intel_hsw_common_init(struct hda_codec *codec, hda_nid_t vendor_nid,
return err;
spec = codec->spec;
codec->dp_mst = true;
spec->dyn_pcm_assign = true;
spec->vendor_nid = vendor_nid;
spec->port_map = port_map;
spec->port_num = port_num;
@@ -3104,17 +3016,9 @@ static int patch_i915_tgl_hdmi(struct hda_codec *codec)
* the index indicate the port number.
*/
static const int map[] = {0x4, 0x6, 0x8, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf};
int ret;
ret = intel_hsw_common_init(codec, 0x02, map, ARRAY_SIZE(map), 4,
enable_silent_stream);
if (!ret) {
struct hdmi_spec *spec = codec->spec;
spec->dyn_pcm_no_legacy = true;
}
return ret;
return intel_hsw_common_init(codec, 0x02, map, ARRAY_SIZE(map), 4,
enable_silent_stream);
}
static int patch_i915_adlp_hdmi(struct hda_codec *codec)
@@ -3754,7 +3658,6 @@ static int patch_nvhdmi(struct hda_codec *codec)
codec->dp_mst = true;
spec = codec->spec;
spec->dyn_pcm_assign = true;
err = hdmi_parse_codec(codec);
if (err < 0) {
@@ -4034,10 +3937,8 @@ static int patch_tegra234_hdmi(struct hda_codec *codec)
return err;
codec->dp_mst = true;
codec->mst_no_extra_pcms = true;
spec = codec->spec;
spec->dyn_pin_out = true;
spec->dyn_pcm_assign = true;
spec->hdmi_intr_trig_ctrl = true;
return tegra_hdmi_init(codec);

View File

@@ -18,6 +18,7 @@
#include <linux/module.h>
#include <linux/input.h>
#include <linux/leds.h>
#include <linux/ctype.h>
#include <sound/core.h>
#include <sound/jack.h>
#include <sound/hda_codec.h>
@@ -6704,23 +6705,51 @@ static void comp_generic_playback_hook(struct hda_pcm_stream *hinfo, struct hda_
}
}
struct cs35l41_dev_name {
const char *bus;
const char *hid;
int index;
};
/* match the device name in a slightly relaxed manner */
static int comp_match_cs35l41_dev_name(struct device *dev, void *data)
{
struct cs35l41_dev_name *p = data;
const char *d = dev_name(dev);
int n = strlen(p->bus);
char tmp[32];
/* check the bus name */
if (strncmp(d, p->bus, n))
return 0;
/* skip the bus number */
if (isdigit(d[n]))
n++;
/* the rest must be exact matching */
snprintf(tmp, sizeof(tmp), "-%s:00-cs35l41-hda.%d", p->hid, p->index);
return !strcmp(d + n, tmp);
}
static void cs35l41_generic_fixup(struct hda_codec *cdc, int action, const char *bus,
const char *hid, int count)
{
struct device *dev = hda_codec_dev(cdc);
struct alc_spec *spec = cdc->spec;
char *name;
struct cs35l41_dev_name *rec;
int ret, i;
switch (action) {
case HDA_FIXUP_ACT_PRE_PROBE:
for (i = 0; i < count; i++) {
name = devm_kasprintf(dev, GFP_KERNEL,
"%s-%s:00-cs35l41-hda.%d", bus, hid, i);
if (!name)
rec = devm_kmalloc(dev, sizeof(*rec), GFP_KERNEL);
if (!rec)
return;
rec->bus = bus;
rec->hid = hid;
rec->index = i;
spec->comps[i].codec = cdc;
component_match_add(dev, &spec->match, component_compare_dev_name, name);
component_match_add(dev, &spec->match,
comp_match_cs35l41_dev_name, rec);
}
ret = component_master_add_with_match(dev, &comp_master_ops, spec->match);
if (ret)
@@ -6738,12 +6767,12 @@ static void cs35l41_fixup_i2c_two(struct hda_codec *cdc, const struct hda_fixup
static void cs35l41_fixup_spi_two(struct hda_codec *codec, const struct hda_fixup *fix, int action)
{
cs35l41_generic_fixup(codec, action, "spi0", "CSC3551", 2);
cs35l41_generic_fixup(codec, action, "spi", "CSC3551", 2);
}
static void cs35l41_fixup_spi_four(struct hda_codec *codec, const struct hda_fixup *fix, int action)
{
cs35l41_generic_fixup(codec, action, "spi0", "CSC3551", 4);
cs35l41_generic_fixup(codec, action, "spi", "CSC3551", 4);
}
static void alc287_fixup_legion_16achg6_speakers(struct hda_codec *cdc, const struct hda_fixup *fix,
@@ -9341,6 +9370,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x8aa3, "HP ProBook 450 G9 (MB 8AA1)", ALC236_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8aa8, "HP EliteBook 640 G9 (MB 8AA6)", ALC236_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8aab, "HP EliteBook 650 G9 (MB 8AA9)", ALC236_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8abb, "HP ZBook Firefly 14 G9", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8ad1, "HP EliteBook 840 14 inch G9 Notebook PC", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8ad2, "HP EliteBook 860 16 inch G9 Notebook PC", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
SND_PCI_QUIRK(0x1043, 0x103e, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC),

View File

@@ -4311,6 +4311,8 @@ static int stac_parse_auto_config(struct hda_codec *codec)
if (codec->beep) {
/* IDT/STAC codecs have linear beep tone parameter */
codec->beep->linear_tone = spec->linear_tone_beep;
/* keep power up while beep is enabled */
codec->beep->keep_power_at_enable = 1;
/* if no beep switch is available, make its own one */
caps = query_amp_caps(codec, nid, HDA_OUTPUT);
if (!(caps & AC_AMPCAP_MUTE)) {
@@ -4444,28 +4446,6 @@ static int stac_suspend(struct hda_codec *codec)
return 0;
}
static int stac_check_power_status(struct hda_codec *codec, hda_nid_t nid)
{
#ifdef CONFIG_SND_HDA_INPUT_BEEP
struct sigmatel_spec *spec = codec->spec;
#endif
int ret = snd_hda_gen_check_power_status(codec, nid);
#ifdef CONFIG_SND_HDA_INPUT_BEEP
if (nid == spec->gen.beep_nid && codec->beep) {
if (codec->beep->enabled != spec->beep_power_on) {
spec->beep_power_on = codec->beep->enabled;
if (spec->beep_power_on)
snd_hda_power_up_pm(codec);
else
snd_hda_power_down_pm(codec);
}
ret |= spec->beep_power_on;
}
#endif
return ret;
}
#else
#define stac_suspend NULL
#endif /* CONFIG_PM */
@@ -4478,7 +4458,6 @@ static const struct hda_codec_ops stac_patch_ops = {
.unsol_event = snd_hda_jack_unsol_event,
#ifdef CONFIG_PM
.suspend = stac_suspend,
.check_power_status = stac_check_power_status,
#endif
};

View File

@@ -257,8 +257,7 @@ int snd_pdacf_pcm_new(struct snd_pdacf *chip)
return err;
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pdacf_pcm_capture_ops);
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC,
snd_dma_continuous_data(GFP_KERNEL | GFP_DMA32),
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC, NULL,
0, 0);
pcm->private_data = chip;

View File

@@ -1060,8 +1060,7 @@ static struct device_node *find_audio_device(const char *name)
if (! gpiop)
return NULL;
for (np = of_get_next_child(gpiop, NULL); np;
np = of_get_next_child(gpiop, np)) {
for_each_child_of_node(gpiop, np) {
const char *property = of_get_property(np, "audio-gpio", NULL);
if (property && strcmp(property, name) == 0)
break;
@@ -1080,8 +1079,7 @@ static struct device_node *find_compatible_audio_device(const char *name)
if (!gpiop)
return NULL;
for (np = of_get_next_child(gpiop, NULL); np;
np = of_get_next_child(gpiop, np)) {
for_each_child_of_node(gpiop, np) {
if (of_device_is_compatible(np, name))
break;
}

View File

@@ -224,9 +224,6 @@ static int hda_codec_probe(struct snd_soc_component *component)
goto err;
}
/* configure codec for 1:1 PCM:DAI mapping */
codec->mst_no_extra_pcms = 1;
ret = snd_hda_codec_parse_pcms(codec);
if (ret < 0) {
dev_err(&hdev->dev, "unable to map pcms to dai %d\n", ret);

View File

@@ -246,7 +246,7 @@ static int hdac_hda_dai_hw_free(struct snd_pcm_substream *substream,
return -EINVAL;
hda_stream = &pcm->stream[substream->stream];
snd_hda_codec_cleanup(&hda_pvt->codec, hda_stream, substream);
snd_hda_codec_cleanup(hda_pvt->codec, hda_stream, substream);
return 0;
}
@@ -264,7 +264,7 @@ static int hdac_hda_dai_prepare(struct snd_pcm_substream *substream,
int ret = 0;
hda_pvt = snd_soc_component_get_drvdata(component);
hdev = &hda_pvt->codec.core;
hdev = &hda_pvt->codec->core;
pcm = snd_soc_find_pcm_from_dai(hda_pvt, dai);
if (!pcm)
return -EINVAL;
@@ -274,7 +274,7 @@ static int hdac_hda_dai_prepare(struct snd_pcm_substream *substream,
stream = hda_pvt->pcm[dai->id].stream_tag[substream->stream];
format_val = hda_pvt->pcm[dai->id].format_val[substream->stream];
ret = snd_hda_codec_prepare(&hda_pvt->codec, hda_stream,
ret = snd_hda_codec_prepare(hda_pvt->codec, hda_stream,
stream, format_val, substream);
if (ret < 0)
dev_err(&hdev->dev, "codec prepare failed %d\n", ret);
@@ -299,7 +299,7 @@ static int hdac_hda_dai_open(struct snd_pcm_substream *substream,
hda_stream = &pcm->stream[substream->stream];
return hda_stream->ops.open(hda_stream, &hda_pvt->codec, substream);
return hda_stream->ops.open(hda_stream, hda_pvt->codec, substream);
}
static void hdac_hda_dai_close(struct snd_pcm_substream *substream,
@@ -317,7 +317,7 @@ static void hdac_hda_dai_close(struct snd_pcm_substream *substream,
hda_stream = &pcm->stream[substream->stream];
hda_stream->ops.close(hda_stream, &hda_pvt->codec, substream);
hda_stream->ops.close(hda_stream, hda_pvt->codec, substream);
snd_hda_codec_pcm_put(pcm);
}
@@ -325,7 +325,7 @@ static void hdac_hda_dai_close(struct snd_pcm_substream *substream,
static struct hda_pcm *snd_soc_find_pcm_from_dai(struct hdac_hda_priv *hda_pvt,
struct snd_soc_dai *dai)
{
struct hda_codec *hcodec = &hda_pvt->codec;
struct hda_codec *hcodec = hda_pvt->codec;
struct hda_pcm *cpcm;
const char *pcm_name;
@@ -394,8 +394,8 @@ static int hdac_hda_codec_probe(struct snd_soc_component *component)
snd_soc_component_get_drvdata(component);
struct snd_soc_dapm_context *dapm =
snd_soc_component_get_dapm(component);
struct hdac_device *hdev = &hda_pvt->codec.core;
struct hda_codec *hcodec = &hda_pvt->codec;
struct hdac_device *hdev = &hda_pvt->codec->core;
struct hda_codec *hcodec = hda_pvt->codec;
struct hdac_ext_link *hlink;
hda_codec_patch_t patch;
int ret;
@@ -461,9 +461,6 @@ static int hdac_hda_codec_probe(struct snd_soc_component *component)
dev_dbg(&hdev->dev, "no patch file found\n");
}
/* configure codec for 1:1 PCM:DAI mapping */
hcodec->mst_no_extra_pcms = 1;
ret = snd_hda_codec_parse_pcms(hcodec);
if (ret < 0) {
dev_err(&hdev->dev, "unable to map pcms to dai %d\n", ret);
@@ -515,8 +512,8 @@ static void hdac_hda_codec_remove(struct snd_soc_component *component)
{
struct hdac_hda_priv *hda_pvt =
snd_soc_component_get_drvdata(component);
struct hdac_device *hdev = &hda_pvt->codec.core;
struct hda_codec *codec = &hda_pvt->codec;
struct hdac_device *hdev = &hda_pvt->codec->core;
struct hda_codec *codec = hda_pvt->codec;
struct hdac_ext_link *hlink = NULL;
hlink = snd_hdac_ext_bus_get_link(hdev->bus, dev_name(&hdev->dev));
@@ -584,7 +581,6 @@ static const struct snd_soc_component_driver hdac_hda_codec = {
static int hdac_hda_dev_probe(struct hdac_device *hdev)
{
struct hdac_ext_link *hlink;
struct hdac_hda_priv *hda_pvt;
int ret;
/* hold the ref while we probe */
@@ -595,10 +591,6 @@ static int hdac_hda_dev_probe(struct hdac_device *hdev)
}
snd_hdac_ext_bus_link_get(hdev->bus, hlink);
hda_pvt = hdac_to_hda_priv(hdev);
if (!hda_pvt)
return -ENOMEM;
/* ASoC specific initialization */
ret = devm_snd_soc_register_component(&hdev->dev,
&hdac_hda_codec, hdac_hda_dais,
@@ -608,7 +600,6 @@ static int hdac_hda_dev_probe(struct hdac_device *hdev)
return ret;
}
dev_set_drvdata(&hdev->dev, hda_pvt);
snd_hdac_ext_bus_link_put(hdev->bus, hlink);
return ret;

View File

@@ -23,7 +23,7 @@ struct hdac_hda_pcm {
};
struct hdac_hda_priv {
struct hda_codec codec;
struct hda_codec *codec;
struct hdac_hda_pcm pcm[HDAC_LAST_DAI_ID];
bool need_display_power;
};

View File

@@ -676,10 +676,9 @@ static int sst_soc_pcm_new(struct snd_soc_component *component,
if (dai->driver->playback.channels_min ||
dai->driver->capture.channels_min) {
snd_pcm_set_managed_buffer_all(pcm,
SNDRV_DMA_TYPE_CONTINUOUS,
snd_dma_continuous_data(GFP_DMA),
SST_MIN_BUFFER, SST_MAX_BUFFER);
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
pcm->card->dev,
SST_MIN_BUFFER, SST_MAX_BUFFER);
}
return 0;
}

View File

@@ -466,7 +466,7 @@ static int avs_pci_probe(struct pci_dev *pci, const struct pci_device_id *id)
err_acquire_irq:
snd_hdac_bus_free_stream_pages(bus);
snd_hdac_stream_free_all(bus);
snd_hdac_ext_stream_free_all(bus);
err_init_streams:
iounmap(adev->dsp_ba);
err_remap_bar4:
@@ -502,7 +502,7 @@ static void avs_pci_remove(struct pci_dev *pci)
snd_hda_codec_unregister(hdac_to_hda_codec(hdev));
snd_hdac_bus_free_stream_pages(bus);
snd_hdac_stream_free_all(bus);
snd_hdac_ext_stream_free_all(bus);
/* reverse ml_capabilities */
snd_hdac_link_free_all(bus);
snd_hdac_ext_bus_exit(bus);

View File

@@ -54,7 +54,7 @@ int hda_dsp_hdmi_build_controls(struct snd_soc_card *card,
return -EINVAL;
hda_pvt = snd_soc_component_get_drvdata(comp);
hcodec = &hda_pvt->codec;
hcodec = hda_pvt->codec;
list_for_each_entry(hpcm, &hcodec->pcm_list_head, list) {
spcm = hda_dsp_hdmi_pcm_handle(card, i);

View File

@@ -190,7 +190,7 @@ static void skl_set_hda_codec_autosuspend_delay(struct snd_soc_card *card)
* all codecs are on the same bus, so it's sufficient
* to look up only the first one
*/
snd_hda_set_power_save(hda_pvt->codec.bus,
snd_hda_set_power_save(hda_pvt->codec->bus,
HDA_CODEC_AUTOSUSPEND_DELAY_MS);
break;
}

View File

@@ -275,7 +275,7 @@ static int skl_pcm_prepare(struct snd_pcm_substream *substream,
* calls prepare another time, reset the FW pipe to clean state
*/
if (mconfig &&
(substream->runtime->status->state == SNDRV_PCM_STATE_XRUN ||
(substream->runtime->state == SNDRV_PCM_STATE_XRUN ||
mconfig->pipe->state == SKL_PIPE_CREATED ||
mconfig->pipe->state == SKL_PIPE_PAUSED)) {
@@ -593,7 +593,7 @@ static int skl_link_pcm_prepare(struct snd_pcm_substream *substream,
/* In case of XRUN recovery, reset the FW pipe to clean state */
mconfig = skl_tplg_be_get_cpr_module(dai, substream->stream);
if (mconfig && !mconfig->pipe->passthru &&
(substream->runtime->status->state == SNDRV_PCM_STATE_XRUN))
(substream->runtime->state == SNDRV_PCM_STATE_XRUN))
skl_reset_pipe(skl, mconfig->pipe);
return 0;

View File

@@ -444,7 +444,7 @@ static int skl_free(struct hdac_bus *bus)
if (bus->irq >= 0)
free_irq(bus->irq, (void *)bus);
snd_hdac_bus_free_stream_pages(bus);
snd_hdac_stream_free_all(bus);
snd_hdac_ext_stream_free_all(bus);
snd_hdac_link_free_all(bus);
if (bus->remap_addr)
@@ -689,6 +689,35 @@ static void load_codec_module(struct hda_codec *codec)
#endif /* CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC */
static void skl_codec_device_exit(struct device *dev)
{
snd_hdac_device_exit(dev_to_hdac_dev(dev));
}
static struct hda_codec *skl_codec_device_init(struct hdac_bus *bus, int addr)
{
struct hda_codec *codec;
int ret;
codec = snd_hda_codec_device_init(to_hda_bus(bus), addr, "ehdaudio%dD%d", bus->idx, addr);
if (IS_ERR(codec)) {
dev_err(bus->dev, "device init failed for hdac device\n");
return codec;
}
codec->core.type = HDA_DEV_ASOC;
codec->core.dev.release = skl_codec_device_exit;
ret = snd_hdac_device_register(&codec->core);
if (ret) {
dev_err(bus->dev, "failed to register hdac device\n");
snd_hdac_device_exit(&codec->core);
return ERR_PTR(ret);
}
return codec;
}
/*
* Probe the given codec address
*/
@@ -697,12 +726,11 @@ static int probe_codec(struct hdac_bus *bus, int addr)
unsigned int cmd = (addr << 28) | (AC_NODE_ROOT << 20) |
(AC_VERB_PARAMETERS << 8) | AC_PAR_VENDOR_ID;
unsigned int res = -1;
struct skl_dev *skl = bus_to_skl(bus);
#if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC)
struct skl_dev *skl = bus_to_skl(bus);
struct hdac_hda_priv *hda_codec;
int err;
#endif
struct hdac_device *hdev;
struct hda_codec *codec;
mutex_lock(&bus->cmd_mutex);
snd_hdac_bus_send_cmd(bus, cmd);
@@ -718,25 +746,22 @@ static int probe_codec(struct hdac_bus *bus, int addr)
if (!hda_codec)
return -ENOMEM;
hda_codec->codec.bus = skl_to_hbus(skl);
hdev = &hda_codec->codec.core;
codec = skl_codec_device_init(bus, addr);
if (IS_ERR(codec))
return PTR_ERR(codec);
err = snd_hdac_ext_bus_device_init(bus, addr, hdev, HDA_DEV_ASOC);
if (err < 0)
return err;
hda_codec->codec = codec;
dev_set_drvdata(&codec->core.dev, hda_codec);
/* use legacy bus only for HDA codecs, idisp uses ext bus */
if ((res & 0xFFFF0000) != IDISP_INTEL_VENDOR_ID) {
hdev->type = HDA_DEV_LEGACY;
load_codec_module(&hda_codec->codec);
codec->core.type = HDA_DEV_LEGACY;
load_codec_module(hda_codec->codec);
}
return 0;
#else
hdev = devm_kzalloc(&skl->pci->dev, sizeof(*hdev), GFP_KERNEL);
if (!hdev)
return -ENOMEM;
return snd_hdac_ext_bus_device_init(bus, addr, hdev, HDA_DEV_ASOC);
codec = skl_codec_device_init(bus, addr);
return PTR_ERR_OR_ZERO(codec);
#endif /* CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC */
}

View File

@@ -598,7 +598,7 @@ static int rz_ssi_dma_transfer(struct rz_ssi_priv *ssi,
return -EINVAL;
runtime = substream->runtime;
if (runtime->status->state == SNDRV_PCM_STATE_DRAINING)
if (runtime->state == SNDRV_PCM_STATE_DRAINING)
/*
* Stream is ending, so do not queue up any more DMA
* transfers otherwise we play partial sound clips

View File

@@ -109,17 +109,45 @@ EXPORT_SYMBOL_NS(hda_codec_jack_check, SND_SOC_SOF_HDA_AUDIO_CODEC);
#define is_generic_config(x) 0
#endif
static void hda_codec_device_exit(struct device *dev)
{
snd_hdac_device_exit(dev_to_hdac_dev(dev));
}
static struct hda_codec *hda_codec_device_init(struct hdac_bus *bus, int addr, int type)
{
struct hda_codec *codec;
int ret;
codec = snd_hda_codec_device_init(to_hda_bus(bus), addr, "ehdaudio%dD%d", bus->idx, addr);
if (IS_ERR(codec)) {
dev_err(bus->dev, "device init failed for hdac device\n");
return codec;
}
codec->core.type = type;
codec->core.dev.release = hda_codec_device_exit;
ret = snd_hdac_device_register(&codec->core);
if (ret) {
dev_err(bus->dev, "failed to register hdac device\n");
snd_hdac_device_exit(&codec->core);
return ERR_PTR(ret);
}
return codec;
}
/* probe individual codec */
static int hda_codec_probe(struct snd_sof_dev *sdev, int address,
bool hda_codec_use_common_hdmi)
{
#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC)
struct hdac_hda_priv *hda_priv;
struct hda_codec *codec;
int type = HDA_DEV_LEGACY;
#endif
struct hda_bus *hbus = sof_to_hbus(sdev);
struct hdac_device *hdev;
struct hda_codec *codec;
u32 hda_cmd = (address << 28) | (AC_NODE_ROOT << 20) |
(AC_VERB_PARAMETERS << 8) | AC_PAR_VENDOR_ID;
u32 resp = -1;
@@ -142,20 +170,20 @@ static int hda_codec_probe(struct snd_sof_dev *sdev, int address,
if (!hda_priv)
return -ENOMEM;
hda_priv->codec.bus = hbus;
hdev = &hda_priv->codec.core;
codec = &hda_priv->codec;
/* only probe ASoC codec drivers for HDAC-HDMI */
if (!hda_codec_use_common_hdmi && (resp & 0xFFFF0000) == IDISP_VID_INTEL)
type = HDA_DEV_ASOC;
ret = snd_hdac_ext_bus_device_init(&hbus->core, address, hdev, type);
codec = hda_codec_device_init(&hbus->core, address, type);
ret = PTR_ERR_OR_ZERO(codec);
if (ret < 0)
return ret;
hda_priv->codec = codec;
dev_set_drvdata(&codec->core.dev, hda_priv);
if ((resp & 0xFFFF0000) == IDISP_VID_INTEL) {
if (!hdev->bus->audio_component) {
if (!hbus->core.audio_component) {
dev_dbg(sdev->dev,
"iDisp hw present but no driver\n");
ret = -ENOENT;
@@ -181,15 +209,12 @@ static int hda_codec_probe(struct snd_sof_dev *sdev, int address,
out:
if (ret < 0) {
snd_hdac_device_unregister(hdev);
put_device(&hdev->dev);
snd_hdac_device_unregister(&codec->core);
put_device(&codec->core.dev);
}
#else
hdev = devm_kzalloc(sdev->dev, sizeof(*hdev), GFP_KERNEL);
if (!hdev)
return -ENOMEM;
ret = snd_hdac_ext_bus_device_init(&hbus->core, address, hdev, HDA_DEV_ASOC);
codec = hda_codec_device_init(&hbus->core, address, HDA_DEV_ASOC);
ret = PTR_ERR_OR_ZERO(codec);
#endif
return ret;

View File

@@ -690,7 +690,7 @@ static bool get_alias_id(struct usb_device *dev, unsigned int *id)
return false;
}
static bool check_delayed_register_option(struct snd_usb_audio *chip, int iface)
static int check_delayed_register_option(struct snd_usb_audio *chip)
{
int i;
unsigned int id, inum;
@@ -699,14 +699,31 @@ static bool check_delayed_register_option(struct snd_usb_audio *chip, int iface)
if (delayed_register[i] &&
sscanf(delayed_register[i], "%x:%x", &id, &inum) == 2 &&
id == chip->usb_id)
return iface < inum;
return inum;
}
return false;
return -1;
}
static const struct usb_device_id usb_audio_ids[]; /* defined below */
/* look for the last interface that matches with our ids and remember it */
static void find_last_interface(struct snd_usb_audio *chip)
{
struct usb_host_config *config = chip->dev->actconfig;
struct usb_interface *intf;
int i;
if (!config)
return;
for (i = 0; i < config->desc.bNumInterfaces; i++) {
intf = config->interface[i];
if (usb_match_id(intf, usb_audio_ids))
chip->last_iface = intf->altsetting[0].desc.bInterfaceNumber;
}
usb_audio_dbg(chip, "Found last interface = %d\n", chip->last_iface);
}
/* look for the corresponding quirk */
static const struct snd_usb_audio_quirk *
get_alias_quirk(struct usb_device *dev, unsigned int id)
@@ -813,6 +830,7 @@ static int usb_audio_probe(struct usb_interface *intf,
err = -ENODEV;
goto __error;
}
find_last_interface(chip);
}
if (chip->num_interfaces >= MAX_CARD_INTERFACES) {
@@ -862,11 +880,11 @@ static int usb_audio_probe(struct usb_interface *intf,
chip->need_delayed_register = false; /* clear again */
}
/* we are allowed to call snd_card_register() many times, but first
* check to see if a device needs to skip it or do anything special
/* register card if we reach to the last interface or to the specified
* one given via option
*/
if (!snd_usb_registration_quirk(chip, ifnum) &&
!check_delayed_register_option(chip, ifnum)) {
if (check_delayed_register_option(chip) == ifnum ||
usb_interface_claimed(usb_ifnum_to_if(dev, chip->last_iface))) {
err = snd_card_register(chip->card);
if (err < 0)
goto __error;

View File

@@ -39,7 +39,9 @@ struct snd_usb_iface_ref {
struct snd_usb_clock_ref {
unsigned char clock;
atomic_t locked;
int opened;
int rate;
bool need_setup;
struct list_head list;
};
@@ -93,12 +95,13 @@ static inline unsigned get_usb_high_speed_rate(unsigned int rate)
*/
static void release_urb_ctx(struct snd_urb_ctx *u)
{
if (u->buffer_size)
if (u->urb && u->buffer_size)
usb_free_coherent(u->ep->chip->dev, u->buffer_size,
u->urb->transfer_buffer,
u->urb->transfer_dma);
usb_free_urb(u->urb);
u->urb = NULL;
u->buffer_size = 0;
}
static const char *usb_error_string(int err)
@@ -758,7 +761,8 @@ bool snd_usb_endpoint_compatible(struct snd_usb_audio *chip,
* The endpoint needs to be closed via snd_usb_endpoint_close() later.
*
* Note that this function doesn't configure the endpoint. The substream
* needs to set it up later via snd_usb_endpoint_configure().
* needs to set it up later via snd_usb_endpoint_set_params() and
* snd_usb_endpoint_prepare().
*/
struct snd_usb_endpoint *
snd_usb_endpoint_open(struct snd_usb_audio *chip,
@@ -801,6 +805,7 @@ snd_usb_endpoint_open(struct snd_usb_audio *chip,
ep = NULL;
goto unlock;
}
ep->clock_ref->opened++;
}
ep->cur_audiofmt = fp;
@@ -924,8 +929,10 @@ void snd_usb_endpoint_close(struct snd_usb_audio *chip,
endpoint_set_interface(chip, ep, false);
if (!--ep->opened) {
if (ep->clock_ref && !atomic_read(&ep->clock_ref->locked))
ep->clock_ref->rate = 0;
if (ep->clock_ref) {
if (!--ep->clock_ref->opened)
ep->clock_ref->rate = 0;
}
ep->iface = 0;
ep->altsetting = 0;
ep->cur_audiofmt = NULL;
@@ -1261,6 +1268,7 @@ static int sync_ep_set_params(struct snd_usb_endpoint *ep)
if (!ep->syncbuf)
return -ENOMEM;
ep->nurbs = SYNC_URBS;
for (i = 0; i < SYNC_URBS; i++) {
struct snd_urb_ctx *u = &ep->urb[i];
u->index = i;
@@ -1280,8 +1288,6 @@ static int sync_ep_set_params(struct snd_usb_endpoint *ep)
u->urb->complete = snd_complete_urb;
}
ep->nurbs = SYNC_URBS;
return 0;
out_of_memory:
@@ -1289,15 +1295,39 @@ static int sync_ep_set_params(struct snd_usb_endpoint *ep)
return -ENOMEM;
}
/* update the rate of the referred clock; return the actual rate */
static int update_clock_ref_rate(struct snd_usb_audio *chip,
struct snd_usb_endpoint *ep)
{
struct snd_usb_clock_ref *clock = ep->clock_ref;
int rate = ep->cur_rate;
if (!clock || clock->rate == rate)
return rate;
if (clock->rate) {
if (atomic_read(&clock->locked))
return clock->rate;
if (clock->rate != rate) {
usb_audio_err(chip, "Mismatched sample rate %d vs %d for EP 0x%x\n",
clock->rate, rate, ep->ep_num);
return clock->rate;
}
}
clock->rate = rate;
clock->need_setup = true;
return rate;
}
/*
* snd_usb_endpoint_set_params: configure an snd_usb_endpoint
*
* It's called either from hw_params callback.
* Determine the number of URBs to be used on this endpoint.
* An endpoint must be configured before it can be started.
* An endpoint that is already running can not be reconfigured.
*/
static int snd_usb_endpoint_set_params(struct snd_usb_audio *chip,
struct snd_usb_endpoint *ep)
int snd_usb_endpoint_set_params(struct snd_usb_audio *chip,
struct snd_usb_endpoint *ep)
{
const struct audioformat *fmt = ep->cur_audiofmt;
int err;
@@ -1349,49 +1379,46 @@ static int snd_usb_endpoint_set_params(struct snd_usb_audio *chip,
ep->maxframesize = ep->maxpacksize / ep->cur_frame_bytes;
ep->curframesize = ep->curpacksize / ep->cur_frame_bytes;
return 0;
return update_clock_ref_rate(chip, ep);
}
static int init_sample_rate(struct snd_usb_audio *chip,
struct snd_usb_endpoint *ep)
{
struct snd_usb_clock_ref *clock = ep->clock_ref;
int err;
int rate, err;
if (clock) {
if (atomic_read(&clock->locked))
return 0;
if (clock->rate == ep->cur_rate)
return 0;
if (clock->rate && clock->rate != ep->cur_rate) {
usb_audio_dbg(chip, "Mismatched sample rate %d vs %d for EP 0x%x\n",
clock->rate, ep->cur_rate, ep->ep_num);
return -EINVAL;
}
rate = update_clock_ref_rate(chip, ep);
if (rate < 0)
return rate;
if (clock && !clock->need_setup)
return 0;
err = snd_usb_init_sample_rate(chip, ep->cur_audiofmt, rate);
if (err < 0) {
if (clock)
clock->rate = 0; /* reset rate */
return err;
}
err = snd_usb_init_sample_rate(chip, ep->cur_audiofmt, ep->cur_rate);
if (err < 0)
return err;
if (clock)
clock->rate = ep->cur_rate;
clock->need_setup = false;
return 0;
}
/*
* snd_usb_endpoint_configure: Configure the endpoint
* snd_usb_endpoint_prepare: Prepare the endpoint
*
* This function sets up the EP to be fully usable state.
* It's called either from hw_params or prepare callback.
* It's called either from prepare callback.
* The function checks need_setup flag, and performs nothing unless needed,
* so it's safe to call this multiple times.
*
* This returns zero if unchanged, 1 if the configuration has changed,
* or a negative error code.
*/
int snd_usb_endpoint_configure(struct snd_usb_audio *chip,
struct snd_usb_endpoint *ep)
int snd_usb_endpoint_prepare(struct snd_usb_audio *chip,
struct snd_usb_endpoint *ep)
{
bool iface_first;
int err = 0;
@@ -1412,9 +1439,6 @@ int snd_usb_endpoint_configure(struct snd_usb_audio *chip,
if (err < 0)
goto unlock;
}
err = snd_usb_endpoint_set_params(chip, ep);
if (err < 0)
goto unlock;
goto done;
}
@@ -1442,10 +1466,6 @@ int snd_usb_endpoint_configure(struct snd_usb_audio *chip,
if (err < 0)
goto unlock;
err = snd_usb_endpoint_set_params(chip, ep);
if (err < 0)
goto unlock;
err = snd_usb_select_mode_quirk(chip, ep->cur_audiofmt);
if (err < 0)
goto unlock;
@@ -1633,8 +1653,7 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep, bool keep_pending)
WRITE_ONCE(ep->sync_source->sync_sink, NULL);
stop_urbs(ep, false, keep_pending);
if (ep->clock_ref)
if (!atomic_dec_return(&ep->clock_ref->locked))
ep->clock_ref->rate = 0;
atomic_dec(&ep->clock_ref->locked);
}
}

View File

@@ -17,8 +17,10 @@ snd_usb_endpoint_open(struct snd_usb_audio *chip,
bool is_sync_ep);
void snd_usb_endpoint_close(struct snd_usb_audio *chip,
struct snd_usb_endpoint *ep);
int snd_usb_endpoint_configure(struct snd_usb_audio *chip,
struct snd_usb_endpoint *ep);
int snd_usb_endpoint_set_params(struct snd_usb_audio *chip,
struct snd_usb_endpoint *ep);
int snd_usb_endpoint_prepare(struct snd_usb_audio *chip,
struct snd_usb_endpoint *ep);
int snd_usb_endpoint_get_clock_rate(struct snd_usb_audio *chip, int clock);
bool snd_usb_endpoint_compatible(struct snd_usb_audio *chip,

View File

@@ -193,8 +193,6 @@ extern int line6_send_raw_message_async(struct usb_line6 *line6,
const char *buffer, int size);
extern int line6_send_sysex_message(struct usb_line6 *line6,
const char *buffer, int size);
extern ssize_t line6_set_raw(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count);
extern int line6_version_request_async(struct usb_line6 *line6);
extern int line6_write_data(struct usb_line6 *line6, unsigned address,
void *data, unsigned datalen);

View File

@@ -433,35 +433,6 @@ static void close_endpoints(struct snd_usb_audio *chip,
}
}
static int configure_endpoints(struct snd_usb_audio *chip,
struct snd_usb_substream *subs)
{
int err;
if (subs->data_endpoint->need_setup) {
/* stop any running stream beforehand */
if (stop_endpoints(subs, false))
sync_pending_stops(subs);
if (subs->sync_endpoint) {
err = snd_usb_endpoint_configure(chip, subs->sync_endpoint);
if (err < 0)
return err;
}
err = snd_usb_endpoint_configure(chip, subs->data_endpoint);
if (err < 0)
return err;
snd_usb_set_format_quirk(subs, subs->cur_audiofmt);
} else {
if (subs->sync_endpoint) {
err = snd_usb_endpoint_configure(chip, subs->sync_endpoint);
if (err < 0)
return err;
}
}
return 0;
}
/*
* hw_params callback
*
@@ -551,7 +522,16 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
subs->cur_audiofmt = fmt;
mutex_unlock(&chip->mutex);
ret = configure_endpoints(chip, subs);
if (!subs->data_endpoint->need_setup)
goto unlock;
if (subs->sync_endpoint) {
ret = snd_usb_endpoint_set_params(chip, subs->sync_endpoint);
if (ret < 0)
goto unlock;
}
ret = snd_usb_endpoint_set_params(chip, subs->data_endpoint);
unlock:
if (ret < 0)
@@ -634,9 +614,18 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
goto unlock;
}
ret = configure_endpoints(chip, subs);
if (subs->sync_endpoint) {
ret = snd_usb_endpoint_prepare(chip, subs->sync_endpoint);
if (ret < 0)
goto unlock;
}
ret = snd_usb_endpoint_prepare(chip, subs->data_endpoint);
if (ret < 0)
goto unlock;
else if (ret > 0)
snd_usb_set_format_quirk(subs, subs->cur_audiofmt);
ret = 0;
/* reset the pointer */
subs->buffer_bytes = frames_to_bytes(runtime, runtime->buffer_size);
@@ -1406,7 +1395,7 @@ static int prepare_playback_urb(struct snd_usb_substream *subs,
transfer_done = subs->transfer_done;
if (subs->lowlatency_playback &&
runtime->status->state != SNDRV_PCM_STATE_DRAINING) {
runtime->state != SNDRV_PCM_STATE_DRAINING) {
unsigned int hwptr = subs->hwptr_done / stride;
/* calculate the byte offset-in-buffer of the appl_ptr */
@@ -1594,7 +1583,7 @@ static int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substrea
return 0;
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_STOP:
stop_endpoints(subs, substream->runtime->status->state == SNDRV_PCM_STATE_DRAINING);
stop_endpoints(subs, substream->runtime->state == SNDRV_PCM_STATE_DRAINING);
snd_usb_endpoint_set_callback(subs->data_endpoint,
NULL, NULL, NULL);
subs->running = 0;

View File

@@ -2985,6 +2985,82 @@ YAMAHA_DEVICE(0x7010, "UB99"),
}
}
},
/* DIGIDESIGN MBOX 3 */
{
USB_DEVICE(0x0dba, 0x5000),
.driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
.vendor_name = "Digidesign",
.product_name = "Mbox 3",
.ifnum = QUIRK_ANY_INTERFACE,
.type = QUIRK_COMPOSITE,
.data = (const struct snd_usb_audio_quirk[]) {
{
.ifnum = 0,
.type = QUIRK_IGNORE_INTERFACE
},
{
.ifnum = 1,
.type = QUIRK_IGNORE_INTERFACE
},
{
.ifnum = 2,
.type = QUIRK_AUDIO_FIXED_ENDPOINT,
.data = &(const struct audioformat) {
.formats = SNDRV_PCM_FMTBIT_S24_3LE,
.channels = 4,
.iface = 2,
.altsetting = 1,
.altset_idx = 1,
.attributes = 0x00,
.endpoint = 0x01,
.ep_attr = USB_ENDPOINT_XFER_ISOC |
USB_ENDPOINT_SYNC_ASYNC,
.rates = SNDRV_PCM_RATE_48000,
.rate_min = 48000,
.rate_max = 48000,
.nr_rates = 1,
.rate_table = (unsigned int[]) {
48000
}
}
},
{
.ifnum = 3,
.type = QUIRK_AUDIO_FIXED_ENDPOINT,
.data = &(const struct audioformat) {
.formats = SNDRV_PCM_FMTBIT_S24_3LE,
.channels = 4,
.iface = 3,
.altsetting = 1,
.altset_idx = 1,
.endpoint = 0x81,
.attributes = 0x00,
.ep_attr = USB_ENDPOINT_XFER_ISOC |
USB_ENDPOINT_SYNC_ASYNC,
.maxpacksize = 0x009c,
.rates = SNDRV_PCM_RATE_48000,
.rate_min = 48000,
.rate_max = 48000,
.nr_rates = 1,
.rate_table = (unsigned int[]) {
48000
}
}
},
{
.ifnum = 4,
.type = QUIRK_MIDI_FIXED_ENDPOINT,
.data = &(const struct snd_usb_midi_endpoint_info) {
.out_cables = 0x0001,
.in_cables = 0x0001
}
},
{
.ifnum = -1
}
}
}
},
{
/* Tascam US122 MKII - playback-only support */
USB_DEVICE_VENDOR_SPEC(0x0644, 0x8021),

View File

@@ -1020,6 +1020,304 @@ static int snd_usb_axefx3_boot_quirk(struct usb_device *dev)
return 0;
}
static void mbox3_setup_48_24_magic(struct usb_device *dev)
{
/* The Mbox 3 is "little endian" */
/* max volume is: 0x0000. */
/* min volume is: 0x0080 (shown in little endian form) */
/* Load 48000Hz rate into buffer */
u8 com_buff[4] = {0x80, 0xbb, 0x00, 0x00};
/* Set 48000Hz sample rate */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
0x01, 0x21, 0x0100, 0x0001, &com_buff, 4); //Is this really needed?
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
0x01, 0x21, 0x0100, 0x8101, &com_buff, 4);
/* Deactivate Tuner */
/* on = 0x01*/
/* off = 0x00*/
com_buff[0] = 0x00;
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
0x01, 0x21, 0x0003, 0x2001, &com_buff, 1);
/* Set clock source to Internal (as opposed to S/PDIF) */
com_buff[0] = 0x01;
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0100, 0x8001, &com_buff, 1);
/* Mute the hardware loopbacks to start the device in a known state. */
com_buff[0] = 0x00;
com_buff[1] = 0x80;
/* Analogue input 1 left channel: */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0110, 0x4001, &com_buff, 2);
/* Analogue input 1 right channel: */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0111, 0x4001, &com_buff, 2);
/* Analogue input 2 left channel: */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0114, 0x4001, &com_buff, 2);
/* Analogue input 2 right channel: */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0115, 0x4001, &com_buff, 2);
/* Analogue input 3 left channel: */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0118, 0x4001, &com_buff, 2);
/* Analogue input 3 right channel: */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0119, 0x4001, &com_buff, 2);
/* Analogue input 4 left channel: */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x011c, 0x4001, &com_buff, 2);
/* Analogue input 4 right channel: */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x011d, 0x4001, &com_buff, 2);
/* Set software sends to output */
com_buff[0] = 0x00;
com_buff[1] = 0x00;
/* Analogue software return 1 left channel: */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0100, 0x4001, &com_buff, 2);
com_buff[0] = 0x00;
com_buff[1] = 0x80;
/* Analogue software return 1 right channel: */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0101, 0x4001, &com_buff, 2);
com_buff[0] = 0x00;
com_buff[1] = 0x80;
/* Analogue software return 2 left channel: */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0104, 0x4001, &com_buff, 2);
com_buff[0] = 0x00;
com_buff[1] = 0x00;
/* Analogue software return 2 right channel: */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0105, 0x4001, &com_buff, 2);
com_buff[0] = 0x00;
com_buff[1] = 0x80;
/* Analogue software return 3 left channel: */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0108, 0x4001, &com_buff, 2);
/* Analogue software return 3 right channel: */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0109, 0x4001, &com_buff, 2);
/* Analogue software return 4 left channel: */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x010c, 0x4001, &com_buff, 2);
/* Analogue software return 4 right channel: */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x010d, 0x4001, &com_buff, 2);
/* Return to muting sends */
com_buff[0] = 0x00;
com_buff[1] = 0x80;
/* Analogue fx return left channel: */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0120, 0x4001, &com_buff, 2);
/* Analogue fx return right channel: */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0121, 0x4001, &com_buff, 2);
/* Analogue software input 1 fx send: */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0100, 0x4201, &com_buff, 2);
/* Analogue software input 2 fx send: */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0101, 0x4201, &com_buff, 2);
/* Analogue software input 3 fx send: */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0102, 0x4201, &com_buff, 2);
/* Analogue software input 4 fx send: */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0103, 0x4201, &com_buff, 2);
/* Analogue input 1 fx send: */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0104, 0x4201, &com_buff, 2);
/* Analogue input 2 fx send: */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0105, 0x4201, &com_buff, 2);
/* Analogue input 3 fx send: */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0106, 0x4201, &com_buff, 2);
/* Analogue input 4 fx send: */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0107, 0x4201, &com_buff, 2);
/* Toggle allowing host control */
com_buff[0] = 0x02;
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
3, 0x21, 0x0000, 0x2001, &com_buff, 1);
/* Do not dim fx returns */
com_buff[0] = 0x00;
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
3, 0x21, 0x0002, 0x2001, &com_buff, 1);
/* Do not set fx returns to mono */
com_buff[0] = 0x00;
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
3, 0x21, 0x0001, 0x2001, &com_buff, 1);
/* Mute the S/PDIF hardware loopback
* same odd volume logic here as above
*/
com_buff[0] = 0x00;
com_buff[1] = 0x80;
/* S/PDIF hardware input 1 left channel */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0112, 0x4001, &com_buff, 2);
/* S/PDIF hardware input 1 right channel */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0113, 0x4001, &com_buff, 2);
/* S/PDIF hardware input 2 left channel */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0116, 0x4001, &com_buff, 2);
/* S/PDIF hardware input 2 right channel */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0117, 0x4001, &com_buff, 2);
/* S/PDIF hardware input 3 left channel */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x011a, 0x4001, &com_buff, 2);
/* S/PDIF hardware input 3 right channel */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x011b, 0x4001, &com_buff, 2);
/* S/PDIF hardware input 4 left channel */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x011e, 0x4001, &com_buff, 2);
/* S/PDIF hardware input 4 right channel */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x011f, 0x4001, &com_buff, 2);
/* S/PDIF software return 1 left channel */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0102, 0x4001, &com_buff, 2);
/* S/PDIF software return 1 right channel */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0103, 0x4001, &com_buff, 2);
/* S/PDIF software return 2 left channel */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0106, 0x4001, &com_buff, 2);
/* S/PDIF software return 2 right channel */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0107, 0x4001, &com_buff, 2);
com_buff[0] = 0x00;
com_buff[1] = 0x00;
/* S/PDIF software return 3 left channel */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x010a, 0x4001, &com_buff, 2);
com_buff[0] = 0x00;
com_buff[1] = 0x80;
/* S/PDIF software return 3 right channel */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x010b, 0x4001, &com_buff, 2);
/* S/PDIF software return 4 left channel */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x010e, 0x4001, &com_buff, 2);
com_buff[0] = 0x00;
com_buff[1] = 0x00;
/* S/PDIF software return 4 right channel */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x010f, 0x4001, &com_buff, 2);
com_buff[0] = 0x00;
com_buff[1] = 0x80;
/* S/PDIF fx returns left channel */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0122, 0x4001, &com_buff, 2);
/* S/PDIF fx returns right channel */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0123, 0x4001, &com_buff, 2);
/* Set the dropdown "Effect" to the first option */
/* Room1 = 0x00 */
/* Room2 = 0x01 */
/* Room3 = 0x02 */
/* Hall 1 = 0x03 */
/* Hall 2 = 0x04 */
/* Plate = 0x05 */
/* Delay = 0x06 */
/* Echo = 0x07 */
com_buff[0] = 0x00;
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0200, 0x4301, &com_buff, 1); /* max is 0xff */
/* min is 0x00 */
/* Set the effect duration to 0 */
/* max is 0xffff */
/* min is 0x0000 */
com_buff[0] = 0x00;
com_buff[1] = 0x00;
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0400, 0x4301, &com_buff, 2);
/* Set the effect volume and feedback to 0 */
/* max is 0xff */
/* min is 0x00 */
com_buff[0] = 0x00;
/* feedback: */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0500, 0x4301, &com_buff, 1);
/* volume: */
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1, 0x21, 0x0300, 0x4301, &com_buff, 1);
/* Set soft button hold duration */
/* 0x03 = 250ms */
/* 0x05 = 500ms DEFAULT */
/* 0x08 = 750ms */
/* 0x0a = 1sec */
com_buff[0] = 0x05;
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
3, 0x21, 0x0005, 0x2001, &com_buff, 1);
/* Use dim LEDs for button of state */
com_buff[0] = 0x00;
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
3, 0x21, 0x0004, 0x2001, &com_buff, 1);
}
#define MBOX3_DESCRIPTOR_SIZE 464
static int snd_usb_mbox3_boot_quirk(struct usb_device *dev)
{
struct usb_host_config *config = dev->actconfig;
int err;
int descriptor_size;
descriptor_size = le16_to_cpu(get_cfg_desc(config)->wTotalLength);
if (descriptor_size != MBOX3_DESCRIPTOR_SIZE) {
dev_err(&dev->dev, "Invalid descriptor size=%d.\n", descriptor_size);
return -ENODEV;
}
dev_dbg(&dev->dev, "device initialised!\n");
err = usb_get_descriptor(dev, USB_DT_DEVICE, 0,
&dev->descriptor, sizeof(dev->descriptor));
config = dev->actconfig;
if (err < 0)
dev_dbg(&dev->dev, "error usb_get_descriptor: %d\n", err);
err = usb_reset_configuration(dev);
if (err < 0)
dev_dbg(&dev->dev, "error usb_reset_configuration: %d\n", err);
dev_dbg(&dev->dev, "mbox3_boot: new boot length = %d\n",
le16_to_cpu(get_cfg_desc(config)->wTotalLength));
mbox3_setup_48_24_magic(dev);
dev_info(&dev->dev, "Digidesign Mbox 3: 24bit 48kHz");
return 0; /* Successful boot */
}
#define MICROBOOK_BUF_SIZE 128
@@ -1324,6 +1622,10 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev,
case USB_ID(0x0dba, 0x3000):
/* Digidesign Mbox 2 */
return snd_usb_mbox2_boot_quirk(dev);
case USB_ID(0x0dba, 0x5000):
/* Digidesign Mbox 3 */
return snd_usb_mbox3_boot_quirk(dev);
case USB_ID(0x1235, 0x0010): /* Focusrite Novation Saffire 6 USB */
case USB_ID(0x1235, 0x0018): /* Focusrite Novation Twitch */
@@ -1728,48 +2030,6 @@ void snd_usb_audioformat_attributes_quirk(struct snd_usb_audio *chip,
}
}
/*
* registration quirk:
* the registration is skipped if a device matches with the given ID,
* unless the interface reaches to the defined one. This is for delaying
* the registration until the last known interface, so that the card and
* devices appear at the same time.
*/
struct registration_quirk {
unsigned int usb_id; /* composed via USB_ID() */
unsigned int interface; /* the interface to trigger register */
};
#define REG_QUIRK_ENTRY(vendor, product, iface) \
{ .usb_id = USB_ID(vendor, product), .interface = (iface) }
static const struct registration_quirk registration_quirks[] = {
REG_QUIRK_ENTRY(0x0951, 0x16d8, 2), /* Kingston HyperX AMP */
REG_QUIRK_ENTRY(0x0951, 0x16ed, 2), /* Kingston HyperX Cloud Alpha S */
REG_QUIRK_ENTRY(0x0951, 0x16ea, 2), /* Kingston HyperX Cloud Flight S */
REG_QUIRK_ENTRY(0x0ecb, 0x1f46, 2), /* JBL Quantum 600 */
REG_QUIRK_ENTRY(0x0ecb, 0x1f47, 2), /* JBL Quantum 800 */
REG_QUIRK_ENTRY(0x0ecb, 0x1f4c, 2), /* JBL Quantum 400 */
REG_QUIRK_ENTRY(0x0ecb, 0x2039, 2), /* JBL Quantum 400 */
REG_QUIRK_ENTRY(0x0ecb, 0x203c, 2), /* JBL Quantum 600 */
REG_QUIRK_ENTRY(0x0ecb, 0x203e, 2), /* JBL Quantum 800 */
{ 0 } /* terminator */
};
/* return true if skipping registration */
bool snd_usb_registration_quirk(struct snd_usb_audio *chip, int iface)
{
const struct registration_quirk *q;
for (q = registration_quirks; q->usb_id; q++)
if (chip->usb_id == q->usb_id)
return iface < q->interface;
/* Register as normal */
return false;
}
/*
* driver behavior quirk flags
*/

View File

@@ -48,8 +48,6 @@ void snd_usb_audioformat_attributes_quirk(struct snd_usb_audio *chip,
struct audioformat *fp,
int stream);
bool snd_usb_registration_quirk(struct snd_usb_audio *chip, int iface);
void snd_usb_init_quirk_flags(struct snd_usb_audio *chip);
#endif /* __USBAUDIO_QUIRKS_H */

View File

@@ -1222,12 +1222,6 @@ static int __snd_usb_parse_audio_interface(struct snd_usb_audio *chip,
if (err < 0)
return err;
}
/* try to set the interface... */
usb_set_interface(chip->dev, iface_no, 0);
snd_usb_init_pitch(chip, fp);
snd_usb_init_sample_rate(chip, fp, fp->rate_max);
usb_set_interface(chip->dev, iface_no, altno);
}
return 0;
}

View File

@@ -37,6 +37,7 @@ struct snd_usb_audio {
unsigned int quirk_flags;
unsigned int need_delayed_register:1; /* warn for delayed registration */
int num_interfaces;
int last_iface;
int num_suspended_intf;
int sample_rate_read_error;

View File

@@ -822,8 +822,7 @@ static int snd_usx2y_pcm_hw_free(struct snd_pcm_substream *substream)
usx2y_urbs_release(subs);
if (!cap_subs->pcm_substream ||
!cap_subs->pcm_substream->runtime ||
!cap_subs->pcm_substream->runtime->status ||
cap_subs->pcm_substream->runtime->status->state < SNDRV_PCM_STATE_PREPARED) {
cap_subs->pcm_substream->runtime->state < SNDRV_PCM_STATE_PREPARED) {
atomic_set(&cap_subs->state, STATE_STOPPED);
usx2y_urbs_release(cap_subs);
}

View File

@@ -374,8 +374,7 @@ static int snd_usx2y_usbpcm_hw_free(struct snd_pcm_substream *substream)
usx2y_usbpcm_urbs_release(subs);
if (!cap_subs->pcm_substream ||
!cap_subs->pcm_substream->runtime ||
!cap_subs->pcm_substream->runtime->status ||
cap_subs->pcm_substream->runtime->status->state < SNDRV_PCM_STATE_PREPARED) {
cap_subs->pcm_substream->runtime->state < SNDRV_PCM_STATE_PREPARED) {
atomic_set(&cap_subs->state, STATE_STOPPED);
if (cap_subs2)
atomic_set(&cap_subs2->state, STATE_STOPPED);