Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 14a4fa20 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6:
  ASoC: add AD1980 obsolete information
  ASoC: register cache should be 1 byte aligned for 1 byte long register
  ALSA: hda - Adding support for new IDT 92HD87XX codecs
  ASoC: Fix inverted mute controls for WM8580
  ALSA: HDA: Use model=auto for LG R510
  ALSA: hda - Update model entries in HD-Audio-Models.txt
  ALSA: hda: document VIA models
  ALSA: hda - patch_nvhdmi.c: Add missing codec IDs, unify names
  ALSA: hda - add support for Conexant CX20584
  ALSA: hda - New snd-hda-intel model/pin config for hp dv7-4000
  ALSA: hda - Fix missing stream for second ADC on Realtek ALC260 HDA codec
  ALSA: hda - Make converter setups sticky
  ALSA: hda - Add support for Acer ZGA ALC271 (1025:047c)
  sound/oss: Adjust confusing if indentation
  sound: oss: au1550_ac97.c removed duplicated #include
  ASoC: Fix for changed Eureka Kconfig symbol names
parents 16bb85bc c6774bcd
Loading
Loading
Loading
Loading
+11 −2
Original line number Original line Diff line number Diff line
@@ -83,8 +83,8 @@ ALC269
======
======
  basic		Basic preset
  basic		Basic preset
  quanta	Quanta FL1
  quanta	Quanta FL1
  eeepc-p703	ASUS Eeepc P703 P900A
  laptop-amic	Laptops with analog-mic input
  eeepc-p901	ASUS Eeepc P901 S101
  laptop-dmic	Laptops with digital-mic input
  fujitsu	FSC Amilo
  fujitsu	FSC Amilo
  lifebook	Fujitsu Lifebook S6420
  lifebook	Fujitsu Lifebook S6420
  auto		auto-config reading BIOS (default)
  auto		auto-config reading BIOS (default)
@@ -109,6 +109,8 @@ ALC662/663/272
  asus-mode4	ASUS
  asus-mode4	ASUS
  asus-mode5	ASUS
  asus-mode5	ASUS
  asus-mode6	ASUS
  asus-mode6	ASUS
  asus-mode7	ASUS
  asus-mode8	ASUS
  dell		Dell with ALC272
  dell		Dell with ALC272
  dell-zm1	Dell ZM1 with ALC272
  dell-zm1	Dell ZM1 with ALC272
  samsung-nc10	Samsung NC10 mini notebook
  samsung-nc10	Samsung NC10 mini notebook
@@ -295,8 +297,10 @@ Conexant 5066
=============
=============
  laptop	Basic Laptop config (default)
  laptop	Basic Laptop config (default)
  dell-laptop	Dell laptops
  dell-laptop	Dell laptops
  dell-vostro	Dell Vostro
  olpc-xo-1_5	OLPC XO 1.5
  olpc-xo-1_5	OLPC XO 1.5
  ideapad       Lenovo IdeaPad U150
  ideapad       Lenovo IdeaPad U150
  thinkpad	Lenovo Thinkpad


STAC9200
STAC9200
========
========
@@ -404,6 +408,7 @@ STAC92HD83*
  mic-ref	Reference board with power management for ports
  mic-ref	Reference board with power management for ports
  dell-s14	Dell laptop
  dell-s14	Dell laptop
  hp		HP laptops with (inverted) mute-LED
  hp		HP laptops with (inverted) mute-LED
  hp-dv7-4000	HP dv-7 4000
  auto		BIOS setup (default)
  auto		BIOS setup (default)


STAC9872
STAC9872
@@ -416,3 +421,7 @@ Cirrus Logic CS4206/4207
  mbp55		MacBook Pro 5,5
  mbp55		MacBook Pro 5,5
  imac27	IMac 27 Inch
  imac27	IMac 27 Inch
  auto		BIOS setup (default)
  auto		BIOS setup (default)

VIA VT17xx/VT18xx/VT20xx
========================
  auto		BIOS setup (default)
+0 −1
Original line number Original line Diff line number Diff line
@@ -50,7 +50,6 @@
#include <linux/poll.h>
#include <linux/poll.h>
#include <linux/bitops.h>
#include <linux/bitops.h>
#include <linux/spinlock.h>
#include <linux/spinlock.h>
#include <linux/smp_lock.h>
#include <linux/ac97_codec.h>
#include <linux/ac97_codec.h>
#include <linux/mutex.h>
#include <linux/mutex.h>


