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, 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 ok | EPOLLERR;

	runtime = substream->runtime;
	if (runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED)
		return ok | EPOLLERR;

	poll_wait(file, &runtime->sleep, wait);

	mask = 0;
	snd_pcm_stream_lock_irq(substream);
	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 = ok;
		break;
	case SNDRV_PCM_STATE_DRAINING:
		if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
			mask = ok;
			if (!avail)
				mask |= EPOLLERR;
		}
		break;
	default:
		mask = ok | EPOLLERR;
		break;
	}
	snd_pcm_stream_unlock_irq(substream);
	return mask;
}
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, 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 ok | EPOLLERR;

	runtime = substream->runtime;
	if (runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED)
		return ok | EPOLLERR;

	poll_wait(file, &runtime->sleep, wait);

	mask = 0;
	snd_pcm_stream_lock_irq(substream);
	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 = ok;
		break;
	case SNDRV_PCM_STATE_DRAINING:
		if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
			mask = ok;
			if (!avail)
				mask |= EPOLLERR;
		}
		break;
	default:
		mask = ok | EPOLLERR;
		break;
	}
	snd_pcm_stream_unlock_irq(substream);
	return mask;
}