提交 a91a4aa1 编写于 作者: T Takashi Iwai

Merge branch 'topic/hda' into for-linus

...@@ -124,6 +124,8 @@ ALC882/883/885/888/889 ...@@ -124,6 +124,8 @@ ALC882/883/885/888/889
asus-a7m ASUS A7M asus-a7m ASUS A7M
macpro MacPro support macpro MacPro support
mb5 Macbook 5,1 mb5 Macbook 5,1
macmini3 Macmini 3,1
mba21 Macbook Air 2,1
mbp3 Macbook Pro rev3 mbp3 Macbook Pro rev3
imac24 iMac 24'' with jack detection imac24 iMac 24'' with jack detection
imac91 iMac 9,1 imac91 iMac 9,1
...@@ -279,13 +281,16 @@ Conexant 5051 ...@@ -279,13 +281,16 @@ Conexant 5051
laptop Basic Laptop config (default) laptop Basic Laptop config (default)
hp HP Spartan laptop hp HP Spartan laptop
hp-dv6736 HP dv6736 hp-dv6736 HP dv6736
hp-f700 HP Compaq Presario F700
lenovo-x200 Lenovo X200 laptop lenovo-x200 Lenovo X200 laptop
toshiba Toshiba Satellite M300
Conexant 5066 Conexant 5066
============= =============
laptop Basic Laptop config (default) laptop Basic Laptop config (default)
dell-laptop Dell laptops dell-laptop Dell laptops
olpc-xo-1_5 OLPC XO 1.5 olpc-xo-1_5 OLPC XO 1.5
ideapad Lenovo IdeaPad U150
STAC9200 STAC9200
======== ========
......
...@@ -452,6 +452,33 @@ Similarly, the lines after `[verb]` are parsed as `init_verbs` ...@@ -452,6 +452,33 @@ Similarly, the lines after `[verb]` are parsed as `init_verbs`
sysfs entries, and the lines after `[hint]` are parsed as `hints` sysfs entries, and the lines after `[hint]` are parsed as `hints`
sysfs entries, respectively. sysfs entries, respectively.
Another example to override the codec vendor id from 0x12345678 to
0xdeadbeef is like below:
------------------------------------------------------------------------
[codec]
0x12345678 0xabcd1234 2
[vendor_id]
0xdeadbeef
------------------------------------------------------------------------
In the similar way, you can override the codec subsystem_id via
`[subsystem_id]`, the revision id via `[revision_id]` line.
Also, the codec chip name can be rewritten via `[chip_name]` line.
------------------------------------------------------------------------
[codec]
0x12345678 0xabcd1234 2
[subsystem_id]
0xffff1111
[revision_id]
0x10
[chip_name]
My-own NEWS-0002
------------------------------------------------------------------------
The hd-audio driver reads the file via request_firmware(). Thus, The hd-audio driver reads the file via request_firmware(). Thus,
a patch file has to be located on the appropriate firmware path, a patch file has to be located on the appropriate firmware path,
typically, /lib/firmware. For example, when you pass the option typically, /lib/firmware. For example, when you pass the option
......
...@@ -2767,7 +2767,8 @@ static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, ...@@ -2767,7 +2767,8 @@ static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE, snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE,
power_state); power_state);
/* partial workaround for "azx_get_response timeout" */ /* partial workaround for "azx_get_response timeout" */
if (power_state == AC_PWRST_D0) if (power_state == AC_PWRST_D0 &&
(codec->vendor_id & 0xffff0000) == 0x14f10000)
msleep(10); msleep(10);
nid = codec->start_nid; nid = codec->start_nid;
...@@ -2801,7 +2802,6 @@ static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, ...@@ -2801,7 +2802,6 @@ static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
if (power_state == AC_PWRST_D0) { if (power_state == AC_PWRST_D0) {
unsigned long end_time; unsigned long end_time;
int state; int state;
msleep(10);
/* wait until the codec reachs to D0 */ /* wait until the codec reachs to D0 */
end_time = jiffies + msecs_to_jiffies(500); end_time = jiffies + msecs_to_jiffies(500);
do { do {
...@@ -3275,6 +3275,8 @@ const char *snd_hda_pcm_type_name[HDA_PCM_NTYPES] = { ...@@ -3275,6 +3275,8 @@ const char *snd_hda_pcm_type_name[HDA_PCM_NTYPES] = {
/* /*
* get the empty PCM device number to assign * get the empty PCM device number to assign
*
* note the max device number is limited by HDA_MAX_PCMS, currently 10
*/ */
static int get_empty_pcm_device(struct hda_bus *bus, int type) static int get_empty_pcm_device(struct hda_bus *bus, int type)
{ {
......
...@@ -527,6 +527,9 @@ enum { ...@@ -527,6 +527,9 @@ enum {
/* max. codec address */ /* max. codec address */
#define HDA_MAX_CODEC_ADDRESS 0x0f #define HDA_MAX_CODEC_ADDRESS 0x0f
/* max number of PCM devics per card */
#define HDA_MAX_PCMS 10
/* /*
* generic arrays * generic arrays
*/ */
......
...@@ -625,6 +625,10 @@ enum { ...@@ -625,6 +625,10 @@ enum {
LINE_MODE_PINCFG, LINE_MODE_PINCFG,
LINE_MODE_VERB, LINE_MODE_VERB,
LINE_MODE_HINT, LINE_MODE_HINT,
LINE_MODE_VENDOR_ID,
LINE_MODE_SUBSYSTEM_ID,
LINE_MODE_REVISION_ID,
LINE_MODE_CHIP_NAME,
NUM_LINE_MODES, NUM_LINE_MODES,
}; };
...@@ -654,53 +658,71 @@ static void parse_codec_mode(char *buf, struct hda_bus *bus, ...@@ -654,53 +658,71 @@ static void parse_codec_mode(char *buf, struct hda_bus *bus,
} }
/* parse the contents after the other command tags, [pincfg], [verb], /* parse the contents after the other command tags, [pincfg], [verb],
* [hint] and [model] * [vendor_id], [subsystem_id], [revision_id], [chip_name], [hint] and [model]
* just pass to the sysfs helper (only when any codec was specified) * just pass to the sysfs helper (only when any codec was specified)
*/ */
static void parse_pincfg_mode(char *buf, struct hda_bus *bus, static void parse_pincfg_mode(char *buf, struct hda_bus *bus,
struct hda_codec **codecp) struct hda_codec **codecp)
{ {
if (!*codecp)
return;
parse_user_pin_configs(*codecp, buf); parse_user_pin_configs(*codecp, buf);
} }
static void parse_verb_mode(char *buf, struct hda_bus *bus, static void parse_verb_mode(char *buf, struct hda_bus *bus,
struct hda_codec **codecp) struct hda_codec **codecp)
{ {
if (!*codecp)
return;
parse_init_verbs(*codecp, buf); parse_init_verbs(*codecp, buf);
} }
static void parse_hint_mode(char *buf, struct hda_bus *bus, static void parse_hint_mode(char *buf, struct hda_bus *bus,
struct hda_codec **codecp) struct hda_codec **codecp)
{ {
if (!*codecp)
return;
parse_hints(*codecp, buf); parse_hints(*codecp, buf);
} }
static void parse_model_mode(char *buf, struct hda_bus *bus, static void parse_model_mode(char *buf, struct hda_bus *bus,
struct hda_codec **codecp) struct hda_codec **codecp)
{ {
if (!*codecp)
return;
kfree((*codecp)->modelname); kfree((*codecp)->modelname);
(*codecp)->modelname = kstrdup(buf, GFP_KERNEL); (*codecp)->modelname = kstrdup(buf, GFP_KERNEL);
} }
static void parse_chip_name_mode(char *buf, struct hda_bus *bus,
struct hda_codec **codecp)
{
kfree((*codecp)->chip_name);
(*codecp)->chip_name = kstrdup(buf, GFP_KERNEL);
}
#define DEFINE_PARSE_ID_MODE(name) \
static void parse_##name##_mode(char *buf, struct hda_bus *bus, \
struct hda_codec **codecp) \
{ \
unsigned long val; \
if (!strict_strtoul(buf, 0, &val)) \
(*codecp)->name = val; \
}
DEFINE_PARSE_ID_MODE(vendor_id);
DEFINE_PARSE_ID_MODE(subsystem_id);
DEFINE_PARSE_ID_MODE(revision_id);
struct hda_patch_item { struct hda_patch_item {
const char *tag; const char *tag;
void (*parser)(char *buf, struct hda_bus *bus, struct hda_codec **retc); void (*parser)(char *buf, struct hda_bus *bus, struct hda_codec **retc);
int need_codec;
}; };
static struct hda_patch_item patch_items[NUM_LINE_MODES] = { static struct hda_patch_item patch_items[NUM_LINE_MODES] = {
[LINE_MODE_CODEC] = { "[codec]", parse_codec_mode }, [LINE_MODE_CODEC] = { "[codec]", parse_codec_mode, 0 },
[LINE_MODE_MODEL] = { "[model]", parse_model_mode }, [LINE_MODE_MODEL] = { "[model]", parse_model_mode, 1 },
[LINE_MODE_VERB] = { "[verb]", parse_verb_mode }, [LINE_MODE_VERB] = { "[verb]", parse_verb_mode, 1 },
[LINE_MODE_PINCFG] = { "[pincfg]", parse_pincfg_mode }, [LINE_MODE_PINCFG] = { "[pincfg]", parse_pincfg_mode, 1 },
[LINE_MODE_HINT] = { "[hint]", parse_hint_mode }, [LINE_MODE_HINT] = { "[hint]", parse_hint_mode, 1 },
[LINE_MODE_VENDOR_ID] = { "[vendor_id]", parse_vendor_id_mode, 1 },
[LINE_MODE_SUBSYSTEM_ID] = { "[subsystem_id]", parse_subsystem_id_mode, 1 },
[LINE_MODE_REVISION_ID] = { "[revision_id]", parse_revision_id_mode, 1 },
[LINE_MODE_CHIP_NAME] = { "[chip_name]", parse_chip_name_mode, 1 },
}; };
/* check the line starting with '[' -- change the parser mode accodingly */ /* check the line starting with '[' -- change the parser mode accodingly */
...@@ -783,7 +805,8 @@ int snd_hda_load_patch(struct hda_bus *bus, const char *patch) ...@@ -783,7 +805,8 @@ int snd_hda_load_patch(struct hda_bus *bus, const char *patch)
continue; continue;
if (*buf == '[') if (*buf == '[')
line_mode = parse_line_mode(buf, bus); line_mode = parse_line_mode(buf, bus);
else if (patch_items[line_mode].parser) else if (patch_items[line_mode].parser &&
(codec || !patch_items[line_mode].need_codec))
patch_items[line_mode].parser(buf, bus, &codec); patch_items[line_mode].parser(buf, bus, &codec);
} }
release_firmware(fw); release_firmware(fw);
......
...@@ -125,6 +125,7 @@ MODULE_SUPPORTED_DEVICE("{{Intel, ICH6}," ...@@ -125,6 +125,7 @@ MODULE_SUPPORTED_DEVICE("{{Intel, ICH6},"
"{Intel, ICH9}," "{Intel, ICH9},"
"{Intel, ICH10}," "{Intel, ICH10},"
"{Intel, PCH}," "{Intel, PCH},"
"{Intel, CPT},"
"{Intel, SCH}," "{Intel, SCH},"
"{ATI, SB450}," "{ATI, SB450},"
"{ATI, SB600}," "{ATI, SB600},"
...@@ -259,8 +260,6 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; ...@@ -259,8 +260,6 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
#define AZX_MAX_FRAG 32 #define AZX_MAX_FRAG 32
/* max buffer size - no h/w limit, you can increase as you like */ /* max buffer size - no h/w limit, you can increase as you like */
#define AZX_MAX_BUF_SIZE (1024*1024*1024) #define AZX_MAX_BUF_SIZE (1024*1024*1024)
/* max number of PCM devics per card */
#define AZX_MAX_PCMS 8
/* RIRB int mask: overrun[2], response[0] */ /* RIRB int mask: overrun[2], response[0] */
#define RIRB_INT_RESPONSE 0x01 #define RIRB_INT_RESPONSE 0x01
...@@ -408,7 +407,7 @@ struct azx { ...@@ -408,7 +407,7 @@ struct azx {
struct azx_dev *azx_dev; struct azx_dev *azx_dev;
/* PCM */ /* PCM */
struct snd_pcm *pcm[AZX_MAX_PCMS]; struct snd_pcm *pcm[HDA_MAX_PCMS];
/* HD codec */ /* HD codec */
unsigned short codec_mask; unsigned short codec_mask;
...@@ -449,6 +448,7 @@ struct azx { ...@@ -449,6 +448,7 @@ struct azx {
/* driver types */ /* driver types */
enum { enum {
AZX_DRIVER_ICH, AZX_DRIVER_ICH,
AZX_DRIVER_PCH,
AZX_DRIVER_SCH, AZX_DRIVER_SCH,
AZX_DRIVER_ATI, AZX_DRIVER_ATI,
AZX_DRIVER_ATIHDMI, AZX_DRIVER_ATIHDMI,
...@@ -463,6 +463,7 @@ enum { ...@@ -463,6 +463,7 @@ enum {
static char *driver_short_names[] __devinitdata = { static char *driver_short_names[] __devinitdata = {
[AZX_DRIVER_ICH] = "HDA Intel", [AZX_DRIVER_ICH] = "HDA Intel",
[AZX_DRIVER_PCH] = "HDA Intel PCH",
[AZX_DRIVER_SCH] = "HDA Intel MID", [AZX_DRIVER_SCH] = "HDA Intel MID",
[AZX_DRIVER_ATI] = "HDA ATI SB", [AZX_DRIVER_ATI] = "HDA ATI SB",
[AZX_DRIVER_ATIHDMI] = "HDA ATI HDMI", [AZX_DRIVER_ATIHDMI] = "HDA ATI HDMI",
...@@ -968,8 +969,8 @@ static void azx_stream_start(struct azx *chip, struct azx_dev *azx_dev) ...@@ -968,8 +969,8 @@ static void azx_stream_start(struct azx *chip, struct azx_dev *azx_dev)
azx_dev->insufficient = 1; azx_dev->insufficient = 1;
/* enable SIE */ /* enable SIE */
azx_writeb(chip, INTCTL, azx_writel(chip, INTCTL,
azx_readb(chip, INTCTL) | (1 << azx_dev->index)); azx_readl(chip, INTCTL) | (1 << azx_dev->index));
/* set DMA start and interrupt mask */ /* set DMA start and interrupt mask */
azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) | azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) |
SD_CTL_DMA_START | SD_INT_MASK); SD_CTL_DMA_START | SD_INT_MASK);
...@@ -988,8 +989,8 @@ static void azx_stream_stop(struct azx *chip, struct azx_dev *azx_dev) ...@@ -988,8 +989,8 @@ static void azx_stream_stop(struct azx *chip, struct azx_dev *azx_dev)
{ {
azx_stream_clear(chip, azx_dev); azx_stream_clear(chip, azx_dev);
/* disable SIE */ /* disable SIE */
azx_writeb(chip, INTCTL, azx_writel(chip, INTCTL,
azx_readb(chip, INTCTL) & ~(1 << azx_dev->index)); azx_readl(chip, INTCTL) & ~(1 << azx_dev->index));
} }
...@@ -1065,6 +1066,7 @@ static void azx_init_pci(struct azx *chip) ...@@ -1065,6 +1066,7 @@ static void azx_init_pci(struct azx *chip)
0x01, NVIDIA_HDA_ENABLE_COHBIT); 0x01, NVIDIA_HDA_ENABLE_COHBIT);
break; break;
case AZX_DRIVER_SCH: case AZX_DRIVER_SCH:
case AZX_DRIVER_PCH:
pci_read_config_word(chip->pci, INTEL_SCH_HDA_DEVC, &snoop); pci_read_config_word(chip->pci, INTEL_SCH_HDA_DEVC, &snoop);
if (snoop & INTEL_SCH_HDA_DEVC_NOSNOOP) { if (snoop & INTEL_SCH_HDA_DEVC_NOSNOOP) {
pci_write_config_word(chip->pci, INTEL_SCH_HDA_DEVC, pci_write_config_word(chip->pci, INTEL_SCH_HDA_DEVC,
...@@ -1350,7 +1352,7 @@ static void azx_bus_reset(struct hda_bus *bus) ...@@ -1350,7 +1352,7 @@ static void azx_bus_reset(struct hda_bus *bus)
if (chip->initialized) { if (chip->initialized) {
int i; int i;
for (i = 0; i < AZX_MAX_PCMS; i++) for (i = 0; i < HDA_MAX_PCMS; i++)
snd_pcm_suspend_all(chip->pcm[i]); snd_pcm_suspend_all(chip->pcm[i]);
snd_hda_suspend(chip->bus); snd_hda_suspend(chip->bus);
snd_hda_resume(chip->bus); snd_hda_resume(chip->bus);
...@@ -1412,7 +1414,7 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model) ...@@ -1412,7 +1414,7 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model)
chip->codec_mask &= ~(1 << c); chip->codec_mask &= ~(1 << c);
/* More badly, accessing to a non-existing /* More badly, accessing to a non-existing
* codec often screws up the controller chip, * codec often screws up the controller chip,
* and distrubs the further communications. * and disturbs the further communications.
* Thus if an error occurs during probing, * Thus if an error occurs during probing,
* better to reset the controller chip to * better to reset the controller chip to
* get back to the sanity state. * get back to the sanity state.
...@@ -1983,7 +1985,7 @@ azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec, ...@@ -1983,7 +1985,7 @@ azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec,
int pcm_dev = cpcm->device; int pcm_dev = cpcm->device;
int s, err; int s, err;
if (pcm_dev >= AZX_MAX_PCMS) { if (pcm_dev >= HDA_MAX_PCMS) {
snd_printk(KERN_ERR SFX "Invalid PCM device number %d\n", snd_printk(KERN_ERR SFX "Invalid PCM device number %d\n",
pcm_dev); pcm_dev);
return -EINVAL; return -EINVAL;
...@@ -2139,7 +2141,7 @@ static int azx_suspend(struct pci_dev *pci, pm_message_t state) ...@@ -2139,7 +2141,7 @@ static int azx_suspend(struct pci_dev *pci, pm_message_t state)
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
azx_clear_irq_pending(chip); azx_clear_irq_pending(chip);
for (i = 0; i < AZX_MAX_PCMS; i++) for (i = 0; i < HDA_MAX_PCMS; i++)
snd_pcm_suspend_all(chip->pcm[i]); snd_pcm_suspend_all(chip->pcm[i]);
if (chip->initialized) if (chip->initialized)
snd_hda_suspend(chip->bus); snd_hda_suspend(chip->bus);
...@@ -2262,6 +2264,7 @@ static struct snd_pci_quirk position_fix_list[] __devinitdata = { ...@@ -2262,6 +2264,7 @@ static struct snd_pci_quirk position_fix_list[] __devinitdata = {
SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_LPIB), SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_LPIB),
SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_LPIB), SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_LPIB),
SND_PCI_QUIRK(0x103c, 0x306d, "HP dv3", POS_FIX_LPIB), SND_PCI_QUIRK(0x103c, 0x306d, "HP dv3", POS_FIX_LPIB),
SND_PCI_QUIRK(0x1106, 0x3288, "ASUS M2V-MX SE", POS_FIX_LPIB),
SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB), SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB),
SND_PCI_QUIRK(0x1462, 0x1002, "MSI Wind U115", POS_FIX_LPIB), SND_PCI_QUIRK(0x1462, 0x1002, "MSI Wind U115", POS_FIX_LPIB),
{} {}
...@@ -2418,6 +2421,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, ...@@ -2418,6 +2421,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
if (bdl_pos_adj[dev] < 0) { if (bdl_pos_adj[dev] < 0) {
switch (chip->driver_type) { switch (chip->driver_type) {
case AZX_DRIVER_ICH: case AZX_DRIVER_ICH:
case AZX_DRIVER_PCH:
bdl_pos_adj[dev] = 1; bdl_pos_adj[dev] = 1;
break; break;
default: default:
...@@ -2696,6 +2700,8 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { ...@@ -2696,6 +2700,8 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {
{ PCI_DEVICE(0x8086, 0x3a6e), .driver_data = AZX_DRIVER_ICH }, { PCI_DEVICE(0x8086, 0x3a6e), .driver_data = AZX_DRIVER_ICH },
/* PCH */ /* PCH */
{ PCI_DEVICE(0x8086, 0x3b56), .driver_data = AZX_DRIVER_ICH }, { PCI_DEVICE(0x8086, 0x3b56), .driver_data = AZX_DRIVER_ICH },
/* CPT */
{ PCI_DEVICE(0x8086, 0x1c20), .driver_data = AZX_DRIVER_PCH },
/* SCH */ /* SCH */
{ PCI_DEVICE(0x8086, 0x811b), .driver_data = AZX_DRIVER_SCH }, { PCI_DEVICE(0x8086, 0x811b), .driver_data = AZX_DRIVER_SCH },
/* ATI SB 450/600 */ /* ATI SB 450/600 */
......
...@@ -1098,7 +1098,7 @@ static struct snd_pci_quirk ad1986a_cfg_tbl[] = { ...@@ -1098,7 +1098,7 @@ static struct snd_pci_quirk ad1986a_cfg_tbl[] = {
SND_PCI_QUIRK(0x1043, 0x81cb, "ASUS M2N", AD1986A_3STACK), SND_PCI_QUIRK(0x1043, 0x81cb, "ASUS M2N", AD1986A_3STACK),
SND_PCI_QUIRK(0x1043, 0x8234, "ASUS M2N", AD1986A_3STACK), SND_PCI_QUIRK(0x1043, 0x8234, "ASUS M2N", AD1986A_3STACK),
SND_PCI_QUIRK(0x10de, 0xcb84, "ASUS A8N-VM", AD1986A_3STACK), SND_PCI_QUIRK(0x10de, 0xcb84, "ASUS A8N-VM", AD1986A_3STACK),
SND_PCI_QUIRK(0x1179, 0xff40, "Toshiba", AD1986A_LAPTOP_EAPD), SND_PCI_QUIRK(0x1179, 0xff40, "Toshiba Satellite L40-10Q", AD1986A_3STACK),
SND_PCI_QUIRK(0x144d, 0xb03c, "Samsung R55", AD1986A_3STACK), SND_PCI_QUIRK(0x144d, 0xb03c, "Samsung R55", AD1986A_3STACK),
SND_PCI_QUIRK(0x144d, 0xc01e, "FSC V2060", AD1986A_LAPTOP), SND_PCI_QUIRK(0x144d, 0xc01e, "FSC V2060", AD1986A_LAPTOP),
SND_PCI_QUIRK(0x144d, 0xc024, "Samsung P50", AD1986A_SAMSUNG_P50), SND_PCI_QUIRK(0x144d, 0xc024, "Samsung P50", AD1986A_SAMSUNG_P50),
......
...@@ -42,10 +42,12 @@ ...@@ -42,10 +42,12 @@
/* Conexant 5051 specific */ /* Conexant 5051 specific */
#define CXT5051_SPDIF_OUT 0x1C #define CXT5051_SPDIF_OUT 0x12
#define CXT5051_PORTB_EVENT 0x38 #define CXT5051_PORTB_EVENT 0x38
#define CXT5051_PORTC_EVENT 0x39 #define CXT5051_PORTC_EVENT 0x39
#define AUTO_MIC_PORTB (1 << 1)
#define AUTO_MIC_PORTC (1 << 2)
struct conexant_jack { struct conexant_jack {
...@@ -74,7 +76,7 @@ struct conexant_spec { ...@@ -74,7 +76,7 @@ struct conexant_spec {
*/ */
unsigned int cur_eapd; unsigned int cur_eapd;
unsigned int hp_present; unsigned int hp_present;
unsigned int no_auto_mic; unsigned int auto_mic;
unsigned int need_dac_fix; unsigned int need_dac_fix;
/* capture */ /* capture */
...@@ -111,7 +113,8 @@ struct conexant_spec { ...@@ -111,7 +113,8 @@ struct conexant_spec {
unsigned int dell_automute; unsigned int dell_automute;
unsigned int port_d_mode; unsigned int port_d_mode;
unsigned int dell_vostro; unsigned int dell_vostro:1;
unsigned int ideapad:1;
unsigned int ext_mic_present; unsigned int ext_mic_present;
unsigned int recording; unsigned int recording;
...@@ -1603,6 +1606,11 @@ static void cxt5051_update_speaker(struct hda_codec *codec) ...@@ -1603,6 +1606,11 @@ static void cxt5051_update_speaker(struct hda_codec *codec)
{ {
struct conexant_spec *spec = codec->spec; struct conexant_spec *spec = codec->spec;
unsigned int pinctl; unsigned int pinctl;
/* headphone pin */
pinctl = (spec->hp_present && spec->cur_eapd) ? PIN_HP : 0;
snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
pinctl);
/* speaker pin */
pinctl = (!spec->hp_present && spec->cur_eapd) ? PIN_OUT : 0; pinctl = (!spec->hp_present && spec->cur_eapd) ? PIN_OUT : 0;
snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
pinctl); pinctl);
...@@ -1626,7 +1634,7 @@ static void cxt5051_portb_automic(struct hda_codec *codec) ...@@ -1626,7 +1634,7 @@ static void cxt5051_portb_automic(struct hda_codec *codec)
struct conexant_spec *spec = codec->spec; struct conexant_spec *spec = codec->spec;
unsigned int present; unsigned int present;
if (spec->no_auto_mic) if (!(spec->auto_mic & AUTO_MIC_PORTB))
return; return;
present = snd_hda_jack_detect(codec, 0x17); present = snd_hda_jack_detect(codec, 0x17);
snd_hda_codec_write(codec, 0x14, 0, snd_hda_codec_write(codec, 0x14, 0,
...@@ -1641,7 +1649,7 @@ static void cxt5051_portc_automic(struct hda_codec *codec) ...@@ -1641,7 +1649,7 @@ static void cxt5051_portc_automic(struct hda_codec *codec)
unsigned int present; unsigned int present;
hda_nid_t new_adc; hda_nid_t new_adc;
if (spec->no_auto_mic) if (!(spec->auto_mic & AUTO_MIC_PORTC))
return; return;
present = snd_hda_jack_detect(codec, 0x18); present = snd_hda_jack_detect(codec, 0x18);
if (present) if (present)
...@@ -1687,13 +1695,7 @@ static void cxt5051_hp_unsol_event(struct hda_codec *codec, ...@@ -1687,13 +1695,7 @@ static void cxt5051_hp_unsol_event(struct hda_codec *codec,
conexant_report_jack(codec, nid); conexant_report_jack(codec, nid);
} }
static struct snd_kcontrol_new cxt5051_mixers[] = { static struct snd_kcontrol_new cxt5051_playback_mixers[] = {
HDA_CODEC_VOLUME("Internal Mic Volume", 0x14, 0x00, HDA_INPUT),
HDA_CODEC_MUTE("Internal Mic Switch", 0x14, 0x00, HDA_INPUT),
HDA_CODEC_VOLUME("External Mic Volume", 0x14, 0x01, HDA_INPUT),
HDA_CODEC_MUTE("External Mic Switch", 0x14, 0x01, HDA_INPUT),
HDA_CODEC_VOLUME("Docking Mic Volume", 0x15, 0x00, HDA_INPUT),
HDA_CODEC_MUTE("Docking Mic Switch", 0x15, 0x00, HDA_INPUT),
HDA_CODEC_VOLUME("Master Playback Volume", 0x10, 0x00, HDA_OUTPUT), HDA_CODEC_VOLUME("Master Playback Volume", 0x10, 0x00, HDA_OUTPUT),
{ {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
...@@ -1703,7 +1705,16 @@ static struct snd_kcontrol_new cxt5051_mixers[] = { ...@@ -1703,7 +1705,16 @@ static struct snd_kcontrol_new cxt5051_mixers[] = {
.put = cxt5051_hp_master_sw_put, .put = cxt5051_hp_master_sw_put,
.private_value = 0x1a, .private_value = 0x1a,
}, },
{}
};
static struct snd_kcontrol_new cxt5051_capture_mixers[] = {
HDA_CODEC_VOLUME("Internal Mic Volume", 0x14, 0x00, HDA_INPUT),
HDA_CODEC_MUTE("Internal Mic Switch", 0x14, 0x00, HDA_INPUT),
HDA_CODEC_VOLUME("External Mic Volume", 0x14, 0x01, HDA_INPUT),
HDA_CODEC_MUTE("External Mic Switch", 0x14, 0x01, HDA_INPUT),
HDA_CODEC_VOLUME("Docking Mic Volume", 0x15, 0x00, HDA_INPUT),
HDA_CODEC_MUTE("Docking Mic Switch", 0x15, 0x00, HDA_INPUT),
{} {}
}; };
...@@ -1712,48 +1723,26 @@ static struct snd_kcontrol_new cxt5051_hp_mixers[] = { ...@@ -1712,48 +1723,26 @@ static struct snd_kcontrol_new cxt5051_hp_mixers[] = {
HDA_CODEC_MUTE("Internal Mic Switch", 0x14, 0x00, HDA_INPUT), HDA_CODEC_MUTE("Internal Mic Switch", 0x14, 0x00, HDA_INPUT),
HDA_CODEC_VOLUME("External Mic Volume", 0x15, 0x00, HDA_INPUT), HDA_CODEC_VOLUME("External Mic Volume", 0x15, 0x00, HDA_INPUT),
HDA_CODEC_MUTE("External Mic Switch", 0x15, 0x00, HDA_INPUT), HDA_CODEC_MUTE("External Mic Switch", 0x15, 0x00, HDA_INPUT),
HDA_CODEC_VOLUME("Master Playback Volume", 0x10, 0x00, HDA_OUTPUT),
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Master Playback Switch",
.info = cxt_eapd_info,
.get = cxt_eapd_get,
.put = cxt5051_hp_master_sw_put,
.private_value = 0x1a,
},
{} {}
}; };
static struct snd_kcontrol_new cxt5051_hp_dv6736_mixers[] = { static struct snd_kcontrol_new cxt5051_hp_dv6736_mixers[] = {
HDA_CODEC_VOLUME("Mic Volume", 0x14, 0x00, HDA_INPUT), HDA_CODEC_VOLUME("Capture Volume", 0x14, 0x00, HDA_INPUT),
HDA_CODEC_MUTE("Mic Switch", 0x14, 0x00, HDA_INPUT), HDA_CODEC_MUTE("Capture Switch", 0x14, 0x00, HDA_INPUT),
HDA_CODEC_VOLUME("Master Playback Volume", 0x10, 0x00, HDA_OUTPUT),
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Master Playback Switch",
.info = cxt_eapd_info,
.get = cxt_eapd_get,
.put = cxt5051_hp_master_sw_put,
.private_value = 0x1a,
},
{} {}
}; };
static struct snd_kcontrol_new cxt5051_f700_mixers[] = { static struct snd_kcontrol_new cxt5051_f700_mixers[] = {
HDA_CODEC_VOLUME("Mic Volume", 0x14, 0x01, HDA_INPUT), HDA_CODEC_VOLUME("Capture Volume", 0x14, 0x01, HDA_INPUT),
HDA_CODEC_MUTE("Mic Switch", 0x14, 0x01, HDA_INPUT), HDA_CODEC_MUTE("Capture Switch", 0x14, 0x01, HDA_INPUT),
HDA_CODEC_VOLUME("Master Playback Volume", 0x10, 0x00, HDA_OUTPUT), {}
{ };
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Master Playback Switch",
.info = cxt_eapd_info,
.get = cxt_eapd_get,
.put = cxt5051_hp_master_sw_put,
.private_value = 0x1a,
},
static struct snd_kcontrol_new cxt5051_toshiba_mixers[] = {
HDA_CODEC_VOLUME("Internal Mic Volume", 0x14, 0x00, HDA_INPUT),
HDA_CODEC_MUTE("Internal Mic Switch", 0x14, 0x00, HDA_INPUT),
HDA_CODEC_VOLUME("External Mic Volume", 0x14, 0x01, HDA_INPUT),
HDA_CODEC_MUTE("External Mic Switch", 0x14, 0x01, HDA_INPUT),
{} {}
}; };
...@@ -1782,8 +1771,6 @@ static struct hda_verb cxt5051_init_verbs[] = { ...@@ -1782,8 +1771,6 @@ static struct hda_verb cxt5051_init_verbs[] = {
/* EAPD */ /* EAPD */
{0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ {0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */
{0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT}, {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT},
{0x17, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CXT5051_PORTB_EVENT},
{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CXT5051_PORTC_EVENT},
{ } /* end */ { } /* end */
}; };
...@@ -1809,7 +1796,6 @@ static struct hda_verb cxt5051_hp_dv6736_init_verbs[] = { ...@@ -1809,7 +1796,6 @@ static struct hda_verb cxt5051_hp_dv6736_init_verbs[] = {
/* EAPD */ /* EAPD */
{0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ {0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */
{0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT}, {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT},
{0x17, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CXT5051_PORTB_EVENT},
{ } /* end */ { } /* end */
}; };
...@@ -1841,15 +1827,13 @@ static struct hda_verb cxt5051_lenovo_x200_init_verbs[] = { ...@@ -1841,15 +1827,13 @@ static struct hda_verb cxt5051_lenovo_x200_init_verbs[] = {
/* EAPD */ /* EAPD */
{0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ {0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */
{0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT}, {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT},
{0x17, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CXT5051_PORTB_EVENT},
{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CXT5051_PORTC_EVENT},
{0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT}, {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT},
{ } /* end */ { } /* end */
}; };
static struct hda_verb cxt5051_f700_init_verbs[] = { static struct hda_verb cxt5051_f700_init_verbs[] = {
/* Line in, Mic */ /* Line in, Mic */
{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x03}, {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03},
{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0}, {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0},
{0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0}, {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0},
...@@ -1869,15 +1853,34 @@ static struct hda_verb cxt5051_f700_init_verbs[] = { ...@@ -1869,15 +1853,34 @@ static struct hda_verb cxt5051_f700_init_verbs[] = {
/* EAPD */ /* EAPD */
{0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ {0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */
{0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT}, {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT},
{0x17, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CXT5051_PORTB_EVENT},
{ } /* end */ { } /* end */
}; };
static void cxt5051_init_mic_port(struct hda_codec *codec, hda_nid_t nid,
unsigned int event)
{
snd_hda_codec_write(codec, nid, 0,
AC_VERB_SET_UNSOLICITED_ENABLE,
AC_USRSP_EN | event);
#ifdef CONFIG_SND_HDA_INPUT_JACK
conexant_add_jack(codec, nid, SND_JACK_MICROPHONE);
conexant_report_jack(codec, nid);
#endif
}
/* initialize jack-sensing, too */ /* initialize jack-sensing, too */
static int cxt5051_init(struct hda_codec *codec) static int cxt5051_init(struct hda_codec *codec)
{ {
struct conexant_spec *spec = codec->spec;
conexant_init(codec); conexant_init(codec);
conexant_init_jacks(codec); conexant_init_jacks(codec);
if (spec->auto_mic & AUTO_MIC_PORTB)
cxt5051_init_mic_port(codec, 0x17, CXT5051_PORTB_EVENT);
if (spec->auto_mic & AUTO_MIC_PORTC)
cxt5051_init_mic_port(codec, 0x18, CXT5051_PORTC_EVENT);
if (codec->patch_ops.unsol_event) { if (codec->patch_ops.unsol_event) {
cxt5051_hp_automute(codec); cxt5051_hp_automute(codec);
cxt5051_portb_automic(codec); cxt5051_portb_automic(codec);
...@@ -1893,6 +1896,7 @@ enum { ...@@ -1893,6 +1896,7 @@ enum {
CXT5051_HP_DV6736, /* HP without mic switch */ CXT5051_HP_DV6736, /* HP without mic switch */
CXT5051_LENOVO_X200, /* Lenovo X200 laptop */ CXT5051_LENOVO_X200, /* Lenovo X200 laptop */
CXT5051_F700, /* HP Compaq Presario F700 */ CXT5051_F700, /* HP Compaq Presario F700 */
CXT5051_TOSHIBA, /* Toshiba M300 & co */
CXT5051_MODELS CXT5051_MODELS
}; };
...@@ -1901,17 +1905,19 @@ static const char *cxt5051_models[CXT5051_MODELS] = { ...@@ -1901,17 +1905,19 @@ static const char *cxt5051_models[CXT5051_MODELS] = {
[CXT5051_HP] = "hp", [CXT5051_HP] = "hp",
[CXT5051_HP_DV6736] = "hp-dv6736", [CXT5051_HP_DV6736] = "hp-dv6736",
[CXT5051_LENOVO_X200] = "lenovo-x200", [CXT5051_LENOVO_X200] = "lenovo-x200",
[CXT5051_F700] = "hp 700" [CXT5051_F700] = "hp-700",
[CXT5051_TOSHIBA] = "toshiba",
}; };
static struct snd_pci_quirk cxt5051_cfg_tbl[] = { static struct snd_pci_quirk cxt5051_cfg_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x30cf, "HP DV6736", CXT5051_HP_DV6736), SND_PCI_QUIRK(0x103c, 0x30cf, "HP DV6736", CXT5051_HP_DV6736),
SND_PCI_QUIRK(0x103c, 0x360b, "Compaq Presario CQ60", CXT5051_HP), SND_PCI_QUIRK(0x103c, 0x360b, "Compaq Presario CQ60", CXT5051_HP),
SND_PCI_QUIRK(0x103c, 0x30ea, "Compaq Presario F700", CXT5051_F700),
SND_PCI_QUIRK(0x1179, 0xff50, "Toshiba M30x", CXT5051_TOSHIBA),
SND_PCI_QUIRK(0x14f1, 0x0101, "Conexant Reference board", SND_PCI_QUIRK(0x14f1, 0x0101, "Conexant Reference board",
CXT5051_LAPTOP), CXT5051_LAPTOP),
SND_PCI_QUIRK(0x14f1, 0x5051, "HP Spartan 1.1", CXT5051_HP), SND_PCI_QUIRK(0x14f1, 0x5051, "HP Spartan 1.1", CXT5051_HP),
SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo X200", CXT5051_LENOVO_X200), SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo X200", CXT5051_LENOVO_X200),
SND_PCI_QUIRK(0x103c, 0x30ea, "Compaq Presario F700", CXT5051_F700),
{} {}
}; };
...@@ -1935,8 +1941,9 @@ static int patch_cxt5051(struct hda_codec *codec) ...@@ -1935,8 +1941,9 @@ static int patch_cxt5051(struct hda_codec *codec)
spec->multiout.dig_out_nid = CXT5051_SPDIF_OUT; spec->multiout.dig_out_nid = CXT5051_SPDIF_OUT;
spec->num_adc_nids = 1; /* not 2; via auto-mic switch */ spec->num_adc_nids = 1; /* not 2; via auto-mic switch */
spec->adc_nids = cxt5051_adc_nids; spec->adc_nids = cxt5051_adc_nids;
spec->num_mixers = 1; spec->num_mixers = 2;
spec->mixers[0] = cxt5051_mixers; spec->mixers[0] = cxt5051_capture_mixers;
spec->mixers[1] = cxt5051_playback_mixers;
spec->num_init_verbs = 1; spec->num_init_verbs = 1;
spec->init_verbs[0] = cxt5051_init_verbs; spec->init_verbs[0] = cxt5051_init_verbs;
spec->spdif_route = 0; spec->spdif_route = 0;
...@@ -1950,6 +1957,7 @@ static int patch_cxt5051(struct hda_codec *codec) ...@@ -1950,6 +1957,7 @@ static int patch_cxt5051(struct hda_codec *codec)
board_config = snd_hda_check_board_config(codec, CXT5051_MODELS, board_config = snd_hda_check_board_config(codec, CXT5051_MODELS,
cxt5051_models, cxt5051_models,
cxt5051_cfg_tbl); cxt5051_cfg_tbl);
spec->auto_mic = AUTO_MIC_PORTB | AUTO_MIC_PORTC;
switch (board_config) { switch (board_config) {
case CXT5051_HP: case CXT5051_HP:
spec->mixers[0] = cxt5051_hp_mixers; spec->mixers[0] = cxt5051_hp_mixers;
...@@ -1957,7 +1965,7 @@ static int patch_cxt5051(struct hda_codec *codec) ...@@ -1957,7 +1965,7 @@ static int patch_cxt5051(struct hda_codec *codec)
case CXT5051_HP_DV6736: case CXT5051_HP_DV6736:
spec->init_verbs[0] = cxt5051_hp_dv6736_init_verbs; spec->init_verbs[0] = cxt5051_hp_dv6736_init_verbs;
spec->mixers[0] = cxt5051_hp_dv6736_mixers; spec->mixers[0] = cxt5051_hp_dv6736_mixers;
spec->no_auto_mic = 1; spec->auto_mic = 0;
break; break;
case CXT5051_LENOVO_X200: case CXT5051_LENOVO_X200:
spec->init_verbs[0] = cxt5051_lenovo_x200_init_verbs; spec->init_verbs[0] = cxt5051_lenovo_x200_init_verbs;
...@@ -1965,7 +1973,11 @@ static int patch_cxt5051(struct hda_codec *codec) ...@@ -1965,7 +1973,11 @@ static int patch_cxt5051(struct hda_codec *codec)
case CXT5051_F700: case CXT5051_F700:
spec->init_verbs[0] = cxt5051_f700_init_verbs; spec->init_verbs[0] = cxt5051_f700_init_verbs;
spec->mixers[0] = cxt5051_f700_mixers; spec->mixers[0] = cxt5051_f700_mixers;
spec->no_auto_mic = 1; spec->auto_mic = 0;
break;
case CXT5051_TOSHIBA:
spec->mixers[0] = cxt5051_toshiba_mixers;
spec->auto_mic = AUTO_MIC_PORTB;
break; break;
} }
...@@ -2156,6 +2168,34 @@ static void cxt5066_vostro_automic(struct hda_codec *codec) ...@@ -2156,6 +2168,34 @@ static void cxt5066_vostro_automic(struct hda_codec *codec)
} }
} }
/* toggle input of built-in digital mic and mic jack appropriately */
static void cxt5066_ideapad_automic(struct hda_codec *codec)
{
unsigned int present;
struct hda_verb ext_mic_present[] = {
{0x14, AC_VERB_SET_CONNECT_SEL, 0},
{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
{0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
{}
};
static struct hda_verb ext_mic_absent[] = {
{0x14, AC_VERB_SET_CONNECT_SEL, 2},
{0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
{}
};
present = snd_hda_jack_detect(codec, 0x1b);
if (present) {
snd_printdd("CXT5066: external microphone detected\n");
snd_hda_sequence_write(codec, ext_mic_present);
} else {
snd_printdd("CXT5066: external microphone absent\n");
snd_hda_sequence_write(codec, ext_mic_absent);
}
}
/* mute internal speaker if HP is plugged */ /* mute internal speaker if HP is plugged */
static void cxt5066_hp_automute(struct hda_codec *codec) static void cxt5066_hp_automute(struct hda_codec *codec)
{ {
...@@ -2205,6 +2245,20 @@ static void cxt5066_vostro_event(struct hda_codec *codec, unsigned int res) ...@@ -2205,6 +2245,20 @@ static void cxt5066_vostro_event(struct hda_codec *codec, unsigned int res)
} }
} }
/* unsolicited event for jack sensing */
static void cxt5066_ideapad_event(struct hda_codec *codec, unsigned int res)
{
snd_printdd("CXT5066_ideapad: unsol event %x (%x)\n", res, res >> 26);
switch (res >> 26) {
case CONEXANT_HP_EVENT:
cxt5066_hp_automute(codec);
break;
case CONEXANT_MIC_EVENT:
cxt5066_ideapad_automic(codec);
break;
}
}
static const struct hda_input_mux cxt5066_analog_mic_boost = { static const struct hda_input_mux cxt5066_analog_mic_boost = {
.num_items = 5, .num_items = 5,
.items = { .items = {
...@@ -2216,13 +2270,21 @@ static const struct hda_input_mux cxt5066_analog_mic_boost = { ...@@ -2216,13 +2270,21 @@ static const struct hda_input_mux cxt5066_analog_mic_boost = {
}, },
}; };
static int cxt5066_set_mic_boost(struct hda_codec *codec) static void cxt5066_set_mic_boost(struct hda_codec *codec)
{ {
struct conexant_spec *spec = codec->spec; struct conexant_spec *spec = codec->spec;
return snd_hda_codec_write_cache(codec, 0x17, 0, snd_hda_codec_write_cache(codec, 0x17, 0,
AC_VERB_SET_AMP_GAIN_MUTE, AC_VERB_SET_AMP_GAIN_MUTE,
AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | AC_AMP_SET_OUTPUT | AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | AC_AMP_SET_OUTPUT |
cxt5066_analog_mic_boost.items[spec->mic_boost].index); cxt5066_analog_mic_boost.items[spec->mic_boost].index);
if (spec->ideapad) {
/* adjust the internal mic as well...it is not through 0x17 */
snd_hda_codec_write_cache(codec, 0x23, 0,
AC_VERB_SET_AMP_GAIN_MUTE,
AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | AC_AMP_SET_INPUT |
cxt5066_analog_mic_boost.
items[spec->mic_boost].index);
}
} }
static int cxt5066_mic_boost_mux_enum_info(struct snd_kcontrol *kcontrol, static int cxt5066_mic_boost_mux_enum_info(struct snd_kcontrol *kcontrol,
...@@ -2653,6 +2715,56 @@ static struct hda_verb cxt5066_init_verbs_vostro[] = { ...@@ -2653,6 +2715,56 @@ static struct hda_verb cxt5066_init_verbs_vostro[] = {
{ } /* end */ { } /* end */
}; };
static struct hda_verb cxt5066_init_verbs_ideapad[] = {
{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port B */
{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port C */
{0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port F */
{0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port E */
/* Speakers */
{0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
{0x1f, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
/* HP, Amp */
{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
{0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
{0x1c, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
/* DAC1 */
{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
/* Node 14 connections: 0x17 0x18 0x23 0x24 0x27 */
{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x50},
{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2) | 0x50},
{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
{0x14, AC_VERB_SET_CONNECT_SEL, 2}, /* default to internal mic */
/* Audio input selector */
{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x2},
{0x17, AC_VERB_SET_CONNECT_SEL, 1}, /* route ext mic */
/* SPDIF route: PCM */
{0x20, AC_VERB_SET_CONNECT_SEL, 0x0},
{0x22, AC_VERB_SET_CONNECT_SEL, 0x0},
{0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
{0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
/* internal microphone */
{0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* enable int mic */
/* EAPD */
{0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */
{0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT},
{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT},
{ } /* end */
};
static struct hda_verb cxt5066_init_verbs_portd_lo[] = { static struct hda_verb cxt5066_init_verbs_portd_lo[] = {
{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
{ } /* end */ { } /* end */
...@@ -2669,6 +2781,8 @@ static int cxt5066_init(struct hda_codec *codec) ...@@ -2669,6 +2781,8 @@ static int cxt5066_init(struct hda_codec *codec)
cxt5066_hp_automute(codec); cxt5066_hp_automute(codec);
if (spec->dell_vostro) if (spec->dell_vostro)
cxt5066_vostro_automic(codec); cxt5066_vostro_automic(codec);
else if (spec->ideapad)
cxt5066_ideapad_automic(codec);
} }
cxt5066_set_mic_boost(codec); cxt5066_set_mic_boost(codec);
return 0; return 0;
...@@ -2694,6 +2808,7 @@ enum { ...@@ -2694,6 +2808,7 @@ enum {
CXT5066_DELL_LAPTOP, /* Dell Laptop */ CXT5066_DELL_LAPTOP, /* Dell Laptop */
CXT5066_OLPC_XO_1_5, /* OLPC XO 1.5 */ CXT5066_OLPC_XO_1_5, /* OLPC XO 1.5 */
CXT5066_DELL_VOSTO, /* Dell Vostro 1015i */ CXT5066_DELL_VOSTO, /* Dell Vostro 1015i */
CXT5066_IDEAPAD, /* Lenovo IdeaPad U150 */
CXT5066_MODELS CXT5066_MODELS
}; };
...@@ -2701,7 +2816,8 @@ static const char *cxt5066_models[CXT5066_MODELS] = { ...@@ -2701,7 +2816,8 @@ static const char *cxt5066_models[CXT5066_MODELS] = {
[CXT5066_LAPTOP] = "laptop", [CXT5066_LAPTOP] = "laptop",
[CXT5066_DELL_LAPTOP] = "dell-laptop", [CXT5066_DELL_LAPTOP] = "dell-laptop",
[CXT5066_OLPC_XO_1_5] = "olpc-xo-1_5", [CXT5066_OLPC_XO_1_5] = "olpc-xo-1_5",
[CXT5066_DELL_VOSTO] = "dell-vostro" [CXT5066_DELL_VOSTO] = "dell-vostro",
[CXT5066_IDEAPAD] = "ideapad",
}; };
static struct snd_pci_quirk cxt5066_cfg_tbl[] = { static struct snd_pci_quirk cxt5066_cfg_tbl[] = {
...@@ -2711,6 +2827,7 @@ static struct snd_pci_quirk cxt5066_cfg_tbl[] = { ...@@ -2711,6 +2827,7 @@ static struct snd_pci_quirk cxt5066_cfg_tbl[] = {
CXT5066_DELL_LAPTOP), CXT5066_DELL_LAPTOP),
SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT5066_OLPC_XO_1_5), SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT5066_OLPC_XO_1_5),
SND_PCI_QUIRK(0x1028, 0x0402, "Dell Vostro", CXT5066_DELL_VOSTO), SND_PCI_QUIRK(0x1028, 0x0402, "Dell Vostro", CXT5066_DELL_VOSTO),
SND_PCI_QUIRK(0x17aa, 0x3a0d, "ideapad", CXT5066_IDEAPAD),
{} {}
}; };
...@@ -2799,6 +2916,22 @@ static int patch_cxt5066(struct hda_codec *codec) ...@@ -2799,6 +2916,22 @@ static int patch_cxt5066(struct hda_codec *codec)
/* no S/PDIF out */ /* no S/PDIF out */
spec->multiout.dig_out_nid = 0; spec->multiout.dig_out_nid = 0;
/* input source automatically selected */
spec->input_mux = NULL;
break;
case CXT5066_IDEAPAD:
codec->patch_ops.init = cxt5066_init;
codec->patch_ops.unsol_event = cxt5066_ideapad_event;
spec->mixers[spec->num_mixers++] = cxt5066_mixer_master;
spec->mixers[spec->num_mixers++] = cxt5066_mixers;
spec->init_verbs[0] = cxt5066_init_verbs_ideapad;
spec->port_d_mode = 0;
spec->ideapad = 1;
spec->mic_boost = 2; /* default 20dB gain */
/* no S/PDIF out */
spec->multiout.dig_out_nid = 0;
/* input source automatically selected */ /* input source automatically selected */
spec->input_mux = NULL; spec->input_mux = NULL;
break; break;
......
...@@ -131,8 +131,10 @@ enum { ...@@ -131,8 +131,10 @@ enum {
enum { enum {
ALC269_BASIC, ALC269_BASIC,
ALC269_QUANTA_FL1, ALC269_QUANTA_FL1,
ALC269_ASUS_AMIC, ALC269_AMIC,
ALC269_ASUS_DMIC, ALC269_DMIC,
ALC269VB_AMIC,
ALC269VB_DMIC,
ALC269_FUJITSU, ALC269_FUJITSU,
ALC269_LIFEBOOK, ALC269_LIFEBOOK,
ALC269_AUTO, ALC269_AUTO,
...@@ -207,8 +209,10 @@ enum { ...@@ -207,8 +209,10 @@ enum {
ALC882_ASUS_A7J, ALC882_ASUS_A7J,
ALC882_ASUS_A7M, ALC882_ASUS_A7M,
ALC885_MACPRO, ALC885_MACPRO,
ALC885_MBA21,
ALC885_MBP3, ALC885_MBP3,
ALC885_MB5, ALC885_MB5,
ALC885_MACMINI3,
ALC885_IMAC24, ALC885_IMAC24,
ALC885_IMAC91, ALC885_IMAC91,
ALC883_3ST_2ch_DIG, ALC883_3ST_2ch_DIG,
...@@ -841,27 +845,6 @@ static void add_verb(struct alc_spec *spec, const struct hda_verb *verb) ...@@ -841,27 +845,6 @@ static void add_verb(struct alc_spec *spec, const struct hda_verb *verb)
spec->init_verbs[spec->num_init_verbs++] = verb; spec->init_verbs[spec->num_init_verbs++] = verb;
} }
#ifdef CONFIG_PROC_FS
/*
* hook for proc
*/
static void print_realtek_coef(struct snd_info_buffer *buffer,
struct hda_codec *codec, hda_nid_t nid)
{
int coeff;
if (nid != 0x20)
return;
coeff = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PROC_COEF, 0);
snd_iprintf(buffer, " Processing Coefficient: 0x%02x\n", coeff);
coeff = snd_hda_codec_read(codec, nid, 0,
AC_VERB_GET_COEF_INDEX, 0);
snd_iprintf(buffer, " Coefficient Index: 0x%02x\n", coeff);
}
#else
#define print_realtek_coef NULL
#endif
/* /*
* set up from the preset table * set up from the preset table
*/ */
...@@ -1166,6 +1149,7 @@ static void alc_auto_init_amp(struct hda_codec *codec, int type) ...@@ -1166,6 +1149,7 @@ static void alc_auto_init_amp(struct hda_codec *codec, int type)
case 0x10ec0888: case 0x10ec0888:
alc888_coef_init(codec); alc888_coef_init(codec);
break; break;
#if 0 /* XXX: This may cause the silent output on speaker on some machines */
case 0x10ec0267: case 0x10ec0267:
case 0x10ec0268: case 0x10ec0268:
snd_hda_codec_write(codec, 0x20, 0, snd_hda_codec_write(codec, 0x20, 0,
...@@ -1178,6 +1162,7 @@ static void alc_auto_init_amp(struct hda_codec *codec, int type) ...@@ -1178,6 +1162,7 @@ static void alc_auto_init_amp(struct hda_codec *codec, int type)
AC_VERB_SET_PROC_COEF, AC_VERB_SET_PROC_COEF,
tmp | 0x3000); tmp | 0x3000);
break; break;
#endif /* XXX */
} }
break; break;
} }
...@@ -1269,7 +1254,7 @@ static void alc_init_auto_mic(struct hda_codec *codec) ...@@ -1269,7 +1254,7 @@ static void alc_init_auto_mic(struct hda_codec *codec)
*/ */
static int alc_subsystem_id(struct hda_codec *codec, static int alc_subsystem_id(struct hda_codec *codec,
hda_nid_t porta, hda_nid_t porte, hda_nid_t porta, hda_nid_t porte,
hda_nid_t portd) hda_nid_t portd, hda_nid_t porti)
{ {
unsigned int ass, tmp, i; unsigned int ass, tmp, i;
unsigned nid; unsigned nid;
...@@ -1295,7 +1280,7 @@ static int alc_subsystem_id(struct hda_codec *codec, ...@@ -1295,7 +1280,7 @@ static int alc_subsystem_id(struct hda_codec *codec,
snd_printd("realtek: No valid SSID, " snd_printd("realtek: No valid SSID, "
"checking pincfg 0x%08x for NID 0x%x\n", "checking pincfg 0x%08x for NID 0x%x\n",
ass, nid); ass, nid);
if (!(ass & 1) && !(ass & 0x100000)) if (!(ass & 1))
return 0; return 0;
if ((ass >> 30) != 1) /* no physical connection */ if ((ass >> 30) != 1) /* no physical connection */
return 0; return 0;
...@@ -1355,6 +1340,8 @@ static int alc_subsystem_id(struct hda_codec *codec, ...@@ -1355,6 +1340,8 @@ static int alc_subsystem_id(struct hda_codec *codec,
nid = porte; nid = porte;
else if (tmp == 2) else if (tmp == 2)
nid = portd; nid = portd;
else if (tmp == 3)
nid = porti;
else else
return 1; return 1;
for (i = 0; i < spec->autocfg.line_outs; i++) for (i = 0; i < spec->autocfg.line_outs; i++)
...@@ -1369,9 +1356,10 @@ static int alc_subsystem_id(struct hda_codec *codec, ...@@ -1369,9 +1356,10 @@ static int alc_subsystem_id(struct hda_codec *codec,
} }
static void alc_ssid_check(struct hda_codec *codec, static void alc_ssid_check(struct hda_codec *codec,
hda_nid_t porta, hda_nid_t porte, hda_nid_t portd) hda_nid_t porta, hda_nid_t porte,
hda_nid_t portd, hda_nid_t porti)
{ {
if (!alc_subsystem_id(codec, porta, porte, portd)) { if (!alc_subsystem_id(codec, porta, porte, portd, porti)) {
struct alc_spec *spec = codec->spec; struct alc_spec *spec = codec->spec;
snd_printd("realtek: " snd_printd("realtek: "
"Enable default setup for auto mode as fallback\n"); "Enable default setup for auto mode as fallback\n");
...@@ -3729,25 +3717,22 @@ static void alc_power_eapd(struct hda_codec *codec) ...@@ -3729,25 +3717,22 @@ static void alc_power_eapd(struct hda_codec *codec)
/* We currently only handle front, HP */ /* We currently only handle front, HP */
switch (codec->vendor_id) { switch (codec->vendor_id) {
case 0x10ec0260: case 0x10ec0260:
snd_hda_codec_write(codec, 0x0f, 0, set_eapd(codec, 0x0f, 0);
AC_VERB_SET_EAPD_BTLENABLE, 0x00); set_eapd(codec, 0x10, 0);
snd_hda_codec_write(codec, 0x10, 0,
AC_VERB_SET_EAPD_BTLENABLE, 0x00);
break; break;
case 0x10ec0262: case 0x10ec0262:
case 0x10ec0267: case 0x10ec0267:
case 0x10ec0268: case 0x10ec0268:
case 0x10ec0269: case 0x10ec0269:
case 0x10ec0270:
case 0x10ec0272: case 0x10ec0272:
case 0x10ec0660: case 0x10ec0660:
case 0x10ec0662: case 0x10ec0662:
case 0x10ec0663: case 0x10ec0663:
case 0x10ec0862: case 0x10ec0862:
case 0x10ec0889: case 0x10ec0889:
snd_hda_codec_write(codec, 0x14, 0, set_eapd(codec, 0x14, 0);
AC_VERB_SET_EAPD_BTLENABLE, 0x00); set_eapd(codec, 0x15, 0);
snd_hda_codec_write(codec, 0x15, 0,
AC_VERB_SET_EAPD_BTLENABLE, 0x00);
break; break;
} }
} }
...@@ -4877,7 +4862,7 @@ static int alc880_parse_auto_config(struct hda_codec *codec) ...@@ -4877,7 +4862,7 @@ static int alc880_parse_auto_config(struct hda_codec *codec)
spec->num_mux_defs = 1; spec->num_mux_defs = 1;
spec->input_mux = &spec->private_imux[0]; spec->input_mux = &spec->private_imux[0];
alc_ssid_check(codec, 0x15, 0x1b, 0x14); alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
return 1; return 1;
} }
...@@ -5081,7 +5066,6 @@ static int patch_alc880(struct hda_codec *codec) ...@@ -5081,7 +5066,6 @@ static int patch_alc880(struct hda_codec *codec)
if (!spec->loopback.amplist) if (!spec->loopback.amplist)
spec->loopback.amplist = alc880_loopbacks; spec->loopback.amplist = alc880_loopbacks;
#endif #endif
codec->proc_widget_hook = print_realtek_coef;
return 0; return 0;
} }
...@@ -6412,7 +6396,7 @@ static int alc260_parse_auto_config(struct hda_codec *codec) ...@@ -6412,7 +6396,7 @@ static int alc260_parse_auto_config(struct hda_codec *codec)
spec->num_mux_defs = 1; spec->num_mux_defs = 1;
spec->input_mux = &spec->private_imux[0]; spec->input_mux = &spec->private_imux[0];
alc_ssid_check(codec, 0x10, 0x15, 0x0f); alc_ssid_check(codec, 0x10, 0x15, 0x0f, 0);
return 1; return 1;
} }
...@@ -6691,7 +6675,6 @@ static int patch_alc260(struct hda_codec *codec) ...@@ -6691,7 +6675,6 @@ static int patch_alc260(struct hda_codec *codec)
if (!spec->loopback.amplist) if (!spec->loopback.amplist)
spec->loopback.amplist = alc260_loopbacks; spec->loopback.amplist = alc260_loopbacks;
#endif #endif
codec->proc_widget_hook = print_realtek_coef;
return 0; return 0;
} }
...@@ -6773,6 +6756,14 @@ static struct hda_input_mux mb5_capture_source = { ...@@ -6773,6 +6756,14 @@ static struct hda_input_mux mb5_capture_source = {
}, },
}; };
static struct hda_input_mux macmini3_capture_source = {
.num_items = 2,
.items = {
{ "Line", 0x2 },
{ "CD", 0x4 },
},
};
static struct hda_input_mux alc883_3stack_6ch_intel = { static struct hda_input_mux alc883_3stack_6ch_intel = {
.num_items = 4, .num_items = 4,
.items = { .items = {
...@@ -6961,6 +6952,13 @@ static struct hda_channel_mode alc882_sixstack_modes[2] = { ...@@ -6961,6 +6952,13 @@ static struct hda_channel_mode alc882_sixstack_modes[2] = {
{ 8, alc882_sixstack_ch8_init }, { 8, alc882_sixstack_ch8_init },
}; };
/* Macbook Air 2,1 */
static struct hda_channel_mode alc885_mba21_ch_modes[1] = {
{ 2, NULL },
};
/* /*
* macbook pro ALC885 can switch LineIn to LineOut without losing Mic * macbook pro ALC885 can switch LineIn to LineOut without losing Mic
*/ */
...@@ -7021,6 +7019,7 @@ static struct hda_channel_mode alc885_mb5_6ch_modes[2] = { ...@@ -7021,6 +7019,7 @@ static struct hda_channel_mode alc885_mb5_6ch_modes[2] = {
{ 6, alc885_mb5_ch6_init }, { 6, alc885_mb5_ch6_init },
}; };
#define alc885_macmini3_6ch_modes alc885_mb5_6ch_modes
/* /*
* 2ch mode * 2ch mode
...@@ -7232,6 +7231,15 @@ static struct snd_kcontrol_new alc882_base_mixer[] = { ...@@ -7232,6 +7231,15 @@ static struct snd_kcontrol_new alc882_base_mixer[] = {
{ } /* end */ { } /* end */
}; };
/* Macbook Air 2,1 same control for HP and internal Speaker */
static struct snd_kcontrol_new alc885_mba21_mixer[] = {
HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
HDA_BIND_MUTE("Speaker Playback Switch", 0x0c, 0x02, HDA_OUTPUT),
{ }
};
static struct snd_kcontrol_new alc885_mbp3_mixer[] = { static struct snd_kcontrol_new alc885_mbp3_mixer[] = {
HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x00, HDA_OUTPUT), HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
HDA_BIND_MUTE ("Speaker Playback Switch", 0x0c, 0x02, HDA_INPUT), HDA_BIND_MUTE ("Speaker Playback Switch", 0x0c, 0x02, HDA_INPUT),
...@@ -7265,6 +7273,21 @@ static struct snd_kcontrol_new alc885_mb5_mixer[] = { ...@@ -7265,6 +7273,21 @@ static struct snd_kcontrol_new alc885_mb5_mixer[] = {
{ } /* end */ { } /* end */
}; };
static struct snd_kcontrol_new alc885_macmini3_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
HDA_BIND_MUTE ("Front Playback Switch", 0x0c, 0x02, HDA_INPUT),
HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT),
HDA_BIND_MUTE ("Surround Playback Switch", 0x0d, 0x02, HDA_INPUT),
HDA_CODEC_VOLUME("LFE Playback Volume", 0x0e, 0x00, HDA_OUTPUT),
HDA_BIND_MUTE ("LFE Playback Switch", 0x0e, 0x02, HDA_INPUT),
HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0f, 0x00, HDA_OUTPUT),
HDA_BIND_MUTE ("Headphone Playback Switch", 0x0f, 0x02, HDA_INPUT),
HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x07, HDA_INPUT),
HDA_CODEC_MUTE ("Line Playback Switch", 0x0b, 0x07, HDA_INPUT),
HDA_CODEC_VOLUME("Line Boost", 0x15, 0x00, HDA_INPUT),
{ } /* end */
};
static struct snd_kcontrol_new alc885_imac91_mixer[] = { static struct snd_kcontrol_new alc885_imac91_mixer[] = {
HDA_CODEC_VOLUME("Line-Out Playback Volume", 0x0c, 0x00, HDA_OUTPUT), HDA_CODEC_VOLUME("Line-Out Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
HDA_BIND_MUTE ("Line-Out Playback Switch", 0x0c, 0x02, HDA_INPUT), HDA_BIND_MUTE ("Line-Out Playback Switch", 0x0c, 0x02, HDA_INPUT),
...@@ -7356,29 +7379,18 @@ static struct snd_kcontrol_new alc882_chmode_mixer[] = { ...@@ -7356,29 +7379,18 @@ static struct snd_kcontrol_new alc882_chmode_mixer[] = {
static struct hda_verb alc882_base_init_verbs[] = { static struct hda_verb alc882_base_init_verbs[] = {
/* Front mixer: unmute input/output amp left and right (volume = 0) */ /* Front mixer: unmute input/output amp left and right (volume = 0) */
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
/* Rear mixer */ /* Rear mixer */
{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
/* CLFE mixer */ /* CLFE mixer */
{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
/* Side mixer */ /* Side mixer */
{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
/* mute analog input loopbacks */
{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
/* Front Pin: output 0 (0x0c) */ /* Front Pin: output 0 (0x0c) */
{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
...@@ -7415,14 +7427,8 @@ static struct hda_verb alc882_base_init_verbs[] = { ...@@ -7415,14 +7427,8 @@ static struct hda_verb alc882_base_init_verbs[] = {
/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
/* Input mixer2 */ /* Input mixer2 */
{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
/* Input mixer3 */ /* Input mixer3 */
{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
/* ADC2: mute amp left and right */ /* ADC2: mute amp left and right */
{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
{0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
...@@ -7466,26 +7472,17 @@ static struct hda_verb alc_hp15_unsol_verbs[] = { ...@@ -7466,26 +7472,17 @@ static struct hda_verb alc_hp15_unsol_verbs[] = {
static struct hda_verb alc885_init_verbs[] = { static struct hda_verb alc885_init_verbs[] = {
/* Front mixer: unmute input/output amp left and right (volume = 0) */ /* Front mixer: unmute input/output amp left and right (volume = 0) */
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
/* Rear mixer */ /* Rear mixer */
{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
/* CLFE mixer */ /* CLFE mixer */
{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
/* Side mixer */ /* Side mixer */
{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
/* mute analog input loopbacks */
{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
/* Front HP Pin: output 0 (0x0c) */ /* Front HP Pin: output 0 (0x0c) */
{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
...@@ -7519,17 +7516,11 @@ static struct hda_verb alc885_init_verbs[] = { ...@@ -7519,17 +7516,11 @@ static struct hda_verb alc885_init_verbs[] = {
/* Mixer elements: 0x18, , 0x1a, 0x1b */ /* Mixer elements: 0x18, , 0x1a, 0x1b */
/* Input mixer1 */ /* Input mixer1 */
{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
/* Input mixer2 */ /* Input mixer2 */
{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
/* Input mixer3 */ /* Input mixer3 */
{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
/* ADC2: mute amp left and right */ /* ADC2: mute amp left and right */
{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
/* ADC3: mute amp left and right */ /* ADC3: mute amp left and right */
...@@ -7671,6 +7662,76 @@ static struct hda_verb alc885_mb5_init_verbs[] = { ...@@ -7671,6 +7662,76 @@ static struct hda_verb alc885_mb5_init_verbs[] = {
{ } { }
}; };
/* Macmini 3,1 */
static struct hda_verb alc885_macmini3_init_verbs[] = {
/* DACs */
{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
/* Front mixer */
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
/* Surround mixer */
{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
/* LFE mixer */
{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
/* HP mixer */
{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
/* Front Pin (0x0c) */
{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x01},
{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
{0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
/* LFE Pin (0x0e) */
{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x01},
{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
{0x1a, AC_VERB_SET_CONNECT_SEL, 0x02},
/* HP Pin (0x0f) */
{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
{0x14, AC_VERB_SET_CONNECT_SEL, 0x03},
{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
/* Line In pin */
{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
{ }
};
static struct hda_verb alc885_mba21_init_verbs[] = {
/*Internal and HP Speaker Mixer*/
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
/*Internal Speaker Pin (0x0c)*/
{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, (PIN_OUT | AC_PINCTL_VREF_50) },
{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
{0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
/* HP Pin: output 0 (0x0e) */
{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc4},
{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, (ALC880_HP_EVENT | AC_USRSP_EN)},
/* Line in (is hp when jack connected)*/
{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, AC_PINCTL_VREF_50},
{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
{ }
};
/* Macbook Pro rev3 */ /* Macbook Pro rev3 */
static struct hda_verb alc885_mbp3_init_verbs[] = { static struct hda_verb alc885_mbp3_init_verbs[] = {
/* Front mixer: unmute input/output amp left and right (volume = 0) */ /* Front mixer: unmute input/output amp left and right (volume = 0) */
...@@ -7833,54 +7894,35 @@ static void alc885_imac24_setup(struct hda_codec *codec) ...@@ -7833,54 +7894,35 @@ static void alc885_imac24_setup(struct hda_codec *codec)
spec->autocfg.speaker_pins[1] = 0x1a; spec->autocfg.speaker_pins[1] = 0x1a;
} }
static void alc885_mbp3_setup(struct hda_codec *codec) #define alc885_mb5_setup alc885_imac24_setup
#define alc885_macmini3_setup alc885_imac24_setup
/* Macbook Air 2,1 */
static void alc885_mba21_setup(struct hda_codec *codec)
{ {
struct alc_spec *spec = codec->spec; struct alc_spec *spec = codec->spec;
spec->autocfg.hp_pins[0] = 0x15; spec->autocfg.hp_pins[0] = 0x14;
spec->autocfg.speaker_pins[0] = 0x14; spec->autocfg.speaker_pins[0] = 0x18;
} }
static void alc885_mb5_automute(struct hda_codec *codec)
{
unsigned int present;
present = snd_hda_codec_read(codec, 0x14, 0,
AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
snd_hda_codec_amp_stereo(codec, 0x18, HDA_OUTPUT, 0,
HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
snd_hda_codec_amp_stereo(codec, 0x1a, HDA_OUTPUT, 0,
HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
}
static void alc885_mb5_unsol_event(struct hda_codec *codec,
unsigned int res)
{
/* Headphone insertion or removal. */
if ((res >> 26) == ALC880_HP_EVENT)
alc885_mb5_automute(codec);
}
static void alc885_imac91_automute(struct hda_codec *codec) static void alc885_mbp3_setup(struct hda_codec *codec)
{ {
unsigned int present; struct alc_spec *spec = codec->spec;
present = snd_hda_codec_read(codec, 0x14, 0,
AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
snd_hda_codec_amp_stereo(codec, 0x1a, HDA_OUTPUT, 0,
HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
spec->autocfg.hp_pins[0] = 0x15;
spec->autocfg.speaker_pins[0] = 0x14;
} }
static void alc885_imac91_unsol_event(struct hda_codec *codec, static void alc885_imac91_setup(struct hda_codec *codec)
unsigned int res)
{ {
/* Headphone insertion or removal. */ struct alc_spec *spec = codec->spec;
if ((res >> 26) == ALC880_HP_EVENT)
alc885_imac91_automute(codec); spec->autocfg.hp_pins[0] = 0x14;
spec->autocfg.speaker_pins[0] = 0x15;
spec->autocfg.speaker_pins[1] = 0x1a;
} }
static struct hda_verb alc882_targa_verbs[] = { static struct hda_verb alc882_targa_verbs[] = {
...@@ -8015,18 +8057,6 @@ static struct hda_verb alc883_auto_init_verbs[] = { ...@@ -8015,18 +8057,6 @@ static struct hda_verb alc883_auto_init_verbs[] = {
{0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
/* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
* mixer widget
* Note: PASD motherboards uses the Line In 2 as the input for
* front panel mic (mic 2)
*/
/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
/* /*
* Set up output mixers (0x0c - 0x0f) * Set up output mixers (0x0c - 0x0f)
*/ */
...@@ -8051,16 +8081,9 @@ static struct hda_verb alc883_auto_init_verbs[] = { ...@@ -8051,16 +8081,9 @@ static struct hda_verb alc883_auto_init_verbs[] = {
/* FIXME: use matrix-type input source selection */ /* FIXME: use matrix-type input source selection */
/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
/* Input mixer2 */ /* Input mixer2 */
{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
/* Input mixer3 */ /* Input mixer3 */
{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
{ } { }
}; };
...@@ -9047,6 +9070,8 @@ static const char *alc882_models[ALC882_MODEL_LAST] = { ...@@ -9047,6 +9070,8 @@ static const char *alc882_models[ALC882_MODEL_LAST] = {
[ALC882_ASUS_A7M] = "asus-a7m", [ALC882_ASUS_A7M] = "asus-a7m",
[ALC885_MACPRO] = "macpro", [ALC885_MACPRO] = "macpro",
[ALC885_MB5] = "mb5", [ALC885_MB5] = "mb5",
[ALC885_MACMINI3] = "macmini3",
[ALC885_MBA21] = "mba21",
[ALC885_MBP3] = "mbp3", [ALC885_MBP3] = "mbp3",
[ALC885_IMAC24] = "imac24", [ALC885_IMAC24] = "imac24",
[ALC885_IMAC91] = "imac91", [ALC885_IMAC91] = "imac91",
...@@ -9230,6 +9255,7 @@ static struct snd_pci_quirk alc882_ssid_cfg_tbl[] = { ...@@ -9230,6 +9255,7 @@ static struct snd_pci_quirk alc882_ssid_cfg_tbl[] = {
*/ */
SND_PCI_QUIRK(0x106b, 0x4000, "MacbookPro 5,1", ALC885_MB5), SND_PCI_QUIRK(0x106b, 0x4000, "MacbookPro 5,1", ALC885_MB5),
SND_PCI_QUIRK(0x106b, 0x4600, "MacbookPro 5,2", ALC885_MB5), SND_PCI_QUIRK(0x106b, 0x4600, "MacbookPro 5,2", ALC885_MB5),
SND_PCI_QUIRK(0x106b, 0x4100, "Macmini 3,1", ALC885_MACMINI3),
{} /* terminator */ {} /* terminator */
}; };
...@@ -9280,6 +9306,18 @@ static struct alc_config_preset alc882_presets[] = { ...@@ -9280,6 +9306,18 @@ static struct alc_config_preset alc882_presets[] = {
.need_dac_fix = 1, .need_dac_fix = 1,
.input_mux = &alc882_capture_source, .input_mux = &alc882_capture_source,
.dig_out_nid = ALC882_DIGOUT_NID, .dig_out_nid = ALC882_DIGOUT_NID,
},
[ALC885_MBA21] = {
.mixers = { alc885_mba21_mixer },
.init_verbs = { alc885_mba21_init_verbs, alc880_gpio1_init_verbs },
.num_dacs = 2,
.dac_nids = alc882_dac_nids,
.channel_mode = alc885_mba21_ch_modes,
.num_channel_mode = ARRAY_SIZE(alc885_mba21_ch_modes),
.input_mux = &alc882_capture_source,
.unsol_event = alc_automute_amp_unsol_event,
.setup = alc885_mba21_setup,
.init_hook = alc_automute_amp,
}, },
[ALC885_MBP3] = { [ALC885_MBP3] = {
.mixers = { alc885_mbp3_mixer, alc882_chmode_mixer }, .mixers = { alc885_mbp3_mixer, alc882_chmode_mixer },
...@@ -9308,8 +9346,24 @@ static struct alc_config_preset alc882_presets[] = { ...@@ -9308,8 +9346,24 @@ static struct alc_config_preset alc882_presets[] = {
.input_mux = &mb5_capture_source, .input_mux = &mb5_capture_source,
.dig_out_nid = ALC882_DIGOUT_NID, .dig_out_nid = ALC882_DIGOUT_NID,
.dig_in_nid = ALC882_DIGIN_NID, .dig_in_nid = ALC882_DIGIN_NID,
.unsol_event = alc885_mb5_unsol_event, .unsol_event = alc_automute_amp_unsol_event,
.init_hook = alc885_mb5_automute, .setup = alc885_mb5_setup,
.init_hook = alc_automute_amp,
},
[ALC885_MACMINI3] = {
.mixers = { alc885_macmini3_mixer, alc882_chmode_mixer },
.init_verbs = { alc885_macmini3_init_verbs,
alc880_gpio1_init_verbs },
.num_dacs = ARRAY_SIZE(alc882_dac_nids),
.dac_nids = alc882_dac_nids,
.channel_mode = alc885_macmini3_6ch_modes,
.num_channel_mode = ARRAY_SIZE(alc885_macmini3_6ch_modes),
.input_mux = &macmini3_capture_source,
.dig_out_nid = ALC882_DIGOUT_NID,
.dig_in_nid = ALC882_DIGIN_NID,
.unsol_event = alc_automute_amp_unsol_event,
.setup = alc885_macmini3_setup,
.init_hook = alc_automute_amp,
}, },
[ALC885_MACPRO] = { [ALC885_MACPRO] = {
.mixers = { alc882_macpro_mixer }, .mixers = { alc882_macpro_mixer },
...@@ -9348,8 +9402,9 @@ static struct alc_config_preset alc882_presets[] = { ...@@ -9348,8 +9402,9 @@ static struct alc_config_preset alc882_presets[] = {
.input_mux = &alc882_capture_source, .input_mux = &alc882_capture_source,
.dig_out_nid = ALC882_DIGOUT_NID, .dig_out_nid = ALC882_DIGOUT_NID,
.dig_in_nid = ALC882_DIGIN_NID, .dig_in_nid = ALC882_DIGIN_NID,
.unsol_event = alc885_imac91_unsol_event, .unsol_event = alc_automute_amp_unsol_event,
.init_hook = alc885_imac91_automute, .setup = alc885_imac91_setup,
.init_hook = alc_automute_amp,
}, },
[ALC882_TARGA] = { [ALC882_TARGA] = {
.mixers = { alc882_targa_mixer, alc882_chmode_mixer }, .mixers = { alc882_targa_mixer, alc882_chmode_mixer },
...@@ -10172,7 +10227,7 @@ static int alc882_parse_auto_config(struct hda_codec *codec) ...@@ -10172,7 +10227,7 @@ static int alc882_parse_auto_config(struct hda_codec *codec)
spec->num_mux_defs = 1; spec->num_mux_defs = 1;
spec->input_mux = &spec->private_imux[0]; spec->input_mux = &spec->private_imux[0];
alc_ssid_check(codec, 0x15, 0x1b, 0x14); alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
err = alc_auto_add_mic_boost(codec); err = alc_auto_add_mic_boost(codec);
if (err < 0) if (err < 0)
...@@ -10310,7 +10365,6 @@ static int patch_alc882(struct hda_codec *codec) ...@@ -10310,7 +10365,6 @@ static int patch_alc882(struct hda_codec *codec)
if (!spec->loopback.amplist) if (!spec->loopback.amplist)
spec->loopback.amplist = alc882_loopbacks; spec->loopback.amplist = alc882_loopbacks;
#endif #endif
codec->proc_widget_hook = print_realtek_coef;
return 0; return 0;
} }
...@@ -11731,7 +11785,7 @@ static int alc262_parse_auto_config(struct hda_codec *codec) ...@@ -11731,7 +11785,7 @@ static int alc262_parse_auto_config(struct hda_codec *codec)
if (err < 0) if (err < 0)
return err; return err;
alc_ssid_check(codec, 0x15, 0x14, 0x1b); alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
return 1; return 1;
} }
...@@ -12174,7 +12228,6 @@ static int patch_alc262(struct hda_codec *codec) ...@@ -12174,7 +12228,6 @@ static int patch_alc262(struct hda_codec *codec)
if (!spec->loopback.amplist) if (!spec->loopback.amplist)
spec->loopback.amplist = alc262_loopbacks; spec->loopback.amplist = alc262_loopbacks;
#endif #endif
codec->proc_widget_hook = print_realtek_coef;
return 0; return 0;
} }
...@@ -12683,7 +12736,6 @@ static int alc268_new_analog_output(struct alc_spec *spec, hda_nid_t nid, ...@@ -12683,7 +12736,6 @@ static int alc268_new_analog_output(struct alc_spec *spec, hda_nid_t nid,
dac = 0x02; dac = 0x02;
break; break;
case 0x15: case 0x15:
case 0x21:
dac = 0x03; dac = 0x03;
break; break;
default: default:
...@@ -12904,7 +12956,7 @@ static int alc268_parse_auto_config(struct hda_codec *codec) ...@@ -12904,7 +12956,7 @@ static int alc268_parse_auto_config(struct hda_codec *codec)
if (err < 0) if (err < 0)
return err; return err;
alc_ssid_check(codec, 0x15, 0x1b, 0x14); alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
return 1; return 1;
} }
...@@ -13241,8 +13293,6 @@ static int patch_alc268(struct hda_codec *codec) ...@@ -13241,8 +13293,6 @@ static int patch_alc268(struct hda_codec *codec)
if (board_config == ALC268_AUTO) if (board_config == ALC268_AUTO)
spec->init_hook = alc268_auto_init; spec->init_hook = alc268_auto_init;
codec->proc_widget_hook = print_realtek_coef;
return 0; return 0;
} }
...@@ -13262,6 +13312,15 @@ static hda_nid_t alc269_capsrc_nids[1] = { ...@@ -13262,6 +13312,15 @@ static hda_nid_t alc269_capsrc_nids[1] = {
0x23, 0x23,
}; };
static hda_nid_t alc269vb_adc_nids[1] = {
/* ADC1 */
0x09,
};
static hda_nid_t alc269vb_capsrc_nids[1] = {
0x22,
};
/* NOTE: ADC2 (0x07) is connected from a recording *MIXER* (0x24), /* NOTE: ADC2 (0x07) is connected from a recording *MIXER* (0x24),
* not a mux! * not a mux!
*/ */
...@@ -13330,7 +13389,7 @@ static struct snd_kcontrol_new alc269_lifebook_mixer[] = { ...@@ -13330,7 +13389,7 @@ static struct snd_kcontrol_new alc269_lifebook_mixer[] = {
{ } { }
}; };
static struct snd_kcontrol_new alc269_eeepc_mixer[] = { static struct snd_kcontrol_new alc269_laptop_mixer[] = {
HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT), HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
...@@ -13338,16 +13397,47 @@ static struct snd_kcontrol_new alc269_eeepc_mixer[] = { ...@@ -13338,16 +13397,47 @@ static struct snd_kcontrol_new alc269_eeepc_mixer[] = {
{ } /* end */ { } /* end */
}; };
static struct snd_kcontrol_new alc269vb_laptop_mixer[] = {
HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Headphone Playback Switch", 0x21, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
{ } /* end */
};
/* capture mixer elements */ /* capture mixer elements */
static struct snd_kcontrol_new alc269_epc_capture_mixer[] = { static struct snd_kcontrol_new alc269_laptop_analog_capture_mixer[] = {
HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
HDA_CODEC_VOLUME("IntMic Boost", 0x19, 0, HDA_INPUT),
{ } /* end */
};
static struct snd_kcontrol_new alc269_laptop_digital_capture_mixer[] = {
HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
{ } /* end */
};
static struct snd_kcontrol_new alc269vb_laptop_analog_capture_mixer[] = {
HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
HDA_CODEC_VOLUME("IntMic Boost", 0x19, 0, HDA_INPUT),
{ } /* end */
};
static struct snd_kcontrol_new alc269vb_laptop_digital_capture_mixer[] = {
HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
{ } /* end */ { } /* end */
}; };
/* FSC amilo */ /* FSC amilo */
#define alc269_fujitsu_mixer alc269_eeepc_mixer #define alc269_fujitsu_mixer alc269_laptop_mixer
static struct hda_verb alc269_quanta_fl1_verbs[] = { static struct hda_verb alc269_quanta_fl1_verbs[] = {
{0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
...@@ -13490,7 +13580,7 @@ static void alc269_lifebook_init_hook(struct hda_codec *codec) ...@@ -13490,7 +13580,7 @@ static void alc269_lifebook_init_hook(struct hda_codec *codec)
alc269_lifebook_mic_autoswitch(codec); alc269_lifebook_mic_autoswitch(codec);
} }
static struct hda_verb alc269_eeepc_dmic_init_verbs[] = { static struct hda_verb alc269_laptop_dmic_init_verbs[] = {
{0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
{0x23, AC_VERB_SET_CONNECT_SEL, 0x05}, {0x23, AC_VERB_SET_CONNECT_SEL, 0x05},
{0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 }, {0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 },
...@@ -13501,7 +13591,7 @@ static struct hda_verb alc269_eeepc_dmic_init_verbs[] = { ...@@ -13501,7 +13591,7 @@ static struct hda_verb alc269_eeepc_dmic_init_verbs[] = {
{} {}
}; };
static struct hda_verb alc269_eeepc_amic_init_verbs[] = { static struct hda_verb alc269_laptop_amic_init_verbs[] = {
{0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
{0x23, AC_VERB_SET_CONNECT_SEL, 0x01}, {0x23, AC_VERB_SET_CONNECT_SEL, 0x01},
{0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 }, {0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 },
...@@ -13511,6 +13601,28 @@ static struct hda_verb alc269_eeepc_amic_init_verbs[] = { ...@@ -13511,6 +13601,28 @@ static struct hda_verb alc269_eeepc_amic_init_verbs[] = {
{} {}
}; };
static struct hda_verb alc269vb_laptop_dmic_init_verbs[] = {
{0x21, AC_VERB_SET_CONNECT_SEL, 0x01},
{0x22, AC_VERB_SET_CONNECT_SEL, 0x06},
{0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 },
{0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7019 | (0x00 << 8))},
{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
{0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
{}
};
static struct hda_verb alc269vb_laptop_amic_init_verbs[] = {
{0x21, AC_VERB_SET_CONNECT_SEL, 0x01},
{0x22, AC_VERB_SET_CONNECT_SEL, 0x01},
{0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 },
{0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7019 | (0x00 << 8))},
{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
{0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
{}
};
/* toggle speaker-output according to the hp-jack state */ /* toggle speaker-output according to the hp-jack state */
static void alc269_speaker_automute(struct hda_codec *codec) static void alc269_speaker_automute(struct hda_codec *codec)
{ {
...@@ -13528,7 +13640,7 @@ static void alc269_speaker_automute(struct hda_codec *codec) ...@@ -13528,7 +13640,7 @@ static void alc269_speaker_automute(struct hda_codec *codec)
} }
/* unsolicited event for HP jack sensing */ /* unsolicited event for HP jack sensing */
static void alc269_eeepc_unsol_event(struct hda_codec *codec, static void alc269_laptop_unsol_event(struct hda_codec *codec,
unsigned int res) unsigned int res)
{ {
switch (res >> 26) { switch (res >> 26) {
...@@ -13541,7 +13653,7 @@ static void alc269_eeepc_unsol_event(struct hda_codec *codec, ...@@ -13541,7 +13653,7 @@ static void alc269_eeepc_unsol_event(struct hda_codec *codec,
} }
} }
static void alc269_eeepc_dmic_setup(struct hda_codec *codec) static void alc269_laptop_dmic_setup(struct hda_codec *codec)
{ {
struct alc_spec *spec = codec->spec; struct alc_spec *spec = codec->spec;
spec->ext_mic.pin = 0x18; spec->ext_mic.pin = 0x18;
...@@ -13551,7 +13663,17 @@ static void alc269_eeepc_dmic_setup(struct hda_codec *codec) ...@@ -13551,7 +13663,17 @@ static void alc269_eeepc_dmic_setup(struct hda_codec *codec)
spec->auto_mic = 1; spec->auto_mic = 1;
} }
static void alc269_eeepc_amic_setup(struct hda_codec *codec) static void alc269vb_laptop_dmic_setup(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
spec->ext_mic.pin = 0x18;
spec->ext_mic.mux_idx = 0;
spec->int_mic.pin = 0x12;
spec->int_mic.mux_idx = 6;
spec->auto_mic = 1;
}
static void alc269_laptop_amic_setup(struct hda_codec *codec)
{ {
struct alc_spec *spec = codec->spec; struct alc_spec *spec = codec->spec;
spec->ext_mic.pin = 0x18; spec->ext_mic.pin = 0x18;
...@@ -13561,7 +13683,7 @@ static void alc269_eeepc_amic_setup(struct hda_codec *codec) ...@@ -13561,7 +13683,7 @@ static void alc269_eeepc_amic_setup(struct hda_codec *codec)
spec->auto_mic = 1; spec->auto_mic = 1;
} }
static void alc269_eeepc_inithook(struct hda_codec *codec) static void alc269_laptop_inithook(struct hda_codec *codec)
{ {
alc269_speaker_automute(codec); alc269_speaker_automute(codec);
alc_mic_automute(codec); alc_mic_automute(codec);
...@@ -13574,22 +13696,10 @@ static struct hda_verb alc269_init_verbs[] = { ...@@ -13574,22 +13696,10 @@ static struct hda_verb alc269_init_verbs[] = {
/* /*
* Unmute ADC0 and set the default input to mic-in * Unmute ADC0 and set the default input to mic-in
*/ */
{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
/* Mute input amps (PCBeep, Line In, Mic 1 & Mic 2) of the
* analog-loopback mixer widget
* Note: PASD motherboards uses the Line In 2 as the input for
* front panel mic (mic 2)
*/
/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
/* /*
* Set up output mixers (0x0c - 0x0e) * Set up output mixers (0x02 - 0x03)
*/ */
/* set vol=0 to output mixers */ /* set vol=0 to output mixers */
{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
...@@ -13614,26 +13724,57 @@ static struct hda_verb alc269_init_verbs[] = { ...@@ -13614,26 +13724,57 @@ static struct hda_verb alc269_init_verbs[] = {
{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
{0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, /* FIXME: use Mux-type input source selection */
{0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Mixer elements: 0x18, 19, 1a, 1b, 1d, 0b */
/* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
{0x23, AC_VERB_SET_CONNECT_SEL, 0x00},
/* FIXME: use matrix-type input source selection */ /* set EAPD */
{0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
{ }
};
static struct hda_verb alc269vb_init_verbs[] = {
/*
* Unmute ADC0 and set the default input to mic-in
*/
{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
/*
* Set up output mixers (0x02 - 0x03)
*/
/* set vol=0 to output mixers */
{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
/* set up input amps for analog loopback */
/* Amp Indices: DAC = 0, mixer = 1 */
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
{0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
/* FIXME: use Mux-type input source selection */
/* Mixer elements: 0x18, 19, 1a, 1b, 1d, 0b */ /* Mixer elements: 0x18, 19, 1a, 1b, 1d, 0b */
/* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */ /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, {0x22, AC_VERB_SET_CONNECT_SEL, 0x00},
{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
/* set EAPD */ /* set EAPD */
{0x14, AC_VERB_SET_EAPD_BTLENABLE, 2}, {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
{0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
{ } { }
}; };
...@@ -13681,6 +13822,7 @@ static int alc269_parse_auto_config(struct hda_codec *codec) ...@@ -13681,6 +13822,7 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
struct alc_spec *spec = codec->spec; struct alc_spec *spec = codec->spec;
int err; int err;
static hda_nid_t alc269_ignore[] = { 0x1d, 0 }; static hda_nid_t alc269_ignore[] = { 0x1d, 0 };
hda_nid_t real_capsrc_nids;
err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
alc269_ignore); alc269_ignore);
...@@ -13702,11 +13844,20 @@ static int alc269_parse_auto_config(struct hda_codec *codec) ...@@ -13702,11 +13844,20 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
if (spec->kctls.list) if (spec->kctls.list)
add_mixer(spec, spec->kctls.list); add_mixer(spec, spec->kctls.list);
if ((alc_read_coef_idx(codec, 0) & 0x00f0) == 0x0010) {
add_verb(spec, alc269vb_init_verbs);
real_capsrc_nids = alc269vb_capsrc_nids[0];
alc_ssid_check(codec, 0, 0x1b, 0x14, 0x21);
} else {
add_verb(spec, alc269_init_verbs); add_verb(spec, alc269_init_verbs);
real_capsrc_nids = alc269_capsrc_nids[0];
alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
}
spec->num_mux_defs = 1; spec->num_mux_defs = 1;
spec->input_mux = &spec->private_imux[0]; spec->input_mux = &spec->private_imux[0];
/* set default input source */ /* set default input source */
snd_hda_codec_write_cache(codec, alc269_capsrc_nids[0], snd_hda_codec_write_cache(codec, real_capsrc_nids,
0, AC_VERB_SET_CONNECT_SEL, 0, AC_VERB_SET_CONNECT_SEL,
spec->input_mux->items[0].index); spec->input_mux->items[0].index);
...@@ -13717,8 +13868,6 @@ static int alc269_parse_auto_config(struct hda_codec *codec) ...@@ -13717,8 +13868,6 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
if (!spec->cap_mixer && !spec->no_analog) if (!spec->cap_mixer && !spec->no_analog)
set_capture_mixer(codec); set_capture_mixer(codec);
alc_ssid_check(codec, 0x15, 0x1b, 0x14);
return 1; return 1;
} }
...@@ -13744,8 +13893,8 @@ static void alc269_auto_init(struct hda_codec *codec) ...@@ -13744,8 +13893,8 @@ static void alc269_auto_init(struct hda_codec *codec)
static const char *alc269_models[ALC269_MODEL_LAST] = { static const char *alc269_models[ALC269_MODEL_LAST] = {
[ALC269_BASIC] = "basic", [ALC269_BASIC] = "basic",
[ALC269_QUANTA_FL1] = "quanta", [ALC269_QUANTA_FL1] = "quanta",
[ALC269_ASUS_AMIC] = "asus-amic", [ALC269_AMIC] = "laptop-amic",
[ALC269_ASUS_DMIC] = "asus-dmic", [ALC269_DMIC] = "laptop-dmic",
[ALC269_FUJITSU] = "fujitsu", [ALC269_FUJITSU] = "fujitsu",
[ALC269_LIFEBOOK] = "lifebook", [ALC269_LIFEBOOK] = "lifebook",
[ALC269_AUTO] = "auto", [ALC269_AUTO] = "auto",
...@@ -13754,43 +13903,57 @@ static const char *alc269_models[ALC269_MODEL_LAST] = { ...@@ -13754,43 +13903,57 @@ static const char *alc269_models[ALC269_MODEL_LAST] = {
static struct snd_pci_quirk alc269_cfg_tbl[] = { static struct snd_pci_quirk alc269_cfg_tbl[] = {
SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_QUANTA_FL1), SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_QUANTA_FL1),
SND_PCI_QUIRK(0x1043, 0x8330, "ASUS Eeepc P703 P900A", SND_PCI_QUIRK(0x1043, 0x8330, "ASUS Eeepc P703 P900A",
ALC269_ASUS_AMIC), ALC269_AMIC),
SND_PCI_QUIRK(0x1043, 0x1133, "ASUS UJ20ft", ALC269_ASUS_AMIC), SND_PCI_QUIRK(0x1043, 0x1013, "ASUS N61Da", ALC269VB_AMIC),
SND_PCI_QUIRK(0x1043, 0x1273, "ASUS UL80JT", ALC269_ASUS_AMIC), SND_PCI_QUIRK(0x1043, 0x1113, "ASUS N63Jn", ALC269VB_AMIC),
SND_PCI_QUIRK(0x1043, 0x1283, "ASUS U53Jc", ALC269_ASUS_AMIC), SND_PCI_QUIRK(0x1043, 0x1143, "ASUS B53f", ALC269VB_AMIC),
SND_PCI_QUIRK(0x1043, 0x12b3, "ASUS N82Jv", ALC269_ASUS_AMIC), SND_PCI_QUIRK(0x1043, 0x1133, "ASUS UJ20ft", ALC269_AMIC),
SND_PCI_QUIRK(0x1043, 0x13a3, "ASUS UL30Vt", ALC269_ASUS_AMIC), SND_PCI_QUIRK(0x1043, 0x1183, "ASUS K72DR", ALC269VB_AMIC),
SND_PCI_QUIRK(0x1043, 0x1373, "ASUS G73JX", ALC269_ASUS_AMIC), SND_PCI_QUIRK(0x1043, 0x11b3, "ASUS K52DR", ALC269VB_AMIC),
SND_PCI_QUIRK(0x1043, 0x1383, "ASUS UJ30Jc", ALC269_ASUS_AMIC), SND_PCI_QUIRK(0x1043, 0x11e3, "ASUS U33Jc", ALC269VB_AMIC),
SND_PCI_QUIRK(0x1043, 0x13d3, "ASUS N61JA", ALC269_ASUS_AMIC), SND_PCI_QUIRK(0x1043, 0x1273, "ASUS UL80Jt", ALC269VB_AMIC),
SND_PCI_QUIRK(0x1043, 0x1413, "ASUS UL50", ALC269_ASUS_AMIC), SND_PCI_QUIRK(0x1043, 0x1283, "ASUS U53Jc", ALC269_AMIC),
SND_PCI_QUIRK(0x1043, 0x1443, "ASUS UL30", ALC269_ASUS_AMIC), SND_PCI_QUIRK(0x1043, 0x12b3, "ASUS N82Jv", ALC269_AMIC),
SND_PCI_QUIRK(0x1043, 0x1453, "ASUS M60Jv", ALC269_ASUS_AMIC), SND_PCI_QUIRK(0x1043, 0x12d3, "ASUS N61Jv", ALC269_AMIC),
SND_PCI_QUIRK(0x1043, 0x1483, "ASUS UL80", ALC269_ASUS_AMIC), SND_PCI_QUIRK(0x1043, 0x13a3, "ASUS UL30Vt", ALC269_AMIC),
SND_PCI_QUIRK(0x1043, 0x14f3, "ASUS F83Vf", ALC269_ASUS_AMIC), SND_PCI_QUIRK(0x1043, 0x1373, "ASUS G73JX", ALC269_AMIC),
SND_PCI_QUIRK(0x1043, 0x14e3, "ASUS UL20", ALC269_ASUS_AMIC), SND_PCI_QUIRK(0x1043, 0x1383, "ASUS UJ30Jc", ALC269_AMIC),
SND_PCI_QUIRK(0x1043, 0x1513, "ASUS UX30", ALC269_ASUS_AMIC), SND_PCI_QUIRK(0x1043, 0x13d3, "ASUS N61JA", ALC269_AMIC),
SND_PCI_QUIRK(0x1043, 0x15a3, "ASUS N60Jv", ALC269_ASUS_AMIC), SND_PCI_QUIRK(0x1043, 0x1413, "ASUS UL50", ALC269_AMIC),
SND_PCI_QUIRK(0x1043, 0x15b3, "ASUS N60Dp", ALC269_ASUS_AMIC), SND_PCI_QUIRK(0x1043, 0x1443, "ASUS UL30", ALC269_AMIC),
SND_PCI_QUIRK(0x1043, 0x15c3, "ASUS N70De", ALC269_ASUS_AMIC), SND_PCI_QUIRK(0x1043, 0x1453, "ASUS M60Jv", ALC269_AMIC),
SND_PCI_QUIRK(0x1043, 0x15e3, "ASUS F83T", ALC269_ASUS_AMIC), SND_PCI_QUIRK(0x1043, 0x1483, "ASUS UL80", ALC269_AMIC),
SND_PCI_QUIRK(0x1043, 0x1643, "ASUS M60J", ALC269_ASUS_AMIC), SND_PCI_QUIRK(0x1043, 0x14f3, "ASUS F83Vf", ALC269_AMIC),
SND_PCI_QUIRK(0x1043, 0x1653, "ASUS U50", ALC269_ASUS_AMIC), SND_PCI_QUIRK(0x1043, 0x14e3, "ASUS UL20", ALC269_AMIC),
SND_PCI_QUIRK(0x1043, 0x1693, "ASUS F50N", ALC269_ASUS_AMIC), SND_PCI_QUIRK(0x1043, 0x1513, "ASUS UX30", ALC269_AMIC),
SND_PCI_QUIRK(0x1043, 0x16a3, "ASUS F5Q", ALC269_ASUS_AMIC), SND_PCI_QUIRK(0x1043, 0x1593, "ASUS N51Vn", ALC269_AMIC),
SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_ASUS_DMIC), SND_PCI_QUIRK(0x1043, 0x15a3, "ASUS N60Jv", ALC269_AMIC),
SND_PCI_QUIRK(0x1043, 0x1723, "ASUS P80", ALC269_ASUS_AMIC), SND_PCI_QUIRK(0x1043, 0x15b3, "ASUS N60Dp", ALC269_AMIC),
SND_PCI_QUIRK(0x1043, 0x1743, "ASUS U80", ALC269_ASUS_AMIC), SND_PCI_QUIRK(0x1043, 0x15c3, "ASUS N70De", ALC269_AMIC),
SND_PCI_QUIRK(0x1043, 0x1773, "ASUS U20A", ALC269_ASUS_AMIC), SND_PCI_QUIRK(0x1043, 0x15e3, "ASUS F83T", ALC269_AMIC),
SND_PCI_QUIRK(0x1043, 0x1883, "ASUS F81Se", ALC269_ASUS_AMIC), SND_PCI_QUIRK(0x1043, 0x1643, "ASUS M60J", ALC269_AMIC),
SND_PCI_QUIRK(0x1043, 0x1653, "ASUS U50", ALC269_AMIC),
SND_PCI_QUIRK(0x1043, 0x1693, "ASUS F50N", ALC269_AMIC),
SND_PCI_QUIRK(0x1043, 0x16a3, "ASUS F5Q", ALC269_AMIC),
SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_DMIC),
SND_PCI_QUIRK(0x1043, 0x1723, "ASUS P80", ALC269_AMIC),
SND_PCI_QUIRK(0x1043, 0x1743, "ASUS U80", ALC269_AMIC),
SND_PCI_QUIRK(0x1043, 0x1773, "ASUS U20A", ALC269_AMIC),
SND_PCI_QUIRK(0x1043, 0x1883, "ASUS F81Se", ALC269_AMIC),
SND_PCI_QUIRK(0x1043, 0x831a, "ASUS Eeepc P901", SND_PCI_QUIRK(0x1043, 0x831a, "ASUS Eeepc P901",
ALC269_ASUS_DMIC), ALC269_DMIC),
SND_PCI_QUIRK(0x1043, 0x834a, "ASUS Eeepc S101", SND_PCI_QUIRK(0x1043, 0x834a, "ASUS Eeepc S101",
ALC269_ASUS_DMIC), ALC269_DMIC),
SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005HA", ALC269_ASUS_DMIC), SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005HA", ALC269_DMIC),
SND_PCI_QUIRK(0x1043, 0x83ce, "ASUS P1005HA", ALC269_ASUS_DMIC), SND_PCI_QUIRK(0x1043, 0x83ce, "ASUS P1005HA", ALC269_DMIC),
SND_PCI_QUIRK(0x1734, 0x115d, "FSC Amilo", ALC269_FUJITSU), SND_PCI_QUIRK(0x104d, 0x9071, "SONY XTB", ALC269_DMIC),
SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook ICH9M-based", ALC269_LIFEBOOK), SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook ICH9M-based", ALC269_LIFEBOOK),
SND_PCI_QUIRK(0x152d, 0x1778, "Quanta ON1", ALC269_DMIC),
SND_PCI_QUIRK(0x1734, 0x115d, "FSC Amilo", ALC269_FUJITSU),
SND_PCI_QUIRK(0x17aa, 0x3be9, "Quanta Wistron", ALC269_AMIC),
SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_AMIC),
SND_PCI_QUIRK(0x17ff, 0x059a, "Quanta EL3", ALC269_DMIC),
SND_PCI_QUIRK(0x17ff, 0x059b, "Quanta JR1", ALC269_DMIC),
{} {}
}; };
...@@ -13818,47 +13981,75 @@ static struct alc_config_preset alc269_presets[] = { ...@@ -13818,47 +13981,75 @@ static struct alc_config_preset alc269_presets[] = {
.setup = alc269_quanta_fl1_setup, .setup = alc269_quanta_fl1_setup,
.init_hook = alc269_quanta_fl1_init_hook, .init_hook = alc269_quanta_fl1_init_hook,
}, },
[ALC269_ASUS_AMIC] = { [ALC269_AMIC] = {
.mixers = { alc269_eeepc_mixer }, .mixers = { alc269_laptop_mixer },
.cap_mixer = alc269_epc_capture_mixer, .cap_mixer = alc269_laptop_analog_capture_mixer,
.init_verbs = { alc269_init_verbs, .init_verbs = { alc269_init_verbs,
alc269_eeepc_amic_init_verbs }, alc269_laptop_amic_init_verbs },
.num_dacs = ARRAY_SIZE(alc269_dac_nids), .num_dacs = ARRAY_SIZE(alc269_dac_nids),
.dac_nids = alc269_dac_nids, .dac_nids = alc269_dac_nids,
.hp_nid = 0x03, .hp_nid = 0x03,
.num_channel_mode = ARRAY_SIZE(alc269_modes), .num_channel_mode = ARRAY_SIZE(alc269_modes),
.channel_mode = alc269_modes, .channel_mode = alc269_modes,
.unsol_event = alc269_eeepc_unsol_event, .unsol_event = alc269_laptop_unsol_event,
.setup = alc269_eeepc_amic_setup, .setup = alc269_laptop_amic_setup,
.init_hook = alc269_eeepc_inithook, .init_hook = alc269_laptop_inithook,
}, },
[ALC269_ASUS_DMIC] = { [ALC269_DMIC] = {
.mixers = { alc269_eeepc_mixer }, .mixers = { alc269_laptop_mixer },
.cap_mixer = alc269_epc_capture_mixer, .cap_mixer = alc269_laptop_digital_capture_mixer,
.init_verbs = { alc269_init_verbs, .init_verbs = { alc269_init_verbs,
alc269_eeepc_dmic_init_verbs }, alc269_laptop_dmic_init_verbs },
.num_dacs = ARRAY_SIZE(alc269_dac_nids), .num_dacs = ARRAY_SIZE(alc269_dac_nids),
.dac_nids = alc269_dac_nids, .dac_nids = alc269_dac_nids,
.hp_nid = 0x03, .hp_nid = 0x03,
.num_channel_mode = ARRAY_SIZE(alc269_modes), .num_channel_mode = ARRAY_SIZE(alc269_modes),
.channel_mode = alc269_modes, .channel_mode = alc269_modes,
.unsol_event = alc269_eeepc_unsol_event, .unsol_event = alc269_laptop_unsol_event,
.setup = alc269_eeepc_dmic_setup, .setup = alc269_laptop_dmic_setup,
.init_hook = alc269_eeepc_inithook, .init_hook = alc269_laptop_inithook,
},
[ALC269VB_AMIC] = {
.mixers = { alc269vb_laptop_mixer },
.cap_mixer = alc269vb_laptop_analog_capture_mixer,
.init_verbs = { alc269vb_init_verbs,
alc269vb_laptop_amic_init_verbs },
.num_dacs = ARRAY_SIZE(alc269_dac_nids),
.dac_nids = alc269_dac_nids,
.hp_nid = 0x03,
.num_channel_mode = ARRAY_SIZE(alc269_modes),
.channel_mode = alc269_modes,
.unsol_event = alc269_laptop_unsol_event,
.setup = alc269_laptop_amic_setup,
.init_hook = alc269_laptop_inithook,
},
[ALC269VB_DMIC] = {
.mixers = { alc269vb_laptop_mixer },
.cap_mixer = alc269vb_laptop_digital_capture_mixer,
.init_verbs = { alc269vb_init_verbs,
alc269vb_laptop_dmic_init_verbs },
.num_dacs = ARRAY_SIZE(alc269_dac_nids),
.dac_nids = alc269_dac_nids,
.hp_nid = 0x03,
.num_channel_mode = ARRAY_SIZE(alc269_modes),
.channel_mode = alc269_modes,
.unsol_event = alc269_laptop_unsol_event,
.setup = alc269vb_laptop_dmic_setup,
.init_hook = alc269_laptop_inithook,
}, },
[ALC269_FUJITSU] = { [ALC269_FUJITSU] = {
.mixers = { alc269_fujitsu_mixer }, .mixers = { alc269_fujitsu_mixer },
.cap_mixer = alc269_epc_capture_mixer, .cap_mixer = alc269_laptop_digital_capture_mixer,
.init_verbs = { alc269_init_verbs, .init_verbs = { alc269_init_verbs,
alc269_eeepc_dmic_init_verbs }, alc269_laptop_dmic_init_verbs },
.num_dacs = ARRAY_SIZE(alc269_dac_nids), .num_dacs = ARRAY_SIZE(alc269_dac_nids),
.dac_nids = alc269_dac_nids, .dac_nids = alc269_dac_nids,
.hp_nid = 0x03, .hp_nid = 0x03,
.num_channel_mode = ARRAY_SIZE(alc269_modes), .num_channel_mode = ARRAY_SIZE(alc269_modes),
.channel_mode = alc269_modes, .channel_mode = alc269_modes,
.unsol_event = alc269_eeepc_unsol_event, .unsol_event = alc269_laptop_unsol_event,
.setup = alc269_eeepc_dmic_setup, .setup = alc269_laptop_dmic_setup,
.init_hook = alc269_eeepc_inithook, .init_hook = alc269_laptop_inithook,
}, },
[ALC269_LIFEBOOK] = { [ALC269_LIFEBOOK] = {
.mixers = { alc269_lifebook_mixer }, .mixers = { alc269_lifebook_mixer },
...@@ -13879,6 +14070,7 @@ static int patch_alc269(struct hda_codec *codec) ...@@ -13879,6 +14070,7 @@ static int patch_alc269(struct hda_codec *codec)
struct alc_spec *spec; struct alc_spec *spec;
int board_config; int board_config;
int err; int err;
int is_alc269vb = 0;
spec = kzalloc(sizeof(*spec), GFP_KERNEL); spec = kzalloc(sizeof(*spec), GFP_KERNEL);
if (spec == NULL) if (spec == NULL)
...@@ -13895,6 +14087,7 @@ static int patch_alc269(struct hda_codec *codec) ...@@ -13895,6 +14087,7 @@ static int patch_alc269(struct hda_codec *codec)
alc_free(codec); alc_free(codec);
return -ENOMEM; return -ENOMEM;
} }
is_alc269vb = 1;
} }
board_config = snd_hda_check_board_config(codec, ALC269_MODEL_LAST, board_config = snd_hda_check_board_config(codec, ALC269_MODEL_LAST,
...@@ -13930,7 +14123,7 @@ static int patch_alc269(struct hda_codec *codec) ...@@ -13930,7 +14123,7 @@ static int patch_alc269(struct hda_codec *codec)
if (board_config != ALC269_AUTO) if (board_config != ALC269_AUTO)
setup_preset(codec, &alc269_presets[board_config]); setup_preset(codec, &alc269_presets[board_config]);
if (codec->subsystem_id == 0x17aa3bf8) { if (board_config == ALC269_QUANTA_FL1) {
/* Due to a hardware problem on Lenovo Ideadpad, we need to /* Due to a hardware problem on Lenovo Ideadpad, we need to
* fix the sample rate of analog I/O to 44.1kHz * fix the sample rate of analog I/O to 44.1kHz
*/ */
...@@ -13943,9 +14136,16 @@ static int patch_alc269(struct hda_codec *codec) ...@@ -13943,9 +14136,16 @@ static int patch_alc269(struct hda_codec *codec)
spec->stream_digital_playback = &alc269_pcm_digital_playback; spec->stream_digital_playback = &alc269_pcm_digital_playback;
spec->stream_digital_capture = &alc269_pcm_digital_capture; spec->stream_digital_capture = &alc269_pcm_digital_capture;
if (!is_alc269vb) {
spec->adc_nids = alc269_adc_nids; spec->adc_nids = alc269_adc_nids;
spec->num_adc_nids = ARRAY_SIZE(alc269_adc_nids); spec->num_adc_nids = ARRAY_SIZE(alc269_adc_nids);
spec->capsrc_nids = alc269_capsrc_nids; spec->capsrc_nids = alc269_capsrc_nids;
} else {
spec->adc_nids = alc269vb_adc_nids;
spec->num_adc_nids = ARRAY_SIZE(alc269vb_adc_nids);
spec->capsrc_nids = alc269vb_capsrc_nids;
}
if (!spec->cap_mixer) if (!spec->cap_mixer)
set_capture_mixer(codec); set_capture_mixer(codec);
set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT); set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
...@@ -13959,7 +14159,6 @@ static int patch_alc269(struct hda_codec *codec) ...@@ -13959,7 +14159,6 @@ static int patch_alc269(struct hda_codec *codec)
if (!spec->loopback.amplist) if (!spec->loopback.amplist)
spec->loopback.amplist = alc269_loopbacks; spec->loopback.amplist = alc269_loopbacks;
#endif #endif
codec->proc_widget_hook = print_realtek_coef;
return 0; return 0;
} }
...@@ -14822,7 +15021,7 @@ static int alc861_parse_auto_config(struct hda_codec *codec) ...@@ -14822,7 +15021,7 @@ static int alc861_parse_auto_config(struct hda_codec *codec)
spec->num_adc_nids = ARRAY_SIZE(alc861_adc_nids); spec->num_adc_nids = ARRAY_SIZE(alc861_adc_nids);
set_capture_mixer(codec); set_capture_mixer(codec);
alc_ssid_check(codec, 0x0e, 0x0f, 0x0b); alc_ssid_check(codec, 0x0e, 0x0f, 0x0b, 0);
return 1; return 1;
} }
...@@ -15087,7 +15286,6 @@ static int patch_alc861(struct hda_codec *codec) ...@@ -15087,7 +15286,6 @@ static int patch_alc861(struct hda_codec *codec)
if (!spec->loopback.amplist) if (!spec->loopback.amplist)
spec->loopback.amplist = alc861_loopbacks; spec->loopback.amplist = alc861_loopbacks;
#endif #endif
codec->proc_widget_hook = print_realtek_coef;
return 0; return 0;
} }
...@@ -15714,7 +15912,7 @@ static struct alc_config_preset alc861vd_presets[] = { ...@@ -15714,7 +15912,7 @@ static struct alc_config_preset alc861vd_presets[] = {
static int alc861vd_auto_create_input_ctls(struct hda_codec *codec, static int alc861vd_auto_create_input_ctls(struct hda_codec *codec,
const struct auto_pin_cfg *cfg) const struct auto_pin_cfg *cfg)
{ {
return alc_auto_create_input_ctls(codec, cfg, 0x15, 0x22, 0); return alc_auto_create_input_ctls(codec, cfg, 0x15, 0x09, 0);
} }
...@@ -15950,7 +16148,7 @@ static int alc861vd_parse_auto_config(struct hda_codec *codec) ...@@ -15950,7 +16148,7 @@ static int alc861vd_parse_auto_config(struct hda_codec *codec)
if (err < 0) if (err < 0)
return err; return err;
alc_ssid_check(codec, 0x15, 0x1b, 0x14); alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
return 1; return 1;
} }
...@@ -16067,7 +16265,6 @@ static int patch_alc861vd(struct hda_codec *codec) ...@@ -16067,7 +16265,6 @@ static int patch_alc861vd(struct hda_codec *codec)
if (!spec->loopback.amplist) if (!spec->loopback.amplist)
spec->loopback.amplist = alc861vd_loopbacks; spec->loopback.amplist = alc861vd_loopbacks;
#endif #endif
codec->proc_widget_hook = print_realtek_coef;
return 0; return 0;
} }
...@@ -16534,13 +16731,6 @@ static struct hda_verb alc662_init_verbs[] = { ...@@ -16534,13 +16731,6 @@ static struct hda_verb alc662_init_verbs[] = {
/* ADC: mute amp left and right */ /* ADC: mute amp left and right */
{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
{0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
/* Front mixer: unmute input/output amp left and right (volume = 0) */
{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
...@@ -16590,6 +16780,28 @@ static struct hda_verb alc662_init_verbs[] = { ...@@ -16590,6 +16780,28 @@ static struct hda_verb alc662_init_verbs[] = {
{ } { }
}; };
static struct hda_verb alc663_init_verbs[] = {
{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
{0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
{ }
};
static struct hda_verb alc272_init_verbs[] = {
{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
{0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
{ }
};
static struct hda_verb alc662_sue_init_verbs[] = { static struct hda_verb alc662_sue_init_verbs[] = {
{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_FRONT_EVENT}, {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_FRONT_EVENT},
{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_HP_EVENT}, {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_HP_EVENT},
...@@ -16609,61 +16821,6 @@ static struct hda_verb alc662_eeepc_ep20_sue_init_verbs[] = { ...@@ -16609,61 +16821,6 @@ static struct hda_verb alc662_eeepc_ep20_sue_init_verbs[] = {
{} {}
}; };
/*
* generic initialization of ADC, input mixers and output mixers
*/
static struct hda_verb alc662_auto_init_verbs[] = {
/*
* Unmute ADC and set the default input to mic-in
*/
{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
/* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
* mixer widget
* Note: PASD motherboards uses the Line In 2 as the input for front
* panel mic (mic 2)
*/
/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
/*
* Set up output mixers (0x0c - 0x0f)
*/
/* set vol=0 to output mixers */
{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
/* set up input amps for analog loopback */
/* Amp Indices: DAC = 0, mixer = 1 */
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
/* FIXME: use matrix-type input source selection */
/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
/* Input mixer */
{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{ }
};
/* additional verbs for ALC663 */
static struct hda_verb alc663_auto_init_verbs[] = {
{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
{ }
};
static struct hda_verb alc663_m51va_init_verbs[] = { static struct hda_verb alc663_m51va_init_verbs[] = {
{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
...@@ -17414,6 +17571,7 @@ static struct snd_pci_quirk alc662_cfg_tbl[] = { ...@@ -17414,6 +17571,7 @@ static struct snd_pci_quirk alc662_cfg_tbl[] = {
SND_PCI_QUIRK(0x1028, 0x02f4, "DELL ZM1", ALC272_DELL_ZM1), SND_PCI_QUIRK(0x1028, 0x02f4, "DELL ZM1", ALC272_DELL_ZM1),
SND_PCI_QUIRK(0x1043, 0x1000, "ASUS N50Vm", ALC663_ASUS_MODE1), SND_PCI_QUIRK(0x1043, 0x1000, "ASUS N50Vm", ALC663_ASUS_MODE1),
SND_PCI_QUIRK(0x1043, 0x1092, "ASUS NB", ALC663_ASUS_MODE3), SND_PCI_QUIRK(0x1043, 0x1092, "ASUS NB", ALC663_ASUS_MODE3),
SND_PCI_QUIRK(0x1043, 0x1173, "ASUS K73Jn", ALC663_ASUS_MODE1),
SND_PCI_QUIRK(0x1043, 0x11c3, "ASUS M70V", ALC663_ASUS_MODE3), SND_PCI_QUIRK(0x1043, 0x11c3, "ASUS M70V", ALC663_ASUS_MODE3),
SND_PCI_QUIRK(0x1043, 0x11d3, "ASUS NB", ALC663_ASUS_MODE1), SND_PCI_QUIRK(0x1043, 0x11d3, "ASUS NB", ALC663_ASUS_MODE1),
SND_PCI_QUIRK(0x1043, 0x11f3, "ASUS NB", ALC662_ASUS_MODE2), SND_PCI_QUIRK(0x1043, 0x11f3, "ASUS NB", ALC662_ASUS_MODE2),
...@@ -17449,6 +17607,7 @@ static struct snd_pci_quirk alc662_cfg_tbl[] = { ...@@ -17449,6 +17607,7 @@ static struct snd_pci_quirk alc662_cfg_tbl[] = {
SND_PCI_QUIRK(0x1043, 0x1893, "ASUS M50Vm", ALC663_ASUS_MODE3), SND_PCI_QUIRK(0x1043, 0x1893, "ASUS M50Vm", ALC663_ASUS_MODE3),
SND_PCI_QUIRK(0x1043, 0x1894, "ASUS X55", ALC663_ASUS_MODE3), SND_PCI_QUIRK(0x1043, 0x1894, "ASUS X55", ALC663_ASUS_MODE3),
SND_PCI_QUIRK(0x1043, 0x18b3, "ASUS N80Vc", ALC663_ASUS_MODE1), SND_PCI_QUIRK(0x1043, 0x18b3, "ASUS N80Vc", ALC663_ASUS_MODE1),
SND_PCI_QUIRK(0x1043, 0x18c3, "ASUS VX5", ALC663_ASUS_MODE1),
SND_PCI_QUIRK(0x1043, 0x18d3, "ASUS N81Te", ALC663_ASUS_MODE1), SND_PCI_QUIRK(0x1043, 0x18d3, "ASUS N81Te", ALC663_ASUS_MODE1),
SND_PCI_QUIRK(0x1043, 0x18f3, "ASUS N505Tp", ALC663_ASUS_MODE1), SND_PCI_QUIRK(0x1043, 0x18f3, "ASUS N505Tp", ALC663_ASUS_MODE1),
SND_PCI_QUIRK(0x1043, 0x1903, "ASUS F5GL", ALC663_ASUS_MODE1), SND_PCI_QUIRK(0x1043, 0x1903, "ASUS F5GL", ALC663_ASUS_MODE1),
...@@ -17476,6 +17635,7 @@ static struct snd_pci_quirk alc662_cfg_tbl[] = { ...@@ -17476,6 +17635,7 @@ static struct snd_pci_quirk alc662_cfg_tbl[] = {
SND_PCI_QUIRK(0x144d, 0xca00, "Samsung NC10", ALC272_SAMSUNG_NC10), SND_PCI_QUIRK(0x144d, 0xca00, "Samsung NC10", ALC272_SAMSUNG_NC10),
SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte 945GCM-S2L", SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte 945GCM-S2L",
ALC662_3ST_6ch_DIG), ALC662_3ST_6ch_DIG),
SND_PCI_QUIRK(0x152d, 0x2304, "Quanta WH1", ALC663_ASUS_H13),
SND_PCI_QUIRK(0x1565, 0x820f, "Biostar TA780G M2+", ALC662_3ST_6ch_DIG), SND_PCI_QUIRK(0x1565, 0x820f, "Biostar TA780G M2+", ALC662_3ST_6ch_DIG),
SND_PCI_QUIRK(0x1631, 0xc10c, "PB RS65", ALC663_ASUS_M51VA), SND_PCI_QUIRK(0x1631, 0xc10c, "PB RS65", ALC663_ASUS_M51VA),
SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo", ALC662_LENOVO_101E), SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo", ALC662_LENOVO_101E),
...@@ -18094,15 +18254,23 @@ static int alc662_parse_auto_config(struct hda_codec *codec) ...@@ -18094,15 +18254,23 @@ static int alc662_parse_auto_config(struct hda_codec *codec)
spec->num_mux_defs = 1; spec->num_mux_defs = 1;
spec->input_mux = &spec->private_imux[0]; spec->input_mux = &spec->private_imux[0];
add_verb(spec, alc662_auto_init_verbs); add_verb(spec, alc662_init_verbs);
if (codec->vendor_id == 0x10ec0663) if (codec->vendor_id == 0x10ec0272 || codec->vendor_id == 0x10ec0663 ||
add_verb(spec, alc663_auto_init_verbs); codec->vendor_id == 0x10ec0665)
add_verb(spec, alc663_init_verbs);
if (codec->vendor_id == 0x10ec0272)
add_verb(spec, alc272_init_verbs);
err = alc_auto_add_mic_boost(codec); err = alc_auto_add_mic_boost(codec);
if (err < 0) if (err < 0)
return err; return err;
alc_ssid_check(codec, 0x15, 0x1b, 0x14); if (codec->vendor_id == 0x10ec0272 || codec->vendor_id == 0x10ec0663 ||
codec->vendor_id == 0x10ec0665 || codec->vendor_id == 0x10ec0670)
alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0x21);
else
alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
return 1; return 1;
} }
...@@ -18188,11 +18356,20 @@ static int patch_alc662(struct hda_codec *codec) ...@@ -18188,11 +18356,20 @@ static int patch_alc662(struct hda_codec *codec)
if (!spec->cap_mixer) if (!spec->cap_mixer)
set_capture_mixer(codec); set_capture_mixer(codec);
if (codec->vendor_id == 0x10ec0662)
switch (codec->vendor_id) {
case 0x10ec0662:
set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
else break;
case 0x10ec0272:
case 0x10ec0663:
case 0x10ec0665:
set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT); set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
break;
case 0x10ec0273:
set_beep_amp(spec, 0x0b, 0x03, HDA_INPUT);
break;
}
spec->vmaster_nid = 0x02; spec->vmaster_nid = 0x02;
codec->patch_ops = alc_patch_ops; codec->patch_ops = alc_patch_ops;
...@@ -18202,7 +18379,6 @@ static int patch_alc662(struct hda_codec *codec) ...@@ -18202,7 +18379,6 @@ static int patch_alc662(struct hda_codec *codec)
if (!spec->loopback.amplist) if (!spec->loopback.amplist)
spec->loopback.amplist = alc662_loopbacks; spec->loopback.amplist = alc662_loopbacks;
#endif #endif
codec->proc_widget_hook = print_realtek_coef;
return 0; return 0;
} }
...@@ -18243,6 +18419,8 @@ static struct hda_codec_preset snd_hda_preset_realtek[] = { ...@@ -18243,6 +18419,8 @@ static struct hda_codec_preset snd_hda_preset_realtek[] = {
{ .id = 0x10ec0662, .rev = 0x100101, .name = "ALC662 rev1", { .id = 0x10ec0662, .rev = 0x100101, .name = "ALC662 rev1",
.patch = patch_alc662 }, .patch = patch_alc662 },
{ .id = 0x10ec0663, .name = "ALC663", .patch = patch_alc662 }, { .id = 0x10ec0663, .name = "ALC663", .patch = patch_alc662 },
{ .id = 0x10ec0665, .name = "ALC665", .patch = patch_alc662 },
{ .id = 0x10ec0670, .name = "ALC670", .patch = patch_alc662 },
{ .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 }, { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
{ .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 }, { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 },
{ .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc882 }, { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc882 },
......
...@@ -568,6 +568,11 @@ static hda_nid_t stac92hd83xxx_pin_nids[10] = { ...@@ -568,6 +568,11 @@ static hda_nid_t stac92hd83xxx_pin_nids[10] = {
0x0f, 0x10, 0x11, 0x1f, 0x20, 0x0f, 0x10, 0x11, 0x1f, 0x20,
}; };
static hda_nid_t stac92hd88xxx_pin_nids[10] = {
0x0a, 0x0b, 0x0c, 0x0d,
0x0f, 0x11, 0x1f, 0x20,
};
#define STAC92HD71BXX_NUM_PINS 13 #define STAC92HD71BXX_NUM_PINS 13
static hda_nid_t stac92hd71bxx_pin_nids_4port[STAC92HD71BXX_NUM_PINS] = { static hda_nid_t stac92hd71bxx_pin_nids_4port[STAC92HD71BXX_NUM_PINS] = {
0x0a, 0x0b, 0x0c, 0x0d, 0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x00,
...@@ -2873,6 +2878,13 @@ static hda_nid_t get_unassigned_dac(struct hda_codec *codec, hda_nid_t nid) ...@@ -2873,6 +2878,13 @@ static hda_nid_t get_unassigned_dac(struct hda_codec *codec, hda_nid_t nid)
conn_len = snd_hda_get_connections(codec, nid, conn, conn_len = snd_hda_get_connections(codec, nid, conn,
HDA_MAX_CONNECTIONS); HDA_MAX_CONNECTIONS);
/* 92HD88: trace back up the link of nids to find the DAC */
while (conn_len == 1 && (get_wcaps_type(get_wcaps(codec, conn[0]))
!= AC_WID_AUD_OUT)) {
nid = conn[0];
conn_len = snd_hda_get_connections(codec, nid, conn,
HDA_MAX_CONNECTIONS);
}
for (j = 0; j < conn_len; j++) { for (j = 0; j < conn_len; j++) {
wcaps = get_wcaps(codec, conn[j]); wcaps = get_wcaps(codec, conn[j]);
wtype = get_wcaps_type(wcaps); wtype = get_wcaps_type(wcaps);
...@@ -4351,6 +4363,12 @@ static int stac92xx_init(struct hda_codec *codec) ...@@ -4351,6 +4363,12 @@ static int stac92xx_init(struct hda_codec *codec)
if (enable_pin_detect(codec, nid, STAC_PWR_EVENT)) if (enable_pin_detect(codec, nid, STAC_PWR_EVENT))
stac_issue_unsol_event(codec, nid); stac_issue_unsol_event(codec, nid);
} }
#ifdef CONFIG_SND_HDA_POWER_SAVE
/* sync mute LED */
if (spec->gpio_led && codec->patch_ops.check_power_status)
codec->patch_ops.check_power_status(codec, 0x01);
#endif
if (spec->dac_list) if (spec->dac_list)
stac92xx_power_down(codec); stac92xx_power_down(codec);
return 0; return 0;
...@@ -4742,19 +4760,14 @@ static int hp_blike_system(u32 subsystem_id); ...@@ -4742,19 +4760,14 @@ static int hp_blike_system(u32 subsystem_id);
static void set_hp_led_gpio(struct hda_codec *codec) static void set_hp_led_gpio(struct hda_codec *codec)
{ {
struct sigmatel_spec *spec = codec->spec; struct sigmatel_spec *spec = codec->spec;
switch (codec->vendor_id) { unsigned int gpio;
case 0x111d7608:
/* GPIO 0 */ gpio = snd_hda_param_read(codec, codec->afg, AC_PAR_GPIO_CAP);
spec->gpio_led = 0x01; gpio &= AC_GPIO_IO_COUNT;
break; if (gpio > 3)
case 0x111d7600: spec->gpio_led = 0x08; /* GPIO 3 */
case 0x111d7601: else
case 0x111d7602: spec->gpio_led = 0x01; /* GPIO 0 */
case 0x111d7603:
/* GPIO 3 */
spec->gpio_led = 0x08;
break;
}
} }
/* /*
...@@ -4777,7 +4790,7 @@ static void set_hp_led_gpio(struct hda_codec *codec) ...@@ -4777,7 +4790,7 @@ static void set_hp_led_gpio(struct hda_codec *codec)
* Need more information on whether it is true across the entire series. * Need more information on whether it is true across the entire series.
* -- kunal * -- kunal
*/ */
static int find_mute_led_gpio(struct hda_codec *codec) static int find_mute_led_gpio(struct hda_codec *codec, int default_polarity)
{ {
struct sigmatel_spec *spec = codec->spec; struct sigmatel_spec *spec = codec->spec;
const struct dmi_device *dev = NULL; const struct dmi_device *dev = NULL;
...@@ -4804,7 +4817,7 @@ static int find_mute_led_gpio(struct hda_codec *codec) ...@@ -4804,7 +4817,7 @@ static int find_mute_led_gpio(struct hda_codec *codec)
*/ */
if (!hp_blike_system(codec->subsystem_id)) { if (!hp_blike_system(codec->subsystem_id)) {
set_hp_led_gpio(codec); set_hp_led_gpio(codec);
spec->gpio_led_polarity = 1; spec->gpio_led_polarity = default_polarity;
return 1; return 1;
} }
} }
...@@ -4902,6 +4915,11 @@ static int stac92xx_resume(struct hda_codec *codec) ...@@ -4902,6 +4915,11 @@ static int stac92xx_resume(struct hda_codec *codec)
stac_issue_unsol_event(codec, stac_issue_unsol_event(codec,
spec->autocfg.line_out_pins[0]); spec->autocfg.line_out_pins[0]);
} }
#ifdef CONFIG_SND_HDA_POWER_SAVE
/* sync mute LED */
if (spec->gpio_led && codec->patch_ops.check_power_status)
codec->patch_ops.check_power_status(codec, 0x01);
#endif
return 0; return 0;
} }
...@@ -4921,10 +4939,17 @@ static int stac92xx_hp_check_power_status(struct hda_codec *codec, ...@@ -4921,10 +4939,17 @@ static int stac92xx_hp_check_power_status(struct hda_codec *codec,
hda_nid_t nid) hda_nid_t nid)
{ {
struct sigmatel_spec *spec = codec->spec; struct sigmatel_spec *spec = codec->spec;
int i, muted = 1;
if (nid == 0x10) { for (i = 0; i < spec->multiout.num_dacs; i++) {
if (snd_hda_codec_amp_read(codec, nid, 0, HDA_OUTPUT, 0) & nid = spec->multiout.dac_nids[i];
HDA_AMP_MUTE) if (!(snd_hda_codec_amp_read(codec, nid, 0, HDA_OUTPUT, 0) &
HDA_AMP_MUTE)) {
muted = 0; /* something heard */
break;
}
}
if (muted)
spec->gpio_data &= ~spec->gpio_led; /* orange */ spec->gpio_data &= ~spec->gpio_led; /* orange */
else else
spec->gpio_data |= spec->gpio_led; /* white */ spec->gpio_data |= spec->gpio_led; /* white */
...@@ -4934,30 +4959,9 @@ static int stac92xx_hp_check_power_status(struct hda_codec *codec, ...@@ -4934,30 +4959,9 @@ static int stac92xx_hp_check_power_status(struct hda_codec *codec,
spec->gpio_data ^= spec->gpio_led; spec->gpio_data ^= spec->gpio_led;
} }
stac_gpio_set(codec, spec->gpio_mask,
spec->gpio_dir,
spec->gpio_data);
}
return 0;
}
static int idt92hd83xxx_hp_check_power_status(struct hda_codec *codec,
hda_nid_t nid)
{
struct sigmatel_spec *spec = codec->spec;
if (nid != 0x13)
return 0;
if (snd_hda_codec_amp_read(codec, nid, 0, HDA_OUTPUT, 0) & HDA_AMP_MUTE)
spec->gpio_data |= spec->gpio_led; /* mute LED on */
else
spec->gpio_data &= ~spec->gpio_led; /* mute LED off */
stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir, spec->gpio_data); stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir, spec->gpio_data);
return 0; return 0;
} }
#endif #endif
static int stac92xx_suspend(struct hda_codec *codec, pm_message_t state) static int stac92xx_suspend(struct hda_codec *codec, pm_message_t state)
...@@ -5279,7 +5283,6 @@ static int patch_stac92hd83xxx(struct hda_codec *codec) ...@@ -5279,7 +5283,6 @@ static int patch_stac92hd83xxx(struct hda_codec *codec)
hda_nid_t conn[STAC92HD83_DAC_COUNT + 1]; hda_nid_t conn[STAC92HD83_DAC_COUNT + 1];
int err; int err;
int num_dacs; int num_dacs;
hda_nid_t nid;
spec = kzalloc(sizeof(*spec), GFP_KERNEL); spec = kzalloc(sizeof(*spec), GFP_KERNEL);
if (spec == NULL) if (spec == NULL)
...@@ -5318,7 +5321,18 @@ static int patch_stac92hd83xxx(struct hda_codec *codec) ...@@ -5318,7 +5321,18 @@ static int patch_stac92hd83xxx(struct hda_codec *codec)
stac92hd83xxx_brd_tbl[spec->board_config]); stac92hd83xxx_brd_tbl[spec->board_config]);
switch (codec->vendor_id) { switch (codec->vendor_id) {
case 0x111d7666:
case 0x111d7667:
case 0x111d7668:
case 0x111d7669:
spec->num_pins = ARRAY_SIZE(stac92hd88xxx_pin_nids);
spec->pin_nids = stac92hd88xxx_pin_nids;
spec->mono_nid = 0;
spec->digbeep_nid = 0;
spec->num_pwrs = 0;
break;
case 0x111d7604: case 0x111d7604:
case 0x111d76d4:
case 0x111d7605: case 0x111d7605:
case 0x111d76d5: case 0x111d76d5:
if (spec->board_config == STAC_92HD83XXX_PWR_REF) if (spec->board_config == STAC_92HD83XXX_PWR_REF)
...@@ -5329,8 +5343,10 @@ static int patch_stac92hd83xxx(struct hda_codec *codec) ...@@ -5329,8 +5343,10 @@ static int patch_stac92hd83xxx(struct hda_codec *codec)
codec->patch_ops = stac92xx_patch_ops; codec->patch_ops = stac92xx_patch_ops;
if (spec->board_config == STAC_92HD83XXX_HP) if (find_mute_led_gpio(codec, 0))
spec->gpio_led = 0x01; snd_printd("mute LED gpio %d polarity %d\n",
spec->gpio_led,
spec->gpio_led_polarity);
#ifdef CONFIG_SND_HDA_POWER_SAVE #ifdef CONFIG_SND_HDA_POWER_SAVE
if (spec->gpio_led) { if (spec->gpio_led) {
...@@ -5339,7 +5355,7 @@ static int patch_stac92hd83xxx(struct hda_codec *codec) ...@@ -5339,7 +5355,7 @@ static int patch_stac92hd83xxx(struct hda_codec *codec)
spec->gpio_data |= spec->gpio_led; spec->gpio_data |= spec->gpio_led;
/* register check_power_status callback. */ /* register check_power_status callback. */
codec->patch_ops.check_power_status = codec->patch_ops.check_power_status =
idt92hd83xxx_hp_check_power_status; stac92xx_hp_check_power_status;
} }
#endif #endif
...@@ -5359,24 +5375,21 @@ static int patch_stac92hd83xxx(struct hda_codec *codec) ...@@ -5359,24 +5375,21 @@ static int patch_stac92hd83xxx(struct hda_codec *codec)
return err; return err;
} }
switch (spec->board_config) { /* docking output support */
case STAC_DELL_S14: num_dacs = snd_hda_get_connections(codec, 0xF,
nid = 0xf;
break;
default:
nid = 0xe;
break;
}
num_dacs = snd_hda_get_connections(codec, nid,
conn, STAC92HD83_DAC_COUNT + 1) - 1; conn, STAC92HD83_DAC_COUNT + 1) - 1;
if (num_dacs < 0) /* skip non-DAC connections */
num_dacs = STAC92HD83_DAC_COUNT; while (num_dacs >= 0 &&
(get_wcaps_type(get_wcaps(codec, conn[num_dacs]))
/* set port X to select the last DAC != AC_WID_AUD_OUT))
*/ num_dacs--;
snd_hda_codec_write_cache(codec, nid, 0, /* set port E and F to select the last DAC */
if (num_dacs >= 0) {
snd_hda_codec_write_cache(codec, 0xE, 0,
AC_VERB_SET_CONNECT_SEL, num_dacs);
snd_hda_codec_write_cache(codec, 0xF, 0,
AC_VERB_SET_CONNECT_SEL, num_dacs); AC_VERB_SET_CONNECT_SEL, num_dacs);
}
codec->proc_widget_hook = stac92hd_proc_hook; codec->proc_widget_hook = stac92hd_proc_hook;
...@@ -5657,7 +5670,6 @@ static int patch_stac92hd71bxx(struct hda_codec *codec) ...@@ -5657,7 +5670,6 @@ static int patch_stac92hd71bxx(struct hda_codec *codec)
*/ */
spec->num_smuxes = 1; spec->num_smuxes = 1;
spec->num_dmuxes = 1; spec->num_dmuxes = 1;
spec->gpio_led = 0x01;
/* fallthrough */ /* fallthrough */
case STAC_HP_DV5: case STAC_HP_DV5:
snd_hda_codec_set_pincfg(codec, 0x0d, 0x90170010); snd_hda_codec_set_pincfg(codec, 0x0d, 0x90170010);
...@@ -5672,8 +5684,6 @@ static int patch_stac92hd71bxx(struct hda_codec *codec) ...@@ -5672,8 +5684,6 @@ static int patch_stac92hd71bxx(struct hda_codec *codec)
spec->num_dmics = 1; spec->num_dmics = 1;
spec->num_dmuxes = 1; spec->num_dmuxes = 1;
spec->num_smuxes = 1; spec->num_smuxes = 1;
/* orange/white mute led on GPIO3, orange=0, white=1 */
spec->gpio_led = 0x08;
break; break;
} }
...@@ -5695,7 +5705,7 @@ static int patch_stac92hd71bxx(struct hda_codec *codec) ...@@ -5695,7 +5705,7 @@ static int patch_stac92hd71bxx(struct hda_codec *codec)
} }
} }
if (find_mute_led_gpio(codec)) if (find_mute_led_gpio(codec, 1))
snd_printd("mute LED gpio %d polarity %d\n", snd_printd("mute LED gpio %d polarity %d\n",
spec->gpio_led, spec->gpio_led,
spec->gpio_led_polarity); spec->gpio_led_polarity);
...@@ -6236,8 +6246,13 @@ static struct hda_codec_preset snd_hda_preset_sigmatel[] = { ...@@ -6236,8 +6246,13 @@ static struct hda_codec_preset snd_hda_preset_sigmatel[] = {
{ .id = 0x838476a7, .name = "STAC9254D", .patch = patch_stac9205 }, { .id = 0x838476a7, .name = "STAC9254D", .patch = patch_stac9205 },
{ .id = 0x111d7603, .name = "92HD75B3X5", .patch = patch_stac92hd71bxx}, { .id = 0x111d7603, .name = "92HD75B3X5", .patch = patch_stac92hd71bxx},
{ .id = 0x111d7604, .name = "92HD83C1X5", .patch = patch_stac92hd83xxx}, { .id = 0x111d7604, .name = "92HD83C1X5", .patch = patch_stac92hd83xxx},
{ .id = 0x111d76d4, .name = "92HD83C1C5", .patch = patch_stac92hd83xxx},
{ .id = 0x111d7605, .name = "92HD81B1X5", .patch = patch_stac92hd83xxx}, { .id = 0x111d7605, .name = "92HD81B1X5", .patch = patch_stac92hd83xxx},
{ .id = 0x111d76d5, .name = "92HD81B1C5", .patch = patch_stac92hd83xxx}, { .id = 0x111d76d5, .name = "92HD81B1C5", .patch = patch_stac92hd83xxx},
{ .id = 0x111d7666, .name = "92HD88B3", .patch = patch_stac92hd83xxx},
{ .id = 0x111d7667, .name = "92HD88B1", .patch = patch_stac92hd83xxx},
{ .id = 0x111d7668, .name = "92HD88B2", .patch = patch_stac92hd83xxx},
{ .id = 0x111d7669, .name = "92HD88B4", .patch = patch_stac92hd83xxx},
{ .id = 0x111d7608, .name = "92HD75B2X5", .patch = patch_stac92hd71bxx}, { .id = 0x111d7608, .name = "92HD75B2X5", .patch = patch_stac92hd71bxx},
{ .id = 0x111d7674, .name = "92HD73D1X5", .patch = patch_stac92hd73xx }, { .id = 0x111d7674, .name = "92HD73D1X5", .patch = patch_stac92hd73xx },
{ .id = 0x111d7675, .name = "92HD73C1X5", .patch = patch_stac92hd73xx }, { .id = 0x111d7675, .name = "92HD73C1X5", .patch = patch_stac92hd73xx },
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册