diff options
-rw-r--r-- | sound/pci/hda/patch_ca0132.c | 131 |
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 | */ |
2635 | static int ca0132_playback_pcm_open(struct hda_pcm_stream *hinfo, | 2635 | static 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 | |||
2669 | static 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 | */ | ||
2644 | static int ca0132_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | 2689 | static 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 | ||
2655 | static int ca0132_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, | 2702 | static 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 | */ | ||
2762 | static 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 | |||
2776 | static 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[] = { | |||
3509 | static struct hda_pcm_stream ca0132_pcm_analog_playback = { | 3597 | static 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 | ||
3526 | static struct hda_pcm_stream ca0132_pcm_digital_playback = { | 3617 | static 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 | ||