diff options
author | Ian Minett <ian_minett@creativelabs.com> | 2012-12-20 21:53:38 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2013-01-15 11:00:31 -0500 |
commit | 44f0c9782cc6ab71ea947f8f710a46f2078a151c (patch) | |
tree | c87fb5354545147a272fbbedb1f10d1823bd990d /sound/pci/hda/patch_ca0132.c | |
parent | a73d511c4867c5aa75a9ab50f7e73d5086c48cda (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.c | 289 |
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 | |||
2881 | static unsigned int voice_focus_vals_lookup[] = { | ||
2882 | 0x41A00000, 0x41A80000, 0x41B00000, 0x41B80000, 0x41C00000, 0x41C80000, | ||
2883 | 0x41D00000, 0x41D80000, 0x41E00000, 0x41E80000, 0x41F00000, 0x41F80000, | ||
2884 | 0x42000000, 0x42040000, 0x42080000, 0x420C0000, 0x42100000, 0x42140000, | ||
2885 | 0x42180000, 0x421C0000, 0x42200000, 0x42240000, 0x42280000, 0x422C0000, | ||
2886 | 0x42300000, 0x42340000, 0x42380000, 0x423C0000, 0x42400000, 0x42440000, | ||
2887 | 0x42480000, 0x424C0000, 0x42500000, 0x42540000, 0x42580000, 0x425C0000, | ||
2888 | 0x42600000, 0x42640000, 0x42680000, 0x426C0000, 0x42700000, 0x42740000, | ||
2889 | 0x42780000, 0x427C0000, 0x42800000, 0x42820000, 0x42840000, 0x42860000, | ||
2890 | 0x42880000, 0x428A0000, 0x428C0000, 0x428E0000, 0x42900000, 0x42920000, | ||
2891 | 0x42940000, 0x42960000, 0x42980000, 0x429A0000, 0x429C0000, 0x429E0000, | ||
2892 | 0x42A00000, 0x42A20000, 0x42A40000, 0x42A60000, 0x42A80000, 0x42AA0000, | ||
2893 | 0x42AC0000, 0x42AE0000, 0x42B00000, 0x42B20000, 0x42B40000, 0x42B60000, | ||
2894 | 0x42B80000, 0x42BA0000, 0x42BC0000, 0x42BE0000, 0x42C00000, 0x42C20000, | ||
2895 | 0x42C40000, 0x42C60000, 0x42C80000, 0x42CA0000, 0x42CC0000, 0x42CE0000, | ||
2896 | 0x42D00000, 0x42D20000, 0x42D40000, 0x42D60000, 0x42D80000, 0x42DA0000, | ||
2897 | 0x42DC0000, 0x42DE0000, 0x42E00000, 0x42E20000, 0x42E40000, 0x42E60000, | ||
2898 | 0x42E80000, 0x42EA0000, 0x42EC0000, 0x42EE0000, 0x42F00000, 0x42F20000, | ||
2899 | 0x42F40000, 0x42F60000, 0x42F80000, 0x42FA0000, 0x42FC0000, 0x42FE0000, | ||
2900 | 0x43000000, 0x43010000, 0x43020000, 0x43030000, 0x43040000, 0x43050000, | ||
2901 | 0x43060000, 0x43070000, 0x43080000, 0x43090000, 0x430A0000, 0x430B0000, | ||
2902 | 0x430C0000, 0x430D0000, 0x430E0000, 0x430F0000, 0x43100000, 0x43110000, | ||
2903 | 0x43120000, 0x43130000, 0x43140000, 0x43150000, 0x43160000, 0x43170000, | ||
2904 | 0x43180000, 0x43190000, 0x431A0000, 0x431B0000, 0x431C0000, 0x431D0000, | ||
2905 | 0x431E0000, 0x431F0000, 0x43200000, 0x43210000, 0x43220000, 0x43230000, | ||
2906 | 0x43240000, 0x43250000, 0x43260000, 0x43270000, 0x43280000, 0x43290000, | ||
2907 | 0x432A0000, 0x432B0000, 0x432C0000, 0x432D0000, 0x432E0000, 0x432F0000, | ||
2908 | 0x43300000, 0x43310000, 0x43320000, 0x43330000, 0x43340000 | ||
2909 | }; | ||
2910 | |||
2911 | static unsigned int mic_svm_vals_lookup[] = { | ||
2912 | 0x00000000, 0x3C23D70A, 0x3CA3D70A, 0x3CF5C28F, 0x3D23D70A, 0x3D4CCCCD, | ||
2913 | 0x3D75C28F, 0x3D8F5C29, 0x3DA3D70A, 0x3DB851EC, 0x3DCCCCCD, 0x3DE147AE, | ||
2914 | 0x3DF5C28F, 0x3E051EB8, 0x3E0F5C29, 0x3E19999A, 0x3E23D70A, 0x3E2E147B, | ||
2915 | 0x3E3851EC, 0x3E428F5C, 0x3E4CCCCD, 0x3E570A3D, 0x3E6147AE, 0x3E6B851F, | ||
2916 | 0x3E75C28F, 0x3E800000, 0x3E851EB8, 0x3E8A3D71, 0x3E8F5C29, 0x3E947AE1, | ||
2917 | 0x3E99999A, 0x3E9EB852, 0x3EA3D70A, 0x3EA8F5C3, 0x3EAE147B, 0x3EB33333, | ||
2918 | 0x3EB851EC, 0x3EBD70A4, 0x3EC28F5C, 0x3EC7AE14, 0x3ECCCCCD, 0x3ED1EB85, | ||
2919 | 0x3ED70A3D, 0x3EDC28F6, 0x3EE147AE, 0x3EE66666, 0x3EEB851F, 0x3EF0A3D7, | ||
2920 | 0x3EF5C28F, 0x3EFAE148, 0x3F000000, 0x3F028F5C, 0x3F051EB8, 0x3F07AE14, | ||
2921 | 0x3F0A3D71, 0x3F0CCCCD, 0x3F0F5C29, 0x3F11EB85, 0x3F147AE1, 0x3F170A3D, | ||
2922 | 0x3F19999A, 0x3F1C28F6, 0x3F1EB852, 0x3F2147AE, 0x3F23D70A, 0x3F266666, | ||
2923 | 0x3F28F5C3, 0x3F2B851F, 0x3F2E147B, 0x3F30A3D7, 0x3F333333, 0x3F35C28F, | ||
2924 | 0x3F3851EC, 0x3F3AE148, 0x3F3D70A4, 0x3F400000, 0x3F428F5C, 0x3F451EB8, | ||
2925 | 0x3F47AE14, 0x3F4A3D71, 0x3F4CCCCD, 0x3F4F5C29, 0x3F51EB85, 0x3F547AE1, | ||
2926 | 0x3F570A3D, 0x3F59999A, 0x3F5C28F6, 0x3F5EB852, 0x3F6147AE, 0x3F63D70A, | ||
2927 | 0x3F666666, 0x3F68F5C3, 0x3F6B851F, 0x3F6E147B, 0x3F70A3D7, 0x3F733333, | ||
2928 | 0x3F75C28F, 0x3F7851EC, 0x3F7AE148, 0x3F7D70A4, 0x3F800000 | ||
2929 | }; | ||
2930 | |||
2931 | static unsigned int equalizer_vals_lookup[] = { | ||
2932 | 0xC1C00000, 0xC1B80000, 0xC1B00000, 0xC1A80000, 0xC1A00000, 0xC1980000, | ||
2933 | 0xC1900000, 0xC1880000, 0xC1800000, 0xC1700000, 0xC1600000, 0xC1500000, | ||
2934 | 0xC1400000, 0xC1300000, 0xC1200000, 0xC1100000, 0xC1000000, 0xC0E00000, | ||
2935 | 0xC0C00000, 0xC0A00000, 0xC0800000, 0xC0400000, 0xC0000000, 0xBF800000, | ||
2936 | 0x00000000, 0x3F800000, 0x40000000, 0x40400000, 0x40800000, 0x40A00000, | ||
2937 | 0x40C00000, 0x40E00000, 0x41000000, 0x41100000, 0x41200000, 0x41300000, | ||
2938 | 0x41400000, 0x41500000, 0x41600000, 0x41700000, 0x41800000, 0x41880000, | ||
2939 | 0x41900000, 0x41980000, 0x41A00000, 0x41A80000, 0x41B00000, 0x41B80000, | ||
2940 | 0x41C00000 | ||
2941 | }; | ||
2942 | |||
2943 | static 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 | |||
2961 | static 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 | |||
2974 | static 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 | |||
2987 | static 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 | |||
3009 | static 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 | |||
3022 | static 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 | |||
3044 | static 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 | |||
3057 | static 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 | |||
3079 | static const DECLARE_TLV_DB_SCALE(voice_focus_db_scale, 2000, 100, 0); | ||
3080 | static const DECLARE_TLV_DB_SCALE(eq_db_scale, -2400, 100, 0); | ||
3081 | |||
3082 | static 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 | |||
3122 | static 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 | |||
3140 | static 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 | ||
4189 | static void ca0132_exit_chip(struct hda_codec *codec) | 4478 | static void ca0132_exit_chip(struct hda_codec *codec) |