#include <sound/core.h>
#include "hda_codec.h"
#include "hda_local.h"
+#include "hda_jack.h"
#include <sound/tlv.h>
/*
unsigned int gpio_mask;
unsigned int gpio_dir;
unsigned int gpio_data;
+ unsigned int gpio_eapd_hp; /* EAPD GPIO bit for headphones */
+ unsigned int gpio_eapd_speaker; /* EAPD GPIO bit for speakers */
struct hda_pcm pcm_rec[2]; /* PCM information */
CS420X_MBP53,
CS420X_MBP55,
CS420X_IMAC27,
+ CS420X_APPLE,
CS420X_AUTO,
CS420X_MODELS
};
if (uinfo->value.enumerated.item >= spec->num_inputs)
uinfo->value.enumerated.item = spec->num_inputs - 1;
idx = spec->input_idx[uinfo->value.enumerated.item];
- strcpy(uinfo->value.enumerated.name,
- hda_get_input_pin_label(codec, cfg->inputs[idx].pin, 1));
+ snd_hda_get_pin_label(codec, cfg->inputs[idx].pin, cfg,
+ uinfo->value.enumerated.name,
+ sizeof(uinfo->value.enumerated.name), NULL);
return 0;
}
spdif_present ? 0 : PIN_OUT);
}
}
- if (spec->board_config == CS420X_MBP53 ||
- spec->board_config == CS420X_MBP55 ||
- spec->board_config == CS420X_IMAC27) {
- unsigned int gpio = hp_present ? 0x02 : 0x08;
+ if (spec->gpio_eapd_hp) {
+ unsigned int gpio = hp_present ?
+ spec->gpio_eapd_hp : spec->gpio_eapd_speaker;
snd_hda_codec_write(codec, 0x01, 0,
AC_VERB_SET_GPIO_DATA, gpio);
}
if (!cfg->speaker_outs)
continue;
if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) {
- snd_hda_codec_write(codec, nid, 0,
- AC_VERB_SET_UNSOLICITED_ENABLE,
- AC_USRSP_EN | HP_EVENT);
+ snd_hda_jack_detect_enable(codec, nid, HP_EVENT);
spec->hp_detect = 1;
}
}
AC_VERB_SET_AMP_GAIN_MUTE,
AMP_IN_MUTE(spec->adc_idx[i]));
if (spec->mic_detect && spec->automic_idx == i)
- snd_hda_codec_write(codec, pin, 0,
- AC_VERB_SET_UNSOLICITED_ENABLE,
- AC_USRSP_EN | MIC_EVENT);
+ snd_hda_jack_detect_enable(codec, pin, MIC_EVENT);
}
/* specific to CS421x */
if (spec->vendor_nid == CS421X_VENDOR_NID) {
init_output(codec);
init_input(codec);
init_digital(codec);
+ snd_hda_jack_report_sync(codec);
+
return 0;
}
static int cs_build_controls(struct hda_codec *codec)
{
+ struct cs_spec *spec = codec->spec;
int err;
err = build_output(codec);
err = build_digital_input(codec);
if (err < 0)
return err;
- return cs_init(codec);
+ err = cs_init(codec);
+ if (err < 0)
+ return err;
+
+ err = snd_hda_jack_add_kctls(codec, &spec->autocfg);
+ if (err < 0)
+ return err;
+
+ return 0;
}
static void cs_free(struct hda_codec *codec)
static void cs_unsol_event(struct hda_codec *codec, unsigned int res)
{
- switch ((res >> 26) & 0x7f) {
+ switch (snd_hda_jack_get_action(codec, res >> 26)) {
case HP_EVENT:
cs_automute(codec);
break;
cs_automic(codec);
break;
}
+ snd_hda_jack_report_sync(codec);
}
static const struct hda_codec_ops cs_patch_ops = {
[CS420X_MBP53] = "mbp53",
[CS420X_MBP55] = "mbp55",
[CS420X_IMAC27] = "imac27",
+ [CS420X_APPLE] = "apple",
[CS420X_AUTO] = "auto",
};
SND_PCI_QUIRK(0x10de, 0x0d94, "MacBookAir 3,1(2)", CS420X_MBP55),
SND_PCI_QUIRK(0x10de, 0xcb79, "MacBookPro 5,5", CS420X_MBP55),
SND_PCI_QUIRK(0x10de, 0xcb89, "MacBookPro 7,1", CS420X_MBP55),
- SND_PCI_QUIRK(0x8086, 0x7270, "IMac 27 Inch", CS420X_IMAC27),
+ /* this conflicts with too many other models */
+ /*SND_PCI_QUIRK(0x8086, 0x7270, "IMac 27 Inch", CS420X_IMAC27),*/
+ {} /* terminator */
+};
+
+static const struct snd_pci_quirk cs420x_codec_cfg_tbl[] = {
+ SND_PCI_QUIRK_VENDOR(0x106b, "Apple", CS420X_APPLE),
{} /* terminator */
};
spec->board_config =
snd_hda_check_board_config(codec, CS420X_MODELS,
cs420x_models, cs420x_cfg_tbl);
+ if (spec->board_config < 0)
+ spec->board_config =
+ snd_hda_check_board_codec_sid_config(codec,
+ CS420X_MODELS, NULL, cs420x_codec_cfg_tbl);
if (spec->board_config >= 0)
fix_pincfg(codec, spec->board_config, cs_pincfgs);
case CS420X_IMAC27:
case CS420X_MBP53:
case CS420X_MBP55:
- /* GPIO1 = headphones */
- /* GPIO3 = speakers */
- spec->gpio_mask = 0x0a;
- spec->gpio_dir = 0x0a;
+ case CS420X_APPLE:
+ spec->gpio_eapd_hp = 2; /* GPIO1 = headphones */
+ spec->gpio_eapd_speaker = 8; /* GPIO3 = speakers */
+ spec->gpio_mask = spec->gpio_dir =
+ spec->gpio_eapd_hp | spec->gpio_eapd_speaker;
break;
}
if (!cfg->speaker_outs)
continue;
if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) {
-
- snd_hda_codec_write(codec, nid, 0,
- AC_VERB_SET_UNSOLICITED_ENABLE,
- AC_USRSP_EN | SPDIF_EVENT);
+ snd_hda_jack_detect_enable(codec, nid, SPDIF_EVENT);
spec->spdif_detect = 1;
}
}
init_output(codec);
init_input(codec);
init_cs421x_digital(codec);
+ snd_hda_jack_report_sync(codec);
return 0;
}
static int cs421x_build_controls(struct hda_codec *codec)
{
+ struct cs_spec *spec = codec->spec;
int err;
err = build_cs421x_output(codec);
err = build_digital_output(codec);
if (err < 0)
return err;
- return cs421x_init(codec);
+ err = cs421x_init(codec);
+ if (err < 0)
+ return err;
+
+ err = snd_hda_jack_add_kctls(codec, &spec->autocfg);
+ if (err < 0)
+ return err;
+
+ return 0;
}
static void cs421x_unsol_event(struct hda_codec *codec, unsigned int res)
{
- switch ((res >> 26) & 0x3f) {
+ switch (snd_hda_jack_get_action(codec, res >> 26)) {
case HP_EVENT:
case SPDIF_EVENT:
cs_automute(codec);
cs_automic(codec);
break;
}
+ snd_hda_jack_report_sync(codec);
}
static int parse_cs421x_input(struct hda_codec *codec)