Commit 750ce8cc authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull sound fixes from Takashi Iwai:
 "A collection of pending small fixes:

  ALSA core:
   - PCM memory leak fix

  ASoC:
   - Lots of SOF and Intel driver fixes
   - Addition of COMMON_CLK for wcd934x
   - Regression fixes for AMD and Tegra platforms

  HD-audio:
   - DP-MST HDMI regression fix, Tegra workarounds, HP quirk fix

  Others:
   - A few fixes relevant with the recent uapi-updates
   - Sparse warnings and endianness fixes"

* tag 'sound-fix-5.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (35 commits)
  ALSA: hda: Clear RIRB status before reading WP
  ALSA: hda/realtek - Fixed one of HP ALC671 platform Headset Mic supported
  ASoC: wcd934x: Add missing COMMON_CLK dependency to SND_SOC_ALL_CODECS
  ALSA: hda - Fix DP-MST support for NVIDIA codecs
  ASoC: wcd934x: Add missing COMMON_CLK dependency
  MAINTAINERS: Remove the Bard Liao from the MAINTAINERS of Realtek CODECs
  ASoC: tegra: Revert 24 and 32 bit support
  ASoC: SOF: Intel: add PCI ID for JasperLake
  ALSA: hdsp: Make the firmware loading ioctl a bit more readable
  ALSA: emu10k1: Fix annotation and cast for the recent uapi header change
  ALSA: dummy: Fix PCM format loop in proc output
  ALSA: usb-audio: Annotate endianess in Scarlett gen2 quirk
  ALSA: usb-audio: Fix endianess in descriptor validation
  ALSA: hda: Add JasperLake PCI ID and codec vid
  ALSA: pcm: Fix sparse warnings wrt snd_pcm_state_t
  ALSA: pcm: Fix memory leak at closing a stream without hw_free
  ALSA: uapi: Fix sparse warning
  ASoC: rt715: Add __maybe_unused to PM callbacks
  ASoC: rt711: Add __maybe_unused to PM callbacks
  ASoC: rt700: Add __maybe_unused to PM callbacks
  ...
