aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorTim Howe <tim.howe@cirrus.com>2011-07-22 17:41:00 -0400
committerTakashi Iwai <tiwai@suse.de>2011-07-26 11:21:25 -0400
commit56487c279fe9fc23c5f15e2b935eb896ab7ba280 (patch)
tree3fbbba96894249c0615b279ae770941375c6fd4e /sound
parentb51beb756aaf0770e4fa8bb2cb142888051aa356 (diff)
ALSA: hda - Cirrus Logic CS421x support
This update includes the changes necessary for supporting the CS421x family of codecs. Previously this file only supported the CS420x family of codecs. This file also contains init verbs to correct several issues in the CS421x hardware. Behavior between the CS421x and CS420x codec families is similar, so several functions have been reused with "if" statements to determine which codec family (CS421x or CS420x) is present. Also, this file will be updated sometime in the near future in order to add support for a system using CS421x that requires mono mix on the speaker output only. [Fix const usages and adaption for new APIs by tiwai] Signed-off-by: Tim Howe <tim.howe@cirrus.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound')
-rw-r--r--sound/pci/hda/patch_cirrus.c743
1 files changed, 709 insertions, 34 deletions
diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c
index 7f93739b1e33..47d6ffc9b5b5 100644
--- a/sound/pci/hda/patch_cirrus.c
+++ b/sound/pci/hda/patch_cirrus.c
@@ -25,6 +25,7 @@
25#include <sound/core.h> 25#include <sound/core.h>
26#include "hda_codec.h" 26#include "hda_codec.h"
27#include "hda_local.h" 27#include "hda_local.h"
28#include <sound/tlv.h>
28 29
29/* 30/*
30 */ 31 */
@@ -61,9 +62,15 @@ struct cs_spec {
61 62
62 unsigned int hp_detect:1; 63 unsigned int hp_detect:1;
63 unsigned int mic_detect:1; 64 unsigned int mic_detect:1;
65 /* CS421x */
66 unsigned int spdif_detect:1;
67 unsigned int sense_b:1;
68 hda_nid_t vendor_nid;
69 struct hda_input_mux input_mux;
70 unsigned int last_input;
64}; 71};
65 72
66/* available models */ 73/* available models with CS420x */
67enum { 74enum {
68 CS420X_MBP53, 75 CS420X_MBP53,
69 CS420X_MBP55, 76 CS420X_MBP55,
@@ -72,6 +79,12 @@ enum {
72 CS420X_MODELS 79 CS420X_MODELS
73}; 80};
74 81
82/* CS421x boards */
83enum {
84 CS421X_CDB4210,
85 CS421X_MODELS
86};
87
75/* Vendor-specific processing widget */ 88/* Vendor-specific processing widget */
76#define CS420X_VENDOR_NID 0x11 89#define CS420X_VENDOR_NID 0x11
77#define CS_DIG_OUT1_PIN_NID 0x10 90#define CS_DIG_OUT1_PIN_NID 0x10
@@ -111,21 +124,42 @@ enum {
111/* 0x0009 - 0x0014 -> 12 test regs */ 124/* 0x0009 - 0x0014 -> 12 test regs */
112/* 0x0015 - visibility reg */ 125/* 0x0015 - visibility reg */
113 126
127/*
128 * Cirrus Logic CS4210
129 *
130 * 1 DAC => HP(sense) / Speakers,
131 * 1 ADC <= LineIn(sense) / MicIn / DMicIn,
132 * 1 SPDIF OUT => SPDIF Trasmitter(sense)
133*/
134#define CS4210_DAC_NID 0x02
135#define CS4210_ADC_NID 0x03
136#define CS421X_VENDOR_NID 0x0B
137#define CS421X_DMIC_PIN_NID 0x09 /* Port E */
138#define CS421X_SPDIF_PIN_NID 0x0A /* Port H */
139
140#define CS421X_IDX_DEV_CFG 0x01
141#define CS421X_IDX_ADC_CFG 0x02
142#define CS421X_IDX_DAC_CFG 0x03
143#define CS421X_IDX_SPK_CTL 0x04
144
145#define SPDIF_EVENT 0x04
114 146
115static inline int cs_vendor_coef_get(struct hda_codec *codec, unsigned int idx) 147static inline int cs_vendor_coef_get(struct hda_codec *codec, unsigned int idx)
116{ 148{
117 snd_hda_codec_write(codec, CS420X_VENDOR_NID, 0, 149 struct cs_spec *spec = codec->spec;
150 snd_hda_codec_write(codec, spec->vendor_nid, 0,
118 AC_VERB_SET_COEF_INDEX, idx); 151 AC_VERB_SET_COEF_INDEX, idx);
119 return snd_hda_codec_read(codec, CS420X_VENDOR_NID, 0, 152 return snd_hda_codec_read(codec, spec->vendor_nid, 0,
120 AC_VERB_GET_PROC_COEF, 0); 153 AC_VERB_GET_PROC_COEF, 0);
121} 154}
122 155
123static inline void cs_vendor_coef_set(struct hda_codec *codec, unsigned int idx, 156static inline void cs_vendor_coef_set(struct hda_codec *codec, unsigned int idx,
124 unsigned int coef) 157 unsigned int coef)
125{ 158{
126 snd_hda_codec_write(codec, CS420X_VENDOR_NID, 0, 159 struct cs_spec *spec = codec->spec;
160 snd_hda_codec_write(codec, spec->vendor_nid, 0,
127 AC_VERB_SET_COEF_INDEX, idx); 161 AC_VERB_SET_COEF_INDEX, idx);
128 snd_hda_codec_write(codec, CS420X_VENDOR_NID, 0, 162 snd_hda_codec_write(codec, spec->vendor_nid, 0,
129 AC_VERB_SET_PROC_COEF, coef); 163 AC_VERB_SET_PROC_COEF, coef);
130} 164}
131 165
@@ -347,15 +381,12 @@ static hda_nid_t get_adc(struct hda_codec *codec, hda_nid_t pin,
347 nid = codec->start_nid; 381 nid = codec->start_nid;
348 for (i = 0; i < codec->num_nodes; i++, nid++) { 382 for (i = 0; i < codec->num_nodes; i++, nid++) {
349 unsigned int type; 383 unsigned int type;
350 int idx;
351 type = get_wcaps_type(get_wcaps(codec, nid)); 384 type = get_wcaps_type(get_wcaps(codec, nid));
352 if (type != AC_WID_AUD_IN) 385 if (type != AC_WID_AUD_IN)
353 continue; 386 continue;
354 idx = snd_hda_get_conn_index(codec, nid, pin, 0); 387 *idxp = snd_hda_get_conn_index(codec, nid, pin, false);
355 if (idx >= 0) { 388 if (*idxp >= 0)
356 *idxp = idx;
357 return nid; 389 return nid;
358 }
359 } 390 }
360 return 0; 391 return 0;
361} 392}
@@ -835,6 +866,8 @@ static int build_digital_input(struct hda_codec *codec)
835 866
836/* 867/*
837 * auto-mute and auto-mic switching 868 * auto-mute and auto-mic switching
869 * CS421x auto-output redirecting
870 * HP/SPK/SPDIF
838 */ 871 */
839 872
840static void cs_automute(struct hda_codec *codec) 873static void cs_automute(struct hda_codec *codec)
@@ -842,9 +875,25 @@ static void cs_automute(struct hda_codec *codec)
842 struct cs_spec *spec = codec->spec; 875 struct cs_spec *spec = codec->spec;
843 struct auto_pin_cfg *cfg = &spec->autocfg; 876 struct auto_pin_cfg *cfg = &spec->autocfg;
844 unsigned int hp_present; 877 unsigned int hp_present;
878 unsigned int spdif_present;
845 hda_nid_t nid; 879 hda_nid_t nid;
846 int i; 880 int i;
847 881
882 spdif_present = 0;
883 if (cfg->dig_outs) {
884 nid = cfg->dig_out_pins[0];
885 if (is_jack_detectable(codec, nid)) {
886 /*
887 TODO: SPDIF output redirect when SENSE_B is enabled.
888 Shared (SENSE_A) jack (e.g HP/mini-TOSLINK)
889 assumed.
890 */
891 if (snd_hda_jack_detect(codec, nid)
892 /* && spec->sense_b */)
893 spdif_present = 1;
894 }
895 }
896
848 hp_present = 0; 897 hp_present = 0;
849 for (i = 0; i < cfg->hp_outs; i++) { 898 for (i = 0; i < cfg->hp_outs; i++) {
850 nid = cfg->hp_pins[i]; 899 nid = cfg->hp_pins[i];
@@ -854,11 +903,19 @@ static void cs_automute(struct hda_codec *codec)
854 if (hp_present) 903 if (hp_present)
855 break; 904 break;
856 } 905 }
906
907 /* mute speakers if spdif or hp jack is plugged in */
857 for (i = 0; i < cfg->speaker_outs; i++) { 908 for (i = 0; i < cfg->speaker_outs; i++) {
858 nid = cfg->speaker_pins[i]; 909 nid = cfg->speaker_pins[i];
859 snd_hda_codec_write(codec, nid, 0, 910 snd_hda_codec_write(codec, nid, 0,
860 AC_VERB_SET_PIN_WIDGET_CONTROL, 911 AC_VERB_SET_PIN_WIDGET_CONTROL,
861 hp_present ? 0 : PIN_OUT); 912 hp_present ? 0 : PIN_OUT);
913 /* detect on spdif is specific to CS421x */
914 if (spec->vendor_nid == CS421X_VENDOR_NID) {
915 snd_hda_codec_write(codec, nid, 0,
916 AC_VERB_SET_PIN_WIDGET_CONTROL,
917 spdif_present ? 0 : PIN_OUT);
918 }
862 } 919 }
863 if (spec->board_config == CS420X_MBP53 || 920 if (spec->board_config == CS420X_MBP53 ||
864 spec->board_config == CS420X_MBP55 || 921 spec->board_config == CS420X_MBP55 ||
@@ -867,21 +924,62 @@ static void cs_automute(struct hda_codec *codec)
867 snd_hda_codec_write(codec, 0x01, 0, 924 snd_hda_codec_write(codec, 0x01, 0,
868 AC_VERB_SET_GPIO_DATA, gpio); 925 AC_VERB_SET_GPIO_DATA, gpio);
869 } 926 }
927
928 /* specific to CS421x */
929 if (spec->vendor_nid == CS421X_VENDOR_NID) {
930 /* mute HPs if spdif jack (SENSE_B) is present */
931 for (i = 0; i < cfg->hp_outs; i++) {
932 nid = cfg->hp_pins[i];
933 snd_hda_codec_write(codec, nid, 0,
934 AC_VERB_SET_PIN_WIDGET_CONTROL,
935 (spdif_present && spec->sense_b) ? 0 : PIN_HP);
936 }
937
938 /* SPDIF TX on/off */
939 if (cfg->dig_outs) {
940 nid = cfg->dig_out_pins[0];
941 snd_hda_codec_write(codec, nid, 0,
942 AC_VERB_SET_PIN_WIDGET_CONTROL,
943 spdif_present ? PIN_OUT : 0);
944
945 }
946 /* Update board GPIOs if neccessary ... */
947 }
870} 948}
871 949
950/*
951 * Auto-input redirect for CS421x
952 * Switch max 3 inputs of a single ADC (nid 3)
953*/
954
872static void cs_automic(struct hda_codec *codec) 955static void cs_automic(struct hda_codec *codec)
873{ 956{
874 struct cs_spec *spec = codec->spec; 957 struct cs_spec *spec = codec->spec;
875 struct auto_pin_cfg *cfg = &spec->autocfg; 958 struct auto_pin_cfg *cfg = &spec->autocfg;
876 hda_nid_t nid; 959 hda_nid_t nid;
877 unsigned int present; 960 unsigned int present;
878 961
879 nid = cfg->inputs[spec->automic_idx].pin; 962 nid = cfg->inputs[spec->automic_idx].pin;
880 present = snd_hda_jack_detect(codec, nid); 963 present = snd_hda_jack_detect(codec, nid);
881 if (present) 964
882 change_cur_input(codec, spec->automic_idx, 0); 965 /* specific to CS421x, single ADC */
883 else 966 if (spec->vendor_nid == CS421X_VENDOR_NID) {
884 change_cur_input(codec, !spec->automic_idx, 0); 967 if (present) {
968 spec->last_input = spec->cur_input;
969 spec->cur_input = spec->automic_idx;
970 } else {
971 spec->cur_input = spec->last_input;
972 }
973
974 snd_hda_codec_write_cache(codec, spec->cur_adc, 0,
975 AC_VERB_SET_CONNECT_SEL,
976 spec->adc_idx[spec->cur_input]);
977 } else {
978 if (present)
979 change_cur_input(codec, spec->automic_idx, 0);
980 else
981 change_cur_input(codec, !spec->automic_idx, 0);
982 }
885} 983}
886 984
887/* 985/*
@@ -911,23 +1009,28 @@ static void init_output(struct hda_codec *codec)
911 for (i = 0; i < cfg->line_outs; i++) 1009 for (i = 0; i < cfg->line_outs; i++)
912 snd_hda_codec_write(codec, cfg->line_out_pins[i], 0, 1010 snd_hda_codec_write(codec, cfg->line_out_pins[i], 0,
913 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); 1011 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
1012 /* HP */
914 for (i = 0; i < cfg->hp_outs; i++) { 1013 for (i = 0; i < cfg->hp_outs; i++) {
915 hda_nid_t nid = cfg->hp_pins[i]; 1014 hda_nid_t nid = cfg->hp_pins[i];
916 snd_hda_codec_write(codec, nid, 0, 1015 snd_hda_codec_write(codec, nid, 0,
917 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP); 1016 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP);
918 if (!cfg->speaker_outs) 1017 if (!cfg->speaker_outs)
919 continue; 1018 continue;
920 if (is_jack_detectable(codec, nid)) { 1019 if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) {
921 snd_hda_codec_write(codec, nid, 0, 1020 snd_hda_codec_write(codec, nid, 0,
922 AC_VERB_SET_UNSOLICITED_ENABLE, 1021 AC_VERB_SET_UNSOLICITED_ENABLE,
923 AC_USRSP_EN | HP_EVENT); 1022 AC_USRSP_EN | HP_EVENT);
924 spec->hp_detect = 1; 1023 spec->hp_detect = 1;
925 } 1024 }
926 } 1025 }
1026
1027 /* Speaker */
927 for (i = 0; i < cfg->speaker_outs; i++) 1028 for (i = 0; i < cfg->speaker_outs; i++)
928 snd_hda_codec_write(codec, cfg->speaker_pins[i], 0, 1029 snd_hda_codec_write(codec, cfg->speaker_pins[i], 0,
929 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); 1030 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
930 if (spec->hp_detect) 1031
1032 /* SPDIF is enabled on presence detect for CS421x */
1033 if (spec->hp_detect || spec->spdif_detect)
931 cs_automute(codec); 1034 cs_automute(codec);
932} 1035}
933 1036
@@ -961,19 +1064,31 @@ static void init_input(struct hda_codec *codec)
961 AC_VERB_SET_UNSOLICITED_ENABLE, 1064 AC_VERB_SET_UNSOLICITED_ENABLE,
962 AC_USRSP_EN | MIC_EVENT); 1065 AC_USRSP_EN | MIC_EVENT);
963 } 1066 }
964 change_cur_input(codec, spec->cur_input, 1); 1067 /* specific to CS421x */
965 if (spec->mic_detect) 1068 if (spec->vendor_nid == CS421X_VENDOR_NID) {
966 cs_automic(codec); 1069 if (spec->mic_detect)
967 1070 cs_automic(codec);
968 coef = 0x000a; /* ADC1/2 - Digital and Analog Soft Ramp */ 1071 else {
969 if (is_active_pin(codec, CS_DMIC2_PIN_NID)) 1072 spec->cur_adc = spec->adc_nid[spec->cur_input];
970 coef |= 0x0500; /* DMIC2 enable 2 channels, disable GPIO1 */ 1073 snd_hda_codec_write(codec, spec->cur_adc, 0,
971 if (is_active_pin(codec, CS_DMIC1_PIN_NID)) 1074 AC_VERB_SET_CONNECT_SEL,
972 coef |= 0x1800; /* DMIC1 enable 2 channels, disable GPIO0 1075 spec->adc_idx[spec->cur_input]);
973 * No effect if SPDIF_OUT2 is selected in 1076 }
974 * IDX_SPDIF_CTL. 1077 } else {
975 */ 1078 change_cur_input(codec, spec->cur_input, 1);
976 cs_vendor_coef_set(codec, IDX_ADC_CFG, coef); 1079 if (spec->mic_detect)
1080 cs_automic(codec);
1081
1082 coef = 0x000a; /* ADC1/2 - Digital and Analog Soft Ramp */
1083 if (is_active_pin(codec, CS_DMIC2_PIN_NID))
1084 coef |= 0x0500; /* DMIC2 2 chan on, GPIO1 off */
1085 if (is_active_pin(codec, CS_DMIC1_PIN_NID))
1086 coef |= 0x1800; /* DMIC1 2 chan on, GPIO0 off
1087 * No effect if SPDIF_OUT2 is
1088 * selected in IDX_SPDIF_CTL.
1089 */
1090 cs_vendor_coef_set(codec, IDX_ADC_CFG, coef);
1091 }
977} 1092}
978 1093
979static const struct hda_verb cs_coef_init_verbs[] = { 1094static const struct hda_verb cs_coef_init_verbs[] = {
@@ -1221,16 +1336,16 @@ static const struct cs_pincfg *cs_pincfgs[CS420X_MODELS] = {
1221 [CS420X_IMAC27] = imac27_pincfgs, 1336 [CS420X_IMAC27] = imac27_pincfgs,
1222}; 1337};
1223 1338
1224static void fix_pincfg(struct hda_codec *codec, int model) 1339static void fix_pincfg(struct hda_codec *codec, int model,
1340 const struct cs_pincfg **pin_configs)
1225{ 1341{
1226 const struct cs_pincfg *cfg = cs_pincfgs[model]; 1342 const struct cs_pincfg *cfg = pin_configs[model];
1227 if (!cfg) 1343 if (!cfg)
1228 return; 1344 return;
1229 for (; cfg->nid; cfg++) 1345 for (; cfg->nid; cfg++)
1230 snd_hda_codec_set_pincfg(codec, cfg->nid, cfg->val); 1346 snd_hda_codec_set_pincfg(codec, cfg->nid, cfg->val);
1231} 1347}
1232 1348
1233
1234static int patch_cs420x(struct hda_codec *codec) 1349static int patch_cs420x(struct hda_codec *codec)
1235{ 1350{
1236 struct cs_spec *spec; 1351 struct cs_spec *spec;
@@ -1241,11 +1356,13 @@ static int patch_cs420x(struct hda_codec *codec)
1241 return -ENOMEM; 1356 return -ENOMEM;
1242 codec->spec = spec; 1357 codec->spec = spec;
1243 1358
1359 spec->vendor_nid = CS420X_VENDOR_NID;
1360
1244 spec->board_config = 1361 spec->board_config =
1245 snd_hda_check_board_config(codec, CS420X_MODELS, 1362 snd_hda_check_board_config(codec, CS420X_MODELS,
1246 cs420x_models, cs420x_cfg_tbl); 1363 cs420x_models, cs420x_cfg_tbl);
1247 if (spec->board_config >= 0) 1364 if (spec->board_config >= 0)
1248 fix_pincfg(codec, spec->board_config); 1365 fix_pincfg(codec, spec->board_config, cs_pincfgs);
1249 1366
1250 switch (spec->board_config) { 1367 switch (spec->board_config) {
1251 case CS420X_IMAC27: 1368 case CS420X_IMAC27:
@@ -1272,6 +1389,562 @@ static int patch_cs420x(struct hda_codec *codec)
1272 return err; 1389 return err;
1273} 1390}
1274 1391
1392/*
1393 * Cirrus Logic CS4210
1394 *
1395 * 1 DAC => HP(sense) / Speakers,
1396 * 1 ADC <= LineIn(sense) / MicIn / DMicIn,
1397 * 1 SPDIF OUT => SPDIF Trasmitter(sense)
1398*/
1399
1400/* CS4210 board names */
1401static const char *cs421x_models[CS421X_MODELS] = {
1402 [CS421X_CDB4210] = "cdb4210",
1403};
1404
1405static const struct snd_pci_quirk cs421x_cfg_tbl[] = {
1406 /* Test Intel board + CDB2410 */
1407 SND_PCI_QUIRK(0x8086, 0x5001, "DP45SG/CDB4210", CS421X_CDB4210),
1408 {} /* terminator */
1409};
1410
1411/* CS4210 board pinconfigs */
1412/* Default CS4210 (CDB4210)*/
1413static const struct cs_pincfg cdb4210_pincfgs[] = {
1414 { 0x05, 0x0321401f },
1415 { 0x06, 0x90170010 },
1416 { 0x07, 0x03813031 },
1417 { 0x08, 0xb7a70037 },
1418 { 0x09, 0xb7a6003e },
1419 { 0x0a, 0x034510f0 },
1420 {} /* terminator */
1421};
1422
1423static const struct cs_pincfg *cs421x_pincfgs[CS421X_MODELS] = {
1424 [CS421X_CDB4210] = cdb4210_pincfgs,
1425};
1426
1427static const struct hda_verb cs421x_coef_init_verbs[] = {
1428 {0x0B, AC_VERB_SET_PROC_STATE, 1},
1429 {0x0B, AC_VERB_SET_COEF_INDEX, CS421X_IDX_DEV_CFG},
1430 /*
1431 Disable Coefficient Index Auto-Increment(DAI)=1,
1432 PDREF=0
1433 */
1434 {0x0B, AC_VERB_SET_PROC_COEF, 0x0001 },
1435
1436 {0x0B, AC_VERB_SET_COEF_INDEX, CS421X_IDX_ADC_CFG},
1437 /* ADC SZCMode = Digital Soft Ramp */
1438 {0x0B, AC_VERB_SET_PROC_COEF, 0x0002 },
1439
1440 {0x0B, AC_VERB_SET_COEF_INDEX, CS421X_IDX_DAC_CFG},
1441 {0x0B, AC_VERB_SET_PROC_COEF,
1442 (0x0002 /* DAC SZCMode = Digital Soft Ramp */
1443 | 0x0004 /* Mute DAC on FIFO error */
1444 | 0x0008 /* Enable DAC High Pass Filter */
1445 )},
1446 {} /* terminator */
1447};
1448
1449/* Errata: CS4210 rev A1 Silicon
1450 *
1451 * http://www.cirrus.com/en/pubs/errata/
1452 *
1453 * Description:
1454 * 1. Performance degredation is present in the ADC.
1455 * 2. Speaker output is not completely muted upon HP detect.
1456 * 3. Noise is present when clipping occurs on the amplified
1457 * speaker outputs.
1458 *
1459 * Workaround:
1460 * The following verb sequence written to the registers during
1461 * initialization will correct the issues listed above.
1462 */
1463
1464static const struct hda_verb cs421x_coef_init_verbs_A1_silicon_fixes[] = {
1465 {0x0B, AC_VERB_SET_PROC_STATE, 0x01}, /* VPW: processing on */
1466
1467 {0x0B, AC_VERB_SET_COEF_INDEX, 0x0006},
1468 {0x0B, AC_VERB_SET_PROC_COEF, 0x9999}, /* Test mode: on */
1469
1470 {0x0B, AC_VERB_SET_COEF_INDEX, 0x000A},
1471 {0x0B, AC_VERB_SET_PROC_COEF, 0x14CB}, /* Chop double */
1472
1473 {0x0B, AC_VERB_SET_COEF_INDEX, 0x0011},
1474 {0x0B, AC_VERB_SET_PROC_COEF, 0xA2D0}, /* Increase ADC current */
1475
1476 {0x0B, AC_VERB_SET_COEF_INDEX, 0x001A},
1477 {0x0B, AC_VERB_SET_PROC_COEF, 0x02A9}, /* Mute speaker */
1478
1479 {0x0B, AC_VERB_SET_COEF_INDEX, 0x001B},
1480 {0x0B, AC_VERB_SET_PROC_COEF, 0X1006}, /* Remove noise */
1481
1482 {} /* terminator */
1483};
1484
1485/* Speaker Amp Gain is controlled by the vendor widget's coef 4 */
1486static const DECLARE_TLV_DB_SCALE(cs421x_speaker_boost_db_scale, 900, 300, 0);
1487
1488static int cs421x_boost_vol_info(struct snd_kcontrol *kcontrol,
1489 struct snd_ctl_elem_info *uinfo)
1490{
1491 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1492 uinfo->count = 1;
1493 uinfo->value.integer.min = 0;
1494 uinfo->value.integer.max = 3;
1495 return 0;
1496}
1497
1498static int cs421x_boost_vol_get(struct snd_kcontrol *kcontrol,
1499 struct snd_ctl_elem_value *ucontrol)
1500{
1501 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1502
1503 ucontrol->value.integer.value[0] =
1504 cs_vendor_coef_get(codec, CS421X_IDX_SPK_CTL) & 0x0003;
1505 return 0;
1506}
1507
1508static int cs421x_boost_vol_put(struct snd_kcontrol *kcontrol,
1509 struct snd_ctl_elem_value *ucontrol)
1510{
1511 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1512
1513 unsigned int vol = ucontrol->value.integer.value[0];
1514 unsigned int coef =
1515 cs_vendor_coef_get(codec, CS421X_IDX_SPK_CTL);
1516 unsigned int original_coef = coef;
1517
1518 coef &= ~0x0003;
1519 coef |= (vol & 0x0003);
1520 if (original_coef == coef)
1521 return 0;
1522 else {
1523 cs_vendor_coef_set(codec, CS421X_IDX_SPK_CTL, coef);
1524 return 1;
1525 }
1526}
1527
1528static const struct snd_kcontrol_new cs421x_speaker_bost_ctl = {
1529
1530 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1531 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1532 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1533 .name = "Speaker Boost Playback Volume",
1534 .info = cs421x_boost_vol_info,
1535 .get = cs421x_boost_vol_get,
1536 .put = cs421x_boost_vol_put,
1537 .tlv = { .p = cs421x_speaker_boost_db_scale },
1538};
1539
1540static void cs421x_pinmux_init(struct hda_codec *codec)
1541{
1542 struct cs_spec *spec = codec->spec;
1543 unsigned int def_conf, coef;
1544
1545 /* GPIO, DMIC_SCL, DMIC_SDA and SENSE_B are multiplexed */
1546 coef = cs_vendor_coef_get(codec, CS421X_IDX_DEV_CFG);
1547
1548 if (spec->gpio_mask)
1549 coef |= 0x0008; /* B1,B2 are GPIOs */
1550 else
1551 coef &= ~0x0008;
1552
1553 if (spec->sense_b)
1554 coef |= 0x0010; /* B2 is SENSE_B, not inverted */
1555 else
1556 coef &= ~0x0010;
1557
1558 cs_vendor_coef_set(codec, CS421X_IDX_DEV_CFG, coef);
1559
1560 if ((spec->gpio_mask || spec->sense_b) &&
1561 is_active_pin(codec, CS421X_DMIC_PIN_NID)) {
1562
1563 /*
1564 GPIO or SENSE_B forced - disconnect the DMIC pin.
1565 */
1566 def_conf = snd_hda_codec_get_pincfg(codec, CS421X_DMIC_PIN_NID);
1567 def_conf &= ~AC_DEFCFG_PORT_CONN;
1568 def_conf |= (AC_JACK_PORT_NONE << AC_DEFCFG_PORT_CONN_SHIFT);
1569 snd_hda_codec_set_pincfg(codec, CS421X_DMIC_PIN_NID, def_conf);
1570 }
1571}
1572
1573static void init_cs421x_digital(struct hda_codec *codec)
1574{
1575 struct cs_spec *spec = codec->spec;
1576 struct auto_pin_cfg *cfg = &spec->autocfg;
1577 int i;
1578
1579
1580 for (i = 0; i < cfg->dig_outs; i++) {
1581 hda_nid_t nid = cfg->dig_out_pins[i];
1582 if (!cfg->speaker_outs)
1583 continue;
1584 if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) {
1585
1586 snd_hda_codec_write(codec, nid, 0,
1587 AC_VERB_SET_UNSOLICITED_ENABLE,
1588 AC_USRSP_EN | SPDIF_EVENT);
1589 spec->spdif_detect = 1;
1590 }
1591 }
1592}
1593
1594static int cs421x_init(struct hda_codec *codec)
1595{
1596 struct cs_spec *spec = codec->spec;
1597
1598 snd_hda_sequence_write(codec, cs421x_coef_init_verbs);
1599 snd_hda_sequence_write(codec, cs421x_coef_init_verbs_A1_silicon_fixes);
1600
1601 cs421x_pinmux_init(codec);
1602
1603 if (spec->gpio_mask) {
1604 snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_MASK,
1605 spec->gpio_mask);
1606 snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DIRECTION,
1607 spec->gpio_dir);
1608 snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
1609 spec->gpio_data);
1610 }
1611
1612 init_output(codec);
1613 init_input(codec);
1614 init_cs421x_digital(codec);
1615
1616 return 0;
1617}
1618
1619/*
1620 * CS4210 Input MUX (1 ADC)
1621 */
1622static int cs421x_mux_enum_info(struct snd_kcontrol *kcontrol,
1623 struct snd_ctl_elem_info *uinfo)
1624{
1625 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1626 struct cs_spec *spec = codec->spec;
1627
1628 return snd_hda_input_mux_info(&spec->input_mux, uinfo);
1629}
1630
1631static int cs421x_mux_enum_get(struct snd_kcontrol *kcontrol,
1632 struct snd_ctl_elem_value *ucontrol)
1633{
1634 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1635 struct cs_spec *spec = codec->spec;
1636
1637 ucontrol->value.enumerated.item[0] = spec->cur_input;
1638 return 0;
1639}
1640
1641static int cs421x_mux_enum_put(struct snd_kcontrol *kcontrol,
1642 struct snd_ctl_elem_value *ucontrol)
1643{
1644 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1645 struct cs_spec *spec = codec->spec;
1646
1647 return snd_hda_input_mux_put(codec, &spec->input_mux, ucontrol,
1648 spec->adc_nid[0], &spec->cur_input);
1649
1650}
1651
1652static struct snd_kcontrol_new cs421x_capture_source = {
1653
1654 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1655 .name = "Capture Source",
1656 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
1657 .info = cs421x_mux_enum_info,
1658 .get = cs421x_mux_enum_get,
1659 .put = cs421x_mux_enum_put,
1660};
1661
1662static int cs421x_add_input_volume_control(struct hda_codec *codec, int item)
1663{
1664 struct cs_spec *spec = codec->spec;
1665 struct auto_pin_cfg *cfg = &spec->autocfg;
1666 const struct hda_input_mux *imux = &spec->input_mux;
1667 hda_nid_t pin = cfg->inputs[item].pin;
1668 struct snd_kcontrol *kctl;
1669 u32 caps;
1670
1671 if (!(get_wcaps(codec, pin) & AC_WCAP_IN_AMP))
1672 return 0;
1673
1674 caps = query_amp_caps(codec, pin, HDA_INPUT);
1675 caps = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
1676 if (caps <= 1)
1677 return 0;
1678
1679 return add_volume(codec, imux->items[item].label, 0,
1680 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_INPUT), 1, &kctl);
1681}
1682
1683/* add a (input-boost) volume control to the given input pin */
1684static int build_cs421x_input(struct hda_codec *codec)
1685{
1686 struct cs_spec *spec = codec->spec;
1687 struct auto_pin_cfg *cfg = &spec->autocfg;
1688 struct hda_input_mux *imux = &spec->input_mux;
1689 int i, err, type_idx;
1690 const char *label;
1691
1692 if (!spec->num_inputs)
1693 return 0;
1694
1695 /* make bind-capture */
1696 spec->capture_bind[0] = make_bind_capture(codec, &snd_hda_bind_sw);
1697 spec->capture_bind[1] = make_bind_capture(codec, &snd_hda_bind_vol);
1698 for (i = 0; i < 2; i++) {
1699 struct snd_kcontrol *kctl;
1700 int n;
1701 if (!spec->capture_bind[i])
1702 return -ENOMEM;
1703 kctl = snd_ctl_new1(&cs_capture_ctls[i], codec);
1704 if (!kctl)
1705 return -ENOMEM;
1706 kctl->private_value = (long)spec->capture_bind[i];
1707 err = snd_hda_ctl_add(codec, 0, kctl);
1708 if (err < 0)
1709 return err;
1710 for (n = 0; n < AUTO_PIN_LAST; n++) {
1711 if (!spec->adc_nid[n])
1712 continue;
1713 err = snd_hda_add_nid(codec, kctl, 0, spec->adc_nid[n]);
1714 if (err < 0)
1715 return err;
1716 }
1717 }
1718
1719 /* Add Input MUX Items + Capture Volume/Switch */
1720 for (i = 0; i < spec->num_inputs; i++) {
1721 label = hda_get_autocfg_input_label(codec, cfg, i);
1722 snd_hda_add_imux_item(imux, label, spec->adc_idx[i], &type_idx);
1723
1724 err = cs421x_add_input_volume_control(codec, i);
1725 if (err < 0)
1726 return err;
1727 }
1728
1729 /*
1730 Add 'Capture Source' Switch if
1731 * 2 inputs and no mic detec
1732 * 3 inputs
1733 */
1734 if ((spec->num_inputs == 2 && !spec->mic_detect) ||
1735 (spec->num_inputs == 3)) {
1736
1737 err = snd_hda_ctl_add(codec, spec->adc_nid[0],
1738 snd_ctl_new1(&cs421x_capture_source, codec));
1739 if (err < 0)
1740 return err;
1741 }
1742
1743 return 0;
1744}
1745
1746/* Single DAC (Mute/Gain) */
1747static int build_cs421x_output(struct hda_codec *codec)
1748{
1749 hda_nid_t dac = CS4210_DAC_NID;
1750 struct cs_spec *spec = codec->spec;
1751 struct auto_pin_cfg *cfg = &spec->autocfg;
1752 struct snd_kcontrol *kctl;
1753 int err;
1754 char *name = "HP/Speakers";
1755
1756 fix_volume_caps(codec, dac);
1757 if (!spec->vmaster_sw) {
1758 err = add_vmaster(codec, dac);
1759 if (err < 0)
1760 return err;
1761 }
1762
1763 err = add_mute(codec, name, 0,
1764 HDA_COMPOSE_AMP_VAL(dac, 3, 0, HDA_OUTPUT), 0, &kctl);
1765 if (err < 0)
1766 return err;
1767 err = snd_ctl_add_slave(spec->vmaster_sw, kctl);
1768 if (err < 0)
1769 return err;
1770
1771 err = add_volume(codec, name, 0,
1772 HDA_COMPOSE_AMP_VAL(dac, 3, 0, HDA_OUTPUT), 0, &kctl);
1773 if (err < 0)
1774 return err;
1775 err = snd_ctl_add_slave(spec->vmaster_vol, kctl);
1776 if (err < 0)
1777 return err;
1778
1779 if (cfg->speaker_outs) {
1780 err = snd_hda_ctl_add(codec, 0,
1781 snd_ctl_new1(&cs421x_speaker_bost_ctl, codec));
1782 if (err < 0)
1783 return err;
1784 }
1785 return err;
1786}
1787
1788static int cs421x_build_controls(struct hda_codec *codec)
1789{
1790 int err;
1791
1792 err = build_cs421x_output(codec);
1793 if (err < 0)
1794 return err;
1795 err = build_cs421x_input(codec);
1796 if (err < 0)
1797 return err;
1798 err = build_digital_output(codec);
1799 if (err < 0)
1800 return err;
1801 return cs421x_init(codec);
1802}
1803
1804static void cs421x_unsol_event(struct hda_codec *codec, unsigned int res)
1805{
1806 switch ((res >> 26) & 0x3f) {
1807 case HP_EVENT:
1808 case SPDIF_EVENT:
1809 cs_automute(codec);
1810 break;
1811
1812 case MIC_EVENT:
1813 cs_automic(codec);
1814 break;
1815 }
1816}
1817
1818static int parse_cs421x_input(struct hda_codec *codec)
1819{
1820 struct cs_spec *spec = codec->spec;
1821 struct auto_pin_cfg *cfg = &spec->autocfg;
1822 int i;
1823
1824 for (i = 0; i < cfg->num_inputs; i++) {
1825 hda_nid_t pin = cfg->inputs[i].pin;
1826 spec->adc_nid[i] = get_adc(codec, pin, &spec->adc_idx[i]);
1827 spec->cur_input = spec->last_input = i;
1828 spec->num_inputs++;
1829
1830 /* check whether the automatic mic switch is available */
1831 if (is_ext_mic(codec, i) && cfg->num_inputs >= 2) {
1832 spec->mic_detect = 1;
1833 spec->automic_idx = i;
1834 }
1835 }
1836 return 0;
1837}
1838
1839static int cs421x_parse_auto_config(struct hda_codec *codec)
1840{
1841 struct cs_spec *spec = codec->spec;
1842 int err;
1843
1844 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
1845 if (err < 0)
1846 return err;
1847 err = parse_output(codec);
1848 if (err < 0)
1849 return err;
1850 err = parse_cs421x_input(codec);
1851 if (err < 0)
1852 return err;
1853 err = parse_digital_output(codec);
1854 if (err < 0)
1855 return err;
1856 return 0;
1857}
1858
1859#ifdef CONFIG_PM
1860/*
1861 Manage PDREF, when transitioning to D3hot
1862 (DAC,ADC) -> D3, PDREF=1, AFG->D3
1863*/
1864static int cs421x_suspend(struct hda_codec *codec, pm_message_t state)
1865{
1866 unsigned int coef;
1867
1868 snd_hda_shutup_pins(codec);
1869
1870 snd_hda_codec_write(codec, CS4210_DAC_NID, 0,
1871 AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
1872 snd_hda_codec_write(codec, CS4210_ADC_NID, 0,
1873 AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
1874
1875 coef = cs_vendor_coef_get(codec, CS421X_IDX_DEV_CFG);
1876 coef |= 0x0004; /* PDREF */
1877 cs_vendor_coef_set(codec, CS421X_IDX_DEV_CFG, coef);
1878
1879 return 0;
1880}
1881#endif
1882
1883static struct hda_codec_ops cs4210_patch_ops = {
1884 .build_controls = cs421x_build_controls,
1885 .build_pcms = cs_build_pcms,
1886 .init = cs421x_init,
1887 .free = cs_free,
1888 .unsol_event = cs421x_unsol_event,
1889#ifdef CONFIG_PM
1890 .suspend = cs421x_suspend,
1891#endif
1892};
1893
1894static int patch_cs421x(struct hda_codec *codec)
1895{
1896 struct cs_spec *spec;
1897 int err;
1898
1899 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1900 if (!spec)
1901 return -ENOMEM;
1902 codec->spec = spec;
1903
1904 spec->vendor_nid = CS421X_VENDOR_NID;
1905
1906 spec->board_config =
1907 snd_hda_check_board_config(codec, CS421X_MODELS,
1908 cs421x_models, cs421x_cfg_tbl);
1909 if (spec->board_config >= 0)
1910 fix_pincfg(codec, spec->board_config, cs421x_pincfgs);
1911 /*
1912 Setup GPIO/SENSE for each board (if used)
1913 */
1914 switch (spec->board_config) {
1915 case CS421X_CDB4210:
1916 snd_printd("CS4210 board: %s\n",
1917 cs421x_models[spec->board_config]);
1918/* spec->gpio_mask = 3;
1919 spec->gpio_dir = 3;
1920 spec->gpio_data = 3;
1921*/
1922 spec->sense_b = 1;
1923
1924 break;
1925 }
1926
1927 /*
1928 Update the GPIO/DMIC/SENSE_B pinmux before the configuration
1929 is auto-parsed. If GPIO or SENSE_B is forced, DMIC input
1930 is disabled.
1931 */
1932 cs421x_pinmux_init(codec);
1933
1934 err = cs421x_parse_auto_config(codec);
1935 if (err < 0)
1936 goto error;
1937
1938 codec->patch_ops = cs4210_patch_ops;
1939
1940 return 0;
1941
1942 error:
1943 kfree(codec->spec);
1944 codec->spec = NULL;
1945 return err;
1946}
1947
1275 1948
1276/* 1949/*
1277 * patch entries 1950 * patch entries
@@ -1279,11 +1952,13 @@ static int patch_cs420x(struct hda_codec *codec)
1279static const struct hda_codec_preset snd_hda_preset_cirrus[] = { 1952static const struct hda_codec_preset snd_hda_preset_cirrus[] = {
1280 { .id = 0x10134206, .name = "CS4206", .patch = patch_cs420x }, 1953 { .id = 0x10134206, .name = "CS4206", .patch = patch_cs420x },
1281 { .id = 0x10134207, .name = "CS4207", .patch = patch_cs420x }, 1954 { .id = 0x10134207, .name = "CS4207", .patch = patch_cs420x },
1955 { .id = 0x10134210, .name = "CS4210", .patch = patch_cs421x },
1282 {} /* terminator */ 1956 {} /* terminator */
1283}; 1957};
1284 1958
1285MODULE_ALIAS("snd-hda-codec-id:10134206"); 1959MODULE_ALIAS("snd-hda-codec-id:10134206");
1286MODULE_ALIAS("snd-hda-codec-id:10134207"); 1960MODULE_ALIAS("snd-hda-codec-id:10134207");
1961MODULE_ALIAS("snd-hda-codec-id:10134210");
1287 1962
1288MODULE_LICENSE("GPL"); 1963MODULE_LICENSE("GPL");
1289MODULE_DESCRIPTION("Cirrus Logic HD-audio codec"); 1964MODULE_DESCRIPTION("Cirrus Logic HD-audio codec");