forked from Minki/linux
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:
commit
cdbc653a04
@ -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.
|
||||
|
||||
|
@ -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
|
||||
========
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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 */
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
||||
|
||||
/*
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -96,6 +96,8 @@ source "sound/x86/Kconfig"
|
||||
|
||||
source "sound/synth/Kconfig"
|
||||
|
||||
source "sound/xen/Kconfig"
|
||||
|
||||
endif # SND
|
||||
|
||||
endif # !UML
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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(®ister_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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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>");
|
||||
|
@ -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 */
|
||||
|
@ -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");
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
52
sound/firewire/dice/dice-alesis.c
Normal file
52
sound/firewire/dice/dice-alesis.c
Normal 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, ®,
|
||||
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;
|
||||
}
|
172
sound/firewire/dice/dice-extension.c
Normal file
172
sound/firewire/dice/dice-extension.c
Normal 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,
|
||||
®, 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;
|
||||
}
|
@ -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.
|
||||
*/
|
||||
|
@ -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,
|
||||
®, sizeof(reg));
|
||||
if (err < 0)
|
||||
return err;
|
||||
midi_in_ports = be32_to_cpu(reg);
|
||||
|
||||
err = snd_dice_transaction_read_rx(dice, RX_NUMBER_MIDI,
|
||||
®, 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;
|
||||
|
46
sound/firewire/dice/dice-mytek.c
Normal file
46
sound/firewire/dice/dice-mytek.c
Normal 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;
|
||||
}
|
@ -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,
|
||||
®, sizeof(reg));
|
||||
} else {
|
||||
stream = &dice->rx_stream[index];
|
||||
err = snd_dice_transaction_read_rx(dice,
|
||||
size * index + RX_NUMBER_AUDIO,
|
||||
®, 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, ®,
|
||||
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, ®,
|
||||
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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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,
|
||||
®, 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;
|
||||
|
104
sound/firewire/dice/dice-tcelectronic.c
Normal file
104
sound/firewire/dice/dice-tcelectronic.c
Normal 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;
|
||||
}
|
@ -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;
|
||||
|
@ -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 @@ error:
|
||||
"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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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++) {
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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 *);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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_ */
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -248,13 +248,13 @@ __found_pages:
|
||||
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;
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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))
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
95
sound/pci/hda/hp_x360_helper.c
Normal file
95
sound/pci/hda/hp_x360_helper.c
Normal 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;
|
||||
}
|
||||
}
|
@ -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
@ -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" },
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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},
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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))
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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},
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user