parents 4c46bef2 6954b323
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -14106,7 +14106,6 @@ F: include/linux/platform_data/rtc-*
F:	tools/testing/selftests/rtc/
REALTEK AUDIO CODECS
M:	Bard Liao <bardliao@realtek.com>
M:	Oder Chiou <oder_chiou@realtek.com>
S:	Maintained
F:	sound/soc/codecs/rt*
+2 −2
Original line number Diff line number Diff line
@@ -1450,7 +1450,7 @@ struct snd_pcm_status64 {
#define SNDRV_PCM_IOCTL_STATUS_EXT64	_IOWR('A', 0x24, struct snd_pcm_status64)

struct snd_pcm_status32 {
	s32 state;		/* stream state */
	snd_pcm_state_t state;		/* stream state */
	s32 trigger_tstamp_sec;	/* time when stream was started/stopped/paused */
	s32 trigger_tstamp_nsec;
	s32 tstamp_sec;		/* reference timestamp */
@@ -1461,7 +1461,7 @@ struct snd_pcm_status32 {
	u32 avail;		/* number of frames available */
	u32 avail_max;		/* max frames available on hw since last status */
	u32 overrange;		/* count of ADC (capture) overrange detections from last status */
	s32 suspended_state;	/* suspended stream state */
	snd_pcm_state_t suspended_state;	/* suspended stream state */
	u32 audio_tstamp_data;	/* needed for 64-bit alignment, used for configs/report to/from userspace */
	s32 audio_tstamp_sec;	/* sample counter, wall clock, PHC or on-demand sync'ed */
	s32 audio_tstamp_nsec;
+2 −2
Original line number Diff line number Diff line
@@ -564,13 +564,13 @@ typedef char __pad_after_uframe[sizeof(__u64) - sizeof(snd_pcm_uframes_t)];
#endif

struct __snd_pcm_mmap_status64 {
	__s32 state;			/* RO: state - SNDRV_PCM_STATE_XXXX */
	snd_pcm_state_t state;		/* RO: state - SNDRV_PCM_STATE_XXXX */
	__u32 pad1;			/* Needed for 64 bit alignment */
	__pad_before_uframe __pad1;
	snd_pcm_uframes_t hw_ptr;	/* RO: hw ptr (0...boundary-1) */
	__pad_after_uframe __pad2;
	struct __snd_timespec64 tstamp;	/* Timestamp */
	__s32 suspended_state;		/* RO: suspended stream state */
	snd_pcm_state_t suspended_state;/* RO: suspended stream state */
	__u32 pad3;			/* Needed for 64 bit alignment */
	struct __snd_timespec64 audio_tstamp; /* sample counter or wall clock */
};
+4 −4
Original line number Diff line number Diff line
@@ -156,7 +156,7 @@ static int snd_pcm_channel_info_user(struct snd_pcm_substream *substream,
#endif /* CONFIG_X86_X32 */

struct compat_snd_pcm_status64 {
	s32 state;
	snd_pcm_state_t state;
	u8 rsvd[4]; /* alignment */
	s64 trigger_tstamp_sec;
	s64 trigger_tstamp_nsec;
@@ -168,7 +168,7 @@ struct compat_snd_pcm_status64 {
	u32 avail;
	u32 avail_max;
	u32 overrange;
	s32 suspended_state;
	snd_pcm_state_t suspended_state;
	u32 audio_tstamp_data;
	s64 audio_tstamp_sec;
	s64 audio_tstamp_nsec;
@@ -376,13 +376,13 @@ static int snd_pcm_ioctl_xfern_compat(struct snd_pcm_substream *substream,
#ifdef CONFIG_X86_X32
/* X32 ABI has 64bit timespec and 64bit alignment */
struct snd_pcm_mmap_status_x32 {
	s32 state;
	snd_pcm_state_t state;
	s32 pad1;
	u32 hw_ptr;
	u32 pad2; /* alignment */
	s64 tstamp_sec;
	s64 tstamp_nsec;
	s32 suspended_state;
	snd_pcm_state_t suspended_state;
	s32 pad3;
	s64 audio_tstamp_sec;
	s64 audio_tstamp_nsec;
+136 −75
Original line number Diff line number Diff line
@@ -551,7 +551,8 @@ static int period_to_usecs(struct snd_pcm_runtime *runtime)
	return usecs;
}

static void snd_pcm_set_state(struct snd_pcm_substream *substream, int state)
static void snd_pcm_set_state(struct snd_pcm_substream *substream,
			      snd_pcm_state_t state)
{
	snd_pcm_stream_lock_irq(substream);
	if (substream->runtime->status->state != SNDRV_PCM_STATE_DISCONNECTED)
@@ -786,10 +787,22 @@ static int snd_pcm_hw_params_user(struct snd_pcm_substream *substream,
	return err;
}

static int do_hw_free(struct snd_pcm_substream *substream)
{
	int result = 0;

	snd_pcm_sync_stop(substream);
	if (substream->ops->hw_free)
		result = substream->ops->hw_free(substream);
	if (substream->managed_buffer_alloc)
		snd_pcm_lib_free_pages(substream);
	return result;
}

static int snd_pcm_hw_free(struct snd_pcm_substream *substream)
{
	struct snd_pcm_runtime *runtime;
	int result = 0;
	int result;

	if (PCM_RUNTIME_CHECK(substream))
		return -ENXIO;
@@ -806,11 +819,7 @@ static int snd_pcm_hw_free(struct snd_pcm_substream *substream)
	snd_pcm_stream_unlock_irq(substream);
	if (atomic_read(&substream->mmap_count))
		return -EBADFD;
	snd_pcm_sync_stop(substream);
	if (substream->ops->hw_free)
		result = substream->ops->hw_free(substream);
	if (substream->managed_buffer_alloc)
		snd_pcm_lib_free_pages(substream);
	result = do_hw_free(substream);
	snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN);
	pm_qos_remove_request(&substream->latency_pm_qos_req);
	return result;
@@ -1097,11 +1106,17 @@ static void snd_pcm_trigger_tstamp(struct snd_pcm_substream *substream)
	runtime->trigger_master = NULL;
}

#define ACTION_ARG_IGNORE	(__force snd_pcm_state_t)0

struct action_ops {
	int (*pre_action)(struct snd_pcm_substream *substream, int state);
	int (*do_action)(struct snd_pcm_substream *substream, int state);
	void (*undo_action)(struct snd_pcm_substream *substream, int state);
	void (*post_action)(struct snd_pcm_substream *substream, int state);
	int (*pre_action)(struct snd_pcm_substream *substream,
			  snd_pcm_state_t state);
	int (*do_action)(struct snd_pcm_substream *substream,
			 snd_pcm_state_t state);
	void (*undo_action)(struct snd_pcm_substream *substream,
			    snd_pcm_state_t state);
	void (*post_action)(struct snd_pcm_substream *substream,
			    snd_pcm_state_t state);
};

/*
@@ -1111,7 +1126,8 @@ struct action_ops {
 */
static int snd_pcm_action_group(const struct action_ops *ops,
				struct snd_pcm_substream *substream,
				int state, int do_lock)
				snd_pcm_state_t state,
				bool do_lock)
{
	struct snd_pcm_substream *s = NULL;
	struct snd_pcm_substream *s1;
@@ -1168,7 +1184,7 @@ static int snd_pcm_action_group(const struct action_ops *ops,
 */
static int snd_pcm_action_single(const struct action_ops *ops,
				 struct snd_pcm_substream *substream,
				 int state)
				 snd_pcm_state_t state)
{
	int res;
	
@@ -1249,14 +1265,14 @@ snd_pcm_stream_group_ref(struct snd_pcm_substream *substream)
 */
static int snd_pcm_action(const struct action_ops *ops,
			  struct snd_pcm_substream *substream,
			  int state)
			  snd_pcm_state_t state)
{
	struct snd_pcm_group *group;
	int res;

	group = snd_pcm_stream_group_ref(substream);
	if (group)
		res = snd_pcm_action_group(ops, substream, state, 1);
		res = snd_pcm_action_group(ops, substream, state, true);
	else
		res = snd_pcm_action_single(ops, substream, state);
	snd_pcm_group_unref(group, substream);
@@ -1268,7 +1284,7 @@ static int snd_pcm_action(const struct action_ops *ops,
 */
static int snd_pcm_action_lock_irq(const struct action_ops *ops,
				   struct snd_pcm_substream *substream,
				   int state)
				   snd_pcm_state_t state)
{
	int res;

@@ -1282,14 +1298,14 @@ static int snd_pcm_action_lock_irq(const struct action_ops *ops,
 */
static int snd_pcm_action_nonatomic(const struct action_ops *ops,
				    struct snd_pcm_substream *substream,
				    int state)
				    snd_pcm_state_t state)
{
	int res;

	/* Guarantee the group members won't change during non-atomic action */
	down_read(&snd_pcm_link_rwsem);
	if (snd_pcm_stream_linked(substream))
		res = snd_pcm_action_group(ops, substream, state, 0);
		res = snd_pcm_action_group(ops, substream, state, false);
	else
		res = snd_pcm_action_single(ops, substream, state);
	up_read(&snd_pcm_link_rwsem);
@@ -1299,7 +1315,8 @@ static int snd_pcm_action_nonatomic(const struct action_ops *ops,
/*
 * start callbacks
 */
static int snd_pcm_pre_start(struct snd_pcm_substream *substream, int state)
static int snd_pcm_pre_start(struct snd_pcm_substream *substream,
			     snd_pcm_state_t state)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	if (runtime->status->state != SNDRV_PCM_STATE_PREPARED)
@@ -1312,20 +1329,23 @@ static int snd_pcm_pre_start(struct snd_pcm_substream *substream, int state)
	return 0;
}

static int snd_pcm_do_start(struct snd_pcm_substream *substream, int state)
static int snd_pcm_do_start(struct snd_pcm_substream *substream,
			    snd_pcm_state_t state)
{
	if (substream->runtime->trigger_master != substream)
		return 0;
	return substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_START);
}

static void snd_pcm_undo_start(struct snd_pcm_substream *substream, int state)
static void snd_pcm_undo_start(struct snd_pcm_substream *substream,
			       snd_pcm_state_t state)
{
	if (substream->runtime->trigger_master == substream)
		substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_STOP);
}

static void snd_pcm_post_start(struct snd_pcm_substream *substream, int state)
static void snd_pcm_post_start(struct snd_pcm_substream *substream,
			       snd_pcm_state_t state)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	snd_pcm_trigger_tstamp(substream);
@@ -1369,7 +1389,8 @@ static int snd_pcm_start_lock_irq(struct snd_pcm_substream *substream)
/*
 * stop callbacks
 */
static int snd_pcm_pre_stop(struct snd_pcm_substream *substream, int state)
static int snd_pcm_pre_stop(struct snd_pcm_substream *substream,
			    snd_pcm_state_t state)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
@@ -1378,7 +1399,8 @@ static int snd_pcm_pre_stop(struct snd_pcm_substream *substream, int state)
	return 0;
}

static int snd_pcm_do_stop(struct snd_pcm_substream *substream, int state)
static int snd_pcm_do_stop(struct snd_pcm_substream *substream,
			   snd_pcm_state_t state)
{
	if (substream->runtime->trigger_master == substream &&
	    snd_pcm_running(substream))
@@ -1386,7 +1408,8 @@ static int snd_pcm_do_stop(struct snd_pcm_substream *substream, int state)
	return 0; /* unconditonally stop all substreams */
}

static void snd_pcm_post_stop(struct snd_pcm_substream *substream, int state)
static void snd_pcm_post_stop(struct snd_pcm_substream *substream,
			      snd_pcm_state_t state)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	if (runtime->status->state != state) {
@@ -1457,14 +1480,17 @@ int snd_pcm_stop_xrun(struct snd_pcm_substream *substream)
EXPORT_SYMBOL_GPL(snd_pcm_stop_xrun);

/*
 * pause callbacks
 * pause callbacks: pass boolean (to start pause or resume) as state argument
 */
static int snd_pcm_pre_pause(struct snd_pcm_substream *substream, int push)
#define pause_pushed(state)	(__force bool)(state)

static int snd_pcm_pre_pause(struct snd_pcm_substream *substream,
			     snd_pcm_state_t state)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	if (!(runtime->info & SNDRV_PCM_INFO_PAUSE))
		return -ENOSYS;
	if (push) {
	if (pause_pushed(state)) {
		if (runtime->status->state != SNDRV_PCM_STATE_RUNNING)
			return -EBADFD;
	} else if (runtime->status->state != SNDRV_PCM_STATE_PAUSED)
@@ -1473,13 +1499,14 @@ static int snd_pcm_pre_pause(struct snd_pcm_substream *substream, int push)
	return 0;
}

static int snd_pcm_do_pause(struct snd_pcm_substream *substream, int push)
static int snd_pcm_do_pause(struct snd_pcm_substream *substream,
			    snd_pcm_state_t state)
{
	if (substream->runtime->trigger_master != substream)
		return 0;
	/* some drivers might use hw_ptr to recover from the pause -
	   update the hw_ptr now */
	if (push)
	if (pause_pushed(state))
		snd_pcm_update_hw_ptr(substream);
	/* The jiffies check in snd_pcm_update_hw_ptr*() is done by
	 * a delta between the current jiffies, this gives a large enough
@@ -1487,23 +1514,27 @@ static int snd_pcm_do_pause(struct snd_pcm_substream *substream, int push)
	 */
	substream->runtime->hw_ptr_jiffies = jiffies - HZ * 1000;
	return substream->ops->trigger(substream,
				       push ? SNDRV_PCM_TRIGGER_PAUSE_PUSH :
				       pause_pushed(state) ?
				       SNDRV_PCM_TRIGGER_PAUSE_PUSH :
				       SNDRV_PCM_TRIGGER_PAUSE_RELEASE);
}

static void snd_pcm_undo_pause(struct snd_pcm_substream *substream, int push)
static void snd_pcm_undo_pause(struct snd_pcm_substream *substream,
			       snd_pcm_state_t state)
{
	if (substream->runtime->trigger_master == substream)
		substream->ops->trigger(substream,
					push ? SNDRV_PCM_TRIGGER_PAUSE_RELEASE :
					pause_pushed(state) ?
					SNDRV_PCM_TRIGGER_PAUSE_RELEASE :
					SNDRV_PCM_TRIGGER_PAUSE_PUSH);
}

static void snd_pcm_post_pause(struct snd_pcm_substream *substream, int push)
static void snd_pcm_post_pause(struct snd_pcm_substream *substream,
			       snd_pcm_state_t state)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	snd_pcm_trigger_tstamp(substream);
	if (push) {
	if (pause_pushed(state)) {
		runtime->status->state = SNDRV_PCM_STATE_PAUSED;
		snd_pcm_timer_notify(substream, SNDRV_TIMER_EVENT_MPAUSE);
		wake_up(&runtime->sleep);
@@ -1524,15 +1555,24 @@ static const struct action_ops snd_pcm_action_pause = {
/*
 * Push/release the pause for all linked streams.
 */
static int snd_pcm_pause(struct snd_pcm_substream *substream, int push)
static int snd_pcm_pause(struct snd_pcm_substream *substream, bool push)
{
	return snd_pcm_action(&snd_pcm_action_pause, substream,
			      (__force snd_pcm_state_t)push);
}

static int snd_pcm_pause_lock_irq(struct snd_pcm_substream *substream,
				  bool push)
{
	return snd_pcm_action(&snd_pcm_action_pause, substream, push);
	return snd_pcm_action_lock_irq(&snd_pcm_action_pause, substream,
				       (__force snd_pcm_state_t)push);
}

#ifdef CONFIG_PM
/* suspend */
/* suspend callback: state argument ignored */

static int snd_pcm_pre_suspend(struct snd_pcm_substream *substream, int state)
static int snd_pcm_pre_suspend(struct snd_pcm_substream *substream,
			       snd_pcm_state_t state)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	switch (runtime->status->state) {
@@ -1548,7 +1588,8 @@ static int snd_pcm_pre_suspend(struct snd_pcm_substream *substream, int state)
	return 0;
}

static int snd_pcm_do_suspend(struct snd_pcm_substream *substream, int state)
static int snd_pcm_do_suspend(struct snd_pcm_substream *substream,
			      snd_pcm_state_t state)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	if (runtime->trigger_master != substream)
@@ -1559,7 +1600,8 @@ static int snd_pcm_do_suspend(struct snd_pcm_substream *substream, int state)
	return 0; /* suspend unconditionally */
}

static void snd_pcm_post_suspend(struct snd_pcm_substream *substream, int state)
static void snd_pcm_post_suspend(struct snd_pcm_substream *substream,
				 snd_pcm_state_t state)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	snd_pcm_trigger_tstamp(substream);
@@ -1590,7 +1632,8 @@ static int snd_pcm_suspend(struct snd_pcm_substream *substream)
	unsigned long flags;

	snd_pcm_stream_lock_irqsave(substream, flags);
	err = snd_pcm_action(&snd_pcm_action_suspend, substream, 0);
	err = snd_pcm_action(&snd_pcm_action_suspend, substream,
			     ACTION_ARG_IGNORE);
	snd_pcm_stream_unlock_irqrestore(substream, flags);
	return err;
}
@@ -1634,9 +1677,10 @@ int snd_pcm_suspend_all(struct snd_pcm *pcm)
}
EXPORT_SYMBOL(snd_pcm_suspend_all);

/* resume */
/* resume callbacks: state argument ignored */

static int snd_pcm_pre_resume(struct snd_pcm_substream *substream, int state)
static int snd_pcm_pre_resume(struct snd_pcm_substream *substream,
			      snd_pcm_state_t state)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	if (!(runtime->info & SNDRV_PCM_INFO_RESUME))
@@ -1645,7 +1689,8 @@ static int snd_pcm_pre_resume(struct snd_pcm_substream *substream, int state)
	return 0;
}

static int snd_pcm_do_resume(struct snd_pcm_substream *substream, int state)
static int snd_pcm_do_resume(struct snd_pcm_substream *substream,
			     snd_pcm_state_t state)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	if (runtime->trigger_master != substream)
@@ -1658,14 +1703,16 @@ static int snd_pcm_do_resume(struct snd_pcm_substream *substream, int state)
	return substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_RESUME);
}

static void snd_pcm_undo_resume(struct snd_pcm_substream *substream, int state)
static void snd_pcm_undo_resume(struct snd_pcm_substream *substream,
				snd_pcm_state_t state)
{
	if (substream->runtime->trigger_master == substream &&
	    snd_pcm_running(substream))
		substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_SUSPEND);
}

static void snd_pcm_post_resume(struct snd_pcm_substream *substream, int state)
static void snd_pcm_post_resume(struct snd_pcm_substream *substream,
				snd_pcm_state_t state)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	snd_pcm_trigger_tstamp(substream);
@@ -1683,7 +1730,8 @@ static const struct action_ops snd_pcm_action_resume = {

static int snd_pcm_resume(struct snd_pcm_substream *substream)
{
	return snd_pcm_action_lock_irq(&snd_pcm_action_resume, substream, 0);
	return snd_pcm_action_lock_irq(&snd_pcm_action_resume, substream,
				       ACTION_ARG_IGNORE);
}

#else
@@ -1724,7 +1772,9 @@ static int snd_pcm_xrun(struct snd_pcm_substream *substream)
/*
 * reset ioctl
 */
static int snd_pcm_pre_reset(struct snd_pcm_substream *substream, int state)
/* reset callbacks:  state argument ignored */
static int snd_pcm_pre_reset(struct snd_pcm_substream *substream,
			     snd_pcm_state_t state)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	switch (runtime->status->state) {
@@ -1738,7 +1788,8 @@ static int snd_pcm_pre_reset(struct snd_pcm_substream *substream, int state)
	}
}

static int snd_pcm_do_reset(struct snd_pcm_substream *substream, int state)
static int snd_pcm_do_reset(struct snd_pcm_substream *substream,
			    snd_pcm_state_t state)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	int err = snd_pcm_ops_ioctl(substream, SNDRV_PCM_IOCTL1_RESET, NULL);
@@ -1752,7 +1803,8 @@ static int snd_pcm_do_reset(struct snd_pcm_substream *substream, int state)
	return 0;
}

static void snd_pcm_post_reset(struct snd_pcm_substream *substream, int state)
static void snd_pcm_post_reset(struct snd_pcm_substream *substream,
			       snd_pcm_state_t state)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	runtime->control->appl_ptr = runtime->status->hw_ptr;
@@ -1769,17 +1821,20 @@ static const struct action_ops snd_pcm_action_reset = {

static int snd_pcm_reset(struct snd_pcm_substream *substream)
{
	return snd_pcm_action_nonatomic(&snd_pcm_action_reset, substream, 0);
	return snd_pcm_action_nonatomic(&snd_pcm_action_reset, substream,
					ACTION_ARG_IGNORE);
}

/*
 * prepare ioctl
 */
/* we use the second argument for updating f_flags */
/* pass f_flags as state argument */
static int snd_pcm_pre_prepare(struct snd_pcm_substream *substream,
			       int f_flags)
			       snd_pcm_state_t state)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	int f_flags = (__force int)state;

	if (runtime->status->state == SNDRV_PCM_STATE_OPEN ||
	    runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED)
		return -EBADFD;
@@ -1789,17 +1844,19 @@ static int snd_pcm_pre_prepare(struct snd_pcm_substream *substream,
	return 0;
}

static int snd_pcm_do_prepare(struct snd_pcm_substream *substream, int state)
static int snd_pcm_do_prepare(struct snd_pcm_substream *substream,
			      snd_pcm_state_t state)
{
	int err;
	snd_pcm_sync_stop(substream);
	err = substream->ops->prepare(substream);
	if (err < 0)
		return err;
	return snd_pcm_do_reset(substream, 0);
	return snd_pcm_do_reset(substream, state);
}

static void snd_pcm_post_prepare(struct snd_pcm_substream *substream, int state)
static void snd_pcm_post_prepare(struct snd_pcm_substream *substream,
				 snd_pcm_state_t state)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	runtime->control->appl_ptr = runtime->status->hw_ptr;
@@ -1832,7 +1889,7 @@ static int snd_pcm_prepare(struct snd_pcm_substream *substream,
	snd_pcm_stream_lock_irq(substream);
	switch (substream->runtime->status->state) {
	case SNDRV_PCM_STATE_PAUSED:
		snd_pcm_pause(substream, 0);
		snd_pcm_pause(substream, false);
		/* fallthru */
	case SNDRV_PCM_STATE_SUSPENDED:
		snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
@@ -1841,14 +1898,17 @@ static int snd_pcm_prepare(struct snd_pcm_substream *substream,
	snd_pcm_stream_unlock_irq(substream);

	return snd_pcm_action_nonatomic(&snd_pcm_action_prepare,
					substream, f_flags);
					substream,
					(__force snd_pcm_state_t)f_flags);
}

/*
 * drain ioctl
 */

static int snd_pcm_pre_drain_init(struct snd_pcm_substream *substream, int state)
/* drain init callbacks: state argument ignored */
static int snd_pcm_pre_drain_init(struct snd_pcm_substream *substream,
				  snd_pcm_state_t state)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	switch (runtime->status->state) {
@@ -1861,7 +1921,8 @@ static int snd_pcm_pre_drain_init(struct snd_pcm_substream *substream, int state
	return 0;
}

static int snd_pcm_do_drain_init(struct snd_pcm_substream *substream, int state)
static int snd_pcm_do_drain_init(struct snd_pcm_substream *substream,
				 snd_pcm_state_t state)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
@@ -1887,7 +1948,9 @@ static int snd_pcm_do_drain_init(struct snd_pcm_substream *substream, int state)
	} else {
		/* stop running stream */
		if (runtime->status->state == SNDRV_PCM_STATE_RUNNING) {
			int new_state = snd_pcm_capture_avail(runtime) > 0 ?
			snd_pcm_state_t new_state;

			new_state = snd_pcm_capture_avail(runtime) > 0 ?
				SNDRV_PCM_STATE_DRAINING : SNDRV_PCM_STATE_SETUP;
			snd_pcm_do_stop(substream, new_state);
			snd_pcm_post_stop(substream, new_state);
@@ -1903,7 +1966,8 @@ static int snd_pcm_do_drain_init(struct snd_pcm_substream *substream, int state)
	return 0;
}

static void snd_pcm_post_drain_init(struct snd_pcm_substream *substream, int state)
static void snd_pcm_post_drain_init(struct snd_pcm_substream *substream,
				    snd_pcm_state_t state)
{
}

@@ -1946,10 +2010,11 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,
	snd_pcm_stream_lock_irq(substream);
	/* resume pause */
	if (runtime->status->state == SNDRV_PCM_STATE_PAUSED)
		snd_pcm_pause(substream, 0);
		snd_pcm_pause(substream, false);

	/* pre-start/stop - all running streams are changed to DRAINING state */
	result = snd_pcm_action(&snd_pcm_action_drain_init, substream, 0);
	result = snd_pcm_action(&snd_pcm_action_drain_init, substream,
				ACTION_ARG_IGNORE);
	if (result < 0)
		goto unlock;
	/* in non-blocking, we don't wait in ioctl but let caller poll */
@@ -2050,7 +2115,7 @@ static int snd_pcm_drop(struct snd_pcm_substream *substream)
	snd_pcm_stream_lock_irq(substream);
	/* resume pause */
	if (runtime->status->state == SNDRV_PCM_STATE_PAUSED)
		snd_pcm_pause(substream, 0);
		snd_pcm_pause(substream, false);

	snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
	/* runtime->control->appl_ptr = runtime->status->hw_ptr; */
@@ -2529,9 +2594,7 @@ void snd_pcm_release_substream(struct snd_pcm_substream *substream)

	snd_pcm_drop(substream);
	if (substream->hw_opened) {
		if (substream->ops->hw_free &&
		    substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
			substream->ops->hw_free(substream);
		do_hw_free(substream);
		substream->ops->close(substream);
		substream->hw_opened = 0;
	}
@@ -2894,12 +2957,12 @@ static int snd_pcm_sync_ptr(struct snd_pcm_substream *substream,
}

struct snd_pcm_mmap_status32 {
	s32 state;
	snd_pcm_state_t state;
	s32 pad1;
	u32 hw_ptr;
	s32 tstamp_sec;
	s32 tstamp_nsec;
	s32 suspended_state;
	snd_pcm_state_t suspended_state;
	s32 audio_tstamp_sec;
	s32 audio_tstamp_nsec;
} __attribute__((packed));
@@ -3177,9 +3240,7 @@ static int snd_pcm_common_ioctl(struct file *file,
	case SNDRV_PCM_IOCTL_DROP:
		return snd_pcm_drop(substream);
	case SNDRV_PCM_IOCTL_PAUSE:
		return snd_pcm_action_lock_irq(&snd_pcm_action_pause,
					       substream,
					       (int)(unsigned long)arg);
		return snd_pcm_pause_lock_irq(substream, (unsigned long)arg);
	case SNDRV_PCM_IOCTL_WRITEI_FRAMES:
	case SNDRV_PCM_IOCTL_READI_FRAMES:
		return snd_pcm_xferi_frames_ioctl(substream, arg);
Loading