Commit a91a4aa1 authored by Takashi Iwai's avatar Takashi Iwai

Merge branch 'topic/hda' into for-linus

parents 12c2a682 61c2d2b5
...@@ -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),
......
This diff is collapsed.
This diff is collapsed.
...@@ -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%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment