Skip to content

Commit

Permalink
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/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
  • Loading branch information
torvalds committed Dec 12, 2009
2 parents 9c3936c + 84a3bd0 commit 6eb7365
Show file tree
Hide file tree
Showing 8 changed files with 201 additions and 70 deletions.
15 changes: 13 additions & 2 deletions sound/core/hrtimer.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,22 @@ static unsigned int resolution;
struct snd_hrtimer {
struct snd_timer *timer;
struct hrtimer hrt;
atomic_t running;
};

static enum hrtimer_restart snd_hrtimer_callback(struct hrtimer *hrt)
{
struct snd_hrtimer *stime = container_of(hrt, struct snd_hrtimer, hrt);
struct snd_timer *t = stime->timer;

if (!atomic_read(&stime->running))
return HRTIMER_NORESTART;

hrtimer_forward_now(hrt, ns_to_ktime(t->sticks * resolution));
snd_timer_interrupt(stime->timer, t->sticks);

if (!atomic_read(&stime->running))
return HRTIMER_NORESTART;
return HRTIMER_RESTART;
}

Expand All @@ -58,6 +66,7 @@ static int snd_hrtimer_open(struct snd_timer *t)
hrtimer_init(&stime->hrt, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
stime->timer = t;
stime->hrt.function = snd_hrtimer_callback;
atomic_set(&stime->running, 0);
t->private_data = stime;
return 0;
}
Expand All @@ -78,16 +87,18 @@ static int snd_hrtimer_start(struct snd_timer *t)
{
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_MODE_REL);
atomic_set(&stime->running, 1);
return 0;
}

static int snd_hrtimer_stop(struct snd_timer *t)
{
struct snd_hrtimer *stime = t->private_data;

hrtimer_cancel(&stime->hrt);
atomic_set(&stime->running, 0);
return 0;
}

Expand Down
18 changes: 10 additions & 8 deletions sound/isa/opti9xx/opti92x-ad1848.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
struct snd_wss *codec = dev_id;
struct snd_opti9xx *chip = codec->card->private_data;
struct snd_opti9xx *chip = dev_id;
struct snd_wss *codec = chip->codec;
unsigned char status;

if (!codec)
return IRQ_HANDLED;

status = snd_opti9xx_read(chip, OPTi9XX_MC_REG(11));
if ((status & OPTi93X_IRQ_PLAYBACK) && codec->playback_substream)
snd_pcm_period_elapsed(codec->playback_substream);
Expand Down Expand Up @@ -691,10 +694,9 @@ static void snd_card_opti9xx_free(struct snd_card *card)

