sound fixes for 4.17-rc3

A significant amount of fixes have been piled up at this time.
 
 - Possible Spectre v1 coverage in OSS sequencer API, control API,
   HD-audio hwdep ioctl, ASIHPI hwdep ioctl, OPL3, and HDSPM/RME
   channel_info API.
 
 - A regression fix in PCM delay reporting that happened at the code
   refactoring for the set_fs() removal
 
 - The long-standing bug in PCM sync_ptr ioctl that missed the audio
   timestamp field
 
 - USB-audio regression fixes due to the recent UAC2 jack support
 
 - vm_fault_t conversions in a couple of places
 
 - ASoC topology API fixes
 
 - Assorted driver fixes:
   * ASoC rsnd, FSL, Intel SST, DMIC, AMD, ADAU17x1, Realtek codec
   * FireWire typo fix
   * HD-audio quirks and USB-audio Dell fixup
   * USB-audio UAC3 corrections
 -----BEGIN PGP SIGNATURE-----
 
 iQJCBAABCAAsFiEEIXTw5fNLNI7mMiVaLtJE4w1nLE8FAlrh07cOHHRpd2FpQHN1
 c2UuZGUACgkQLtJE4w1nLE8+6g/9F9nI4FEBb+jpP360vPyRJmjIR5Y5pp34+bA7
 paMaa67J7HielEwUoos/8RhoH9/i1dXrT/ZhA1CkFleDohQqV6u0xpaT/07m+Yak
 lwQK2qJMn9hpahxrWDZ68qqIuI5IB7DzeRNjt9BmedWgzxn3PMoFc1ETGK8EepkL
 v9DSr+htSl83bmYxmhabBWCcI8lbpnPDbKwTewqp2GDarz7WBI/Mqw5tEycvpd04
 oSxKruFGYUMw+e7+eEX/h+LxA7Wx7jmroXdMq5C8OC3oQ+T0n1I84MeCHvp8/Lh6
 5u5jdm1nKH16pe6L6ZzcQ9iWHgATyGKi7u3dmvfl58GrVJsBtYpZxCA59bktl1Ab
 JFn1hqrM49IbndfuPaznAtIhGg/dd3wZcN32owKo+U2TWIzKflA7NQaqceTXhlxn
 Ly6v9HcI9hCAuLObVAFZ8WaJlQGUNGOSabtjUqsYVFwe4s0dTWVYKyCGGiahQ7UL
 LJ1sH1vH7vfn48FCxOUOODw/l9N8Ka/rqTdfKJRYsZPBRyzbXqty1VdFXJbhbWsX
 7qkpYwM2zuNTyUASBkKgJY9SuGtUQlvusuLLTf/8j6srR94fz1H5uww0V+2WEgT/
 GyoXRLtiDPvf/+MnIhKBnOWcpyz+1Pql7LNX9YWe/f13ibGFfV5SdddbIOu+08Xa
 N/eA+I0=
 =eSik
 -----END PGP SIGNATURE-----

Merge tag 'sound-4.17-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound

Pull sound fixes from Takashi Iwai:
 "A significant amount of fixes have been piled up at this time.

   - Possible Spectre v1 coverage in OSS sequencer API, control API,
     HD-audio hwdep ioctl, ASIHPI hwdep ioctl, OPL3, and HDSPM/RME
     channel_info API.

   - A regression fix in PCM delay reporting that happened at the code
     refactoring for the set_fs() removal

   - The long-standing bug in PCM sync_ptr ioctl that missed the audio
     timestamp field

   - USB-audio regression fixes due to the recent UAC2 jack support

   - vm_fault_t conversions in a couple of places

   - ASoC topology API fixes

   - Assorted driver fixes:
      * ASoC rsnd, FSL, Intel SST, DMIC, AMD, ADAU17x1, Realtek codec
      * FireWire typo fix
      * HD-audio quirks and USB-audio Dell fixup
      * USB-audio UAC3 corrections"

* tag 'sound-4.17-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (35 commits)
  ALSA: dice: fix error path to destroy initialized stream data
  ALSA: hda - Skip jack and others for non-existing PCM streams
  ALSA: hda/realtek - change the location for one of two front mics
  ALSA: rme9652: Hardening for potential Spectre v1
  ALSA: hdspm: Hardening for potential Spectre v1
  ALSA: asihpi: Hardening for potential Spectre v1
  ALSA: opl3: Hardening for potential Spectre v1
  ALSA: hda: Hardening for potential Spectre v1
  ALSA: control: Hardening for potential Spectre v1
  ALSA: seq: oss: Hardening for potential Spectre v1
  ALSA: seq: oss: Fix unbalanced use lock for synth MIDI device
  ALSA: hda/realtek - Update ALC255 depop optimize
  ALSA: hda/realtek - Add some fixes for ALC233
  ALSA: pcm: Change return type to vm_fault_t
  ALSA: usx2y: Change return type to vm_fault_t
  ALSA: usb-audio: ADC3: Fix channel mapping conversion for ADC3.
  ALSA: dice: fix OUI for TC group
  ALSA: usb-audio: Skip broken EU on Dell dock USB-audio
  ALSA: usb-audio: Fix missing endian conversion
  ALSA: usb-audio: Fix forgotten conversion of control query functions
  ...
This commit is contained in:
Linus Torvalds 2018-04-27 09:29:18 -07:00
commit 7ff5000268
35 changed files with 244 additions and 127 deletions

View File

@ -23,6 +23,7 @@
*/ */
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/nospec.h>
#include <sound/asound.h> #include <sound/asound.h>
#define snd_kcontrol_chip(kcontrol) ((kcontrol)->private_data) #define snd_kcontrol_chip(kcontrol) ((kcontrol)->private_data)
@ -148,12 +149,14 @@ int snd_ctl_get_preferred_subdevice(struct snd_card *card, int type);
static inline unsigned int snd_ctl_get_ioffnum(struct snd_kcontrol *kctl, struct snd_ctl_elem_id *id) static inline unsigned int snd_ctl_get_ioffnum(struct snd_kcontrol *kctl, struct snd_ctl_elem_id *id)
{ {
return id->numid - kctl->id.numid; unsigned int ioff = id->numid - kctl->id.numid;
return array_index_nospec(ioff, kctl->count);
} }
static inline unsigned int snd_ctl_get_ioffidx(struct snd_kcontrol *kctl, struct snd_ctl_elem_id *id) static inline unsigned int snd_ctl_get_ioffidx(struct snd_kcontrol *kctl, struct snd_ctl_elem_id *id)
{ {
return id->index - kctl->id.index; unsigned int ioff = id->index - kctl->id.index;
return array_index_nospec(ioff, kctl->count);
} }
static inline unsigned int snd_ctl_get_ioff(struct snd_kcontrol *kctl, struct snd_ctl_elem_id *id) static inline unsigned int snd_ctl_get_ioff(struct snd_kcontrol *kctl, struct snd_ctl_elem_id *id)

View File

