diff options
-rw-r--r-- | sound/pci/hda/hda_codec.c | 162 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.h | 4 | ||||
-rw-r--r-- | sound/pci/hda/hda_hwdep.c | 2 |
3 files changed, 98 insertions, 70 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 052a898a63ba..1cb85b73e19b 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -1206,6 +1206,7 @@ int snd_hda_ctl_add(struct hda_codec *codec, struct snd_kcontrol *kctl) | |||
1206 | return 0; | 1206 | return 0; |
1207 | } | 1207 | } |
1208 | 1208 | ||
1209 | #ifdef CONFIG_SND_HDA_RECONFIG | ||
1209 | /* Clear all controls assigned to the given codec */ | 1210 | /* Clear all controls assigned to the given codec */ |
1210 | void snd_hda_ctls_clear(struct hda_codec *codec) | 1211 | void snd_hda_ctls_clear(struct hda_codec *codec) |
1211 | { | 1212 | { |
@@ -1227,9 +1228,12 @@ void snd_hda_codec_reset(struct hda_codec *codec) | |||
1227 | snd_hda_ctls_clear(codec); | 1228 | snd_hda_ctls_clear(codec); |
1228 | /* relase PCMs */ | 1229 | /* relase PCMs */ |
1229 | for (i = 0; i < codec->num_pcms; i++) { | 1230 | for (i = 0; i < codec->num_pcms; i++) { |
1230 | if (codec->pcm_info[i].pcm) | 1231 | if (codec->pcm_info[i].pcm) { |
1231 | snd_device_free(codec->bus->card, | 1232 | snd_device_free(codec->bus->card, |
1232 | codec->pcm_info[i].pcm); | 1233 | codec->pcm_info[i].pcm); |
1234 | clear_bit(codec->pcm_info[i].device, | ||
1235 | codec->bus->pcm_dev_bits); | ||
1236 | } | ||
1233 | } | 1237 | } |
1234 | if (codec->patch_ops.free) | 1238 | if (codec->patch_ops.free) |
1235 | codec->patch_ops.free(codec); | 1239 | codec->patch_ops.free(codec); |
@@ -1240,6 +1244,7 @@ void snd_hda_codec_reset(struct hda_codec *codec) | |||
1240 | codec->pcm_info = NULL; | 1244 | codec->pcm_info = NULL; |
1241 | codec->preset = NULL; | 1245 | codec->preset = NULL; |
1242 | } | 1246 | } |
1247 | #endif /* CONFIG_SND_HDA_RECONFIG */ | ||
1243 | 1248 | ||
1244 | /* create a virtual master control and add slaves */ | 1249 | /* create a virtual master control and add slaves */ |
1245 | int snd_hda_add_vmaster(struct hda_codec *codec, char *name, | 1250 | int snd_hda_add_vmaster(struct hda_codec *codec, char *name, |
@@ -2433,10 +2438,58 @@ static int set_pcm_default_values(struct hda_codec *codec, | |||
2433 | } | 2438 | } |
2434 | 2439 | ||
2435 | /* | 2440 | /* |
2441 | * get the empty PCM device number to assign | ||
2442 | */ | ||
2443 | static int get_empty_pcm_device(struct hda_bus *bus, int type) | ||
2444 | { | ||
2445 | static const char *dev_name[HDA_PCM_NTYPES] = { | ||
2446 | "Audio", "SPDIF", "HDMI", "Modem" | ||
2447 | }; | ||
2448 | /* starting device index for each PCM type */ | ||
2449 | static int dev_idx[HDA_PCM_NTYPES] = { | ||
2450 | [HDA_PCM_TYPE_AUDIO] = 0, | ||
2451 | [HDA_PCM_TYPE_SPDIF] = 1, | ||
2452 | [HDA_PCM_TYPE_HDMI] = 3, | ||
2453 | [HDA_PCM_TYPE_MODEM] = 6 | ||
2454 | }; | ||
2455 | /* normal audio device indices; not linear to keep compatibility */ | ||
2456 | static int audio_idx[4] = { 0, 2, 4, 5 }; | ||
2457 | int i, dev; | ||
2458 | |||
2459 | switch (type) { | ||
2460 | case HDA_PCM_TYPE_AUDIO: | ||
2461 | for (i = 0; i < ARRAY_SIZE(audio_idx); i++) { | ||
2462 | dev = audio_idx[i]; | ||
2463 | if (!test_bit(dev, bus->pcm_dev_bits)) | ||
2464 | break; | ||
2465 | } | ||
2466 | if (i >= ARRAY_SIZE(audio_idx)) { | ||
2467 | snd_printk(KERN_WARNING "Too many audio devices\n"); | ||
2468 | return -EAGAIN; | ||
2469 | } | ||
2470 | break; | ||
2471 | case HDA_PCM_TYPE_SPDIF: | ||
2472 | case HDA_PCM_TYPE_HDMI: | ||
2473 | case HDA_PCM_TYPE_MODEM: | ||
2474 | dev = dev_idx[type]; | ||
2475 | if (test_bit(dev, bus->pcm_dev_bits)) { | ||
2476 | snd_printk(KERN_WARNING "%s already defined\n", | ||
2477 | dev_name[type]); | ||
2478 | return -EAGAIN; | ||
2479 | } | ||
2480 | break; | ||
2481 | default: | ||
2482 | snd_printk(KERN_WARNING "Invalid PCM type %d\n", type); | ||
2483 | return -EINVAL; | ||
2484 | } | ||
2485 | set_bit(dev, bus->pcm_dev_bits); | ||
2486 | return dev; | ||
2487 | } | ||
2488 | |||
2489 | /* | ||
2436 | * attach a new PCM stream | 2490 | * attach a new PCM stream |
2437 | */ | 2491 | */ |
2438 | static int __devinit | 2492 | static int snd_hda_attach_pcm(struct hda_codec *codec, struct hda_pcm *pcm) |
2439 | snd_hda_attach_pcm(struct hda_codec *codec, struct hda_pcm *pcm) | ||
2440 | { | 2493 | { |
2441 | struct hda_bus *bus = codec->bus; | 2494 | struct hda_bus *bus = codec->bus; |
2442 | struct hda_pcm_stream *info; | 2495 | struct hda_pcm_stream *info; |
@@ -2455,6 +2508,39 @@ snd_hda_attach_pcm(struct hda_codec *codec, struct hda_pcm *pcm) | |||
2455 | return bus->ops.attach_pcm(bus, codec, pcm); | 2508 | return bus->ops.attach_pcm(bus, codec, pcm); |
2456 | } | 2509 | } |
2457 | 2510 | ||
2511 | /* assign all PCMs of the given codec */ | ||
2512 | int snd_hda_codec_build_pcms(struct hda_codec *codec) | ||
2513 | { | ||
2514 | unsigned int pcm; | ||
2515 | int err; | ||
2516 | |||
2517 | if (!codec->num_pcms) { | ||
2518 | if (!codec->patch_ops.build_pcms) | ||
2519 | return 0; | ||
2520 | err = codec->patch_ops.build_pcms(codec); | ||
2521 | if (err < 0) | ||
2522 | return err; | ||
2523 | } | ||
2524 | for (pcm = 0; pcm < codec->num_pcms; pcm++) { | ||
2525 | struct hda_pcm *cpcm = &codec->pcm_info[pcm]; | ||
2526 | int dev; | ||
2527 | |||
2528 | if (!cpcm->stream[0].substreams && !cpcm->stream[1].substreams) | ||
2529 | return 0; /* no substreams assigned */ | ||
2530 | |||
2531 | if (!cpcm->pcm) { | ||
2532 | dev = get_empty_pcm_device(codec->bus, cpcm->pcm_type); | ||
2533 | if (dev < 0) | ||
2534 | return 0; | ||
2535 | cpcm->device = dev; | ||
2536 | err = snd_hda_attach_pcm(codec, cpcm); | ||
2537 | if (err < 0) | ||
2538 | return err; | ||
2539 | } | ||
2540 | } | ||
2541 | return 0; | ||
2542 | } | ||
2543 | |||
2458 | /** | 2544 | /** |
2459 | * snd_hda_build_pcms - build PCM information | 2545 | * snd_hda_build_pcms - build PCM information |
2460 | * @bus: the BUS | 2546 | * @bus: the BUS |
@@ -2481,76 +2567,14 @@ snd_hda_attach_pcm(struct hda_codec *codec, struct hda_pcm *pcm) | |||
2481 | * | 2567 | * |
2482 | * This function returns 0 if successfull, or a negative error code. | 2568 | * This function returns 0 if successfull, or a negative error code. |
2483 | */ | 2569 | */ |
2484 | int snd_hda_build_pcms(struct hda_bus *bus) | 2570 | int __devinit snd_hda_build_pcms(struct hda_bus *bus) |
2485 | { | 2571 | { |
2486 | static const char *dev_name[HDA_PCM_NTYPES] = { | ||
2487 | "Audio", "SPDIF", "HDMI", "Modem" | ||
2488 | }; | ||
2489 | /* starting device index for each PCM type */ | ||
2490 | static int dev_idx[HDA_PCM_NTYPES] = { | ||
2491 | [HDA_PCM_TYPE_AUDIO] = 0, | ||
2492 | [HDA_PCM_TYPE_SPDIF] = 1, | ||
2493 | [HDA_PCM_TYPE_HDMI] = 3, | ||
2494 | [HDA_PCM_TYPE_MODEM] = 6 | ||
2495 | }; | ||
2496 | /* normal audio device indices; not linear to keep compatibility */ | ||
2497 | static int audio_idx[4] = { 0, 2, 4, 5 }; | ||
2498 | struct hda_codec *codec; | 2572 | struct hda_codec *codec; |
2499 | int num_devs[HDA_PCM_NTYPES]; | ||
2500 | 2573 | ||
2501 | memset(num_devs, 0, sizeof(num_devs)); | ||
2502 | list_for_each_entry(codec, &bus->codec_list, list) { | 2574 | list_for_each_entry(codec, &bus->codec_list, list) { |
2503 | unsigned int pcm; | 2575 | int err = snd_hda_codec_build_pcms(codec); |
2504 | int err; | 2576 | if (err < 0) |
2505 | if (!codec->num_pcms) { | 2577 | return err; |
2506 | if (!codec->patch_ops.build_pcms) | ||
2507 | continue; | ||
2508 | err = codec->patch_ops.build_pcms(codec); | ||
2509 | if (err < 0) | ||
2510 | return err; | ||
2511 | } | ||
2512 | for (pcm = 0; pcm < codec->num_pcms; pcm++) { | ||
2513 | struct hda_pcm *cpcm = &codec->pcm_info[pcm]; | ||
2514 | int type = cpcm->pcm_type; | ||
2515 | int dev; | ||
2516 | |||
2517 | if (!cpcm->stream[0].substreams && | ||
2518 | !cpcm->stream[1].substreams) | ||
2519 | continue; /* no substreams assigned */ | ||
2520 | |||
2521 | switch (type) { | ||
2522 | case HDA_PCM_TYPE_AUDIO: | ||
2523 | if (num_devs[type] >= ARRAY_SIZE(audio_idx)) { | ||
2524 | snd_printk(KERN_WARNING | ||
2525 | "Too many audio devices\n"); | ||
2526 | continue; | ||
2527 | } | ||
2528 | dev = audio_idx[num_devs[type]]; | ||
2529 | break; | ||
2530 | case HDA_PCM_TYPE_SPDIF: | ||
2531 | case HDA_PCM_TYPE_HDMI: | ||
2532 | case HDA_PCM_TYPE_MODEM: | ||
2533 | if (num_devs[type]) { | ||
2534 | snd_printk(KERN_WARNING | ||
2535 | "%s already defined\n", | ||
2536 | dev_name[type]); | ||
2537 | continue; | ||
2538 | } | ||
2539 | dev = dev_idx[type]; | ||
2540 | break; | ||
2541 | default: | ||
2542 | snd_printk(KERN_WARNING | ||
2543 | "Invalid PCM type %d\n", type); | ||
2544 | continue; | ||
2545 | } | ||
2546 | num_devs[type]++; | ||
2547 | if (!cpcm->pcm) { | ||
2548 | cpcm->device = dev; | ||
2549 | err = snd_hda_attach_pcm(codec, cpcm); | ||
2550 | if (err < 0) | ||
2551 | return err; | ||
2552 | } | ||
2553 | } | ||
2554 | } | 2578 | } |
2555 | return 0; | 2579 | return 0; |
2556 | } | 2580 | } |
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 4034625b5997..9fe0b67bb1e4 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h | |||
@@ -617,6 +617,9 @@ struct hda_bus { | |||
617 | 617 | ||
618 | struct snd_info_entry *proc; | 618 | struct snd_info_entry *proc; |
619 | 619 | ||
620 | /* assigned PCMs */ | ||
621 | DECLARE_BITMAP(pcm_dev_bits, SNDRV_PCM_DEVICES); | ||
622 | |||
620 | /* misc op flags */ | 623 | /* misc op flags */ |
621 | unsigned int needs_damn_long_delay :1; | 624 | unsigned int needs_damn_long_delay :1; |
622 | unsigned int shutdown :1; /* being unloaded */ | 625 | unsigned int shutdown :1; /* being unloaded */ |
@@ -846,6 +849,7 @@ int snd_hda_codec_build_controls(struct hda_codec *codec); | |||
846 | * PCM | 849 | * PCM |
847 | */ | 850 | */ |
848 | int snd_hda_build_pcms(struct hda_bus *bus); | 851 | int snd_hda_build_pcms(struct hda_bus *bus); |
852 | int snd_hda_codec_build_pcms(struct hda_codec *codec); | ||
849 | void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, | 853 | void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, |
850 | u32 stream_tag, | 854 | u32 stream_tag, |
851 | int channel_id, int format); | 855 | int channel_id, int format); |
diff --git a/sound/pci/hda/hda_hwdep.c b/sound/pci/hda/hda_hwdep.c index 5868bbc131cd..173af489322f 100644 --- a/sound/pci/hda/hda_hwdep.c +++ b/sound/pci/hda/hda_hwdep.c | |||
@@ -168,7 +168,7 @@ static int reconfig_codec(struct hda_codec *codec) | |||
168 | if (err < 0) | 168 | if (err < 0) |
169 | return err; | 169 | return err; |
170 | /* rebuild PCMs */ | 170 | /* rebuild PCMs */ |
171 | err = snd_hda_build_pcms(codec->bus); | 171 | err = snd_hda_codec_build_pcms(codec); |
172 | if (err < 0) | 172 | if (err < 0) |
173 | return err; | 173 | return err; |
174 | /* rebuild mixers */ | 174 | /* rebuild mixers */ |