static int audio_probe_channel()

in most_snd.c [511:607]


static int audio_probe_channel(struct most_interface *iface, int channel_id,
			       struct most_channel_config *cfg,
			       char *device_name, char *arg_list)
{
	struct channel *channel;
	struct sound_adapter *adpt;
	struct snd_pcm *pcm;
	int playback_count = 0;
	int capture_count = 0;
	int ret;
	int direction;
	u16 ch_num;
	char *sample_res;
	char arg_list_cpy[STRING_SIZE];

	if (cfg->data_type != MOST_CH_SYNC) {
		pr_err("Incompatible channel type\n");
		return -EINVAL;
	}
	strscpy(arg_list_cpy, arg_list, STRING_SIZE);
	ret = split_arg_list(arg_list_cpy, &ch_num, &sample_res);
	if (ret < 0)
		return ret;

	list_for_each_entry(adpt, &adpt_list, list) {
		if (adpt->iface != iface)
			continue;
		if (adpt->registered)
			return -ENOSPC;
		adpt->pcm_dev_idx++;
		goto skip_adpt_alloc;
	}
	adpt = kzalloc(sizeof(*adpt), GFP_KERNEL);
	if (!adpt)
		return -ENOMEM;

	adpt->iface = iface;
	INIT_LIST_HEAD(&adpt->dev_list);
	iface->priv = adpt;
	list_add_tail(&adpt->list, &adpt_list);
	ret = snd_card_new(iface->driver_dev, -1, "INIC", THIS_MODULE,
			   sizeof(*channel), &adpt->card);
	if (ret < 0)
		goto err_free_adpt;
	snprintf(adpt->card->driver, sizeof(adpt->card->driver),
		 "%s", DRIVER_NAME);
	snprintf(adpt->card->shortname, sizeof(adpt->card->shortname),
		 "Microchip INIC");
	snprintf(adpt->card->longname, sizeof(adpt->card->longname),
		 "%s at %s", adpt->card->shortname, iface->description);
skip_adpt_alloc:
	if (get_channel(iface, channel_id)) {
		pr_err("channel (%s:%d) is already linked\n",
		       iface->description, channel_id);
		return -EEXIST;
	}

	if (cfg->direction == MOST_CH_TX) {
		playback_count = 1;
		direction = SNDRV_PCM_STREAM_PLAYBACK;
	} else {
		capture_count = 1;
		direction = SNDRV_PCM_STREAM_CAPTURE;
	}
	channel = kzalloc(sizeof(*channel), GFP_KERNEL);
	if (!channel) {
		ret = -ENOMEM;
		goto err_free_adpt;
	}
	channel->card = adpt->card;
	channel->cfg = cfg;
	channel->iface = iface;
	channel->id = channel_id;
	init_waitqueue_head(&channel->playback_waitq);
	list_add_tail(&channel->list, &adpt->dev_list);

	ret = audio_set_hw_params(&channel->pcm_hardware, ch_num, sample_res,
				  cfg);
	if (ret)
		goto err_free_adpt;

	ret = snd_pcm_new(adpt->card, device_name, adpt->pcm_dev_idx,
			  playback_count, capture_count, &pcm);

	if (ret < 0)
		goto err_free_adpt;

	pcm->private_data = channel;
	strscpy(pcm->name, device_name, sizeof(pcm->name));
	snd_pcm_set_ops(pcm, direction, &pcm_ops);
	snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC, NULL, 0, 0);
	return 0;

err_free_adpt:
	release_adapter(adpt);
	return ret;
}