*/
struct cs_spec {
+ int board_config;
struct auto_pin_cfg autocfg;
struct hda_multi_out multiout;
struct snd_kcontrol *vmaster_sw;
struct hda_bind_ctls *capture_bind[2];
+ unsigned int gpio_mask;
+ unsigned int gpio_dir;
+ unsigned int gpio_data;
+
struct hda_pcm pcm_rec[2]; /* PCM information */
unsigned int hp_detect:1;
unsigned int mic_detect:1;
};
+/* available models */
+enum {
+ CS420X_MBP55,
+ CS420X_AUTO,
+ CS420X_MODELS
+};
+
/* Vendor-specific processing widget */
#define CS420X_VENDOR_NID 0x11
#define CS_DIG_OUT1_PIN_NID 0x10
/* 0x0015 - visibility reg */
-static int cs_vendor_coef_get(struct hda_codec *codec, unsigned int idx)
+static inline int cs_vendor_coef_get(struct hda_codec *codec, unsigned int idx)
{
snd_hda_codec_write(codec, CS420X_VENDOR_NID, 0,
AC_VERB_SET_COEF_INDEX, idx);
AC_VERB_GET_PROC_COEF, 0);
}
-static void cs_vendor_coef_set(struct hda_codec *codec, unsigned int idx,
- unsigned int coef)
+static inline void cs_vendor_coef_set(struct hda_codec *codec, unsigned int idx,
+ unsigned int coef)
{
snd_hda_codec_write(codec, CS420X_VENDOR_NID, 0,
AC_VERB_SET_COEF_INDEX, idx);
static int is_active_pin(struct hda_codec *codec, hda_nid_t nid)
{
- struct cs_spec *spec = codec->spec;
unsigned int val;
val = snd_hda_codec_get_pincfg(codec, nid);
return (get_defcfg_connect(val) != AC_JACK_PORT_NONE);
{
struct cs_spec *spec = codec->spec;
struct auto_pin_cfg *cfg = &spec->autocfg;
- int i, err, extra_nids;
+ int i, extra_nids;
hda_nid_t dac;
for (i = 0; i < cfg->line_outs; i++) {
{
struct cs_spec *spec = codec->spec;
struct auto_pin_cfg *cfg = &spec->autocfg;
- int i, n, err;
+ int i;
for (i = 0; i < AUTO_PIN_LAST; i++) {
hda_nid_t pin = cfg->input_pins[i];
- struct snd_kcontrol *kctl;
if (!pin)
continue;
spec->input_idx[spec->num_inputs] = i;
struct cs_spec *spec = codec->spec;
struct auto_pin_cfg *cfg = &spec->autocfg;
hda_nid_t nid;
- int err;
if (!cfg->dig_outs)
return 0;
static int add_mute(struct hda_codec *codec, const char *name, int index,
unsigned int pval, int dir, struct snd_kcontrol **kctlp)
{
- char tmp[32];
+ char tmp[44];
struct snd_kcontrol_new knew =
HDA_CODEC_MUTE_IDX(tmp, index, 0, 0, HDA_OUTPUT);
knew.private_value = pval;
int force)
{
struct cs_spec *spec = codec->spec;
- struct auto_pin_cfg *cfg = &spec->autocfg;
if (spec->cur_input == idx && !force)
return 0;
struct cs_spec *spec = codec->spec;
int err;
+ if (!spec->multiout.dig_out_nid)
+ return 0;
+
err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
if (err < 0)
return err;
struct cs_spec *spec = codec->spec;
snd_hda_sequence_write(codec, cs_coef_init_verbs);
+
+ if (spec->gpio_mask) {
+ snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_MASK,
+ spec->gpio_mask);
+ snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DIRECTION,
+ spec->gpio_dir);
+ snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
+ spec->gpio_data);
+ }
+
init_output(codec);
init_input(codec);
init_digital(codec);
static int cs_build_controls(struct hda_codec *codec)
{
- struct cs_spec *spec = codec->spec;
int err;
err = build_output(codec);
int err;
err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
+ if (err < 0)
+ return err;
+
+ err = parse_output(codec);
+ if (err < 0)
+ return err;
+ err = parse_input(codec);
+ if (err < 0)
+ return err;
+ err = parse_digital_output(codec);
+ if (err < 0)
+ return err;
+ err = parse_digital_input(codec);
if (err < 0)
return err;
return 0;
}
+static const char *cs420x_models[CS420X_MODELS] = {
+ [CS420X_MBP55] = "mbp55",
+ [CS420X_AUTO] = "auto",
+};
+
+
+static struct snd_pci_quirk cs420x_cfg_tbl[] = {
+ SND_PCI_QUIRK(0x10de, 0xcb79, "MacBookPro 5,5", CS420X_MBP55),
+ {} /* terminator */
+};
+
+struct cs_pincfg {
+ hda_nid_t nid;
+ u32 val;
+};
+
+static struct cs_pincfg mbp55_pincfgs[] = {
+ { 0x09, 0x012b4030 },
+ { 0x0a, 0x90100121 },
+ { 0x0b, 0x90100120 },
+ { 0x0c, 0x400000f0 },
+ { 0x0d, 0x90a00110 },
+ { 0x0e, 0x400000f0 },
+ { 0x0f, 0x400000f0 },
+ { 0x10, 0x014be040 },
+ { 0x12, 0x400000f0 },
+ { 0x15, 0x400000f0 },
+ {} /* terminator */
+};
+
+static struct cs_pincfg *cs_pincfgs[CS420X_MODELS] = {
+ [CS420X_MBP55] = mbp55_pincfgs,
+};
+
+static void fix_pincfg(struct hda_codec *codec, int model)
+{
+ const struct cs_pincfg *cfg = cs_pincfgs[model];
+ if (!cfg)
+ return;
+ for (; cfg->nid; cfg++)
+ snd_hda_codec_set_pincfg(codec, cfg->nid, cfg->val);
+}
+
static int patch_cs420x(struct hda_codec *codec)
{
return -ENOMEM;
codec->spec = spec;
- err = cs_parse_auto_config(codec);
- if (err < 0)
- goto error;
+ spec->board_config =
+ snd_hda_check_board_config(codec, CS420X_MODELS,
+ cs420x_models, cs420x_cfg_tbl);
+ if (spec->board_config >= 0)
+ fix_pincfg(codec, spec->board_config);
+
+ switch (spec->board_config) {
+ case CS420X_MBP55:
+ /* GPIO3 = EAPD? */
+ spec->gpio_mask = 0x08;
+ spec->gpio_dir = 0x08;
+ spec->gpio_data = 0x08;
+ break;
+ }
- err = parse_output(codec);
- if (err < 0)
- goto error;
- err = parse_input(codec);
- if (err < 0)
- goto error;
- err = parse_digital_output(codec);
- if (err < 0)
- goto error;
- err = parse_digital_input(codec);
+ err = cs_parse_auto_config(codec);
if (err < 0)
goto error;