Merge branch 'for-next' into for-linus

4.18-rc1 merge material.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
Takashi Iwai 2018-06-04 11:41:48 +02:00
commit cdbc653a04
129 changed files with 8718 additions and 1444 deletions

View file

@ -2224,6 +2224,13 @@ quirk_alias
Quirk alias list, pass strings like ``0123abcd:5678beef``, which
applies the existing quirk for the device 5678:beef to a new
device 0123:abcd.
use_vmalloc
Use vmalloc() for allocations of the PCM buffers (default: yes).
For architectures with non-coherent memory like ARM or MIPS, the
mmap access may give inconsistent results with vmalloc'ed
buffers. If mmap is used on such architectures, turn off this
option, so that the DMA-coherent buffers are allocated and used
instead.
This module supports multiple devices, autoprobe and hotplugging.

View file

@ -263,6 +263,8 @@ hp-dock
HP dock support
mute-led-gpio
Mute LED control via GPIO
hp-mic-fix
Fix for headset mic pin on HP boxes
STAC9200
========

View file

@ -15494,6 +15494,13 @@ S: Supported
F: arch/x86/xen/*swiotlb*
F: drivers/xen/*swiotlb*
XEN SOUND FRONTEND DRIVER
M: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>
L: xen-devel@lists.xenproject.org (moderated for non-subscribers)
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
S: Supported
F: sound/xen/*
XFS FILESYSTEM
M: Darrick J. Wong <darrick.wong@oracle.com>
M: linux-xfs@vger.kernel.org

View file

@ -189,6 +189,13 @@ struct uac2_iso_endpoint_descriptor {
#define UAC2_CONTROL_DATA_OVERRUN (3 << 2)
#define UAC2_CONTROL_DATA_UNDERRUN (3 << 4)
/* 5.2.5.4.2 Connector Control Parameter Block */
struct uac2_connectors_ctl_blk {
__u8 bNrChannels;
__le32 bmChannelConfig;
__u8 iChannelNames;
} __attribute__((packed));
/* 6.1 Interrupt Data Message */
#define UAC2_INTERRUPT_DATA_MSG_VENDOR (1 << 0)

View file

@ -221,6 +221,12 @@ struct uac3_iso_endpoint_descriptor {
__le16 wLockDelay;
} __attribute__((packed));
/* 5.2.1.6.1 INSERTION CONTROL PARAMETER BLOCK */
struct uac3_insertion_ctl_blk {
__u8 bSize;
__u8 bmConInserted;
} __attribute__ ((packed));
/* 6.1 INTERRUPT DATA MESSAGE */
struct uac3_interrupt_data_msg {
__u8 bInfo;
@ -392,4 +398,38 @@ struct uac3_interrupt_data_msg {
#define UAC3_AC_ACTIVE_INTERFACE_CONTROL 0x01
#define UAC3_AC_POWER_DOMAIN_CONTROL 0x02
/* A.23.5 TERMINAL CONTROL SELECTORS */
#define UAC3_TE_UNDEFINED 0x00
#define UAC3_TE_INSERTION 0x01
#define UAC3_TE_OVERLOAD 0x02
#define UAC3_TE_UNDERFLOW 0x03
#define UAC3_TE_OVERFLOW 0x04
#define UAC3_TE_LATENCY 0x05
/* BADD predefined Unit/Terminal values */
#define UAC3_BADD_IT_ID1 1 /* Input Terminal ID1: bTerminalID = 1 */
#define UAC3_BADD_FU_ID2 2 /* Feature Unit ID2: bUnitID = 2 */
#define UAC3_BADD_OT_ID3 3 /* Output Terminal ID3: bTerminalID = 3 */
#define UAC3_BADD_IT_ID4 4 /* Input Terminal ID4: bTerminalID = 4 */
#define UAC3_BADD_FU_ID5 5 /* Feature Unit ID5: bUnitID = 5 */
#define UAC3_BADD_OT_ID6 6 /* Output Terminal ID6: bTerminalID = 6 */
#define UAC3_BADD_FU_ID7 7 /* Feature Unit ID7: bUnitID = 7 */
#define UAC3_BADD_MU_ID8 8 /* Mixer Unit ID8: bUnitID = 8 */
#define UAC3_BADD_CS_ID9 9 /* Clock Source Entity ID9: bClockID = 9 */
#define UAC3_BADD_PD_ID10 10 /* Power Domain ID10: bPowerDomainID = 10 */
#define UAC3_BADD_PD_ID11 11 /* Power Domain ID11: bPowerDomainID = 11 */
/* BADD wMaxPacketSize of AS endpoints */
#define UAC3_BADD_EP_MAXPSIZE_SYNC_MONO_16 0x0060
#define UAC3_BADD_EP_MAXPSIZE_ASYNC_MONO_16 0x0062
#define UAC3_BADD_EP_MAXPSIZE_SYNC_MONO_24 0x0090
#define UAC3_BADD_EP_MAXPSIZE_ASYNC_MONO_24 0x0093
#define UAC3_BADD_EP_MAXPSIZE_SYNC_STEREO_16 0x00C0
#define UAC3_BADD_EP_MAXPSIZE_ASYNC_STEREO_16 0x00C4
#define UAC3_BADD_EP_MAXPSIZE_SYNC_STEREO_24 0x0120
#define UAC3_BADD_EP_MAXPSIZE_ASYNC_STEREO_24 0x0126
/* BADD sample rate is always fixed to 48kHz */
#define UAC3_BADD_SAMPLING_RATE 48000
#endif /* __LINUX_USB_AUDIO_V3_H */

View file

@ -51,7 +51,6 @@ struct completion;
*/
enum snd_device_type {
SNDRV_DEV_LOWLEVEL,
SNDRV_DEV_CONTROL,
SNDRV_DEV_INFO,
SNDRV_DEV_BUS,
SNDRV_DEV_CODEC,
@ -62,6 +61,7 @@ enum snd_device_type {
SNDRV_DEV_SEQUENCER,
SNDRV_DEV_HWDEP,
SNDRV_DEV_JACK,
SNDRV_DEV_CONTROL, /* NOTE: this must be the last one */
};
enum snd_device_state {

View file

@ -1610,7 +1610,7 @@ struct snd_emu10k1_fx8010_pcm {
struct snd_pcm_indirect pcm_rec;
unsigned int tram_pos;
unsigned int tram_shift;
struct snd_emu10k1_fx8010_irq *irq;
struct snd_emu10k1_fx8010_irq irq;
};
struct snd_emu10k1_fx8010 {
@ -1902,7 +1902,7 @@ int snd_emu10k1_fx8010_register_irq_handler(struct snd_emu10k1 *emu,
snd_fx8010_irq_handler_t *handler,
unsigned char gpr_running,
void *private_data,
struct snd_emu10k1_fx8010_irq **r_irq);
struct snd_emu10k1_fx8010_irq *irq);
int snd_emu10k1_fx8010_unregister_irq_handler(struct snd_emu10k1 *emu,
struct snd_emu10k1_fx8010_irq *irq);

View file

@ -571,4 +571,9 @@ static inline unsigned int snd_array_index(struct snd_array *array, void *ptr)
return (unsigned long)(ptr - array->list) / array->elem_size;
}
/* a helper macro to iterate for each snd_array element */
#define snd_array_for_each(array, idx, ptr) \
for ((idx) = 0, (ptr) = (array)->list; (idx) < (array)->used; \
(ptr) = snd_array_elem(array, ++(idx)))
#endif /* __SOUND_HDAUDIO_H */

View file

@ -34,11 +34,9 @@ struct snd_dma_device {
struct device *dev; /* generic device */
};
#ifndef snd_dma_pci_data
#define snd_dma_pci_data(pci) (&(pci)->dev)
#define snd_dma_isa_data() NULL
#define snd_dma_continuous_data(x) ((struct device *)(__force unsigned long)(x))
#endif
/*

View file

@ -285,9 +285,22 @@ static inline __u8 uac_mixer_unit_iChannelNames(struct uac_mixer_unit_descriptor
static inline __u8 *uac_mixer_unit_bmControls(struct uac_mixer_unit_descriptor *desc,
int protocol)
{
return (protocol == UAC_VERSION_1) ?
&desc->baSourceID[desc->bNrInPins + 4] :
&desc->baSourceID[desc->bNrInPins + 6];
switch (protocol) {
case UAC_VERSION_1:
return &desc->baSourceID[desc->bNrInPins + 4];
case UAC_VERSION_2:
return &desc->baSourceID[desc->bNrInPins + 6];
case UAC_VERSION_3:
return &desc->baSourceID[desc->bNrInPins + 2];
default:
return NULL;
}
}
static inline __u16 uac3_mixer_unit_wClusterDescrID(struct uac_mixer_unit_descriptor *desc)
{
return (desc->baSourceID[desc->bNrInPins + 1] << 8) |
desc->baSourceID[desc->bNrInPins];
}
static inline __u8 uac_mixer_unit_iMixer(struct uac_mixer_unit_descriptor *desc)

View file

@ -42,6 +42,10 @@
#define SNDRV_CTL_TLVD_LENGTH(...) \
((unsigned int)sizeof((const unsigned int[]) { __VA_ARGS__ }))
/* Accessor offsets for TLV data items */
#define SNDRV_CTL_TLVO_TYPE 0
#define SNDRV_CTL_TLVO_LEN 1
#define SNDRV_CTL_TLVD_CONTAINER_ITEM(...) \
SNDRV_CTL_TLVD_ITEM(SNDRV_CTL_TLVT_CONTAINER, __VA_ARGS__)
#define SNDRV_CTL_TLVD_DECLARE_CONTAINER(name, ...) \
@ -61,6 +65,10 @@
SNDRV_CTL_TLVD_DB_SCALE_ITEM(min, step, mute) \
}
/* Accessor offsets for min, mute and step items in dB scale type TLV */
#define SNDRV_CTL_TLVO_DB_SCALE_MIN 2
#define SNDRV_CTL_TLVO_DB_SCALE_MUTE_AND_STEP 3
/* dB scale specified with min/max values instead of step */
#define SNDRV_CTL_TLVD_DB_MINMAX_ITEM(min_dB, max_dB) \
SNDRV_CTL_TLVD_ITEM(SNDRV_CTL_TLVT_DB_MINMAX, (min_dB), (max_dB))
@ -75,6 +83,10 @@
SNDRV_CTL_TLVD_DB_MINMAX_MUTE_ITEM(min_dB, max_dB) \
}
/* Accessor offsets for min, max items in db-minmax types of TLV. */
#define SNDRV_CTL_TLVO_DB_MINMAX_MIN 2
#define SNDRV_CTL_TLVO_DB_MINMAX_MAX 3
/* linear volume between min_dB and max_dB (.01dB unit) */
#define SNDRV_CTL_TLVD_DB_LINEAR_ITEM(min_dB, max_dB) \
SNDRV_CTL_TLVD_ITEM(SNDRV_CTL_TLVT_DB_LINEAR, (min_dB), (max_dB))
@ -83,6 +95,10 @@
SNDRV_CTL_TLVD_DB_LINEAR_ITEM(min_dB, max_dB) \
}
/* Accessor offsets for min, max items in db-linear type of TLV. */
#define SNDRV_CTL_TLVO_DB_LINEAR_MIN 2
#define SNDRV_CTL_TLVO_DB_LINEAR_MAX 3
/* dB range container:
* Items in dB range container must be ordered by their values and by their
* dB values. This implies that larger values must correspond with larger

View file

@ -96,6 +96,8 @@ source "sound/x86/Kconfig"
source "sound/synth/Kconfig"
source "sound/xen/Kconfig"
endif # SND
endif # !UML

View file

@ -5,7 +5,7 @@
obj-$(CONFIG_SOUND) += soundcore.o
obj-$(CONFIG_DMASOUND) += oss/dmasound/
obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ sh/ synth/ usb/ \
firewire/ sparc/ spi/ parisc/ pcmcia/ mips/ soc/ atmel/ hda/ x86/
firewire/ sparc/ spi/ parisc/ pcmcia/ mips/ soc/ atmel/ hda/ x86/ xen/
obj-$(CONFIG_SND_AOA) += aoa/
# This one must be compilable even if sound is configured out

View file

@ -1001,7 +1001,7 @@ static int snd_compress_proc_init(struct snd_compr *compr)
compr->card->proc_root);
if (!entry)
return -ENOMEM;
entry->mode = S_IFDIR | S_IRUGO | S_IXUGO;
entry->mode = S_IFDIR | 0555;
if (snd_info_register(entry) < 0) {
snd_info_free_entry(entry);
return -ENOMEM;

View file

@ -240,6 +240,15 @@ void snd_device_free_all(struct snd_card *card)
if (snd_BUG_ON(!card))
return;
list_for_each_entry_safe_reverse(dev, next, &card->devices, list) {
/* exception: free ctl and lowlevel stuff later */
if (dev->type == SNDRV_DEV_CONTROL ||
dev->type == SNDRV_DEV_LOWLEVEL)
continue;
__snd_device_free(dev);
}
/* free all */
list_for_each_entry_safe_reverse(dev, next, &card->devices, list)
__snd_device_free(dev);
}

View file