+142 −8
Original line number Original line Diff line number Diff line
@@ -970,6 +970,36 @@ static void restore_init_pincfgs(struct hda_codec *codec)
	snd_array_free(&codec->init_pins);
	snd_array_free(&codec->init_pins);
}
}


/*
 * audio-converter setup caches
 */
struct hda_cvt_setup {
	hda_nid_t nid;
	u8 stream_tag;
	u8 channel_id;
	u16 format_id;
	unsigned char active;	/* cvt is currently used */
	unsigned char dirty;	/* setups should be cleared */
};

/* get or create a cache entry for the given audio converter NID */
static struct hda_cvt_setup *
get_hda_cvt_setup(struct hda_codec *codec, hda_nid_t nid)
{
	struct hda_cvt_setup *p;
	int i;

	for (i = 0; i < codec->cvt_setups.used; i++) {
		p = snd_array_elem(&codec->cvt_setups, i);
		if (p->nid == nid)
			return p;
	}
	p = snd_array_new(&codec->cvt_setups);
	if (p)
		p->nid = nid;
	return p;
}

/*
/*
 * codec destructor
 * codec destructor
 */
 */
@@ -1038,12 +1068,14 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus,
	codec->addr = codec_addr;
	codec->addr = codec_addr;
	mutex_init(&codec->spdif_mutex);
	mutex_init(&codec->spdif_mutex);
	mutex_init(&codec->control_mutex);
	mutex_init(&codec->control_mutex);
	mutex_init(&codec->prepare_mutex);
	init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info));
	init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info));
	init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
	init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
	snd_array_init(&codec->mixers, sizeof(struct hda_nid_item), 32);
	snd_array_init(&codec->mixers, sizeof(struct hda_nid_item), 32);
	snd_array_init(&codec->nids, sizeof(struct hda_nid_item), 32);
	snd_array_init(&codec->nids, sizeof(struct hda_nid_item), 32);
	snd_array_init(&codec->init_pins, sizeof(struct hda_pincfg), 16);
	snd_array_init(&codec->init_pins, sizeof(struct hda_pincfg), 16);
	snd_array_init(&codec->driver_pins, sizeof(struct hda_pincfg), 16);
	snd_array_init(&codec->driver_pins, sizeof(struct hda_pincfg), 16);
	snd_array_init(&codec->cvt_setups, sizeof(struct hda_cvt_setup), 8);
	if (codec->bus->modelname) {
	if (codec->bus->modelname) {
		codec->modelname = kstrdup(codec->bus->modelname, GFP_KERNEL);
		codec->modelname = kstrdup(codec->bus->modelname, GFP_KERNEL);
		if (!codec->modelname) {
		if (!codec->modelname) {
@@ -1181,16 +1213,51 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
				u32 stream_tag,
				u32 stream_tag,
				int channel_id, int format)
				int channel_id, int format)
{
{
	struct hda_cvt_setup *p;
	unsigned int oldval, newval;
	int i;

	if (!nid)
	if (!nid)
		return;
		return;


	snd_printdd("hda_codec_setup_stream: "
	snd_printdd("hda_codec_setup_stream: "
		    "NID=0x%x, stream=0x%x, channel=%d, format=0x%x\n",
		    "NID=0x%x, stream=0x%x, channel=%d, format=0x%x\n",
		    nid, stream_tag, channel_id, format);
		    nid, stream_tag, channel_id, format);
	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID,
	p = get_hda_cvt_setup(codec, nid);
			    (stream_tag << 4) | channel_id);
	if (!p)
		return;
	/* update the stream-id if changed */
	if (p->stream_tag != stream_tag || p->channel_id != channel_id) {
		oldval = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0);
		newval = (stream_tag << 4) | channel_id;
		if (oldval != newval)
			snd_hda_codec_write(codec, nid, 0,
					    AC_VERB_SET_CHANNEL_STREAMID,
					    newval);
		p->stream_tag = stream_tag;
		p->channel_id = channel_id;
	}
	/* update the format-id if changed */
	if (p->format_id != format) {
		oldval = snd_hda_codec_read(codec, nid, 0,
					    AC_VERB_GET_STREAM_FORMAT, 0);
		if (oldval != format) {
			msleep(1);
			msleep(1);
	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, format);
			snd_hda_codec_write(codec, nid, 0,
					    AC_VERB_SET_STREAM_FORMAT,
					    format);
		}
		p->format_id = format;
	}
	p->active = 1;
	p->dirty = 0;

	/* make other inactive cvts with the same stream-tag dirty */
	for (i = 0; i < codec->cvt_setups.used; i++) {
		p = snd_array_elem(&codec->cvt_setups, i);
		if (!p->active && p->stream_tag == stream_tag)
			p->dirty = 1;
	}
}
}
EXPORT_SYMBOL_HDA(snd_hda_codec_setup_stream);
EXPORT_SYMBOL_HDA(snd_hda_codec_setup_stream);


