aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/pci/hda/hda_codec.c162
-rw-r--r--sound/pci/hda/hda_codec.h4
-rw-r--r--sound/pci/hda/hda_hwdep.c2
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 */
1210void snd_hda_ctls_clear(struct hda_codec *codec) 1211void 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 */
1245int snd_hda_add_vmaster(struct hda_codec *codec, char *name, 1250int 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 */
2443static 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 */
2438static int __devinit 2492static int snd_hda_attach_pcm(struct hda_codec *codec, struct hda_pcm *pcm)
2439snd_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 */
2512int 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 */
2484int snd_hda_build_pcms(struct hda_bus *bus) 2570int __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 */
848int snd_hda_build_pcms(struct hda_bus *bus); 851int snd_hda_build_pcms(struct hda_bus *bus);
852int snd_hda_codec_build_pcms(struct hda_codec *codec);
849void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, 853void 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 */