if (chip) {
#ifdef OPTi93X
struct snd_wss *codec = chip->codec;
if (codec && codec->irq > 0) {
disable_irq(codec->irq);
free_irq(codec->irq, codec);
if (chip->irq > 0) {
disable_irq(chip->irq);
free_irq(chip->irq, chip);
}
release_and_free_resource(chip->res_mc_indir);
#endif
Expand Down Expand Up @@ -759,9 +761,9 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card)
#endif
#ifdef OPTi93X
error = request_irq(irq, snd_opti93x_interrupt,
IRQF_DISABLED, DEV_NAME" - WSS", codec);
IRQF_DISABLED, DEV_NAME" - WSS", chip);
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;
}
#endif
Expand Down
5 changes: 5 additions & 0 deletions sound/pci/hda/hda_codec.h
Original file line number Diff line number Diff line change
Expand Up @@ -255,9 +255,13 @@ enum {
* in HD-audio specification
*/
#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_SHIFT 8
#define AC_PINCAP_EAPD (1<<16) /* EAPD capable */
#define AC_PINCAP_HBR (1<<27) /* High Bit Rate */
/* Vref status (used in pin cap) */
#define AC_PINCAP_VREF_HIZ (1<<0) /* Hi-Z */
#define AC_PINCAP_VREF_50 (1<<1) /* 50% */
Expand Down Expand Up @@ -635,6 +639,7 @@ struct hda_bus {
unsigned int rirb_error:1; /* error in codec communication */
unsigned int response_reset:1; /* controller was reset */
unsigned int in_reset:1; /* during reset operation */
unsigned int power_keep_link_on:1; /* don't power off HDA link */
};

/*
Expand Down
3 changes: 2 additions & 1 deletion sound/pci/hda/hda_intel.c
Original file line number Diff line number Diff line change
Expand Up @@ -2082,7 +2082,8 @@ static void azx_power_notify(struct hda_bus *bus)
}
if (power_on)
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);
}
#endif /* CONFIG_SND_HDA_POWER_SAVE */
Expand Down
7 changes: 6 additions & 1 deletion sound/pci/hda/hda_proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -240,9 +240,14 @@ static void print_pin_caps(struct snd_info_buffer *buffer,
/* Realtek uses this bit as a different meaning */
if ((codec->vendor_id >> 16) == 0x10ec)
snd_iprintf(buffer, " R/L");
else
else {
if (caps & AC_PINCAP_HBR)
snd_iprintf(buffer, " HBR");
snd_iprintf(buffer, " HDMI");
}
}
if (caps & AC_PINCAP_DP)
snd_iprintf(buffer, " DP");
if (caps & AC_PINCAP_TRIG_REQ)
snd_iprintf(buffer, " Trigger");
if (caps & AC_PINCAP_IMP_SENSE)
Expand Down
114 changes: 86 additions & 28 deletions sound/pci/hda/patch_intelhdmi.c
Original file line number Diff line number Diff line change
Expand Up @@ -145,39 +145,79 @@ struct cea_channel_speaker_allocation {
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!
*
* The preceding ones have better chances to be selected by
* hdmi_setup_channel_allocation().
*/
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 } },
/* 2.1 */
{ .ca_index = 0x01, .speakers = { 0, 0, 0, 0, 0, LFE, FR, FL } },
/* Dolby Surround */
{ .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 = 0x04, .speakers = { 0, 0, 0, RC, 0, 0, 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 = 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 = 0x0d, .speakers = { 0, RC, RR, RL, 0, LFE, 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 = 0x11, .speakers = { RRC, RLC, RR, RL, 0, LFE, 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 = 0x15, .speakers = { FRC, FLC, 0, 0, 0, LFE, FR, FL } },
{ .ca_index = 0x16, .speakers = { FRC, FLC, 0, 0, FC, 0, FR, FL } },
Expand Down Expand Up @@ -210,7 +250,6 @@ static struct cea_channel_speaker_allocation channel_allocations[] = {
{ .ca_index = 0x31, .speakers = { FRW, FLW, RR, RL, FC, LFE, FR, FL } },
};


/*
* HDA/HDMI auto parsing
*/
Expand Down Expand Up @@ -344,14 +383,25 @@ static int intel_hdmi_parse_codec(struct hda_codec *codec)
break;
case AC_WID_PIN:
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;
if (intel_hdmi_add_pin(codec, nid) < 0)
return -EINVAL;
break;
}
}

/*
* 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;
}

Expand Down Expand Up @@ -436,14 +486,15 @@ static void hdmi_set_channel_count(struct hda_codec *codec,
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
int i;
int slot;

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);
printk(KERN_DEBUG "HDMI: ASP channel %d => slot %d\n",
slot >> 4, slot & 0xf);
Expand Down Expand Up @@ -619,25 +670,32 @@ static int hdmi_setup_channel_allocation(struct hda_codec *codec, hda_nid_t nid,
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)
{
int i;
int ca = ai->CA;
int err;

if (!ai->CA)
return;

/*
* TODO: adjust channel mapping if necessary
* ALSA sequence is front/surr/clfe/side?
*/
if (hdmi_channel_mapping[ca][1] == 0) {
for (i = 0; i < channel_allocations[ca].channels; i++)
hdmi_channel_mapping[ca][i] = i | (i << 4);
for (; i < 8; i++)
hdmi_channel_mapping[ca][i] = 0xf | (i << 4);
}

for (i = 0; i < 8; i++)
snd_hda_codec_write(codec, nid, 0,
AC_VERB_SET_HDMI_CHAN_SLOT,
(i << 4) | i);
for (i = 0; i < 8; i++) {
err = snd_hda_codec_write(codec, pin_nid, 0,
AC_VERB_SET_HDMI_CHAN_SLOT,
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,
Expand Down Expand Up @@ -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_mapping(codec, nid, &ai);

for (i = 0; i < spec->num_pins; i++) {
if (spec->pin_cvt[i] != nid)
Expand All @@ -686,6 +743,7 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid,

pin_nid = spec->pin[i];
if (!hdmi_infoframe_uptodate(codec, pin_nid, &ai)) {
hdmi_setup_channel_mapping(codec, pin_nid, &ai);
hdmi_stop_infoframe_trans(codec, pin_nid);
hdmi_fill_audio_infoframe(codec, pin_nid, &ai);
hdmi_start_infoframe_trans(codec, pin_nid);
Expand Down
Loading

0 comments on commit 6eb7365

Please sign in to comment.