Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0eee62e0 authored by Takashi Iwai's avatar Takashi Iwai
Browse files

Merge branch 'topic/pcm-internal' into for-next

parents 8d085d3c b2022138
Loading
Loading
Loading
Loading
+41 −51
Original line number Original line Diff line number Diff line
@@ -49,8 +49,6 @@ static struct snd_pcm *snd_pcm_get(struct snd_card *card, int device)
	struct snd_pcm *pcm;
	struct snd_pcm *pcm;


	list_for_each_entry(pcm, &snd_pcm_devices, list) {
	list_for_each_entry(pcm, &snd_pcm_devices, list) {
		if (pcm->internal)
			continue;
		if (pcm->card == card && pcm->device == device)
		if (pcm->card == card && pcm->device == device)
			return pcm;
			return pcm;
	}
	}
@@ -62,8 +60,6 @@ static int snd_pcm_next(struct snd_card *card, int device)
	struct snd_pcm *pcm;
	struct snd_pcm *pcm;


	list_for_each_entry(pcm, &snd_pcm_devices, list) {
	list_for_each_entry(pcm, &snd_pcm_devices, list) {
		if (pcm->internal)
			continue;
		if (pcm->card == card && pcm->device > device)
		if (pcm->card == card && pcm->device > device)
			return pcm->device;
			return pcm->device;
		else if (pcm->card->number > card->number)
		else if (pcm->card->number > card->number)
@@ -76,6 +72,9 @@ static int snd_pcm_add(struct snd_pcm *newpcm)
{
{
	struct snd_pcm *pcm;
	struct snd_pcm *pcm;


	if (newpcm->internal)
		return 0;

	list_for_each_entry(pcm, &snd_pcm_devices, list) {
	list_for_each_entry(pcm, &snd_pcm_devices, list) {
		if (pcm->card == newpcm->card && pcm->device == newpcm->device)
		if (pcm->card == newpcm->card && pcm->device == newpcm->device)
			return -EBUSY;
			return -EBUSY;
@@ -782,6 +781,9 @@ static int _snd_pcm_new(struct snd_card *card, const char *id, int device,
	pcm->card = card;
	pcm->card = card;
	pcm->device = device;
	pcm->device = device;
	pcm->internal = internal;
	pcm->internal = internal;
	mutex_init(&pcm->open_mutex);
	init_waitqueue_head(&pcm->open_wait);
	INIT_LIST_HEAD(&pcm->list);
	if (id)
	if (id)
		strlcpy(pcm->id, id, sizeof(pcm->id));
		strlcpy(pcm->id, id, sizeof(pcm->id));
	if ((err = snd_pcm_new_stream(pcm, SNDRV_PCM_STREAM_PLAYBACK, playback_count)) < 0) {
	if ((err = snd_pcm_new_stream(pcm, SNDRV_PCM_STREAM_PLAYBACK, playback_count)) < 0) {
@@ -792,8 +794,6 @@ static int _snd_pcm_new(struct snd_card *card, const char *id, int device,
		snd_pcm_free(pcm);
		snd_pcm_free(pcm);
		return err;
		return err;
	}
	}
	mutex_init(&pcm->open_mutex);
	init_waitqueue_head(&pcm->open_wait);
	if ((err = snd_device_new(card, SNDRV_DEV_PCM, pcm, &ops)) < 0) {
	if ((err = snd_device_new(card, SNDRV_DEV_PCM, pcm, &ops)) < 0) {
		snd_pcm_free(pcm);
		snd_pcm_free(pcm);
		return err;
		return err;
@@ -888,7 +888,8 @@ static int snd_pcm_free(struct snd_pcm *pcm)


	if (!pcm)
	if (!pcm)
		return 0;
		return 0;
	list_for_each_entry(notify, &snd_pcm_notify_list, list) {
	if (!pcm->internal) {
		list_for_each_entry(notify, &snd_pcm_notify_list, list)
			notify->n_unregister(pcm);
			notify->n_unregister(pcm);
	}
	}
	if (pcm->private_free)
	if (pcm->private_free)
@@ -919,6 +920,9 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,


	if (snd_BUG_ON(!pcm || !rsubstream))
	if (snd_BUG_ON(!pcm || !rsubstream))
		return -ENXIO;
		return -ENXIO;
	if (snd_BUG_ON(stream != SNDRV_PCM_STREAM_PLAYBACK &&
		       stream != SNDRV_PCM_STREAM_CAPTURE))
		return -EINVAL;
	*rsubstream = NULL;
	*rsubstream = NULL;
	pstr = &pcm->streams[stream];
	pstr = &pcm->streams[stream];
	if (pstr->substream == NULL || pstr->substream_count == 0)
	if (pstr->substream == NULL || pstr->substream_count == 0)
@@ -927,26 +931,15 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,
	card = pcm->card;
	card = pcm->card;
	prefer_subdevice = snd_ctl_get_preferred_subdevice(card, SND_CTL_SUBDEV_PCM);
	prefer_subdevice = snd_ctl_get_preferred_subdevice(card, SND_CTL_SUBDEV_PCM);


	switch (stream) {
	case SNDRV_PCM_STREAM_PLAYBACK:
		if (pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX) {
			for (substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; substream; substream = substream->next) {
				if (SUBSTREAM_BUSY(substream))
					return -EAGAIN;
			}
		}
		break;
	case SNDRV_PCM_STREAM_CAPTURE:
	if (pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX) {
	if (pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX) {
			for (substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; substream; substream = substream->next) {
		int opposite = !stream;

		for (substream = pcm->streams[opposite].substream; substream;
		     substream = substream->next) {
			if (SUBSTREAM_BUSY(substream))
			if (SUBSTREAM_BUSY(substream))
				return -EAGAIN;
				return -EAGAIN;
		}
		}
	}
	}
		break;
	default:
		return -EINVAL;
	}


	if (file->f_flags & O_APPEND) {
	if (file->f_flags & O_APPEND) {
		if (prefer_subdevice < 0) {
		if (prefer_subdevice < 0) {
@@ -968,15 +961,12 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,
		return 0;
		return 0;
	}
	}


	if (prefer_subdevice >= 0) {
	for (substream = pstr->substream; substream; substream = substream->next) {
		for (substream = pstr->substream; substream; substream = substream->next)
		if (!SUBSTREAM_BUSY(substream) &&
			if (!SUBSTREAM_BUSY(substream) && substream->number == prefer_subdevice)
		    (prefer_subdevice == -1 ||
				goto __ok;
		     substream->number == prefer_subdevice))
	}
	for (substream = pstr->substream; substream; substream = substream->next)
		if (!SUBSTREAM_BUSY(substream))
			break;
			break;
      __ok:
	}
	if (substream == NULL)
	if (substream == NULL)
		return -EAGAIN;
		return -EAGAIN;


@@ -1086,15 +1076,16 @@ static int snd_pcm_dev_register(struct snd_device *device)
	if (snd_BUG_ON(!device || !device->device_data))
	if (snd_BUG_ON(!device || !device->device_data))
		return -ENXIO;
		return -ENXIO;
	pcm = device->device_data;
	pcm = device->device_data;
	if (pcm->internal)
		return 0;

	mutex_lock(&register_mutex);
	mutex_lock(&register_mutex);
	err = snd_pcm_add(pcm);
	err = snd_pcm_add(pcm);
	if (err) {
	if (err)
		mutex_unlock(&register_mutex);
		goto unlock;
		return err;
	}
	for (cidx = 0; cidx < 2; cidx++) {
	for (cidx = 0; cidx < 2; cidx++) {
		int devtype = -1;
		int devtype = -1;
		if (pcm->streams[cidx].substream == NULL || pcm->internal)
		if (pcm->streams[cidx].substream == NULL)
			continue;
			continue;
		switch (cidx) {
		switch (cidx) {
		case SNDRV_PCM_STREAM_PLAYBACK:
		case SNDRV_PCM_STREAM_PLAYBACK:
@@ -1109,9 +1100,8 @@ static int snd_pcm_dev_register(struct snd_device *device)
					  &snd_pcm_f_ops[cidx], pcm,
					  &snd_pcm_f_ops[cidx], pcm,
					  &pcm->streams[cidx].dev);
					  &pcm->streams[cidx].dev);
		if (err < 0) {
		if (err < 0) {
			list_del(&pcm->list);
			list_del_init(&pcm->list);
			mutex_unlock(&register_mutex);
			goto unlock;
			return err;
		}
		}


		for (substream = pcm->streams[cidx].substream; substream; substream = substream->next)
		for (substream = pcm->streams[cidx].substream; substream; substream = substream->next)
@@ -1121,8 +1111,9 @@ static int snd_pcm_dev_register(struct snd_device *device)
	list_for_each_entry(notify, &snd_pcm_notify_list, list)
	list_for_each_entry(notify, &snd_pcm_notify_list, list)
		notify->n_register(pcm);
		notify->n_register(pcm);


 unlock:
	mutex_unlock(&register_mutex);
	mutex_unlock(&register_mutex);
	return 0;
	return err;
}
}


static int snd_pcm_dev_disconnect(struct snd_device *device)
static int snd_pcm_dev_disconnect(struct snd_device *device)
@@ -1133,13 +1124,10 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)
	int cidx;
	int cidx;


	mutex_lock(&register_mutex);
	mutex_lock(&register_mutex);
	if (list_empty(&pcm->list))
		goto unlock;

	mutex_lock(&pcm->open_mutex);
	mutex_lock(&pcm->open_mutex);
	wake_up(&pcm->open_wait);
	wake_up(&pcm->open_wait);
	list_del_init(&pcm->list);
	list_del_init(&pcm->list);
	for (cidx = 0; cidx < 2; cidx++)
	for (cidx = 0; cidx < 2; cidx++) {
		for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) {
		for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) {
			snd_pcm_stream_lock_irq(substream);
			snd_pcm_stream_lock_irq(substream);
			if (substream->runtime) {
			if (substream->runtime) {
@@ -1149,10 +1137,13 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)
			}
			}
			snd_pcm_stream_unlock_irq(substream);
			snd_pcm_stream_unlock_irq(substream);
		}
		}
	list_for_each_entry(notify, &snd_pcm_notify_list, list) {
	}
	if (!pcm->internal) {
		list_for_each_entry(notify, &snd_pcm_notify_list, list)
			notify->n_disconnect(pcm);
			notify->n_disconnect(pcm);
	}
	}
	for (cidx = 0; cidx < 2; cidx++) {
	for (cidx = 0; cidx < 2; cidx++) {
		if (!pcm->internal)
			snd_unregister_device(&pcm->streams[cidx].dev);
			snd_unregister_device(&pcm->streams[cidx].dev);
		if (pcm->streams[cidx].chmap_kctl) {
		if (pcm->streams[cidx].chmap_kctl) {
			snd_ctl_remove(pcm->card, pcm->streams[cidx].chmap_kctl);
			snd_ctl_remove(pcm->card, pcm->streams[cidx].chmap_kctl);
@@ -1160,7 +1151,6 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)
		}
		}
	}
	}
	mutex_unlock(&pcm->open_mutex);
	mutex_unlock(&pcm->open_mutex);
 unlock:
	mutex_unlock(&register_mutex);
	mutex_unlock(&register_mutex);
	return 0;
	return 0;
}
}