@@ -1201,17 +1268,54 @@ EXPORT_SYMBOL_HDA(snd_hda_codec_setup_stream);
 */
 */
void snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid)
void snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid)
{
{
	struct hda_cvt_setup *p;

	if (!nid)
	if (!nid)
		return;
		return;


	snd_printdd("hda_codec_cleanup_stream: NID=0x%x\n", nid);
	snd_printdd("hda_codec_cleanup_stream: NID=0x%x\n", nid);
	/* here we just clear the active flag; actual clean-ups will be done
	 * in purify_inactive_streams()
	 */
	p = get_hda_cvt_setup(codec, nid);
	if (p)
		p->active = 0;
}
EXPORT_SYMBOL_HDA(snd_hda_codec_cleanup_stream);

static void really_cleanup_stream(struct hda_codec *codec,
				  struct hda_cvt_setup *q)
{
	hda_nid_t nid = q->nid;
	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID, 0);
	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID, 0);
#if 0 /* keep the format */
	msleep(1);
	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, 0);
	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, 0);
#endif
	memset(q, 0, sizeof(*q));
	q->nid = nid;
}

/* clean up the all conflicting obsolete streams */
static void purify_inactive_streams(struct hda_codec *codec)
{
	int i;

	for (i = 0; i < codec->cvt_setups.used; i++) {
		struct hda_cvt_setup *p = snd_array_elem(&codec->cvt_setups, i);
		if (p->dirty)
			really_cleanup_stream(codec, p);
	}
}

/* clean up all streams; called from suspend */
static void hda_cleanup_all_streams(struct hda_codec *codec)
{
	int i;

	for (i = 0; i < codec->cvt_setups.used; i++) {
		struct hda_cvt_setup *p = snd_array_elem(&codec->cvt_setups, i);
		if (p->stream_tag)
			really_cleanup_stream(codec, p);
	}
}
}
EXPORT_SYMBOL_HDA(snd_hda_codec_cleanup_stream);


/*
/*
 * amp access functions
 * amp access functions
@@ -2928,6 +3032,7 @@ static void hda_call_codec_suspend(struct hda_codec *codec)
{
{
	if (codec->patch_ops.suspend)
	if (codec->patch_ops.suspend)
		codec->patch_ops.suspend(codec, PMSG_SUSPEND);
		codec->patch_ops.suspend(codec, PMSG_SUSPEND);
	hda_cleanup_all_streams(codec);
	hda_set_power_state(codec,
	hda_set_power_state(codec,
			    codec->afg ? codec->afg : codec->mfg,
			    codec->afg ? codec->afg : codec->mfg,
			    AC_PWRST_D3);
			    AC_PWRST_D3);
@@ -3377,6 +3482,35 @@ static int set_pcm_default_values(struct hda_codec *codec,
	return 0;
	return 0;
}
}


/*
 * codec prepare/cleanup entries
 */
int snd_hda_codec_prepare(struct hda_codec *codec,
			  struct hda_pcm_stream *hinfo,
			  unsigned int stream,
			  unsigned int format,
			  struct snd_pcm_substream *substream)
{
	int ret;
	mutex_lock(&codec->prepare_mutex);
	ret = hinfo->ops.prepare(hinfo, codec, stream, format, substream);
	if (ret >= 0)
		purify_inactive_streams(codec);
	mutex_unlock(&codec->prepare_mutex);
	return ret;
}
EXPORT_SYMBOL_HDA(snd_hda_codec_prepare);

