aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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