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;
}