diff options
author | Ian Minett <ian_minett@creativelabs.com> | 2012-12-20 21:53:35 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2013-01-15 10:58:12 -0500 |
commit | a7e76271bdca5b85adb42fed05aae10ff6adeef3 (patch) | |
tree | 7a9f69acb105fb305ea51bb48e72a07d95a88a97 /sound/pci/hda/patch_ca0132.c | |
parent | 5aaca44d8d05d144eec891498ff529c6ad4f5794 (diff) |
ALSA: hda/ca0132: Add DSP mixer controls and helpers
This patch adds the kcontrols for the DSP effects, playback and recording
source selection.
ca0132_is_vnode_effective() checks whether virtual node settings have
taken effect.
The control change helpers ca0132_pe_switch_set(), ca0132_voicefx_set()
and ca0132_cvoice_switch_set() are added to toggle playback / capture
DSP effects, ca0132_voicefx_info(), _get() and _put() are added for
input path DSP effect value access. The volume helpers are updated to
volume_info(), _get() and _set() to use the virtual nodes.
The redundant headphone and speaker switches and ct_extension function
are removed.
Signed-off-by: Ian Minett <ian_minett@creativelabs.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda/patch_ca0132.c')
-rw-r--r-- | sound/pci/hda/patch_ca0132.c | 832 |
1 files changed, 544 insertions, 288 deletions
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index e4e1684ace6f..91c4a5017282 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c | |||
@@ -710,49 +710,6 @@ static void init_input(struct hda_codec *codec, hda_nid_t pin, hda_nid_t adc) | |||
710 | } | 710 | } |
711 | } | 711 | } |
712 | 712 | ||
713 | static int _add_switch(struct hda_codec *codec, hda_nid_t nid, const char *pfx, | ||
714 | int chan, int dir) | ||
715 | { | ||
716 | char namestr[44]; | ||
717 | int type = dir ? HDA_INPUT : HDA_OUTPUT; | ||
718 | struct snd_kcontrol_new knew = | ||
719 | HDA_CODEC_MUTE_MONO(namestr, nid, chan, 0, type); | ||
720 | if ((query_amp_caps(codec, nid, type) & AC_AMPCAP_MUTE) == 0) { | ||
721 | snd_printdd("Skipping '%s %s Switch' (no mute on node 0x%x)\n", pfx, dirstr[dir], nid); | ||
722 | return 0; | ||
723 | } | ||
724 | sprintf(namestr, "%s %s Switch", pfx, dirstr[dir]); | ||
725 | return snd_hda_ctl_add(codec, nid, snd_ctl_new1(&knew, codec)); | ||
726 | } | ||
727 | |||
728 | static int _add_volume(struct hda_codec *codec, hda_nid_t nid, const char *pfx, | ||
729 | int chan, int dir) | ||
730 | { | ||
731 | char namestr[44]; | ||
732 | int type = dir ? HDA_INPUT : HDA_OUTPUT; | ||
733 | struct snd_kcontrol_new knew = | ||
734 | HDA_CODEC_VOLUME_MONO(namestr, nid, chan, 0, type); | ||
735 | if ((query_amp_caps(codec, nid, type) & AC_AMPCAP_NUM_STEPS) == 0) { | ||
736 | snd_printdd("Skipping '%s %s Volume' (no amp on node 0x%x)\n", pfx, dirstr[dir], nid); | ||
737 | return 0; | ||
738 | } | ||
739 | sprintf(namestr, "%s %s Volume", pfx, dirstr[dir]); | ||
740 | return snd_hda_ctl_add(codec, nid, snd_ctl_new1(&knew, codec)); | ||
741 | } | ||
742 | |||
743 | #define add_out_switch(codec, nid, pfx) _add_switch(codec, nid, pfx, 3, 0) | ||
744 | #define add_out_volume(codec, nid, pfx) _add_volume(codec, nid, pfx, 3, 0) | ||
745 | #define add_in_switch(codec, nid, pfx) _add_switch(codec, nid, pfx, 3, 1) | ||
746 | #define add_in_volume(codec, nid, pfx) _add_volume(codec, nid, pfx, 3, 1) | ||
747 | #define add_mono_switch(codec, nid, pfx, chan) \ | ||
748 | _add_switch(codec, nid, pfx, chan, 0) | ||
749 | #define add_mono_volume(codec, nid, pfx, chan) \ | ||
750 | _add_volume(codec, nid, pfx, chan, 0) | ||
751 | #define add_in_mono_switch(codec, nid, pfx, chan) \ | ||
752 | _add_switch(codec, nid, pfx, chan, 1) | ||
753 | #define add_in_mono_volume(codec, nid, pfx, chan) \ | ||
754 | _add_volume(codec, nid, pfx, chan, 1) | ||
755 | |||
756 | enum dsp_download_state { | 713 | enum dsp_download_state { |
757 | DSP_DOWNLOAD_FAILED = -1, | 714 | DSP_DOWNLOAD_FAILED = -1, |
758 | DSP_DOWNLOAD_INIT = 0, | 715 | DSP_DOWNLOAD_INIT = 0, |
@@ -771,6 +728,8 @@ enum dsp_download_state { | |||
771 | */ | 728 | */ |
772 | 729 | ||
773 | struct ca0132_spec { | 730 | struct ca0132_spec { |
731 | struct snd_kcontrol_new *mixers[5]; | ||
732 | unsigned int num_mixers; | ||
774 | const struct hda_verb *base_init_verbs; | 733 | const struct hda_verb *base_init_verbs; |
775 | const struct hda_verb *base_exit_verbs; | 734 | const struct hda_verb *base_exit_verbs; |
776 | const struct hda_verb *init_verbs[5]; | 735 | const struct hda_verb *init_verbs[5]; |
@@ -781,17 +740,14 @@ struct ca0132_spec { | |||
781 | struct hda_multi_out multiout; | 740 | struct hda_multi_out multiout; |
782 | hda_nid_t out_pins[AUTO_CFG_MAX_OUTS]; | 741 | hda_nid_t out_pins[AUTO_CFG_MAX_OUTS]; |
783 | hda_nid_t dacs[AUTO_CFG_MAX_OUTS]; | 742 | hda_nid_t dacs[AUTO_CFG_MAX_OUTS]; |
784 | hda_nid_t hp_dac; | ||
785 | unsigned int num_outputs; | 743 | unsigned int num_outputs; |
786 | hda_nid_t input_pins[AUTO_PIN_LAST]; | 744 | hda_nid_t input_pins[AUTO_PIN_LAST]; |
787 | hda_nid_t adcs[AUTO_PIN_LAST]; | 745 | hda_nid_t adcs[AUTO_PIN_LAST]; |
788 | hda_nid_t dig_out; | 746 | hda_nid_t dig_out; |
789 | hda_nid_t dig_in; | 747 | hda_nid_t dig_in; |
790 | unsigned int num_inputs; | 748 | unsigned int num_inputs; |
791 | long curr_hp_switch; | 749 | hda_nid_t shared_mic_nid; |
792 | long curr_hp_volume[2]; | 750 | hda_nid_t shared_out_nid; |
793 | long curr_speaker_switch; | ||
794 | const char *input_labels[AUTO_PIN_LAST]; | ||
795 | struct hda_pcm pcm_rec[5]; /* PCM information */ | 751 | struct hda_pcm pcm_rec[5]; /* PCM information */ |
796 | 752 | ||
797 | /* chip access */ | 753 | /* chip access */ |
@@ -2950,6 +2906,59 @@ static int ca0132_select_mic(struct hda_codec *codec) | |||
2950 | } | 2906 | } |
2951 | 2907 | ||
2952 | /* | 2908 | /* |
2909 | * Check if VNODE settings take effect immediately. | ||
2910 | */ | ||
2911 | static bool ca0132_is_vnode_effective(struct hda_codec *codec, | ||
2912 | hda_nid_t vnid, | ||
2913 | hda_nid_t *shared_nid) | ||
2914 | { | ||
2915 | struct ca0132_spec *spec = codec->spec; | ||
2916 | hda_nid_t nid; | ||
2917 | bool effective = false; | ||
2918 | |||
2919 | switch (vnid) { | ||
2920 | case VNID_SPK: | ||
2921 | nid = spec->shared_out_nid; | ||
2922 | effective = true; | ||
2923 | break; | ||
2924 | case VNID_MIC: | ||
2925 | nid = spec->shared_mic_nid; | ||
2926 | effective = true; | ||
2927 | break; | ||
2928 | default: | ||
2929 | break; | ||
2930 | } | ||
2931 | |||
2932 | if (effective && shared_nid) | ||
2933 | *shared_nid = nid; | ||
2934 | |||
2935 | return effective; | ||
2936 | } | ||
2937 | |||
2938 | /* | ||
2939 | * The following functions are control change helpers. | ||
2940 | * They return 0 if no changed. Return 1 if changed. | ||
2941 | */ | ||
2942 | static int ca0132_voicefx_set(struct hda_codec *codec, int enable) | ||
2943 | { | ||
2944 | struct ca0132_spec *spec = codec->spec; | ||
2945 | unsigned int tmp; | ||
2946 | |||
2947 | /* based on CrystalVoice state to enable VoiceFX. */ | ||
2948 | if (enable) { | ||
2949 | tmp = spec->effects_switch[CRYSTAL_VOICE - EFFECT_START_NID] ? | ||
2950 | FLOAT_ONE : FLOAT_ZERO; | ||
2951 | } else { | ||
2952 | tmp = FLOAT_ZERO; | ||
2953 | } | ||
2954 | |||
2955 | dspio_set_uint_param(codec, ca0132_voicefx.mid, | ||
2956 | ca0132_voicefx.reqs[0], tmp); | ||
2957 | |||
2958 | return 1; | ||
2959 | } | ||
2960 | |||
2961 | /* | ||
2953 | * Set the effects parameters | 2962 | * Set the effects parameters |
2954 | */ | 2963 | */ |
2955 | static int ca0132_effects_set(struct hda_codec *codec, hda_nid_t nid, long val) | 2964 | static int ca0132_effects_set(struct hda_codec *codec, hda_nid_t nid, long val) |
@@ -2994,6 +3003,27 @@ static int ca0132_effects_set(struct hda_codec *codec, hda_nid_t nid, long val) | |||
2994 | return 1; | 3003 | return 1; |
2995 | } | 3004 | } |
2996 | 3005 | ||
3006 | /* | ||
3007 | * Turn on/off Playback Enhancements | ||
3008 | */ | ||
3009 | static int ca0132_pe_switch_set(struct hda_codec *codec) | ||
3010 | { | ||
3011 | struct ca0132_spec *spec = codec->spec; | ||
3012 | hda_nid_t nid; | ||
3013 | int i, ret = 0; | ||
3014 | |||
3015 | snd_printdd(KERN_INFO "ca0132_pe_switch_set: val=%ld\n", | ||
3016 | spec->effects_switch[PLAY_ENHANCEMENT - EFFECT_START_NID]); | ||
3017 | |||
3018 | i = OUT_EFFECT_START_NID - EFFECT_START_NID; | ||
3019 | nid = OUT_EFFECT_START_NID; | ||
3020 | /* PE affects all out effects */ | ||
3021 | for (; nid < OUT_EFFECT_END_NID; nid++, i++) | ||
3022 | ret |= ca0132_effects_set(codec, nid, spec->effects_switch[i]); | ||
3023 | |||
3024 | return ret; | ||
3025 | } | ||
3026 | |||
2997 | /* Check if Mic1 is streaming, if so, stop streaming */ | 3027 | /* Check if Mic1 is streaming, if so, stop streaming */ |
2998 | static int stop_mic1(struct hda_codec *codec) | 3028 | static int stop_mic1(struct hda_codec *codec) |
2999 | { | 3029 | { |
@@ -3019,8 +3049,34 @@ static void resume_mic1(struct hda_codec *codec, unsigned int oldval) | |||
3019 | } | 3049 | } |
3020 | 3050 | ||
3021 | /* | 3051 | /* |
3022 | * Set Mic Boost | 3052 | * Turn on/off CrystalVoice |
3023 | */ | 3053 | */ |
3054 | static int ca0132_cvoice_switch_set(struct hda_codec *codec) | ||
3055 | { | ||
3056 | struct ca0132_spec *spec = codec->spec; | ||
3057 | hda_nid_t nid; | ||
3058 | int i, ret = 0; | ||
3059 | unsigned int oldval; | ||
3060 | |||
3061 | snd_printdd(KERN_INFO "ca0132_cvoice_switch_set: val=%ld\n", | ||
3062 | spec->effects_switch[CRYSTAL_VOICE - EFFECT_START_NID]); | ||
3063 | |||
3064 | i = IN_EFFECT_START_NID - EFFECT_START_NID; | ||
3065 | nid = IN_EFFECT_START_NID; | ||
3066 | /* CrystalVoice affects all in effects */ | ||
3067 | for (; nid < IN_EFFECT_END_NID; nid++, i++) | ||
3068 | ret |= ca0132_effects_set(codec, nid, spec->effects_switch[i]); | ||
3069 | |||
3070 | /* including VoiceFX */ | ||
3071 | ret |= ca0132_voicefx_set(codec, (spec->voicefx_val ? 1 : 0)); | ||
3072 | |||
3073 | /* set correct vipsource */ | ||
3074 | oldval = stop_mic1(codec); | ||
3075 | ret |= ca0132_set_vipsource(codec, 1); | ||
3076 | resume_mic1(codec, oldval); | ||
3077 | return ret; | ||
3078 | } | ||
3079 | |||
3024 | static int ca0132_mic_boost_set(struct hda_codec *codec, long val) | 3080 | static int ca0132_mic_boost_set(struct hda_codec *codec, long val) |
3025 | { | 3081 | { |
3026 | struct ca0132_spec *spec = codec->spec; | 3082 | struct ca0132_spec *spec = codec->spec; |
@@ -3036,309 +3092,532 @@ static int ca0132_mic_boost_set(struct hda_codec *codec, long val) | |||
3036 | return ret; | 3092 | return ret; |
3037 | } | 3093 | } |
3038 | 3094 | ||
3039 | /* | 3095 | static int ca0132_vnode_switch_set(struct snd_kcontrol *kcontrol, |
3040 | */ | 3096 | struct snd_ctl_elem_value *ucontrol) |
3041 | static struct hda_pcm_stream ca0132_pcm_analog_playback = { | ||
3042 | .substreams = 1, | ||
3043 | .channels_min = 2, | ||
3044 | .channels_max = 2, | ||
3045 | .ops = { | ||
3046 | .open = ca0132_playback_pcm_open, | ||
3047 | .prepare = ca0132_playback_pcm_prepare, | ||
3048 | .cleanup = ca0132_playback_pcm_cleanup | ||
3049 | }, | ||
3050 | }; | ||
3051 | |||
3052 | static struct hda_pcm_stream ca0132_pcm_analog_capture = { | ||
3053 | .substreams = 1, | ||
3054 | .channels_min = 2, | ||
3055 | .channels_max = 2, | ||
3056 | }; | ||
3057 | |||
3058 | static struct hda_pcm_stream ca0132_pcm_digital_playback = { | ||
3059 | .substreams = 1, | ||
3060 | .channels_min = 2, | ||
3061 | .channels_max = 2, | ||
3062 | .ops = { | ||
3063 | .open = ca0132_dig_playback_pcm_open, | ||
3064 | .close = ca0132_dig_playback_pcm_close, | ||
3065 | .prepare = ca0132_dig_playback_pcm_prepare, | ||
3066 | .cleanup = ca0132_dig_playback_pcm_cleanup | ||
3067 | }, | ||
3068 | }; | ||
3069 | |||
3070 | static struct hda_pcm_stream ca0132_pcm_digital_capture = { | ||
3071 | .substreams = 1, | ||
3072 | .channels_min = 2, | ||
3073 | .channels_max = 2, | ||
3074 | }; | ||
3075 | |||
3076 | static int ca0132_build_pcms(struct hda_codec *codec) | ||
3077 | { | 3097 | { |
3098 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
3099 | hda_nid_t nid = get_amp_nid(kcontrol); | ||
3100 | hda_nid_t shared_nid = 0; | ||
3101 | bool effective; | ||
3102 | int ret = 0; | ||
3078 | struct ca0132_spec *spec = codec->spec; | 3103 | struct ca0132_spec *spec = codec->spec; |
3079 | struct hda_pcm *info = spec->pcm_rec; | 3104 | int auto_jack; |
3080 | 3105 | ||
3081 | codec->pcm_info = info; | 3106 | if (nid == VNID_HP_SEL) { |
3082 | codec->num_pcms = 0; | 3107 | auto_jack = |
3108 | spec->vnode_lswitch[VNID_HP_ASEL - VNODE_START_NID]; | ||
3109 | if (!auto_jack) | ||
3110 | ca0132_select_out(codec); | ||
3111 | return 1; | ||
3112 | } | ||
3083 | 3113 | ||
3084 | info->name = "CA0132 Analog"; | 3114 | if (nid == VNID_AMIC1_SEL) { |
3085 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ca0132_pcm_analog_playback; | 3115 | auto_jack = |
3086 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->dacs[0]; | 3116 | spec->vnode_lswitch[VNID_AMIC1_ASEL - VNODE_START_NID]; |
3087 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = | 3117 | if (!auto_jack) |
3088 | spec->multiout.max_channels; | 3118 | ca0132_select_mic(codec); |
3089 | info->stream[SNDRV_PCM_STREAM_CAPTURE] = ca0132_pcm_analog_capture; | 3119 | return 1; |
3090 | info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = spec->num_inputs; | 3120 | } |
3091 | info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adcs[0]; | ||
3092 | codec->num_pcms++; | ||
3093 | 3121 | ||
3094 | if (!spec->dig_out && !spec->dig_in) | 3122 | if (nid == VNID_HP_ASEL) { |
3095 | return 0; | 3123 | ca0132_select_out(codec); |
3124 | return 1; | ||
3125 | } | ||
3096 | 3126 | ||
3097 | info++; | 3127 | if (nid == VNID_AMIC1_ASEL) { |
3098 | info->name = "CA0132 Digital"; | 3128 | ca0132_select_mic(codec); |
3099 | info->pcm_type = HDA_PCM_TYPE_SPDIF; | 3129 | return 1; |
3100 | if (spec->dig_out) { | ||
3101 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = | ||
3102 | ca0132_pcm_digital_playback; | ||
3103 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->dig_out; | ||
3104 | } | 3130 | } |
3105 | if (spec->dig_in) { | 3131 | |
3106 | info->stream[SNDRV_PCM_STREAM_CAPTURE] = | 3132 | /* if effective conditions, then update hw immediately. */ |
3107 | ca0132_pcm_digital_capture; | 3133 | effective = ca0132_is_vnode_effective(codec, nid, &shared_nid); |
3108 | info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in; | 3134 | if (effective) { |
3135 | int dir = get_amp_direction(kcontrol); | ||
3136 | int ch = get_amp_channels(kcontrol); | ||
3137 | unsigned long pval; | ||
3138 | |||
3139 | mutex_lock(&codec->control_mutex); | ||
3140 | pval = kcontrol->private_value; | ||
3141 | kcontrol->private_value = HDA_COMPOSE_AMP_VAL(shared_nid, ch, | ||
3142 | 0, dir); | ||
3143 | ret = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); | ||
3144 | kcontrol->private_value = pval; | ||
3145 | mutex_unlock(&codec->control_mutex); | ||
3109 | } | 3146 | } |
3110 | codec->num_pcms++; | ||
3111 | 3147 | ||
3112 | return 0; | 3148 | return ret; |
3113 | } | 3149 | } |
3150 | /* End of control change helpers. */ | ||
3114 | 3151 | ||
3115 | #define REG_CODEC_MUTE 0x18b014 | 3152 | static int ca0132_voicefx_info(struct snd_kcontrol *kcontrol, |
3116 | #define REG_CODEC_HP_VOL_L 0x18b070 | 3153 | struct snd_ctl_elem_info *uinfo) |
3117 | #define REG_CODEC_HP_VOL_R 0x18b074 | 3154 | { |
3155 | unsigned int items = sizeof(ca0132_voicefx_presets) | ||
3156 | / sizeof(struct ct_voicefx_preset); | ||
3157 | |||
3158 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
3159 | uinfo->count = 1; | ||
3160 | uinfo->value.enumerated.items = items; | ||
3161 | if (uinfo->value.enumerated.item >= items) | ||
3162 | uinfo->value.enumerated.item = items - 1; | ||
3163 | strcpy(uinfo->value.enumerated.name, | ||
3164 | ca0132_voicefx_presets[uinfo->value.enumerated.item].name); | ||
3165 | return 0; | ||
3166 | } | ||
3118 | 3167 | ||
3119 | static int ca0132_hp_switch_get(struct snd_kcontrol *kcontrol, | 3168 | static int ca0132_voicefx_get(struct snd_kcontrol *kcontrol, |
3120 | struct snd_ctl_elem_value *ucontrol) | 3169 | struct snd_ctl_elem_value *ucontrol) |
3121 | { | 3170 | { |
3122 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 3171 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
3123 | struct ca0132_spec *spec = codec->spec; | 3172 | struct ca0132_spec *spec = codec->spec; |
3124 | long *valp = ucontrol->value.integer.value; | ||
3125 | 3173 | ||
3126 | *valp = spec->curr_hp_switch; | 3174 | ucontrol->value.enumerated.item[0] = spec->voicefx_val; |
3127 | return 0; | 3175 | return 0; |
3128 | } | 3176 | } |
3129 | 3177 | ||
3130 | static int ca0132_hp_switch_put(struct snd_kcontrol *kcontrol, | 3178 | static int ca0132_voicefx_put(struct snd_kcontrol *kcontrol, |
3131 | struct snd_ctl_elem_value *ucontrol) | 3179 | struct snd_ctl_elem_value *ucontrol) |
3132 | { | 3180 | { |
3133 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 3181 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
3134 | struct ca0132_spec *spec = codec->spec; | 3182 | struct ca0132_spec *spec = codec->spec; |
3135 | long *valp = ucontrol->value.integer.value; | 3183 | int i, err = 0; |
3136 | unsigned int data; | 3184 | int sel = ucontrol->value.enumerated.item[0]; |
3137 | int err; | 3185 | unsigned int items = sizeof(ca0132_voicefx_presets) |
3186 | / sizeof(struct ct_voicefx_preset); | ||
3138 | 3187 | ||
3139 | /* any change? */ | 3188 | if (sel >= items) |
3140 | if (spec->curr_hp_switch == *valp) | ||
3141 | return 0; | 3189 | return 0; |
3142 | 3190 | ||
3143 | snd_hda_power_up(codec); | 3191 | snd_printdd(KERN_INFO "ca0132_voicefx_put: sel=%d, preset=%s\n", |
3144 | 3192 | sel, ca0132_voicefx_presets[sel].name); | |
3145 | err = chipio_read(codec, REG_CODEC_MUTE, &data); | ||
3146 | if (err < 0) | ||
3147 | goto exit; | ||
3148 | 3193 | ||
3149 | /* *valp 0 is mute, 1 is unmute */ | 3194 | /* |
3150 | data = (data & 0x7f) | (*valp ? 0 : 0x80); | 3195 | * Idx 0 is default. |
3151 | err = chipio_write(codec, REG_CODEC_MUTE, data); | 3196 | * Default needs to qualify with CrystalVoice state. |
3152 | if (err < 0) | 3197 | */ |
3153 | goto exit; | 3198 | for (i = 0; i < VOICEFX_MAX_PARAM_COUNT; i++) { |
3199 | err = dspio_set_uint_param(codec, ca0132_voicefx.mid, | ||
3200 | ca0132_voicefx.reqs[i], | ||
3201 | ca0132_voicefx_presets[sel].vals[i]); | ||
3202 | if (err < 0) | ||
3203 | break; | ||
3204 | } | ||
3154 | 3205 | ||
3155 | spec->curr_hp_switch = *valp; | 3206 | if (err >= 0) { |
3207 | spec->voicefx_val = sel; | ||
3208 | /* enable voice fx */ | ||
3209 | ca0132_voicefx_set(codec, (sel ? 1 : 0)); | ||
3210 | } | ||
3156 | 3211 | ||
3157 | exit: | 3212 | return 1; |
3158 | snd_hda_power_down(codec); | ||
3159 | return err < 0 ? err : 1; | ||
3160 | } | 3213 | } |
3161 | 3214 | ||
3162 | static int ca0132_speaker_switch_get(struct snd_kcontrol *kcontrol, | 3215 | static int ca0132_switch_get(struct snd_kcontrol *kcontrol, |
3163 | struct snd_ctl_elem_value *ucontrol) | 3216 | struct snd_ctl_elem_value *ucontrol) |
3164 | { | 3217 | { |
3165 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 3218 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
3166 | struct ca0132_spec *spec = codec->spec; | 3219 | struct ca0132_spec *spec = codec->spec; |
3220 | hda_nid_t nid = get_amp_nid(kcontrol); | ||
3221 | int ch = get_amp_channels(kcontrol); | ||
3167 | long *valp = ucontrol->value.integer.value; | 3222 | long *valp = ucontrol->value.integer.value; |
3168 | 3223 | ||
3169 | *valp = spec->curr_speaker_switch; | 3224 | /* vnode */ |
3225 | if ((nid >= VNODE_START_NID) && (nid < VNODE_END_NID)) { | ||
3226 | if (ch & 1) { | ||
3227 | *valp = spec->vnode_lswitch[nid - VNODE_START_NID]; | ||
3228 | valp++; | ||
3229 | } | ||
3230 | if (ch & 2) { | ||
3231 | *valp = spec->vnode_rswitch[nid - VNODE_START_NID]; | ||
3232 | valp++; | ||
3233 | } | ||
3234 | return 0; | ||
3235 | } | ||
3236 | |||
3237 | /* effects, include PE and CrystalVoice */ | ||
3238 | if ((nid >= EFFECT_START_NID) && (nid < EFFECT_END_NID)) { | ||
3239 | *valp = spec->effects_switch[nid - EFFECT_START_NID]; | ||
3240 | return 0; | ||
3241 | } | ||
3242 | |||
3243 | /* mic boost */ | ||
3244 | if (nid == spec->input_pins[0]) { | ||
3245 | *valp = spec->cur_mic_boost; | ||
3246 | return 0; | ||
3247 | } | ||
3248 | |||
3170 | return 0; | 3249 | return 0; |
3171 | } | 3250 | } |
3172 | 3251 | ||
3173 | static int ca0132_speaker_switch_put(struct snd_kcontrol *kcontrol, | 3252 | static int ca0132_switch_put(struct snd_kcontrol *kcontrol, |
3174 | struct snd_ctl_elem_value *ucontrol) | 3253 | struct snd_ctl_elem_value *ucontrol) |
3175 | { | 3254 | { |
3176 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 3255 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
3177 | struct ca0132_spec *spec = codec->spec; | 3256 | struct ca0132_spec *spec = codec->spec; |
3257 | hda_nid_t nid = get_amp_nid(kcontrol); | ||
3258 | int ch = get_amp_channels(kcontrol); | ||
3178 | long *valp = ucontrol->value.integer.value; | 3259 | long *valp = ucontrol->value.integer.value; |
3179 | unsigned int data; | 3260 | int changed = 1; |
3180 | int err; | ||
3181 | 3261 | ||
3182 | /* any change? */ | 3262 | snd_printdd(KERN_INFO "ca0132_switch_put: nid=0x%x, val=%ld\n", |
3183 | if (spec->curr_speaker_switch == *valp) | 3263 | nid, *valp); |
3184 | return 0; | ||
3185 | 3264 | ||
3186 | snd_hda_power_up(codec); | 3265 | snd_hda_power_up(codec); |
3266 | /* vnode */ | ||
3267 | if ((nid >= VNODE_START_NID) && (nid < VNODE_END_NID)) { | ||
3268 | if (ch & 1) { | ||
3269 | spec->vnode_lswitch[nid - VNODE_START_NID] = *valp; | ||
3270 | valp++; | ||
3271 | } | ||
3272 | if (ch & 2) { | ||
3273 | spec->vnode_rswitch[nid - VNODE_START_NID] = *valp; | ||
3274 | valp++; | ||
3275 | } | ||
3276 | changed = ca0132_vnode_switch_set(kcontrol, ucontrol); | ||
3277 | goto exit; | ||
3278 | } | ||
3187 | 3279 | ||
3188 | err = chipio_read(codec, REG_CODEC_MUTE, &data); | 3280 | /* PE */ |
3189 | if (err < 0) | 3281 | if (nid == PLAY_ENHANCEMENT) { |
3282 | spec->effects_switch[nid - EFFECT_START_NID] = *valp; | ||
3283 | changed = ca0132_pe_switch_set(codec); | ||
3190 | goto exit; | 3284 | goto exit; |
3285 | } | ||
3191 | 3286 | ||
3192 | /* *valp 0 is mute, 1 is unmute */ | 3287 | /* CrystalVoice */ |
3193 | data = (data & 0xef) | (*valp ? 0 : 0x10); | 3288 | if (nid == CRYSTAL_VOICE) { |
3194 | err = chipio_write(codec, REG_CODEC_MUTE, data); | 3289 | spec->effects_switch[nid - EFFECT_START_NID] = *valp; |
3195 | if (err < 0) | 3290 | changed = ca0132_cvoice_switch_set(codec); |
3196 | goto exit; | 3291 | goto exit; |
3292 | } | ||
3197 | 3293 | ||
3198 | spec->curr_speaker_switch = *valp; | 3294 | /* out and in effects */ |
3295 | if (((nid >= OUT_EFFECT_START_NID) && (nid < OUT_EFFECT_END_NID)) || | ||
3296 | ((nid >= IN_EFFECT_START_NID) && (nid < IN_EFFECT_END_NID))) { | ||
3297 | spec->effects_switch[nid - EFFECT_START_NID] = *valp; | ||
3298 | changed = ca0132_effects_set(codec, nid, *valp); | ||
3299 | goto exit; | ||
3300 | } | ||
3301 | |||
3302 | /* mic boost */ | ||
3303 | if (nid == spec->input_pins[0]) { | ||
3304 | spec->cur_mic_boost = *valp; | ||
3305 | |||
3306 | /* Mic boost does not apply to Digital Mic */ | ||
3307 | if (spec->cur_mic_type != DIGITAL_MIC) | ||
3308 | changed = ca0132_mic_boost_set(codec, *valp); | ||
3309 | goto exit; | ||
3310 | } | ||
3199 | 3311 | ||
3200 | exit: | 3312 | exit: |
3201 | snd_hda_power_down(codec); | 3313 | snd_hda_power_down(codec); |
3202 | return err < 0 ? err : 1; | 3314 | return changed; |
3203 | } | 3315 | } |
3204 | 3316 | ||
3205 | static int ca0132_hp_volume_get(struct snd_kcontrol *kcontrol, | 3317 | /* |
3318 | * Volume related | ||
3319 | */ | ||
3320 | static int ca0132_volume_info(struct snd_kcontrol *kcontrol, | ||
3321 | struct snd_ctl_elem_info *uinfo) | ||
3322 | { | ||
3323 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
3324 | struct ca0132_spec *spec = codec->spec; | ||
3325 | hda_nid_t nid = get_amp_nid(kcontrol); | ||
3326 | int ch = get_amp_channels(kcontrol); | ||
3327 | int dir = get_amp_direction(kcontrol); | ||
3328 | unsigned long pval; | ||
3329 | int err; | ||
3330 | |||
3331 | switch (nid) { | ||
3332 | case VNID_SPK: | ||
3333 | /* follow shared_out info */ | ||
3334 | nid = spec->shared_out_nid; | ||
3335 | mutex_lock(&codec->control_mutex); | ||
3336 | pval = kcontrol->private_value; | ||
3337 | kcontrol->private_value = HDA_COMPOSE_AMP_VAL(nid, ch, 0, dir); | ||
3338 | err = snd_hda_mixer_amp_volume_info(kcontrol, uinfo); | ||
3339 | kcontrol->private_value = pval; | ||
3340 | mutex_unlock(&codec->control_mutex); | ||
3341 | break; | ||
3342 | case VNID_MIC: | ||
3343 | /* follow shared_mic info */ | ||
3344 | nid = spec->shared_mic_nid; | ||
3345 | mutex_lock(&codec->control_mutex); | ||
3346 | pval = kcontrol->private_value; | ||
3347 | kcontrol->private_value = HDA_COMPOSE_AMP_VAL(nid, ch, 0, dir); | ||
3348 | err = snd_hda_mixer_amp_volume_info(kcontrol, uinfo); | ||
3349 | kcontrol->private_value = pval; | ||
3350 | mutex_unlock(&codec->control_mutex); | ||
3351 | break; | ||
3352 | default: | ||
3353 | err = snd_hda_mixer_amp_volume_info(kcontrol, uinfo); | ||
3354 | } | ||
3355 | return err; | ||
3356 | } | ||
3357 | |||
3358 | static int ca0132_volume_get(struct snd_kcontrol *kcontrol, | ||
3206 | struct snd_ctl_elem_value *ucontrol) | 3359 | struct snd_ctl_elem_value *ucontrol) |
3207 | { | 3360 | { |
3208 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 3361 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
3209 | struct ca0132_spec *spec = codec->spec; | 3362 | struct ca0132_spec *spec = codec->spec; |
3363 | hda_nid_t nid = get_amp_nid(kcontrol); | ||
3364 | int ch = get_amp_channels(kcontrol); | ||
3210 | long *valp = ucontrol->value.integer.value; | 3365 | long *valp = ucontrol->value.integer.value; |
3211 | 3366 | ||
3212 | *valp++ = spec->curr_hp_volume[0]; | 3367 | /* store the left and right volume */ |
3213 | *valp = spec->curr_hp_volume[1]; | 3368 | if (ch & 1) { |
3369 | *valp = spec->vnode_lvol[nid - VNODE_START_NID]; | ||
3370 | valp++; | ||
3371 | } | ||
3372 | if (ch & 2) { | ||
3373 | *valp = spec->vnode_rvol[nid - VNODE_START_NID]; | ||
3374 | valp++; | ||
3375 | } | ||
3214 | return 0; | 3376 | return 0; |
3215 | } | 3377 | } |
3216 | 3378 | ||
3217 | static int ca0132_hp_volume_put(struct snd_kcontrol *kcontrol, | 3379 | static int ca0132_volume_put(struct snd_kcontrol *kcontrol, |
3218 | struct snd_ctl_elem_value *ucontrol) | 3380 | struct snd_ctl_elem_value *ucontrol) |
3219 | { | 3381 | { |
3220 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 3382 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
3221 | struct ca0132_spec *spec = codec->spec; | 3383 | struct ca0132_spec *spec = codec->spec; |
3384 | hda_nid_t nid = get_amp_nid(kcontrol); | ||
3385 | int ch = get_amp_channels(kcontrol); | ||
3222 | long *valp = ucontrol->value.integer.value; | 3386 | long *valp = ucontrol->value.integer.value; |
3223 | long left_vol, right_vol; | 3387 | hda_nid_t shared_nid = 0; |
3224 | unsigned int data; | 3388 | bool effective; |
3225 | int val; | 3389 | int changed = 1; |
3226 | int err; | 3390 | |
3227 | 3391 | /* store the left and right volume */ | |
3228 | left_vol = *valp++; | 3392 | if (ch & 1) { |
3229 | right_vol = *valp; | 3393 | spec->vnode_lvol[nid - VNODE_START_NID] = *valp; |
3230 | 3394 | valp++; | |
3231 | /* any change? */ | 3395 | } |
3232 | if ((spec->curr_hp_volume[0] == left_vol) && | 3396 | if (ch & 2) { |
3233 | (spec->curr_hp_volume[1] == right_vol)) | 3397 | spec->vnode_rvol[nid - VNODE_START_NID] = *valp; |
3234 | return 0; | 3398 | valp++; |
3235 | 3399 | } | |
3236 | snd_hda_power_up(codec); | ||
3237 | |||
3238 | err = chipio_read(codec, REG_CODEC_HP_VOL_L, &data); | ||
3239 | if (err < 0) | ||
3240 | goto exit; | ||
3241 | |||
3242 | val = 31 - left_vol; | ||
3243 | data = (data & 0xe0) | val; | ||
3244 | err = chipio_write(codec, REG_CODEC_HP_VOL_L, data); | ||
3245 | if (err < 0) | ||
3246 | goto exit; | ||
3247 | |||
3248 | val = 31 - right_vol; | ||
3249 | data = (data & 0xe0) | val; | ||
3250 | err = chipio_write(codec, REG_CODEC_HP_VOL_R, data); | ||
3251 | if (err < 0) | ||
3252 | goto exit; | ||
3253 | 3400 | ||
3254 | spec->curr_hp_volume[0] = left_vol; | 3401 | /* if effective conditions, then update hw immediately. */ |
3255 | spec->curr_hp_volume[1] = right_vol; | 3402 | effective = ca0132_is_vnode_effective(codec, nid, &shared_nid); |
3403 | if (effective) { | ||
3404 | int dir = get_amp_direction(kcontrol); | ||
3405 | unsigned long pval; | ||
3406 | |||
3407 | snd_hda_power_up(codec); | ||
3408 | mutex_lock(&codec->control_mutex); | ||
3409 | pval = kcontrol->private_value; | ||
3410 | kcontrol->private_value = HDA_COMPOSE_AMP_VAL(shared_nid, ch, | ||
3411 | 0, dir); | ||
3412 | changed = snd_hda_mixer_amp_volume_put(kcontrol, ucontrol); | ||
3413 | kcontrol->private_value = pval; | ||
3414 | mutex_unlock(&codec->control_mutex); | ||
3415 | snd_hda_power_down(codec); | ||
3416 | } | ||
3256 | 3417 | ||
3257 | exit: | 3418 | return changed; |
3258 | snd_hda_power_down(codec); | ||
3259 | return err < 0 ? err : 1; | ||
3260 | } | 3419 | } |
3261 | 3420 | ||
3262 | static int add_hp_switch(struct hda_codec *codec, hda_nid_t nid) | 3421 | static int ca0132_volume_tlv(struct snd_kcontrol *kcontrol, int op_flag, |
3422 | unsigned int size, unsigned int __user *tlv) | ||
3263 | { | 3423 | { |
3264 | struct snd_kcontrol_new knew = | 3424 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
3265 | HDA_CODEC_MUTE_MONO("Headphone Playback Switch", | 3425 | struct ca0132_spec *spec = codec->spec; |
3266 | nid, 1, 0, HDA_OUTPUT); | 3426 | hda_nid_t nid = get_amp_nid(kcontrol); |
3267 | knew.get = ca0132_hp_switch_get; | 3427 | int ch = get_amp_channels(kcontrol); |
3268 | knew.put = ca0132_hp_switch_put; | 3428 | int dir = get_amp_direction(kcontrol); |
3269 | return snd_hda_ctl_add(codec, nid, snd_ctl_new1(&knew, codec)); | 3429 | unsigned long pval; |
3430 | int err; | ||
3431 | |||
3432 | switch (nid) { | ||
3433 | case VNID_SPK: | ||
3434 | /* follow shared_out tlv */ | ||
3435 | nid = spec->shared_out_nid; | ||
3436 | mutex_lock(&codec->control_mutex); | ||
3437 | pval = kcontrol->private_value; | ||
3438 | kcontrol->private_value = HDA_COMPOSE_AMP_VAL(nid, ch, 0, dir); | ||
3439 | err = snd_hda_mixer_amp_tlv(kcontrol, op_flag, size, tlv); | ||
3440 | kcontrol->private_value = pval; | ||
3441 | mutex_unlock(&codec->control_mutex); | ||
3442 | break; | ||
3443 | case VNID_MIC: | ||
3444 | /* follow shared_mic tlv */ | ||
3445 | nid = spec->shared_mic_nid; | ||
3446 | mutex_lock(&codec->control_mutex); | ||
3447 | pval = kcontrol->private_value; | ||
3448 | kcontrol->private_value = HDA_COMPOSE_AMP_VAL(nid, ch, 0, dir); | ||
3449 | err = snd_hda_mixer_amp_tlv(kcontrol, op_flag, size, tlv); | ||
3450 | kcontrol->private_value = pval; | ||
3451 | mutex_unlock(&codec->control_mutex); | ||
3452 | break; | ||
3453 | default: | ||
3454 | err = snd_hda_mixer_amp_tlv(kcontrol, op_flag, size, tlv); | ||
3455 | } | ||
3456 | return err; | ||
3270 | } | 3457 | } |
3271 | 3458 | ||
3272 | static int add_hp_volume(struct hda_codec *codec, hda_nid_t nid) | 3459 | static int add_fx_switch(struct hda_codec *codec, hda_nid_t nid, |
3460 | const char *pfx, int dir) | ||
3273 | { | 3461 | { |
3462 | char namestr[44]; | ||
3463 | int type = dir ? HDA_INPUT : HDA_OUTPUT; | ||
3274 | struct snd_kcontrol_new knew = | 3464 | struct snd_kcontrol_new knew = |
3275 | HDA_CODEC_VOLUME_MONO("Headphone Playback Volume", | 3465 | CA0132_CODEC_MUTE_MONO(namestr, nid, 1, type); |
3276 | nid, 3, 0, HDA_OUTPUT); | 3466 | sprintf(namestr, "%s %s Switch", pfx, dirstr[dir]); |
3277 | knew.get = ca0132_hp_volume_get; | ||
3278 | knew.put = ca0132_hp_volume_put; | ||
3279 | return snd_hda_ctl_add(codec, nid, snd_ctl_new1(&knew, codec)); | 3467 | return snd_hda_ctl_add(codec, nid, snd_ctl_new1(&knew, codec)); |
3280 | } | 3468 | } |
3281 | 3469 | ||
3282 | static int add_speaker_switch(struct hda_codec *codec, hda_nid_t nid) | 3470 | static int add_voicefx(struct hda_codec *codec) |
3283 | { | 3471 | { |
3284 | struct snd_kcontrol_new knew = | 3472 | struct snd_kcontrol_new knew = |
3285 | HDA_CODEC_MUTE_MONO("Speaker Playback Switch", | 3473 | HDA_CODEC_MUTE_MONO(ca0132_voicefx.name, |
3286 | nid, 1, 0, HDA_OUTPUT); | 3474 | VOICEFX, 1, 0, HDA_INPUT); |
3287 | knew.get = ca0132_speaker_switch_get; | 3475 | knew.info = ca0132_voicefx_info; |
3288 | knew.put = ca0132_speaker_switch_put; | 3476 | knew.get = ca0132_voicefx_get; |
3289 | return snd_hda_ctl_add(codec, nid, snd_ctl_new1(&knew, codec)); | 3477 | knew.put = ca0132_voicefx_put; |
3478 | return snd_hda_ctl_add(codec, VOICEFX, snd_ctl_new1(&knew, codec)); | ||
3290 | } | 3479 | } |
3291 | 3480 | ||
3292 | static void ca0132_fix_hp_caps(struct hda_codec *codec) | 3481 | /* |
3482 | * When changing Node IDs for Mixer Controls below, make sure to update | ||
3483 | * Node IDs in ca0132_config() as well. | ||
3484 | */ | ||
3485 | static struct snd_kcontrol_new ca0132_mixer[] = { | ||
3486 | CA0132_CODEC_VOL("Master Playback Volume", VNID_SPK, HDA_OUTPUT), | ||
3487 | CA0132_CODEC_MUTE("Master Playback Switch", VNID_SPK, HDA_OUTPUT), | ||
3488 | CA0132_CODEC_VOL("Capture Volume", VNID_MIC, HDA_INPUT), | ||
3489 | CA0132_CODEC_MUTE("Capture Switch", VNID_MIC, HDA_INPUT), | ||
3490 | HDA_CODEC_VOLUME("Analog-Mic2 Capture Volume", 0x08, 0, HDA_INPUT), | ||
3491 | HDA_CODEC_MUTE("Analog-Mic2 Capture Switch", 0x08, 0, HDA_INPUT), | ||
3492 | HDA_CODEC_VOLUME("What U Hear Capture Volume", 0x0a, 0, HDA_INPUT), | ||
3493 | HDA_CODEC_MUTE("What U Hear Capture Switch", 0x0a, 0, HDA_INPUT), | ||
3494 | CA0132_CODEC_MUTE_MONO("Mic1-Boost (30dB) Capture Switch", | ||
3495 | 0x12, 1, HDA_INPUT), | ||
3496 | CA0132_CODEC_MUTE_MONO("HP/Speaker Playback Switch", | ||
3497 | VNID_HP_SEL, 1, HDA_OUTPUT), | ||
3498 | CA0132_CODEC_MUTE_MONO("AMic1/DMic Capture Switch", | ||
3499 | VNID_AMIC1_SEL, 1, HDA_INPUT), | ||
3500 | CA0132_CODEC_MUTE_MONO("HP/Speaker Auto Detect Playback Switch", | ||
3501 | VNID_HP_ASEL, 1, HDA_OUTPUT), | ||
3502 | CA0132_CODEC_MUTE_MONO("AMic1/DMic Auto Detect Capture Switch", | ||
3503 | VNID_AMIC1_ASEL, 1, HDA_INPUT), | ||
3504 | { } /* end */ | ||
3505 | }; | ||
3506 | |||
3507 | /* | ||
3508 | */ | ||
3509 | static struct hda_pcm_stream ca0132_pcm_analog_playback = { | ||
3510 | .substreams = 1, | ||
3511 | .channels_min = 2, | ||
3512 | .channels_max = 2, | ||
3513 | .ops = { | ||
3514 | .open = ca0132_playback_pcm_open, | ||
3515 | .prepare = ca0132_playback_pcm_prepare, | ||
3516 | .cleanup = ca0132_playback_pcm_cleanup | ||
3517 | }, | ||
3518 | }; | ||
3519 | |||
3520 | static struct hda_pcm_stream ca0132_pcm_analog_capture = { | ||
3521 | .substreams = 1, | ||
3522 | .channels_min = 2, | ||
3523 | .channels_max = 2, | ||
3524 | }; | ||
3525 | |||
3526 | static struct hda_pcm_stream ca0132_pcm_digital_playback = { | ||
3527 | .substreams = 1, | ||
3528 | .channels_min = 2, | ||
3529 | .channels_max = 2, | ||
3530 | .ops = { | ||
3531 | .open = ca0132_dig_playback_pcm_open, | ||
3532 | .close = ca0132_dig_playback_pcm_close, | ||
3533 | .prepare = ca0132_dig_playback_pcm_prepare, | ||
3534 | .cleanup = ca0132_dig_playback_pcm_cleanup | ||
3535 | }, | ||
3536 | }; | ||
3537 | |||
3538 | static struct hda_pcm_stream ca0132_pcm_digital_capture = { | ||
3539 | .substreams = 1, | ||
3540 | .channels_min = 2, | ||
3541 | .channels_max = 2, | ||
3542 | }; | ||
3543 | |||
3544 | static int ca0132_build_pcms(struct hda_codec *codec) | ||
3293 | { | 3545 | { |
3294 | struct ca0132_spec *spec = codec->spec; | 3546 | struct ca0132_spec *spec = codec->spec; |
3295 | struct auto_pin_cfg *cfg = &spec->autocfg; | 3547 | struct hda_pcm *info = spec->pcm_rec; |
3296 | unsigned int caps; | 3548 | |
3549 | codec->pcm_info = info; | ||
3550 | codec->num_pcms = 0; | ||
3551 | |||
3552 | info->name = "CA0132 Analog"; | ||
3553 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ca0132_pcm_analog_playback; | ||
3554 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->dacs[0]; | ||
3555 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = | ||
3556 | spec->multiout.max_channels; | ||
3557 | info->stream[SNDRV_PCM_STREAM_CAPTURE] = ca0132_pcm_analog_capture; | ||
3558 | info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = spec->num_inputs; | ||
3559 | info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adcs[0]; | ||
3560 | codec->num_pcms++; | ||
3561 | |||
3562 | if (!spec->dig_out && !spec->dig_in) | ||
3563 | return 0; | ||
3564 | |||
3565 | info++; | ||
3566 | info->name = "CA0132 Digital"; | ||
3567 | info->pcm_type = HDA_PCM_TYPE_SPDIF; | ||
3568 | if (spec->dig_out) { | ||
3569 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = | ||
3570 | ca0132_pcm_digital_playback; | ||
3571 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->dig_out; | ||
3572 | } | ||
3573 | if (spec->dig_in) { | ||
3574 | info->stream[SNDRV_PCM_STREAM_CAPTURE] = | ||
3575 | ca0132_pcm_digital_capture; | ||
3576 | info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in; | ||
3577 | } | ||
3578 | codec->num_pcms++; | ||
3297 | 3579 | ||
3298 | /* set mute-capable, 1db step, 32 steps, ofs 6 */ | 3580 | return 0; |
3299 | caps = 0x80031f06; | ||
3300 | snd_hda_override_amp_caps(codec, cfg->hp_pins[0], HDA_OUTPUT, caps); | ||
3301 | } | 3581 | } |
3302 | 3582 | ||
3303 | static int ca0132_build_controls(struct hda_codec *codec) | 3583 | static int ca0132_build_controls(struct hda_codec *codec) |
3304 | { | 3584 | { |
3305 | struct ca0132_spec *spec = codec->spec; | 3585 | struct ca0132_spec *spec = codec->spec; |
3306 | struct auto_pin_cfg *cfg = &spec->autocfg; | 3586 | int i, num_fx; |
3307 | int i, err; | 3587 | int err = 0; |
3308 | 3588 | ||
3309 | if (spec->multiout.num_dacs) { | 3589 | /* Add Mixer controls */ |
3310 | err = add_speaker_switch(codec, spec->out_pins[0]); | 3590 | for (i = 0; i < spec->num_mixers; i++) { |
3591 | err = snd_hda_add_new_ctls(codec, spec->mixers[i]); | ||
3311 | if (err < 0) | 3592 | if (err < 0) |
3312 | return err; | 3593 | return err; |
3313 | } | 3594 | } |
3314 | 3595 | ||
3315 | if (cfg->hp_outs) { | 3596 | /* Add in and out effects controls. |
3316 | ca0132_fix_hp_caps(codec); | 3597 | * VoiceFX, PE and CrystalVoice are added separately. |
3317 | err = add_hp_switch(codec, cfg->hp_pins[0]); | 3598 | */ |
3318 | if (err < 0) | 3599 | num_fx = OUT_EFFECTS_COUNT + IN_EFFECTS_COUNT; |
3319 | return err; | 3600 | for (i = 0; i < num_fx; i++) { |
3320 | err = add_hp_volume(codec, cfg->hp_pins[0]); | 3601 | err = add_fx_switch(codec, ca0132_effects[i].nid, |
3602 | ca0132_effects[i].name, | ||
3603 | ca0132_effects[i].direct); | ||
3321 | if (err < 0) | 3604 | if (err < 0) |
3322 | return err; | 3605 | return err; |
3323 | } | 3606 | } |
3324 | 3607 | ||
3325 | for (i = 0; i < spec->num_inputs; i++) { | 3608 | err = add_fx_switch(codec, PLAY_ENHANCEMENT, "PlayEnhancement", 0); |
3326 | const char *label = spec->input_labels[i]; | 3609 | if (err < 0) |
3610 | return err; | ||
3327 | 3611 | ||
3328 | err = add_in_switch(codec, spec->adcs[i], label); | 3612 | err = add_fx_switch(codec, CRYSTAL_VOICE, "CrystalVoice", 1); |
3329 | if (err < 0) | 3613 | if (err < 0) |
3330 | return err; | 3614 | return err; |
3331 | err = add_in_volume(codec, spec->adcs[i], label); | 3615 | |
3332 | if (err < 0) | 3616 | add_voicefx(codec); |
3333 | return err; | 3617 | |
3334 | if (cfg->inputs[i].type == AUTO_PIN_MIC) { | 3618 | err = snd_hda_jack_add_kctls(codec, &spec->autocfg); |
3335 | /* add Mic-Boost */ | 3619 | if (err < 0) |
3336 | err = add_in_mono_volume(codec, spec->input_pins[i], | 3620 | return err; |
3337 | "Mic Boost", 1); | ||
3338 | if (err < 0) | ||
3339 | return err; | ||
3340 | } | ||
3341 | } | ||
3342 | 3621 | ||
3343 | if (spec->dig_out) { | 3622 | if (spec->dig_out) { |
3344 | err = snd_hda_create_spdif_out_ctls(codec, spec->dig_out, | 3623 | err = snd_hda_create_spdif_out_ctls(codec, spec->dig_out, |
@@ -3569,59 +3848,33 @@ static void ca0132_init_params(struct hda_codec *codec) | |||
3569 | chipio_set_control_param(codec, CONTROL_PARAM_PORTD_160OHM_GAIN, 6); | 3848 | chipio_set_control_param(codec, CONTROL_PARAM_PORTD_160OHM_GAIN, 6); |
3570 | } | 3849 | } |
3571 | 3850 | ||
3572 | static void ca0132_set_ct_ext(struct hda_codec *codec, int enable) | ||
3573 | { | ||
3574 | /* Set Creative extension */ | ||
3575 | snd_printdd("SET CREATIVE EXTENSION\n"); | ||
3576 | snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, | ||
3577 | VENDOR_CHIPIO_CT_EXTENSIONS_ENABLE, | ||
3578 | enable); | ||
3579 | msleep(20); | ||
3580 | } | ||
3581 | |||
3582 | |||
3583 | static void ca0132_config(struct hda_codec *codec) | 3851 | static void ca0132_config(struct hda_codec *codec) |
3584 | { | 3852 | { |
3585 | struct ca0132_spec *spec = codec->spec; | 3853 | struct ca0132_spec *spec = codec->spec; |
3586 | struct auto_pin_cfg *cfg = &spec->autocfg; | 3854 | struct auto_pin_cfg *cfg = &spec->autocfg; |
3587 | 3855 | ||
3588 | codec->no_sticky_stream = 1; | 3856 | spec->dacs[0] = 0x2; |
3589 | 3857 | spec->dacs[1] = 0x3; | |
3590 | /* line-outs */ | 3858 | spec->dacs[2] = 0x4; |
3591 | cfg->line_outs = 1; | ||
3592 | cfg->line_out_pins[0] = 0x0b; /* front */ | ||
3593 | cfg->line_out_type = AUTO_PIN_LINE_OUT; | ||
3594 | 3859 | ||
3595 | spec->dacs[0] = 0x02; | ||
3596 | spec->out_pins[0] = 0x0b; | ||
3597 | spec->multiout.dac_nids = spec->dacs; | 3860 | spec->multiout.dac_nids = spec->dacs; |
3598 | spec->multiout.num_dacs = 1; | 3861 | spec->multiout.num_dacs = 3; |
3599 | spec->multiout.max_channels = 2; | 3862 | spec->multiout.max_channels = 2; |
3600 | 3863 | ||
3601 | /* headphone */ | 3864 | spec->num_outputs = 2; |
3602 | cfg->hp_outs = 1; | 3865 | spec->out_pins[0] = 0x0b; /* speaker out */ |
3603 | cfg->hp_pins[0] = 0x0f; | 3866 | spec->out_pins[1] = 0x10; /* headphone out */ |
3604 | 3867 | spec->shared_out_nid = 0x2; | |
3605 | spec->hp_dac = 0; | ||
3606 | spec->multiout.hp_nid = 0; | ||
3607 | 3868 | ||
3608 | /* inputs */ | 3869 | spec->num_inputs = 3; |
3609 | cfg->num_inputs = 2; /* Mic-in and line-in */ | 3870 | spec->adcs[0] = 0x7; /* digital mic / analog mic1 */ |
3610 | cfg->inputs[0].pin = 0x12; | 3871 | spec->adcs[1] = 0x8; /* analog mic2 */ |
3611 | cfg->inputs[0].type = AUTO_PIN_MIC; | 3872 | spec->adcs[2] = 0xa; /* what u hear */ |
3612 | cfg->inputs[1].pin = 0x11; | 3873 | spec->shared_mic_nid = 0x7; |
3613 | cfg->inputs[1].type = AUTO_PIN_LINE_IN; | ||
3614 | 3874 | ||
3615 | /* Mic-in */ | ||
3616 | spec->input_pins[0] = 0x12; | 3875 | spec->input_pins[0] = 0x12; |
3617 | spec->input_labels[0] = "Mic"; | ||
3618 | spec->adcs[0] = 0x07; | ||
3619 | |||
3620 | /* Line-In */ | ||
3621 | spec->input_pins[1] = 0x11; | 3876 | spec->input_pins[1] = 0x11; |
3622 | spec->input_labels[1] = "Line"; | 3877 | spec->input_pins[2] = 0x13; |
3623 | spec->adcs[1] = 0x08; | ||
3624 | spec->num_inputs = 2; | ||
3625 | 3878 | ||
3626 | /* SPDIF I/O */ | 3879 | /* SPDIF I/O */ |
3627 | spec->dig_out = 0x05; | 3880 | spec->dig_out = 0x05; |
@@ -3866,6 +4119,9 @@ static int patch_ca0132(struct hda_codec *codec) | |||
3866 | return -ENOMEM; | 4119 | return -ENOMEM; |
3867 | codec->spec = spec; | 4120 | codec->spec = spec; |
3868 | 4121 | ||
4122 | spec->num_mixers = 1; | ||
4123 | spec->mixers[0] = ca0132_mixer; | ||
4124 | |||
3869 | spec->base_init_verbs = ca0132_base_init_verbs; | 4125 | spec->base_init_verbs = ca0132_base_init_verbs; |
3870 | spec->base_exit_verbs = ca0132_base_exit_verbs; | 4126 | spec->base_exit_verbs = ca0132_base_exit_verbs; |
3871 | spec->init_verbs[0] = ca0132_init_verbs0; | 4127 | spec->init_verbs[0] = ca0132_init_verbs0; |