void snd_hda_codec_cleanup(struct hda_codec *codec,
			   struct hda_pcm_stream *hinfo,
			   struct snd_pcm_substream *substream)
{
	mutex_lock(&codec->prepare_mutex);
	hinfo->ops.cleanup(hinfo, codec, substream);
	mutex_unlock(&codec->prepare_mutex);
}
EXPORT_SYMBOL_HDA(snd_hda_codec_cleanup);

/* global */
/* global */
const char *snd_hda_pcm_type_name[HDA_PCM_NTYPES] = {
const char *snd_hda_pcm_type_name[HDA_PCM_NTYPES] = {
	"Audio", "SPDIF", "HDMI", "Modem"
	"Audio", "SPDIF", "HDMI", "Modem"
+12 −0
Original line number Original line Diff line number Diff line
@@ -826,12 +826,14 @@ struct hda_codec {


	struct mutex spdif_mutex;
	struct mutex spdif_mutex;
	struct mutex control_mutex;
	struct mutex control_mutex;
	struct mutex prepare_mutex;
	unsigned int spdif_status;	/* IEC958 status bits */
	unsigned int spdif_status;	/* IEC958 status bits */
	unsigned short spdif_ctls;	/* SPDIF control bits */
	unsigned short spdif_ctls;	/* SPDIF control bits */
	unsigned int spdif_in_enable;	/* SPDIF input enable? */
	unsigned int spdif_in_enable;	/* SPDIF input enable? */
	hda_nid_t *slave_dig_outs; /* optional digital out slave widgets */
	hda_nid_t *slave_dig_outs; /* optional digital out slave widgets */
	struct snd_array init_pins;	/* initial (BIOS) pin configurations */
	struct snd_array init_pins;	/* initial (BIOS) pin configurations */
	struct snd_array driver_pins;	/* pin configs set by codec parser */
	struct snd_array driver_pins;	/* pin configs set by codec parser */
	struct snd_array cvt_setups;	/* audio convert setups */


#ifdef CONFIG_SND_HDA_HWDEP
#ifdef CONFIG_SND_HDA_HWDEP
	struct snd_hwdep *hwdep;	/* assigned hwdep device */
	struct snd_hwdep *hwdep;	/* assigned hwdep device */
@@ -948,6 +950,16 @@ int snd_hda_codec_build_controls(struct hda_codec *codec);
 */
 */
int snd_hda_build_pcms(struct hda_bus *bus);
int snd_hda_build_pcms(struct hda_bus *bus);
int snd_hda_codec_build_pcms(struct hda_codec *codec);
int snd_hda_codec_build_pcms(struct hda_codec *codec);

int snd_hda_codec_prepare(struct hda_codec *codec,
			  struct hda_pcm_stream *hinfo,
			  unsigned int stream,
			  unsigned int format,
			  struct snd_pcm_substream *substream);
void snd_hda_codec_cleanup(struct hda_codec *codec,
			   struct hda_pcm_stream *hinfo,
			   struct snd_pcm_substream *substream);

void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
				u32 stream_tag,
				u32 stream_tag,
				int channel_id, int format);
				int channel_id, int format);
+3 −3
Original line number Original line Diff line number Diff line
@@ -1634,7 +1634,7 @@ static int azx_pcm_hw_free(struct snd_pcm_substream *substream)
	azx_dev->period_bytes = 0;
	azx_dev->period_bytes = 0;
	azx_dev->format_val = 0;
	azx_dev->format_val = 0;


	hinfo->ops.cleanup(hinfo, apcm->codec, substream);
	snd_hda_codec_cleanup(apcm->codec, hinfo, substream);


	return snd_pcm_lib_free_pages(substream);
	return snd_pcm_lib_free_pages(substream);
}
}
@@ -1688,7 +1688,7 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
	else
	else
		azx_dev->fifo_size = 0;
		azx_dev->fifo_size = 0;


	return hinfo->ops.prepare(hinfo, apcm->codec, azx_dev->stream_tag,
	return snd_hda_codec_prepare(apcm->codec, hinfo, azx_dev->stream_tag,
				     azx_dev->format_val, substream);
				     azx_dev->format_val, substream);
}
}


Loading