@ -1492,7 +1492,7 @@ static int snd_ctl_tlv_ioctl(struct snd_ctl_file *file,
int op_flag) int op_flag)
{ {
struct snd_ctl_tlv header; struct snd_ctl_tlv header;
unsigned int *container; unsigned int __user *container;
unsigned int container_size; unsigned int container_size;
struct snd_kcontrol *kctl; struct snd_kcontrol *kctl;
struct snd_ctl_elem_id id; struct snd_ctl_elem_id id;

View File

@ -27,10 +27,11 @@ static int snd_pcm_ioctl_delay_compat(struct snd_pcm_substream *substream,
s32 __user *src) s32 __user *src)
{ {
snd_pcm_sframes_t delay; snd_pcm_sframes_t delay;
int err;
delay = snd_pcm_delay(substream); err = snd_pcm_delay(substream, &delay);
if (delay < 0) if (err)
return delay; return err;
if (put_user(delay, src)) if (put_user(delay, src))
return -EFAULT; return -EFAULT;
return 0; return 0;

View File

@ -2692,7 +2692,8 @@ static int snd_pcm_hwsync(struct snd_pcm_substream *substream)
return err; return err;
} }
static snd_pcm_sframes_t snd_pcm_delay(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; struct snd_pcm_runtime *runtime = substream->runtime;
int err; int err;
@ -2708,7 +2709,9 @@ static snd_pcm_sframes_t snd_pcm_delay(struct snd_pcm_substream *substream)
n += runtime->delay; n += runtime->delay;
} }
snd_pcm_stream_unlock_irq(substream); snd_pcm_stream_unlock_irq(substream);
return err < 0 ? err : n; if (!err)
*delay = n;
return err;
} }
static int snd_pcm_sync_ptr(struct snd_pcm_substream *substream, static int snd_pcm_sync_ptr(struct snd_pcm_substream *substream,
@ -2751,6 +2754,7 @@ static int snd_pcm_sync_ptr(struct snd_pcm_substream *substream,
sync_ptr.s.status.hw_ptr = status->hw_ptr; sync_ptr.s.status.hw_ptr = status->hw_ptr;
sync_ptr.s.status.tstamp = status->tstamp; sync_ptr.s.status.tstamp = status->tstamp;
sync_ptr.s.status.suspended_state = status->suspended_state; sync_ptr.s.status.suspended_state = status->suspended_state;
sync_ptr.s.status.audio_tstamp = status->audio_tstamp;
snd_pcm_stream_unlock_irq(substream); snd_pcm_stream_unlock_irq(substream);
if (copy_to_user(_sync_ptr, &sync_ptr, sizeof(sync_ptr))) if (copy_to_user(_sync_ptr, &sync_ptr, sizeof(sync_ptr)))
return -EFAULT; return -EFAULT;
@ -2916,11 +2920,13 @@ static int snd_pcm_common_ioctl(struct file *file,
return snd_pcm_hwsync(substream); return snd_pcm_hwsync(substream);
case SNDRV_PCM_IOCTL_DELAY: case SNDRV_PCM_IOCTL_DELAY:
{ {
snd_pcm_sframes_t delay = snd_pcm_delay(substream); snd_pcm_sframes_t delay;
snd_pcm_sframes_t __user *res = arg; snd_pcm_sframes_t __user *res = arg;
int err;
if (delay < 0) err = snd_pcm_delay(substream, &delay);
return delay; if (err)
return err;
if (put_user(delay, res)) if (put_user(delay, res))
return -EFAULT; return -EFAULT;
return 0; return 0;
@ -3008,13 +3014,7 @@ int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream,
case SNDRV_PCM_IOCTL_DROP: case SNDRV_PCM_IOCTL_DROP:
return snd_pcm_drop(substream); return snd_pcm_drop(substream);
case SNDRV_PCM_IOCTL_DELAY: case SNDRV_PCM_IOCTL_DELAY:
{ return snd_pcm_delay(substream, frames);
result = snd_pcm_delay(substream);
if (result < 0)
return result;
*frames = result;
return 0;
}
default: default:
return -EINVAL; return -EINVAL;
} }
@ -3234,7 +3234,7 @@ static __poll_t snd_pcm_capture_poll(struct file *file, poll_table * wait)
/* /*
* mmap status record * mmap status record
*/ */
static int snd_pcm_mmap_status_fault(struct vm_fault *vmf) static vm_fault_t snd_pcm_mmap_status_fault(struct vm_fault *vmf)
{ {
struct snd_pcm_substream *substream = vmf->vma->vm_private_data; struct snd_pcm_substream *substream = vmf->vma->vm_private_data;
struct snd_pcm_runtime *runtime; struct snd_pcm_runtime *runtime;
@ -3270,7 +3270,7 @@ static int snd_pcm_mmap_status(struct snd_pcm_substream *substream, struct file
/* /*
* mmap control record * mmap control record
*/ */
static int snd_pcm_mmap_control_fault(struct vm_fault *vmf) static vm_fault_t snd_pcm_mmap_control_fault(struct vm_fault *vmf)
{ {
struct snd_pcm_substream *substream = vmf->vma->vm_private_data; struct snd_pcm_substream *substream = vmf->vma->vm_private_data;
struct snd_pcm_runtime *runtime; struct snd_pcm_runtime *runtime;
@ -3359,7 +3359,7 @@ snd_pcm_default_page_ops(struct snd_pcm_substream *substream, unsigned long ofs)
/* /*
* fault callback for mmapping a RAM page * fault callback for mmapping a RAM page
*/ */
static int snd_pcm_mmap_data_fault(struct vm_fault *vmf) static vm_fault_t snd_pcm_mmap_data_fault(struct vm_fault *vmf)
{ {
struct snd_pcm_substream *substream = vmf->vma->vm_private_data; struct snd_pcm_substream *substream = vmf->vma->vm_private_data;
struct snd_pcm_runtime *runtime; struct snd_pcm_runtime *runtime;

View File

@ -26,6 +26,7 @@
#include <sound/seq_oss_legacy.h> #include <sound/seq_oss_legacy.h>
#include "seq_oss_readq.h" #include "seq_oss_readq.h"
#include "seq_oss_writeq.h" #include "seq_oss_writeq.h"
#include <linux/nospec.h>
/* /*
@ -287,10 +288,10 @@ note_on_event(struct seq_oss_devinfo *dp, int dev, int ch, int note, int vel, st
{ {
struct seq_oss_synthinfo *info; struct seq_oss_synthinfo *info;
if (!snd_seq_oss_synth_is_valid(dp, dev)) info = snd_seq_oss_synth_info(dp, dev);
if (!info)
return -ENXIO; return -ENXIO;
info = &dp->synths[dev];
switch (info->arg.event_passing) { switch (info->arg.event_passing) {
case SNDRV_SEQ_OSS_PROCESS_EVENTS: case SNDRV_SEQ_OSS_PROCESS_EVENTS:
if (! info->ch || ch < 0 || ch >= info->nr_voices) { if (! info->ch || ch < 0 || ch >= info->nr_voices) {
@ -298,6 +299,7 @@ note_on_event(struct seq_oss_devinfo *dp, int dev, int ch, int note, int vel, st
return set_note_event(dp, dev, SNDRV_SEQ_EVENT_NOTEON, ch, note, vel, ev); return set_note_event(dp, dev, SNDRV_SEQ_EVENT_NOTEON, ch, note, vel, ev);
} }
ch = array_index_nospec(ch, info->nr_voices);
if (note == 255 && info->ch[ch].note >= 0) { if (note == 255 && info->ch[ch].note >= 0) {
/* volume control */ /* volume control */
int type; int type;
@ -347,10 +349,10 @@ note_off_event(struct seq_oss_devinfo *dp, int dev, int ch, int note, int vel, s
{ {
struct seq_oss_synthinfo *info; struct seq_oss_synthinfo *info;
if (!snd_seq_oss_synth_is_valid(dp, dev)) info = snd_seq_oss_synth_info(dp, dev);
if (!info)
return -ENXIO; return -ENXIO;
info = &dp->synths[dev];
switch (info->arg.event_passing) { switch (info->arg.event_passing) {
case SNDRV_SEQ_OSS_PROCESS_EVENTS: case SNDRV_SEQ_OSS_PROCESS_EVENTS:
if (! info->ch || ch < 0 || ch >= info->nr_voices) { if (! info->ch || ch < 0 || ch >= info->nr_voices) {
@ -358,6 +360,7 @@ note_off_event(struct seq_oss_devinfo *dp, int dev, int ch, int note, int vel, s
return set_note_event(dp, dev, SNDRV_SEQ_EVENT_NOTEON, ch, note, vel, ev); return set_note_event(dp, dev, SNDRV_SEQ_EVENT_NOTEON, ch, note, vel, ev);
} }
ch = array_index_nospec(ch, info->nr_voices);
if (info->ch[ch].note >= 0) { if (info->ch[ch].note >= 0) {
note = info->ch[ch].note; note = info->ch[ch].note;
info->ch[ch].vel = 0; info->ch[ch].vel = 0;
@ -381,7 +384,7 @@ note_off_event(struct seq_oss_devinfo *dp, int dev, int ch, int note, int vel, s
static int static int
set_note_event(struct seq_oss_devinfo *dp, int dev, int type, int ch, int note, int vel, struct snd_seq_event *ev) set_note_event(struct seq_oss_devinfo *dp, int dev, int type, int ch, int note, int vel, struct snd_seq_event *ev)
{ {
if (! snd_seq_oss_synth_is_valid(dp, dev)) if (!snd_seq_oss_synth_info(dp, dev))
return -ENXIO; return -ENXIO;
ev->type = type; ev->type = type;
@ -399,7 +402,7 @@ set_note_event(struct seq_oss_devinfo *dp, int dev, int type, int ch, int note,
static int static int
set_control_event(struct seq_oss_devinfo *dp, int dev, int type, int ch, int param, int val, struct snd_seq_event *ev) set_control_event(struct seq_oss_devinfo *dp, int dev, int type, int ch, int param, int val, struct snd_seq_event *ev)
{ {
if (! snd_seq_oss_synth_is_valid(dp, dev)) if (!snd_seq_oss_synth_info(dp, dev))
return -ENXIO; return -ENXIO;
ev->type = type; ev->type = type;

View File

@ -29,6 +29,7 @@
#include "../seq_lock.h" #include "../seq_lock.h"
#include <linux/init.h> #include <linux/init.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/nospec.h>
/* /*
@ -315,6 +316,7 @@ get_mididev(struct seq_oss_devinfo *dp, int dev)
{ {
if (dev < 0 || dev >= dp->max_mididev) if (dev < 0 || dev >= dp->max_mididev)
return NULL; return NULL;
dev = array_index_nospec(dev, dp->max_mididev);
return get_mdev(dev); return get_mdev(dev);
} }

View File

@ -26,6 +26,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/nospec.h>
/* /*
* constants * constants
@ -339,17 +340,13 @@ snd_seq_oss_synth_cleanup(struct seq_oss_devinfo *dp)
dp->max_synthdev = 0; dp->max_synthdev = 0;
} }
/* static struct seq_oss_synthinfo *
* check if the specified device is MIDI mapped device get_synthinfo_nospec(struct seq_oss_devinfo *dp, int dev)
*/
static int
is_midi_dev(struct seq_oss_devinfo *dp, int dev)
{ {
if (dev < 0 || dev >= dp->max_synthdev) if (dev < 0 || dev >= dp->max_synthdev)
return 0; return NULL;
if (dp->synths[dev].is_midi) dev = array_index_nospec(dev, SNDRV_SEQ_OSS_MAX_SYNTH_DEVS);
return 1; return &dp->synths[dev];
return 0;
} }
/* /*
@ -359,14 +356,20 @@ static struct seq_oss_synth *
get_synthdev(struct seq_oss_devinfo *dp, int dev) get_synthdev(struct seq_oss_devinfo *dp, int dev)
{ {
struct seq_oss_synth *rec; struct seq_oss_synth *rec;
if (dev < 0 || dev >= dp->max_synthdev) struct seq_oss_synthinfo *info = get_synthinfo_nospec(dp, dev);
if (!info)
return NULL; return NULL;
if (! dp->synths[dev].opened) if (!info->opened)
return NULL;
if (dp->synths[dev].is_midi)
return &midi_synth_dev;
if ((rec = get_sdev(dev)) == NULL)
return NULL; return NULL;
if (info->is_midi) {
rec = &midi_synth_dev;
snd_use_lock_use(&rec->use_lock);
} else {
rec = get_sdev(dev);
if (!rec)
return NULL;
}
if (! rec->opened) { if (! rec->opened) {
snd_use_lock_free(&rec->use_lock); snd_use_lock_free(&rec->use_lock);
return NULL; return NULL;
@ -402,10 +405,8 @@ snd_seq_oss_synth_reset(struct seq_oss_devinfo *dp, int dev)
struct seq_oss_synth *rec; struct seq_oss_synth *rec;
struct seq_oss_synthinfo *info; struct seq_oss_synthinfo *info;
if (snd_BUG_ON(dev < 0 || dev >= dp->max_synthdev)) info = get_synthinfo_nospec(dp, dev);
return; if (!info || !info->opened)
info = &dp->synths[dev];
if (! info->opened)
return; return;
if (info->sysex) if (info->sysex)
info->sysex->len = 0; /* reset sysex */ info->sysex->len = 0; /* reset sysex */
@ -454,12 +455,14 @@ snd_seq_oss_synth_load_patch(struct seq_oss_devinfo *dp, int dev, int fmt,
const char __user *buf, int p, int c) const char __user *buf, int p, int c)
{ {
struct seq_oss_synth *rec; struct seq_oss_synth *rec;
struct seq_oss_synthinfo *info;
int rc; int rc;
if (dev < 0 || dev >= dp->max_synthdev) info = get_synthinfo_nospec(dp, dev);
if (!info)
return -ENXIO; return -ENXIO;
if (is_midi_dev(dp, dev)) if (info->is_midi)
return 0; return 0;
if ((rec = get_synthdev(dp, dev)) == NULL) if ((rec = get_synthdev(dp, dev)) == NULL)
return -ENXIO; return -ENXIO;
@ -467,24 +470,25 @@ snd_seq_oss_synth_load_patch(struct seq_oss_devinfo *dp, int dev, int fmt,
if (rec->oper.load_patch == NULL) if (rec->oper.load_patch == NULL)
rc = -ENXIO; rc = -ENXIO;
else else
rc = rec->oper.load_patch(&dp->synths[dev].arg, fmt, buf, p, c); rc = rec->oper.load_patch(&info->arg, fmt, buf, p, c);
snd_use_lock_free(&rec->use_lock); snd_use_lock_free(&rec->use_lock);
return rc; return rc;
} }
/* /*
* check if the device is valid synth device * check if the device is valid synth device and return the synth info
*/ */
int struct seq_oss_synthinfo *
snd_seq_oss_synth_is_valid(struct seq_oss_devinfo *dp, int dev) snd_seq_oss_synth_info(struct seq_oss_devinfo *dp, int dev)
{ {
struct seq_oss_synth *rec; struct seq_oss_synth *rec;
rec = get_synthdev(dp, dev); rec = get_synthdev(dp, dev);
if (rec) { if (rec) {
snd_use_lock_free(&rec->use_lock); snd_use_lock_free(&rec->use_lock);
return 1; return get_synthinfo_nospec(dp, dev);
} }
return 0; return NULL;
} }
@ -499,16 +503,18 @@ snd_seq_oss_synth_sysex(struct seq_oss_devinfo *dp, int dev, unsigned char *buf,
int i, send; int i, send;
unsigned char *dest; unsigned char *dest;
struct seq_oss_synth_sysex *sysex; struct seq_oss_synth_sysex *sysex;
struct seq_oss_synthinfo *info;
if (! snd_seq_oss_synth_is_valid(dp, dev)) info = snd_seq_oss_synth_info(dp, dev);
if (!info)
return -ENXIO; return -ENXIO;
sysex = dp->synths[dev].sysex; sysex = info->sysex;
if (sysex == NULL) { if (sysex == NULL) {
sysex = kzalloc(sizeof(*sysex), GFP_KERNEL); sysex = kzalloc(sizeof(*sysex), GFP_KERNEL);
if (sysex == NULL) if (sysex == NULL)
return -ENOMEM; return -ENOMEM;
dp->synths[dev].sysex = sysex; info->sysex = sysex;
} }
send = 0; send = 0;
@ -553,10 +559,12 @@ snd_seq_oss_synth_sysex(struct seq_oss_devinfo *dp, int dev, unsigned char *buf,
int int
snd_seq_oss_synth_addr(struct seq_oss_devinfo *dp, int dev, struct snd_seq_event *ev) snd_seq_oss_synth_addr(struct seq_oss_devinfo *dp, int dev, struct snd_seq_event *ev)
{ {
if (! snd_seq_oss_synth_is_valid(dp, dev)) struct seq_oss_synthinfo *info = snd_seq_oss_synth_info(dp, dev);
if (!info)
return -EINVAL; return -EINVAL;
snd_seq_oss_fill_addr(dp, ev, dp->synths[dev].arg.addr.client, snd_seq_oss_fill_addr(dp, ev, info->arg.addr.client,
dp->synths[dev].arg.addr.port); info->arg.addr.port);
return 0; return 0;
} }
@ -568,16 +576,18 @@ int
snd_seq_oss_synth_ioctl(struct seq_oss_devinfo *dp, int dev, unsigned int cmd, unsigned long addr) snd_seq_oss_synth_ioctl(struct seq_oss_devinfo *dp, int dev, unsigned int cmd, unsigned long addr)
{ {
struct seq_oss_synth *rec; struct seq_oss_synth *rec;
struct seq_oss_synthinfo *info;
int rc; int rc;
if (is_midi_dev(dp, dev)) info = get_synthinfo_nospec(dp, dev);
if (!info || info->is_midi)
return -ENXIO; return -ENXIO;
if ((rec = get_synthdev(dp, dev)) == NULL) if ((rec = get_synthdev(dp, dev)) == NULL)
return -ENXIO; return -ENXIO;
if (rec->oper.ioctl == NULL) if (rec->oper.ioctl == NULL)
rc = -ENXIO; rc = -ENXIO;
else else
rc = rec->oper.ioctl(&dp->synths[dev].arg, cmd, addr); rc = rec->oper.ioctl(&info->arg, cmd, addr);
snd_use_lock_free(&rec->use_lock); snd_use_lock_free(&rec->use_lock);
return rc; return rc;
} }
@ -589,7 +599,10 @@ snd_seq_oss_synth_ioctl(struct seq_oss_devinfo *dp, int dev, unsigned int cmd, u
int int
snd_seq_oss_synth_raw_event(struct seq_oss_devinfo *dp, int dev, unsigned char *data, struct snd_seq_event *ev) snd_seq_oss_synth_raw_event(struct seq_oss_devinfo *dp, int dev, unsigned char *data, struct snd_seq_event *ev)
{ {
if (! snd_seq_oss_synth_is_valid(dp, dev) || is_midi_dev(dp, dev)) struct seq_oss_synthinfo *info;
info = snd_seq_oss_synth_info(dp, dev);
if (!info || info->is_midi)
return -ENXIO; return -ENXIO;
ev->type = SNDRV_SEQ_EVENT_OSS; ev->type = SNDRV_SEQ_EVENT_OSS;
memcpy(ev->data.raw8.d, data, 8); memcpy(ev->data.raw8.d, data, 8);

View File

@ -37,7 +37,8 @@ void snd_seq_oss_synth_cleanup(struct seq_oss_devinfo *dp);
void snd_seq_oss_synth_reset(struct seq_oss_devinfo *dp, int dev); void snd_seq_oss_synth_reset(struct seq_oss_devinfo *dp, int dev);
int snd_seq_oss_synth_load_patch(struct seq_oss_devinfo *dp, int dev, int fmt, int snd_seq_oss_synth_load_patch(struct seq_oss_devinfo *dp, int dev, int fmt,
const char __user *buf, int p, int c); const char __user *buf, int p, int c);
int snd_seq_oss_synth_is_valid(struct seq_oss_devinfo *dp, int dev); struct seq_oss_synthinfo *snd_seq_oss_synth_info(struct seq_oss_devinfo *dp,
int dev);
int snd_seq_oss_synth_sysex(struct seq_oss_devinfo *dp, int dev, unsigned char *buf, int snd_seq_oss_synth_sysex(struct seq_oss_devinfo *dp, int dev, unsigned char *buf,
struct snd_seq_event *ev); struct snd_seq_event *ev);
int snd_seq_oss_synth_addr(struct seq_oss_devinfo *dp, int dev, struct snd_seq_event *ev); int snd_seq_oss_synth_addr(struct seq_oss_devinfo *dp, int dev, struct snd_seq_event *ev);

View File

@ -21,6 +21,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/export.h> #include <linux/export.h>
#include <linux/nospec.h>
#include <sound/opl3.h> #include <sound/opl3.h>
#include <sound/asound_fm.h> #include <sound/asound_fm.h>
@ -448,7 +449,7 @@ static int snd_opl3_set_voice(struct snd_opl3 * opl3, struct snd_dm_fm_voice * v
{ {
unsigned short reg_side; unsigned short reg_side;
unsigned char op_offset; unsigned char op_offset;
unsigned char voice_offset; unsigned char voice_offset, voice_op;
unsigned short opl3_reg; unsigned short opl3_reg;
unsigned char reg_val; unsigned char reg_val;
@ -473,7 +474,9 @@ static int snd_opl3_set_voice(struct snd_opl3 * opl3, struct snd_dm_fm_voice * v
voice_offset = voice->voice - MAX_OPL2_VOICES; voice_offset = voice->voice - MAX_OPL2_VOICES;
} }
/* Get register offset of operator */ /* Get register offset of operator */
op_offset = snd_opl3_regmap[voice_offset][voice->op]; voice_offset = array_index_nospec(voice_offset, MAX_OPL2_VOICES);
voice_op = array_index_nospec(voice->op, 4);
op_offset = snd_opl3_regmap[voice_offset][voice_op];
reg_val = 0x00; reg_val = 0x00;
/* Set amplitude modulation (tremolo) effect */ /* Set amplitude modulation (tremolo) effect */

View File

@ -435,7 +435,7 @@ int snd_dice_stream_init_duplex(struct snd_dice *dice)
err = init_stream(dice, AMDTP_IN_STREAM, i); err = init_stream(dice, AMDTP_IN_STREAM, i);
if (err < 0) { if (err < 0) {
for (; i >= 0; i--) for (; i >= 0; i--)
destroy_stream(dice, AMDTP_OUT_STREAM, i); destroy_stream(dice, AMDTP_IN_STREAM, i);
goto end; goto end;
} }
} }

View File

@ -14,7 +14,7 @@ MODULE_LICENSE("GPL v2");
#define OUI_WEISS 0x001c6a #define OUI_WEISS 0x001c6a
#define OUI_LOUD 0x000ff2 #define OUI_LOUD 0x000ff2
#define OUI_FOCUSRITE 0x00130e #define OUI_FOCUSRITE 0x00130e
#define OUI_TCELECTRONIC 0x001486 #define OUI_TCELECTRONIC 0x000166
#define DICE_CATEGORY_ID 0x04 #define DICE_CATEGORY_ID 0x04
#define WEISS_CATEGORY_ID 0x00 #define WEISS_CATEGORY_ID 0x00

View File

@ -23,6 +23,7 @@
#include "hpi_internal.h" #include "hpi_internal.h"
#include "hpimsginit.h" #include "hpimsginit.h"
#include <linux/nospec.h>
/* The actual message size for each object type */ /* The actual message size for each object type */
static u16 msg_size[HPI_OBJ_MAXINDEX + 1] = HPI_MESSAGE_SIZE_BY_OBJECT; static u16 msg_size[HPI_OBJ_MAXINDEX + 1] = HPI_MESSAGE_SIZE_BY_OBJECT;
@ -39,10 +40,12 @@ static void hpi_init_message(struct hpi_message *phm, u16 object,
{ {
u16 size; u16 size;
if ((object > 0) && (object <= HPI_OBJ_MAXINDEX)) if ((object > 0) && (object <= HPI_OBJ_MAXINDEX)) {
object = array_index_nospec(object, HPI_OBJ_MAXINDEX + 1);
size = msg_size[object]; size = msg_size[object];
else } else {
size = sizeof(*phm); size = sizeof(*phm);
}
memset(phm, 0, size); memset(phm, 0, size);
phm->size = size; phm->size = size;
@ -66,10 +69,12 @@ void hpi_init_response(struct hpi_response *phr, u16 object, u16 function,
{ {
u16 size; u16 size;
if ((object > 0) && (object <= HPI_OBJ_MAXINDEX)) if ((object > 0) && (object <= HPI_OBJ_MAXINDEX)) {
object = array_index_nospec(object, HPI_OBJ_MAXINDEX + 1);
size = res_size[object]; size = res_size[object];
else } else {
size = sizeof(*phr); size = sizeof(*phr);
}
memset(phr, 0, sizeof(*phr)); memset(phr, 0, sizeof(*phr));
phr->size = size; phr->size = size;

View File

@ -33,6 +33,7 @@
#include <linux/stringify.h> #include <linux/stringify.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/nospec.h>
#ifdef MODULE_FIRMWARE #ifdef MODULE_FIRMWARE
MODULE_FIRMWARE("asihpi/dsp5000.bin"); MODULE_FIRMWARE("asihpi/dsp5000.bin");
@ -186,7 +187,8 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
struct hpi_adapter *pa = NULL; struct hpi_adapter *pa = NULL;
if (hm->h.adapter_index < ARRAY_SIZE(adapters)) if (hm->h.adapter_index < ARRAY_SIZE(adapters))
pa = &adapters[hm->h.adapter_index]; pa = &adapters[array_index_nospec(hm->h.adapter_index,
ARRAY_SIZE(adapters))];
if (!pa || !pa->adapter || !pa->adapter->type) { if (!pa || !pa->adapter || !pa->adapter->type) {
hpi_init_response(&hr->r0, hm->h.object, hpi_init_response(&hr->r0, hm->h.object,

View File

@ -21,6 +21,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/compat.h> #include <linux/compat.h>
#include <linux/nospec.h>
#include <sound/core.h> #include <sound/core.h>
#include "hda_codec.h" #include "hda_codec.h"
#include "hda_local.h" #include "hda_local.h"
@ -51,7 +52,16 @@ static int get_wcap_ioctl(struct hda_codec *codec,
if (get_user(verb, &arg->verb)) if (get_user(verb, &arg->verb))
return -EFAULT; return -EFAULT;
res = get_wcaps(codec, verb >> 24); /* open-code get_wcaps(verb>>24) with nospec */
verb >>= 24;
if (verb < codec->core.start_nid ||
verb >= codec->core.start_nid + codec->core.num_nodes) {
res = 0;
} else {
verb -= codec->core.start_nid;
verb = array_index_nospec(verb, codec->core.num_nodes);
res = codec->wcaps[verb];
}
if (put_user(res, &arg->res)) if (put_user(res, &arg->res))
return -EFAULT; return -EFAULT;
return 0; return 0;

View File

@ -1383,6 +1383,8 @@ static void hdmi_pcm_setup_pin(struct hdmi_spec *spec,
pcm = get_pcm_rec(spec, per_pin->pcm_idx); pcm = get_pcm_rec(spec, per_pin->pcm_idx);
else else
return; return;
if (!pcm->pcm)
return;
if (!test_bit(per_pin->pcm_idx, &spec->pcm_in_use)) if (!test_bit(per_pin->pcm_idx, &spec->pcm_in_use))
return; return;
@ -2151,8 +2153,13 @@ static int generic_hdmi_build_controls(struct hda_codec *codec)
int dev, err; int dev, err;
int pin_idx, pcm_idx; int pin_idx, pcm_idx;
for (pcm_idx = 0; pcm_idx < spec->pcm_used; pcm_idx++) { for (pcm_idx = 0; pcm_idx < spec->pcm_used; pcm_idx++) {
if (!get_pcm_rec(spec, pcm_idx)->pcm) {
/* no PCM: mark this for skipping permanently */
set_bit(pcm_idx, &spec->pcm_bitmap);
continue;
}
err = generic_hdmi_build_jack(codec, pcm_idx); err = generic_hdmi_build_jack(codec, pcm_idx);
if (err < 0) if (err < 0)
return err; return err;

View File

@ -331,6 +331,7 @@ static void alc_fill_eapd_coef(struct hda_codec *codec)
/* fallthrough */ /* fallthrough */
case 0x10ec0215: case 0x10ec0215:
case 0x10ec0233: case 0x10ec0233:
case 0x10ec0235:
case 0x10ec0236: case 0x10ec0236:
case 0x10ec0255: case 0x10ec0255:
case 0x10ec0256: case 0x10ec0256:
@ -6575,6 +6576,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x17aa, 0x30bb, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY), SND_PCI_QUIRK(0x17aa, 0x30bb, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY),
SND_PCI_QUIRK(0x17aa, 0x30e2, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY), SND_PCI_QUIRK(0x17aa, 0x30e2, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY),
SND_PCI_QUIRK(0x17aa, 0x310c, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION), SND_PCI_QUIRK(0x17aa, 0x310c, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION),
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, 0x3138, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION),
SND_PCI_QUIRK(0x17aa, 0x313c, "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, 0x3112, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY),
@ -7160,8 +7162,11 @@ static int patch_alc269(struct hda_codec *codec)
case 0x10ec0298: case 0x10ec0298:
spec->codec_variant = ALC269_TYPE_ALC298; spec->codec_variant = ALC269_TYPE_ALC298;
break; break;
case 0x10ec0235:
case 0x10ec0255: case 0x10ec0255:
spec->codec_variant = ALC269_TYPE_ALC255; spec->codec_variant = ALC269_TYPE_ALC255;
spec->shutup = alc256_shutup;
spec->init_hook = alc256_init;
break; break;
case 0x10ec0236: case 0x10ec0236:
case 0x10ec0256: case 0x10ec0256:

View File

@ -137,6 +137,7 @@
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/math64.h> #include <linux/math64.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/nospec.h>
#include <sound/core.h> #include <sound/core.h>
#include <sound/control.h> #include <sound/control.h>
@ -5698,40 +5699,43 @@ static int snd_hdspm_channel_info(struct snd_pcm_substream *substream,
struct snd_pcm_channel_info *info) struct snd_pcm_channel_info *info)
{ {
struct hdspm *hdspm = snd_pcm_substream_chip(substream); struct hdspm *hdspm = snd_pcm_substream_chip(substream);
unsigned int channel = info->channel;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
if (snd_BUG_ON(info->channel >= hdspm->max_channels_out)) { if (snd_BUG_ON(channel >= hdspm->max_channels_out)) {
dev_info(hdspm->card->dev, dev_info(hdspm->card->dev,
"snd_hdspm_channel_info: output channel out of range (%d)\n", "snd_hdspm_channel_info: output channel out of range (%d)\n",
info->channel); channel);
return -EINVAL; return -EINVAL;
} }
if (hdspm->channel_map_out[info->channel] < 0) { channel = array_index_nospec(channel, hdspm->max_channels_out);
if (hdspm->channel_map_out[channel] < 0) {
dev_info(hdspm->card->dev, dev_info(hdspm->card->dev,
"snd_hdspm_channel_info: output channel %d mapped out\n", "snd_hdspm_channel_info: output channel %d mapped out\n",
info->channel); channel);
return -EINVAL; return -EINVAL;
} }
info->offset = hdspm->channel_map_out[info->channel] * info->offset = hdspm->channel_map_out[channel] *
HDSPM_CHANNEL_BUFFER_BYTES; HDSPM_CHANNEL_BUFFER_BYTES;
} else { } else {
if (snd_BUG_ON(info->channel >= hdspm->max_channels_in)) { if (snd_BUG_ON(channel >= hdspm->max_channels_in)) {
dev_info(hdspm->card->dev, dev_info(hdspm->card->dev,
"snd_hdspm_channel_info: input channel out of range (%d)\n", "snd_hdspm_channel_info: input channel out of range (%d)\n",
info->channel); channel);
return -EINVAL; return -EINVAL;
} }
if (hdspm->channel_map_in[info->channel] < 0) { channel = array_index_nospec(channel, hdspm->max_channels_in);
if (hdspm->channel_map_in[channel] < 0) {
dev_info(hdspm->card->dev, dev_info(hdspm->card->dev,
"snd_hdspm_channel_info: input channel %d mapped out\n", "snd_hdspm_channel_info: input channel %d mapped out\n",
info->channel); channel);
return -EINVAL; return -EINVAL;
} }
info->offset = hdspm->channel_map_in[info->channel] * info->offset = hdspm->channel_map_in[channel] *
HDSPM_CHANNEL_BUFFER_BYTES; HDSPM_CHANNEL_BUFFER_BYTES;
} }

View File

@ -26,6 +26,7 @@
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/nospec.h>
#include <sound/core.h> #include <sound/core.h>
#include <sound/control.h> #include <sound/control.h>
@ -2071,9 +2072,10 @@ static int snd_rme9652_channel_info(struct snd_pcm_substream *substream,
if (snd_BUG_ON(info->channel >= RME9652_NCHANNELS)) if (snd_BUG_ON(info->channel >= RME9652_NCHANNELS))
return -EINVAL; return -EINVAL;
if ((chn = rme9652->channel_map[info->channel]) < 0) { chn = rme9652->channel_map[array_index_nospec(info->channel,
RME9652_NCHANNELS)];
if (chn < 0)
return -EINVAL; return -EINVAL;
}
info->offset = chn * RME9652_CHANNEL_BUFFER_BYTES; info->offset = chn * RME9652_CHANNEL_BUFFER_BYTES;
info->first = 0; info->first = 0;

View File

@ -43,7 +43,7 @@
#define DUAL_CHANNEL 2 #define DUAL_CHANNEL 2
static struct snd_soc_jack cz_jack; static struct snd_soc_jack cz_jack;
struct clk *da7219_dai_clk; static struct clk *da7219_dai_clk;
static int cz_da7219_init(struct snd_soc_pcm_runtime *rtd) static int cz_da7219_init(struct snd_soc_pcm_runtime *rtd)
{ {

View File

@ -502,7 +502,7 @@ static int adau17x1_hw_params(struct snd_pcm_substream *substream,
} }
if (adau->sigmadsp) { if (adau->sigmadsp) {
ret = adau17x1_setup_firmware(adau, params_rate(params)); ret = adau17x1_setup_firmware(component, params_rate(params));
if (ret < 0) if (ret < 0)
return ret; return ret;
} }
@ -835,26 +835,40 @@ bool adau17x1_volatile_register(struct device *dev, unsigned int reg)
} }
EXPORT_SYMBOL_GPL(adau17x1_volatile_register); EXPORT_SYMBOL_GPL(adau17x1_volatile_register);
int adau17x1_setup_firmware(struct adau *adau, unsigned int rate) int adau17x1_setup_firmware(struct snd_soc_component *component,
unsigned int rate)
{ {
int ret; int ret;
int dspsr; int dspsr, dsp_run;
struct adau *adau = snd_soc_component_get_drvdata(component);
struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
snd_soc_dapm_mutex_lock(dapm);
ret = regmap_read(adau->regmap, ADAU17X1_DSP_SAMPLING_RATE, &dspsr); ret = regmap_read(adau->regmap, ADAU17X1_DSP_SAMPLING_RATE, &dspsr);
if (ret) if (ret)
return ret; goto err;
ret = regmap_read(adau->regmap, ADAU17X1_DSP_RUN, &dsp_run);
if (ret)
goto err;
regmap_write(adau->regmap, ADAU17X1_DSP_ENABLE, 1); regmap_write(adau->regmap, ADAU17X1_DSP_ENABLE, 1);
regmap_write(adau->regmap, ADAU17X1_DSP_SAMPLING_RATE, 0xf); regmap_write(adau->regmap, ADAU17X1_DSP_SAMPLING_RATE, 0xf);
regmap_write(adau->regmap, ADAU17X1_DSP_RUN, 0);
ret = sigmadsp_setup(adau->sigmadsp, rate); ret = sigmadsp_setup(adau->sigmadsp, rate);
if (ret) { if (ret) {
regmap_write(adau->regmap, ADAU17X1_DSP_ENABLE, 0); regmap_write(adau->regmap, ADAU17X1_DSP_ENABLE, 0);
return ret; goto err;
} }
regmap_write(adau->regmap, ADAU17X1_DSP_SAMPLING_RATE, dspsr); regmap_write(adau->regmap, ADAU17X1_DSP_SAMPLING_RATE, dspsr);
regmap_write(adau->regmap, ADAU17X1_DSP_RUN, dsp_run);
return 0; err:
snd_soc_dapm_mutex_unlock(dapm);
return ret;
} }
EXPORT_SYMBOL_GPL(adau17x1_setup_firmware); EXPORT_SYMBOL_GPL(adau17x1_setup_firmware);

View File

@ -68,7 +68,8 @@ int adau17x1_resume(struct snd_soc_component *component);
extern const struct snd_soc_dai_ops adau17x1_dai_ops; extern const struct snd_soc_dai_ops adau17x1_dai_ops;
int adau17x1_setup_firmware(struct adau *adau, unsigned int rate); int adau17x1_setup_firmware(struct snd_soc_component *component,
unsigned int rate);
bool adau17x1_has_dsp(struct adau *adau); bool adau17x1_has_dsp(struct adau *adau);
#define ADAU17X1_CLOCK_CONTROL 0x4000 #define ADAU17X1_CLOCK_CONTROL 0x4000

View File

@ -1187,7 +1187,8 @@ static int pm8916_wcd_analog_spmi_probe(struct platform_device *pdev)
return irq; return irq;
} }
ret = devm_request_irq(dev, irq, pm8916_mbhc_switch_irq_handler, ret = devm_request_threaded_irq(dev, irq, NULL,
pm8916_mbhc_switch_irq_handler,
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
IRQF_ONESHOT, IRQF_ONESHOT,
"mbhc switch irq", priv); "mbhc switch irq", priv);
@ -1201,7 +1202,8 @@ static int pm8916_wcd_analog_spmi_probe(struct platform_device *pdev)
return irq; return irq;
} }
ret = devm_request_irq(dev, irq, mbhc_btn_press_irq_handler, ret = devm_request_threaded_irq(dev, irq, NULL,
mbhc_btn_press_irq_handler,
IRQF_TRIGGER_RISING | IRQF_TRIGGER_RISING |
IRQF_TRIGGER_FALLING | IRQF_ONESHOT, IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
"mbhc btn press irq", priv); "mbhc btn press irq", priv);
@ -1214,7 +1216,8 @@ static int pm8916_wcd_analog_spmi_probe(struct platform_device *pdev)
return irq; return irq;
} }
ret = devm_request_irq(dev, irq, mbhc_btn_release_irq_handler, ret = devm_request_threaded_irq(dev, irq, NULL,
mbhc_btn_release_irq_handler,
IRQF_TRIGGER_RISING | IRQF_TRIGGER_RISING |
IRQF_TRIGGER_FALLING | IRQF_ONESHOT, IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
"mbhc btn release irq", priv); "mbhc btn release irq", priv);

View File

@ -89,6 +89,7 @@ static const struct reg_default rt5514_reg[] = {
{RT5514_PLL3_CALIB_CTRL5, 0x40220012}, {RT5514_PLL3_CALIB_CTRL5, 0x40220012},
{RT5514_DELAY_BUF_CTRL1, 0x7fff006a}, {RT5514_DELAY_BUF_CTRL1, 0x7fff006a},
{RT5514_DELAY_BUF_CTRL3, 0x00000000}, {RT5514_DELAY_BUF_CTRL3, 0x00000000},
{RT5514_ASRC_IN_CTRL1, 0x00000003},
{RT5514_DOWNFILTER0_CTRL1, 0x00020c2f}, {RT5514_DOWNFILTER0_CTRL1, 0x00020c2f},
{RT5514_DOWNFILTER0_CTRL2, 0x00020c2f}, {RT5514_DOWNFILTER0_CTRL2, 0x00020c2f},
{RT5514_DOWNFILTER0_CTRL3, 0x10000362}, {RT5514_DOWNFILTER0_CTRL3, 0x10000362},
@ -181,6 +182,7 @@ static bool rt5514_readable_register(struct device *dev, unsigned int reg)
case RT5514_PLL3_CALIB_CTRL5: case RT5514_PLL3_CALIB_CTRL5:
case RT5514_DELAY_BUF_CTRL1: case RT5514_DELAY_BUF_CTRL1:
case RT5514_DELAY_BUF_CTRL3: case RT5514_DELAY_BUF_CTRL3:
case RT5514_ASRC_IN_CTRL1:
case RT5514_DOWNFILTER0_CTRL1: case RT5514_DOWNFILTER0_CTRL1:
case RT5514_DOWNFILTER0_CTRL2: case RT5514_DOWNFILTER0_CTRL2:
case RT5514_DOWNFILTER0_CTRL3: case RT5514_DOWNFILTER0_CTRL3:
@ -238,6 +240,7 @@ static bool rt5514_i2c_readable_register(struct device *dev,
case RT5514_DSP_MAPPING | RT5514_PLL3_CALIB_CTRL5: case RT5514_DSP_MAPPING | RT5514_PLL3_CALIB_CTRL5:
case RT5514_DSP_MAPPING | RT5514_DELAY_BUF_CTRL1: case RT5514_DSP_MAPPING | RT5514_DELAY_BUF_CTRL1:
case RT5514_DSP_MAPPING | RT5514_DELAY_BUF_CTRL3: case RT5514_DSP_MAPPING | RT5514_DELAY_BUF_CTRL3:
case RT5514_DSP_MAPPING | RT5514_ASRC_IN_CTRL1:
case RT5514_DSP_MAPPING | RT5514_DOWNFILTER0_CTRL1: case RT5514_DSP_MAPPING | RT5514_DOWNFILTER0_CTRL1:
case RT5514_DSP_MAPPING | RT5514_DOWNFILTER0_CTRL2: case RT5514_DSP_MAPPING | RT5514_DOWNFILTER0_CTRL2:
case RT5514_DSP_MAPPING | RT5514_DOWNFILTER0_CTRL3: case RT5514_DSP_MAPPING | RT5514_DOWNFILTER0_CTRL3:

View File

@ -144,6 +144,13 @@ static int fsl_esai_divisor_cal(struct snd_soc_dai *dai, bool tx, u32 ratio,
psr = ratio <= 256 * maxfp ? ESAI_xCCR_xPSR_BYPASS : ESAI_xCCR_xPSR_DIV8; psr = ratio <= 256 * maxfp ? ESAI_xCCR_xPSR_BYPASS : ESAI_xCCR_xPSR_DIV8;
/* Do not loop-search if PM (1 ~ 256) alone can serve the ratio */
if (ratio <= 256) {
pm = ratio;
fp = 1;
goto out;
}
/* Set the max fluctuation -- 0.1% of the max devisor */ /* Set the max fluctuation -- 0.1% of the max devisor */
savesub = (psr ? 1 : 8) * 256 * maxfp / 1000; savesub = (psr ? 1 : 8) * 256 * maxfp / 1000;

View File

@ -217,6 +217,7 @@ struct fsl_ssi_soc_data {
* @dai_fmt: DAI configuration this device is currently used with * @dai_fmt: DAI configuration this device is currently used with
* @streams: Mask of current active streams: BIT(TX) and BIT(RX) * @streams: Mask of current active streams: BIT(TX) and BIT(RX)
* @i2s_net: I2S and Network mode configurations of SCR register * @i2s_net: I2S and Network mode configurations of SCR register
* (this is the initial settings based on the DAI format)
* @synchronous: Use synchronous mode - both of TX and RX use STCK and SFCK * @synchronous: Use synchronous mode - both of TX and RX use STCK and SFCK
* @use_dma: DMA is used or FIQ with stream filter * @use_dma: DMA is used or FIQ with stream filter
* @use_dual_fifo: DMA with support for dual FIFO mode * @use_dual_fifo: DMA with support for dual FIFO mode
@ -829,16 +830,23 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream *substream,
} }
if (!fsl_ssi_is_ac97(ssi)) { if (!fsl_ssi_is_ac97(ssi)) {
/*
* Keep the ssi->i2s_net intact while having a local variable
* to override settings for special use cases. Otherwise, the
* ssi->i2s_net will lose the settings for regular use cases.
*/
u8 i2s_net = ssi->i2s_net;
/* Normal + Network mode to send 16-bit data in 32-bit frames */ /* Normal + Network mode to send 16-bit data in 32-bit frames */
if (fsl_ssi_is_i2s_cbm_cfs(ssi) && sample_size == 16) if (fsl_ssi_is_i2s_cbm_cfs(ssi) && sample_size == 16)
ssi->i2s_net = SSI_SCR_I2S_MODE_NORMAL | SSI_SCR_NET; i2s_net = SSI_SCR_I2S_MODE_NORMAL | SSI_SCR_NET;
/* Use Normal mode to send mono data at 1st slot of 2 slots */ /* Use Normal mode to send mono data at 1st slot of 2 slots */
if (channels == 1) if (channels == 1)
ssi->i2s_net = SSI_SCR_I2S_MODE_NORMAL; i2s_net = SSI_SCR_I2S_MODE_NORMAL;
regmap_update_bits(regs, REG_SSI_SCR, regmap_update_bits(regs, REG_SSI_SCR,
SSI_SCR_I2S_NET_MASK, ssi->i2s_net); SSI_SCR_I2S_NET_MASK, i2s_net);
} }
/* In synchronous mode, the SSI uses STCCR for capture */ /* In synchronous mode, the SSI uses STCCR for capture */

View File

@ -72,24 +72,28 @@ config SND_SOC_INTEL_BAYTRAIL
for Baytrail Chromebooks but this option is now deprecated and is for Baytrail Chromebooks but this option is now deprecated and is
not recommended, use SND_SST_ATOM_HIFI2_PLATFORM instead. not recommended, use SND_SST_ATOM_HIFI2_PLATFORM instead.
config SND_SST_ATOM_HIFI2_PLATFORM
tristate
select SND_SOC_COMPRESS
config SND_SST_ATOM_HIFI2_PLATFORM_PCI config SND_SST_ATOM_HIFI2_PLATFORM_PCI
tristate "PCI HiFi2 (Medfield, Merrifield) Platforms" tristate "PCI HiFi2 (Merrifield) Platforms"
depends on X86 && PCI depends on X86 && PCI
select SND_SST_IPC_PCI select SND_SST_IPC_PCI
select SND_SOC_COMPRESS select SND_SST_ATOM_HIFI2_PLATFORM
help help
If you have a Intel Medfield or Merrifield/Edison platform, then If you have a Intel Merrifield/Edison platform, then
enable this option by saying Y or m. Distros will typically not enable this option by saying Y or m. Distros will typically not
enable this option: Medfield devices are not available to enable this option: while Merrifield/Edison can run a mainline
developers and while Merrifield/Edison can run a mainline kernel with kernel with limited functionality it will require a firmware file
limited functionality it will require a firmware file which which is not in the standard firmware tree
is not in the standard firmware tree
config SND_SST_ATOM_HIFI2_PLATFORM config SND_SST_ATOM_HIFI2_PLATFORM_ACPI
tristate "ACPI HiFi2 (Baytrail, Cherrytrail) Platforms" tristate "ACPI HiFi2 (Baytrail, Cherrytrail) Platforms"
default ACPI
depends on X86 && ACPI depends on X86 && ACPI
select SND_SST_IPC_ACPI select SND_SST_IPC_ACPI
select SND_SOC_COMPRESS select SND_SST_ATOM_HIFI2_PLATFORM
select SND_SOC_ACPI_INTEL_MATCH select SND_SOC_ACPI_INTEL_MATCH
select IOSF_MBI select IOSF_MBI
help help

View File

@ -281,7 +281,7 @@ static int omap_dmic_dai_trigger(struct snd_pcm_substream *substream,
static int omap_dmic_select_fclk(struct omap_dmic *dmic, int clk_id, static int omap_dmic_select_fclk(struct omap_dmic *dmic, int clk_id,
unsigned int freq) unsigned int freq)
{ {
struct clk *parent_clk; struct clk *parent_clk, *mux;
char *parent_clk_name; char *parent_clk_name;
int ret = 0; int ret = 0;
@ -329,14 +329,21 @@ static int omap_dmic_select_fclk(struct omap_dmic *dmic, int clk_id,
return -ENODEV; return -ENODEV;
} }
mux = clk_get_parent(dmic->fclk);
if (IS_ERR(mux)) {
dev_err(dmic->dev, "can't get fck mux parent\n");
clk_put(parent_clk);
return -ENODEV;
}
mutex_lock(&dmic->mutex); mutex_lock(&dmic->mutex);
if (dmic->active) { if (dmic->active) {
/* disable clock while reparenting */ /* disable clock while reparenting */
pm_runtime_put_sync(dmic->dev); pm_runtime_put_sync(dmic->dev);
ret = clk_set_parent(dmic->fclk, parent_clk); ret = clk_set_parent(mux, parent_clk);
pm_runtime_get_sync(dmic->dev); pm_runtime_get_sync(dmic->dev);
} else { } else {
ret = clk_set_parent(dmic->fclk, parent_clk); ret = clk_set_parent(mux, parent_clk);
} }
mutex_unlock(&dmic->mutex); mutex_unlock(&dmic->mutex);
@ -349,6 +356,7 @@ static int omap_dmic_select_fclk(struct omap_dmic *dmic, int clk_id,
dmic->fclk_freq = freq; dmic->fclk_freq = freq;
err_busy: err_busy:
clk_put(mux);
clk_put(parent_clk); clk_put(parent_clk);
return ret; return ret;

View File

@ -1536,7 +1536,7 @@ static int rsnd_remove(struct platform_device *pdev)
return ret; return ret;
} }
static int rsnd_suspend(struct device *dev) static int __maybe_unused rsnd_suspend(struct device *dev)
{ {
struct rsnd_priv *priv = dev_get_drvdata(dev); struct rsnd_priv *priv = dev_get_drvdata(dev);
@ -1545,7 +1545,7 @@ static int rsnd_suspend(struct device *dev)
return 0; return 0;
} }
static int rsnd_resume(struct device *dev) static int __maybe_unused rsnd_resume(struct device *dev)
{ {
struct rsnd_priv *priv = dev_get_drvdata(dev); struct rsnd_priv *priv = dev_get_drvdata(dev);

View File

@ -513,7 +513,7 @@ static void remove_widget(struct snd_soc_component *comp,
*/ */
if (dobj->widget.kcontrol_type == SND_SOC_TPLG_TYPE_ENUM) { if (dobj->widget.kcontrol_type == SND_SOC_TPLG_TYPE_ENUM) {
/* enumerated widget mixer */ /* enumerated widget mixer */
for (i = 0; i < w->num_kcontrols; i++) { for (i = 0; w->kcontrols != NULL && i < w->num_kcontrols; i++) {
struct snd_kcontrol *kcontrol = w->kcontrols[i]; struct snd_kcontrol *kcontrol = w->kcontrols[i];
struct soc_enum *se = struct soc_enum *se =
(struct soc_enum *)kcontrol->private_value; (struct soc_enum *)kcontrol->private_value;
@ -530,7 +530,7 @@ static void remove_widget(struct snd_soc_component *comp,
} }
} else { } else {
/* volume mixer or bytes controls */ /* volume mixer or bytes controls */
for (i = 0; i < w->num_kcontrols; i++) { for (i = 0; w->kcontrols != NULL && i < w->num_kcontrols; i++) {
struct snd_kcontrol *kcontrol = w->kcontrols[i]; struct snd_kcontrol *kcontrol = w->kcontrols[i];
if (dobj->widget.kcontrol_type if (dobj->widget.kcontrol_type
@ -1325,8 +1325,10 @@ static struct snd_kcontrol_new *soc_tplg_dapm_widget_denum_create(
ec->hdr.name); ec->hdr.name);
kc[i].name = kstrdup(ec->hdr.name, GFP_KERNEL); kc[i].name = kstrdup(ec->hdr.name, GFP_KERNEL);
if (kc[i].name == NULL) if (kc[i].name == NULL) {
kfree(se);
goto err_se; goto err_se;
}
kc[i].private_value = (long)se; kc[i].private_value = (long)se;
kc[i].iface = SNDRV_CTL_ELEM_IFACE_MIXER; kc[i].iface = SNDRV_CTL_ELEM_IFACE_MIXER;
kc[i].access = ec->hdr.access; kc[i].access = ec->hdr.access;
@ -1442,8 +1444,10 @@ static struct snd_kcontrol_new *soc_tplg_dapm_widget_dbytes_create(
be->hdr.name, be->hdr.access); be->hdr.name, be->hdr.access);
kc[i].name = kstrdup(be->hdr.name, GFP_KERNEL); kc[i].name = kstrdup(be->hdr.name, GFP_KERNEL);
if (kc[i].name == NULL) if (kc[i].name == NULL) {
kfree(sbe);
goto err; goto err;
}
kc[i].private_value = (long)sbe; kc[i].private_value = (long)sbe;
kc[i].iface = SNDRV_CTL_ELEM_IFACE_MIXER; kc[i].iface = SNDRV_CTL_ELEM_IFACE_MIXER;
kc[i].access = be->hdr.access; kc[i].access = be->hdr.access;
@ -2576,7 +2580,7 @@ int snd_soc_tplg_component_remove(struct snd_soc_component *comp, u32 index)
/* match index */ /* match index */
if (dobj->index != index && if (dobj->index != index &&
dobj->index != SND_SOC_TPLG_INDEX_ALL) index != SND_SOC_TPLG_INDEX_ALL)
continue; continue;
switch (dobj->type) { switch (dobj->type) {

View File

@ -1776,7 +1776,8 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid,
build_feature_ctl(state, _ftr, ch_bits, control, build_feature_ctl(state, _ftr, ch_bits, control,
&iterm, unitid, ch_read_only); &iterm, unitid, ch_read_only);
if (uac_v2v3_control_is_readable(master_bits, control)) if (uac_v2v3_control_is_readable(master_bits, control))
build_feature_ctl(state, _ftr, 0, i, &iterm, unitid, build_feature_ctl(state, _ftr, 0, control,
&iterm, unitid,
!uac_v2v3_control_is_writeable(master_bits, !uac_v2v3_control_is_writeable(master_bits,
control)); control));
} }
@ -1859,7 +1860,7 @@ static int parse_audio_input_terminal(struct mixer_build *state, int unitid,
check_input_term(state, d->bTerminalID, &iterm); check_input_term(state, d->bTerminalID, &iterm);
if (state->mixer->protocol == UAC_VERSION_2) { if (state->mixer->protocol == UAC_VERSION_2) {
/* Check for jack detection. */ /* Check for jack detection. */
if (uac_v2v3_control_is_readable(d->bmControls, if (uac_v2v3_control_is_readable(le16_to_cpu(d->bmControls),
UAC2_TE_CONNECTOR)) { UAC2_TE_CONNECTOR)) {
build_connector_control(state, &iterm, true); build_connector_control(state, &iterm, true);
} }
@ -2561,7 +2562,7 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
if (err < 0 && err != -EINVAL) if (err < 0 && err != -EINVAL)
return err; return err;
if (uac_v2v3_control_is_readable(desc->bmControls, if (uac_v2v3_control_is_readable(le16_to_cpu(desc->bmControls),
UAC2_TE_CONNECTOR)) { UAC2_TE_CONNECTOR)) {
build_connector_control(&state, &state.oterm, build_connector_control(&state, &state.oterm,
false); false);

View File

@ -353,8 +353,11 @@ static struct usbmix_name_map bose_companion5_map[] = {
/* /*
* Dell usb dock with ALC4020 codec had a firmware problem where it got * Dell usb dock with ALC4020 codec had a firmware problem where it got
* screwed up when zero volume is passed; just skip it as a workaround * screwed up when zero volume is passed; just skip it as a workaround
*
* Also the extension unit gives an access error, so skip it as well.
*/ */
static const struct usbmix_name_map dell_alc4020_map[] = { static const struct usbmix_name_map dell_alc4020_map[] = {
{ 4, NULL }, /* extension unit */
{ 16, NULL }, { 16, NULL },
{ 19, NULL }, { 19, NULL },
{ 0 } { 0 }

View File

@ -349,7 +349,7 @@ snd_pcm_chmap_elem *convert_chmap_v3(struct uac3_cluster_header_descriptor
* TODO: this conversion is not complete, update it * TODO: this conversion is not complete, update it
* after adding UAC3 values to asound.h * after adding UAC3 values to asound.h
*/ */
switch (is->bChPurpose) { switch (is->bChRelationship) {
case UAC3_CH_MONO: case UAC3_CH_MONO:
map = SNDRV_CHMAP_MONO; map = SNDRV_CHMAP_MONO;
break; break;

View File

@ -139,7 +139,7 @@ static void usb_stream_hwdep_vm_open(struct vm_area_struct *area)
snd_printdd(KERN_DEBUG "%i\n", atomic_read(&us122l->mmap_count)); snd_printdd(KERN_DEBUG "%i\n", atomic_read(&us122l->mmap_count));
} }
static int usb_stream_hwdep_vm_fault(struct vm_fault *vmf) static vm_fault_t usb_stream_hwdep_vm_fault(struct vm_fault *vmf)
{ {
unsigned long offset; unsigned long offset;
struct page *page; struct page *page;

View File

@ -31,7 +31,7 @@
#include "usbusx2y.h" #include "usbusx2y.h"
#include "usX2Yhwdep.h" #include "usX2Yhwdep.h"
static int snd_us428ctls_vm_fault(struct vm_fault *vmf) static vm_fault_t snd_us428ctls_vm_fault(struct vm_fault *vmf)
{ {
unsigned long offset; unsigned long offset;
struct page * page; struct page * page;

View File

@ -652,7 +652,7 @@ static void snd_usX2Y_hwdep_pcm_vm_close(struct vm_area_struct *area)
} }
static int snd_usX2Y_hwdep_pcm_vm_fault(struct vm_fault *vmf) static vm_fault_t snd_usX2Y_hwdep_pcm_vm_fault(struct vm_fault *vmf)
{ {
unsigned long offset; unsigned long offset;
void *vaddr; void *vaddr;