mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-02 13:23:35 -04:00
Merge branch 'for-next' into for-linus
This commit is contained in:
@@ -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
|
||||
==============
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) \
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) \
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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__
|
||||
|
||||
@@ -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__
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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__
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
*
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 },
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 */
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user