2005-04-17 06:20:36 +08:00
|
|
|
/*
|
|
|
|
* Universal Interface for Intel High Definition Audio Codec
|
|
|
|
*
|
|
|
|
* Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
|
|
* under the terms of the GNU General Public License as published by the Free
|
|
|
|
* Software Foundation; either version 2 of the License, or (at your option)
|
|
|
|
* any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
|
|
* more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License along with
|
|
|
|
* this program; if not, write to the Free Software Foundation, Inc., 59
|
|
|
|
* Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef __SOUND_HDA_CODEC_H
|
|
|
|
#define __SOUND_HDA_CODEC_H
|
|
|
|
|
|
|
|
#include <sound/info.h>
|
|
|
|
#include <sound/control.h>
|
|
|
|
#include <sound/pcm.h>
|
2007-07-28 00:58:06 +08:00
|
|
|
#include <sound/hwdep.h>
|
2013-12-09 21:28:36 +08:00
|
|
|
#include <sound/hda_verbs.h>
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2008-07-30 21:01:44 +08:00
|
|
|
/*
|
|
|
|
* generic arrays
|
|
|
|
*/
|
|
|
|
struct snd_array {
|
|
|
|
unsigned int used;
|
|
|
|
unsigned int alloced;
|
|
|
|
unsigned int elem_size;
|
|
|
|
unsigned int alloc_align;
|
|
|
|
void *list;
|
|
|
|
};
|
|
|
|
|
|
|
|
void *snd_array_new(struct snd_array *array);
|
|
|
|
void snd_array_free(struct snd_array *array);
|
|
|
|
static inline void snd_array_init(struct snd_array *array, unsigned int size,
|
|
|
|
unsigned int align)
|
|
|
|
{
|
|
|
|
array->elem_size = size;
|
|
|
|
array->alloc_align = align;
|
|
|
|
}
|
|
|
|
|
2008-11-10 23:24:26 +08:00
|
|
|
static inline void *snd_array_elem(struct snd_array *array, unsigned int idx)
|
|
|
|
{
|
|
|
|
return array->list + idx * array->elem_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline unsigned int snd_array_index(struct snd_array *array, void *ptr)
|
|
|
|
{
|
|
|
|
return (unsigned long)(ptr - array->list) / array->elem_size;
|
|
|
|
}
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
/*
|
|
|
|
* Structures
|
|
|
|
*/
|
|
|
|
|
|
|
|
struct hda_bus;
|
2008-07-19 00:20:52 +08:00
|
|
|
struct hda_beep;
|
2005-04-17 06:20:36 +08:00
|
|
|
struct hda_codec;
|
|
|
|
struct hda_pcm;
|
|
|
|
struct hda_pcm_stream;
|
|
|
|
struct hda_bus_unsolicited;
|
|
|
|
|
|
|
|
/* NID type */
|
|
|
|
typedef u16 hda_nid_t;
|
|
|
|
|
|
|
|
/* bus operators */
|
|
|
|
struct hda_bus_ops {
|
|
|
|
/* send a single command */
|
2008-11-06 23:50:40 +08:00
|
|
|
int (*command)(struct hda_bus *bus, unsigned int cmd);
|
2005-04-17 06:20:36 +08:00
|
|
|
/* get a response from the last command */
|
2009-08-01 18:45:16 +08:00
|
|
|
unsigned int (*get_response)(struct hda_bus *bus, unsigned int addr);
|
2005-04-17 06:20:36 +08:00
|
|
|
/* free the private data */
|
|
|
|
void (*private_free)(struct hda_bus *);
|
2008-07-30 21:01:44 +08:00
|
|
|
/* attach a PCM stream */
|
2008-11-06 23:50:40 +08:00
|
|
|
int (*attach_pcm)(struct hda_bus *bus, struct hda_codec *codec,
|
|
|
|
struct hda_pcm *pcm);
|
2009-06-02 07:16:07 +08:00
|
|
|
/* reset bus for retry verb */
|
|
|
|
void (*bus_reset)(struct hda_bus *bus);
|
2012-08-25 00:38:08 +08:00
|
|
|
#ifdef CONFIG_PM
|
2007-12-18 20:13:47 +08:00
|
|
|
/* notify power-up/down from codec to controller */
|
2012-08-29 00:14:29 +08:00
|
|
|
void (*pm_notify)(struct hda_bus *bus, bool power_up);
|
2007-08-10 23:21:45 +08:00
|
|
|
#endif
|
2012-09-21 11:29:13 +08:00
|
|
|
#ifdef CONFIG_SND_HDA_DSP_LOADER
|
|
|
|
/* prepare DSP transfer */
|
|
|
|
int (*load_dsp_prepare)(struct hda_bus *bus, unsigned int format,
|
|
|
|
unsigned int byte_size,
|
|
|
|
struct snd_dma_buffer *bufp);
|
|
|
|
/* start/stop DSP transfer */
|
|
|
|
void (*load_dsp_trigger)(struct hda_bus *bus, bool start);
|
|
|
|
/* clean up DSP transfer */
|
|
|
|
void (*load_dsp_cleanup)(struct hda_bus *bus,
|
|
|
|
struct snd_dma_buffer *dmab);
|
|
|
|
#endif
|
2005-04-17 06:20:36 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
/* template to pass to the bus constructor */
|
|
|
|
struct hda_bus_template {
|
|
|
|
void *private_data;
|
|
|
|
struct pci_dev *pci;
|
|
|
|
const char *modelname;
|
2008-11-27 19:43:28 +08:00
|
|
|
int *power_save;
|
2005-04-17 06:20:36 +08:00
|
|
|
struct hda_bus_ops ops;
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* codec bus
|
|
|
|
*
|
|
|
|
* each controller needs to creata a hda_bus to assign the accessor.
|
|
|
|
* A hda_bus contains several codecs in the list codec_list.
|
|
|
|
*/
|
|
|
|
struct hda_bus {
|
2005-11-17 21:57:47 +08:00
|
|
|
struct snd_card *card;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
/* copied from template */
|
|
|
|
void *private_data;
|
|
|
|
struct pci_dev *pci;
|
|
|
|
const char *modelname;
|
2008-11-27 19:43:28 +08:00
|
|
|
int *power_save;
|
2005-04-17 06:20:36 +08:00
|
|
|
struct hda_bus_ops ops;
|
|
|
|
|
|
|
|
/* codec linked list */
|
|
|
|
struct list_head codec_list;
|
2013-11-27 12:00:51 +08:00
|
|
|
unsigned int num_codecs;
|
2007-07-27 22:52:19 +08:00
|
|
|
/* link caddr -> codec */
|
|
|
|
struct hda_codec *caddr_tbl[HDA_MAX_CODEC_ADDRESS + 1];
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2006-01-16 23:34:20 +08:00
|
|
|
struct mutex cmd_mutex;
|
2010-08-20 15:44:36 +08:00
|
|
|
struct mutex prepare_mutex;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
/* unsolicited event queue */
|
|
|
|
struct hda_bus_unsolicited *unsol;
|
2009-02-05 14:34:28 +08:00
|
|
|
char workq_name[16];
|
2009-01-12 17:09:24 +08:00
|
|
|
struct workqueue_struct *workq; /* common workqueue for codecs */
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2008-11-27 21:17:01 +08:00
|
|
|
/* assigned PCMs */
|
|
|
|
DECLARE_BITMAP(pcm_dev_bits, SNDRV_PCM_DEVICES);
|
|
|
|
|
2008-01-16 23:09:47 +08:00
|
|
|
/* misc op flags */
|
|
|
|
unsigned int needs_damn_long_delay :1;
|
2009-06-02 07:20:22 +08:00
|
|
|
unsigned int allow_bus_reset:1; /* allow bus reset at fatal error */
|
|
|
|
unsigned int sync_write:1; /* sync after verb write */
|
|
|
|
/* status for codec/controller */
|
2008-11-21 16:08:06 +08:00
|
|
|
unsigned int shutdown :1; /* being unloaded */
|
2009-03-24 14:36:09 +08:00
|
|
|
unsigned int rirb_error:1; /* error in codec communication */
|
2009-06-02 07:16:07 +08:00
|
|
|
unsigned int response_reset:1; /* controller was reset */
|
|
|
|
unsigned int in_reset:1; /* during reset operation */
|
2009-12-11 20:15:11 +08:00
|
|
|
unsigned int power_keep_link_on:1; /* don't power off HDA link */
|
2013-06-06 20:20:19 +08:00
|
|
|
unsigned int no_response_fallback:1; /* don't fallback at RIRB error */
|
ALSA: hda - Fix broken workaround for HDMI/SPDIF conflicts
The commit [dcda58061: ALSA: hda - Add workaround for conflicting
IEC958 controls] introduced a workaround for cards that have both
SPDIF and HDMI devices for giving device=1 to SPDIF control elements.
It turned out, however, that this workaround doesn't work well -
- The workaround checks only conflicts in a single codec, but SPDIF
and HDMI are provided by multiple codecs in many cases, and
- ALSA mixer abstraction doesn't care about the device number in ctl
elements, thus you'll get errors from amixer such as
% amixer scontrols -c 0
ALSA lib simple_none.c:1551:(simple_add1) helem (MIXER,'IEC958
Playback Switch',0,1,0) appears twice or more
amixer: Mixer hw:0 load error: Invalid argument
This patch fixes the previous broken workaround. Instead of changing
the device number of SPDIF ctl elements, shift the element indices of
such controls up to 16. Also, the conflict check is performed over
all codecs found on the bus.
HDMI devices will be put to dev=0,index=0 as before. Only the
conflicting SPDIF device is moved to a different place. The new place
of SPDIF device is supposed by the updated alsa-lib HDA-Intel.conf,
respectively.
Reported-by: Stephan Raue <stephan@openelec.tv>
Reported-by: Anssi Hannula <anssi.hannula@iki.fi>
Cc: <stable@vger.kernel.org> [v3.8]
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2013-02-13 00:02:41 +08:00
|
|
|
|
|
|
|
int primary_dig_out_type; /* primary digital out PCM type */
|
2005-04-17 06:20:36 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* codec preset
|
|
|
|
*
|
|
|
|
* Known codecs have the patch to build and set up the controls/PCMs
|
|
|
|
* better than the generic parser.
|
|
|
|
*/
|
|
|
|
struct hda_codec_preset {
|
|
|
|
unsigned int id;
|
|
|
|
unsigned int mask;
|
|
|
|
unsigned int subs;
|
|
|
|
unsigned int subs_mask;
|
|
|
|
unsigned int rev;
|
2008-01-22 22:32:25 +08:00
|
|
|
hda_nid_t afg, mfg;
|
2005-04-17 06:20:36 +08:00
|
|
|
const char *name;
|
|
|
|
int (*patch)(struct hda_codec *codec);
|
|
|
|
};
|
|
|
|
|
2008-11-27 22:47:11 +08:00
|
|
|
struct hda_codec_preset_list {
|
|
|
|
const struct hda_codec_preset *preset;
|
|
|
|
struct module *owner;
|
|
|
|
struct list_head list;
|
|
|
|
};
|
|
|
|
|
|
|
|
/* initial hook */
|
|
|
|
int snd_hda_add_codec_preset(struct hda_codec_preset_list *preset);
|
|
|
|
int snd_hda_delete_codec_preset(struct hda_codec_preset_list *preset);
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
/* ops set by the preset patch */
|
|
|
|
struct hda_codec_ops {
|
|
|
|
int (*build_controls)(struct hda_codec *codec);
|
|
|
|
int (*build_pcms)(struct hda_codec *codec);
|
|
|
|
int (*init)(struct hda_codec *codec);
|
|
|
|
void (*free)(struct hda_codec *codec);
|
|
|
|
void (*unsol_event)(struct hda_codec *codec, unsigned int res);
|
2011-07-26 16:33:10 +08:00
|
|
|
void (*set_power_state)(struct hda_codec *codec, hda_nid_t fg,
|
|
|
|
unsigned int power_state);
|
2011-07-26 15:52:50 +08:00
|
|
|
#ifdef CONFIG_PM
|
2012-07-02 21:20:37 +08:00
|
|
|
int (*suspend)(struct hda_codec *codec);
|
2005-04-17 06:20:36 +08:00
|
|
|
int (*resume)(struct hda_codec *codec);
|
2007-08-10 23:21:45 +08:00
|
|
|
int (*check_power_status)(struct hda_codec *codec, hda_nid_t nid);
|
|
|
|
#endif
|
2009-11-10 23:02:29 +08:00
|
|
|
void (*reboot_notify)(struct hda_codec *codec);
|
2005-04-17 06:20:36 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
/* record for amp information cache */
|
2007-08-10 22:59:39 +08:00
|
|
|
struct hda_cache_head {
|
2012-12-14 01:30:04 +08:00
|
|
|
u32 key:31; /* hash key */
|
|
|
|
u32 dirty:1;
|
2007-08-10 22:59:39 +08:00
|
|
|
u16 val; /* assigned value */
|
2012-12-14 01:30:04 +08:00
|
|
|
u16 next;
|
2007-08-10 22:59:39 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
struct hda_amp_info {
|
|
|
|
struct hda_cache_head head;
|
2005-04-17 06:20:36 +08:00
|
|
|
u32 amp_caps; /* amp capabilities */
|
2006-07-05 23:39:14 +08:00
|
|
|
u16 vol[2]; /* current volume & mute */
|
2007-08-10 22:59:39 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
struct hda_cache_rec {
|
|
|
|
u16 hash[64]; /* hash table for index */
|
2008-07-30 21:01:44 +08:00
|
|
|
struct snd_array buf; /* record entries */
|
2005-04-17 06:20:36 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
/* PCM callbacks */
|
|
|
|
struct hda_pcm_ops {
|
|
|
|
int (*open)(struct hda_pcm_stream *info, struct hda_codec *codec,
|
2005-11-17 21:57:47 +08:00
|
|
|
struct snd_pcm_substream *substream);
|
2005-04-17 06:20:36 +08:00
|
|
|
int (*close)(struct hda_pcm_stream *info, struct hda_codec *codec,
|
2005-11-17 21:57:47 +08:00
|
|
|
struct snd_pcm_substream *substream);
|
2005-04-17 06:20:36 +08:00
|
|
|
int (*prepare)(struct hda_pcm_stream *info, struct hda_codec *codec,
|
|
|
|
unsigned int stream_tag, unsigned int format,
|
2005-11-17 21:57:47 +08:00
|
|
|
struct snd_pcm_substream *substream);
|
2005-04-17 06:20:36 +08:00
|
|
|
int (*cleanup)(struct hda_pcm_stream *info, struct hda_codec *codec,
|
2005-11-17 21:57:47 +08:00
|
|
|
struct snd_pcm_substream *substream);
|
2013-04-05 13:27:45 +08:00
|
|
|
unsigned int (*get_delay)(struct hda_pcm_stream *info,
|
|
|
|
struct hda_codec *codec,
|
|
|
|
struct snd_pcm_substream *substream);
|
2005-04-17 06:20:36 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
/* PCM information for each substream */
|
|
|
|
struct hda_pcm_stream {
|
2007-07-27 22:52:19 +08:00
|
|
|
unsigned int substreams; /* number of substreams, 0 = not exist*/
|
2005-04-17 06:20:36 +08:00
|
|
|
unsigned int channels_min; /* min. number of channels */
|
|
|
|
unsigned int channels_max; /* max. number of channels */
|
|
|
|
hda_nid_t nid; /* default NID to query rates/formats/bps, or set up */
|
|
|
|
u32 rates; /* supported rates */
|
|
|
|
u64 formats; /* supported formats (SNDRV_PCM_FMTBIT_) */
|
|
|
|
unsigned int maxbps; /* supported max. bit per sample */
|
2012-11-09 00:12:10 +08:00
|
|
|
const struct snd_pcm_chmap_elem *chmap; /* chmap to override */
|
2005-04-17 06:20:36 +08:00
|
|
|
struct hda_pcm_ops ops;
|
|
|
|
};
|
|
|
|
|
[ALSA] hda-intel - Fix PCM device number assignment
In the current scheme, PCM device numbers are assigned incrementally
in the order of codecs. This causes problems when the codec number
is irregular, e.g. codec #0 for HDMI and codec #1 for analog. Then
the HDMI becomes the first PCM, which is picked up as the default
output device. Unfortuantely this doesn't work well with normal
setups.
This patch introduced the fixed device numbers for the PCM types,
namely, analog, SPDIF, HDMI and modem. The PCM devices are assigned
according to the corresponding PCM type. After this patch, HDMI will
be always assigned to PCM #3, SPDIF to PCM #1, and the first analog
to PCM #0, etc.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2008-02-06 21:03:20 +08:00
|
|
|
/* PCM types */
|
|
|
|
enum {
|
|
|
|
HDA_PCM_TYPE_AUDIO,
|
|
|
|
HDA_PCM_TYPE_SPDIF,
|
|
|
|
HDA_PCM_TYPE_HDMI,
|
|
|
|
HDA_PCM_TYPE_MODEM,
|
|
|
|
HDA_PCM_NTYPES
|
|
|
|
};
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
/* for PCM creation */
|
|
|
|
struct hda_pcm {
|
|
|
|
char *name;
|
|
|
|
struct hda_pcm_stream stream[2];
|
[ALSA] hda-intel - Fix PCM device number assignment
In the current scheme, PCM device numbers are assigned incrementally
in the order of codecs. This causes problems when the codec number
is irregular, e.g. codec #0 for HDMI and codec #1 for analog. Then
the HDMI becomes the first PCM, which is picked up as the default
output device. Unfortuantely this doesn't work well with normal
setups.
This patch introduced the fixed device numbers for the PCM types,
namely, analog, SPDIF, HDMI and modem. The PCM devices are assigned
according to the corresponding PCM type. After this patch, HDMI will
be always assigned to PCM #3, SPDIF to PCM #1, and the first analog
to PCM #0, etc.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2008-02-06 21:03:20 +08:00
|
|
|
unsigned int pcm_type; /* HDA_PCM_TYPE_XXX */
|
2008-07-30 21:01:44 +08:00
|
|
|
int device; /* device number to assign */
|
|
|
|
struct snd_pcm *pcm; /* assigned PCM instance */
|
2012-07-31 17:35:35 +08:00
|
|
|
bool own_chmap; /* codec driver provides own channel maps */
|
2005-04-17 06:20:36 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
/* codec information */
|
|
|
|
struct hda_codec {
|
2014-02-25 14:53:47 +08:00
|
|
|
struct device dev;
|
2005-04-17 06:20:36 +08:00
|
|
|
struct hda_bus *bus;
|
|
|
|
unsigned int addr; /* codec addr*/
|
|
|
|
struct list_head list; /* list point */
|
|
|
|
|
|
|
|
hda_nid_t afg; /* AFG node id */
|
2005-08-11 17:00:16 +08:00
|
|
|
hda_nid_t mfg; /* MFG node id */
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
/* ids */
|
2010-07-19 21:52:39 +08:00
|
|
|
u8 afg_function_id;
|
|
|
|
u8 mfg_function_id;
|
|
|
|
u8 afg_unsol;
|
|
|
|
u8 mfg_unsol;
|
2005-04-17 06:20:36 +08:00
|
|
|
u32 vendor_id;
|
|
|
|
u32 subsystem_id;
|
|
|
|
u32 revision_id;
|
|
|
|
|
|
|
|
/* detected preset */
|
|
|
|
const struct hda_codec_preset *preset;
|
2008-11-27 22:47:11 +08:00
|
|
|
struct module *owner;
|
2013-11-18 19:03:56 +08:00
|
|
|
int (*parser)(struct hda_codec *codec);
|
2009-05-16 16:00:49 +08:00
|
|
|
const char *vendor_name; /* codec vendor name */
|
|
|
|
const char *chip_name; /* codec chip name */
|
2008-07-30 21:01:45 +08:00
|
|
|
const char *modelname; /* model name for preset */
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
/* set by patch */
|
|
|
|
struct hda_codec_ops patch_ops;
|
|
|
|
|
|
|
|
/* PCM to create, set by patch_ops.build_pcms callback */
|
|
|
|
unsigned int num_pcms;
|
|
|
|
struct hda_pcm *pcm_info;
|
|
|
|
|
|
|
|
/* codec specific info */
|
|
|
|
void *spec;
|
|
|
|
|
2008-07-19 00:20:52 +08:00
|
|
|
/* beep device */
|
|
|
|
struct hda_beep *beep;
|
2009-11-14 01:41:52 +08:00
|
|
|
unsigned int beep_mode;
|
2008-07-19 00:20:52 +08:00
|
|
|
|
2005-11-21 23:33:22 +08:00
|
|
|
/* widget capabilities cache */
|
|
|
|
unsigned int num_nodes;
|
|
|
|
hda_nid_t start_nid;
|
|
|
|
u32 *wcaps;
|
|
|
|
|
2008-07-30 21:01:45 +08:00
|
|
|
struct snd_array mixers; /* list of assigned mixer elements */
|
2009-12-08 23:13:32 +08:00
|
|
|
struct snd_array nids; /* list of mapped mixer elements */
|
2008-07-30 21:01:45 +08:00
|
|
|
|
2007-08-10 22:59:39 +08:00
|
|
|
struct hda_cache_rec amp_cache; /* cache for amp access */
|
2007-08-10 23:03:40 +08:00
|
|
|
struct hda_cache_rec cmd_cache; /* cache for other commands */
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2013-01-03 22:25:11 +08:00
|
|
|
struct list_head conn_list; /* linked-list of connection-list */
|
2011-04-07 21:55:15 +08:00
|
|
|
|
2006-01-16 23:34:20 +08:00
|
|
|
struct mutex spdif_mutex;
|
2009-01-09 16:45:24 +08:00
|
|
|
struct mutex control_mutex;
|
2012-05-10 22:11:15 +08:00
|
|
|
struct mutex hash_mutex;
|
ALSA: hda: Allow multple SPDIF controls per codec
Currently, the data that backs the kcontrols created by
snd_hda_create_spdif_out_ctls is stored directly in struct hda_codec. When
multiple sets of these controls are stored, they will all manipulate the
same data, causing confusion. Instead, store an array of this data, one
copy per converter, to isolate the controls.
This patch would cause a behavioural change in the case where
snd_hda_create_spdif_out_ctls was called multiple times for a single codec.
As best I can tell, this is never the case for any codec.
This will be relevant at least for some HDMI audio codecs, such as the
NVIDIA GeForce 520 and Intel Ibex Peak. A future change will modify the
driver's handling of those codecs to create multiple PCMs per codec. Note
that this issue isn't affected by whether one creates a PCM-per-converter
or PCM-per-pin; there are multiple of both within a single codec in both
of those codecs.
Note that those codecs don't currently create multiple PCMs for the codec
due to the default HW mux state of all pins being to point at the same
converter, hence there is only a single converter routed to any pin, and
hence only a single PCM.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:17 +08:00
|
|
|
struct snd_array spdif_out;
|
2005-04-17 06:20:36 +08:00
|
|
|
unsigned int spdif_in_enable; /* SPDIF input enable? */
|
2011-05-02 17:29:30 +08:00
|
|
|
const hda_nid_t *slave_dig_outs; /* optional digital out slave widgets */
|
2009-02-20 21:11:16 +08:00
|
|
|
struct snd_array init_pins; /* initial (BIOS) pin configurations */
|
2009-02-23 16:42:57 +08:00
|
|
|
struct snd_array driver_pins; /* pin configs set by codec parser */
|
2010-08-06 19:48:11 +08:00
|
|
|
struct snd_array cvt_setups; /* audio convert setups */
|
2007-07-28 00:58:06 +08:00
|
|
|
|
2013-01-11 01:21:56 +08:00
|
|
|
struct mutex user_mutex;
|
2014-02-25 18:54:06 +08:00
|
|
|
#ifdef CONFIG_SND_HDA_RECONFIG
|
2008-07-30 21:01:46 +08:00
|
|
|
struct snd_array init_verbs; /* additional init verbs */
|
2008-07-30 21:01:46 +08:00
|
|
|
struct snd_array hints; /* additional hints */
|
2009-02-23 16:42:57 +08:00
|
|
|
struct snd_array user_pins; /* default pin configs to override */
|
2008-07-30 21:01:46 +08:00
|
|
|
#endif
|
2007-08-10 23:21:45 +08:00
|
|
|
|
2014-02-25 17:38:13 +08:00
|
|
|
#ifdef CONFIG_SND_HDA_HWDEP
|
|
|
|
struct snd_hwdep *hwdep; /* assigned hwdep device */
|
|
|
|
#endif
|
|
|
|
|
2008-08-11 16:04:40 +08:00
|
|
|
/* misc flags */
|
|
|
|
unsigned int spdif_status_reset :1; /* needs to toggle SPDIF for each
|
|
|
|
* status change
|
|
|
|
* (e.g. Realtek codecs)
|
|
|
|
*/
|
2009-03-13 00:06:07 +08:00
|
|
|
unsigned int pin_amp_workaround:1; /* pin out-amp takes index
|
|
|
|
* (e.g. Conexant codecs)
|
|
|
|
*/
|
2012-04-06 21:34:15 +08:00
|
|
|
unsigned int single_adc_amp:1; /* adc in-amp takes no index
|
|
|
|
* (e.g. CX20549 codec)
|
|
|
|
*/
|
2010-10-25 16:37:11 +08:00
|
|
|
unsigned int no_sticky_stream:1; /* no sticky-PCM stream assignment */
|
2010-07-05 22:50:13 +08:00
|
|
|
unsigned int pins_shutup:1; /* pins are shut up */
|
2009-12-26 05:49:01 +08:00
|
|
|
unsigned int no_trigger_sense:1; /* don't trigger at pin-sensing */
|
2012-02-13 18:55:02 +08:00
|
|
|
unsigned int no_jack_detect:1; /* Machine has no jack-detection */
|
2012-12-21 22:23:01 +08:00
|
|
|
unsigned int inv_eapd:1; /* broken h/w: inverted EAPD control */
|
2012-12-21 22:31:41 +08:00
|
|
|
unsigned int inv_jack_detect:1; /* broken h/w: inverted detection bit */
|
2012-08-08 23:12:52 +08:00
|
|
|
unsigned int pcm_format_first:1; /* PCM format must be set first */
|
2012-08-29 00:18:01 +08:00
|
|
|
unsigned int epss:1; /* supporting EPSS? */
|
2012-12-14 01:30:04 +08:00
|
|
|
unsigned int cached_write:1; /* write only to caches */
|
2013-08-27 09:35:21 +08:00
|
|
|
unsigned int dp_mst:1; /* support DP1.2 Multi-stream transport */
|
2014-01-29 17:37:10 +08:00
|
|
|
unsigned int dump_coef:1; /* dump processing coefs in codec proc file */
|
2012-08-25 00:38:08 +08:00
|
|
|
#ifdef CONFIG_PM
|
2007-08-16 22:35:33 +08:00
|
|
|
unsigned int power_on :1; /* current (global) power-state */
|
2012-08-29 07:39:25 +08:00
|
|
|
unsigned int d3_stop_clk:1; /* support D3 operation without BCLK */
|
2013-11-20 19:41:20 +08:00
|
|
|
unsigned int pm_up_notified:1; /* PM notified to controller */
|
2012-11-19 21:14:58 +08:00
|
|
|
unsigned int in_pm:1; /* suspend/resume being performed */
|
2012-05-09 18:36:22 +08:00
|
|
|
int power_transition; /* power-state in transition */
|
2007-08-10 23:21:45 +08:00
|
|
|
int power_count; /* current (global) power refcount */
|
|
|
|
struct delayed_work power_work; /* delayed task for powerdown */
|
2009-11-11 16:34:25 +08:00
|
|
|
unsigned long power_on_acct;
|
|
|
|
unsigned long power_off_acct;
|
|
|
|
unsigned long power_jiffies;
|
2012-05-08 23:08:10 +08:00
|
|
|
spinlock_t power_lock;
|
2007-08-10 23:21:45 +08:00
|
|
|
#endif
|
2008-11-28 19:55:36 +08:00
|
|
|
|
2013-01-25 00:23:35 +08:00
|
|
|
/* filter the requested power state per nid */
|
|
|
|
unsigned int (*power_filter)(struct hda_codec *codec, hda_nid_t nid,
|
|
|
|
unsigned int power_state);
|
|
|
|
|
2008-11-28 19:55:36 +08:00
|
|
|
/* codec-specific additional proc output */
|
|
|
|
void (*proc_widget_hook)(struct snd_info_buffer *buffer,
|
|
|
|
struct hda_codec *codec, hda_nid_t nid);
|
2011-03-03 21:40:14 +08:00
|
|
|
|
2011-10-28 04:12:46 +08:00
|
|
|
/* jack detection */
|
|
|
|
struct snd_array jacktbl;
|
2012-10-09 21:04:21 +08:00
|
|
|
unsigned long jackpoll_interval; /* In jiffies. Zero means no poll, rely on unsol events */
|
|
|
|
struct delayed_work jackpoll_work;
|
2011-10-28 04:12:46 +08:00
|
|
|
|
2011-03-03 21:40:14 +08:00
|
|
|
#ifdef CONFIG_SND_HDA_INPUT_JACK
|
|
|
|
/* jack detection */
|
|
|
|
struct snd_array jacks;
|
|
|
|
#endif
|
2012-12-19 01:12:44 +08:00
|
|
|
|
2013-11-29 14:48:45 +08:00
|
|
|
int depop_delay; /* depop delay in ms, -1 for default delay time */
|
|
|
|
|
2012-12-19 01:12:44 +08:00
|
|
|
/* fix-up list */
|
|
|
|
int fixup_id;
|
|
|
|
const struct hda_fixup *fixup_list;
|
|
|
|
const char *fixup_name;
|
|
|
|
|
|
|
|
/* additional init verbs */
|
|
|
|
struct snd_array verbs;
|
2005-04-17 06:20:36 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
/* direction */
|
|
|
|
enum {
|
|
|
|
HDA_INPUT, HDA_OUTPUT
|
|
|
|
};
|
|
|
|
|
2013-06-06 20:20:19 +08:00
|
|
|
/* snd_hda_codec_read/write optional flags */
|
|
|
|
#define HDA_RW_NO_RESPONSE_FALLBACK (1 << 0)
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* constructors
|
|
|
|
*/
|
2005-11-17 21:57:47 +08:00
|
|
|
int snd_hda_bus_new(struct snd_card *card, const struct hda_bus_template *temp,
|
2005-04-17 06:20:36 +08:00
|
|
|
struct hda_bus **busp);
|
|
|
|
int snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
|
2009-06-17 15:33:52 +08:00
|
|
|
struct hda_codec **codecp);
|
|
|
|
int snd_hda_codec_configure(struct hda_codec *codec);
|
2013-02-09 06:09:31 +08:00
|
|
|
int snd_hda_codec_update_widgets(struct hda_codec *codec);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* low level functions
|
|
|
|
*/
|
2007-07-27 22:52:19 +08:00
|
|
|
unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid,
|
2013-06-06 20:00:23 +08:00
|
|
|
int flags,
|
2005-04-17 06:20:36 +08:00
|
|
|
unsigned int verb, unsigned int parm);
|
2013-06-06 20:00:23 +08:00
|
|
|
int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int flags,
|
2005-04-17 06:20:36 +08:00
|
|
|
unsigned int verb, unsigned int parm);
|
2007-07-27 22:52:19 +08:00
|
|
|
#define snd_hda_param_read(codec, nid, param) \
|
|
|
|
snd_hda_codec_read(codec, nid, 0, AC_VERB_PARAMETERS, param)
|
|
|
|
int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid,
|
|
|
|
hda_nid_t *start_id);
|
|
|
|
int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
|
|
|
|
hda_nid_t *conn_list, int max_conns);
|
2012-05-19 23:21:25 +08:00
|
|
|
static inline int
|
|
|
|
snd_hda_get_num_conns(struct hda_codec *codec, hda_nid_t nid)
|
|
|
|
{
|
|
|
|
return snd_hda_get_connections(codec, nid, NULL, 0);
|
|
|
|
}
|
ALSA: hda - Remove limit of widget connections
Currently we set the max number of connections to be 32, but there
seems codec that gives longer connection lists like AD1988, and we see
errors in proc output and else. (Though, in the case of AD1988, it's
a list of all codecs connected to a single vendor widget, so this must
be something fishy, but it's still valid from the h/w design POV.)
This patch tries to remove this restriction. For efficiency, we still
use the fixed size array in the parser, but takes a dynamic array when
the size is reported to be greater than that.
Now the fixed array size is found only in patch_hdmi.c, but it should
be fine, as the codec itself can't support so many pins.
Reported-by: Raymond Yau <superquad.vortex2@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2013-02-08 01:18:19 +08:00
|
|
|
int snd_hda_get_num_raw_conns(struct hda_codec *codec, hda_nid_t nid);
|
2011-07-11 21:42:52 +08:00
|
|
|
int snd_hda_get_raw_connections(struct hda_codec *codec, hda_nid_t nid,
|
|
|
|
hda_nid_t *conn_list, int max_conns);
|
2013-01-03 22:25:11 +08:00
|
|
|
int snd_hda_get_conn_list(struct hda_codec *codec, hda_nid_t nid,
|
|
|
|
const hda_nid_t **listp);
|
2011-07-04 22:23:26 +08:00
|
|
|
int snd_hda_override_conn_list(struct hda_codec *codec, hda_nid_t nid, int nums,
|
|
|
|
const hda_nid_t *list);
|
2011-06-28 18:45:47 +08:00
|
|
|
int snd_hda_get_conn_index(struct hda_codec *codec, hda_nid_t mux,
|
|
|
|
hda_nid_t nid, int recursive);
|
2013-08-27 09:35:21 +08:00
|
|
|
int snd_hda_get_devices(struct hda_codec *codec, hda_nid_t nid,
|
|
|
|
u8 *dev_list, int max_devices);
|
ALSA: hda: HDMI: Support codecs with fewer cvts than pins
The general concept of this change is to create a PCM device for each
pin widget instead of each converter widget. Whenever a PCM is opened,
a converter is dynamically selected to drive that pin based on those
available for muxing into the pin.
The one thing this model doesn't support is a single PCM/converter
sending audio to multiple pin widgets at once.
Note that this means that a struct hda_pcm_stream's nid variable is
set to 0 except between a stream's open and cleanup calls. The dynamic
de-assignment of converters to PCMs occurs within cleanup, not close,
in order for it to co-incide with when controller stream IDs are
cleaned up from converters.
While the PCM for a pin is not open, the pin is disabled (its widget
control's PIN_OUT bit is cleared) so that if the currently routed
converter is used to drive a different PCM/pin, that audio does not
leak out over a disabled pin.
We use the recently added SPDIF virtualization feature in order to
create SPDIF controls for each pin widget instead of each converter
widget, so that state is specific to a PCM.
In order to support this, a number of more mechanical changes are made:
* s/nid/pin_nid/ or s/nid/cvt_nid/ in many places in order to make it
clear exactly what the code is dealing with.
* We now have per_pin and per_cvt arrays in hdmi_spec to store relevant
data. In particular, we store a converter's capabilities in the per_cvt
entry, rather than relying on a combination of codec_pcm_pars and
the struct hda_pcm_stream.
* ELD-related workarounds were removed from hdmi_channel_allocation
into hdmi_instrinsic in order to simplifiy infoframe calculations and
remove HW dependencies.
* Various functions only apply to a single pin, since there is now
only 1 pin per PCM. For example, hdmi_setup_infoframe,
hdmi_setup_stream.
* hdmi_add_pin and hdmi_add_cvt are more oriented at pure codec parsing
and data retrieval, rather than determining which pins/converters
are to be used for creating PCMs.
This is quite a large change; it may be appropriate to simply read the
result of the patch rather than the diffs. Some small parts of the change
might be separable into different patches, but I think the bulk of the
change will probably always be one large patch. Hopefully the change
isn't too opaque!
This has been tested on:
* NVIDIA GeForce 400 series discrete graphics card. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM
audio to a PC monitor that supports audio.
* NVIDIA GeForce 520 discrete graphics card. This model is the new
1 codec n converters m pins m>n model. Tested stereo PCM audio to a
PC monitor that supports audio.
* NVIDIA GeForce 400 series laptop graphics chip. This model has the
classical 1:1:1 codec:converter:pcm widget model. Tested stereo PCM,
multi-channel PCM, and AC3 pass-through to an AV receiver.
* Intel Ibex Peak laptop. This model is the new 1 codec n converters m
pins m>n model. Tested stereo PCM, multi-channel PCM, and AC3 pass-
through to an AV receiver.
Note that I'm not familiar at all with AC3 pass-through. Hence, I may
not have covered all possible mechanisms that are applicable here. I do
know that my receiver definitely received AC3, not decoded PCM. I tested
with mplayer's "-afm hwac3" and/or "-af lavcac3enc" options, and alsa a
WAV file that I believe has AC3 content rather than PCM.
I also tested:
* Play a stream
* Mute while playing
* Stop stream
* Play some other streams to re-assign the converter to a different
pin, PCM, set of SPDIF controls, ... hence hopefully triggering
cleanup for the original PCM.
* Unmute original stream while not playing
* Play a stream on the original pin/PCM.
This was to test SPDIF control virtualization.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:21 +08:00
|
|
|
int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
|
|
|
|
u32 *ratesp, u64 *formatsp, unsigned int *bpsp);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
struct hda_verb {
|
|
|
|
hda_nid_t nid;
|
|
|
|
u32 verb;
|
|
|
|
u32 param;
|
|
|
|
};
|
|
|
|
|
2007-07-27 22:52:19 +08:00
|
|
|
void snd_hda_sequence_write(struct hda_codec *codec,
|
|
|
|
const struct hda_verb *seq);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
/* unsolicited event */
|
|
|
|
int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex);
|
|
|
|
|
2007-08-10 23:03:40 +08:00
|
|
|
/* cached write */
|
|
|
|
int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
|
2013-06-06 20:00:23 +08:00
|
|
|
int flags, unsigned int verb, unsigned int parm);
|
2007-08-10 23:03:40 +08:00
|
|
|
void snd_hda_sequence_write_cache(struct hda_codec *codec,
|
|
|
|
const struct hda_verb *seq);
|
2010-03-31 00:03:44 +08:00
|
|
|
int snd_hda_codec_update_cache(struct hda_codec *codec, hda_nid_t nid,
|
2013-06-06 20:00:23 +08:00
|
|
|
int flags, unsigned int verb, unsigned int parm);
|
2007-08-10 23:03:40 +08:00
|
|
|
void snd_hda_codec_resume_cache(struct hda_codec *codec);
|
2013-01-22 22:24:30 +08:00
|
|
|
/* both for cmd & amp caches */
|
|
|
|
void snd_hda_codec_flush_cache(struct hda_codec *codec);
|
2012-12-20 18:41:54 +08:00
|
|
|
|
2009-02-20 21:11:16 +08:00
|
|
|
/* the struct for codec->pin_configs */
|
|
|
|
struct hda_pincfg {
|
|
|
|
hda_nid_t nid;
|
2013-01-10 15:38:04 +08:00
|
|
|
unsigned char ctrl; /* original pin control value */
|
|
|
|
unsigned char target; /* target pin control value */
|
2010-07-05 22:50:13 +08:00
|
|
|
unsigned int cfg; /* default configuration */
|
2009-02-20 21:11:16 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
unsigned int snd_hda_codec_get_pincfg(struct hda_codec *codec, hda_nid_t nid);
|
|
|
|
int snd_hda_codec_set_pincfg(struct hda_codec *codec, hda_nid_t nid,
|
|
|
|
unsigned int cfg);
|
|
|
|
int snd_hda_add_pincfg(struct hda_codec *codec, struct snd_array *list,
|
|
|
|
hda_nid_t nid, unsigned int cfg); /* for hwdep */
|
2009-12-27 18:18:59 +08:00
|
|
|
void snd_hda_shutup_pins(struct hda_codec *codec);
|
2009-02-20 21:11:16 +08:00
|
|
|
|
ALSA: hda: Allow multple SPDIF controls per codec
Currently, the data that backs the kcontrols created by
snd_hda_create_spdif_out_ctls is stored directly in struct hda_codec. When
multiple sets of these controls are stored, they will all manipulate the
same data, causing confusion. Instead, store an array of this data, one
copy per converter, to isolate the controls.
This patch would cause a behavioural change in the case where
snd_hda_create_spdif_out_ctls was called multiple times for a single codec.
As best I can tell, this is never the case for any codec.
This will be relevant at least for some HDMI audio codecs, such as the
NVIDIA GeForce 520 and Intel Ibex Peak. A future change will modify the
driver's handling of those codecs to create multiple PCMs per codec. Note
that this issue isn't affected by whether one creates a PCM-per-converter
or PCM-per-pin; there are multiple of both within a single codec in both
of those codecs.
Note that those codecs don't currently create multiple PCMs for the codec
due to the default HW mux state of all pins being to point at the same
converter, hence there is only a single converter routed to any pin, and
hence only a single PCM.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:17 +08:00
|
|
|
/* SPDIF controls */
|
|
|
|
struct hda_spdif_out {
|
|
|
|
hda_nid_t nid; /* Converter nid values relate to */
|
|
|
|
unsigned int status; /* IEC958 status bits */
|
|
|
|
unsigned short ctls; /* SPDIF control bits */
|
|
|
|
};
|
|
|
|
struct hda_spdif_out *snd_hda_spdif_out_of_nid(struct hda_codec *codec,
|
|
|
|
hda_nid_t nid);
|
2011-06-02 01:14:18 +08:00
|
|
|
void snd_hda_spdif_ctls_unassign(struct hda_codec *codec, int idx);
|
|
|
|
void snd_hda_spdif_ctls_assign(struct hda_codec *codec, int idx, hda_nid_t nid);
|
ALSA: hda: Allow multple SPDIF controls per codec
Currently, the data that backs the kcontrols created by
snd_hda_create_spdif_out_ctls is stored directly in struct hda_codec. When
multiple sets of these controls are stored, they will all manipulate the
same data, causing confusion. Instead, store an array of this data, one
copy per converter, to isolate the controls.
This patch would cause a behavioural change in the case where
snd_hda_create_spdif_out_ctls was called multiple times for a single codec.
As best I can tell, this is never the case for any codec.
This will be relevant at least for some HDMI audio codecs, such as the
NVIDIA GeForce 520 and Intel Ibex Peak. A future change will modify the
driver's handling of those codecs to create multiple PCMs per codec. Note
that this issue isn't affected by whether one creates a PCM-per-converter
or PCM-per-pin; there are multiple of both within a single codec in both
of those codecs.
Note that those codecs don't currently create multiple PCMs for the codec
due to the default HW mux state of all pins being to point at the same
converter, hence there is only a single converter routed to any pin, and
hence only a single PCM.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2011-06-02 01:14:17 +08:00
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
/*
|
|
|
|
* Mixer
|
|
|
|
*/
|
|
|
|
int snd_hda_build_controls(struct hda_bus *bus);
|
2008-07-30 21:01:45 +08:00
|
|
|
int snd_hda_codec_build_controls(struct hda_codec *codec);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* PCM
|
|
|
|
*/
|
|
|
|
int snd_hda_build_pcms(struct hda_bus *bus);
|
2008-11-27 21:17:01 +08:00
|
|
|
int snd_hda_codec_build_pcms(struct hda_codec *codec);
|
2010-08-06 19:48:11 +08:00
|
|
|
|
|
|
|
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);
|
|
|
|
|
2007-07-27 22:52:19 +08:00
|
|
|
void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
|
|
|
|
u32 stream_tag,
|
2005-04-17 06:20:36 +08:00
|
|
|
int channel_id, int format);
|
2010-08-13 17:56:53 +08:00
|
|
|
void __snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid,
|
|
|
|
int do_now);
|
|
|
|
#define snd_hda_codec_cleanup_stream(codec, nid) \
|
|
|
|
__snd_hda_codec_cleanup_stream(codec, nid, 0)
|
2007-07-27 22:52:19 +08:00
|
|
|
unsigned int snd_hda_calc_stream_format(unsigned int rate,
|
|
|
|
unsigned int channels,
|
|
|
|
unsigned int format,
|
2010-08-03 18:28:57 +08:00
|
|
|
unsigned int maxbps,
|
|
|
|
unsigned short spdif_ctls);
|
2005-04-17 06:20:36 +08:00
|
|
|
int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid,
|
|
|
|
unsigned int format);
|
|
|
|
|
2012-11-09 00:12:10 +08:00
|
|
|
extern const struct snd_pcm_chmap_elem snd_pcm_2_1_chmaps[];
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
/*
|
|
|
|
* Misc
|
|
|
|
*/
|
|
|
|
void snd_hda_get_codec_name(struct hda_codec *codec, char *name, int namelen);
|
2009-11-10 23:02:29 +08:00
|
|
|
void snd_hda_bus_reboot_notify(struct hda_bus *bus);
|
2011-07-26 16:33:10 +08:00
|
|
|
void snd_hda_codec_set_power_to_all(struct hda_codec *codec, hda_nid_t fg,
|
2013-01-25 00:23:35 +08:00
|
|
|
unsigned int power_state);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2012-04-26 18:11:44 +08:00
|
|
|
int snd_hda_lock_devices(struct hda_bus *bus);
|
|
|
|
void snd_hda_unlock_devices(struct hda_bus *bus);
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
/*
|
|
|
|
* power management
|
|
|
|
*/
|
|
|
|
#ifdef CONFIG_PM
|
2009-06-02 07:16:07 +08:00
|
|
|
int snd_hda_suspend(struct hda_bus *bus);
|
2005-04-17 06:20:36 +08:00
|
|
|
int snd_hda_resume(struct hda_bus *bus);
|
|
|
|
#endif
|
|
|
|
|
2010-09-21 15:57:06 +08:00
|
|
|
static inline
|
|
|
|
int hda_call_check_power_status(struct hda_codec *codec, hda_nid_t nid)
|
|
|
|
{
|
2012-08-25 00:38:08 +08:00
|
|
|
#ifdef CONFIG_PM
|
2010-09-21 15:57:06 +08:00
|
|
|
if (codec->patch_ops.check_power_status)
|
|
|
|
return codec->patch_ops.check_power_status(codec, nid);
|
2011-06-28 14:59:30 +08:00
|
|
|
#endif
|
2010-09-21 15:57:06 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2008-10-25 13:05:45 +08:00
|
|
|
/*
|
|
|
|
* get widget information
|
|
|
|
*/
|
|
|
|
const char *snd_hda_get_jack_connectivity(u32 cfg);
|
|
|
|
const char *snd_hda_get_jack_type(u32 cfg);
|
|
|
|
const char *snd_hda_get_jack_location(u32 cfg);
|
|
|
|
|
2007-08-10 23:21:45 +08:00
|
|
|
/*
|
|
|
|
* power saving
|
|
|
|
*/
|
2012-08-25 00:38:08 +08:00
|
|
|
#ifdef CONFIG_PM
|
2012-08-14 23:12:47 +08:00
|
|
|
void snd_hda_power_save(struct hda_codec *codec, int delta, bool d3wait);
|
2009-11-11 16:34:25 +08:00
|
|
|
void snd_hda_update_power_acct(struct hda_codec *codec);
|
2007-08-10 23:21:45 +08:00
|
|
|
#else
|
2012-08-14 23:12:47 +08:00
|
|
|
static inline void snd_hda_power_save(struct hda_codec *codec, int delta,
|
|
|
|
bool d3wait) {}
|
2007-08-10 23:21:45 +08:00
|
|
|
#endif
|
|
|
|
|
2012-08-14 23:12:47 +08:00
|
|
|
/**
|
|
|
|
* snd_hda_power_up - Power-up the codec
|
|
|
|
* @codec: HD-audio codec
|
|
|
|
*
|
|
|
|
* Increment the power-up counter and power up the hardware really when
|
|
|
|
* not turned on yet.
|
|
|
|
*/
|
|
|
|
static inline void snd_hda_power_up(struct hda_codec *codec)
|
|
|
|
{
|
|
|
|
snd_hda_power_save(codec, 1, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* snd_hda_power_up_d3wait - Power-up the codec after waiting for any pending
|
|
|
|
* D3 transition to complete. This differs from snd_hda_power_up() when
|
|
|
|
* power_transition == -1. snd_hda_power_up sees this case as a nop,
|
|
|
|
* snd_hda_power_up_d3wait waits for the D3 transition to complete then powers
|
|
|
|
* back up.
|
|
|
|
* @codec: HD-audio codec
|
|
|
|
*
|
|
|
|
* Cancel any power down operation hapenning on the work queue, then power up.
|
|
|
|
*/
|
|
|
|
static inline void snd_hda_power_up_d3wait(struct hda_codec *codec)
|
|
|
|
{
|
|
|
|
snd_hda_power_save(codec, 1, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* snd_hda_power_down - Power-down the codec
|
|
|
|
* @codec: HD-audio codec
|
|
|
|
*
|
|
|
|
* Decrement the power-up counter and schedules the power-off work if
|
|
|
|
* the counter rearches to zero.
|
|
|
|
*/
|
|
|
|
static inline void snd_hda_power_down(struct hda_codec *codec)
|
|
|
|
{
|
|
|
|
snd_hda_power_save(codec, -1, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* snd_hda_power_sync - Synchronize the power-save status
|
|
|
|
* @codec: HD-audio codec
|
|
|
|
*
|
|
|
|
* Synchronize the actual power state with the power account;
|
|
|
|
* called when power_save parameter is changed
|
|
|
|
*/
|
|
|
|
static inline void snd_hda_power_sync(struct hda_codec *codec)
|
|
|
|
{
|
|
|
|
snd_hda_power_save(codec, 0, false);
|
|
|
|
}
|
|
|
|
|
2009-06-17 15:52:54 +08:00
|
|
|
#ifdef CONFIG_SND_HDA_PATCH_LOADER
|
|
|
|
/*
|
|
|
|
* patch firmware
|
|
|
|
*/
|
2012-08-09 18:33:28 +08:00
|
|
|
int snd_hda_load_patch(struct hda_bus *bus, size_t size, const void *buf);
|
2009-06-17 15:52:54 +08:00
|
|
|
#endif
|
|
|
|
|
2012-09-21 11:29:13 +08:00
|
|
|
#ifdef CONFIG_SND_HDA_DSP_LOADER
|
|
|
|
static inline int
|
|
|
|
snd_hda_codec_load_dsp_prepare(struct hda_codec *codec, unsigned int format,
|
|
|
|
unsigned int size,
|
|
|
|
struct snd_dma_buffer *bufp)
|
|
|
|
{
|
|
|
|
return codec->bus->ops.load_dsp_prepare(codec->bus, format, size, bufp);
|
|
|
|
}
|
|
|
|
static inline void
|
|
|
|
snd_hda_codec_load_dsp_trigger(struct hda_codec *codec, bool start)
|
|
|
|
{
|
|
|
|
return codec->bus->ops.load_dsp_trigger(codec->bus, start);
|
|
|
|
}
|
|
|
|
static inline void
|
|
|
|
snd_hda_codec_load_dsp_cleanup(struct hda_codec *codec,
|
|
|
|
struct snd_dma_buffer *dmab)
|
|
|
|
{
|
|
|
|
return codec->bus->ops.load_dsp_cleanup(codec->bus, dmab);
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
static inline int
|
|
|
|
snd_hda_codec_load_dsp_prepare(struct hda_codec *codec, unsigned int format,
|
|
|
|
unsigned int size,
|
|
|
|
struct snd_dma_buffer *bufp)
|
|
|
|
{
|
2012-09-21 11:29:19 +08:00
|
|
|
return -ENOSYS;
|
2012-09-21 11:29:13 +08:00
|
|
|
}
|
|
|
|
static inline void
|
|
|
|
snd_hda_codec_load_dsp_trigger(struct hda_codec *codec, bool start) {}
|
|
|
|
static inline void
|
|
|
|
snd_hda_codec_load_dsp_cleanup(struct hda_codec *codec,
|
|
|
|
struct snd_dma_buffer *dmab) {}
|
|
|
|
#endif
|
|
|
|
|
2008-11-28 22:17:06 +08:00
|
|
|
#define EXPORT_SYMBOL_HDA(sym) EXPORT_SYMBOL_GPL(sym)
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
#endif /* __SOUND_HDA_CODEC_H */
|