diff options
author | Takashi Iwai <tiwai@suse.de> | 2008-07-30 09:01:44 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2008-10-12 20:42:58 -0400 |
commit | 176d5335fe66f379a339b0ab99cc7566e90ff1a9 (patch) | |
tree | 00f294bebf1270f65fe527141d3e6c1f440bba36 /sound/pci/hda/hda_codec.c | |
parent | 687cb98e893f492932abb3e92660d7d828bd44fb (diff) |
ALSA: hda - Add infrastructure for dynamic stream allocation
Added the infrastructure for dynamic stream allocation on HD-audio.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda/hda_codec.c')
-rw-r--r-- | sound/pci/hda/hda_codec.c | 74 |
1 files changed, 66 insertions, 8 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 6447754ae56e..19b4530e3baf 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -2262,6 +2262,28 @@ static int __devinit set_pcm_default_values(struct hda_codec *codec, | |||
2262 | return 0; | 2262 | return 0; |
2263 | } | 2263 | } |
2264 | 2264 | ||
2265 | /* | ||
2266 | * attach a new PCM stream | ||
2267 | */ | ||
2268 | static int __devinit | ||
2269 | snd_hda_attach_pcm(struct hda_codec *codec, struct hda_pcm *pcm) | ||
2270 | { | ||
2271 | struct hda_pcm_stream *info; | ||
2272 | int stream, err; | ||
2273 | |||
2274 | if (!pcm->name) | ||
2275 | return -EINVAL; | ||
2276 | for (stream = 0; stream < 2; stream++) { | ||
2277 | info = &pcm->stream[stream]; | ||
2278 | if (info->substreams) { | ||
2279 | err = set_pcm_default_values(codec, info); | ||
2280 | if (err < 0) | ||
2281 | return err; | ||
2282 | } | ||
2283 | } | ||
2284 | return codec->bus->ops.attach_pcm(codec, pcm); | ||
2285 | } | ||
2286 | |||
2265 | /** | 2287 | /** |
2266 | * snd_hda_build_pcms - build PCM information | 2288 | * snd_hda_build_pcms - build PCM information |
2267 | * @bus: the BUS | 2289 | * @bus: the BUS |
@@ -2290,10 +2312,24 @@ static int __devinit set_pcm_default_values(struct hda_codec *codec, | |||
2290 | */ | 2312 | */ |
2291 | int __devinit snd_hda_build_pcms(struct hda_bus *bus) | 2313 | int __devinit snd_hda_build_pcms(struct hda_bus *bus) |
2292 | { | 2314 | { |
2315 | static const char *dev_name[HDA_PCM_NTYPES] = { | ||
2316 | "Audio", "SPDIF", "HDMI", "Modem" | ||
2317 | }; | ||
2318 | /* starting device index for each PCM type */ | ||
2319 | static int dev_idx[HDA_PCM_NTYPES] = { | ||
2320 | [HDA_PCM_TYPE_AUDIO] = 0, | ||
2321 | [HDA_PCM_TYPE_SPDIF] = 1, | ||
2322 | [HDA_PCM_TYPE_HDMI] = 3, | ||
2323 | [HDA_PCM_TYPE_MODEM] = 6 | ||
2324 | }; | ||
2325 | /* normal audio device indices; not linear to keep compatibility */ | ||
2326 | static int audio_idx[4] = { 0, 2, 4, 5 }; | ||
2293 | struct hda_codec *codec; | 2327 | struct hda_codec *codec; |
2328 | int num_devs[HDA_PCM_NTYPES]; | ||
2294 | 2329 | ||
2330 | memset(num_devs, 0, sizeof(num_devs)); | ||
2295 | list_for_each_entry(codec, &bus->codec_list, list) { | 2331 | list_for_each_entry(codec, &bus->codec_list, list) { |
2296 | unsigned int pcm, s; | 2332 | unsigned int pcm; |
2297 | int err; | 2333 | int err; |
2298 | if (!codec->patch_ops.build_pcms) | 2334 | if (!codec->patch_ops.build_pcms) |
2299 | continue; | 2335 | continue; |
@@ -2301,15 +2337,37 @@ int __devinit snd_hda_build_pcms(struct hda_bus *bus) | |||
2301 | if (err < 0) | 2337 | if (err < 0) |
2302 | return err; | 2338 | return err; |
2303 | for (pcm = 0; pcm < codec->num_pcms; pcm++) { | 2339 | for (pcm = 0; pcm < codec->num_pcms; pcm++) { |
2304 | for (s = 0; s < 2; s++) { | 2340 | struct hda_pcm *cpcm = &codec->pcm_info[pcm]; |
2305 | struct hda_pcm_stream *info; | 2341 | int type = cpcm->pcm_type; |
2306 | info = &codec->pcm_info[pcm].stream[s]; | 2342 | switch (type) { |
2307 | if (!info->substreams) | 2343 | case HDA_PCM_TYPE_AUDIO: |
2344 | if (num_devs[type] >= ARRAY_SIZE(audio_idx)) { | ||
2345 | snd_printk(KERN_WARNING | ||
2346 | "Too many audio devices\n"); | ||
2347 | continue; | ||
2348 | } | ||
2349 | cpcm->device = audio_idx[num_devs[type]]; | ||
2350 | break; | ||
2351 | case HDA_PCM_TYPE_SPDIF: | ||
2352 | case HDA_PCM_TYPE_HDMI: | ||
2353 | case HDA_PCM_TYPE_MODEM: | ||
2354 | if (num_devs[type]) { | ||
2355 | snd_printk(KERN_WARNING | ||
2356 | "%s already defined\n", | ||
2357 | dev_name[type]); | ||
2308 | continue; | 2358 | continue; |
2309 | err = set_pcm_default_values(codec, info); | 2359 | } |
2310 | if (err < 0) | 2360 | cpcm->device = dev_idx[type]; |
2311 | return err; | 2361 | break; |
2362 | default: | ||
2363 | snd_printk(KERN_WARNING | ||
2364 | "Invalid PCM type %d\n", type); | ||
2365 | continue; | ||
2312 | } | 2366 | } |
2367 | num_devs[type]++; | ||
2368 | err = snd_hda_attach_pcm(codec, cpcm); | ||
2369 | if (err < 0) | ||
2370 | return err; | ||
2313 | } | 2371 | } |
2314 | } | 2372 | } |
2315 | return 0; | 2373 | return 0; |