|
@@ -4569,71 +4569,87 @@ static int get_empty_pcm_device(struct hda_bus *bus, unsigned int type)
|
|
return -EAGAIN;
|
|
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);
|
|
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 err;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- return bus->ops.attach_pcm(bus, codec, pcm);
|
|
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
}
|
|
}
|
|
|
|
|
|
/* assign all PCMs of the given codec */
|
|
/* assign all PCMs of the given codec */
|
|
int snd_hda_codec_build_pcms(struct hda_codec *codec)
|
|
int snd_hda_codec_build_pcms(struct hda_codec *codec)
|
|
{
|
|
{
|
|
|
|
+ struct hda_bus *bus = codec->bus;
|
|
unsigned int pcm;
|
|
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++) {
|
|
for (pcm = 0; pcm < codec->num_pcms; pcm++) {
|
|
struct hda_pcm *cpcm = &codec->pcm_info[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)
|
|
if (!cpcm->stream[0].substreams && !cpcm->stream[1].substreams)
|
|
continue; /* no substreams assigned */
|
|
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;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|