Commit 6eb7365d authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6:
  ALSA: hda - Overwrite pin config on intel DG45ID board.
  intelhdmi - dont power off HDA link
  ALSA: hrtimer - Fix lock-up
  ALSA: intelhdmi - add channel mapping for typical configurations
  ALSA: intelhdmi - channel mapping applies to Pin
  ALSA: intelhdmi - accept DisplayPort pin
  ALSA: hda - show HBR(High Bit Rate) pin cap in procfs
  ALSA: hda - Fix LED GPIO setup for HP laptops with IDT codecs
  ASoC: Fix build of OMAP sound drivers
  ALSA: opti93x: fix irq releasing if the irq cannot be allocated
parents 9c3936cb 84a3bd06
...@@ -37,14 +37,22 @@ static unsigned int resolution; ...@@ -37,14 +37,22 @@ static unsigned int resolution;
struct snd_hrtimer { struct snd_hrtimer {
struct snd_timer *timer; struct snd_timer *timer;
struct hrtimer hrt; struct hrtimer hrt;
atomic_t running;
}; };
static enum hrtimer_restart snd_hrtimer_callback(struct hrtimer *hrt) static enum hrtimer_restart snd_hrtimer_callback(struct hrtimer *hrt)
{ {
struct snd_hrtimer *stime = container_of(hrt, struct snd_hrtimer, hrt); struct snd_hrtimer *stime = container_of(hrt, struct snd_hrtimer, hrt);
struct snd_timer *t = stime->timer; struct snd_timer *t = stime->timer;
if (!atomic_read(&stime->running))
return HRTIMER_NORESTART;
hrtimer_forward_now(hrt, ns_to_ktime(t->sticks * resolution)); hrtimer_forward_now(hrt, ns_to_ktime(t->sticks * resolution));
snd_timer_interrupt(stime->timer, t->sticks); snd_timer_interrupt(stime->timer, t->sticks);
if (!atomic_read(&stime->running))
return HRTIMER_NORESTART;
return HRTIMER_RESTART; return HRTIMER_RESTART;
} }
...@@ -58,6 +66,7 @@ static int snd_hrtimer_open(struct snd_timer *t) ...@@ -58,6 +66,7 @@ static int snd_hrtimer_open(struct snd_timer *t)
hrtimer_init(&stime->hrt, CLOCK_MONOTONIC, HRTIMER_MODE_REL); hrtimer_init(&stime->hrt, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
stime->timer = t; stime->timer = t;
stime->hrt.function = snd_hrtimer_callback; stime->hrt.function = snd_hrtimer_callback;
atomic_set(&stime->running, 0);
t->private_data = stime; t->private_data = stime;
return 0; return 0;
} }
...@@ -78,16 +87,18 @@ static int snd_hrtimer_start(struct snd_timer *t) ...@@ -78,16 +87,18 @@ static int snd_hrtimer_start(struct snd_timer *t)
{ {
struct snd_hrtimer *stime = t->private_data; struct snd_hrtimer *stime = t->private_data;
atomic_set(&stime->running, 0);
hrtimer_cancel(&stime->hrt);
hrtimer_start(&stime->hrt, ns_to_ktime(t->sticks * resolution), hrtimer_start(&stime->hrt, ns_to_ktime(t->sticks * resolution),
HRTIMER_MODE_REL); HRTIMER_MODE_REL);
atomic_set(&stime->running, 1);
return 0; return 0;
} }
static int snd_hrtimer_stop(struct snd_timer *t) static int snd_hrtimer_stop(struct snd_timer *t)
{ {
struct snd_hrtimer *stime = t->private_data; struct snd_hrtimer *stime = t->private_data;
atomic_set(&stime->running, 0);
hrtimer_cancel(&stime->hrt);
return 0; return 0;
} }
......
...@@ -548,10 +548,13 @@ static int __devinit snd_opti9xx_configure(struct snd_opti9xx *chip, ...@@ -548,10 +548,13 @@ static int __devinit snd_opti9xx_configure(struct snd_opti9xx *chip,
static irqreturn_t snd_opti93x_interrupt(int irq, void *dev_id) static irqreturn_t snd_opti93x_interrupt(int irq, void *dev_id)
{ {
struct snd_wss *codec = dev_id; struct snd_opti9xx *chip = dev_id;
struct snd_opti9xx *chip = codec->card->private_data; struct snd_wss *codec = chip->codec;
unsigned char status; unsigned char status;
if (!codec)
return IRQ_HANDLED;
status = snd_opti9xx_read(chip, OPTi9XX_MC_REG(11)); status = snd_opti9xx_read(chip, OPTi9XX_MC_REG(11));
if ((status & OPTi93X_IRQ_PLAYBACK) && codec->playback_substream) if ((status & OPTi93X_IRQ_PLAYBACK) && codec->playback_substream)
snd_pcm_period_elapsed(codec->playback_substream); snd_pcm_period_elapsed(codec->playback_substream);
...@@ -691,10 +694,9 @@ static void snd_card_opti9xx_free(struct snd_card *card) ...@@ -691,10 +694,9 @@ static void snd_card_opti9xx_free(struct snd_card *card)
if (chip) { if (chip) {
#ifdef OPTi93X #ifdef OPTi93X
struct snd_wss *codec = chip->codec; if (chip->irq > 0) {
if (codec && codec->irq > 0) { disable_irq(chip->irq);
disable_irq(codec->irq); free_irq(chip->irq, chip);
free_irq(codec->irq, codec);
} }
release_and_free_resource(chip->res_mc_indir); release_and_free_resource(chip->res_mc_indir);
#endif #endif
...@@ -759,9 +761,9 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card) ...@@ -759,9 +761,9 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card)
#endif #endif
#ifdef OPTi93X #ifdef OPTi93X
error = request_irq(irq, snd_opti93x_interrupt, error = request_irq(irq, snd_opti93x_interrupt,
IRQF_DISABLED, DEV_NAME" - WSS", codec); IRQF_DISABLED, DEV_NAME" - WSS", chip);
if (error < 0) { if (error < 0) {
snd_printk(KERN_ERR "opti9xx: can't grab IRQ %d\n", chip->irq); snd_printk(KERN_ERR "opti9xx: can't grab IRQ %d\n", irq);
return error; return error;
} }
#endif #endif
......
...@@ -255,9 +255,13 @@ enum { ...@@ -255,9 +255,13 @@ enum {
* in HD-audio specification * in HD-audio specification
*/ */
#define AC_PINCAP_HDMI (1<<7) /* HDMI pin */ #define AC_PINCAP_HDMI (1<<7) /* HDMI pin */
#define AC_PINCAP_DP (1<<24) /* DisplayPort pin, can
* coexist with AC_PINCAP_HDMI
*/
#define AC_PINCAP_VREF (0x37<<8) #define AC_PINCAP_VREF (0x37<<8)
#define AC_PINCAP_VREF_SHIFT 8 #define AC_PINCAP_VREF_SHIFT 8
#define AC_PINCAP_EAPD (1<<16) /* EAPD capable */ #define AC_PINCAP_EAPD (1<<16) /* EAPD capable */
#define AC_PINCAP_HBR (1<<27) /* High Bit Rate */
/* Vref status (used in pin cap) */ /* Vref status (used in pin cap) */
#define AC_PINCAP_VREF_HIZ (1<<0) /* Hi-Z */ #define AC_PINCAP_VREF_HIZ (1<<0) /* Hi-Z */
#define AC_PINCAP_VREF_50 (1<<1) /* 50% */ #define AC_PINCAP_VREF_50 (1<<1) /* 50% */
...@@ -635,6 +639,7 @@ struct hda_bus { ...@@ -635,6 +639,7 @@ struct hda_bus {
unsigned int rirb_error:1; /* error in codec communication */ unsigned int rirb_error:1; /* error in codec communication */
unsigned int response_reset:1; /* controller was reset */ unsigned int response_reset:1; /* controller was reset */
unsigned int in_reset:1; /* during reset operation */ unsigned int in_reset:1; /* during reset operation */
unsigned int power_keep_link_on:1; /* don't power off HDA link */
}; };
/* /*
......
...@@ -2082,7 +2082,8 @@ static void azx_power_notify(struct hda_bus *bus) ...@@ -2082,7 +2082,8 @@ static void azx_power_notify(struct hda_bus *bus)
} }
if (power_on) if (power_on)
azx_init_chip(chip); azx_init_chip(chip);
else if (chip->running && power_save_controller) else if (chip->running && power_save_controller &&
!bus->power_keep_link_on)
azx_stop_chip(chip); azx_stop_chip(chip);
} }
#endif /* CONFIG_SND_HDA_POWER_SAVE */ #endif /* CONFIG_SND_HDA_POWER_SAVE */
......
...@@ -240,9 +240,14 @@ static void print_pin_caps(struct snd_info_buffer *buffer, ...@@ -240,9 +240,14 @@ static void print_pin_caps(struct snd_info_buffer *buffer,
/* Realtek uses this bit as a different meaning */ /* Realtek uses this bit as a different meaning */
if ((codec->vendor_id >> 16) == 0x10ec) if ((codec->vendor_id >> 16) == 0x10ec)
snd_iprintf(buffer, " R/L"); snd_iprintf(buffer, " R/L");
else else {
if (caps & AC_PINCAP_HBR)
snd_iprintf(buffer, " HBR");
snd_iprintf(buffer, " HDMI"); snd_iprintf(buffer, " HDMI");
}
} }
if (caps & AC_PINCAP_DP)
snd_iprintf(buffer, " DP");
if (caps & AC_PINCAP_TRIG_REQ) if (caps & AC_PINCAP_TRIG_REQ)
snd_iprintf(buffer, " Trigger"); snd_iprintf(buffer, " Trigger");
if (caps & AC_PINCAP_IMP_SENSE) if (caps & AC_PINCAP_IMP_SENSE)
......
...@@ -145,6 +145,42 @@ struct cea_channel_speaker_allocation { ...@@ -145,6 +145,42 @@ struct cea_channel_speaker_allocation {
int spk_mask; int spk_mask;
}; };
/*
* ALSA sequence is:
*
* surround40 surround41 surround50 surround51 surround71
* ch0 front left = = = =
* ch1 front right = = = =
* ch2 rear left = = = =
* ch3 rear right = = = =
* ch4 LFE center center center
* ch5 LFE LFE
* ch6 side left
* ch7 side right
*
* surround71 = {FL, FR, RLC, RRC, FC, LFE, RL, RR}
*/
static int hdmi_channel_mapping[0x32][8] = {
/* stereo */
[0x00] = { 0x00, 0x11, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 },
/* 2.1 */
[0x01] = { 0x00, 0x11, 0x22, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 },
/* Dolby Surround */
[0x02] = { 0x00, 0x11, 0x23, 0xf2, 0xf4, 0xf5, 0xf6, 0xf7 },
/* surround40 */
[0x08] = { 0x00, 0x11, 0x24, 0x35, 0xf3, 0xf2, 0xf6, 0xf7 },
/* 4ch */
[0x03] = { 0x00, 0x11, 0x23, 0x32, 0x44, 0xf5, 0xf6, 0xf7 },
/* surround41 */
[0x09] = { 0x00, 0x11, 0x24, 0x34, 0x43, 0xf2, 0xf6, 0xf7 },
/* surround50 */
[0x0a] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0xf2, 0xf6, 0xf7 },
/* surround51 */
[0x0b] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0x52, 0xf6, 0xf7 },
/* 7.1 */
[0x13] = { 0x00, 0x11, 0x26, 0x37, 0x43, 0x52, 0x64, 0x75 },
};
/* /*
* This is an ordered list! * This is an ordered list!
* *
...@@ -152,32 +188,36 @@ struct cea_channel_speaker_allocation { ...@@ -152,32 +188,36 @@ struct cea_channel_speaker_allocation {
* hdmi_setup_channel_allocation(). * hdmi_setup_channel_allocation().
*/ */
static struct cea_channel_speaker_allocation channel_allocations[] = { static struct cea_channel_speaker_allocation channel_allocations[] = {
/* channel: 8 7 6 5 4 3 2 1 */ /* channel: 7 6 5 4 3 2 1 0 */
{ .ca_index = 0x00, .speakers = { 0, 0, 0, 0, 0, 0, FR, FL } }, { .ca_index = 0x00, .speakers = { 0, 0, 0, 0, 0, 0, FR, FL } },
/* 2.1 */ /* 2.1 */
{ .ca_index = 0x01, .speakers = { 0, 0, 0, 0, 0, LFE, FR, FL } }, { .ca_index = 0x01, .speakers = { 0, 0, 0, 0, 0, LFE, FR, FL } },
/* Dolby Surround */ /* Dolby Surround */
{ .ca_index = 0x02, .speakers = { 0, 0, 0, 0, FC, 0, FR, FL } }, { .ca_index = 0x02, .speakers = { 0, 0, 0, 0, FC, 0, FR, FL } },
/* surround40 */
{ .ca_index = 0x08, .speakers = { 0, 0, RR, RL, 0, 0, FR, FL } },
/* surround41 */
{ .ca_index = 0x09, .speakers = { 0, 0, RR, RL, 0, LFE, FR, FL } },
/* surround50 */
{ .ca_index = 0x0a, .speakers = { 0, 0, RR, RL, FC, 0, FR, FL } },
/* surround51 */
{ .ca_index = 0x0b, .speakers = { 0, 0, RR, RL, FC, LFE, FR, FL } },
/* 6.1 */
{ .ca_index = 0x0f, .speakers = { 0, RC, RR, RL, FC, LFE, FR, FL } },
/* surround71 */
{ .ca_index = 0x13, .speakers = { RRC, RLC, RR, RL, FC, LFE, FR, FL } },
{ .ca_index = 0x03, .speakers = { 0, 0, 0, 0, FC, LFE, FR, FL } }, { .ca_index = 0x03, .speakers = { 0, 0, 0, 0, FC, LFE, FR, FL } },
{ .ca_index = 0x04, .speakers = { 0, 0, 0, RC, 0, 0, FR, FL } }, { .ca_index = 0x04, .speakers = { 0, 0, 0, RC, 0, 0, FR, FL } },
{ .ca_index = 0x05, .speakers = { 0, 0, 0, RC, 0, LFE, FR, FL } }, { .ca_index = 0x05, .speakers = { 0, 0, 0, RC, 0, LFE, FR, FL } },
{ .ca_index = 0x06, .speakers = { 0, 0, 0, RC, FC, 0, FR, FL } }, { .ca_index = 0x06, .speakers = { 0, 0, 0, RC, FC, 0, FR, FL } },
{ .ca_index = 0x07, .speakers = { 0, 0, 0, RC, FC, LFE, FR, FL } }, { .ca_index = 0x07, .speakers = { 0, 0, 0, RC, FC, LFE, FR, FL } },
{ .ca_index = 0x08, .speakers = { 0, 0, RR, RL, 0, 0, FR, FL } },
{ .ca_index = 0x09, .speakers = { 0, 0, RR, RL, 0, LFE, FR, FL } },
{ .ca_index = 0x0a, .speakers = { 0, 0, RR, RL, FC, 0, FR, FL } },
/* 5.1 */
{ .ca_index = 0x0b, .speakers = { 0, 0, RR, RL, FC, LFE, FR, FL } },
{ .ca_index = 0x0c, .speakers = { 0, RC, RR, RL, 0, 0, FR, FL } }, { .ca_index = 0x0c, .speakers = { 0, RC, RR, RL, 0, 0, FR, FL } },
{ .ca_index = 0x0d, .speakers = { 0, RC, RR, RL, 0, LFE, FR, FL } }, { .ca_index = 0x0d, .speakers = { 0, RC, RR, RL, 0, LFE, FR, FL } },
{ .ca_index = 0x0e, .speakers = { 0, RC, RR, RL, FC, 0, FR, FL } }, { .ca_index = 0x0e, .speakers = { 0, RC, RR, RL, FC, 0, FR, FL } },
/* 6.1 */
{ .ca_index = 0x0f, .speakers = { 0, RC, RR, RL, FC, LFE, FR, FL } },
{ .ca_index = 0x10, .speakers = { RRC, RLC, RR, RL, 0, 0, FR, FL } }, { .ca_index = 0x10, .speakers = { RRC, RLC, RR, RL, 0, 0, FR, FL } },
{ .ca_index = 0x11, .speakers = { RRC, RLC, RR, RL, 0, LFE, FR, FL } }, { .ca_index = 0x11, .speakers = { RRC, RLC, RR, RL, 0, LFE, FR, FL } },
{ .ca_index = 0x12, .speakers = { RRC, RLC, RR, RL, FC, 0, FR, FL } }, { .ca_index = 0x12, .speakers = { RRC, RLC, RR, RL, FC, 0, FR, FL } },
/* 7.1 */
{ .ca_index = 0x13, .speakers = { RRC, RLC, RR, RL, FC, LFE, FR, FL } },
{ .ca_index = 0x14, .speakers = { FRC, FLC, 0, 0, 0, 0, FR, FL } }, { .ca_index = 0x14, .speakers = { FRC, FLC, 0, 0, 0, 0, FR, FL } },
{ .ca_index = 0x15, .speakers = { FRC, FLC, 0, 0, 0, LFE, FR, FL } }, { .ca_index = 0x15, .speakers = { FRC, FLC, 0, 0, 0, LFE, FR, FL } },
{ .ca_index = 0x16, .speakers = { FRC, FLC, 0, 0, FC, 0, FR, FL } }, { .ca_index = 0x16, .speakers = { FRC, FLC, 0, 0, FC, 0, FR, FL } },
...@@ -210,7 +250,6 @@ static struct cea_channel_speaker_allocation channel_allocations[] = { ...@@ -210,7 +250,6 @@ static struct cea_channel_speaker_allocation channel_allocations[] = {
{ .ca_index = 0x31, .speakers = { FRW, FLW, RR, RL, FC, LFE, FR, FL } }, { .ca_index = 0x31, .speakers = { FRW, FLW, RR, RL, FC, LFE, FR, FL } },
}; };
/* /*
* HDA/HDMI auto parsing * HDA/HDMI auto parsing
*/ */
...@@ -344,7 +383,7 @@ static int intel_hdmi_parse_codec(struct hda_codec *codec) ...@@ -344,7 +383,7 @@ static int intel_hdmi_parse_codec(struct hda_codec *codec)
break; break;
case AC_WID_PIN: case AC_WID_PIN:
caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
if (!(caps & AC_PINCAP_HDMI)) if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP)))
continue; continue;
if (intel_hdmi_add_pin(codec, nid) < 0) if (intel_hdmi_add_pin(codec, nid) < 0)
return -EINVAL; return -EINVAL;
...@@ -352,6 +391,17 @@ static int intel_hdmi_parse_codec(struct hda_codec *codec) ...@@ -352,6 +391,17 @@ static int intel_hdmi_parse_codec(struct hda_codec *codec)
} }
} }
/*
* G45/IbexPeak don't support EPSS: the unsolicited pin hot plug event
* can be lost and presence sense verb will become inaccurate if the
* HDA link is powered off at hot plug or hw initialization time.
*/
#ifdef CONFIG_SND_HDA_POWER_SAVE
if (!(snd_hda_param_read(codec, codec->afg, AC_PAR_POWER_STATE) &
AC_PWRST_EPSS))
codec->bus->power_keep_link_on = 1;
#endif
return 0; return 0;
} }
...@@ -436,14 +486,15 @@ static void hdmi_set_channel_count(struct hda_codec *codec, ...@@ -436,14 +486,15 @@ static void hdmi_set_channel_count(struct hda_codec *codec,
AC_VERB_SET_CVT_CHAN_COUNT, chs - 1); AC_VERB_SET_CVT_CHAN_COUNT, chs - 1);
} }
static void hdmi_debug_channel_mapping(struct hda_codec *codec, hda_nid_t nid) static void hdmi_debug_channel_mapping(struct hda_codec *codec,
hda_nid_t pin_nid)
{ {
#ifdef CONFIG_SND_DEBUG_VERBOSE #ifdef CONFIG_SND_DEBUG_VERBOSE
int i; int i;
int slot; int slot;
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
slot = snd_hda_codec_read(codec, nid, 0, slot = snd_hda_codec_read(codec, pin_nid, 0,
AC_VERB_GET_HDMI_CHAN_SLOT, i); AC_VERB_GET_HDMI_CHAN_SLOT, i);
printk(KERN_DEBUG "HDMI: ASP channel %d => slot %d\n", printk(KERN_DEBUG "HDMI: ASP channel %d => slot %d\n",
slot >> 4, slot & 0xf); slot >> 4, slot & 0xf);
...@@ -619,25 +670,32 @@ static int hdmi_setup_channel_allocation(struct hda_codec *codec, hda_nid_t nid, ...@@ -619,25 +670,32 @@ static int hdmi_setup_channel_allocation(struct hda_codec *codec, hda_nid_t nid,
return ai->CA; return ai->CA;
} }
static void hdmi_setup_channel_mapping(struct hda_codec *codec, hda_nid_t nid, static void hdmi_setup_channel_mapping(struct hda_codec *codec,
hda_nid_t pin_nid,
struct hdmi_audio_infoframe *ai) struct hdmi_audio_infoframe *ai)
{ {
int i; int i;
int ca = ai->CA;
int err;
if (!ai->CA) if (hdmi_channel_mapping[ca][1] == 0) {
return; for (i = 0; i < channel_allocations[ca].channels; i++)
hdmi_channel_mapping[ca][i] = i | (i << 4);
/* for (; i < 8; i++)
* TODO: adjust channel mapping if necessary hdmi_channel_mapping[ca][i] = 0xf | (i << 4);
* ALSA sequence is front/surr/clfe/side? }
*/
for (i = 0; i < 8; i++) for (i = 0; i < 8; i++) {
snd_hda_codec_write(codec, nid, 0, err = snd_hda_codec_write(codec, pin_nid, 0,
AC_VERB_SET_HDMI_CHAN_SLOT, AC_VERB_SET_HDMI_CHAN_SLOT,
(i << 4) | i); hdmi_channel_mapping[ca][i]);
if (err) {
snd_printdd(KERN_INFO "HDMI: channel mapping failed\n");
break;
}
}
hdmi_debug_channel_mapping(codec, nid); hdmi_debug_channel_mapping(codec, pin_nid);
} }
static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid, static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid,
...@@ -676,7 +734,6 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid, ...@@ -676,7 +734,6 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid,
}; };
hdmi_setup_channel_allocation(codec, nid, &ai); hdmi_setup_channel_allocation(codec, nid, &ai);
hdmi_setup_channel_mapping(codec, nid, &ai);
for (i = 0; i < spec->num_pins; i++) { for (i = 0; i < spec->num_pins; i++) {
if (spec->pin_cvt[i] != nid) if (spec->pin_cvt[i] != nid)
...@@ -686,6 +743,7 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid, ...@@ -686,6 +743,7 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid,
pin_nid = spec->pin[i]; pin_nid = spec->pin[i];
if (!hdmi_infoframe_uptodate(codec, pin_nid, &ai)) { if (!hdmi_infoframe_uptodate(codec, pin_nid, &ai)) {
hdmi_setup_channel_mapping(codec, pin_nid, &ai);
hdmi_stop_infoframe_trans(codec, pin_nid); hdmi_stop_infoframe_trans(codec, pin_nid);
hdmi_fill_audio_infoframe(codec, pin_nid, &ai); hdmi_fill_audio_infoframe(codec, pin_nid, &ai);
hdmi_start_infoframe_trans(codec, pin_nid); hdmi_start_infoframe_trans(codec, pin_nid);
......
...@@ -209,6 +209,7 @@ struct sigmatel_spec { ...@@ -209,6 +209,7 @@ struct sigmatel_spec {
unsigned int gpio_data; unsigned int gpio_data;
unsigned int gpio_mute; unsigned int gpio_mute;
unsigned int gpio_led; unsigned int gpio_led;
unsigned int gpio_led_polarity;
/* stream */ /* stream */
unsigned int stream_delay; unsigned int stream_delay;
...@@ -1538,6 +1539,13 @@ static unsigned int alienware_m17x_pin_configs[13] = { ...@@ -1538,6 +1539,13 @@ static unsigned int alienware_m17x_pin_configs[13] = {
0x904601b0, 0x904601b0,
}; };
static unsigned int intel_dg45id_pin_configs[14] = {
0x02214230, 0x02A19240, 0x01013214, 0x01014210,
0x01A19250, 0x01011212, 0x01016211, 0x40f000f0,
0x40f000f0, 0x40f000f0, 0x40f000f0, 0x014510A0,
0x074510B0, 0x40f000f0
};
static unsigned int *stac92hd73xx_brd_tbl[STAC_92HD73XX_MODELS] = { static unsigned int *stac92hd73xx_brd_tbl[STAC_92HD73XX_MODELS] = {
[STAC_92HD73XX_REF] = ref92hd73xx_pin_configs, [STAC_92HD73XX_REF] = ref92hd73xx_pin_configs,
[STAC_DELL_M6_AMIC] = dell_m6_pin_configs, [STAC_DELL_M6_AMIC] = dell_m6_pin_configs,
...@@ -1545,6 +1553,7 @@ static unsigned int *stac92hd73xx_brd_tbl[STAC_92HD73XX_MODELS] = { ...@@ -1545,6 +1553,7 @@ static unsigned int *stac92hd73xx_brd_tbl[STAC_92HD73XX_MODELS] = {
[STAC_DELL_M6_BOTH] = dell_m6_pin_configs, [STAC_DELL_M6_BOTH] = dell_m6_pin_configs,
[STAC_DELL_EQ] = dell_m6_pin_configs, [STAC_DELL_EQ] = dell_m6_pin_configs,
[STAC_ALIENWARE_M17X] = alienware_m17x_pin_configs, [STAC_ALIENWARE_M17X] = alienware_m17x_pin_configs,
[STAC_92HD73XX_INTEL] = intel_dg45id_pin_configs,
}; };
static const char *stac92hd73xx_models[STAC_92HD73XX_MODELS] = { static const char *stac92hd73xx_models[STAC_92HD73XX_MODELS] = {
...@@ -4724,13 +4733,61 @@ static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res) ...@@ -4724,13 +4733,61 @@ static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res)
} }
} }
static int hp_bseries_system(u32 subsystem_id) /*
* This method searches for the mute LED GPIO configuration
* provided as OEM string in SMBIOS. The format of that string
* is HP_Mute_LED_P_G or HP_Mute_LED_P
* where P can be 0 or 1 and defines mute LED GPIO control state (low/high)
* that corresponds to the NOT muted state of the master volume
* and G is the index of the GPIO to use as the mute LED control (0..9)
* If _G portion is missing it is assigned based on the codec ID
*
* So, HP B-series like systems may have HP_Mute_LED_0 (current models)
* or HP_Mute_LED_0_3 (future models) OEM SMBIOS strings
*/
static int find_mute_led_gpio(struct hda_codec *codec)
{
struct sigmatel_spec *spec = codec->spec;
const struct dmi_device *dev = NULL;
if ((codec->subsystem_id >> 16) == PCI_VENDOR_ID_HP) {
while ((dev = dmi_find_device(DMI_DEV_TYPE_OEM_STRING,
NULL, dev))) {
if (sscanf(dev->name, "HP_Mute_LED_%d_%d",
&spec->gpio_led_polarity,
&spec->gpio_led) == 2) {
spec->gpio_led = 1 << spec->gpio_led;
return 1;
}
if (sscanf(dev->name, "HP_Mute_LED_%d",
&spec->gpio_led_polarity) == 1) {
switch (codec->vendor_id) {
case 0x111d7608:
/* GPIO 0 */
spec->gpio_led = 0x01;
return 1;
case 0x111d7600:
case 0x111d7601:
case 0x111d7602:
case 0x111d7603:
/* GPIO 3 */
spec->gpio_led = 0x08;
return 1;
}
}
}
}
return 0;
}
static int hp_blike_system(u32 subsystem_id)
{ {
switch (subsystem_id) { switch (subsystem_id) {
case 0x103c307e: case 0x103c1520:
case 0x103c307f: case 0x103c1521:
case 0x103c3080: case 0x103c1523:
case 0x103c3081: case 0x103c1524:
case 0x103c1525:
case 0x103c1722: case 0x103c1722:
case 0x103c1723: case 0x103c1723:
case 0x103c1724: case 0x103c1724:
...@@ -4739,6 +4796,14 @@ static int hp_bseries_system(u32 subsystem_id) ...@@ -4739,6 +4796,14 @@ static int hp_bseries_system(u32 subsystem_id)
case 0x103c1727: case 0x103c1727:
case 0x103c1728: case 0x103c1728:
case 0x103c1729: case 0x103c1729:
case 0x103c172a:
case 0x103c172b:
case 0x103c307e:
case 0x103c307f:
case 0x103c3080:
case 0x103c3081:
case 0x103c7007:
case 0x103c7008:
return 1; return 1;
} }
return 0; return 0;
...@@ -4833,7 +4898,7 @@ static int stac92xx_hp_check_power_status(struct hda_codec *codec, ...@@ -4833,7 +4898,7 @@ static int stac92xx_hp_check_power_status(struct hda_codec *codec,
else else
spec->gpio_data |= spec->gpio_led; /* white */ spec->gpio_data |= spec->gpio_led; /* white */
if (hp_bseries_system(codec->subsystem_id)) { if (!spec->gpio_led_polarity) {
/* LED state is inverted on these systems */ /* LED state is inverted on these systems */
spec->gpio_data ^= spec->gpio_led; spec->gpio_data ^= spec->gpio_led;
} }
...@@ -5526,7 +5591,7 @@ static int patch_stac92hd71bxx(struct hda_codec *codec) ...@@ -5526,7 +5591,7 @@ static int patch_stac92hd71bxx(struct hda_codec *codec)
break; break;
} }
if (hp_bseries_system(codec->subsystem_id)) { if (hp_blike_system(codec->subsystem_id)) {
pin_cfg = snd_hda_codec_get_pincfg(codec, 0x0f); pin_cfg = snd_hda_codec_get_pincfg(codec, 0x0f);
if (get_defcfg_device(pin_cfg) == AC_JACK_LINE_OUT || if (get_defcfg_device(pin_cfg) == AC_JACK_LINE_OUT ||
get_defcfg_device(pin_cfg) == AC_JACK_SPEAKER || get_defcfg_device(pin_cfg) == AC_JACK_SPEAKER ||
...@@ -5544,26 +5609,10 @@ static int patch_stac92hd71bxx(struct hda_codec *codec) ...@@ -5544,26 +5609,10 @@ static int patch_stac92hd71bxx(struct hda_codec *codec)
} }
} }
if ((codec->subsystem_id >> 16) == PCI_VENDOR_ID_HP) { if (find_mute_led_gpio(codec))
const struct dmi_device *dev = NULL; snd_printd("mute LED gpio %d polarity %d\n",
while ((dev = dmi_find_device(DMI_DEV_TYPE_OEM_STRING, spec->gpio_led,
NULL, dev))) { spec->gpio_led_polarity);
if (strcmp(dev->name, "HP_Mute_LED_1")) {
switch (codec->vendor_id) {
case 0x111d7608:
spec->gpio_led = 0x01;
break;
case 0x111d7600:
case 0x111d7601:
case 0x111d7602:
case 0x111d7603:
spec->gpio_led = 0x08;
break;
}
break;
}
}
}
#ifdef CONFIG_SND_HDA_POWER_SAVE #ifdef CONFIG_SND_HDA_POWER_SAVE
if (spec->gpio_led) { if (spec->gpio_led) {
......
...@@ -23,9 +23,9 @@ obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o ...@@ -23,9 +23,9 @@ obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o
obj-$(CONFIG_SND_OMAP_SOC_AMS_DELTA) += snd-soc-ams-delta.o obj-$(CONFIG_SND_OMAP_SOC_AMS_DELTA) += snd-soc-ams-delta.o
obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o
obj-$(CONFIG_SND_OMAP_SOC_OVERO) += snd-soc-overo.o obj-$(CONFIG_SND_OMAP_SOC_OVERO) += snd-soc-overo.o
obj-$(CONFIG_MACH_OMAP2EVM) += snd-soc-omap2evm.o obj-$(CONFIG_SND_OMAP_SOC_OMAP2EVM) += snd-soc-omap2evm.o
obj-$(CONFIG_MACH_OMAP3EVM) += snd-soc-omap3evm.o obj-$(CONFIG_SND_OMAP_SOC_OMAP3EVM) += snd-soc-omap3evm.o
obj-$(CONFIG_MACH_OMAP3517EVM) += snd-soc-am3517evm.o obj-$(CONFIG_SND_OMAP_SOC_OMAP3517EVM) += snd-soc-am3517evm.o
obj-$(CONFIG_SND_OMAP_SOC_SDP3430) += snd-soc-sdp3430.o obj-$(CONFIG_SND_OMAP_SOC_SDP3430) += snd-soc-sdp3430.o
obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o
obj-$(CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE) += snd-soc-omap3beagle.o obj-$(CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE) += snd-soc-omap3beagle.o
......
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