aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2008-01-24 09:31:36 -0500
committerJaroslav Kysela <perex@perex.cz>2008-01-31 11:30:13 -0500
commit6330079fc6df4a0829f952b73c4d4999e56034f8 (patch)
tree936d9f393e49fc986f7383b757f69a4529f5bf12 /sound/pci/hda
parent09a99959180d25f4e5070f902e3adc1b20439cd6 (diff)
[ALSA] hda-codec - Fix handling of multiple capture streams
Fixed the bug that multiple capture streams conflict on Realtek codec routines. Also, this adds a framework to enable the alternative playback stream, e.g. for VoIP. It's not fully implemented yet, though. Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Jaroslav Kysela <perex@perex.cz>
Diffstat (limited to 'sound/pci/hda')
-rw-r--r--sound/pci/hda/patch_realtek.c85
1 files changed, 58 insertions, 27 deletions
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 6f652afd3cbe..c08852acd07e 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -220,6 +220,8 @@ struct alc_spec {
220 char *stream_name_analog; /* analog PCM stream */ 220 char *stream_name_analog; /* analog PCM stream */
221 struct hda_pcm_stream *stream_analog_playback; 221 struct hda_pcm_stream *stream_analog_playback;
222 struct hda_pcm_stream *stream_analog_capture; 222 struct hda_pcm_stream *stream_analog_capture;
223 struct hda_pcm_stream *stream_analog_alt_playback;
224 struct hda_pcm_stream *stream_analog_alt_capture;
223 225
224 char *stream_name_digital; /* digital PCM stream */ 226 char *stream_name_digital; /* digital PCM stream */
225 struct hda_pcm_stream *stream_digital_playback; 227 struct hda_pcm_stream *stream_digital_playback;
@@ -230,6 +232,7 @@ struct alc_spec {
230 * max_channels, dacs must be set 232 * max_channels, dacs must be set
231 * dig_out_nid and hp_nid are optional 233 * dig_out_nid and hp_nid are optional
232 */ 234 */
235 hda_nid_t alt_dac_nid;
233 236
234 /* capture */ 237 /* capture */
235 unsigned int num_adc_nids; 238 unsigned int num_adc_nids;
@@ -2370,7 +2373,7 @@ static int alc880_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
2370/* 2373/*
2371 * Analog capture 2374 * Analog capture
2372 */ 2375 */
2373static int alc880_capture_pcm_prepare(struct hda_pcm_stream *hinfo, 2376static int alc880_alt_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
2374 struct hda_codec *codec, 2377 struct hda_codec *codec,
2375 unsigned int stream_tag, 2378 unsigned int stream_tag,
2376 unsigned int format, 2379 unsigned int format,
@@ -2378,18 +2381,18 @@ static int alc880_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
2378{ 2381{
2379 struct alc_spec *spec = codec->spec; 2382 struct alc_spec *spec = codec->spec;
2380 2383
2381 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], 2384 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number + 1],
2382 stream_tag, 0, format); 2385 stream_tag, 0, format);
2383 return 0; 2386 return 0;
2384} 2387}
2385 2388
2386static int alc880_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, 2389static int alc880_alt_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
2387 struct hda_codec *codec, 2390 struct hda_codec *codec,
2388 struct snd_pcm_substream *substream) 2391 struct snd_pcm_substream *substream)
2389{ 2392{
2390 struct alc_spec *spec = codec->spec; 2393 struct alc_spec *spec = codec->spec;
2391 2394
2392 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], 2395 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number + 1],
2393 0, 0, 0); 2396 0, 0, 0);
2394 return 0; 2397 return 0;
2395} 2398}
@@ -2410,13 +2413,27 @@ static struct hda_pcm_stream alc880_pcm_analog_playback = {
2410}; 2413};
2411 2414
2412static struct hda_pcm_stream alc880_pcm_analog_capture = { 2415static struct hda_pcm_stream alc880_pcm_analog_capture = {
2413 .substreams = 2, 2416 .substreams = 1,
2417 .channels_min = 2,
2418 .channels_max = 2,
2419 /* NID is set in alc_build_pcms */
2420};
2421
2422static struct hda_pcm_stream alc880_pcm_analog_alt_playback = {
2423 .substreams = 1,
2424 .channels_min = 2,
2425 .channels_max = 2,
2426 /* NID is set in alc_build_pcms */
2427};
2428
2429static struct hda_pcm_stream alc880_pcm_analog_alt_capture = {
2430 .substreams = 2, /* can be overridden */
2414 .channels_min = 2, 2431 .channels_min = 2,
2415 .channels_max = 2, 2432 .channels_max = 2,
2416 /* NID is set in alc_build_pcms */ 2433 /* NID is set in alc_build_pcms */
2417 .ops = { 2434 .ops = {
2418 .prepare = alc880_capture_pcm_prepare, 2435 .prepare = alc880_alt_capture_pcm_prepare,
2419 .cleanup = alc880_capture_pcm_cleanup 2436 .cleanup = alc880_alt_capture_pcm_cleanup
2420 }, 2437 },
2421}; 2438};
2422 2439
@@ -2440,7 +2457,7 @@ static struct hda_pcm_stream alc880_pcm_digital_capture = {
2440}; 2457};
2441 2458
2442/* Used by alc_build_pcms to flag that a PCM has no playback stream */ 2459/* Used by alc_build_pcms to flag that a PCM has no playback stream */
2443static struct hda_pcm_stream alc_pcm_null_playback = { 2460static struct hda_pcm_stream alc_pcm_null_stream = {
2444 .substreams = 0, 2461 .substreams = 0,
2445 .channels_min = 0, 2462 .channels_min = 0,
2446 .channels_max = 0, 2463 .channels_max = 0,
@@ -2497,17 +2514,32 @@ static int alc_build_pcms(struct hda_codec *codec)
2497 * model, configure a second analog capture-only PCM. 2514 * model, configure a second analog capture-only PCM.
2498 */ 2515 */
2499 /* Additional Analaog capture for index #2 */ 2516 /* Additional Analaog capture for index #2 */
2500 if (spec->num_adc_nids > 1 && spec->stream_analog_capture && 2517 if ((spec->alt_dac_nid && spec->stream_analog_alt_playback) ||
2501 spec->adc_nids) { 2518 (spec->num_adc_nids > 1 && spec->stream_analog_alt_capture)) {
2502 codec->num_pcms = 3; 2519 codec->num_pcms = 3;
2503 info = spec->pcm_rec + 2; 2520 info = spec->pcm_rec + 2;
2504 info->name = spec->stream_name_analog; 2521 info->name = spec->stream_name_analog;
2505 /* No playback stream for second PCM */ 2522 if (spec->alt_dac_nid) {
2506 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = alc_pcm_null_playback; 2523 info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
2507 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = 0; 2524 *spec->stream_analog_alt_playback;
2508 if (spec->stream_analog_capture) { 2525 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
2509 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture); 2526 spec->alt_dac_nid;
2510 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[1]; 2527 } else {
2528 info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
2529 alc_pcm_null_stream;
2530 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = 0;
2531 }
2532 if (spec->num_adc_nids > 1) {
2533 info->stream[SNDRV_PCM_STREAM_CAPTURE] =
2534 *spec->stream_analog_alt_capture;
2535 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
2536 spec->adc_nids[1];
2537 info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams =
2538 spec->num_adc_nids - 1;
2539 } else {
2540 info->stream[SNDRV_PCM_STREAM_CAPTURE] =
2541 alc_pcm_null_stream;
2542 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = 0;
2511 } 2543 }
2512 } 2544 }
2513 2545
@@ -3615,6 +3647,7 @@ static int patch_alc880(struct hda_codec *codec)
3615 spec->stream_name_analog = "ALC880 Analog"; 3647 spec->stream_name_analog = "ALC880 Analog";
3616 spec->stream_analog_playback = &alc880_pcm_analog_playback; 3648 spec->stream_analog_playback = &alc880_pcm_analog_playback;
3617 spec->stream_analog_capture = &alc880_pcm_analog_capture; 3649 spec->stream_analog_capture = &alc880_pcm_analog_capture;
3650 spec->stream_analog_alt_capture = &alc880_pcm_analog_alt_capture;
3618 3651
3619 spec->stream_name_digital = "ALC880 Digital"; 3652 spec->stream_name_digital = "ALC880 Digital";
3620 spec->stream_digital_playback = &alc880_pcm_digital_playback; 3653 spec->stream_digital_playback = &alc880_pcm_digital_playback;
@@ -4527,17 +4560,8 @@ static struct hda_verb alc260_test_init_verbs[] = {
4527}; 4560};
4528#endif 4561#endif
4529 4562
4530static struct hda_pcm_stream alc260_pcm_analog_playback = { 4563#define alc260_pcm_analog_playback alc880_pcm_analog_alt_playback
4531 .substreams = 1, 4564#define alc260_pcm_analog_capture alc880_pcm_analog_capture
4532 .channels_min = 2,
4533 .channels_max = 2,
4534};
4535
4536static struct hda_pcm_stream alc260_pcm_analog_capture = {
4537 .substreams = 1,
4538 .channels_min = 2,
4539 .channels_max = 2,
4540};
4541 4565
4542#define alc260_pcm_digital_playback alc880_pcm_digital_playback 4566#define alc260_pcm_digital_playback alc880_pcm_digital_playback
4543#define alc260_pcm_digital_capture alc880_pcm_digital_capture 4567#define alc260_pcm_digital_capture alc880_pcm_digital_capture
@@ -6204,6 +6228,9 @@ static int patch_alc882(struct hda_codec *codec)
6204 spec->stream_name_analog = "ALC882 Analog"; 6228 spec->stream_name_analog = "ALC882 Analog";
6205 spec->stream_analog_playback = &alc882_pcm_analog_playback; 6229 spec->stream_analog_playback = &alc882_pcm_analog_playback;
6206 spec->stream_analog_capture = &alc882_pcm_analog_capture; 6230 spec->stream_analog_capture = &alc882_pcm_analog_capture;
6231 /* FIXME: setup DAC5 */
6232 /*spec->stream_analog_alt_playback = &alc880_pcm_analog_alt_playback;*/
6233 spec->stream_analog_alt_capture = &alc880_pcm_analog_alt_capture;
6207 6234
6208 spec->stream_name_digital = "ALC882 Digital"; 6235 spec->stream_name_digital = "ALC882 Digital";
6209 spec->stream_digital_playback = &alc882_pcm_digital_playback; 6236 spec->stream_digital_playback = &alc882_pcm_digital_playback;
@@ -7409,6 +7436,7 @@ static struct snd_kcontrol_new alc883_capture_mixer[] = {
7409/* pcm configuration: identiacal with ALC880 */ 7436/* pcm configuration: identiacal with ALC880 */
7410#define alc883_pcm_analog_playback alc880_pcm_analog_playback 7437#define alc883_pcm_analog_playback alc880_pcm_analog_playback
7411#define alc883_pcm_analog_capture alc880_pcm_analog_capture 7438#define alc883_pcm_analog_capture alc880_pcm_analog_capture
7439#define alc883_pcm_analog_alt_capture alc880_pcm_analog_alt_capture
7412#define alc883_pcm_digital_playback alc880_pcm_digital_playback 7440#define alc883_pcm_digital_playback alc880_pcm_digital_playback
7413#define alc883_pcm_digital_capture alc880_pcm_digital_capture 7441#define alc883_pcm_digital_capture alc880_pcm_digital_capture
7414 7442
@@ -7894,6 +7922,7 @@ static int patch_alc883(struct hda_codec *codec)
7894 spec->stream_name_analog = "ALC883 Analog"; 7922 spec->stream_name_analog = "ALC883 Analog";
7895 spec->stream_analog_playback = &alc883_pcm_analog_playback; 7923 spec->stream_analog_playback = &alc883_pcm_analog_playback;
7896 spec->stream_analog_capture = &alc883_pcm_analog_capture; 7924 spec->stream_analog_capture = &alc883_pcm_analog_capture;
7925 spec->stream_analog_alt_capture = &alc883_pcm_analog_alt_capture;
7897 7926
7898 spec->stream_name_digital = "ALC883 Digital"; 7927 spec->stream_name_digital = "ALC883 Digital";
7899 spec->stream_digital_playback = &alc883_pcm_digital_playback; 7928 spec->stream_digital_playback = &alc883_pcm_digital_playback;
@@ -9821,6 +9850,7 @@ static void alc268_auto_init_mono_speaker_out(struct hda_codec *codec)
9821/* pcm configuration: identiacal with ALC880 */ 9850/* pcm configuration: identiacal with ALC880 */
9822#define alc268_pcm_analog_playback alc880_pcm_analog_playback 9851#define alc268_pcm_analog_playback alc880_pcm_analog_playback
9823#define alc268_pcm_analog_capture alc880_pcm_analog_capture 9852#define alc268_pcm_analog_capture alc880_pcm_analog_capture
9853#define alc268_pcm_analog_alt_capture alc880_pcm_analog_alt_capture
9824#define alc268_pcm_digital_playback alc880_pcm_digital_playback 9854#define alc268_pcm_digital_playback alc880_pcm_digital_playback
9825 9855
9826/* 9856/*
@@ -10022,6 +10052,7 @@ static int patch_alc268(struct hda_codec *codec)
10022 spec->stream_name_analog = "ALC268 Analog"; 10052 spec->stream_name_analog = "ALC268 Analog";
10023 spec->stream_analog_playback = &alc268_pcm_analog_playback; 10053 spec->stream_analog_playback = &alc268_pcm_analog_playback;
10024 spec->stream_analog_capture = &alc268_pcm_analog_capture; 10054 spec->stream_analog_capture = &alc268_pcm_analog_capture;
10055 spec->stream_analog_alt_capture = &alc268_pcm_analog_alt_capture;
10025 10056
10026 spec->stream_name_digital = "ALC268 Digital"; 10057 spec->stream_name_digital = "ALC268 Digital";
10027 spec->stream_digital_playback = &alc268_pcm_digital_playback; 10058 spec->stream_digital_playback = &alc268_pcm_digital_playback;