diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index db86b446743c..40300fcc5308 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -4569,71 +4569,87 @@ static int get_empty_pcm_device(struct hda_bus *bus, unsigned int type) return -EAGAIN; } -/* - * attach a new PCM stream - */ -static int snd_hda_attach_pcm(struct hda_codec *codec, struct hda_pcm *pcm) +/* call build_pcms ops of the given codec and set up the default parameters */ +int snd_hda_codec_parse_pcms(struct hda_codec *codec) { - struct hda_bus *bus = codec->bus; - struct hda_pcm_stream *info; - int stream, err; + unsigned int pcm; + int err; - if (snd_BUG_ON(!pcm->name)) - return -EINVAL; - for (stream = 0; stream < 2; stream++) { - info = &pcm->stream[stream]; - if (info->substreams) { + if (codec->num_pcms) + return 0; /* already parsed */ + + if (!codec->patch_ops.build_pcms) + return 0; + + err = codec->patch_ops.build_pcms(codec); + if (err < 0) { + codec_err(codec, "cannot build PCMs for #%d (error %d)\n", + codec->addr, err); + return err; + } + + for (pcm = 0; pcm < codec->num_pcms; pcm++) { + struct hda_pcm *cpcm = &codec->pcm_info[pcm]; + int stream; + + for (stream = 0; stream < 2; stream++) { + struct hda_pcm_stream *info = &cpcm->stream[stream]; + + if (!info->substreams) + continue; + if (snd_BUG_ON(!cpcm->name)) + return -EINVAL; err = set_pcm_default_values(codec, info); - if (err < 0) + if (err < 0) { + codec_warn(codec, + "fail to setup default for PCM %s\n", + cpcm->name); return err; + } } } - return bus->ops.attach_pcm(bus, codec, pcm); + + return 0; } /* assign all PCMs of the given codec */ int snd_hda_codec_build_pcms(struct hda_codec *codec) { + struct hda_bus *bus = codec->bus; unsigned int pcm; - int err; + int dev, err; - if (!codec->num_pcms) { - if (!codec->patch_ops.build_pcms) - return 0; - err = codec->patch_ops.build_pcms(codec); - if (err < 0) { - codec_err(codec, - "cannot build PCMs for #%d (error %d)\n", - codec->addr, err); - err = snd_hda_codec_reset(codec); - if (err < 0) { - codec_err(codec, - "cannot revert codec\n"); - return err; - } - } + if (snd_BUG_ON(!bus->ops.attach_pcm)) + return -EINVAL; + + err = snd_hda_codec_parse_pcms(codec); + if (err < 0) { + snd_hda_codec_reset(codec); + return err; } + + /* attach a new PCM streams */ for (pcm = 0; pcm < codec->num_pcms; pcm++) { struct hda_pcm *cpcm = &codec->pcm_info[pcm]; - int dev; + if (cpcm->pcm) + continue; /* already attached */ if (!cpcm->stream[0].substreams && !cpcm->stream[1].substreams) continue; /* no substreams assigned */ - if (!cpcm->pcm) { - dev = get_empty_pcm_device(codec->bus, cpcm->pcm_type); - if (dev < 0) - continue; /* no fatal error */ - cpcm->device = dev; - err = snd_hda_attach_pcm(codec, cpcm); - if (err < 0) { - codec_err(codec, - "cannot attach PCM stream %d for codec #%d\n", - dev, codec->addr); - continue; /* no fatal error */ - } + dev = get_empty_pcm_device(bus, cpcm->pcm_type); + if (dev < 0) + continue; /* no fatal error */ + cpcm->device = dev; + err = bus->ops.attach_pcm(bus, codec, cpcm); + if (err < 0) { + codec_err(codec, + "cannot attach PCM stream %d for codec #%d\n", + dev, codec->addr); + continue; /* no fatal error */ } } + return 0; } diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 457fc589eb46..8cf70369cd10 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h @@ -517,6 +517,7 @@ int snd_hda_codec_build_controls(struct hda_codec *codec); * PCM */ int snd_hda_build_pcms(struct hda_bus *bus); +int snd_hda_codec_parse_pcms(struct hda_codec *codec); int snd_hda_codec_build_pcms(struct hda_codec *codec); int snd_hda_codec_prepare(struct hda_codec *codec,