aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/patch_ca0132.c
diff options
context:
space:
mode:
authorIan Minett <ian_minett@creativelabs.com>2012-12-20 21:53:38 -0500
committerTakashi Iwai <tiwai@suse.de>2013-01-15 11:00:31 -0500
commit44f0c9782cc6ab71ea947f8f710a46f2078a151c (patch)
treec87fb5354545147a272fbbedb1f10d1823bd990d /sound/pci/hda/patch_ca0132.c
parenta73d511c4867c5aa75a9ab50f7e73d5086c48cda (diff)
ALSA: hda/ca0132: Add tuning controls
This patch adds the controls used for tuning the DSP effects. 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.c289
1 files changed, 289 insertions, 0 deletions
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c
index 9ea5660e1a3a..c1391f43cc61 100644
--- a/sound/pci/hda/patch_ca0132.c
+++ b/sound/pci/hda/patch_ca0132.c
@@ -775,6 +775,10 @@ struct ca0132_spec {
775 long effects_switch[EFFECTS_COUNT]; 775 long effects_switch[EFFECTS_COUNT];
776 long voicefx_val; 776 long voicefx_val;
777 long cur_mic_boost; 777 long cur_mic_boost;
778
779#ifdef ENABLE_TUNING_CONTROLS
780 long cur_ctl_vals[TUNING_CTLS_COUNT];
781#endif
778}; 782};
779 783
780/* 784/*
@@ -2871,6 +2875,284 @@ static int ca0132_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
2871 return 0; 2875 return 0;
2872} 2876}
2873 2877
2878/* The followings are for tuning of products */
2879#ifdef ENABLE_TUNING_CONTROLS
2880
2881static unsigned int voice_focus_vals_lookup[] = {
28820x41A00000, 0x41A80000, 0x41B00000, 0x41B80000, 0x41C00000, 0x41C80000,
28830x41D00000, 0x41D80000, 0x41E00000, 0x41E80000, 0x41F00000, 0x41F80000,
28840x42000000, 0x42040000, 0x42080000, 0x420C0000, 0x42100000, 0x42140000,
28850x42180000, 0x421C0000, 0x42200000, 0x42240000, 0x42280000, 0x422C0000,
28860x42300000, 0x42340000, 0x42380000, 0x423C0000, 0x42400000, 0x42440000,
28870x42480000, 0x424C0000, 0x42500000, 0x42540000, 0x42580000, 0x425C0000,
28880x42600000, 0x42640000, 0x42680000, 0x426C0000, 0x42700000, 0x42740000,
28890x42780000, 0x427C0000, 0x42800000, 0x42820000, 0x42840000, 0x42860000,
28900x42880000, 0x428A0000, 0x428C0000, 0x428E0000, 0x42900000, 0x42920000,
28910x42940000, 0x42960000, 0x42980000, 0x429A0000, 0x429C0000, 0x429E0000,
28920x42A00000, 0x42A20000, 0x42A40000, 0x42A60000, 0x42A80000, 0x42AA0000,
28930x42AC0000, 0x42AE0000, 0x42B00000, 0x42B20000, 0x42B40000, 0x42B60000,
28940x42B80000, 0x42BA0000, 0x42BC0000, 0x42BE0000, 0x42C00000, 0x42C20000,
28950x42C40000, 0x42C60000, 0x42C80000, 0x42CA0000, 0x42CC0000, 0x42CE0000,
28960x42D00000, 0x42D20000, 0x42D40000, 0x42D60000, 0x42D80000, 0x42DA0000,
28970x42DC0000, 0x42DE0000, 0x42E00000, 0x42E20000, 0x42E40000, 0x42E60000,
28980x42E80000, 0x42EA0000, 0x42EC0000, 0x42EE0000, 0x42F00000, 0x42F20000,
28990x42F40000, 0x42F60000, 0x42F80000, 0x42FA0000, 0x42FC0000, 0x42FE0000,
29000x43000000, 0x43010000, 0x43020000, 0x43030000, 0x43040000, 0x43050000,
29010x43060000, 0x43070000, 0x43080000, 0x43090000, 0x430A0000, 0x430B0000,
29020x430C0000, 0x430D0000, 0x430E0000, 0x430F0000, 0x43100000, 0x43110000,
29030x43120000, 0x43130000, 0x43140000, 0x43150000, 0x43160000, 0x43170000,
29040x43180000, 0x43190000, 0x431A0000, 0x431B0000, 0x431C0000, 0x431D0000,
29050x431E0000, 0x431F0000, 0x43200000, 0x43210000, 0x43220000, 0x43230000,
29060x43240000, 0x43250000, 0x43260000, 0x43270000, 0x43280000, 0x43290000,
29070x432A0000, 0x432B0000, 0x432C0000, 0x432D0000, 0x432E0000, 0x432F0000,
29080x43300000, 0x43310000, 0x43320000, 0x43330000, 0x43340000
2909};
2910
2911static unsigned int mic_svm_vals_lookup[] = {
29120x00000000, 0x3C23D70A, 0x3CA3D70A, 0x3CF5C28F, 0x3D23D70A, 0x3D4CCCCD,
29130x3D75C28F, 0x3D8F5C29, 0x3DA3D70A, 0x3DB851EC, 0x3DCCCCCD, 0x3DE147AE,
29140x3DF5C28F, 0x3E051EB8, 0x3E0F5C29, 0x3E19999A, 0x3E23D70A, 0x3E2E147B,
29150x3E3851EC, 0x3E428F5C, 0x3E4CCCCD, 0x3E570A3D, 0x3E6147AE, 0x3E6B851F,
29160x3E75C28F, 0x3E800000, 0x3E851EB8, 0x3E8A3D71, 0x3E8F5C29, 0x3E947AE1,
29170x3E99999A, 0x3E9EB852, 0x3EA3D70A, 0x3EA8F5C3, 0x3EAE147B, 0x3EB33333,
29180x3EB851EC, 0x3EBD70A4, 0x3EC28F5C, 0x3EC7AE14, 0x3ECCCCCD, 0x3ED1EB85,
29190x3ED70A3D, 0x3EDC28F6, 0x3EE147AE, 0x3EE66666, 0x3EEB851F, 0x3EF0A3D7,
29200x3EF5C28F, 0x3EFAE148, 0x3F000000, 0x3F028F5C, 0x3F051EB8, 0x3F07AE14,
29210x3F0A3D71, 0x3F0CCCCD, 0x3F0F5C29, 0x3F11EB85, 0x3F147AE1, 0x3F170A3D,
29220x3F19999A, 0x3F1C28F6, 0x3F1EB852, 0x3F2147AE, 0x3F23D70A, 0x3F266666,
29230x3F28F5C3, 0x3F2B851F, 0x3F2E147B, 0x3F30A3D7, 0x3F333333, 0x3F35C28F,
29240x3F3851EC, 0x3F3AE148, 0x3F3D70A4, 0x3F400000, 0x3F428F5C, 0x3F451EB8,
29250x3F47AE14, 0x3F4A3D71, 0x3F4CCCCD, 0x3F4F5C29, 0x3F51EB85, 0x3F547AE1,
29260x3F570A3D, 0x3F59999A, 0x3F5C28F6, 0x3F5EB852, 0x3F6147AE, 0x3F63D70A,
29270x3F666666, 0x3F68F5C3, 0x3F6B851F, 0x3F6E147B, 0x3F70A3D7, 0x3F733333,
29280x3F75C28F, 0x3F7851EC, 0x3F7AE148, 0x3F7D70A4, 0x3F800000
2929};
2930
2931static unsigned int equalizer_vals_lookup[] = {
29320xC1C00000, 0xC1B80000, 0xC1B00000, 0xC1A80000, 0xC1A00000, 0xC1980000,
29330xC1900000, 0xC1880000, 0xC1800000, 0xC1700000, 0xC1600000, 0xC1500000,
29340xC1400000, 0xC1300000, 0xC1200000, 0xC1100000, 0xC1000000, 0xC0E00000,
29350xC0C00000, 0xC0A00000, 0xC0800000, 0xC0400000, 0xC0000000, 0xBF800000,
29360x00000000, 0x3F800000, 0x40000000, 0x40400000, 0x40800000, 0x40A00000,
29370x40C00000, 0x40E00000, 0x41000000, 0x41100000, 0x41200000, 0x41300000,
29380x41400000, 0x41500000, 0x41600000, 0x41700000, 0x41800000, 0x41880000,
29390x41900000, 0x41980000, 0x41A00000, 0x41A80000, 0x41B00000, 0x41B80000,
29400x41C00000
2941};
2942
2943static int tuning_ctl_set(struct hda_codec *codec, hda_nid_t nid,
2944 unsigned int *lookup, int idx)
2945{
2946 int i = 0;
2947
2948 for (i = 0; i < TUNING_CTLS_COUNT; i++)
2949 if (nid == ca0132_tuning_ctls[i].nid)
2950 break;
2951
2952 snd_hda_power_up(codec);
2953 dspio_set_param(codec, ca0132_tuning_ctls[i].mid,
2954 ca0132_tuning_ctls[i].req,
2955 &(lookup[idx]), sizeof(unsigned int));
2956 snd_hda_power_down(codec);
2957
2958 return 1;
2959}
2960
2961static int tuning_ctl_get(struct snd_kcontrol *kcontrol,
2962 struct snd_ctl_elem_value *ucontrol)
2963{
2964 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2965 struct ca0132_spec *spec = codec->spec;
2966 hda_nid_t nid = get_amp_nid(kcontrol);
2967 long *valp = ucontrol->value.integer.value;
2968 int idx = nid - TUNING_CTL_START_NID;
2969
2970 *valp = spec->cur_ctl_vals[idx];
2971 return 0;
2972}
2973
2974static int voice_focus_ctl_info(struct snd_kcontrol *kcontrol,
2975 struct snd_ctl_elem_info *uinfo)
2976{
2977 int chs = get_amp_channels(kcontrol);
2978 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2979 uinfo->count = chs == 3 ? 2 : 1;
2980 uinfo->value.integer.min = 20;
2981 uinfo->value.integer.max = 180;
2982 uinfo->value.integer.step = 1;
2983
2984 return 0;
2985}
2986
2987static int voice_focus_ctl_put(struct snd_kcontrol *kcontrol,
2988 struct snd_ctl_elem_value *ucontrol)
2989{
2990 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2991 struct ca0132_spec *spec = codec->spec;
2992 hda_nid_t nid = get_amp_nid(kcontrol);
2993 long *valp = ucontrol->value.integer.value;
2994 int idx;
2995
2996 idx = nid - TUNING_CTL_START_NID;
2997 /* any change? */
2998 if (spec->cur_ctl_vals[idx] == *valp)
2999 return 0;
3000
3001 spec->cur_ctl_vals[idx] = *valp;
3002
3003 idx = *valp - 20;
3004 tuning_ctl_set(codec, nid, voice_focus_vals_lookup, idx);
3005
3006 return 1;
3007}
3008
3009static int mic_svm_ctl_info(struct snd_kcontrol *kcontrol,
3010 struct snd_ctl_elem_info *uinfo)
3011{
3012 int chs = get_amp_channels(kcontrol);
3013 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
3014 uinfo->count = chs == 3 ? 2 : 1;
3015 uinfo->value.integer.min = 0;
3016 uinfo->value.integer.max = 100;
3017 uinfo->value.integer.step = 1;
3018
3019 return 0;
3020}
3021
3022static int mic_svm_ctl_put(struct snd_kcontrol *kcontrol,
3023 struct snd_ctl_elem_value *ucontrol)
3024{
3025 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3026 struct ca0132_spec *spec = codec->spec;
3027 hda_nid_t nid = get_amp_nid(kcontrol);
3028 long *valp = ucontrol->value.integer.value;
3029 int idx;
3030
3031 idx = nid - TUNING_CTL_START_NID;
3032 /* any change? */
3033 if (spec->cur_ctl_vals[idx] == *valp)
3034 return 0;
3035
3036 spec->cur_ctl_vals[idx] = *valp;
3037
3038 idx = *valp;
3039 tuning_ctl_set(codec, nid, mic_svm_vals_lookup, idx);
3040
3041 return 0;
3042}
3043
3044static int equalizer_ctl_info(struct snd_kcontrol *kcontrol,
3045 struct snd_ctl_elem_info *uinfo)
3046{
3047 int chs = get_amp_channels(kcontrol);
3048 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
3049 uinfo->count = chs == 3 ? 2 : 1;
3050 uinfo->value.integer.min = 0;
3051 uinfo->value.integer.max = 48;
3052 uinfo->value.integer.step = 1;
3053
3054 return 0;
3055}
3056
3057static int equalizer_ctl_put(struct snd_kcontrol *kcontrol,
3058 struct snd_ctl_elem_value *ucontrol)
3059{
3060 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3061 struct ca0132_spec *spec = codec->spec;
3062 hda_nid_t nid = get_amp_nid(kcontrol);
3063 long *valp = ucontrol->value.integer.value;
3064 int idx;
3065
3066 idx = nid - TUNING_CTL_START_NID;
3067 /* any change? */
3068 if (spec->cur_ctl_vals[idx] == *valp)
3069 return 0;
3070
3071 spec->cur_ctl_vals[idx] = *valp;
3072
3073 idx = *valp;
3074 tuning_ctl_set(codec, nid, equalizer_vals_lookup, idx);
3075
3076 return 1;
3077}
3078
3079static const DECLARE_TLV_DB_SCALE(voice_focus_db_scale, 2000, 100, 0);
3080static const DECLARE_TLV_DB_SCALE(eq_db_scale, -2400, 100, 0);
3081
3082static int add_tuning_control(struct hda_codec *codec,
3083 hda_nid_t pnid, hda_nid_t nid,
3084 const char *name, int dir)
3085{
3086 char namestr[44];
3087 int type = dir ? HDA_INPUT : HDA_OUTPUT;
3088 struct snd_kcontrol_new knew =
3089 HDA_CODEC_VOLUME_MONO(namestr, nid, 1, 0, type);
3090
3091 knew.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
3092 SNDRV_CTL_ELEM_ACCESS_TLV_READ;
3093 knew.tlv.c = 0;
3094 knew.tlv.p = 0;
3095 switch (pnid) {
3096 case VOICE_FOCUS:
3097 knew.info = voice_focus_ctl_info;
3098 knew.get = tuning_ctl_get;
3099 knew.put = voice_focus_ctl_put;
3100 knew.tlv.p = voice_focus_db_scale;
3101 break;
3102 case MIC_SVM:
3103 knew.info = mic_svm_ctl_info;
3104 knew.get = tuning_ctl_get;
3105 knew.put = mic_svm_ctl_put;
3106 break;
3107 case EQUALIZER:
3108 knew.info = equalizer_ctl_info;
3109 knew.get = tuning_ctl_get;
3110 knew.put = equalizer_ctl_put;
3111 knew.tlv.p = eq_db_scale;
3112 break;
3113 default:
3114 return 0;
3115 }
3116 knew.private_value =
3117 HDA_COMPOSE_AMP_VAL(nid, 1, 0, type);
3118 sprintf(namestr, "%s %s Volume", name, dirstr[dir]);
3119 return snd_hda_ctl_add(codec, nid, snd_ctl_new1(&knew, codec));
3120}
3121
3122static int add_tuning_ctls(struct hda_codec *codec)
3123{
3124 int i;
3125 int err;
3126
3127 for (i = 0; i < TUNING_CTLS_COUNT; i++) {
3128 err = add_tuning_control(codec,
3129 ca0132_tuning_ctls[i].parent_nid,
3130 ca0132_tuning_ctls[i].nid,
3131 ca0132_tuning_ctls[i].name,
3132 ca0132_tuning_ctls[i].direct);
3133 if (err < 0)
3134 return err;
3135 }
3136
3137 return 0;
3138}
3139
3140static void ca0132_init_tuning_defaults(struct hda_codec *codec)
3141{
3142 struct ca0132_spec *spec = codec->spec;
3143 int i;
3144
3145 /* Wedge Angle defaults to 30. 10 below is 30 - 20. 20 is min. */
3146 spec->cur_ctl_vals[WEDGE_ANGLE - TUNING_CTL_START_NID] = 10;
3147 /* SVM level defaults to 0.74. */
3148 spec->cur_ctl_vals[SVM_LEVEL - TUNING_CTL_START_NID] = 74;
3149
3150 /* EQ defaults to 0dB. */
3151 for (i = 2; i < TUNING_CTLS_COUNT; i++)
3152 spec->cur_ctl_vals[i] = 24;
3153}
3154#endif /*ENABLE_TUNING_CONTROLS*/
3155
2874/* 3156/*
2875 * Select the active output. 3157 * Select the active output.
2876 * If autodetect is enabled, output will be selected based on jack detection. 3158 * If autodetect is enabled, output will be selected based on jack detection.
@@ -3805,6 +4087,10 @@ static int ca0132_build_controls(struct hda_codec *codec)
3805 4087
3806 add_voicefx(codec); 4088 add_voicefx(codec);
3807 4089
4090#ifdef ENABLE_TUNING_CONTROLS
4091 add_tuning_ctls(codec);
4092#endif
4093
3808 err = snd_hda_jack_add_kctls(codec, &spec->autocfg); 4094 err = snd_hda_jack_add_kctls(codec, &spec->autocfg);
3809 if (err < 0) 4095 if (err < 0)
3810 return err; 4096 return err;
@@ -4184,6 +4470,9 @@ static void ca0132_init_chip(struct hda_codec *codec)
4184 spec->effects_switch[PLAY_ENHANCEMENT - EFFECT_START_NID] = 1; 4470 spec->effects_switch[PLAY_ENHANCEMENT - EFFECT_START_NID] = 1;
4185 spec->effects_switch[CRYSTAL_VOICE - EFFECT_START_NID] = 0; 4471 spec->effects_switch[CRYSTAL_VOICE - EFFECT_START_NID] = 0;
4186 4472
4473#ifdef ENABLE_TUNING_CONTROLS
4474 ca0132_init_tuning_defaults(codec);
4475#endif
4187} 4476}
4188 4477
4189static void ca0132_exit_chip(struct hda_codec *codec) 4478static void ca0132_exit_chip(struct hda_codec *codec)