@ -454,7 +454,7 @@ static struct snd_info_entry *create_subdir(struct module *mod,
entry = snd_info_create_module_entry(mod, name, NULL);
if (!entry)
return NULL;
entry->mode = S_IFDIR | S_IRUGO | S_IXUGO;
entry->mode = S_IFDIR | 0555;
if (snd_info_register(entry) < 0) {
snd_info_free_entry(entry);
return NULL;
@ -470,7 +470,7 @@ int __init snd_info_init(void)
snd_proc_root = snd_info_create_entry("asound", NULL);
if (!snd_proc_root)
return -ENOMEM;
snd_proc_root->mode = S_IFDIR | S_IRUGO | S_IXUGO;
snd_proc_root->mode = S_IFDIR | 0555;
snd_proc_root->p = proc_mkdir("asound", NULL);
if (!snd_proc_root->p)
goto error;
@ -716,7 +716,7 @@ snd_info_create_entry(const char *name, struct snd_info_entry *parent)
kfree(entry);
return NULL;
}
entry->mode = S_IFREG | S_IRUGO;
entry->mode = S_IFREG | 0444;
entry->content = SNDRV_INFO_CONTENT_TEXT;
mutex_init(&entry->access);
INIT_LIST_HEAD(&entry->children);

View file

@ -703,7 +703,7 @@ card_id_store_attr(struct device *dev, struct device_attribute *attr,
return count;
}
static DEVICE_ATTR(id, S_IRUGO | S_IWUSR, card_id_show_attr, card_id_store_attr);
static DEVICE_ATTR(id, 0644, card_id_show_attr, card_id_store_attr);
static ssize_t
card_number_show_attr(struct device *dev,
@ -713,7 +713,7 @@ card_number_show_attr(struct device *dev,
return scnprintf(buf, PAGE_SIZE, "%i\n", card->number);
}
static DEVICE_ATTR(number, S_IRUGO, card_number_show_attr, NULL);
static DEVICE_ATTR(number, 0444, card_number_show_attr, NULL);
static struct attribute *card_dev_attrs[] = {
&dev_attr_id.attr,

View file

@ -1247,7 +1247,7 @@ static void snd_mixer_oss_proc_init(struct snd_mixer_oss *mixer)
if (! entry)
return;
entry->content = SNDRV_INFO_CONTENT_TEXT;
entry->mode = S_IFREG | S_IRUGO | S_IWUSR;
entry->mode = S_IFREG | 0644;
entry->c.text.read = snd_mixer_oss_proc_read;
entry->c.text.write = snd_mixer_oss_proc_write;
entry->private_data = mixer;

View file

@ -3045,7 +3045,7 @@ static void snd_pcm_oss_proc_init(struct snd_pcm *pcm)
continue;
if ((entry = snd_info_create_card_entry(pcm->card, "oss", pstr->proc_root)) != NULL) {
entry->content = SNDRV_INFO_CONTENT_TEXT;
entry->mode = S_IFREG | S_IRUGO | S_IWUSR;
entry->mode = S_IFREG | 0644;
entry->c.text.read = snd_pcm_oss_proc_read;
entry->c.text.write = snd_pcm_oss_proc_write;
entry->private_data = pstr;

View file

@ -530,7 +530,7 @@ static int snd_pcm_stream_proc_init(struct snd_pcm_str *pstr)
pcm->card->proc_root);
if (!entry)
return -ENOMEM;
entry->mode = S_IFDIR | S_IRUGO | S_IXUGO;
entry->mode = S_IFDIR | 0555;
if (snd_info_register(entry) < 0) {
snd_info_free_entry(entry);
return -ENOMEM;
@ -552,7 +552,7 @@ static int snd_pcm_stream_proc_init(struct snd_pcm_str *pstr)
if (entry) {
entry->c.text.read = snd_pcm_xrun_debug_read;
entry->c.text.write = snd_pcm_xrun_debug_write;
entry->mode |= S_IWUSR;
entry->mode |= 0200;
entry->private_data = pstr;
if (snd_info_register(entry) < 0) {
snd_info_free_entry(entry);
@ -590,7 +590,7 @@ static int snd_pcm_substream_proc_init(struct snd_pcm_substream *substream)
substream->pstr->proc_root);
if (!entry)
return -ENOMEM;
entry->mode = S_IFDIR | S_IRUGO | S_IXUGO;
entry->mode = S_IFDIR | 0555;
if (snd_info_register(entry) < 0) {
snd_info_free_entry(entry);
return -ENOMEM;
@ -647,7 +647,7 @@ static int snd_pcm_substream_proc_init(struct snd_pcm_substream *substream)
entry->private_data = substream;
entry->c.text.read = NULL;
entry->c.text.write = snd_pcm_xrun_injection_write;
entry->mode = S_IFREG | S_IWUSR;
entry->mode = S_IFREG | 0200;
if (snd_info_register(entry) < 0) {
snd_info_free_entry(entry);
entry = NULL;
@ -1087,7 +1087,7 @@ static ssize_t show_pcm_class(struct device *dev,
return snprintf(buf, PAGE_SIZE, "%s\n", str);
}
static DEVICE_ATTR(pcm_class, S_IRUGO, show_pcm_class, NULL);
static DEVICE_ATTR(pcm_class, 0444, show_pcm_class, NULL);
static struct attribute *pcm_dev_attrs[] = {
&dev_attr_pcm_class.attr,
NULL

View file

@ -45,10 +45,7 @@ static int snd_pcm_ioctl_rewind_compat(struct snd_pcm_substream *substream,
if (get_user(frames, src))
return -EFAULT;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
err = snd_pcm_playback_rewind(substream, frames);
else
err = snd_pcm_capture_rewind(substream, frames);
err = snd_pcm_rewind(substream, frames);
if (put_user(err, src))
return -EFAULT;
return err < 0 ? err : 0;
@ -62,10 +59,7 @@ static int snd_pcm_ioctl_forward_compat(struct snd_pcm_substream *substream,
if (get_user(frames, src))
return -EFAULT;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
err = snd_pcm_playback_forward(substream, frames);
else
err = snd_pcm_capture_forward(substream, frames);
err = snd_pcm_forward(substream, frames);
if (put_user(err, src))
return -EFAULT;
return err < 0 ? err : 0;

View file

@ -191,10 +191,7 @@ int snd_pcm_update_state(struct snd_pcm_substream *substream,
{
snd_pcm_uframes_t avail;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
avail = snd_pcm_playback_avail(runtime);
else
avail = snd_pcm_capture_avail(runtime);
avail = snd_pcm_avail(substream);
if (avail > runtime->avail_max)
runtime->avail_max = avail;
if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
@ -1856,10 +1853,7 @@ static int wait_for_avail(struct snd_pcm_substream *substream,
* This check must happen after been added to the waitqueue
* and having current state be INTERRUPTIBLE.
*/
if (is_playback)
avail = snd_pcm_playback_avail(runtime);
else
avail = snd_pcm_capture_avail(runtime);
avail = snd_pcm_avail(substream);
if (avail >= runtime->twake)
break;
snd_pcm_stream_unlock_irq(substream);
@ -2175,10 +2169,7 @@ snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream,
runtime->twake = runtime->control->avail_min ? : 1;
if (runtime->status->state == SNDRV_PCM_STATE_RUNNING)
snd_pcm_update_hw_ptr(substream);
if (is_playback)
avail = snd_pcm_playback_avail(runtime);
else
avail = snd_pcm_capture_avail(runtime);
avail = snd_pcm_avail(substream);
while (size > 0) {
snd_pcm_uframes_t frames, appl_ptr, appl_ofs;
snd_pcm_uframes_t cont;

View file

@ -36,6 +36,24 @@ int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream);
void snd_pcm_playback_silence(struct snd_pcm_substream *substream,
snd_pcm_uframes_t new_hw_ptr);
static inline snd_pcm_uframes_t
snd_pcm_avail(struct snd_pcm_substream *substream)
{
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
return snd_pcm_playback_avail(substream->runtime);
else
return snd_pcm_capture_avail(substream->runtime);
}
static inline snd_pcm_uframes_t
snd_pcm_hw_avail(struct snd_pcm_substream *substream)
{
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
return snd_pcm_playback_hw_avail(substream->runtime);
else
return snd_pcm_capture_hw_avail(substream->runtime);
}
#ifdef CONFIG_SND_PCM_TIMER
void snd_pcm_timer_resolution_change(struct snd_pcm_substream *substream);
void snd_pcm_timer_init(struct snd_pcm_substream *substream);

View file

@ -201,7 +201,7 @@ static inline void preallocate_info_init(struct snd_pcm_substream *substream)
if ((entry = snd_info_create_card_entry(substream->pcm->card, "prealloc", substream->proc_root)) != NULL) {
entry->c.text.read = snd_pcm_lib_preallocate_proc_read;
entry->c.text.write = snd_pcm_lib_preallocate_proc_write;
entry->mode |= S_IWUSR;
entry->mode |= 0200;
entry->private_data = substream;
if (snd_info_register(entry) < 0) {
snd_info_free_entry(entry);

View file

@ -99,6 +99,57 @@ static inline void down_write_nonblock(struct rw_semaphore *lock)
cond_resched();
}
#define PCM_LOCK_DEFAULT 0
#define PCM_LOCK_IRQ 1
#define PCM_LOCK_IRQSAVE 2
static unsigned long __snd_pcm_stream_lock_mode(struct snd_pcm_substream *substream,
unsigned int mode)
{
unsigned long flags = 0;
if (substream->pcm->nonatomic) {
down_read_nested(&snd_pcm_link_rwsem, SINGLE_DEPTH_NESTING);
mutex_lock(&substream->self_group.mutex);
} else {
switch (mode) {
case PCM_LOCK_DEFAULT:
read_lock(&snd_pcm_link_rwlock);
break;
case PCM_LOCK_IRQ:
read_lock_irq(&snd_pcm_link_rwlock);
break;
case PCM_LOCK_IRQSAVE:
read_lock_irqsave(&snd_pcm_link_rwlock, flags);
break;
}
spin_lock(&substream->self_group.lock);
}
return flags;
}
static void __snd_pcm_stream_unlock_mode(struct snd_pcm_substream *substream,
unsigned int mode, unsigned long flags)
{
if (substream->pcm->nonatomic) {
mutex_unlock(&substream->self_group.mutex);
up_read(&snd_pcm_link_rwsem);
} else {
spin_unlock(&substream->self_group.lock);
switch (mode) {
case PCM_LOCK_DEFAULT:
read_unlock(&snd_pcm_link_rwlock);
break;
case PCM_LOCK_IRQ:
read_unlock_irq(&snd_pcm_link_rwlock);
break;
case PCM_LOCK_IRQSAVE:
read_unlock_irqrestore(&snd_pcm_link_rwlock, flags);
break;
}
}
}
/**
* snd_pcm_stream_lock - Lock the PCM stream
* @substream: PCM substream
@ -109,13 +160,7 @@ static inline void down_write_nonblock(struct rw_semaphore *lock)
*/
void snd_pcm_stream_lock(struct snd_pcm_substream *substream)
{
if (substream->pcm->nonatomic) {
down_read_nested(&snd_pcm_link_rwsem, SINGLE_DEPTH_NESTING);
mutex_lock(&substream->self_group.mutex);
} else {
read_lock(&snd_pcm_link_rwlock);
spin_lock(&substream->self_group.lock);
}
__snd_pcm_stream_lock_mode(substream, PCM_LOCK_DEFAULT);
}
EXPORT_SYMBOL_GPL(snd_pcm_stream_lock);
@ -127,13 +172,7 @@ EXPORT_SYMBOL_GPL(snd_pcm_stream_lock);
*/
void snd_pcm_stream_unlock(struct snd_pcm_substream *substream)
{
if (substream->pcm->nonatomic) {
mutex_unlock(&substream->self_group.mutex);
up_read(&snd_pcm_link_rwsem);
} else {
spin_unlock(&substream->self_group.lock);
read_unlock(&snd_pcm_link_rwlock);
}
__snd_pcm_stream_unlock_mode(substream, PCM_LOCK_DEFAULT, 0);
}
EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock);
@ -147,9 +186,7 @@ EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock);
*/
void snd_pcm_stream_lock_irq(struct snd_pcm_substream *substream)
{
if (!substream->pcm->nonatomic)
local_irq_disable();
snd_pcm_stream_lock(substream);
__snd_pcm_stream_lock_mode(substream, PCM_LOCK_IRQ);
}
EXPORT_SYMBOL_GPL(snd_pcm_stream_lock_irq);
@ -161,19 +198,13 @@ EXPORT_SYMBOL_GPL(snd_pcm_stream_lock_irq);
*/
void snd_pcm_stream_unlock_irq(struct snd_pcm_substream *substream)
{
snd_pcm_stream_unlock(substream);
if (!substream->pcm->nonatomic)
local_irq_enable();
__snd_pcm_stream_unlock_mode(substream, PCM_LOCK_IRQ, 0);
}
EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock_irq);
unsigned long _snd_pcm_stream_lock_irqsave(struct snd_pcm_substream *substream)
{
unsigned long flags = 0;
if (!substream->pcm->nonatomic)
local_irq_save(flags);
snd_pcm_stream_lock(substream);
return flags;
return __snd_pcm_stream_lock_mode(substream, PCM_LOCK_IRQSAVE);
}
EXPORT_SYMBOL_GPL(_snd_pcm_stream_lock_irqsave);
@ -187,9 +218,7 @@ EXPORT_SYMBOL_GPL(_snd_pcm_stream_lock_irqsave);
void snd_pcm_stream_unlock_irqrestore(struct snd_pcm_substream *substream,
unsigned long flags)
{
snd_pcm_stream_unlock(substream);
if (!substream->pcm->nonatomic)
local_irq_restore(flags);
__snd_pcm_stream_unlock_mode(substream, PCM_LOCK_IRQSAVE, flags);
}
EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock_irqrestore);
@ -857,6 +886,18 @@ static int snd_pcm_sw_params_user(struct snd_pcm_substream *substream,
return err;
}
static inline snd_pcm_uframes_t
snd_pcm_calc_delay(struct snd_pcm_substream *substream)
{
snd_pcm_uframes_t delay;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
delay = snd_pcm_playback_hw_avail(substream->runtime);
else
delay = snd_pcm_capture_avail(substream->runtime);
return delay + substream->runtime->delay;
}
int snd_pcm_status(struct snd_pcm_substream *substream,
struct snd_pcm_status *status)
{
@ -908,21 +949,9 @@ int snd_pcm_status(struct snd_pcm_substream *substream,
_tstamp_end:
status->appl_ptr = runtime->control->appl_ptr;
status->hw_ptr = runtime->status->hw_ptr;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
status->avail = snd_pcm_playback_avail(runtime);
if (runtime->status->state == SNDRV_PCM_STATE_RUNNING ||
runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
status->delay = runtime->buffer_size - status->avail;
status->delay += runtime->delay;
} else
status->delay = 0;
} else {
status->avail = snd_pcm_capture_avail(runtime);
if (runtime->status->state == SNDRV_PCM_STATE_RUNNING)
status->delay = status->avail + runtime->delay;
else
status->delay = 0;
}
status->avail = snd_pcm_avail(substream);
status->delay = snd_pcm_running(substream) ?
snd_pcm_calc_delay(substream) : 0;
status->avail_max = runtime->avail_max;
status->overrange = runtime->overrange;
runtime->avail_max = 0;
@ -2610,10 +2639,9 @@ static snd_pcm_sframes_t rewind_appl_ptr(struct snd_pcm_substream *substream,
return ret < 0 ? 0 : frames;
}
static snd_pcm_sframes_t snd_pcm_playback_rewind(struct snd_pcm_substream *substream,
snd_pcm_uframes_t frames)
static snd_pcm_sframes_t snd_pcm_rewind(struct snd_pcm_substream *substream,
snd_pcm_uframes_t frames)
{
struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_sframes_t ret;
if (frames == 0)
@ -2623,33 +2651,14 @@ static snd_pcm_sframes_t snd_pcm_playback_rewind(struct snd_pcm_substream *subst
ret = do_pcm_hwsync(substream);
if (!ret)
ret = rewind_appl_ptr(substream, frames,
snd_pcm_playback_hw_avail(runtime));
snd_pcm_hw_avail(substream));
snd_pcm_stream_unlock_irq(substream);
return ret;
}
static snd_pcm_sframes_t snd_pcm_capture_rewind(struct snd_pcm_substream *substream,
snd_pcm_uframes_t frames)
static snd_pcm_sframes_t snd_pcm_forward(struct snd_pcm_substream *substream,
snd_pcm_uframes_t frames)
{
struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_sframes_t ret;
if (frames == 0)
return 0;
snd_pcm_stream_lock_irq(substream);
ret = do_pcm_hwsync(substream);
if (!ret)
ret = rewind_appl_ptr(substream, frames,
snd_pcm_capture_hw_avail(runtime));
snd_pcm_stream_unlock_irq(substream);
return ret;
}
static snd_pcm_sframes_t snd_pcm_playback_forward(struct snd_pcm_substream *substream,
snd_pcm_uframes_t frames)
{
struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_sframes_t ret;
if (frames == 0)
@ -2659,25 +2668,7 @@ static snd_pcm_sframes_t snd_pcm_playback_forward(struct snd_pcm_substream *subs
ret = do_pcm_hwsync(substream);
if (!ret)
ret = forward_appl_ptr(substream, frames,
snd_pcm_playback_avail(runtime));
snd_pcm_stream_unlock_irq(substream);
return ret;
}
static snd_pcm_sframes_t snd_pcm_capture_forward(struct snd_pcm_substream *substream,
snd_pcm_uframes_t frames)
{
struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_sframes_t ret;
if (frames == 0)
return 0;
snd_pcm_stream_lock_irq(substream);
ret = do_pcm_hwsync(substream);
if (!ret)
ret = forward_appl_ptr(substream, frames,
snd_pcm_capture_avail(runtime));
snd_pcm_avail(substream));
snd_pcm_stream_unlock_irq(substream);
return ret;
}
@ -2695,19 +2686,13 @@ static int snd_pcm_hwsync(struct snd_pcm_substream *substream)
static int snd_pcm_delay(struct snd_pcm_substream *substream,
snd_pcm_sframes_t *delay)
{
struct snd_pcm_runtime *runtime = substream->runtime;
int err;
snd_pcm_sframes_t n = 0;
snd_pcm_stream_lock_irq(substream);
err = do_pcm_hwsync(substream);
if (!err) {
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
n = snd_pcm_playback_hw_avail(runtime);
else
n = snd_pcm_capture_avail(runtime);
n += runtime->delay;
}
if (!err)
n = snd_pcm_calc_delay(substream);
snd_pcm_stream_unlock_irq(substream);
if (!err)
*delay = n;
@ -2834,10 +2819,7 @@ static int snd_pcm_rewind_ioctl(struct snd_pcm_substream *substream,
return -EFAULT;
if (put_user(0, _frames))
return -EFAULT;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
result = snd_pcm_playback_rewind(substream, frames);
else
result = snd_pcm_capture_rewind(substream, frames);
result = snd_pcm_rewind(substream, frames);
__put_user(result, _frames);
return result < 0 ? result : 0;
}
@ -2852,10 +2834,7 @@ static int snd_pcm_forward_ioctl(struct snd_pcm_substream *substream,
return -EFAULT;
if (put_user(0, _frames))
return -EFAULT;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
result = snd_pcm_playback_forward(substream, frames);
else
result = snd_pcm_capture_forward(substream, frames);
result = snd_pcm_forward(substream, frames);
__put_user(result, _frames);
return result < 0 ? result : 0;
}
@ -2998,7 +2977,7 @@ int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream,
/* provided only for OSS; capture-only and no value returned */
if (substream->stream != SNDRV_PCM_STREAM_CAPTURE)
return -EINVAL;
result = snd_pcm_capture_forward(substream, *frames);
result = snd_pcm_forward(substream, *frames);
return result < 0 ? result : 0;
}
case SNDRV_PCM_IOCTL_HW_PARAMS:
@ -3140,82 +3119,46 @@ static ssize_t snd_pcm_writev(struct kiocb *iocb, struct iov_iter *from)
return result;
}
static __poll_t snd_pcm_playback_poll(struct file *file, poll_table * wait)
static __poll_t snd_pcm_poll(struct file *file, poll_table *wait)
{
struct snd_pcm_file *pcm_file;
struct snd_pcm_substream *substream;
struct snd_pcm_runtime *runtime;
__poll_t mask;
__poll_t mask, ok;
snd_pcm_uframes_t avail;
pcm_file = file->private_data;
substream = pcm_file->substream;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
ok = EPOLLOUT | EPOLLWRNORM;
else
ok = EPOLLIN | EPOLLRDNORM;
if (PCM_RUNTIME_CHECK(substream))
return EPOLLOUT | EPOLLWRNORM | EPOLLERR;
runtime = substream->runtime;
return ok | EPOLLERR;
runtime = substream->runtime;
poll_wait(file, &runtime->sleep, wait);
mask = 0;
snd_pcm_stream_lock_irq(substream);
avail = snd_pcm_playback_avail(runtime);
avail = snd_pcm_avail(substream);
switch (runtime->status->state) {
case SNDRV_PCM_STATE_RUNNING:
case SNDRV_PCM_STATE_PREPARED:
case SNDRV_PCM_STATE_PAUSED:
if (avail >= runtime->control->avail_min) {
mask = EPOLLOUT | EPOLLWRNORM;
break;
}
/* Fall through */
case SNDRV_PCM_STATE_DRAINING:
mask = 0;
break;
default:
mask = EPOLLOUT | EPOLLWRNORM | EPOLLERR;
break;
}
snd_pcm_stream_unlock_irq(substream);
return mask;
}
static __poll_t snd_pcm_capture_poll(struct file *file, poll_table * wait)
{
struct snd_pcm_file *pcm_file;
struct snd_pcm_substream *substream;
struct snd_pcm_runtime *runtime;
__poll_t mask;
snd_pcm_uframes_t avail;
pcm_file = file->private_data;
substream = pcm_file->substream;
if (PCM_RUNTIME_CHECK(substream))
return EPOLLIN | EPOLLRDNORM | EPOLLERR;
runtime = substream->runtime;
poll_wait(file, &runtime->sleep, wait);
snd_pcm_stream_lock_irq(substream);
avail = snd_pcm_capture_avail(runtime);
switch (runtime->status->state) {
case SNDRV_PCM_STATE_RUNNING:
case SNDRV_PCM_STATE_PREPARED:
case SNDRV_PCM_STATE_PAUSED:
if (avail >= runtime->control->avail_min) {
mask = EPOLLIN | EPOLLRDNORM;
break;
}
mask = 0;
if (avail >= runtime->control->avail_min)
mask = ok;
break;
case SNDRV_PCM_STATE_DRAINING:
if (avail > 0) {
mask = EPOLLIN | EPOLLRDNORM;
break;
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
mask = ok;
if (!avail)
mask |= EPOLLERR;
}
/* Fall through */
break;
default:
mask = EPOLLIN | EPOLLRDNORM | EPOLLERR;
mask = ok | EPOLLERR;
break;
}
snd_pcm_stream_unlock_irq(substream);
@ -3707,7 +3650,7 @@ const struct file_operations snd_pcm_f_ops[2] = {
.open = snd_pcm_playback_open,
.release = snd_pcm_release,
.llseek = no_llseek,
.poll = snd_pcm_playback_poll,
.poll = snd_pcm_poll,
.unlocked_ioctl = snd_pcm_ioctl,
.compat_ioctl = snd_pcm_ioctl_compat,
.mmap = snd_pcm_mmap,
@ -3721,7 +3664,7 @@ const struct file_operations snd_pcm_f_ops[2] = {
.open = snd_pcm_capture_open,
.release = snd_pcm_release,
.llseek = no_llseek,
.poll = snd_pcm_capture_poll,
.poll = snd_pcm_poll,
.unlocked_ioctl = snd_pcm_ioctl,
.compat_ioctl = snd_pcm_ioctl_compat,
.mmap = snd_pcm_mmap,

View file

@ -669,7 +669,7 @@ int snd_seq_event_port_attach(int client,
/* Set up the port */
memset(&portinfo, 0, sizeof(portinfo));
portinfo.addr.client = client;
strlcpy(portinfo.name, portname ? portname : "Unamed port",
strlcpy(portinfo.name, portname ? portname : "Unnamed port",
sizeof(portinfo.name));
portinfo.capability = cap;

View file

@ -371,9 +371,7 @@ static int initialize_timer(struct snd_seq_timer *tmr)
tmr->ticks = 1;
if (!(t->hw.flags & SNDRV_TIMER_HW_SLAVE)) {
unsigned long r = t->hw.resolution;
if (! r && t->hw.c_resolution)
r = t->hw.c_resolution(t);
unsigned long r = snd_timer_resolution(tmr->timeri);
if (r) {
tmr->ticks = (unsigned int)(1000000000uL / (r * freq));
if (! tmr->ticks)

View file

@ -427,25 +427,35 @@ int snd_timer_close(struct snd_timer_instance *timeri)
}
EXPORT_SYMBOL(snd_timer_close);
static unsigned long snd_timer_hw_resolution(struct snd_timer *timer)
{
if (timer->hw.c_resolution)
return timer->hw.c_resolution(timer);
else
return timer->hw.resolution;
}
unsigned long snd_timer_resolution(struct snd_timer_instance *timeri)
{
struct snd_timer * timer;
unsigned long ret = 0;
unsigned long flags;
if (timeri == NULL)
return 0;
timer = timeri->timer;
if (timer) {
if (timer->hw.c_resolution)
return timer->hw.c_resolution(timer);
return timer->hw.resolution;
spin_lock_irqsave(&timer->lock, flags);
ret = snd_timer_hw_resolution(timer);
spin_unlock_irqrestore(&timer->lock, flags);
}
return 0;
return ret;
}
EXPORT_SYMBOL(snd_timer_resolution);
static void snd_timer_notify1(struct snd_timer_instance *ti, int event)
{
struct snd_timer *timer;
struct snd_timer *timer = ti->timer;
unsigned long resolution = 0;
struct snd_timer_instance *ts;
struct timespec tstamp;
@ -457,14 +467,14 @@ static void snd_timer_notify1(struct snd_timer_instance *ti, int event)
if (snd_BUG_ON(event < SNDRV_TIMER_EVENT_START ||
event > SNDRV_TIMER_EVENT_PAUSE))
return;
if (event == SNDRV_TIMER_EVENT_START ||
event == SNDRV_TIMER_EVENT_CONTINUE)
resolution = snd_timer_resolution(ti);
if (timer &&
(event == SNDRV_TIMER_EVENT_START ||
event == SNDRV_TIMER_EVENT_CONTINUE))
resolution = snd_timer_hw_resolution(timer);
if (ti->ccallback)
ti->ccallback(ti, event, &tstamp, resolution);
if (ti->flags & SNDRV_TIMER_IFLG_SLAVE)
return;
timer = ti->timer;
if (timer == NULL)
return;
if (timer->hw.flags & SNDRV_TIMER_HW_SLAVE)
@ -771,10 +781,7 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left)
spin_lock_irqsave(&timer->lock, flags);
/* remember the current resolution */
if (timer->hw.c_resolution)
resolution = timer->hw.c_resolution(timer);
else
resolution = timer->hw.resolution;
resolution = snd_timer_hw_resolution(timer);
/* loop for all active instances
* Here we cannot use list_for_each_entry because the active_list of a
@ -1014,12 +1021,8 @@ void snd_timer_notify(struct snd_timer *timer, int event, struct timespec *tstam
spin_lock_irqsave(&timer->lock, flags);
if (event == SNDRV_TIMER_EVENT_MSTART ||
event == SNDRV_TIMER_EVENT_MCONTINUE ||
event == SNDRV_TIMER_EVENT_MRESUME) {
if (timer->hw.c_resolution)
resolution = timer->hw.c_resolution(timer);
else
resolution = timer->hw.resolution;
}
event == SNDRV_TIMER_EVENT_MRESUME)
resolution = snd_timer_hw_resolution(timer);
list_for_each_entry(ti, &timer->active_list_head, active_list) {
if (ti->ccallback)
ti->ccallback(ti, event, tstamp, resolution);
@ -1656,10 +1659,8 @@ static int snd_timer_user_gstatus(struct file *file,
mutex_lock(&register_mutex);
t = snd_timer_find(&tid);
if (t != NULL) {
if (t->hw.c_resolution)
gstatus.resolution = t->hw.c_resolution(t);
else
gstatus.resolution = t->hw.resolution;
spin_lock_irq(&t->lock);
gstatus.resolution = snd_timer_hw_resolution(t);
if (t->hw.precise_resolution) {
t->hw.precise_resolution(t, &gstatus.resolution_num,
&gstatus.resolution_den);
@ -1667,6 +1668,7 @@ static int snd_timer_user_gstatus(struct file *file,
gstatus.resolution_num = gstatus.resolution;
gstatus.resolution_den = 1000000000uL;
}
spin_unlock_irq(&t->lock);
} else {
err = -ENODEV;
}

View file

@ -421,13 +421,15 @@ struct snd_kcontrol *snd_ctl_make_virtual_master(char *name,
kctl->private_free = master_free;
/* additional (constant) TLV read */
if (tlv &&
(tlv[0] == SNDRV_CTL_TLVT_DB_SCALE ||
tlv[0] == SNDRV_CTL_TLVT_DB_MINMAX ||
tlv[0] == SNDRV_CTL_TLVT_DB_MINMAX_MUTE)) {
kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
memcpy(master->tlv, tlv, sizeof(master->tlv));
kctl->tlv.p = master->tlv;
if (tlv) {
unsigned int type = tlv[SNDRV_CTL_TLVO_TYPE];
if (type == SNDRV_CTL_TLVT_DB_SCALE ||
type == SNDRV_CTL_TLVT_DB_MINMAX ||
type == SNDRV_CTL_TLVT_DB_MINMAX_MUTE) {
kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
memcpy(master->tlv, tlv, sizeof(master->tlv));
kctl->tlv.p = master->tlv;
}
}
return kctl;

View file

@ -768,20 +768,7 @@ static int loopback_close(struct snd_pcm_substream *substream)
return 0;
}
static const struct snd_pcm_ops loopback_playback_ops = {
.open = loopback_open,
.close = loopback_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = loopback_hw_params,
.hw_free = loopback_hw_free,
.prepare = loopback_prepare,
.trigger = loopback_trigger,
.pointer = loopback_pointer,
.page = snd_pcm_lib_get_vmalloc_page,
.mmap = snd_pcm_lib_mmap_vmalloc,
};
static const struct snd_pcm_ops loopback_capture_ops = {
static const struct snd_pcm_ops loopback_pcm_ops = {
.open = loopback_open,
.close = loopback_close,
.ioctl = snd_pcm_lib_ioctl,
@ -804,8 +791,8 @@ static int loopback_pcm_new(struct loopback *loopback,
substreams, substreams, &pcm);
if (err < 0)
return err;
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &loopback_playback_ops);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &loopback_capture_ops);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &loopback_pcm_ops);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &loopback_pcm_ops);
pcm->private_data = loopback;
pcm->info_flags = 0;

View file

@ -1042,7 +1042,7 @@ static void dummy_proc_init(struct snd_dummy *chip)
if (!snd_card_proc_new(chip->card, "dummy_pcm", &entry)) {
snd_info_set_text_ops(entry, chip, dummy_proc_read);
entry->c.text.write = dummy_proc_write;
entry->mode |= S_IWUSR;
entry->mode |= 0200;
entry->private_data = chip;
}
}

View file

@ -41,11 +41,11 @@ static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
static struct platform_device *platform_devices[SNDRV_CARDS];
static int device_count;
module_param_array(index, int, NULL, S_IRUGO);
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard.");
module_param_array(id, charp, NULL, S_IRUGO);
module_param_array(id, charp, NULL, 0444);
MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard.");
module_param_array(enable, bool, NULL, S_IRUGO);
module_param_array(enable, bool, NULL, 0444);
MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard.");
MODULE_AUTHOR("Matthias Koenig <mk@phasorlab.de>");

View file

@ -104,7 +104,7 @@ int snd_opl4_create_proc(struct snd_opl4 *opl4)
if (entry) {
if (opl4->hardware < OPL3_HW_OPL4_ML) {
/* OPL4 can access 4 MB external ROM/SRAM */
entry->mode |= S_IWUSR;
entry->mode |= 0200;
entry->size = 4 * 1024 * 1024;
} else {
/* OPL4-ML has 1 MB internal ROM */

View file

@ -60,11 +60,11 @@ static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
static struct platform_device *platform_devices[SNDRV_CARDS];
static int device_count;
module_param_array(index, int, NULL, S_IRUGO);
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard.");
module_param_array(id, charp, NULL, S_IRUGO);
module_param_array(id, charp, NULL, 0444);
MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard.");
module_param_array(enable, bool, NULL, S_IRUGO);
module_param_array(enable, bool, NULL, 0444);
MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard.");
MODULE_AUTHOR("Levent Guendogdu, Tobias Gehrig, Matthias Koenig");

View file

@ -183,7 +183,7 @@ void snd_bebob_proc_init(struct snd_bebob *bebob)
bebob->card->proc_root);
if (root == NULL)
return;
root->mode = S_IFDIR | S_IRUGO | S_IXUGO;
root->mode = S_IFDIR | 0555;
if (snd_info_register(root) < 0) {
snd_info_free_entry(root);
return;

View file

@ -1,3 +1,4 @@
snd-dice-objs := dice-transaction.o dice-stream.o dice-proc.o dice-midi.o \
dice-pcm.o dice-hwdep.o dice.o
dice-pcm.o dice-hwdep.o dice.o dice-tcelectronic.o \
dice-alesis.o dice-extension.o dice-mytek.o
obj-$(CONFIG_SND_DICE) += snd-dice.o

View file

@ -0,0 +1,52 @@
// SPDX-License-Identifier: GPL-2.0
/*
* dice-alesis.c - a part of driver for DICE based devices
*
* Copyright (c) 2018 Takashi Sakamoto
*/
#include "dice.h"
static const unsigned int
alesis_io14_tx_pcm_chs[MAX_STREAMS][SND_DICE_RATE_MODE_COUNT] = {
{6, 6, 4}, /* Tx0 = Analog + S/PDIF. */
{8, 4, 0}, /* Tx1 = ADAT1. */
};
static const unsigned int
alesis_io26_tx_pcm_chs[MAX_STREAMS][SND_DICE_RATE_MODE_COUNT] = {
{10, 10, 8}, /* Tx0 = Analog + S/PDIF. */
{16, 8, 0}, /* Tx1 = ADAT1 + ADAT2. */
};
int snd_dice_detect_alesis_formats(struct snd_dice *dice)
{
__be32 reg;
u32 data;
int i;
int err;
err = snd_dice_transaction_read_tx(dice, TX_NUMBER_AUDIO, &reg,
sizeof(reg));
if (err < 0)
return err;
data = be32_to_cpu(reg);
if (data == 4 || data == 6) {
memcpy(dice->tx_pcm_chs, alesis_io14_tx_pcm_chs,
MAX_STREAMS * SND_DICE_RATE_MODE_COUNT *
sizeof(unsigned int));
} else {
memcpy(dice->rx_pcm_chs, alesis_io26_tx_pcm_chs,
MAX_STREAMS * SND_DICE_RATE_MODE_COUNT *
sizeof(unsigned int));
}
for (i = 0; i < SND_DICE_RATE_MODE_COUNT; ++i)
dice->rx_pcm_chs[0][i] = 8;
dice->tx_midi_ports[0] = 1;
dice->rx_midi_ports[0] = 1;
return 0;
}

View file

@ -0,0 +1,172 @@
// SPDX-License-Identifier: GPL-2.0
/*
* dice-extension.c - a part of driver for DICE based devices
*
* Copyright (c) 2018 Takashi Sakamoto
*/
#include "dice.h"
/* For TCD2210/2220, TCAT defines extension of application protocol. */
#define DICE_EXT_APP_SPACE 0xffffe0200000uLL
#define DICE_EXT_APP_CAPS_OFFSET 0x00
#define DICE_EXT_APP_CAPS_SIZE 0x04
#define DICE_EXT_APP_CMD_OFFSET 0x08
#define DICE_EXT_APP_CMD_SIZE 0x0c
#define DICE_EXT_APP_MIXER_OFFSET 0x10
#define DICE_EXT_APP_MIXER_SIZE 0x14
#define DICE_EXT_APP_PEAK_OFFSET 0x18
#define DICE_EXT_APP_PEAK_SIZE 0x1c
#define DICE_EXT_APP_ROUTER_OFFSET 0x20
#define DICE_EXT_APP_ROUTER_SIZE 0x24
#define DICE_EXT_APP_STREAM_OFFSET 0x28
#define DICE_EXT_APP_STREAM_SIZE 0x2c
#define DICE_EXT_APP_CURRENT_OFFSET 0x30
#define DICE_EXT_APP_CURRENT_SIZE 0x34
#define DICE_EXT_APP_STANDALONE_OFFSET 0x38
#define DICE_EXT_APP_STANDALONE_SIZE 0x3c
#define DICE_EXT_APP_APPLICATION_OFFSET 0x40
#define DICE_EXT_APP_APPLICATION_SIZE 0x44
#define EXT_APP_STREAM_TX_NUMBER 0x0000
#define EXT_APP_STREAM_RX_NUMBER 0x0004
#define EXT_APP_STREAM_ENTRIES 0x0008
#define EXT_APP_STREAM_ENTRY_SIZE 0x010c
#define EXT_APP_NUMBER_AUDIO 0x0000
#define EXT_APP_NUMBER_MIDI 0x0004
#define EXT_APP_NAMES 0x0008
#define EXT_APP_NAMES_SIZE 256
#define EXT_APP_AC3 0x0108
#define EXT_APP_CONFIG_LOW_ROUTER 0x0000
#define EXT_APP_CONFIG_LOW_STREAM 0x1000
#define EXT_APP_CONFIG_MIDDLE_ROUTER 0x2000
#define EXT_APP_CONFIG_MIDDLE_STREAM 0x3000
#define EXT_APP_CONFIG_HIGH_ROUTER 0x4000
#define EXT_APP_CONFIG_HIGH_STREAM 0x5000
static inline int read_transaction(struct snd_dice *dice, u64 section_addr,
u32 offset, void *buf, size_t len)
{
return snd_fw_transaction(dice->unit,
len == 4 ? TCODE_READ_QUADLET_REQUEST :
TCODE_READ_BLOCK_REQUEST,
section_addr + offset, buf, len, 0);
}
static int read_stream_entries(struct snd_dice *dice, u64 section_addr,
u32 base_offset, unsigned int stream_count,
unsigned int mode,
unsigned int pcm_channels[MAX_STREAMS][3],
unsigned int midi_ports[MAX_STREAMS])
{
u32 entry_offset;
__be32 reg[2];
int err;
int i;
for (i = 0; i < stream_count; ++i) {
entry_offset = base_offset + i * EXT_APP_STREAM_ENTRY_SIZE;
err = read_transaction(dice, section_addr,
entry_offset + EXT_APP_NUMBER_AUDIO,
reg, sizeof(reg));
if (err < 0)
return err;
pcm_channels[i][mode] = be32_to_cpu(reg[0]);
midi_ports[i] = max(midi_ports[i], be32_to_cpu(reg[1]));
}
return 0;
}
static int detect_stream_formats(struct snd_dice *dice, u64 section_addr)
{
u32 base_offset;
__be32 reg[2];
unsigned int stream_count;
int mode;
int err = 0;
for (mode = 0; mode < SND_DICE_RATE_MODE_COUNT; ++mode) {
unsigned int cap;
/*
* Some models report stream formats at highest mode, however
* they don't support the mode. Check clock capabilities.
*/
if (mode == 2) {
cap = CLOCK_CAP_RATE_176400 | CLOCK_CAP_RATE_192000;
} else if (mode == 1) {
cap = CLOCK_CAP_RATE_88200 | CLOCK_CAP_RATE_96000;
} else {
cap = CLOCK_CAP_RATE_32000 | CLOCK_CAP_RATE_44100 |
CLOCK_CAP_RATE_48000;
}
if (!(cap & dice->clock_caps))
continue;
base_offset = 0x2000 * mode + 0x1000;
err = read_transaction(dice, section_addr,
base_offset + EXT_APP_STREAM_TX_NUMBER,
&reg, sizeof(reg));
if (err < 0)
break;
base_offset += EXT_APP_STREAM_ENTRIES;
stream_count = be32_to_cpu(reg[0]);
err = read_stream_entries(dice, section_addr, base_offset,
stream_count, mode,
dice->tx_pcm_chs,
dice->tx_midi_ports);
if (err < 0)
break;
base_offset += stream_count * EXT_APP_STREAM_ENTRY_SIZE;
stream_count = be32_to_cpu(reg[1]);
err = read_stream_entries(dice, section_addr, base_offset,
stream_count,
mode, dice->rx_pcm_chs,
dice->rx_midi_ports);
if (err < 0)
break;
}
return err;
}
int snd_dice_detect_extension_formats(struct snd_dice *dice)
{
__be32 *pointers;
unsigned int i;
u64 section_addr;
int err;
pointers = kmalloc_array(9, sizeof(__be32) * 2, GFP_KERNEL);
if (pointers == NULL)
return -ENOMEM;
err = snd_fw_transaction(dice->unit, TCODE_READ_BLOCK_REQUEST,
DICE_EXT_APP_SPACE, pointers,
9 * sizeof(__be32) * 2, 0);
if (err < 0)
goto end;
/* Check two of them for offset have the same value or not. */
for (i = 0; i < 9; ++i) {
int j;
for (j = i + 1; j < 9; ++j) {
if (pointers[i * 2] == pointers[j * 2])
goto end;
}
}
section_addr = DICE_EXT_APP_SPACE + be32_to_cpu(pointers[12]) * 4;
err = detect_stream_formats(dice, section_addr);
end:
kfree(pointers);
return err;
}

View file

@ -174,14 +174,19 @@
*/
#define GLOBAL_SAMPLE_RATE 0x05c
/*
* Some old firmware versions do not have the following global registers.
* Windows drivers produced by TCAT lost backward compatibility in its
* early release because they can handle firmware only which supports the
* following registers.
*/
/*
* The version of the DICE driver specification that this device conforms to;
* read-only.
*/
#define GLOBAL_VERSION 0x060
/* Some old firmware versions do not have the following global registers: */
/*
* Supported sample rates and clock sources; read-only.
*/

View file

@ -101,27 +101,18 @@ int snd_dice_create_midi(struct snd_dice *dice)
.close = midi_close,
.trigger = midi_playback_trigger,
};
__be32 reg;
struct snd_rawmidi *rmidi;
struct snd_rawmidi_str *str;
unsigned int midi_in_ports, midi_out_ports;
int i;
int err;
/*
* Use the number of MIDI conformant data channel at current sampling
* transfer frequency.
*/
err = snd_dice_transaction_read_tx(dice, TX_NUMBER_MIDI,
&reg, sizeof(reg));
if (err < 0)
return err;
midi_in_ports = be32_to_cpu(reg);
err = snd_dice_transaction_read_rx(dice, RX_NUMBER_MIDI,
&reg, sizeof(reg));
if (err < 0)
return err;
midi_out_ports = be32_to_cpu(reg);
midi_in_ports = 0;
midi_out_ports = 0;
for (i = 0; i < MAX_STREAMS; ++i) {
midi_in_ports = max(midi_in_ports, dice->tx_midi_ports[i]);
midi_out_ports = max(midi_out_ports, dice->rx_midi_ports[i]);
}
if (midi_in_ports + midi_out_ports == 0)
return 0;

View file

@ -0,0 +1,46 @@
// SPDX-License-Identifier: GPL-2.0
/*
* dice-mytek.c - a part of driver for DICE based devices
*
* Copyright (c) 2018 Melvin Vermeeren
*/
#include "dice.h"
struct dice_mytek_spec {
unsigned int tx_pcm_chs[MAX_STREAMS][SND_DICE_RATE_MODE_COUNT];
unsigned int rx_pcm_chs[MAX_STREAMS][SND_DICE_RATE_MODE_COUNT];
};
static const struct dice_mytek_spec stereo_192_dsd_dac = {
/* AES, TOSLINK, SPDIF, ADAT inputs on device */
.tx_pcm_chs = {{8, 8, 8}, {0, 0, 0} },
/* PCM 44.1-192, native DSD64/DSD128 to device */
.rx_pcm_chs = {{4, 4, 4}, {0, 0, 0} }
};
/*
* Mytek has a few other firewire-capable devices, though newer models appear
* to lack the port more often than not. As I don't have access to any of them
* they are missing here. An example is the Mytek 8x192 ADDA, which is DICE.
*/
int snd_dice_detect_mytek_formats(struct snd_dice *dice)
{
int i;
const struct dice_mytek_spec *dev;
dev = &stereo_192_dsd_dac;
memcpy(dice->tx_pcm_chs, dev->tx_pcm_chs,
MAX_STREAMS * SND_DICE_RATE_MODE_COUNT * sizeof(unsigned int));
memcpy(dice->rx_pcm_chs, dev->rx_pcm_chs,
MAX_STREAMS * SND_DICE_RATE_MODE_COUNT * sizeof(unsigned int));
for (i = 0; i < MAX_STREAMS; ++i) {
dice->tx_midi_ports[i] = 0;
dice->rx_midi_ports[i] = 0;
}
return 0;
}

View file

@ -9,43 +9,115 @@
#include "dice.h"
static int dice_rate_constraint(struct snd_pcm_hw_params *params,
struct snd_pcm_hw_rule *rule)
{
struct snd_pcm_substream *substream = rule->private;
struct snd_dice *dice = substream->private_data;
unsigned int index = substream->pcm->device;
const struct snd_interval *c =
hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_CHANNELS);
struct snd_interval *r =
hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
struct snd_interval rates = {
.min = UINT_MAX, .max = 0, .integer = 1
};
unsigned int *pcm_channels;
enum snd_dice_rate_mode mode;
unsigned int i, rate;
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
pcm_channels = dice->tx_pcm_chs[index];
else
pcm_channels = dice->rx_pcm_chs[index];
for (i = 0; i < ARRAY_SIZE(snd_dice_rates); ++i) {
rate = snd_dice_rates[i];
if (snd_dice_stream_get_rate_mode(dice, rate, &mode) < 0)
continue;
if (!snd_interval_test(c, pcm_channels[mode]))
continue;
rates.min = min(rates.min, rate);
rates.max = max(rates.max, rate);
}
return snd_interval_refine(r, &rates);
}
static int dice_channels_constraint(struct snd_pcm_hw_params *params,
struct snd_pcm_hw_rule *rule)
{
struct snd_pcm_substream *substream = rule->private;
struct snd_dice *dice = substream->private_data;
unsigned int index = substream->pcm->device;
const struct snd_interval *r =
hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_RATE);
struct snd_interval *c =
hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
struct snd_interval channels = {
.min = UINT_MAX, .max = 0, .integer = 1
};
unsigned int *pcm_channels;
enum snd_dice_rate_mode mode;
unsigned int i, rate;
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
pcm_channels = dice->tx_pcm_chs[index];
else
pcm_channels = dice->rx_pcm_chs[index];
for (i = 0; i < ARRAY_SIZE(snd_dice_rates); ++i) {
rate = snd_dice_rates[i];
if (snd_dice_stream_get_rate_mode(dice, rate, &mode) < 0)
continue;
if (!snd_interval_test(r, rate))
continue;
channels.min = min(channels.min, pcm_channels[mode]);
channels.max = max(channels.max, pcm_channels[mode]);
}
return snd_interval_refine(c, &channels);
}
static int limit_channels_and_rates(struct snd_dice *dice,
struct snd_pcm_runtime *runtime,
enum amdtp_stream_direction dir,
unsigned int index, unsigned int size)
unsigned int index)
{
struct snd_pcm_hardware *hw = &runtime->hw;
struct amdtp_stream *stream;
unsigned int rate;
__be32 reg;
int err;
unsigned int *pcm_channels;
unsigned int i;
/*
* Retrieve current Multi Bit Linear Audio data channel and limit to
* it.
*/
if (dir == AMDTP_IN_STREAM) {
stream = &dice->tx_stream[index];
err = snd_dice_transaction_read_tx(dice,
size * index + TX_NUMBER_AUDIO,
&reg, sizeof(reg));
} else {
stream = &dice->rx_stream[index];
err = snd_dice_transaction_read_rx(dice,
size * index + RX_NUMBER_AUDIO,
&reg, sizeof(reg));
if (dir == AMDTP_IN_STREAM)
pcm_channels = dice->tx_pcm_chs[index];
else
pcm_channels = dice->rx_pcm_chs[index];
hw->channels_min = UINT_MAX;
hw->channels_max = 0;
for (i = 0; i < ARRAY_SIZE(snd_dice_rates); ++i) {
enum snd_dice_rate_mode mode;
unsigned int rate, channels;
rate = snd_dice_rates[i];
if (snd_dice_stream_get_rate_mode(dice, rate, &mode) < 0)
continue;
hw->rates |= snd_pcm_rate_to_rate_bit(rate);
channels = pcm_channels[mode];
if (channels == 0)
continue;
hw->channels_min = min(hw->channels_min, channels);
hw->channels_max = max(hw->channels_max, channels);
}
if (err < 0)
return err;
hw->channels_min = hw->channels_max = be32_to_cpu(reg);
/* Retrieve current sampling transfer frequency and limit to it. */
err = snd_dice_transaction_get_rate(dice, &rate);
if (err < 0)
return err;
hw->rates = snd_pcm_rate_to_rate_bit(rate);
snd_pcm_limit_hw_rates(runtime);
return 0;
@ -56,36 +128,34 @@ static int init_hw_info(struct snd_dice *dice,
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_pcm_hardware *hw = &runtime->hw;
unsigned int index = substream->pcm->device;
enum amdtp_stream_direction dir;
struct amdtp_stream *stream;
__be32 reg[2];
unsigned int count, size;
int err;
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
hw->formats = AM824_IN_PCM_FORMAT_BITS;
dir = AMDTP_IN_STREAM;
stream = &dice->tx_stream[substream->pcm->device];
err = snd_dice_transaction_read_tx(dice, TX_NUMBER, reg,
sizeof(reg));
stream = &dice->tx_stream[index];
} else {
hw->formats = AM824_OUT_PCM_FORMAT_BITS;
dir = AMDTP_OUT_STREAM;
stream = &dice->rx_stream[substream->pcm->device];
err = snd_dice_transaction_read_rx(dice, RX_NUMBER, reg,
sizeof(reg));
stream = &dice->rx_stream[index];
}
err = limit_channels_and_rates(dice, substream->runtime, dir,
index);
if (err < 0)
return err;
count = min_t(unsigned int, be32_to_cpu(reg[0]), MAX_STREAMS);
if (substream->pcm->device >= count)
return -ENXIO;
size = be32_to_cpu(reg[1]) * 4;
err = limit_channels_and_rates(dice, substream->runtime, dir,
substream->pcm->device, size);
err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
dice_rate_constraint, substream,
SNDRV_PCM_HW_PARAM_CHANNELS, -1);
if (err < 0)
return err;
err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
dice_channels_constraint, substream,
SNDRV_PCM_HW_PARAM_RATE, -1);
if (err < 0)
return err;
@ -95,6 +165,8 @@ static int init_hw_info(struct snd_dice *dice,
static int pcm_open(struct snd_pcm_substream *substream)
{
struct snd_dice *dice = substream->private_data;
unsigned int source;
bool internal;
int err;
err = snd_dice_stream_lock_try(dice);
@ -105,6 +177,43 @@ static int pcm_open(struct snd_pcm_substream *substream)
if (err < 0)
goto err_locked;
err = snd_dice_transaction_get_clock_source(dice, &source);
if (err < 0)
goto err_locked;
switch (source) {
case CLOCK_SOURCE_AES1:
case CLOCK_SOURCE_AES2:
case CLOCK_SOURCE_AES3:
case CLOCK_SOURCE_AES4:
case CLOCK_SOURCE_AES_ANY:
case CLOCK_SOURCE_ADAT:
case CLOCK_SOURCE_TDIF:
case CLOCK_SOURCE_WC:
internal = false;
break;
default:
internal = true;
break;
}
/*
* When source of clock is not internal or any PCM streams are running,
* available sampling rate is limited at current sampling rate.
*/
if (!internal ||
amdtp_stream_pcm_running(&dice->tx_stream[0]) ||
amdtp_stream_pcm_running(&dice->tx_stream[1]) ||
amdtp_stream_pcm_running(&dice->rx_stream[0]) ||
amdtp_stream_pcm_running(&dice->rx_stream[1])) {
unsigned int rate;
err = snd_dice_transaction_get_rate(dice, &rate);
if (err < 0)
goto err_locked;
substream->runtime->hw.rate_min = rate;
substream->runtime->hw.rate_max = rate;
}
snd_pcm_set_sync(substream);
end:
return err;
@ -318,37 +427,19 @@ int snd_dice_create_pcm(struct snd_dice *dice)
.page = snd_pcm_lib_get_vmalloc_page,
.mmap = snd_pcm_lib_mmap_vmalloc,
};
__be32 reg;
struct snd_pcm *pcm;
unsigned int i, max_capture, max_playback, capture, playback;
unsigned int capture, playback;
int i, j;
int err;
/* Check whether PCM substreams are required. */
if (dice->force_two_pcms) {
max_capture = max_playback = 2;
} else {
max_capture = max_playback = 0;
err = snd_dice_transaction_read_tx(dice, TX_NUMBER, &reg,
sizeof(reg));
if (err < 0)
return err;
max_capture = min_t(unsigned int, be32_to_cpu(reg), MAX_STREAMS);
err = snd_dice_transaction_read_rx(dice, RX_NUMBER, &reg,
sizeof(reg));
if (err < 0)
return err;
max_playback = min_t(unsigned int, be32_to_cpu(reg), MAX_STREAMS);
}
for (i = 0; i < MAX_STREAMS; i++) {
capture = playback = 0;
if (i < max_capture)
capture = 1;
if (i < max_playback)
playback = 1;
if (capture == 0 && playback == 0)
break;
for (j = 0; j < SND_DICE_RATE_MODE_COUNT; ++j) {
if (dice->tx_pcm_chs[i][j] > 0)
capture = 1;
if (dice->rx_pcm_chs[i][j] > 0)
playback = 1;
}
err = snd_pcm_new(dice->card, "DICE", i, playback, capture,
&pcm);

View file

@ -148,12 +148,12 @@ static void dice_proc_read(struct snd_info_entry *entry,
>> CLOCK_RATE_SHIFT));
snd_iprintf(buffer, " ext status: %08x\n", buf.global.extended_status);
snd_iprintf(buffer, " sample rate: %u\n", buf.global.sample_rate);
snd_iprintf(buffer, " version: %u.%u.%u.%u\n",
(buf.global.version >> 24) & 0xff,
(buf.global.version >> 16) & 0xff,
(buf.global.version >> 8) & 0xff,
(buf.global.version >> 0) & 0xff);
if (quadlets >= 90) {
snd_iprintf(buffer, " version: %u.%u.%u.%u\n",
(buf.global.version >> 24) & 0xff,
(buf.global.version >> 16) & 0xff,
(buf.global.version >> 8) & 0xff,
(buf.global.version >> 0) & 0xff);
snd_iprintf(buffer, " clock caps:");
for (i = 0; i <= 6; ++i)
if (buf.global.clock_caps & (1 << i))
@ -243,10 +243,74 @@ static void dice_proc_read(struct snd_info_entry *entry,
}
}
void snd_dice_create_proc(struct snd_dice *dice)
static void dice_proc_read_formation(struct snd_info_entry *entry,
struct snd_info_buffer *buffer)
{
static const char *const rate_labels[] = {
[SND_DICE_RATE_MODE_LOW] = "low",
[SND_DICE_RATE_MODE_MIDDLE] = "middle",
[SND_DICE_RATE_MODE_HIGH] = "high",
};
struct snd_dice *dice = entry->private_data;
int i, j;
snd_iprintf(buffer, "Output stream from unit:\n");
for (i = 0; i < SND_DICE_RATE_MODE_COUNT; ++i)
snd_iprintf(buffer, "\t%s", rate_labels[i]);
snd_iprintf(buffer, "\tMIDI\n");
for (i = 0; i < MAX_STREAMS; ++i) {
snd_iprintf(buffer, "Tx %u:", i);
for (j = 0; j < SND_DICE_RATE_MODE_COUNT; ++j)
snd_iprintf(buffer, "\t%u", dice->tx_pcm_chs[i][j]);
snd_iprintf(buffer, "\t%u\n", dice->tx_midi_ports[i]);
}
snd_iprintf(buffer, "Input stream to unit:\n");
for (i = 0; i < SND_DICE_RATE_MODE_COUNT; ++i)
snd_iprintf(buffer, "\t%s", rate_labels[i]);
snd_iprintf(buffer, "\n");
for (i = 0; i < MAX_STREAMS; ++i) {
snd_iprintf(buffer, "Rx %u:", i);
for (j = 0; j < SND_DICE_RATE_MODE_COUNT; ++j)
snd_iprintf(buffer, "\t%u", dice->rx_pcm_chs[i][j]);
snd_iprintf(buffer, "\t%u\n", dice->rx_midi_ports[i]);
}
}
static void add_node(struct snd_dice *dice, struct snd_info_entry *root,
const char *name,
void (*op)(struct snd_info_entry *entry,
struct snd_info_buffer *buffer))
{
struct snd_info_entry *entry;
if (!snd_card_proc_new(dice->card, "dice", &entry))
snd_info_set_text_ops(entry, dice, dice_proc_read);
entry = snd_info_create_card_entry(dice->card, name, root);
if (!entry)
return;
snd_info_set_text_ops(entry, dice, op);
if (snd_info_register(entry) < 0)
snd_info_free_entry(entry);
}
void snd_dice_create_proc(struct snd_dice *dice)
{
struct snd_info_entry *root;
/*
* All nodes are automatically removed at snd_card_disconnect(),
* by following to link list.
*/
root = snd_info_create_card_entry(dice->card, "firewire",
dice->card->proc_root);
if (!root)
return;
root->mode = S_IFDIR | 0555;
if (snd_info_register(root) < 0) {
snd_info_free_entry(root);
return;
}
add_node(dice, root, "dice", dice_proc_read);
add_node(dice, root, "formation", dice_proc_read_formation);
}

View file

@ -30,13 +30,43 @@ const unsigned int snd_dice_rates[SND_DICE_RATES_COUNT] = {
[6] = 192000,
};
int snd_dice_stream_get_rate_mode(struct snd_dice *dice, unsigned int rate,
enum snd_dice_rate_mode *mode)
{
/* Corresponding to each entry in snd_dice_rates. */
static const enum snd_dice_rate_mode modes[] = {
[0] = SND_DICE_RATE_MODE_LOW,
[1] = SND_DICE_RATE_MODE_LOW,
[2] = SND_DICE_RATE_MODE_LOW,
[3] = SND_DICE_RATE_MODE_MIDDLE,
[4] = SND_DICE_RATE_MODE_MIDDLE,
[5] = SND_DICE_RATE_MODE_HIGH,
[6] = SND_DICE_RATE_MODE_HIGH,
};
int i;
for (i = 0; i < ARRAY_SIZE(snd_dice_rates); i++) {
if (!(dice->clock_caps & BIT(i)))
continue;
if (snd_dice_rates[i] != rate)
continue;
*mode = modes[i];
return 0;
}
return -EINVAL;
}
/*
* This operation has an effect to synchronize GLOBAL_STATUS/GLOBAL_SAMPLE_RATE
* to GLOBAL_STATUS. Especially, just after powering on, these are different.
*/
static int ensure_phase_lock(struct snd_dice *dice)
static int ensure_phase_lock(struct snd_dice *dice, unsigned int rate)
{
__be32 reg, nominal;
u32 data;
int i;
int err;
err = snd_dice_transaction_read_global(dice, GLOBAL_CLOCK_SELECT,
@ -44,9 +74,21 @@ static int ensure_phase_lock(struct snd_dice *dice)
if (err < 0)
return err;
data = be32_to_cpu(reg);
data &= ~CLOCK_RATE_MASK;
for (i = 0; i < ARRAY_SIZE(snd_dice_rates); ++i) {
if (snd_dice_rates[i] == rate)
break;
}
if (i == ARRAY_SIZE(snd_dice_rates))
return -EINVAL;
data |= i << CLOCK_RATE_SHIFT;
if (completion_done(&dice->clock_accepted))
reinit_completion(&dice->clock_accepted);
reg = cpu_to_be32(data);
err = snd_dice_transaction_write_global(dice, GLOBAL_CLOCK_SELECT,
&reg, sizeof(reg));
if (err < 0)
@ -192,6 +234,7 @@ static int start_streams(struct snd_dice *dice, enum amdtp_stream_direction dir,
unsigned int rate, struct reg_params *params)
{
__be32 reg[2];
enum snd_dice_rate_mode mode;
unsigned int i, pcm_chs, midi_ports;
struct amdtp_stream *streams;
struct fw_iso_resources *resources;
@ -206,12 +249,23 @@ static int start_streams(struct snd_dice *dice, enum amdtp_stream_direction dir,
resources = dice->rx_resources;
}
err = snd_dice_stream_get_rate_mode(dice, rate, &mode);
if (err < 0)
return err;
for (i = 0; i < params->count; i++) {
unsigned int pcm_cache;
unsigned int midi_cache;
if (dir == AMDTP_IN_STREAM) {
pcm_cache = dice->tx_pcm_chs[i][mode];
midi_cache = dice->tx_midi_ports[i];
err = snd_dice_transaction_read_tx(dice,
params->size * i + TX_NUMBER_AUDIO,
reg, sizeof(reg));
} else {
pcm_cache = dice->rx_pcm_chs[i][mode];
midi_cache = dice->rx_midi_ports[i];
err = snd_dice_transaction_read_rx(dice,
params->size * i + RX_NUMBER_AUDIO,
reg, sizeof(reg));
@ -221,6 +275,14 @@ static int start_streams(struct snd_dice *dice, enum amdtp_stream_direction dir,
pcm_chs = be32_to_cpu(reg[0]);
midi_ports = be32_to_cpu(reg[1]);
/* These are important for developer of this driver. */
if (pcm_chs != pcm_cache || midi_ports != midi_cache) {
dev_info(&dice->unit->device,
"cache mismatch: pcm: %u:%u, midi: %u:%u\n",
pcm_chs, pcm_cache, midi_ports, midi_cache);
return -EPROTO;
}
err = keep_resources(dice, dir, i, rate, pcm_chs, midi_ports);
if (err < 0)
return err;
@ -256,6 +318,68 @@ static int start_streams(struct snd_dice *dice, enum amdtp_stream_direction dir,
return err;
}
static int start_duplex_streams(struct snd_dice *dice, unsigned int rate)
{
struct reg_params tx_params, rx_params;
int i;
int err;
err = get_register_params(dice, &tx_params, &rx_params);
if (err < 0)
return err;
/* Stop transmission. */
stop_streams(dice, AMDTP_IN_STREAM, &tx_params);
stop_streams(dice, AMDTP_OUT_STREAM, &rx_params);
snd_dice_transaction_clear_enable(dice);
release_resources(dice);
err = ensure_phase_lock(dice, rate);
if (err < 0) {
dev_err(&dice->unit->device, "fail to ensure phase lock\n");
return err;
}
/* Likely to have changed stream formats. */
err = get_register_params(dice, &tx_params, &rx_params);
if (err < 0)
return err;
/* Start both streams. */
err = start_streams(dice, AMDTP_IN_STREAM, rate, &tx_params);
if (err < 0)
goto error;
err = start_streams(dice, AMDTP_OUT_STREAM, rate, &rx_params);
if (err < 0)
goto error;
err = snd_dice_transaction_set_enable(dice);
if (err < 0) {
dev_err(&dice->unit->device, "fail to enable interface\n");
goto error;
}
for (i = 0; i < MAX_STREAMS; i++) {
if ((i < tx_params.count &&
!amdtp_stream_wait_callback(&dice->tx_stream[i],
CALLBACK_TIMEOUT)) ||
(i < rx_params.count &&
!amdtp_stream_wait_callback(&dice->rx_stream[i],
CALLBACK_TIMEOUT))) {
err = -ETIMEDOUT;
goto error;
}
}
return 0;
error:
stop_streams(dice, AMDTP_IN_STREAM, &tx_params);
stop_streams(dice, AMDTP_OUT_STREAM, &rx_params);
snd_dice_transaction_clear_enable(dice);
release_resources(dice);
return err;
}
/*
* MEMO: After this function, there're two states of streams:
* - None streams are running.
@ -265,17 +389,13 @@ int snd_dice_stream_start_duplex(struct snd_dice *dice, unsigned int rate)
{
unsigned int curr_rate;
unsigned int i;
struct reg_params tx_params, rx_params;
bool need_to_start;
enum snd_dice_rate_mode mode;
int err;
if (dice->substreams_counter == 0)
return -EIO;
err = get_register_params(dice, &tx_params, &rx_params);
if (err < 0)
return err;
/* Check sampling transmission frequency. */
err = snd_dice_transaction_get_rate(dice, &curr_rate);
if (err < 0) {
dev_err(&dice->unit->device,
@ -285,72 +405,36 @@ int snd_dice_stream_start_duplex(struct snd_dice *dice, unsigned int rate)
if (rate == 0)
rate = curr_rate;
if (rate != curr_rate)
return -EINVAL;
goto restart;
/* Judge to need to restart streams. */
for (i = 0; i < MAX_STREAMS; i++) {
if (i < tx_params.count) {
if (amdtp_streaming_error(&dice->tx_stream[i]) ||
!amdtp_stream_running(&dice->tx_stream[i]))
break;
}
if (i < rx_params.count) {
if (amdtp_streaming_error(&dice->rx_stream[i]) ||
!amdtp_stream_running(&dice->rx_stream[i]))
break;
}
/* Check error of packet streaming. */
for (i = 0; i < MAX_STREAMS; ++i) {
if (amdtp_streaming_error(&dice->tx_stream[i]))
break;
if (amdtp_streaming_error(&dice->rx_stream[i]))
break;
}
need_to_start = (i < MAX_STREAMS);
if (i < MAX_STREAMS)
goto restart;
if (need_to_start) {
/* Stop transmission. */
snd_dice_transaction_clear_enable(dice);
stop_streams(dice, AMDTP_IN_STREAM, &tx_params);
stop_streams(dice, AMDTP_OUT_STREAM, &rx_params);
release_resources(dice);
err = ensure_phase_lock(dice);
if (err < 0) {
dev_err(&dice->unit->device,
"fail to ensure phase lock\n");
return err;
}
/* Start both streams. */
err = start_streams(dice, AMDTP_IN_STREAM, rate, &tx_params);
if (err < 0)
goto error;
err = start_streams(dice, AMDTP_OUT_STREAM, rate, &rx_params);
if (err < 0)
goto error;
err = snd_dice_transaction_set_enable(dice);
if (err < 0) {
dev_err(&dice->unit->device,
"fail to enable interface\n");
goto error;
}
for (i = 0; i < MAX_STREAMS; i++) {
if ((i < tx_params.count &&
!amdtp_stream_wait_callback(&dice->tx_stream[i],
CALLBACK_TIMEOUT)) ||
(i < rx_params.count &&
!amdtp_stream_wait_callback(&dice->rx_stream[i],
CALLBACK_TIMEOUT))) {
err = -ETIMEDOUT;
goto error;
}
}
/* Check required streams are running or not. */
err = snd_dice_stream_get_rate_mode(dice, rate, &mode);
if (err < 0)
return err;
for (i = 0; i < MAX_STREAMS; ++i) {
if (dice->tx_pcm_chs[i][mode] > 0 &&
!amdtp_stream_running(&dice->tx_stream[i]))
break;
if (dice->rx_pcm_chs[i][mode] > 0 &&
!amdtp_stream_running(&dice->rx_stream[i]))
break;
}
if (i < MAX_STREAMS)
goto restart;
return err;
error:
snd_dice_transaction_clear_enable(dice);
stop_streams(dice, AMDTP_IN_STREAM, &tx_params);
stop_streams(dice, AMDTP_OUT_STREAM, &rx_params);
release_resources(dice);
return err;
return 0;
restart:
return start_duplex_streams(dice, rate);
}
/*
@ -484,6 +568,69 @@ void snd_dice_stream_update_duplex(struct snd_dice *dice)
}
}
int snd_dice_stream_detect_current_formats(struct snd_dice *dice)
{
unsigned int rate;
enum snd_dice_rate_mode mode;
__be32 reg[2];
struct reg_params tx_params, rx_params;
int i;
int err;
/* If extended protocol is available, detect detail spec. */
err = snd_dice_detect_extension_formats(dice);
if (err >= 0)
return err;
/*
* Available stream format is restricted at current mode of sampling
* clock.
*/
err = snd_dice_transaction_get_rate(dice, &rate);
if (err < 0)
return err;
err = snd_dice_stream_get_rate_mode(dice, rate, &mode);
if (err < 0)
return err;
/*
* Just after owning the unit (GLOBAL_OWNER), the unit can return
* invalid stream formats. Selecting clock parameters have an effect
* for the unit to refine it.
*/
err = ensure_phase_lock(dice, rate);
if (err < 0)
return err;
err = get_register_params(dice, &tx_params, &rx_params);
if (err < 0)
return err;
for (i = 0; i < tx_params.count; ++i) {
err = snd_dice_transaction_read_tx(dice,
tx_params.size * i + TX_NUMBER_AUDIO,
reg, sizeof(reg));
if (err < 0)
return err;
dice->tx_pcm_chs[i][mode] = be32_to_cpu(reg[0]);
dice->tx_midi_ports[i] = max_t(unsigned int,
be32_to_cpu(reg[1]), dice->tx_midi_ports[i]);
}
for (i = 0; i < rx_params.count; ++i) {
err = snd_dice_transaction_read_rx(dice,
rx_params.size * i + RX_NUMBER_AUDIO,
reg, sizeof(reg));
if (err < 0)
return err;
dice->rx_pcm_chs[i][mode] = be32_to_cpu(reg[0]);
dice->rx_midi_ports[i] = max_t(unsigned int,
be32_to_cpu(reg[1]), dice->rx_midi_ports[i]);
}
return 0;
}
static void dice_lock_changed(struct snd_dice *dice)
{
dice->dev_lock_changed = true;

View file

@ -0,0 +1,104 @@
// SPDX-License-Identifier: GPL-2.0
/*
* dice-tc_electronic.c - a part of driver for DICE based devices
*
* Copyright (c) 2018 Takashi Sakamoto
*/
#include "dice.h"
struct dice_tc_spec {
unsigned int tx_pcm_chs[MAX_STREAMS][SND_DICE_RATE_MODE_COUNT];
unsigned int rx_pcm_chs[MAX_STREAMS][SND_DICE_RATE_MODE_COUNT];
bool has_midi;
};
static const struct dice_tc_spec desktop_konnekt6 = {
.tx_pcm_chs = {{6, 6, 2}, {0, 0, 0} },
.rx_pcm_chs = {{6, 6, 4}, {0, 0, 0} },
.has_midi = false,
};
static const struct dice_tc_spec impact_twin = {
.tx_pcm_chs = {{14, 10, 6}, {0, 0, 0} },
.rx_pcm_chs = {{14, 10, 6}, {0, 0, 0} },
.has_midi = true,
};
static const struct dice_tc_spec konnekt_8 = {
.tx_pcm_chs = {{4, 4, 3}, {0, 0, 0} },
.rx_pcm_chs = {{4, 4, 3}, {0, 0, 0} },
.has_midi = true,
};
static const struct dice_tc_spec konnekt_24d = {
.tx_pcm_chs = {{16, 16, 6}, {0, 0, 0} },
.rx_pcm_chs = {{16, 16, 6}, {0, 0, 0} },
.has_midi = true,
};
static const struct dice_tc_spec konnekt_live = {
.tx_pcm_chs = {{16, 16, 16}, {0, 0, 0} },
.rx_pcm_chs = {{16, 16, 16}, {0, 0, 0} },
.has_midi = true,
};
static const struct dice_tc_spec studio_konnekt_48 = {
.tx_pcm_chs = {{16, 16, 8}, {16, 16, 7} },
.rx_pcm_chs = {{16, 16, 8}, {14, 14, 7} },
.has_midi = true,
};
static const struct dice_tc_spec digital_konnekt_x32 = {
.tx_pcm_chs = {{16, 16, 4}, {0, 0, 0} },
.rx_pcm_chs = {{16, 16, 4}, {0, 0, 0} },
.has_midi = false,
};
int snd_dice_detect_tcelectronic_formats(struct snd_dice *dice)
{
static const struct {
u32 model_id;
const struct dice_tc_spec *spec;
} *entry, entries[] = {
{0x00000020, &konnekt_24d},
{0x00000021, &konnekt_8},
{0x00000022, &studio_konnekt_48},
{0x00000023, &konnekt_live},
{0x00000024, &desktop_konnekt6},
{0x00000027, &impact_twin},
{0x00000030, &digital_konnekt_x32},
};
struct fw_csr_iterator it;
int key, val, model_id;
int i;
model_id = 0;
fw_csr_iterator_init(&it, dice->unit->directory);
while (fw_csr_iterator_next(&it, &key, &val)) {
if (key == CSR_MODEL) {
model_id = val;
break;
}
}
for (i = 0; i < ARRAY_SIZE(entries); ++i) {
entry = entries + i;
if (entry->model_id == model_id)
break;
}
if (i == ARRAY_SIZE(entries))
return -ENODEV;
memcpy(dice->tx_pcm_chs, entry->spec->tx_pcm_chs,
MAX_STREAMS * SND_DICE_RATE_MODE_COUNT * sizeof(unsigned int));
memcpy(dice->rx_pcm_chs, entry->spec->rx_pcm_chs,
MAX_STREAMS * SND_DICE_RATE_MODE_COUNT * sizeof(unsigned int));
if (entry->spec->has_midi) {
dice->tx_midi_ports[0] = 1;
dice->rx_midi_ports[0] = 1;
}
return 0;
}

View file

@ -265,7 +265,7 @@ int snd_dice_transaction_reinit(struct snd_dice *dice)
static int get_subaddrs(struct snd_dice *dice)
{
static const int min_values[10] = {
10, 0x64 / 4,
10, 0x60 / 4,
10, 0x18 / 4,
10, 0x18 / 4,
0, 0,
@ -301,33 +301,40 @@ static int get_subaddrs(struct snd_dice *dice)
}
}
/*
* Check that the implemented DICE driver specification major version
* number matches.
*/
err = snd_fw_transaction(dice->unit, TCODE_READ_QUADLET_REQUEST,
DICE_PRIVATE_SPACE +
be32_to_cpu(pointers[0]) * 4 + GLOBAL_VERSION,
&version, sizeof(version), 0);
if (err < 0)
goto end;
if (be32_to_cpu(pointers[1]) > 0x18) {
/*
* Check that the implemented DICE driver specification major
* version number matches.
*/
err = snd_fw_transaction(dice->unit, TCODE_READ_QUADLET_REQUEST,
DICE_PRIVATE_SPACE +
be32_to_cpu(pointers[0]) * 4 + GLOBAL_VERSION,
&version, sizeof(version), 0);
if (err < 0)
goto end;
if ((version & cpu_to_be32(0xff000000)) != cpu_to_be32(0x01000000)) {
dev_err(&dice->unit->device,
"unknown DICE version: 0x%08x\n", be32_to_cpu(version));
err = -ENODEV;
goto end;
if ((version & cpu_to_be32(0xff000000)) !=
cpu_to_be32(0x01000000)) {
dev_err(&dice->unit->device,
"unknown DICE version: 0x%08x\n",
be32_to_cpu(version));
err = -ENODEV;
goto end;
}
/* Set up later. */
dice->clock_caps = 1;
}
dice->global_offset = be32_to_cpu(pointers[0]) * 4;
dice->tx_offset = be32_to_cpu(pointers[2]) * 4;
dice->rx_offset = be32_to_cpu(pointers[4]) * 4;
dice->sync_offset = be32_to_cpu(pointers[6]) * 4;
dice->rsrv_offset = be32_to_cpu(pointers[8]) * 4;
/* Set up later. */
if (be32_to_cpu(pointers[1]) * 4 >= GLOBAL_CLOCK_CAPABILITIES + 4)
dice->clock_caps = 1;
/* Old firmware doesn't support these fields. */
if (pointers[7])
dice->sync_offset = be32_to_cpu(pointers[6]) * 4;
if (pointers[9])
dice->rsrv_offset = be32_to_cpu(pointers[8]) * 4;
end:
kfree(pointers);
return err;

View file

@ -15,40 +15,15 @@ MODULE_LICENSE("GPL v2");
#define OUI_LOUD 0x000ff2
#define OUI_FOCUSRITE 0x00130e
#define OUI_TCELECTRONIC 0x000166
#define OUI_ALESIS 0x000595
#define OUI_MAUDIO 0x000d6c
#define OUI_MYTEK 0x001ee8
#define DICE_CATEGORY_ID 0x04
#define WEISS_CATEGORY_ID 0x00
#define LOUD_CATEGORY_ID 0x10
/*
* Some models support several isochronous channels, while these streams are not
* always available. In this case, add the model name to this list.
*/
static bool force_two_pcm_support(struct fw_unit *unit)
{
static const char *const models[] = {
/* TC Electronic models. */
"StudioKonnekt48",
/* Focusrite models. */
"SAFFIRE_PRO_40",
"LIQUID_SAFFIRE_56",
"SAFFIRE_PRO_40_1",
};
char model[32];
unsigned int i;
int err;
err = fw_csr_string(unit->directory, CSR_MODEL, model, sizeof(model));
if (err < 0)
return false;
for (i = 0; i < ARRAY_SIZE(models); i++) {
if (strcmp(models[i], model) == 0)
break;
}
return i < ARRAY_SIZE(models);
}
#define MODEL_ALESIS_IO_BOTH 0x000001
static int check_dice_category(struct fw_unit *unit)
{
@ -75,11 +50,6 @@ static int check_dice_category(struct fw_unit *unit)
}
}
if (vendor == OUI_FOCUSRITE || vendor == OUI_TCELECTRONIC) {
if (force_two_pcm_support(unit))
return 0;
}
if (vendor == OUI_WEISS)
category = WEISS_CATEGORY_ID;
else if (vendor == OUI_LOUD)
@ -186,9 +156,6 @@ static void do_registration(struct work_struct *work)
if (err < 0)
return;
if (force_two_pcm_support(dice->unit))
dice->force_two_pcms = true;
err = snd_dice_transaction_init(dice);
if (err < 0)
goto error;
@ -199,6 +166,10 @@ static void do_registration(struct work_struct *work)
dice_card_strings(dice);
err = dice->detect_formats(dice);
if (err < 0)
goto error;
err = snd_dice_stream_init_duplex(dice);
if (err < 0)
goto error;
@ -239,14 +210,17 @@ static void do_registration(struct work_struct *work)
"Sound card registration failed: %d\n", err);
}
static int dice_probe(struct fw_unit *unit, const struct ieee1394_device_id *id)
static int dice_probe(struct fw_unit *unit,
const struct ieee1394_device_id *entry)
{
struct snd_dice *dice;
int err;
err = check_dice_category(unit);
if (err < 0)
return -ENODEV;
if (!entry->driver_data) {
err = check_dice_category(unit);
if (err < 0)
return -ENODEV;
}
/* Allocate this independent of sound card instance. */
dice = kzalloc(sizeof(struct snd_dice), GFP_KERNEL);
@ -256,6 +230,13 @@ static int dice_probe(struct fw_unit *unit, const struct ieee1394_device_id *id)
dice->unit = fw_unit_get(unit);
dev_set_drvdata(&unit->device, dice);
if (!entry->driver_data) {
dice->detect_formats = snd_dice_stream_detect_current_formats;
} else {
dice->detect_formats =
(snd_dice_detect_formats_t)entry->driver_data;
}
spin_lock_init(&dice->lock);
mutex_init(&dice->mutex);
init_completion(&dice->clock_accepted);
@ -313,17 +294,98 @@ static void dice_bus_reset(struct fw_unit *unit)
#define DICE_INTERFACE 0x000001
static const struct ieee1394_device_id dice_id_table[] = {
/* M-Audio Profire 2626 has a different value in version field. */
{
.match_flags = IEEE1394_MATCH_VENDOR_ID |
IEEE1394_MATCH_MODEL_ID,
.vendor_id = OUI_MAUDIO,
.model_id = 0x000010,
.driver_data = (kernel_ulong_t)snd_dice_detect_extension_formats,
},
/* M-Audio Profire 610 has a different value in version field. */
{
.match_flags = IEEE1394_MATCH_VENDOR_ID |
IEEE1394_MATCH_MODEL_ID,
.vendor_id = OUI_MAUDIO,
.model_id = 0x000011,
.driver_data = (kernel_ulong_t)snd_dice_detect_extension_formats,
},
/* TC Electronic Konnekt 24D. */
{
.match_flags = IEEE1394_MATCH_VENDOR_ID |
IEEE1394_MATCH_MODEL_ID,
.vendor_id = OUI_TCELECTRONIC,
.model_id = 0x000020,
.driver_data = (kernel_ulong_t)snd_dice_detect_tcelectronic_formats,
},
/* TC Electronic Konnekt 8. */
{
.match_flags = IEEE1394_MATCH_VENDOR_ID |
IEEE1394_MATCH_MODEL_ID,
.vendor_id = OUI_TCELECTRONIC,
.model_id = 0x000021,
.driver_data = (kernel_ulong_t)snd_dice_detect_tcelectronic_formats,
},
/* TC Electronic Studio Konnekt 48. */
{
.match_flags = IEEE1394_MATCH_VENDOR_ID |
IEEE1394_MATCH_MODEL_ID,
.vendor_id = OUI_TCELECTRONIC,
.model_id = 0x000022,
.driver_data = (kernel_ulong_t)snd_dice_detect_tcelectronic_formats,
},
/* TC Electronic Konnekt Live. */
{
.match_flags = IEEE1394_MATCH_VENDOR_ID |
IEEE1394_MATCH_MODEL_ID,
.vendor_id = OUI_TCELECTRONIC,
.model_id = 0x000023,
.driver_data = (kernel_ulong_t)snd_dice_detect_tcelectronic_formats,
},
/* TC Electronic Desktop Konnekt 6. */
{
.match_flags = IEEE1394_MATCH_VENDOR_ID |
IEEE1394_MATCH_MODEL_ID,
.vendor_id = OUI_TCELECTRONIC,
.model_id = 0x000024,
.driver_data = (kernel_ulong_t)snd_dice_detect_tcelectronic_formats,
},
/* TC Electronic Impact Twin. */
{
.match_flags = IEEE1394_MATCH_VENDOR_ID |
IEEE1394_MATCH_MODEL_ID,
.vendor_id = OUI_TCELECTRONIC,
.model_id = 0x000027,
.driver_data = (kernel_ulong_t)snd_dice_detect_tcelectronic_formats,
},
/* TC Electronic Digital Konnekt x32. */
{
.match_flags = IEEE1394_MATCH_VENDOR_ID |
IEEE1394_MATCH_MODEL_ID,
.vendor_id = OUI_TCELECTRONIC,
.model_id = 0x000030,
.driver_data = (kernel_ulong_t)snd_dice_detect_tcelectronic_formats,
},
/* Alesis iO14/iO26. */
{
.match_flags = IEEE1394_MATCH_VENDOR_ID |
IEEE1394_MATCH_MODEL_ID,
.vendor_id = OUI_ALESIS,
.model_id = MODEL_ALESIS_IO_BOTH,
.driver_data = (kernel_ulong_t)snd_dice_detect_alesis_formats,
},
/* Mytek Stereo 192 DSD-DAC. */
{
.match_flags = IEEE1394_MATCH_VENDOR_ID |
IEEE1394_MATCH_MODEL_ID,
.vendor_id = OUI_MYTEK,
.model_id = 0x000002,
.driver_data = (kernel_ulong_t)snd_dice_detect_mytek_formats,
},
{
.match_flags = IEEE1394_MATCH_VERSION,
.version = DICE_INTERFACE,
},
/* M-Audio Profire 610/2626 has a different value in version field. */
{
.match_flags = IEEE1394_MATCH_VENDOR_ID |
IEEE1394_MATCH_SPECIFIER_ID,
.vendor_id = 0x000d6c,
.specifier_id = 0x000d6c,
},
{ }
};
MODULE_DEVICE_TABLE(ieee1394, dice_id_table);

View file

@ -63,6 +63,16 @@
*/
#define MAX_STREAMS 2
enum snd_dice_rate_mode {
SND_DICE_RATE_MODE_LOW = 0,
SND_DICE_RATE_MODE_MIDDLE,
SND_DICE_RATE_MODE_HIGH,
SND_DICE_RATE_MODE_COUNT,
};
struct snd_dice;
typedef int (*snd_dice_detect_formats_t)(struct snd_dice *dice);
struct snd_dice {
struct snd_card *card;
struct fw_unit *unit;
@ -80,6 +90,11 @@ struct snd_dice {
unsigned int rsrv_offset;
unsigned int clock_caps;
unsigned int tx_pcm_chs[MAX_STREAMS][SND_DICE_RATE_MODE_COUNT];
unsigned int rx_pcm_chs[MAX_STREAMS][SND_DICE_RATE_MODE_COUNT];
unsigned int tx_midi_ports[MAX_STREAMS];
unsigned int rx_midi_ports[MAX_STREAMS];
snd_dice_detect_formats_t detect_formats;
struct fw_address_handler notification_handler;
int owner_generation;
@ -98,8 +113,6 @@ struct snd_dice {
bool global_enabled;
struct completion clock_accepted;
unsigned int substreams_counter;
bool force_two_pcms;
};
enum snd_dice_addr_type {
@ -190,11 +203,14 @@ void snd_dice_transaction_destroy(struct snd_dice *dice);
#define SND_DICE_RATES_COUNT 7
extern const unsigned int snd_dice_rates[SND_DICE_RATES_COUNT];
int snd_dice_stream_get_rate_mode(struct snd_dice *dice, unsigned int rate,
enum snd_dice_rate_mode *mode);
int snd_dice_stream_start_duplex(struct snd_dice *dice, unsigned int rate);
void snd_dice_stream_stop_duplex(struct snd_dice *dice);
int snd_dice_stream_init_duplex(struct snd_dice *dice);
void snd_dice_stream_destroy_duplex(struct snd_dice *dice);
void snd_dice_stream_update_duplex(struct snd_dice *dice);
int snd_dice_stream_detect_current_formats(struct snd_dice *dice);
int snd_dice_stream_lock_try(struct snd_dice *dice);
void snd_dice_stream_lock_release(struct snd_dice *dice);
@ -207,4 +223,9 @@ void snd_dice_create_proc(struct snd_dice *dice);
int snd_dice_create_midi(struct snd_dice *dice);
int snd_dice_detect_tcelectronic_formats(struct snd_dice *dice);
int snd_dice_detect_alesis_formats(struct snd_dice *dice);
int snd_dice_detect_extension_formats(struct snd_dice *dice);
int snd_dice_detect_mytek_formats(struct snd_dice *dice);
#endif

View file

@ -79,7 +79,7 @@ void snd_dg00x_proc_init(struct snd_dg00x *dg00x)
if (root == NULL)
return;
root->mode = S_IFDIR | S_IRUGO | S_IXUGO;
root->mode = S_IFDIR | 0555;
if (snd_info_register(root) < 0) {
snd_info_free_entry(root);
return;

View file

@ -52,7 +52,7 @@ void snd_ff_proc_init(struct snd_ff *ff)
ff->card->proc_root);
if (root == NULL)
return;
root->mode = S_IFDIR | S_IRUGO | S_IXUGO;
root->mode = S_IFDIR | 0555;
if (snd_info_register(root) < 0) {
snd_info_free_entry(root);
return;

View file

@ -219,7 +219,7 @@ void snd_efw_proc_init(struct snd_efw *efw)
efw->card->proc_root);
if (root == NULL)
return;
root->mode = S_IFDIR | S_IRUGO | S_IXUGO;
root->mode = S_IFDIR | 0555;
if (snd_info_register(root) < 0) {
snd_info_free_entry(root);
return;

View file

@ -569,18 +569,20 @@ static int isight_create_mixer(struct isight *isight)
return err;
isight->gain_max = be32_to_cpu(value);
isight->gain_tlv[0] = SNDRV_CTL_TLVT_DB_MINMAX;
isight->gain_tlv[1] = 2 * sizeof(unsigned int);
isight->gain_tlv[SNDRV_CTL_TLVO_TYPE] = SNDRV_CTL_TLVT_DB_MINMAX;
isight->gain_tlv[SNDRV_CTL_TLVO_LEN] = 2 * sizeof(unsigned int);
err = reg_read(isight, REG_GAIN_DB_START, &value);
if (err < 0)
return err;
isight->gain_tlv[2] = (s32)be32_to_cpu(value) * 100;
isight->gain_tlv[SNDRV_CTL_TLVO_DB_MINMAX_MIN] =
(s32)be32_to_cpu(value) * 100;
err = reg_read(isight, REG_GAIN_DB_END, &value);
if (err < 0)
return err;
isight->gain_tlv[3] = (s32)be32_to_cpu(value) * 100;
isight->gain_tlv[SNDRV_CTL_TLVO_DB_MINMAX_MAX] =
(s32)be32_to_cpu(value) * 100;
ctl = snd_ctl_new1(&gain_control, isight);
if (ctl)

View file

@ -107,7 +107,7 @@ void snd_motu_proc_init(struct snd_motu *motu)
motu->card->proc_root);
if (root == NULL)
return;
root->mode = S_IFDIR | S_IRUGO | S_IXUGO;
root->mode = S_IFDIR | 0555;
if (snd_info_register(root) < 0) {
snd_info_free_entry(root);
return;

View file

@ -103,7 +103,7 @@ void snd_oxfw_proc_init(struct snd_oxfw *oxfw)
oxfw->card->proc_root);
if (root == NULL)
return;
root->mode = S_IFDIR | S_IRUGO | S_IXUGO;
root->mode = S_IFDIR | 0555;
if (snd_info_register(root) < 0) {
snd_info_free_entry(root);
return;

View file

@ -49,7 +49,6 @@ static bool detect_loud_models(struct fw_unit *unit)
"Tapco LINK.firewire 4x6",
"U.420"};
char model[32];
unsigned int i;
int err;
err = fw_csr_string(unit->directory, CSR_MODEL,
@ -57,12 +56,7 @@ static bool detect_loud_models(struct fw_unit *unit)
if (err < 0)
return false;
for (i = 0; i < ARRAY_SIZE(models); i++) {
if (strcmp(models[i], model) == 0)
break;
}
return (i < ARRAY_SIZE(models));
return match_string(models, ARRAY_SIZE(models), model) >= 0;
}
static int name_card(struct snd_oxfw *oxfw)

View file

@ -78,7 +78,7 @@ void snd_tscm_proc_init(struct snd_tscm *tscm)
tscm->card->proc_root);
if (root == NULL)
return;
root->mode = S_IFDIR | S_IRUGO | S_IXUGO;
root->mode = S_IFDIR | 0555;
if (snd_info_register(root) < 0) {
snd_info_free_entry(root);
return;

View file

@ -65,10 +65,10 @@ static bool hda_writeable_reg(struct device *dev, unsigned int reg)
{
struct hdac_device *codec = dev_to_hdac_dev(dev);
unsigned int verb = get_verb(reg);
const unsigned int *v;
int i;
for (i = 0; i < codec->vendor_verbs.used; i++) {
unsigned int *v = snd_array_elem(&codec->vendor_verbs, i);
snd_array_for_each(&codec->vendor_verbs, i, v) {
if (verb == *v)
return true;
}

View file

@ -192,7 +192,7 @@ static int snd_cmi8328_mixer(struct snd_wss *chip)
}
/* find index of an item in "-1"-ended array */
int array_find(int array[], int item)
static int array_find(int array[], int item)
{
int i;
@ -203,7 +203,7 @@ int array_find(int array[], int item)
return -1;
}
/* the same for long */
int array_find_l(long array[], long item)
static int array_find_l(long array[], long item)
{
int i;

View file

@ -757,9 +757,9 @@ static int snd_msnd_pinnacle_cfg_reset(int cfg)
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
module_param_array(index, int, NULL, S_IRUGO);
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for msnd_pinnacle soundcard.");
module_param_array(id, charp, NULL, S_IRUGO);
module_param_array(id, charp, NULL, 0444);
MODULE_PARM_DESC(id, "ID string for msnd_pinnacle soundcard.");
static long io[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
@ -801,22 +801,22 @@ MODULE_LICENSE("GPL");
MODULE_FIRMWARE(INITCODEFILE);
MODULE_FIRMWARE(PERMCODEFILE);
module_param_hw_array(io, long, ioport, NULL, S_IRUGO);
module_param_hw_array(io, long, ioport, NULL, 0444);
MODULE_PARM_DESC(io, "IO port #");
module_param_hw_array(irq, int, irq, NULL, S_IRUGO);
module_param_hw_array(mem, long, iomem, NULL, S_IRUGO);
module_param_array(write_ndelay, int, NULL, S_IRUGO);
module_param(calibrate_signal, int, S_IRUGO);
module_param_hw_array(irq, int, irq, NULL, 0444);
module_param_hw_array(mem, long, iomem, NULL, 0444);
module_param_array(write_ndelay, int, NULL, 0444);
module_param(calibrate_signal, int, 0444);
#ifndef MSND_CLASSIC
module_param_array(digital, int, NULL, S_IRUGO);
module_param_hw_array(cfg, long, ioport, NULL, S_IRUGO);
module_param_array(reset, int, 0, S_IRUGO);
module_param_hw_array(mpu_io, long, ioport, NULL, S_IRUGO);
module_param_hw_array(mpu_irq, int, irq, NULL, S_IRUGO);
module_param_hw_array(ide_io0, long, ioport, NULL, S_IRUGO);
module_param_hw_array(ide_io1, long, ioport, NULL, S_IRUGO);
module_param_hw_array(ide_irq, int, irq, NULL, S_IRUGO);
module_param_hw_array(joystick_io, long, ioport, NULL, S_IRUGO);
module_param_array(digital, int, NULL, 0444);
module_param_hw_array(cfg, long, ioport, NULL, 0444);
module_param_array(reset, int, 0, 0444);
module_param_hw_array(mpu_io, long, ioport, NULL, 0444);
module_param_hw_array(mpu_irq, int, irq, NULL, 0444);
module_param_hw_array(ide_io0, long, ioport, NULL, 0444);
module_param_hw_array(ide_io1, long, ioport, NULL, 0444);
module_param_hw_array(ide_irq, int, irq, NULL, 0444);
module_param_hw_array(joystick_io, long, ioport, NULL, 0444);
#endif

View file

@ -592,7 +592,7 @@ static int snd_sc6000_probe(struct device *devptr, unsigned int dev)
*vport = devm_ioport_map(devptr, port[dev], 0x10);
if (*vport == NULL) {
snd_printk(KERN_ERR PFX
"I/O port cannot be iomaped.\n");
"I/O port cannot be iomapped.\n");
err = -EBUSY;
goto err_unmap1;
}
@ -607,7 +607,7 @@ static int snd_sc6000_probe(struct device *devptr, unsigned int dev)
vmss_port = devm_ioport_map(devptr, mss_port[dev], 4);
if (!vmss_port) {
snd_printk(KERN_ERR PFX
"MSS port I/O cannot be iomaped.\n");
"MSS port I/O cannot be iomapped.\n");
err = -EBUSY;
goto err_unmap2;
}

View file

@ -448,7 +448,7 @@ void snd_ac97_proc_init(struct snd_ac97 * ac97)
if ((entry = snd_info_create_card_entry(ac97->bus->card, name, ac97->bus->proc)) != NULL) {
snd_info_set_text_ops(entry, ac97, snd_ac97_proc_regs_read);
#ifdef CONFIG_SND_DEBUG
entry->mode |= S_IWUSR;
entry->mode |= 0200;
entry->c.text.write = snd_ac97_proc_regs_write;
#endif
if (snd_info_register(entry) < 0) {
@ -474,7 +474,7 @@ void snd_ac97_bus_proc_init(struct snd_ac97_bus * bus)
sprintf(name, "codec97#%d", bus->num);
if ((entry = snd_info_create_card_entry(bus->card, name, bus->card->proc_root)) != NULL) {
entry->mode = S_IFDIR | S_IRUGO | S_IXUGO;
entry->mode = S_IFDIR | 0555;
if (snd_info_register(entry) < 0) {
snd_info_free_entry(entry);
entry = NULL;

View file

@ -258,7 +258,7 @@ snd_ad1889_ac97_ready(struct snd_ad1889 *chip)
while (!(ad1889_readw(chip, AD_AC97_ACIC) & AD_AC97_ACIC_ACRDY)
&& --retry)
mdelay(1);
usleep_range(1000, 2000);
if (!retry) {
dev_err(chip->card->dev, "[%s] Link is not ready.\n",
__func__);
@ -872,7 +872,7 @@ snd_ad1889_init(struct snd_ad1889 *chip)
ad1889_writew(chip, AD_DS_CCS, AD_DS_CCS_CLKEN); /* turn on clock */
ad1889_readw(chip, AD_DS_CCS); /* flush posted write */
mdelay(10);
usleep_range(10000, 11000);
/* enable Master and Target abort interrupts */
ad1889_writel(chip, AD_DMA_DISR, AD_DMA_DISR_PMAE | AD_DMA_DISR_PTAE);

View file

@ -69,27 +69,27 @@ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
static bool enable_hpi_hwdep = 1;
module_param_array(index, int, NULL, S_IRUGO);
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "ALSA index value for AudioScience soundcard.");
module_param_array(id, charp, NULL, S_IRUGO);
module_param_array(id, charp, NULL, 0444);
MODULE_PARM_DESC(id, "ALSA ID string for AudioScience soundcard.");
module_param_array(enable, bool, NULL, S_IRUGO);
module_param_array(enable, bool, NULL, 0444);
MODULE_PARM_DESC(enable, "ALSA enable AudioScience soundcard.");
module_param(enable_hpi_hwdep, bool, S_IRUGO|S_IWUSR);
module_param(enable_hpi_hwdep, bool, 0644);
MODULE_PARM_DESC(enable_hpi_hwdep,
"ALSA enable HPI hwdep for AudioScience soundcard ");
/* identify driver */
#ifdef KERNEL_ALSA_BUILD
static char *build_info = "Built using headers from kernel source";
module_param(build_info, charp, S_IRUGO);
module_param(build_info, charp, 0444);
MODULE_PARM_DESC(build_info, "Built using headers from kernel source");
#else
static char *build_info = "Built within ALSA source";
module_param(build_info, charp, S_IRUGO);
module_param(build_info, charp, 0444);
MODULE_PARM_DESC(build_info, "Built within ALSA source");
#endif

View file

@ -46,14 +46,14 @@ MODULE_FIRMWARE("asihpi/dsp8900.bin");
#endif
static int prealloc_stream_buf;
module_param(prealloc_stream_buf, int, S_IRUGO);
module_param(prealloc_stream_buf, int, 0444);
MODULE_PARM_DESC(prealloc_stream_buf,
"Preallocate size for per-adapter stream buffer");
/* Allow the debug level to be changed after module load.
E.g. echo 2 > /sys/module/asihpi/parameters/hpiDebugLevel
*/
module_param(hpi_debug_level, int, S_IRUGO | S_IWUSR);
module_param(hpi_debug_level, int, 0644);
MODULE_PARM_DESC(hpi_debug_level, "debug verbosity 0..5");
/* List of adapters found */

View file

@ -431,7 +431,7 @@ int snd_ca0106_proc_init(struct snd_ca0106 *emu)
if(! snd_card_proc_new(emu->card, "ca0106_reg32", &entry)) {
snd_info_set_text_ops(entry, emu, snd_ca0106_proc_reg_read32);
entry->c.text.write = snd_ca0106_proc_reg_write32;
entry->mode |= S_IWUSR;
entry->mode |= 0200;
}
if(! snd_card_proc_new(emu->card, "ca0106_reg16", &entry))
snd_info_set_text_ops(entry, emu, snd_ca0106_proc_reg_read16);
@ -440,12 +440,12 @@ int snd_ca0106_proc_init(struct snd_ca0106 *emu)
if(! snd_card_proc_new(emu->card, "ca0106_regs1", &entry)) {
snd_info_set_text_ops(entry, emu, snd_ca0106_proc_reg_read1);
entry->c.text.write = snd_ca0106_proc_reg_write;
entry->mode |= S_IWUSR;
entry->mode |= 0200;
}
if(! snd_card_proc_new(emu->card, "ca0106_i2c", &entry)) {
entry->c.text.write = snd_ca0106_proc_i2c_write;
entry->private_data = emu;
entry->mode |= S_IWUSR;
entry->mode |= 0200;
}
if(! snd_card_proc_new(emu->card, "ca0106_regs2", &entry))
snd_info_set_text_ops(entry, emu, snd_ca0106_proc_reg_read2);

View file

@ -1139,7 +1139,7 @@ static int save_mixer_state(struct cmipci *cm)
struct snd_ctl_elem_value *val;
unsigned int i;
val = kmalloc(sizeof(*val), GFP_ATOMIC);
val = kmalloc(sizeof(*val), GFP_KERNEL);
if (!val)
return -ENOMEM;
for (i = 0; i < CM_SAVED_MIXERS; i++) {

View file

@ -58,7 +58,7 @@ MODULE_PARM_DESC(id, "ID string for the CS46xx soundcard.");
module_param_array(enable, bool, NULL, 0444);
MODULE_PARM_DESC(enable, "Enable CS46xx soundcard.");
module_param_array(external_amp, bool, NULL, 0444);
MODULE_PARM_DESC(external_amp, "Force to enable external amplifer.");
MODULE_PARM_DESC(external_amp, "Force to enable external amplifier.");
module_param_array(thinkpad, bool, NULL, 0444);
MODULE_PARM_DESC(thinkpad, "Force to enable Thinkpad's CLKRUN control.");
module_param_array(mmap_valid, bool, NULL, 0444);

View file

@ -2849,7 +2849,7 @@ static int snd_cs46xx_proc_init(struct snd_card *card, struct snd_cs46xx *chip)
entry->private_data = chip;
entry->c.ops = &snd_cs46xx_proc_io_ops;
entry->size = region->size;
entry->mode = S_IFREG | S_IRUSR;
entry->mode = S_IFREG | 0400;
}
}
#ifdef CONFIG_SND_CS46XX_NEW_DSP

View file

@ -798,7 +798,7 @@ int cs46xx_dsp_proc_init (struct snd_card *card, struct snd_cs46xx *chip)
if ((entry = snd_info_create_card_entry(card, "dsp", card->proc_root)) != NULL) {
entry->content = SNDRV_INFO_CONTENT_TEXT;
entry->mode = S_IFDIR | S_IRUGO | S_IXUGO;
entry->mode = S_IFDIR | 0555;
if (snd_info_register(entry) < 0) {
snd_info_free_entry(entry);
@ -814,7 +814,7 @@ int cs46xx_dsp_proc_init (struct snd_card *card, struct snd_cs46xx *chip)
if ((entry = snd_info_create_card_entry(card, "spos_symbols", ins->proc_dsp_dir)) != NULL) {
entry->content = SNDRV_INFO_CONTENT_TEXT;
entry->private_data = chip;
entry->mode = S_IFREG | S_IRUGO | S_IWUSR;
entry->mode = S_IFREG | 0644;
entry->c.text.read = cs46xx_dsp_proc_symbol_table_read;
if (snd_info_register(entry) < 0) {
snd_info_free_entry(entry);
@ -826,7 +826,7 @@ int cs46xx_dsp_proc_init (struct snd_card *card, struct snd_cs46xx *chip)
if ((entry = snd_info_create_card_entry(card, "spos_modules", ins->proc_dsp_dir)) != NULL) {
entry->content = SNDRV_INFO_CONTENT_TEXT;
entry->private_data = chip;
entry->mode = S_IFREG | S_IRUGO | S_IWUSR;
entry->mode = S_IFREG | 0644;
entry->c.text.read = cs46xx_dsp_proc_modules_read;
if (snd_info_register(entry) < 0) {
snd_info_free_entry(entry);
@ -838,7 +838,7 @@ int cs46xx_dsp_proc_init (struct snd_card *card, struct snd_cs46xx *chip)
if ((entry = snd_info_create_card_entry(card, "parameter", ins->proc_dsp_dir)) != NULL) {
entry->content = SNDRV_INFO_CONTENT_TEXT;
entry->private_data = chip;
entry->mode = S_IFREG | S_IRUGO | S_IWUSR;
entry->mode = S_IFREG | 0644;
entry->c.text.read = cs46xx_dsp_proc_parameter_dump_read;
if (snd_info_register(entry) < 0) {
snd_info_free_entry(entry);
@ -850,7 +850,7 @@ int cs46xx_dsp_proc_init (struct snd_card *card, struct snd_cs46xx *chip)
if ((entry = snd_info_create_card_entry(card, "sample", ins->proc_dsp_dir)) != NULL) {
entry->content = SNDRV_INFO_CONTENT_TEXT;
entry->private_data = chip;
entry->mode = S_IFREG | S_IRUGO | S_IWUSR;
entry->mode = S_IFREG | 0644;
entry->c.text.read = cs46xx_dsp_proc_sample_dump_read;
if (snd_info_register(entry) < 0) {
snd_info_free_entry(entry);
@ -862,7 +862,7 @@ int cs46xx_dsp_proc_init (struct snd_card *card, struct snd_cs46xx *chip)
if ((entry = snd_info_create_card_entry(card, "task_tree", ins->proc_dsp_dir)) != NULL) {
entry->content = SNDRV_INFO_CONTENT_TEXT;
entry->private_data = chip;
entry->mode = S_IFREG | S_IRUGO | S_IWUSR;
entry->mode = S_IFREG | 0644;
entry->c.text.read = cs46xx_dsp_proc_task_tree_read;
if (snd_info_register(entry) < 0) {
snd_info_free_entry(entry);
@ -874,7 +874,7 @@ int cs46xx_dsp_proc_init (struct snd_card *card, struct snd_cs46xx *chip)
if ((entry = snd_info_create_card_entry(card, "scb_info", ins->proc_dsp_dir)) != NULL) {
entry->content = SNDRV_INFO_CONTENT_TEXT;
entry->private_data = chip;
entry->mode = S_IFREG | S_IRUGO | S_IWUSR;
entry->mode = S_IFREG | 0644;
entry->c.text.read = cs46xx_dsp_proc_scb_read;
if (snd_info_register(entry) < 0) {
snd_info_free_entry(entry);

View file

@ -271,7 +271,7 @@ void cs46xx_dsp_proc_register_scb_desc (struct snd_cs46xx *chip,
entry->content = SNDRV_INFO_CONTENT_TEXT;
entry->private_data = scb_info;
entry->mode = S_IFREG | S_IRUGO | S_IWUSR;
entry->mode = S_IFREG | 0644;
entry->c.text.read = cs46xx_dsp_proc_scb_info_read;

View file

@ -17,7 +17,7 @@
static bool use_system_timer;
MODULE_PARM_DESC(use_system_timer, "Force to use system-timer");
module_param(use_system_timer, bool, S_IRUGO);
module_param(use_system_timer, bool, 0444);
struct ct_timer_ops {
void (*init)(struct ct_timer_instance *);

View file

@ -26,9 +26,9 @@ MODULE_SUPPORTED_DEVICE("{{Creative Labs, Sound Blaster X-Fi}");
static unsigned int reference_rate = 48000;
static unsigned int multiple = 2;
MODULE_PARM_DESC(reference_rate, "Reference rate (default=48000)");
module_param(reference_rate, uint, S_IRUGO);
module_param(reference_rate, uint, 0444);
MODULE_PARM_DESC(multiple, "Rate multiplier (default=2)");
module_param(multiple, uint, S_IRUGO);
module_param(multiple, uint, 0444);
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;

View file

@ -59,7 +59,7 @@ static int get_firmware(const struct firmware **fw_entry,
dev_dbg(chip->card->dev,
"firmware requested: %s\n", card_fw[fw_index].data);
snprintf(name, sizeof(name), "ea/%s", card_fw[fw_index].data);
err = request_firmware(fw_entry, name, pci_device(chip));
err = request_firmware(fw_entry, name, &chip->pci->dev);
if (err < 0)
dev_err(chip->card->dev,
"get_firmware(): Firmware not available (%d)\n", err);

View file

@ -559,10 +559,4 @@ static inline int monitor_index(const struct echoaudio *chip, int out, int in)
return out * num_busses_in(chip) + in;
}
#ifndef pci_device
#define pci_device(chip) (&chip->pci->dev)
#endif
#endif /* _ECHOAUDIO_H_ */

View file

@ -1070,7 +1070,7 @@ static int snd_emu10k1x_proc_init(struct emu10k1x *emu)
if(! snd_card_proc_new(emu->card, "emu10k1x_regs", &entry)) {
snd_info_set_text_ops(entry, emu, snd_emu10k1x_proc_reg_read);
entry->c.text.write = snd_emu10k1x_proc_reg_write;
entry->mode |= S_IWUSR;
entry->mode |= 0200;
entry->private_data = emu;
}

View file

@ -170,7 +170,7 @@ static char *audigy_outs[32] = {
/* 0x0f */ "Rear Right",
/* 0x10 */ "AC97 Front Left",
/* 0x11 */ "AC97 Front Right",
/* 0x12 */ "ADC Caputre Left",
/* 0x12 */ "ADC Capture Left",
/* 0x13 */ "ADC Capture Right",
/* 0x14 */ NULL,
/* 0x15 */ NULL,
@ -421,14 +421,10 @@ int snd_emu10k1_fx8010_register_irq_handler(struct snd_emu10k1 *emu,
snd_fx8010_irq_handler_t *handler,
unsigned char gpr_running,
void *private_data,
struct snd_emu10k1_fx8010_irq **r_irq)
struct snd_emu10k1_fx8010_irq *irq)
{
struct snd_emu10k1_fx8010_irq *irq;
unsigned long flags;
irq = kmalloc(sizeof(*irq), GFP_ATOMIC);
if (irq == NULL)
return -ENOMEM;
irq->handler = handler;
irq->gpr_running = gpr_running;
irq->private_data = private_data;
@ -443,8 +439,6 @@ int snd_emu10k1_fx8010_register_irq_handler(struct snd_emu10k1 *emu,
emu->fx8010.irq_handlers = irq;
}
spin_unlock_irqrestore(&emu->fx8010.irq_lock, flags);
if (r_irq)
*r_irq = irq;
return 0;
}
@ -468,7 +462,6 @@ int snd_emu10k1_fx8010_unregister_irq_handler(struct snd_emu10k1 *emu,
tmp->next = tmp->next->next;
}
spin_unlock_irqrestore(&emu->fx8010.irq_lock, flags);
kfree(irq);
return 0;
}

View file

@ -1724,7 +1724,7 @@ static int snd_emu10k1_fx8010_playback_trigger(struct snd_pcm_substream *substre
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
case SNDRV_PCM_TRIGGER_SUSPEND:
snd_emu10k1_fx8010_unregister_irq_handler(emu, pcm->irq); pcm->irq = NULL;
snd_emu10k1_fx8010_unregister_irq_handler(emu, &pcm->irq);
snd_emu10k1_ptr_write(emu, emu->gpr_base + pcm->gpr_trigger, 0, 0);
pcm->tram_pos = INITIAL_TRAM_POS(pcm->buffer_size);
pcm->tram_shift = 0;

View file

@ -135,7 +135,7 @@ static void snd_emu10k1_proc_read(struct snd_info_entry *entry,
/* 15 */ "Rear Right",
/* 16 */ "AC97 Front Left",
/* 17 */ "AC97 Front Right",
/* 18 */ "ADC Caputre Left",
/* 18 */ "ADC Capture Left",
/* 19 */ "ADC Capture Right",
/* 20 */ "???",
/* 21 */ "???",
@ -574,32 +574,32 @@ int snd_emu10k1_proc_init(struct snd_emu10k1 *emu)
if (! snd_card_proc_new(emu->card, "io_regs", &entry)) {
snd_info_set_text_ops(entry, emu, snd_emu_proc_io_reg_read);
entry->c.text.write = snd_emu_proc_io_reg_write;
entry->mode |= S_IWUSR;
entry->mode |= 0200;
}
if (! snd_card_proc_new(emu->card, "ptr_regs00a", &entry)) {
snd_info_set_text_ops(entry, emu, snd_emu_proc_ptr_reg_read00a);
entry->c.text.write = snd_emu_proc_ptr_reg_write00;
entry->mode |= S_IWUSR;
entry->mode |= 0200;
}
if (! snd_card_proc_new(emu->card, "ptr_regs00b", &entry)) {
snd_info_set_text_ops(entry, emu, snd_emu_proc_ptr_reg_read00b);
entry->c.text.write = snd_emu_proc_ptr_reg_write00;
entry->mode |= S_IWUSR;
entry->mode |= 0200;
}
if (! snd_card_proc_new(emu->card, "ptr_regs20a", &entry)) {
snd_info_set_text_ops(entry, emu, snd_emu_proc_ptr_reg_read20a);
entry->c.text.write = snd_emu_proc_ptr_reg_write20;
entry->mode |= S_IWUSR;
entry->mode |= 0200;
}
if (! snd_card_proc_new(emu->card, "ptr_regs20b", &entry)) {
snd_info_set_text_ops(entry, emu, snd_emu_proc_ptr_reg_read20b);
entry->c.text.write = snd_emu_proc_ptr_reg_write20;
entry->mode |= S_IWUSR;
entry->mode |= 0200;
}
if (! snd_card_proc_new(emu->card, "ptr_regs20c", &entry)) {
snd_info_set_text_ops(entry, emu, snd_emu_proc_ptr_reg_read20c);
entry->c.text.write = snd_emu_proc_ptr_reg_write20;
entry->mode |= S_IWUSR;
entry->mode |= 0200;
}
#endif
@ -621,35 +621,35 @@ int snd_emu10k1_proc_init(struct snd_emu10k1 *emu)
if (! snd_card_proc_new(emu->card, "fx8010_gpr", &entry)) {
entry->content = SNDRV_INFO_CONTENT_DATA;
entry->private_data = emu;
entry->mode = S_IFREG | S_IRUGO /*| S_IWUSR*/;
entry->mode = S_IFREG | 0444 /*| S_IWUSR*/;
entry->size = emu->audigy ? A_TOTAL_SIZE_GPR : TOTAL_SIZE_GPR;
entry->c.ops = &snd_emu10k1_proc_ops_fx8010;
}
if (! snd_card_proc_new(emu->card, "fx8010_tram_data", &entry)) {
entry->content = SNDRV_INFO_CONTENT_DATA;
entry->private_data = emu;
entry->mode = S_IFREG | S_IRUGO /*| S_IWUSR*/;
entry->mode = S_IFREG | 0444 /*| S_IWUSR*/;
entry->size = emu->audigy ? A_TOTAL_SIZE_TANKMEM_DATA : TOTAL_SIZE_TANKMEM_DATA ;
entry->c.ops = &snd_emu10k1_proc_ops_fx8010;
}
if (! snd_card_proc_new(emu->card, "fx8010_tram_addr", &entry)) {
entry->content = SNDRV_INFO_CONTENT_DATA;
entry->private_data = emu;
entry->mode = S_IFREG | S_IRUGO /*| S_IWUSR*/;
entry->mode = S_IFREG | 0444 /*| S_IWUSR*/;
entry->size = emu->audigy ? A_TOTAL_SIZE_TANKMEM_ADDR : TOTAL_SIZE_TANKMEM_ADDR ;
entry->c.ops = &snd_emu10k1_proc_ops_fx8010;
}
if (! snd_card_proc_new(emu->card, "fx8010_code", &entry)) {
entry->content = SNDRV_INFO_CONTENT_DATA;
entry->private_data = emu;
entry->mode = S_IFREG | S_IRUGO /*| S_IWUSR*/;
entry->mode = S_IFREG | 0444 /*| S_IWUSR*/;
entry->size = emu->audigy ? A_TOTAL_SIZE_CODE : TOTAL_SIZE_CODE;
entry->c.ops = &snd_emu10k1_proc_ops_fx8010;
}
if (! snd_card_proc_new(emu->card, "fx8010_acode", &entry)) {
entry->content = SNDRV_INFO_CONTENT_TEXT;
entry->private_data = emu;
entry->mode = S_IFREG | S_IRUGO /*| S_IWUSR*/;
entry->mode = S_IFREG | 0444 /*| S_IWUSR*/;
entry->c.text.read = snd_emu10k1_proc_acode_read;
}
return 0;

View file

@ -248,13 +248,13 @@ search_empty(struct snd_emu10k1 *emu, int size)
static int is_valid_page(struct snd_emu10k1 *emu, dma_addr_t addr)
{
if (addr & ~emu->dma_mask) {
dev_err(emu->card->dev,
dev_err_ratelimited(emu->card->dev,
"max memory size is 0x%lx (addr = 0x%lx)!!\n",
emu->dma_mask, (unsigned long)addr);
return 0;
}
if (addr & (EMUPAGESIZE-1)) {
dev_err(emu->card->dev, "page is not aligned\n");
dev_err_ratelimited(emu->card->dev, "page is not aligned\n");
return 0;
}
return 1;
@ -345,7 +345,7 @@ snd_emu10k1_alloc_pages(struct snd_emu10k1 *emu, struct snd_pcm_substream *subst
else
addr = snd_pcm_sgbuf_get_addr(substream, ofs);
if (! is_valid_page(emu, addr)) {
dev_err(emu->card->dev,
dev_err_ratelimited(emu->card->dev,
"emu: failure page = %d\n", idx);
mutex_unlock(&hdr->block_mutex);
return NULL;

View file

@ -127,11 +127,15 @@ comment "Set to Y if you want auto-loading the codec driver"
config SND_HDA_CODEC_HDMI
tristate "Build HDMI/DisplayPort HD-audio codec support"
select SND_DYNAMIC_MINORS
help
Say Y or M here to include HDMI and DisplayPort HD-audio codec
support in snd-hda-intel driver. This includes all AMD/ATI,
Intel and Nvidia HDMI/DisplayPort codecs.
Note that this option mandatorily enables CONFIG_SND_DYNAMIC_MINORS
to assure the multiple streams for DP-MST support.
comment "Set to Y if you want auto-loading the codec driver"
depends on SND_HDA=y && SND_HDA_CODEC_HDMI=m

View file

@ -793,11 +793,11 @@ EXPORT_SYMBOL_GPL(snd_hda_add_verbs);
*/
void snd_hda_apply_verbs(struct hda_codec *codec)
{
const struct hda_verb **v;
int i;
for (i = 0; i < codec->verbs.used; i++) {
struct hda_verb **v = snd_array_elem(&codec->verbs, i);
snd_array_for_each(&codec->verbs, i, v)
snd_hda_sequence_write(codec, *v);
}
}
EXPORT_SYMBOL_GPL(snd_hda_apply_verbs);
@ -890,10 +890,10 @@ EXPORT_SYMBOL_GPL(snd_hda_apply_fixup);
static bool pin_config_match(struct hda_codec *codec,
const struct hda_pintbl *pins)
{
const struct hda_pincfg *pin;
int i;
for (i = 0; i < codec->init_pins.used; i++) {
struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
snd_array_for_each(&codec->init_pins, i, pin) {
hda_nid_t nid = pin->nid;
u32 cfg = pin->cfg;
const struct hda_pintbl *t_pins;

View file

@ -481,9 +481,10 @@ static struct hda_pincfg *look_up_pincfg(struct hda_codec *codec,
struct snd_array *array,
hda_nid_t nid)
{
struct hda_pincfg *pin;
int i;
for (i = 0; i < array->used; i++) {
struct hda_pincfg *pin = snd_array_elem(array, i);
snd_array_for_each(array, i, pin) {
if (pin->nid == nid)
return pin;
}
@ -618,14 +619,15 @@ EXPORT_SYMBOL_GPL(snd_hda_codec_get_pin_target);
*/
void snd_hda_shutup_pins(struct hda_codec *codec)
{
const struct hda_pincfg *pin;
int i;
/* don't shut up pins when unloading the driver; otherwise it breaks
* the default pin setup at the next load of the driver
*/
if (codec->bus->shutdown)
return;
for (i = 0; i < codec->init_pins.used; i++) {
struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
snd_array_for_each(&codec->init_pins, i, pin) {
/* use read here for syncing after issuing each verb */
snd_hda_codec_read(codec, pin->nid, 0,
AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
@ -638,13 +640,14 @@ EXPORT_SYMBOL_GPL(snd_hda_shutup_pins);
/* Restore the pin controls cleared previously via snd_hda_shutup_pins() */
static void restore_shutup_pins(struct hda_codec *codec)
{
const struct hda_pincfg *pin;
int i;
if (!codec->pins_shutup)
return;
if (codec->bus->shutdown)
return;
for (i = 0; i < codec->init_pins.used; i++) {
struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
snd_array_for_each(&codec->init_pins, i, pin) {
snd_hda_codec_write(codec, pin->nid, 0,
AC_VERB_SET_PIN_WIDGET_CONTROL,
pin->ctrl);
@ -697,8 +700,7 @@ get_hda_cvt_setup(struct hda_codec *codec, hda_nid_t nid)
struct hda_cvt_setup *p;
int i;
for (i = 0; i < codec->cvt_setups.used; i++) {
p = snd_array_elem(&codec->cvt_setups, i);
snd_array_for_each(&codec->cvt_setups, i, p) {
if (p->nid == nid)
return p;
}
@ -1076,8 +1078,7 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
/* make other inactive cvts with the same stream-tag dirty */
type = get_wcaps_type(get_wcaps(codec, nid));
list_for_each_codec(c, codec->bus) {
for (i = 0; i < c->cvt_setups.used; i++) {
p = snd_array_elem(&c->cvt_setups, i);
snd_array_for_each(&c->cvt_setups, i, p) {
if (!p->active && p->stream_tag == stream_tag &&
get_wcaps_type(get_wcaps(c, p->nid)) == type)
p->dirty = 1;
@ -1140,12 +1141,11 @@ static void really_cleanup_stream(struct hda_codec *codec,
static void purify_inactive_streams(struct hda_codec *codec)
{
struct hda_codec *c;
struct hda_cvt_setup *p;
int i;
list_for_each_codec(c, codec->bus) {
for (i = 0; i < c->cvt_setups.used; i++) {
struct hda_cvt_setup *p;
p = snd_array_elem(&c->cvt_setups, i);
snd_array_for_each(&c->cvt_setups, i, p) {
if (p->dirty)
really_cleanup_stream(c, p);
}
@ -1156,10 +1156,10 @@ static void purify_inactive_streams(struct hda_codec *codec)
/* clean up all streams; called from suspend */
static void hda_cleanup_all_streams(struct hda_codec *codec)
{
struct hda_cvt_setup *p;
int i;
for (i = 0; i < codec->cvt_setups.used; i++) {
struct hda_cvt_setup *p = snd_array_elem(&codec->cvt_setups, i);
snd_array_for_each(&codec->cvt_setups, i, p) {
if (p->stream_tag)
really_cleanup_stream(codec, p);
}
@ -1493,10 +1493,10 @@ static void get_ctl_amp_tlv(struct snd_kcontrol *kcontrol, unsigned int *tlv)
val1 = ((int)val1) * ((int)val2);
if (min_mute || (caps & AC_AMPCAP_MIN_MUTE))
val2 |= TLV_DB_SCALE_MUTE;
tlv[0] = SNDRV_CTL_TLVT_DB_SCALE;
tlv[1] = 2 * sizeof(unsigned int);
tlv[2] = val1;
tlv[3] = val2;
tlv[SNDRV_CTL_TLVO_TYPE] = SNDRV_CTL_TLVT_DB_SCALE;
tlv[SNDRV_CTL_TLVO_LEN] = 2 * sizeof(unsigned int);
tlv[SNDRV_CTL_TLVO_DB_SCALE_MIN] = val1;
tlv[SNDRV_CTL_TLVO_DB_SCALE_MUTE_AND_STEP] = val2;
}
/**
@ -1544,10 +1544,10 @@ void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir,
nums = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
step = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT;
step = (step + 1) * 25;
tlv[0] = SNDRV_CTL_TLVT_DB_SCALE;
tlv[1] = 2 * sizeof(unsigned int);
tlv[2] = -nums * step;
tlv[3] = step;
tlv[SNDRV_CTL_TLVO_TYPE] = SNDRV_CTL_TLVT_DB_SCALE;
tlv[SNDRV_CTL_TLVO_LEN] = 2 * sizeof(unsigned int);
tlv[SNDRV_CTL_TLVO_DB_SCALE_MIN] = -nums * step;
tlv[SNDRV_CTL_TLVO_DB_SCALE_MUTE_AND_STEP] = step;
}
EXPORT_SYMBOL_GPL(snd_hda_set_vmaster_tlv);
@ -1845,10 +1845,10 @@ static int init_slave_0dB(struct snd_kcontrol *slave,
} else if (kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_READ)
tlv = kctl->tlv.p;
if (!tlv || tlv[0] != SNDRV_CTL_TLVT_DB_SCALE)
if (!tlv || tlv[SNDRV_CTL_TLVO_TYPE] != SNDRV_CTL_TLVT_DB_SCALE)
return 0;
step = tlv[3];
step = tlv[SNDRV_CTL_TLVO_DB_SCALE_MUTE_AND_STEP];
step &= ~TLV_DB_SCALE_MUTE;
if (!step)
return 0;
@ -1860,7 +1860,7 @@ static int init_slave_0dB(struct snd_kcontrol *slave,
}
arg->step = step;
val = -tlv[2] / step;
val = -tlv[SNDRV_CTL_TLVO_DB_SCALE_MIN] / step;
if (val > 0) {
put_kctl_with_value(slave, val);
return val;
@ -2175,6 +2175,8 @@ static int snd_hda_spdif_default_get(struct snd_kcontrol *kcontrol,
int idx = kcontrol->private_value;
struct hda_spdif_out *spdif;
if (WARN_ON(codec->spdif_out.used <= idx))
return -EINVAL;
mutex_lock(&codec->spdif_mutex);
spdif = snd_array_elem(&codec->spdif_out, idx);
ucontrol->value.iec958.status[0] = spdif->status & 0xff;
@ -2282,6 +2284,8 @@ static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol,
unsigned short val;
int change;
if (WARN_ON(codec->spdif_out.used <= idx))
return -EINVAL;
mutex_lock(&codec->spdif_mutex);
spdif = snd_array_elem(&codec->spdif_out, idx);
nid = spdif->nid;
@ -2308,6 +2312,8 @@ static int snd_hda_spdif_out_switch_get(struct snd_kcontrol *kcontrol,
int idx = kcontrol->private_value;
struct hda_spdif_out *spdif;
if (WARN_ON(codec->spdif_out.used <= idx))
return -EINVAL;
mutex_lock(&codec->spdif_mutex);
spdif = snd_array_elem(&codec->spdif_out, idx);
ucontrol->value.integer.value[0] = spdif->ctls & AC_DIG1_ENABLE;
@ -2336,6 +2342,8 @@ static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol,
unsigned short val;
int change;
if (WARN_ON(codec->spdif_out.used <= idx))
return -EINVAL;
mutex_lock(&codec->spdif_mutex);
spdif = snd_array_elem(&codec->spdif_out, idx);
nid = spdif->nid;
@ -2461,10 +2469,10 @@ EXPORT_SYMBOL_GPL(snd_hda_create_dig_out_ctls);
struct hda_spdif_out *snd_hda_spdif_out_of_nid(struct hda_codec *codec,
hda_nid_t nid)
{
struct hda_spdif_out *spdif;
int i;
for (i = 0; i < codec->spdif_out.used; i++) {
struct hda_spdif_out *spdif =
snd_array_elem(&codec->spdif_out, i);
snd_array_for_each(&codec->spdif_out, i, spdif) {
if (spdif->nid == nid)
return spdif;
}
@ -2483,6 +2491,8 @@ void snd_hda_spdif_ctls_unassign(struct hda_codec *codec, int idx)
{
struct hda_spdif_out *spdif;
if (WARN_ON(codec->spdif_out.used <= idx))
return;
mutex_lock(&codec->spdif_mutex);
spdif = snd_array_elem(&codec->spdif_out, idx);
spdif->nid = (u16)-1;
@ -2503,6 +2513,8 @@ void snd_hda_spdif_ctls_assign(struct hda_codec *codec, int idx, hda_nid_t nid)
struct hda_spdif_out *spdif;
unsigned short val;
if (WARN_ON(codec->spdif_out.used <= idx))
return;
mutex_lock(&codec->spdif_mutex);
spdif = snd_array_elem(&codec->spdif_out, idx);
if (spdif->nid != nid) {

View file

@ -748,8 +748,10 @@ int snd_hda_attach_pcm_stream(struct hda_bus *_bus, struct hda_codec *codec,
return err;
strlcpy(pcm->name, cpcm->name, sizeof(pcm->name));
apcm = kzalloc(sizeof(*apcm), GFP_KERNEL);
if (apcm == NULL)
if (apcm == NULL) {
snd_device_free(chip->card, pcm);
return -ENOMEM;
}
apcm->chip = chip;
apcm->pcm = pcm;
apcm->codec = codec;

View file

@ -264,10 +264,10 @@ static struct nid_path *get_nid_path(struct hda_codec *codec,
int anchor_nid)
{
struct hda_gen_spec *spec = codec->spec;
struct nid_path *path;
int i;
for (i = 0; i < spec->paths.used; i++) {
struct nid_path *path = snd_array_elem(&spec->paths, i);
snd_array_for_each(&spec->paths, i, path) {
if (path->depth <= 0)
continue;
if ((!from_nid || path->path[0] == from_nid) &&
@ -325,10 +325,10 @@ EXPORT_SYMBOL_GPL(snd_hda_get_path_from_idx);
static bool is_dac_already_used(struct hda_codec *codec, hda_nid_t nid)
{
struct hda_gen_spec *spec = codec->spec;
const struct nid_path *path;
int i;
for (i = 0; i < spec->paths.used; i++) {
struct nid_path *path = snd_array_elem(&spec->paths, i);
snd_array_for_each(&spec->paths, i, path) {
if (path->path[0] == nid)
return true;
}
@ -351,11 +351,11 @@ static bool is_reachable_path(struct hda_codec *codec,
static bool is_ctl_used(struct hda_codec *codec, unsigned int val, int type)
{
struct hda_gen_spec *spec = codec->spec;
const struct nid_path *path;
int i;
val &= AMP_VAL_COMPARE_MASK;
for (i = 0; i < spec->paths.used; i++) {
struct nid_path *path = snd_array_elem(&spec->paths, i);
snd_array_for_each(&spec->paths, i, path) {
if ((path->ctls[type] & AMP_VAL_COMPARE_MASK) == val)
return true;
}
@ -638,13 +638,13 @@ static bool is_active_nid(struct hda_codec *codec, hda_nid_t nid,
{
struct hda_gen_spec *spec = codec->spec;
int type = get_wcaps_type(get_wcaps(codec, nid));
const struct nid_path *path;
int i, n;
if (nid == codec->core.afg)
return true;
for (n = 0; n < spec->paths.used; n++) {
struct nid_path *path = snd_array_elem(&spec->paths, n);
snd_array_for_each(&spec->paths, n, path) {
if (!path->active)
continue;
if (codec->power_save_node) {
@ -2065,7 +2065,7 @@ static int parse_output_paths(struct hda_codec *codec)
snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
HDA_OUTPUT, spec->vmaster_tlv);
if (spec->dac_min_mute)
spec->vmaster_tlv[3] |= TLV_DB_SCALE_MUTE;
spec->vmaster_tlv[SNDRV_CTL_TLVO_DB_SCALE_MUTE_AND_STEP] |= TLV_DB_SCALE_MUTE;
}
}
@ -2696,10 +2696,10 @@ static const struct snd_kcontrol_new out_jack_mode_enum = {
static bool find_kctl_name(struct hda_codec *codec, const char *name, int idx)
{
struct hda_gen_spec *spec = codec->spec;
const struct snd_kcontrol_new *kctl;
int i;
for (i = 0; i < spec->kctls.used; i++) {
struct snd_kcontrol_new *kctl = snd_array_elem(&spec->kctls, i);
snd_array_for_each(&spec->kctls, i, kctl) {
if (!strcmp(kctl->name, name) && kctl->index == idx)
return true;
}
@ -4021,8 +4021,7 @@ static hda_nid_t set_path_power(struct hda_codec *codec, hda_nid_t nid,
struct nid_path *path;
int n;
for (n = 0; n < spec->paths.used; n++) {
path = snd_array_elem(&spec->paths, n);
snd_array_for_each(&spec->paths, n, path) {
if (!path->depth)
continue;
if (path->path[0] == nid ||
@ -5831,10 +5830,10 @@ static void init_digital(struct hda_codec *codec)
*/
static void clear_unsol_on_unused_pins(struct hda_codec *codec)
{
const struct hda_pincfg *pin;
int i;
for (i = 0; i < codec->init_pins.used; i++) {
struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
snd_array_for_each(&codec->init_pins, i, pin) {
hda_nid_t nid = pin->nid;
if (is_jack_detectable(codec, nid) &&
!snd_hda_jack_tbl_get(codec, nid))

View file

@ -2209,7 +2209,18 @@ static struct snd_pci_quirk power_save_blacklist[] = {
/* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */
SND_PCI_QUIRK(0x1849, 0x0c0c, "Asrock B85M-ITX", 0),
/* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */
SND_PCI_QUIRK(0x1849, 0x7662, "Asrock H81M-HDS", 0),
/* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */
SND_PCI_QUIRK(0x1043, 0x8733, "Asus Prime X370-Pro", 0),
/* https://bugzilla.redhat.com/show_bug.cgi?id=1581607 */
SND_PCI_QUIRK(0x1558, 0x3501, "Clevo W35xSS_370SS", 0),
/* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */
/* Note the P55A-UD3 and Z87-D3HP share the subsys id for the HDA dev */
SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte P55A-UD3 / Z87-D3HP", 0),
/* https://bugzilla.kernel.org/show_bug.cgi?id=199607 */
SND_PCI_QUIRK(0x8086, 0x2057, "Intel NUC5i7RYB", 0),
/* https://bugzilla.redhat.com/show_bug.cgi?id=1520902 */
SND_PCI_QUIRK(0x8086, 0x2068, "Intel NUC7i3BNB", 0),
/* https://bugzilla.redhat.com/show_bug.cgi?id=1572975 */
SND_PCI_QUIRK(0x17aa, 0x36a7, "Lenovo C50 All in one", 0),
/* https://bugzilla.kernel.org/show_bug.cgi?id=198611 */

View file

@ -80,10 +80,10 @@ static ssize_t pin_configs_show(struct hda_codec *codec,
struct snd_array *list,
char *buf)
{
const struct hda_pincfg *pin;
int i, len = 0;
mutex_lock(&codec->user_mutex);
for (i = 0; i < list->used; i++) {
struct hda_pincfg *pin = snd_array_elem(list, i);
snd_array_for_each(list, i, pin) {
len += sprintf(buf + len, "0x%02x 0x%08x\n",
pin->nid, pin->cfg);
}
@ -217,10 +217,10 @@ static ssize_t init_verbs_show(struct device *dev,
char *buf)
{
struct hda_codec *codec = dev_get_drvdata(dev);
const struct hda_verb *v;
int i, len = 0;
mutex_lock(&codec->user_mutex);
for (i = 0; i < codec->init_verbs.used; i++) {
struct hda_verb *v = snd_array_elem(&codec->init_verbs, i);
snd_array_for_each(&codec->init_verbs, i, v) {
len += snprintf(buf + len, PAGE_SIZE - len,
"0x%02x 0x%03x 0x%04x\n",
v->nid, v->verb, v->param);
@ -267,10 +267,10 @@ static ssize_t hints_show(struct device *dev,
char *buf)
{
struct hda_codec *codec = dev_get_drvdata(dev);
const struct hda_hint *hint;
int i, len = 0;
mutex_lock(&codec->user_mutex);
for (i = 0; i < codec->hints.used; i++) {
struct hda_hint *hint = snd_array_elem(&codec->hints, i);
snd_array_for_each(&codec->hints, i, hint) {
len += snprintf(buf + len, PAGE_SIZE - len,
"%s = %s\n", hint->key, hint->val);
}
@ -280,10 +280,10 @@ static ssize_t hints_show(struct device *dev,
static struct hda_hint *get_hint(struct hda_codec *codec, const char *key)
{
struct hda_hint *hint;
int i;
for (i = 0; i < codec->hints.used; i++) {
struct hda_hint *hint = snd_array_elem(&codec->hints, i);
snd_array_for_each(&codec->hints, i, hint) {
if (!strcmp(hint->key, key))
return hint;
}
@ -783,13 +783,13 @@ void snd_hda_sysfs_init(struct hda_codec *codec)
void snd_hda_sysfs_clear(struct hda_codec *codec)
{
#ifdef CONFIG_SND_HDA_RECONFIG
struct hda_hint *hint;
int i;
/* clear init verbs */
snd_array_free(&codec->init_verbs);
/* clear hints */
for (i = 0; i < codec->hints.used; i++) {
struct hda_hint *hint = snd_array_elem(&codec->hints, i);
snd_array_for_each(&codec->hints, i, hint) {
kfree(hint->key); /* we don't need to free hint->val */
}
snd_array_free(&codec->hints);

View file

@ -0,0 +1,95 @@
// SPDX-License-Identifier: GPL-2.0
/* Fixes for HP X360 laptops with top B&O speakers
* to be included from codec driver
*/
static void alc295_fixup_hp_top_speakers(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
static const struct hda_pintbl pincfgs[] = {
{ 0x17, 0x90170110 },
{ }
};
static const struct coef_fw alc295_hp_speakers_coefs[] = {
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0000), WRITE_COEF(0x28, 0x0000), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x003f), WRITE_COEF(0x28, 0x1000), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0004), WRITE_COEF(0x28, 0x0600), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x006a), WRITE_COEF(0x28, 0x0006), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x006c), WRITE_COEF(0x28, 0xc0c0), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0008), WRITE_COEF(0x28, 0xb000), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x002e), WRITE_COEF(0x28, 0x0800), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x006a), WRITE_COEF(0x28, 0x00c1), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x006c), WRITE_COEF(0x28, 0x0320), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0039), WRITE_COEF(0x28, 0x0000), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x003b), WRITE_COEF(0x28, 0xffff), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x003c), WRITE_COEF(0x28, 0xffd0), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x003a), WRITE_COEF(0x28, 0x1dfe), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0080), WRITE_COEF(0x28, 0x0880), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x003a), WRITE_COEF(0x28, 0x0dfe), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0018), WRITE_COEF(0x28, 0x0219), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x006a), WRITE_COEF(0x28, 0x005d), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x006c), WRITE_COEF(0x28, 0x9142), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x00c0), WRITE_COEF(0x28, 0x01ce), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x00c1), WRITE_COEF(0x28, 0xed0c), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x00c2), WRITE_COEF(0x28, 0x1c00), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x00c3), WRITE_COEF(0x28, 0x0000), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x00c4), WRITE_COEF(0x28, 0x0200), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x00c5), WRITE_COEF(0x28, 0x0000), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x00c6), WRITE_COEF(0x28, 0x0399), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x00c7), WRITE_COEF(0x28, 0x2330), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x00c8), WRITE_COEF(0x28, 0x1e5d), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x00c9), WRITE_COEF(0x28, 0x6eff), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x00ca), WRITE_COEF(0x28, 0x01c0), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x00cb), WRITE_COEF(0x28, 0xed0c), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x00cc), WRITE_COEF(0x28, 0x1c00), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x00cd), WRITE_COEF(0x28, 0x0000), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x00ce), WRITE_COEF(0x28, 0x0200), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x00cf), WRITE_COEF(0x28, 0x0000), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x00d0), WRITE_COEF(0x28, 0x0399), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x00d1), WRITE_COEF(0x28, 0x2330), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x00d2), WRITE_COEF(0x28, 0x1e5d), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x00d3), WRITE_COEF(0x28, 0x6eff), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0062), WRITE_COEF(0x28, 0x8000), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0063), WRITE_COEF(0x28, 0x5f5f), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0064), WRITE_COEF(0x28, 0x1000), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0065), WRITE_COEF(0x28, 0x0000), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0066), WRITE_COEF(0x28, 0x4004), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0067), WRITE_COEF(0x28, 0x0802), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0068), WRITE_COEF(0x28, 0x890f), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0069), WRITE_COEF(0x28, 0xe021), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0070), WRITE_COEF(0x28, 0x8012), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0071), WRITE_COEF(0x28, 0x3450), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0072), WRITE_COEF(0x28, 0x0123), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0073), WRITE_COEF(0x28, 0x4543), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0074), WRITE_COEF(0x28, 0x2100), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0075), WRITE_COEF(0x28, 0x4321), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0076), WRITE_COEF(0x28, 0x0000), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0050), WRITE_COEF(0x28, 0x8200), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x003a), WRITE_COEF(0x28, 0x1dfe), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0051), WRITE_COEF(0x28, 0x0707), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0052), WRITE_COEF(0x28, 0x4090), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x006a), WRITE_COEF(0x28, 0x0090), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x006c), WRITE_COEF(0x28, 0x721f), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0012), WRITE_COEF(0x28, 0xebeb), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x009e), WRITE_COEF(0x28, 0x0000), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0060), WRITE_COEF(0x28, 0x2213), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x006a), WRITE_COEF(0x28, 0x0006), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x006c), WRITE_COEF(0x28, 0x0000), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x003f), WRITE_COEF(0x28, 0x3000), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0004), WRITE_COEF(0x28, 0x0500), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0040), WRITE_COEF(0x28, 0x800c), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0046), WRITE_COEF(0x28, 0xc22e), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x004b), WRITE_COEF(0x28, 0x0000), WRITE_COEF(0x29, 0xb024),
WRITE_COEF(0x24, 0x0012), WRITE_COEF(0x26, 0x0050), WRITE_COEF(0x28, 0x82ec), WRITE_COEF(0x29, 0xb024),
};
switch (action) {
case HDA_FIXUP_ACT_PRE_PROBE:
snd_hda_apply_pincfgs(codec, pincfgs);
alc295_fixup_disable_dac3(codec, fix, action);
break;
case HDA_FIXUP_ACT_INIT:
alc_process_coef_fw(codec, alc295_hp_speakers_coefs);
break;
}
}

View file

@ -1,40 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
*/
#ifndef __HDAC_LOCAL_H
#define __HDAC_LOCAL_H
int hdac_read_parm(struct hdac_device *codec, hda_nid_t nid, int parm);
#define get_wcaps(codec, nid) \
hdac_read_parm(codec, nid, AC_PAR_AUDIO_WIDGET_CAP)
/* get the widget type from widget capability bits */
static inline int get_wcaps_type(unsigned int wcaps)
{
if (!wcaps)
return -1; /* invalid type */
return (wcaps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
}
#define get_pin_caps(codec, nid) \
hdac_read_parm(codec, nid, AC_PAR_PIN_CAP)
static inline
unsigned int get_pin_cfg(struct hdac_device *codec, hda_nid_t nid)
{
unsigned int val;
if (snd_hdac_read(codec, nid, AC_VERB_GET_CONFIG_DEFAULT, 0, &val))
return -1;
return val;
}
#define get_amp_caps(codec, nid, dir) \
hdac_read_parm(codec, nid, (dir) == HDA_OUTPUT ? \
AC_PAR_AMP_OUT_CAP : AC_PAR_AMP_IN_CAP)
#define get_power_caps(codec, nid) \
hdac_read_parm(codec, nid, AC_PAR_POWER_STATE)
#endif /* __HDAC_LOCAL_H */

File diff suppressed because it is too large Load diff

View file

@ -588,6 +588,7 @@ static void cxt_fixup_olpc_xo(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
struct conexant_spec *spec = codec->spec;
struct snd_kcontrol_new *kctl;
int i;
if (action != HDA_FIXUP_ACT_PROBE)
@ -606,9 +607,7 @@ static void cxt_fixup_olpc_xo(struct hda_codec *codec,
snd_hda_codec_set_pin_target(codec, 0x1a, PIN_VREF50);
/* override mic boost control */
for (i = 0; i < spec->gen.kctls.used; i++) {
struct snd_kcontrol_new *kctl =
snd_array_elem(&spec->gen.kctls, i);
snd_array_for_each(&spec->gen.kctls, i, kctl) {
if (!strcmp(kctl->name, "Mic Boost Volume")) {
kctl->put = olpc_xo_mic_boost_put;
break;
@ -965,6 +964,7 @@ static const struct snd_pci_quirk cxt5066_fixups[] = {
SND_PCI_QUIRK(0x103c, 0x822e, "HP ProBook 440 G4", CXT_FIXUP_MUTE_LED_GPIO),
SND_PCI_QUIRK(0x103c, 0x8299, "HP 800 G3 SFF", CXT_FIXUP_HP_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x103c, 0x829a, "HP 800 G3 DM", CXT_FIXUP_HP_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x103c, 0x8455, "HP Z2 G4", CXT_FIXUP_HP_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1043, 0x138d, "Asus", CXT_FIXUP_HEADPHONE_MIC_PIN),
SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT_FIXUP_OLPC_XO),
SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400", CXT_PINCFG_LENOVO_TP410),
@ -998,6 +998,7 @@ static const struct hda_model_fixup cxt5066_fixup_models[] = {
{ .id = CXT_FIXUP_MUTE_LED_EAPD, .name = "mute-led-eapd" },
{ .id = CXT_FIXUP_HP_DOCK, .name = "hp-dock" },
{ .id = CXT_FIXUP_MUTE_LED_GPIO, .name = "mute-led-gpio" },
{ .id = CXT_FIXUP_HP_MIC_NO_PRESENCE, .name = "hp-mic-fix" },
{}
};

View file

@ -510,7 +510,7 @@ static int eld_proc_new(struct hdmi_spec_per_pin *per_pin, int index)
snd_info_set_text_ops(entry, per_pin, print_eld_info);
entry->c.text.write = write_eld_info;
entry->mode |= S_IWUSR;
entry->mode |= 0200;
per_pin->proc_entry = entry;
return 0;

View file

@ -2830,6 +2830,7 @@ static int find_ext_mic_pin(struct hda_codec *codec);
static void alc286_shutup(struct hda_codec *codec)
{
const struct hda_pincfg *pin;
int i;
int mic_pin = find_ext_mic_pin(codec);
/* don't shut up pins when unloading the driver; otherwise it breaks
@ -2837,8 +2838,7 @@ static void alc286_shutup(struct hda_codec *codec)
*/
if (codec->bus->shutdown)
return;
for (i = 0; i < codec->init_pins.used; i++) {
struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
snd_array_for_each(&codec->init_pins, i, pin) {
/* use read here for syncing after issuing each verb */
if (pin->nid != mic_pin)
snd_hda_codec_read(codec, pin->nid, 0,
@ -3653,30 +3653,37 @@ static void alc269_fixup_hp_mute_led(struct hda_codec *codec,
}
}
static void alc269_fixup_hp_mute_led_mic1(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
static void alc269_fixup_hp_mute_led_micx(struct hda_codec *codec,
const struct hda_fixup *fix,
int action, hda_nid_t pin)
{
struct alc_spec *spec = codec->spec;
if (action == HDA_FIXUP_ACT_PRE_PROBE) {
spec->mute_led_polarity = 0;
spec->mute_led_nid = 0x18;
spec->mute_led_nid = pin;
spec->gen.vmaster_mute.hook = alc269_fixup_mic_mute_hook;
spec->gen.vmaster_mute_enum = 1;
codec->power_filter = led_power_filter;
}
}
static void alc269_fixup_hp_mute_led_mic1(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
alc269_fixup_hp_mute_led_micx(codec, fix, action, 0x18);
}
static void alc269_fixup_hp_mute_led_mic2(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
struct alc_spec *spec = codec->spec;
if (action == HDA_FIXUP_ACT_PRE_PROBE) {
spec->mute_led_polarity = 0;
spec->mute_led_nid = 0x19;
spec->gen.vmaster_mute.hook = alc269_fixup_mic_mute_hook;
spec->gen.vmaster_mute_enum = 1;
codec->power_filter = led_power_filter;
}
alc269_fixup_hp_mute_led_micx(codec, fix, action, 0x19);
}
static void alc269_fixup_hp_mute_led_mic3(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
alc269_fixup_hp_mute_led_micx(codec, fix, action, 0x1b);
}
/* update LED status via GPIO */
@ -5387,6 +5394,9 @@ static void alc274_fixup_bind_dacs(struct hda_codec *codec,
/* for dell wmi mic mute led */
#include "dell_wmi_helper.c"
/* for alc295_fixup_hp_top_speakers */
#include "hp_x360_helper.c"
enum {
ALC269_FIXUP_SONY_VAIO,
ALC275_FIXUP_SONY_VAIO_GPIO2,
@ -5413,6 +5423,7 @@ enum {
ALC269_FIXUP_HP_MUTE_LED,
ALC269_FIXUP_HP_MUTE_LED_MIC1,
ALC269_FIXUP_HP_MUTE_LED_MIC2,
ALC269_FIXUP_HP_MUTE_LED_MIC3,
ALC269_FIXUP_HP_GPIO_LED,
ALC269_FIXUP_HP_GPIO_MIC1_LED,
ALC269_FIXUP_HP_LINE1_MIC1_LED,
@ -5506,6 +5517,7 @@ enum {
ALC298_FIXUP_TPT470_DOCK,
ALC255_FIXUP_DUMMY_LINEOUT_VERB,
ALC255_FIXUP_DELL_HEADSET_MIC,
ALC295_FIXUP_HP_X360,
};
static const struct hda_fixup alc269_fixups[] = {
@ -5672,6 +5684,10 @@ static const struct hda_fixup alc269_fixups[] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc269_fixup_hp_mute_led_mic2,
},
[ALC269_FIXUP_HP_MUTE_LED_MIC3] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc269_fixup_hp_mute_led_mic3,
},
[ALC269_FIXUP_HP_GPIO_LED] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc269_fixup_hp_gpio_led,
@ -6375,6 +6391,12 @@ static const struct hda_fixup alc269_fixups[] = {
.chained = true,
.chain_id = ALC269_FIXUP_HEADSET_MIC
},
[ALC295_FIXUP_HP_X360] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc295_fixup_hp_top_speakers,
.chained = true,
.chain_id = ALC269_FIXUP_HP_MUTE_LED_MIC3
}
};
static const struct snd_pci_quirk alc269_fixup_tbl[] = {
@ -6494,6 +6516,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x2337, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
SND_PCI_QUIRK(0x103c, 0x221c, "HP EliteBook 755 G2", ALC280_FIXUP_HP_HEADSET_MIC),
SND_PCI_QUIRK(0x103c, 0x8256, "HP", ALC221_FIXUP_HP_FRONT_MIC),
SND_PCI_QUIRK(0x103c, 0x827e, "HP x360", ALC295_FIXUP_HP_X360),
SND_PCI_QUIRK(0x103c, 0x82bf, "HP", ALC221_FIXUP_HP_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x103c, 0x82c0, "HP", ALC221_FIXUP_HP_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1043, 0x103e, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC),
@ -6580,7 +6603,6 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x17aa, 0x312f, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION),
SND_PCI_QUIRK(0x17aa, 0x3138, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION),
SND_PCI_QUIRK(0x17aa, 0x313c, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION),
SND_PCI_QUIRK(0x17aa, 0x3112, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY),
SND_PCI_QUIRK(0x17aa, 0x3902, "Lenovo E50-80", ALC269_FIXUP_DMIC_THINKPAD_ACPI),
SND_PCI_QUIRK(0x17aa, 0x3977, "IdeaPad S210", ALC283_FIXUP_INT_MIC),
SND_PCI_QUIRK(0x17aa, 0x3978, "IdeaPad Y410P", ALC269_FIXUP_NO_SHUTUP),
@ -6752,6 +6774,11 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
{0x1b, 0x01111010},
{0x1e, 0x01451130},
{0x21, 0x02211020}),
SND_HDA_PIN_QUIRK(0x10ec0235, 0x17aa, "Lenovo", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY,
{0x12, 0x90a60140},
{0x14, 0x90170110},
{0x19, 0x02a11030},
{0x21, 0x02211020}),
SND_HDA_PIN_QUIRK(0x10ec0236, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
{0x12, 0x90a60140},
{0x14, 0x90170110},

View file

@ -662,7 +662,7 @@ static void wm_proc_init(struct snd_ice1712 *ice)
struct snd_info_entry *entry;
if (! snd_card_proc_new(ice->card, "wm_codec", &entry)) {
snd_info_set_text_ops(entry, ice, wm_proc_regs_read);
entry->mode |= S_IWUSR;
entry->mode |= 0200;
entry->c.text.write = wm_proc_regs_write;
}
}

View file

@ -926,7 +926,7 @@ static void wm_proc_init(struct snd_ice1712 *ice)
struct snd_info_entry *entry;
if (!snd_card_proc_new(ice->card, "wm_codec", &entry)) {
snd_info_set_text_ops(entry, ice, wm_proc_regs_read);
entry->mode |= S_IWUSR;
entry->mode |= 0200;
entry->c.text.write = wm_proc_regs_write;
}
}

View file

@ -214,7 +214,7 @@ void lola_proc_debug_new(struct lola *chip)
snd_info_set_text_ops(entry, chip, lola_proc_codec_read);
if (!snd_card_proc_new(chip->card, "codec_rw", &entry)) {
snd_info_set_text_ops(entry, chip, lola_proc_codec_rw_read);
entry->mode |= S_IWUSR;
entry->mode |= 0200;
entry->c.text.write = lola_proc_codec_rw_write;
}
if (!snd_card_proc_new(chip->card, "regs", &entry))

View file

@ -1052,10 +1052,10 @@ static int add_controls(struct oxygen *chip,
[CONTROL_CD_CAPTURE_SWITCH] = "CD Capture Switch",
[CONTROL_AUX_CAPTURE_SWITCH] = "Aux Capture Switch",
};
unsigned int i, j;
unsigned int i;
struct snd_kcontrol_new template;
struct snd_kcontrol *ctl;
int err;
int j, err;
for (i = 0; i < count; ++i) {
template = controls[i];
@ -1086,11 +1086,11 @@ static int add_controls(struct oxygen *chip,
err = snd_ctl_add(chip->card, ctl);
if (err < 0)
return err;
for (j = 0; j < CONTROL_COUNT; ++j)
if (!strcmp(ctl->id.name, known_ctl_names[j])) {
chip->controls[j] = ctl;
ctl->private_free = oxygen_any_ctl_free;
}
j = match_string(known_ctl_names, CONTROL_COUNT, ctl->id.name);
if (j >= 0) {
chip->controls[j] = ctl;
ctl->private_free = oxygen_any_ctl_free;
}
}
return 0;
}

View file

@ -1465,7 +1465,7 @@ static void pcxhr_proc_init(struct snd_pcxhr *chip)
!snd_card_proc_new(chip->card, "gpio", &entry)) {
snd_info_set_text_ops(entry, chip, pcxhr_proc_gpio_read);
entry->c.text.write = pcxhr_proc_gpo_write;
entry->mode |= S_IWUSR;
entry->mode |= 0200;
}
if (!snd_card_proc_new(chip->card, "ltc", &entry))
snd_info_set_text_ops(entry, chip, pcxhr_proc_ltc);

View file

@ -1733,10 +1733,10 @@ static ssize_t cs43130_show_ac_r(struct device *dev,
return cs43130_show_ac(dev, buf, HP_RIGHT);
}
static DEVICE_ATTR(hpload_dc_l, S_IRUGO, cs43130_show_dc_l, NULL);
static DEVICE_ATTR(hpload_dc_r, S_IRUGO, cs43130_show_dc_r, NULL);
static DEVICE_ATTR(hpload_ac_l, S_IRUGO, cs43130_show_ac_l, NULL);
static DEVICE_ATTR(hpload_ac_r, S_IRUGO, cs43130_show_ac_r, NULL);
static DEVICE_ATTR(hpload_dc_l, 0444, cs43130_show_dc_l, NULL);
static DEVICE_ATTR(hpload_dc_r, 0444, cs43130_show_dc_r, NULL);
static DEVICE_ATTR(hpload_ac_l, 0444, cs43130_show_ac_l, NULL);
static DEVICE_ATTR(hpload_ac_r, 0444, cs43130_show_ac_r, NULL);
static struct reg_sequence hp_en_cal_seq[] = {
{CS43130_INT_MASK_4, CS43130_INT_MASK_ALL},

View file

@ -627,22 +627,21 @@ static void wm_adsp2_init_debugfs(struct wm_adsp *dsp,
if (!root)
goto err;
if (!debugfs_create_bool("booted", S_IRUGO, root, &dsp->booted))
if (!debugfs_create_bool("booted", 0444, root, &dsp->booted))
goto err;
if (!debugfs_create_bool("running", S_IRUGO, root, &dsp->running))
if (!debugfs_create_bool("running", 0444, root, &dsp->running))
goto err;
if (!debugfs_create_x32("fw_id", S_IRUGO, root, &dsp->fw_id))
if (!debugfs_create_x32("fw_id", 0444, root, &dsp->fw_id))
goto err;
if (!debugfs_create_x32("fw_version", S_IRUGO, root,
&dsp->fw_id_version))
if (!debugfs_create_x32("fw_version", 0444, root, &dsp->fw_id_version))
goto err;
for (i = 0; i < ARRAY_SIZE(wm_adsp_debugfs_fops); ++i) {
if (!debugfs_create_file(wm_adsp_debugfs_fops[i].name,
S_IRUGO, root, dsp,
0444, root, dsp,
&wm_adsp_debugfs_fops[i].fops))
goto err;
}

View file

@ -146,7 +146,7 @@ int fsl_ssi_debugfs_create(struct fsl_ssi_dbg *ssi_dbg, struct device *dev)
if (!ssi_dbg->dbg_dir)
return -ENOMEM;
ssi_dbg->dbg_stats = debugfs_create_file("stats", S_IRUGO,
ssi_dbg->dbg_stats = debugfs_create_file("stats", 0444,
ssi_dbg->dbg_dir, ssi_dbg,
&fsl_ssi_stats_ops);
if (!ssi_dbg->dbg_stats) {

Some files were not shown because too many files have changed in this diff Show more