aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda
diff options
context:
space:
mode:
authorIan Minett <ian_minett@creativelabs.com>2012-12-20 21:53:36 -0500
committerTakashi Iwai <tiwai@suse.de>2013-01-15 10:59:21 -0500
commit825315bc5b5c33e5af5124ff100ef05a30ad722f (patch)
tree86f1446eb4ece9a06ed7e5c04d84d33298d08e3a /sound/pci/hda
parenta7e76271bdca5b85adb42fed05aae10ff6adeef3 (diff)
ALSA: hda/ca0132: Add PCM enhancements
Remove the playback PCM open callback. PCM stream setup and cleanup functions are added for use by PCM callbacks. Delay stream cleanup if effects are on, to allow time for any effects tail to finish. Add the analog capture PCM callbacks. Change the max channels of analog playback to 6. Add two new PCMs: AMic2 and What-U-Hear. Signed-off-by: Ian Minett <ian_minett@creativelabs.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda')
-rw-r--r--sound/pci/hda/patch_ca0132.c131
1 files changed, 118 insertions, 13 deletions
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c
index 91c4a5017282..748fca78131c 100644
--- a/sound/pci/hda/patch_ca0132.c
+++ b/sound/pci/hda/patch_ca0132.c
@@ -2630,17 +2630,62 @@ static bool dspload_wait_loaded(struct hda_codec *codec)
2630 CA0132_CODEC_MUTE_MONO(xname, nid, 3, dir) 2630 CA0132_CODEC_MUTE_MONO(xname, nid, 3, dir)
2631 2631
2632/* 2632/*
2633 * PCM callbacks 2633 * PCM stuffs
2634 */ 2634 */
2635static int ca0132_playback_pcm_open(struct hda_pcm_stream *hinfo, 2635static void ca0132_setup_stream(struct hda_codec *codec, hda_nid_t nid,
2636 struct hda_codec *codec, 2636 u32 stream_tag,
2637 struct snd_pcm_substream *substream) 2637 int channel_id, int format)
2638{ 2638{
2639 struct ca0132_spec *spec = codec->spec; 2639 unsigned int oldval, newval;
2640 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream, 2640
2641 hinfo); 2641 if (!nid)
2642 return;
2643
2644 snd_printdd(
2645 "ca0132_setup_stream: NID=0x%x, stream=0x%x, "
2646 "channel=%d, format=0x%x\n",
2647 nid, stream_tag, channel_id, format);
2648
2649 /* update the format-id if changed */
2650 oldval = snd_hda_codec_read(codec, nid, 0,
2651 AC_VERB_GET_STREAM_FORMAT,
2652 0);
2653 if (oldval != format) {
2654 msleep(20);
2655 snd_hda_codec_write(codec, nid, 0,
2656 AC_VERB_SET_STREAM_FORMAT,
2657 format);
2658 }
2659
2660 oldval = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0);
2661 newval = (stream_tag << 4) | channel_id;
2662 if (oldval != newval) {
2663 snd_hda_codec_write(codec, nid, 0,
2664 AC_VERB_SET_CHANNEL_STREAMID,
2665 newval);
2666 }
2667}
2668
2669static void ca0132_cleanup_stream(struct hda_codec *codec, hda_nid_t nid)
2670{
2671 unsigned int val;
2672
2673 if (!nid)
2674 return;
2675
2676 snd_printdd(KERN_INFO "ca0132_cleanup_stream: NID=0x%x\n", nid);
2677
2678 val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0);
2679 if (!val)
2680 return;
2681
2682 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, 0);
2683 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID, 0);
2642} 2684}
2643 2685
2686/*
2687 * PCM callbacks
2688 */
2644static int ca0132_playback_pcm_prepare(struct hda_pcm_stream *hinfo, 2689static int ca0132_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
2645 struct hda_codec *codec, 2690 struct hda_codec *codec,
2646 unsigned int stream_tag, 2691 unsigned int stream_tag,
@@ -2648,8 +2693,10 @@ static int ca0132_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
2648 struct snd_pcm_substream *substream) 2693 struct snd_pcm_substream *substream)
2649{ 2694{
2650 struct ca0132_spec *spec = codec->spec; 2695 struct ca0132_spec *spec = codec->spec;
2651 return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, 2696
2652 stream_tag, format, substream); 2697 ca0132_setup_stream(codec, spec->dacs[0], stream_tag, 0, format);
2698
2699 return 0;
2653} 2700}
2654 2701
2655static int ca0132_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, 2702static int ca0132_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
@@ -2657,7 +2704,18 @@ static int ca0132_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
2657 struct snd_pcm_substream *substream) 2704 struct snd_pcm_substream *substream)
2658{ 2705{
2659 struct ca0132_spec *spec = codec->spec; 2706 struct ca0132_spec *spec = codec->spec;
2660 return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout); 2707
2708 if (spec->dsp_state == DSP_DOWNLOADING)
2709 return 0;
2710
2711 /*If Playback effects are on, allow stream some time to flush
2712 *effects tail*/
2713 if (spec->effects_switch[PLAY_ENHANCEMENT - EFFECT_START_NID])
2714 msleep(50);
2715
2716 ca0132_cleanup_stream(codec, spec->dacs[0]);
2717
2718 return 0;
2661} 2719}
2662 2720
2663/* 2721/*
@@ -2699,6 +2757,36 @@ static int ca0132_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
2699} 2757}
2700 2758
2701/* 2759/*
2760 * Analog capture
2761 */
2762static int ca0132_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
2763 struct hda_codec *codec,
2764 unsigned int stream_tag,
2765 unsigned int format,
2766 struct snd_pcm_substream *substream)
2767{
2768 struct ca0132_spec *spec = codec->spec;
2769
2770 ca0132_setup_stream(codec, spec->adcs[substream->number],
2771 stream_tag, 0, format);
2772
2773 return 0;
2774}
2775
2776static int ca0132_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
2777 struct hda_codec *codec,
2778 struct snd_pcm_substream *substream)
2779{
2780 struct ca0132_spec *spec = codec->spec;
2781
2782 if (spec->dsp_state == DSP_DOWNLOADING)
2783 return 0;
2784
2785 ca0132_cleanup_stream(codec, hinfo->nid);
2786 return 0;
2787}
2788
2789/*
2702 * Select the active output. 2790 * Select the active output.
2703 * If autodetect is enabled, output will be selected based on jack detection. 2791 * If autodetect is enabled, output will be selected based on jack detection.
2704 * If jack inserted, headphone will be selected, else built-in speakers 2792 * If jack inserted, headphone will be selected, else built-in speakers
@@ -3509,9 +3597,8 @@ static struct snd_kcontrol_new ca0132_mixer[] = {
3509static struct hda_pcm_stream ca0132_pcm_analog_playback = { 3597static struct hda_pcm_stream ca0132_pcm_analog_playback = {
3510 .substreams = 1, 3598 .substreams = 1,
3511 .channels_min = 2, 3599 .channels_min = 2,
3512 .channels_max = 2, 3600 .channels_max = 6,
3513 .ops = { 3601 .ops = {
3514 .open = ca0132_playback_pcm_open,
3515 .prepare = ca0132_playback_pcm_prepare, 3602 .prepare = ca0132_playback_pcm_prepare,
3516 .cleanup = ca0132_playback_pcm_cleanup 3603 .cleanup = ca0132_playback_pcm_cleanup
3517 }, 3604 },
@@ -3521,6 +3608,10 @@ static struct hda_pcm_stream ca0132_pcm_analog_capture = {
3521 .substreams = 1, 3608 .substreams = 1,
3522 .channels_min = 2, 3609 .channels_min = 2,
3523 .channels_max = 2, 3610 .channels_max = 2,
3611 .ops = {
3612 .prepare = ca0132_capture_pcm_prepare,
3613 .cleanup = ca0132_capture_pcm_cleanup
3614 },
3524}; 3615};
3525 3616
3526static struct hda_pcm_stream ca0132_pcm_digital_playback = { 3617static struct hda_pcm_stream ca0132_pcm_digital_playback = {
@@ -3555,10 +3646,24 @@ static int ca0132_build_pcms(struct hda_codec *codec)
3555 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = 3646 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
3556 spec->multiout.max_channels; 3647 spec->multiout.max_channels;
3557 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ca0132_pcm_analog_capture; 3648 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ca0132_pcm_analog_capture;
3558 info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = spec->num_inputs; 3649 info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = 1;
3559 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adcs[0]; 3650 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adcs[0];
3560 codec->num_pcms++; 3651 codec->num_pcms++;
3561 3652
3653 info++;
3654 info->name = "CA0132 Analog Mic-In2";
3655 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ca0132_pcm_analog_capture;
3656 info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = 1;
3657 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adcs[1];
3658 codec->num_pcms++;
3659
3660 info++;
3661 info->name = "CA0132 What U Hear";
3662 info->stream[SNDRV_PCM_STREAM_CAPTURE] = ca0132_pcm_analog_capture;
3663 info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = 1;
3664 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adcs[2];
3665 codec->num_pcms++;
3666
3562 if (!spec->dig_out && !spec->dig_in) 3667 if (!spec->dig_out && !spec->dig_in)
3563 return 0; 3668 return 0;
3564 3669