|
@@ -30,6 +30,7 @@
|
|
|
#include <sound/tlv.h>
|
|
#include <sound/tlv.h>
|
|
|
#include <sound/initval.h>
|
|
#include <sound/initval.h>
|
|
|
#include "hda_local.h"
|
|
#include "hda_local.h"
|
|
|
|
|
+#include "hda_beep.h"
|
|
|
#include <sound/hda_hwdep.h>
|
|
#include <sound/hda_hwdep.h>
|
|
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -93,6 +94,13 @@ static void hda_keep_power_on(struct hda_codec *codec);
|
|
|
static inline void hda_keep_power_on(struct hda_codec *codec) {}
|
|
static inline void hda_keep_power_on(struct hda_codec *codec) {}
|
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * snd_hda_get_jack_location - Give a location string of the jack
|
|
|
|
|
+ * @cfg: pin default config value
|
|
|
|
|
+ *
|
|
|
|
|
+ * Parse the pin default config value and returns the string of the
|
|
|
|
|
+ * jack location, e.g. "Rear", "Front", etc.
|
|
|
|
|
+ */
|
|
|
const char *snd_hda_get_jack_location(u32 cfg)
|
|
const char *snd_hda_get_jack_location(u32 cfg)
|
|
|
{
|
|
{
|
|
|
static char *bases[7] = {
|
|
static char *bases[7] = {
|
|
@@ -120,6 +128,13 @@ const char *snd_hda_get_jack_location(u32 cfg)
|
|
|
}
|
|
}
|
|
|
EXPORT_SYMBOL_HDA(snd_hda_get_jack_location);
|
|
EXPORT_SYMBOL_HDA(snd_hda_get_jack_location);
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * snd_hda_get_jack_connectivity - Give a connectivity string of the jack
|
|
|
|
|
+ * @cfg: pin default config value
|
|
|
|
|
+ *
|
|
|
|
|
+ * Parse the pin default config value and returns the string of the
|
|
|
|
|
+ * jack connectivity, i.e. external or internal connection.
|
|
|
|
|
+ */
|
|
|
const char *snd_hda_get_jack_connectivity(u32 cfg)
|
|
const char *snd_hda_get_jack_connectivity(u32 cfg)
|
|
|
{
|
|
{
|
|
|
static char *jack_locations[4] = { "Ext", "Int", "Sep", "Oth" };
|
|
static char *jack_locations[4] = { "Ext", "Int", "Sep", "Oth" };
|
|
@@ -128,6 +143,13 @@ const char *snd_hda_get_jack_connectivity(u32 cfg)
|
|
|
}
|
|
}
|
|
|
EXPORT_SYMBOL_HDA(snd_hda_get_jack_connectivity);
|
|
EXPORT_SYMBOL_HDA(snd_hda_get_jack_connectivity);
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * snd_hda_get_jack_type - Give a type string of the jack
|
|
|
|
|
+ * @cfg: pin default config value
|
|
|
|
|
+ *
|
|
|
|
|
+ * Parse the pin default config value and returns the string of the
|
|
|
|
|
+ * jack type, i.e. the purpose of the jack, such as Line-Out or CD.
|
|
|
|
|
+ */
|
|
|
const char *snd_hda_get_jack_type(u32 cfg)
|
|
const char *snd_hda_get_jack_type(u32 cfg)
|
|
|
{
|
|
{
|
|
|
static char *jack_types[16] = {
|
|
static char *jack_types[16] = {
|
|
@@ -515,6 +537,7 @@ static int snd_hda_bus_dev_register(struct snd_device *device)
|
|
|
struct hda_codec *codec;
|
|
struct hda_codec *codec;
|
|
|
list_for_each_entry(codec, &bus->codec_list, list) {
|
|
list_for_each_entry(codec, &bus->codec_list, list) {
|
|
|
snd_hda_hwdep_add_sysfs(codec);
|
|
snd_hda_hwdep_add_sysfs(codec);
|
|
|
|
|
+ snd_hda_hwdep_add_power_sysfs(codec);
|
|
|
}
|
|
}
|
|
|
return 0;
|
|
return 0;
|
|
|
}
|
|
}
|
|
@@ -820,6 +843,16 @@ int snd_hda_add_pincfg(struct hda_codec *codec, struct snd_array *list,
|
|
|
return 0;
|
|
return 0;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * snd_hda_codec_set_pincfg - Override a pin default configuration
|
|
|
|
|
+ * @codec: the HDA codec
|
|
|
|
|
+ * @nid: NID to set the pin config
|
|
|
|
|
+ * @cfg: the pin default config value
|
|
|
|
|
+ *
|
|
|
|
|
+ * Override a pin default configuration value in the cache.
|
|
|
|
|
+ * This value can be read by snd_hda_codec_get_pincfg() in a higher
|
|
|
|
|
+ * priority than the real hardware value.
|
|
|
|
|
+ */
|
|
|
int snd_hda_codec_set_pincfg(struct hda_codec *codec,
|
|
int snd_hda_codec_set_pincfg(struct hda_codec *codec,
|
|
|
hda_nid_t nid, unsigned int cfg)
|
|
hda_nid_t nid, unsigned int cfg)
|
|
|
{
|
|
{
|
|
@@ -827,7 +860,15 @@ int snd_hda_codec_set_pincfg(struct hda_codec *codec,
|
|
|
}
|
|
}
|
|
|
EXPORT_SYMBOL_HDA(snd_hda_codec_set_pincfg);
|
|
EXPORT_SYMBOL_HDA(snd_hda_codec_set_pincfg);
|
|
|
|
|
|
|
|
-/* get the current pin config value of the given pin NID */
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * snd_hda_codec_get_pincfg - Obtain a pin-default configuration
|
|
|
|
|
+ * @codec: the HDA codec
|
|
|
|
|
+ * @nid: NID to get the pin config
|
|
|
|
|
+ *
|
|
|
|
|
+ * Get the current pin config value of the given pin NID.
|
|
|
|
|
+ * If the pincfg value is cached or overridden via sysfs or driver,
|
|
|
|
|
+ * returns the cached value.
|
|
|
|
|
+ */
|
|
|
unsigned int snd_hda_codec_get_pincfg(struct hda_codec *codec, hda_nid_t nid)
|
|
unsigned int snd_hda_codec_get_pincfg(struct hda_codec *codec, hda_nid_t nid)
|
|
|
{
|
|
{
|
|
|
struct hda_pincfg *pin;
|
|
struct hda_pincfg *pin;
|
|
@@ -944,7 +985,7 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr
|
|
|
mutex_init(&codec->control_mutex);
|
|
mutex_init(&codec->control_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 snd_kcontrol *), 32);
|
|
|
|
|
|
|
+ snd_array_init(&codec->mixers, sizeof(struct hda_nid_item), 60);
|
|
|
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);
|
|
|
if (codec->bus->modelname) {
|
|
if (codec->bus->modelname) {
|
|
@@ -1026,6 +1067,15 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr
|
|
|
}
|
|
}
|
|
|
EXPORT_SYMBOL_HDA(snd_hda_codec_new);
|
|
EXPORT_SYMBOL_HDA(snd_hda_codec_new);
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * snd_hda_codec_configure - (Re-)configure the HD-audio codec
|
|
|
|
|
+ * @codec: the HDA codec
|
|
|
|
|
+ *
|
|
|
|
|
+ * Start parsing of the given codec tree and (re-)initialize the whole
|
|
|
|
|
+ * patch instance.
|
|
|
|
|
+ *
|
|
|
|
|
+ * Returns 0 if successful or a negative error code.
|
|
|
|
|
+ */
|
|
|
int snd_hda_codec_configure(struct hda_codec *codec)
|
|
int snd_hda_codec_configure(struct hda_codec *codec)
|
|
|
{
|
|
{
|
|
|
int err;
|
|
int err;
|
|
@@ -1088,6 +1138,11 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
|
|
|
}
|
|
}
|
|
|
EXPORT_SYMBOL_HDA(snd_hda_codec_setup_stream);
|
|
EXPORT_SYMBOL_HDA(snd_hda_codec_setup_stream);
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * snd_hda_codec_cleanup_stream - clean up the codec for closing
|
|
|
|
|
+ * @codec: the CODEC to clean up
|
|
|
|
|
+ * @nid: the NID to clean up
|
|
|
|
|
+ */
|
|
|
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)
|
|
|
{
|
|
{
|
|
|
if (!nid)
|
|
if (!nid)
|
|
@@ -1163,8 +1218,17 @@ get_alloc_amp_hash(struct hda_codec *codec, u32 key)
|
|
|
return (struct hda_amp_info *)get_alloc_hash(&codec->amp_cache, key);
|
|
return (struct hda_amp_info *)get_alloc_hash(&codec->amp_cache, key);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-/*
|
|
|
|
|
- * query AMP capabilities for the given widget and direction
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * query_amp_caps - query AMP capabilities
|
|
|
|
|
+ * @codec: the HD-auio codec
|
|
|
|
|
+ * @nid: the NID to query
|
|
|
|
|
+ * @direction: either #HDA_INPUT or #HDA_OUTPUT
|
|
|
|
|
+ *
|
|
|
|
|
+ * Query AMP capabilities for the given widget and direction.
|
|
|
|
|
+ * Returns the obtained capability bits.
|
|
|
|
|
+ *
|
|
|
|
|
+ * When cap bits have been already read, this doesn't read again but
|
|
|
|
|
+ * returns the cached value.
|
|
|
*/
|
|
*/
|
|
|
u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction)
|
|
u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction)
|
|
|
{
|
|
{
|
|
@@ -1187,6 +1251,19 @@ u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction)
|
|
|
}
|
|
}
|
|
|
EXPORT_SYMBOL_HDA(query_amp_caps);
|
|
EXPORT_SYMBOL_HDA(query_amp_caps);
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * snd_hda_override_amp_caps - Override the AMP capabilities
|
|
|
|
|
+ * @codec: the CODEC to clean up
|
|
|
|
|
+ * @nid: the NID to clean up
|
|
|
|
|
+ * @direction: either #HDA_INPUT or #HDA_OUTPUT
|
|
|
|
|
+ * @caps: the capability bits to set
|
|
|
|
|
+ *
|
|
|
|
|
+ * Override the cached AMP caps bits value by the given one.
|
|
|
|
|
+ * This function is useful if the driver needs to adjust the AMP ranges,
|
|
|
|
|
+ * e.g. limit to 0dB, etc.
|
|
|
|
|
+ *
|
|
|
|
|
+ * Returns zero if successful or a negative error code.
|
|
|
|
|
+ */
|
|
|
int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
|
|
int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
|
|
|
unsigned int caps)
|
|
unsigned int caps)
|
|
|
{
|
|
{
|
|
@@ -1222,6 +1299,17 @@ static unsigned int read_pin_cap(struct hda_codec *codec, hda_nid_t nid)
|
|
|
return snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
|
|
return snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * snd_hda_query_pin_caps - Query PIN capabilities
|
|
|
|
|
+ * @codec: the HD-auio codec
|
|
|
|
|
+ * @nid: the NID to query
|
|
|
|
|
+ *
|
|
|
|
|
+ * Query PIN capabilities for the given widget.
|
|
|
|
|
+ * Returns the obtained capability bits.
|
|
|
|
|
+ *
|
|
|
|
|
+ * When cap bits have been already read, this doesn't read again but
|
|
|
|
|
+ * returns the cached value.
|
|
|
|
|
+ */
|
|
|
u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid)
|
|
u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid)
|
|
|
{
|
|
{
|
|
|
return query_caps_hash(codec, nid, HDA_HASH_PINCAP_KEY(nid),
|
|
return query_caps_hash(codec, nid, HDA_HASH_PINCAP_KEY(nid),
|
|
@@ -1229,6 +1317,40 @@ u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid)
|
|
|
}
|
|
}
|
|
|
EXPORT_SYMBOL_HDA(snd_hda_query_pin_caps);
|
|
EXPORT_SYMBOL_HDA(snd_hda_query_pin_caps);
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * snd_hda_pin_sense - execute pin sense measurement
|
|
|
|
|
+ * @codec: the CODEC to sense
|
|
|
|
|
+ * @nid: the pin NID to sense
|
|
|
|
|
+ *
|
|
|
|
|
+ * Execute necessary pin sense measurement and return its Presence Detect,
|
|
|
|
|
+ * Impedance, ELD Valid etc. status bits.
|
|
|
|
|
+ */
|
|
|
|
|
+u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid)
|
|
|
|
|
+{
|
|
|
|
|
+ u32 pincap = snd_hda_query_pin_caps(codec, nid);
|
|
|
|
|
+
|
|
|
|
|
+ if (pincap & AC_PINCAP_TRIG_REQ) /* need trigger? */
|
|
|
|
|
+ snd_hda_codec_read(codec, nid, 0, AC_VERB_SET_PIN_SENSE, 0);
|
|
|
|
|
+
|
|
|
|
|
+ return snd_hda_codec_read(codec, nid, 0,
|
|
|
|
|
+ AC_VERB_GET_PIN_SENSE, 0);
|
|
|
|
|
+}
|
|
|
|
|
+EXPORT_SYMBOL_HDA(snd_hda_pin_sense);
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * snd_hda_jack_detect - query pin Presence Detect status
|
|
|
|
|
+ * @codec: the CODEC to sense
|
|
|
|
|
+ * @nid: the pin NID to sense
|
|
|
|
|
+ *
|
|
|
|
|
+ * Query and return the pin's Presence Detect status.
|
|
|
|
|
+ */
|
|
|
|
|
+int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid)
|
|
|
|
|
+{
|
|
|
|
|
+ u32 sense = snd_hda_pin_sense(codec, nid);
|
|
|
|
|
+ return !!(sense & AC_PINSENSE_PRESENCE);
|
|
|
|
|
+}
|
|
|
|
|
+EXPORT_SYMBOL_HDA(snd_hda_jack_detect);
|
|
|
|
|
+
|
|
|
/*
|
|
/*
|
|
|
* read the current volume to info
|
|
* read the current volume to info
|
|
|
* if the cache exists, read the cache value.
|
|
* if the cache exists, read the cache value.
|
|
@@ -1269,8 +1391,15 @@ static void put_vol_mute(struct hda_codec *codec, struct hda_amp_info *info,
|
|
|
info->vol[ch] = val;
|
|
info->vol[ch] = val;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-/*
|
|
|
|
|
- * read AMP value. The volume is between 0 to 0x7f, 0x80 = mute bit.
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * snd_hda_codec_amp_read - Read AMP value
|
|
|
|
|
+ * @codec: HD-audio codec
|
|
|
|
|
+ * @nid: NID to read the AMP value
|
|
|
|
|
+ * @ch: channel (left=0 or right=1)
|
|
|
|
|
+ * @direction: #HDA_INPUT or #HDA_OUTPUT
|
|
|
|
|
+ * @index: the index value (only for input direction)
|
|
|
|
|
+ *
|
|
|
|
|
+ * Read AMP value. The volume is between 0 to 0x7f, 0x80 = mute bit.
|
|
|
*/
|
|
*/
|
|
|
int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch,
|
|
int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch,
|
|
|
int direction, int index)
|
|
int direction, int index)
|
|
@@ -1283,8 +1412,18 @@ int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch,
|
|
|
}
|
|
}
|
|
|
EXPORT_SYMBOL_HDA(snd_hda_codec_amp_read);
|
|
EXPORT_SYMBOL_HDA(snd_hda_codec_amp_read);
|
|
|
|
|
|
|
|
-/*
|
|
|
|
|
- * update the AMP value, mask = bit mask to set, val = the value
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * snd_hda_codec_amp_update - update the AMP value
|
|
|
|
|
+ * @codec: HD-audio codec
|
|
|
|
|
+ * @nid: NID to read the AMP value
|
|
|
|
|
+ * @ch: channel (left=0 or right=1)
|
|
|
|
|
+ * @direction: #HDA_INPUT or #HDA_OUTPUT
|
|
|
|
|
+ * @idx: the index value (only for input direction)
|
|
|
|
|
+ * @mask: bit mask to set
|
|
|
|
|
+ * @val: the bits value to set
|
|
|
|
|
+ *
|
|
|
|
|
+ * Update the AMP value with a bit mask.
|
|
|
|
|
+ * Returns 0 if the value is unchanged, 1 if changed.
|
|
|
*/
|
|
*/
|
|
|
int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
|
|
int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
|
|
|
int direction, int idx, int mask, int val)
|
|
int direction, int idx, int mask, int val)
|
|
@@ -1303,8 +1442,17 @@ int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
|
|
|
}
|
|
}
|
|
|
EXPORT_SYMBOL_HDA(snd_hda_codec_amp_update);
|
|
EXPORT_SYMBOL_HDA(snd_hda_codec_amp_update);
|
|
|
|
|
|
|
|
-/*
|
|
|
|
|
- * update the AMP stereo with the same mask and value
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * snd_hda_codec_amp_stereo - update the AMP stereo values
|
|
|
|
|
+ * @codec: HD-audio codec
|
|
|
|
|
+ * @nid: NID to read the AMP value
|
|
|
|
|
+ * @direction: #HDA_INPUT or #HDA_OUTPUT
|
|
|
|
|
+ * @idx: the index value (only for input direction)
|
|
|
|
|
+ * @mask: bit mask to set
|
|
|
|
|
+ * @val: the bits value to set
|
|
|
|
|
+ *
|
|
|
|
|
+ * Update the AMP values like snd_hda_codec_amp_update(), but for a
|
|
|
|
|
+ * stereo widget with the same mask and value.
|
|
|
*/
|
|
*/
|
|
|
int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid,
|
|
int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid,
|
|
|
int direction, int idx, int mask, int val)
|
|
int direction, int idx, int mask, int val)
|
|
@@ -1318,7 +1466,12 @@ int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid,
|
|
|
EXPORT_SYMBOL_HDA(snd_hda_codec_amp_stereo);
|
|
EXPORT_SYMBOL_HDA(snd_hda_codec_amp_stereo);
|
|
|
|
|
|
|
|
#ifdef SND_HDA_NEEDS_RESUME
|
|
#ifdef SND_HDA_NEEDS_RESUME
|
|
|
-/* resume the all amp commands from the cache */
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * snd_hda_codec_resume_amp - Resume all AMP commands from the cache
|
|
|
|
|
+ * @codec: HD-audio codec
|
|
|
|
|
+ *
|
|
|
|
|
+ * Resume the all amp commands from the cache.
|
|
|
|
|
+ */
|
|
|
void snd_hda_codec_resume_amp(struct hda_codec *codec)
|
|
void snd_hda_codec_resume_amp(struct hda_codec *codec)
|
|
|
{
|
|
{
|
|
|
struct hda_amp_info *buffer = codec->amp_cache.buf.list;
|
|
struct hda_amp_info *buffer = codec->amp_cache.buf.list;
|
|
@@ -1344,7 +1497,12 @@ void snd_hda_codec_resume_amp(struct hda_codec *codec)
|
|
|
EXPORT_SYMBOL_HDA(snd_hda_codec_resume_amp);
|
|
EXPORT_SYMBOL_HDA(snd_hda_codec_resume_amp);
|
|
|
#endif /* SND_HDA_NEEDS_RESUME */
|
|
#endif /* SND_HDA_NEEDS_RESUME */
|
|
|
|
|
|
|
|
-/* volume */
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * snd_hda_mixer_amp_volume_info - Info callback for a standard AMP mixer
|
|
|
|
|
+ *
|
|
|
|
|
+ * The control element is supposed to have the private_value field
|
|
|
|
|
+ * set up via HDA_COMPOSE_AMP_VAL*() or related macros.
|
|
|
|
|
+ */
|
|
|
int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol,
|
|
int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol,
|
|
|
struct snd_ctl_elem_info *uinfo)
|
|
struct snd_ctl_elem_info *uinfo)
|
|
|
{
|
|
{
|
|
@@ -1400,6 +1558,12 @@ update_amp_value(struct hda_codec *codec, hda_nid_t nid,
|
|
|
HDA_AMP_VOLMASK, val);
|
|
HDA_AMP_VOLMASK, val);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * snd_hda_mixer_amp_volume_get - Get callback for a standard AMP mixer volume
|
|
|
|
|
+ *
|
|
|
|
|
+ * The control element is supposed to have the private_value field
|
|
|
|
|
+ * set up via HDA_COMPOSE_AMP_VAL*() or related macros.
|
|
|
|
|
+ */
|
|
|
int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol,
|
|
int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol,
|
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
|
{
|
|
{
|
|
@@ -1419,6 +1583,12 @@ int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol,
|
|
|
}
|
|
}
|
|
|
EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_get);
|
|
EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_get);
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * snd_hda_mixer_amp_volume_put - Put callback for a standard AMP mixer volume
|
|
|
|
|
+ *
|
|
|
|
|
+ * The control element is supposed to have the private_value field
|
|
|
|
|
+ * set up via HDA_COMPOSE_AMP_VAL*() or related macros.
|
|
|
|
|
+ */
|
|
|
int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol,
|
|
int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol,
|
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
|
{
|
|
{
|
|
@@ -1443,6 +1613,12 @@ int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol,
|
|
|
}
|
|
}
|
|
|
EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_put);
|
|
EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_put);
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * snd_hda_mixer_amp_volume_put - TLV callback for a standard AMP mixer volume
|
|
|
|
|
+ *
|
|
|
|
|
+ * The control element is supposed to have the private_value field
|
|
|
|
|
+ * set up via HDA_COMPOSE_AMP_VAL*() or related macros.
|
|
|
|
|
+ */
|
|
|
int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
|
|
int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
|
|
|
unsigned int size, unsigned int __user *_tlv)
|
|
unsigned int size, unsigned int __user *_tlv)
|
|
|
{
|
|
{
|
|
@@ -1472,8 +1648,16 @@ int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
|
|
|
}
|
|
}
|
|
|
EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_tlv);
|
|
EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_tlv);
|
|
|
|
|
|
|
|
-/*
|
|
|
|
|
- * set (static) TLV for virtual master volume; recalculated as max 0dB
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * snd_hda_set_vmaster_tlv - Set TLV for a virtual master control
|
|
|
|
|
+ * @codec: HD-audio codec
|
|
|
|
|
+ * @nid: NID of a reference widget
|
|
|
|
|
+ * @dir: #HDA_INPUT or #HDA_OUTPUT
|
|
|
|
|
+ * @tlv: TLV data to be stored, at least 4 elements
|
|
|
|
|
+ *
|
|
|
|
|
+ * Set (static) TLV data for a virtual master volume using the AMP caps
|
|
|
|
|
+ * obtained from the reference NID.
|
|
|
|
|
+ * The volume range is recalculated as if the max volume is 0dB.
|
|
|
*/
|
|
*/
|
|
|
void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir,
|
|
void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir,
|
|
|
unsigned int *tlv)
|
|
unsigned int *tlv)
|
|
@@ -1507,6 +1691,13 @@ _snd_hda_find_mixer_ctl(struct hda_codec *codec,
|
|
|
return snd_ctl_find_id(codec->bus->card, &id);
|
|
return snd_ctl_find_id(codec->bus->card, &id);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * snd_hda_find_mixer_ctl - Find a mixer control element with the given name
|
|
|
|
|
+ * @codec: HD-audio codec
|
|
|
|
|
+ * @name: ctl id name string
|
|
|
|
|
+ *
|
|
|
|
|
+ * Get the control element with the given id string and IFACE_MIXER.
|
|
|
|
|
+ */
|
|
|
struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
|
|
struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
|
|
|
const char *name)
|
|
const char *name)
|
|
|
{
|
|
{
|
|
@@ -1514,30 +1705,57 @@ struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
|
|
|
}
|
|
}
|
|
|
EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl);
|
|
EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl);
|
|
|
|
|
|
|
|
-/* Add a control element and assign to the codec */
|
|
|
|
|
-int snd_hda_ctl_add(struct hda_codec *codec, struct snd_kcontrol *kctl)
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * snd_hda_ctl-add - Add a control element and assign to the codec
|
|
|
|
|
+ * @codec: HD-audio codec
|
|
|
|
|
+ * @nid: corresponding NID (optional)
|
|
|
|
|
+ * @kctl: the control element to assign
|
|
|
|
|
+ *
|
|
|
|
|
+ * Add the given control element to an array inside the codec instance.
|
|
|
|
|
+ * All control elements belonging to a codec are supposed to be added
|
|
|
|
|
+ * by this function so that a proper clean-up works at the free or
|
|
|
|
|
+ * reconfiguration time.
|
|
|
|
|
+ *
|
|
|
|
|
+ * If non-zero @nid is passed, the NID is assigned to the control element.
|
|
|
|
|
+ * The assignment is shown in the codec proc file.
|
|
|
|
|
+ *
|
|
|
|
|
+ * snd_hda_ctl_add() checks the control subdev id field whether
|
|
|
|
|
+ * #HDA_SUBDEV_NID_FLAG bit is set. If set (and @nid is zero), the lower
|
|
|
|
|
+ * bits value is taken as the NID to assign.
|
|
|
|
|
+ */
|
|
|
|
|
+int snd_hda_ctl_add(struct hda_codec *codec, hda_nid_t nid,
|
|
|
|
|
+ struct snd_kcontrol *kctl)
|
|
|
{
|
|
{
|
|
|
int err;
|
|
int err;
|
|
|
- struct snd_kcontrol **knewp;
|
|
|
|
|
|
|
+ struct hda_nid_item *item;
|
|
|
|
|
|
|
|
|
|
+ if (kctl->id.subdevice & HDA_SUBDEV_NID_FLAG) {
|
|
|
|
|
+ if (nid == 0)
|
|
|
|
|
+ nid = kctl->id.subdevice & 0xffff;
|
|
|
|
|
+ kctl->id.subdevice = 0;
|
|
|
|
|
+ }
|
|
|
err = snd_ctl_add(codec->bus->card, kctl);
|
|
err = snd_ctl_add(codec->bus->card, kctl);
|
|
|
if (err < 0)
|
|
if (err < 0)
|
|
|
return err;
|
|
return err;
|
|
|
- knewp = snd_array_new(&codec->mixers);
|
|
|
|
|
- if (!knewp)
|
|
|
|
|
|
|
+ item = snd_array_new(&codec->mixers);
|
|
|
|
|
+ if (!item)
|
|
|
return -ENOMEM;
|
|
return -ENOMEM;
|
|
|
- *knewp = kctl;
|
|
|
|
|
|
|
+ item->kctl = kctl;
|
|
|
|
|
+ item->nid = nid;
|
|
|
return 0;
|
|
return 0;
|
|
|
}
|
|
}
|
|
|
EXPORT_SYMBOL_HDA(snd_hda_ctl_add);
|
|
EXPORT_SYMBOL_HDA(snd_hda_ctl_add);
|
|
|
|
|
|
|
|
-/* Clear all controls assigned to the given codec */
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * snd_hda_ctls_clear - Clear all controls assigned to the given codec
|
|
|
|
|
+ * @codec: HD-audio codec
|
|
|
|
|
+ */
|
|
|
void snd_hda_ctls_clear(struct hda_codec *codec)
|
|
void snd_hda_ctls_clear(struct hda_codec *codec)
|
|
|
{
|
|
{
|
|
|
int i;
|
|
int i;
|
|
|
- struct snd_kcontrol **kctls = codec->mixers.list;
|
|
|
|
|
|
|
+ struct hda_nid_item *items = codec->mixers.list;
|
|
|
for (i = 0; i < codec->mixers.used; i++)
|
|
for (i = 0; i < codec->mixers.used; i++)
|
|
|
- snd_ctl_remove(codec->bus->card, kctls[i]);
|
|
|
|
|
|
|
+ snd_ctl_remove(codec->bus->card, items[i].kctl);
|
|
|
snd_array_free(&codec->mixers);
|
|
snd_array_free(&codec->mixers);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -1563,6 +1781,16 @@ static void hda_unlock_devices(struct snd_card *card)
|
|
|
spin_unlock(&card->files_lock);
|
|
spin_unlock(&card->files_lock);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * snd_hda_codec_reset - Clear all objects assigned to the codec
|
|
|
|
|
+ * @codec: HD-audio codec
|
|
|
|
|
+ *
|
|
|
|
|
+ * This frees the all PCM and control elements assigned to the codec, and
|
|
|
|
|
+ * clears the caches and restores the pin default configurations.
|
|
|
|
|
+ *
|
|
|
|
|
+ * When a device is being used, it returns -EBSY. If successfully freed,
|
|
|
|
|
+ * returns zero.
|
|
|
|
|
+ */
|
|
|
int snd_hda_codec_reset(struct hda_codec *codec)
|
|
int snd_hda_codec_reset(struct hda_codec *codec)
|
|
|
{
|
|
{
|
|
|
struct snd_card *card = codec->bus->card;
|
|
struct snd_card *card = codec->bus->card;
|
|
@@ -1626,7 +1854,22 @@ int snd_hda_codec_reset(struct hda_codec *codec)
|
|
|
return 0;
|
|
return 0;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-/* create a virtual master control and add slaves */
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * snd_hda_add_vmaster - create a virtual master control and add slaves
|
|
|
|
|
+ * @codec: HD-audio codec
|
|
|
|
|
+ * @name: vmaster control name
|
|
|
|
|
+ * @tlv: TLV data (optional)
|
|
|
|
|
+ * @slaves: slave control names (optional)
|
|
|
|
|
+ *
|
|
|
|
|
+ * Create a virtual master control with the given name. The TLV data
|
|
|
|
|
+ * must be either NULL or a valid data.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @slaves is a NULL-terminated array of strings, each of which is a
|
|
|
|
|
+ * slave control name. All controls with these names are assigned to
|
|
|
|
|
+ * the new virtual master control.
|
|
|
|
|
+ *
|
|
|
|
|
+ * This function returns zero if successful or a negative error code.
|
|
|
|
|
+ */
|
|
|
int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
|
|
int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
|
|
|
unsigned int *tlv, const char **slaves)
|
|
unsigned int *tlv, const char **slaves)
|
|
|
{
|
|
{
|
|
@@ -1643,7 +1886,7 @@ int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
|
|
|
kctl = snd_ctl_make_virtual_master(name, tlv);
|
|
kctl = snd_ctl_make_virtual_master(name, tlv);
|
|
|
if (!kctl)
|
|
if (!kctl)
|
|
|
return -ENOMEM;
|
|
return -ENOMEM;
|
|
|
- err = snd_hda_ctl_add(codec, kctl);
|
|
|
|
|
|
|
+ err = snd_hda_ctl_add(codec, 0, kctl);
|
|
|
if (err < 0)
|
|
if (err < 0)
|
|
|
return err;
|
|
return err;
|
|
|
|
|
|
|
@@ -1668,7 +1911,12 @@ int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
|
|
|
}
|
|
}
|
|
|
EXPORT_SYMBOL_HDA(snd_hda_add_vmaster);
|
|
EXPORT_SYMBOL_HDA(snd_hda_add_vmaster);
|
|
|
|
|
|
|
|
-/* switch */
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * snd_hda_mixer_amp_switch_info - Info callback for a standard AMP mixer switch
|
|
|
|
|
+ *
|
|
|
|
|
+ * The control element is supposed to have the private_value field
|
|
|
|
|
+ * set up via HDA_COMPOSE_AMP_VAL*() or related macros.
|
|
|
|
|
+ */
|
|
|
int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol,
|
|
int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol,
|
|
|
struct snd_ctl_elem_info *uinfo)
|
|
struct snd_ctl_elem_info *uinfo)
|
|
|
{
|
|
{
|
|
@@ -1682,6 +1930,12 @@ int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol,
|
|
|
}
|
|
}
|
|
|
EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_info);
|
|
EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_info);
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * snd_hda_mixer_amp_switch_get - Get callback for a standard AMP mixer switch
|
|
|
|
|
+ *
|
|
|
|
|
+ * The control element is supposed to have the private_value field
|
|
|
|
|
+ * set up via HDA_COMPOSE_AMP_VAL*() or related macros.
|
|
|
|
|
+ */
|
|
|
int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol,
|
|
int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol,
|
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
|
{
|
|
{
|
|
@@ -1702,6 +1956,12 @@ int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol,
|
|
|
}
|
|
}
|
|
|
EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_get);
|
|
EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_get);
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * snd_hda_mixer_amp_switch_put - Put callback for a standard AMP mixer switch
|
|
|
|
|
+ *
|
|
|
|
|
+ * The control element is supposed to have the private_value field
|
|
|
|
|
+ * set up via HDA_COMPOSE_AMP_VAL*() or related macros.
|
|
|
|
|
+ */
|
|
|
int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol,
|
|
int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol,
|
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
|
{
|
|
{
|
|
@@ -1733,6 +1993,25 @@ int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol,
|
|
|
}
|
|
}
|
|
|
EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put);
|
|
EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put);
|
|
|
|
|
|
|
|
|
|
+#ifdef CONFIG_SND_HDA_INPUT_BEEP
|
|
|
|
|
+/**
|
|
|
|
|
+ * snd_hda_mixer_amp_switch_put_beep - Put callback for a beep AMP switch
|
|
|
|
|
+ *
|
|
|
|
|
+ * This function calls snd_hda_enable_beep_device(), which behaves differently
|
|
|
|
|
+ * depending on beep_mode option.
|
|
|
|
|
+ */
|
|
|
|
|
+int snd_hda_mixer_amp_switch_put_beep(struct snd_kcontrol *kcontrol,
|
|
|
|
|
+ struct snd_ctl_elem_value *ucontrol)
|
|
|
|
|
+{
|
|
|
|
|
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
|
|
|
|
|
+ long *valp = ucontrol->value.integer.value;
|
|
|
|
|
+
|
|
|
|
|
+ snd_hda_enable_beep_device(codec, *valp);
|
|
|
|
|
+ return snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
|
|
|
|
|
+}
|
|
|
|
|
+EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put_beep);
|
|
|
|
|
+#endif /* CONFIG_SND_HDA_INPUT_BEEP */
|
|
|
|
|
+
|
|
|
/*
|
|
/*
|
|
|
* bound volume controls
|
|
* bound volume controls
|
|
|
*
|
|
*
|
|
@@ -1742,6 +2021,12 @@ EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put);
|
|
|
#define AMP_VAL_IDX_SHIFT 19
|
|
#define AMP_VAL_IDX_SHIFT 19
|
|
|
#define AMP_VAL_IDX_MASK (0x0f<<19)
|
|
#define AMP_VAL_IDX_MASK (0x0f<<19)
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * snd_hda_mixer_bind_switch_get - Get callback for a bound volume control
|
|
|
|
|
+ *
|
|
|
|
|
+ * The control element is supposed to have the private_value field
|
|
|
|
|
+ * set up via HDA_BIND_MUTE*() macros.
|
|
|
|
|
+ */
|
|
|
int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol,
|
|
int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol,
|
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
|
{
|
|
{
|
|
@@ -1759,6 +2044,12 @@ int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol,
|
|
|
}
|
|
}
|
|
|
EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_get);
|
|
EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_get);
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * snd_hda_mixer_bind_switch_put - Put callback for a bound volume control
|
|
|
|
|
+ *
|
|
|
|
|
+ * The control element is supposed to have the private_value field
|
|
|
|
|
+ * set up via HDA_BIND_MUTE*() macros.
|
|
|
|
|
+ */
|
|
|
int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol,
|
|
int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol,
|
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
|
{
|
|
{
|
|
@@ -1783,8 +2074,11 @@ int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol,
|
|
|
}
|
|
}
|
|
|
EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_put);
|
|
EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_put);
|
|
|
|
|
|
|
|
-/*
|
|
|
|
|
- * generic bound volume/swtich controls
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * snd_hda_mixer_bind_ctls_info - Info callback for a generic bound control
|
|
|
|
|
+ *
|
|
|
|
|
+ * The control element is supposed to have the private_value field
|
|
|
|
|
+ * set up via HDA_BIND_VOL() or HDA_BIND_SW() macros.
|
|
|
*/
|
|
*/
|
|
|
int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol,
|
|
int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol,
|
|
|
struct snd_ctl_elem_info *uinfo)
|
|
struct snd_ctl_elem_info *uinfo)
|
|
@@ -1803,6 +2097,12 @@ int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol,
|
|
|
}
|
|
}
|
|
|
EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_info);
|
|
EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_info);
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * snd_hda_mixer_bind_ctls_get - Get callback for a generic bound control
|
|
|
|
|
+ *
|
|
|
|
|
+ * The control element is supposed to have the private_value field
|
|
|
|
|
+ * set up via HDA_BIND_VOL() or HDA_BIND_SW() macros.
|
|
|
|
|
+ */
|
|
|
int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol,
|
|
int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol,
|
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
|
{
|
|
{
|
|
@@ -1820,6 +2120,12 @@ int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol,
|
|
|
}
|
|
}
|
|
|
EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_get);
|
|
EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_get);
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * snd_hda_mixer_bind_ctls_put - Put callback for a generic bound control
|
|
|
|
|
+ *
|
|
|
|
|
+ * The control element is supposed to have the private_value field
|
|
|
|
|
+ * set up via HDA_BIND_VOL() or HDA_BIND_SW() macros.
|
|
|
|
|
+ */
|
|
|
int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol,
|
|
int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol,
|
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
struct snd_ctl_elem_value *ucontrol)
|
|
|
{
|
|
{
|
|
@@ -1843,6 +2149,12 @@ int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol,
|
|
|
}
|
|
}
|
|
|
EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_put);
|
|
EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_put);
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * snd_hda_mixer_bind_tlv - TLV callback for a generic bound control
|
|
|
|
|
+ *
|
|
|
|
|
+ * The control element is supposed to have the private_value field
|
|
|
|
|
+ * set up via HDA_BIND_VOL() macro.
|
|
|
|
|
+ */
|
|
|
int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag,
|
|
int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag,
|
|
|
unsigned int size, unsigned int __user *tlv)
|
|
unsigned int size, unsigned int __user *tlv)
|
|
|
{
|
|
{
|
|
@@ -2126,7 +2438,7 @@ int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid)
|
|
|
return -ENOMEM;
|
|
return -ENOMEM;
|
|
|
kctl->id.index = idx;
|
|
kctl->id.index = idx;
|
|
|
kctl->private_value = nid;
|
|
kctl->private_value = nid;
|
|
|
- err = snd_hda_ctl_add(codec, kctl);
|
|
|
|
|
|
|
+ err = snd_hda_ctl_add(codec, nid, kctl);
|
|
|
if (err < 0)
|
|
if (err < 0)
|
|
|
return err;
|
|
return err;
|
|
|
}
|
|
}
|
|
@@ -2165,14 +2477,19 @@ static struct snd_kcontrol_new spdif_share_sw = {
|
|
|
.put = spdif_share_sw_put,
|
|
.put = spdif_share_sw_put,
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * snd_hda_create_spdif_share_sw - create Default PCM switch
|
|
|
|
|
+ * @codec: the HDA codec
|
|
|
|
|
+ * @mout: multi-out instance
|
|
|
|
|
+ */
|
|
|
int snd_hda_create_spdif_share_sw(struct hda_codec *codec,
|
|
int snd_hda_create_spdif_share_sw(struct hda_codec *codec,
|
|
|
struct hda_multi_out *mout)
|
|
struct hda_multi_out *mout)
|
|
|
{
|
|
{
|
|
|
if (!mout->dig_out_nid)
|
|
if (!mout->dig_out_nid)
|
|
|
return 0;
|
|
return 0;
|
|
|
/* ATTENTION: here mout is passed as private_data, instead of codec */
|
|
/* ATTENTION: here mout is passed as private_data, instead of codec */
|
|
|
- return snd_hda_ctl_add(codec,
|
|
|
|
|
- snd_ctl_new1(&spdif_share_sw, mout));
|
|
|
|
|
|
|
+ return snd_hda_ctl_add(codec, mout->dig_out_nid,
|
|
|
|
|
+ snd_ctl_new1(&spdif_share_sw, mout));
|
|
|
}
|
|
}
|
|
|
EXPORT_SYMBOL_HDA(snd_hda_create_spdif_share_sw);
|
|
EXPORT_SYMBOL_HDA(snd_hda_create_spdif_share_sw);
|
|
|
|
|
|
|
@@ -2276,7 +2593,7 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid)
|
|
|
if (!kctl)
|
|
if (!kctl)
|
|
|
return -ENOMEM;
|
|
return -ENOMEM;
|
|
|
kctl->private_value = nid;
|
|
kctl->private_value = nid;
|
|
|
- err = snd_hda_ctl_add(codec, kctl);
|
|
|
|
|
|
|
+ err = snd_hda_ctl_add(codec, nid, kctl);
|
|
|
if (err < 0)
|
|
if (err < 0)
|
|
|
return err;
|
|
return err;
|
|
|
}
|
|
}
|
|
@@ -2332,7 +2649,12 @@ int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
|
|
|
}
|
|
}
|
|
|
EXPORT_SYMBOL_HDA(snd_hda_codec_write_cache);
|
|
EXPORT_SYMBOL_HDA(snd_hda_codec_write_cache);
|
|
|
|
|
|
|
|
-/* resume the all commands from the cache */
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * snd_hda_codec_resume_cache - Resume the all commands from the cache
|
|
|
|
|
+ * @codec: HD-audio codec
|
|
|
|
|
+ *
|
|
|
|
|
+ * Execute all verbs recorded in the command caches to resume.
|
|
|
|
|
+ */
|
|
|
void snd_hda_codec_resume_cache(struct hda_codec *codec)
|
|
void snd_hda_codec_resume_cache(struct hda_codec *codec)
|
|
|
{
|
|
{
|
|
|
struct hda_cache_head *buffer = codec->cmd_cache.buf.list;
|
|
struct hda_cache_head *buffer = codec->cmd_cache.buf.list;
|
|
@@ -2452,9 +2774,11 @@ static void hda_call_codec_suspend(struct hda_codec *codec)
|
|
|
codec->afg ? codec->afg : codec->mfg,
|
|
codec->afg ? codec->afg : codec->mfg,
|
|
|
AC_PWRST_D3);
|
|
AC_PWRST_D3);
|
|
|
#ifdef CONFIG_SND_HDA_POWER_SAVE
|
|
#ifdef CONFIG_SND_HDA_POWER_SAVE
|
|
|
|
|
+ snd_hda_update_power_acct(codec);
|
|
|
cancel_delayed_work(&codec->power_work);
|
|
cancel_delayed_work(&codec->power_work);
|
|
|
codec->power_on = 0;
|
|
codec->power_on = 0;
|
|
|
codec->power_transition = 0;
|
|
codec->power_transition = 0;
|
|
|
|
|
+ codec->power_jiffies = jiffies;
|
|
|
#endif
|
|
#endif
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -2756,8 +3080,12 @@ static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * snd_hda_is_supported_format - check whether the given node supports
|
|
|
|
|
- * the format val
|
|
|
|
|
|
|
+ * snd_hda_is_supported_format - Check the validity of the format
|
|
|
|
|
+ * @codec: HD-audio codec
|
|
|
|
|
+ * @nid: NID to check
|
|
|
|
|
+ * @format: the HD-audio format value to check
|
|
|
|
|
+ *
|
|
|
|
|
+ * Check whether the given node supports the format value.
|
|
|
*
|
|
*
|
|
|
* Returns 1 if supported, 0 if not.
|
|
* Returns 1 if supported, 0 if not.
|
|
|
*/
|
|
*/
|
|
@@ -2877,51 +3205,36 @@ static int set_pcm_default_values(struct hda_codec *codec,
|
|
|
return 0;
|
|
return 0;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+/* global */
|
|
|
|
|
+const char *snd_hda_pcm_type_name[HDA_PCM_NTYPES] = {
|
|
|
|
|
+ "Audio", "SPDIF", "HDMI", "Modem"
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
/*
|
|
/*
|
|
|
* get the empty PCM device number to assign
|
|
* get the empty PCM device number to assign
|
|
|
*/
|
|
*/
|
|
|
static int get_empty_pcm_device(struct hda_bus *bus, int type)
|
|
static int get_empty_pcm_device(struct hda_bus *bus, int type)
|
|
|
{
|
|
{
|
|
|
- static const char *dev_name[HDA_PCM_NTYPES] = {
|
|
|
|
|
- "Audio", "SPDIF", "HDMI", "Modem"
|
|
|
|
|
- };
|
|
|
|
|
- /* starting device index for each PCM type */
|
|
|
|
|
- static int dev_idx[HDA_PCM_NTYPES] = {
|
|
|
|
|
- [HDA_PCM_TYPE_AUDIO] = 0,
|
|
|
|
|
- [HDA_PCM_TYPE_SPDIF] = 1,
|
|
|
|
|
- [HDA_PCM_TYPE_HDMI] = 3,
|
|
|
|
|
- [HDA_PCM_TYPE_MODEM] = 6
|
|
|
|
|
|
|
+ /* audio device indices; not linear to keep compatibility */
|
|
|
|
|
+ static int audio_idx[HDA_PCM_NTYPES][5] = {
|
|
|
|
|
+ [HDA_PCM_TYPE_AUDIO] = { 0, 2, 4, 5, -1 },
|
|
|
|
|
+ [HDA_PCM_TYPE_SPDIF] = { 1, -1 },
|
|
|
|
|
+ [HDA_PCM_TYPE_HDMI] = { 3, 7, 8, 9, -1 },
|
|
|
|
|
+ [HDA_PCM_TYPE_MODEM] = { 6, -1 },
|
|
|
};
|
|
};
|
|
|
- /* normal audio device indices; not linear to keep compatibility */
|
|
|
|
|
- static int audio_idx[4] = { 0, 2, 4, 5 };
|
|
|
|
|
- int i, dev;
|
|
|
|
|
-
|
|
|
|
|
- switch (type) {
|
|
|
|
|
- case HDA_PCM_TYPE_AUDIO:
|
|
|
|
|
- for (i = 0; i < ARRAY_SIZE(audio_idx); i++) {
|
|
|
|
|
- dev = audio_idx[i];
|
|
|
|
|
- if (!test_bit(dev, bus->pcm_dev_bits))
|
|
|
|
|
- goto ok;
|
|
|
|
|
- }
|
|
|
|
|
- snd_printk(KERN_WARNING "Too many audio devices\n");
|
|
|
|
|
- return -EAGAIN;
|
|
|
|
|
- case HDA_PCM_TYPE_SPDIF:
|
|
|
|
|
- case HDA_PCM_TYPE_HDMI:
|
|
|
|
|
- case HDA_PCM_TYPE_MODEM:
|
|
|
|
|
- dev = dev_idx[type];
|
|
|
|
|
- if (test_bit(dev, bus->pcm_dev_bits)) {
|
|
|
|
|
- snd_printk(KERN_WARNING "%s already defined\n",
|
|
|
|
|
- dev_name[type]);
|
|
|
|
|
- return -EAGAIN;
|
|
|
|
|
- }
|
|
|
|
|
- break;
|
|
|
|
|
- default:
|
|
|
|
|
|
|
+ int i;
|
|
|
|
|
+
|
|
|
|
|
+ if (type >= HDA_PCM_NTYPES) {
|
|
|
snd_printk(KERN_WARNING "Invalid PCM type %d\n", type);
|
|
snd_printk(KERN_WARNING "Invalid PCM type %d\n", type);
|
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
}
|
|
}
|
|
|
- ok:
|
|
|
|
|
- set_bit(dev, bus->pcm_dev_bits);
|
|
|
|
|
- return dev;
|
|
|
|
|
|
|
+
|
|
|
|
|
+ for (i = 0; audio_idx[type][i] >= 0 ; i++)
|
|
|
|
|
+ if (!test_and_set_bit(audio_idx[type][i], bus->pcm_dev_bits))
|
|
|
|
|
+ return audio_idx[type][i];
|
|
|
|
|
+
|
|
|
|
|
+ snd_printk(KERN_WARNING "Too many %s devices\n", snd_hda_pcm_type_name[type]);
|
|
|
|
|
+ return -EAGAIN;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -3159,14 +3472,14 @@ EXPORT_SYMBOL_HDA(snd_hda_check_board_codec_sid_config);
|
|
|
*/
|
|
*/
|
|
|
int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew)
|
|
int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew)
|
|
|
{
|
|
{
|
|
|
- int err;
|
|
|
|
|
|
|
+ int err;
|
|
|
|
|
|
|
|
for (; knew->name; knew++) {
|
|
for (; knew->name; knew++) {
|
|
|
struct snd_kcontrol *kctl;
|
|
struct snd_kcontrol *kctl;
|
|
|
kctl = snd_ctl_new1(knew, codec);
|
|
kctl = snd_ctl_new1(knew, codec);
|
|
|
if (!kctl)
|
|
if (!kctl)
|
|
|
return -ENOMEM;
|
|
return -ENOMEM;
|
|
|
- err = snd_hda_ctl_add(codec, kctl);
|
|
|
|
|
|
|
+ err = snd_hda_ctl_add(codec, 0, kctl);
|
|
|
if (err < 0) {
|
|
if (err < 0) {
|
|
|
if (!codec->addr)
|
|
if (!codec->addr)
|
|
|
return err;
|
|
return err;
|
|
@@ -3174,7 +3487,7 @@ int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew)
|
|
|
if (!kctl)
|
|
if (!kctl)
|
|
|
return -ENOMEM;
|
|
return -ENOMEM;
|
|
|
kctl->id.device = codec->addr;
|
|
kctl->id.device = codec->addr;
|
|
|
- err = snd_hda_ctl_add(codec, kctl);
|
|
|
|
|
|
|
+ err = snd_hda_ctl_add(codec, 0, kctl);
|
|
|
if (err < 0)
|
|
if (err < 0)
|
|
|
return err;
|
|
return err;
|
|
|
}
|
|
}
|
|
@@ -3207,8 +3520,27 @@ static void hda_keep_power_on(struct hda_codec *codec)
|
|
|
{
|
|
{
|
|
|
codec->power_count++;
|
|
codec->power_count++;
|
|
|
codec->power_on = 1;
|
|
codec->power_on = 1;
|
|
|
|
|
+ codec->power_jiffies = jiffies;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+/* update the power on/off account with the current jiffies */
|
|
|
|
|
+void snd_hda_update_power_acct(struct hda_codec *codec)
|
|
|
|
|
+{
|
|
|
|
|
+ unsigned long delta = jiffies - codec->power_jiffies;
|
|
|
|
|
+ if (codec->power_on)
|
|
|
|
|
+ codec->power_on_acct += delta;
|
|
|
|
|
+ else
|
|
|
|
|
+ codec->power_off_acct += delta;
|
|
|
|
|
+ codec->power_jiffies += delta;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 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.
|
|
|
|
|
+ */
|
|
|
void snd_hda_power_up(struct hda_codec *codec)
|
|
void snd_hda_power_up(struct hda_codec *codec)
|
|
|
{
|
|
{
|
|
|
struct hda_bus *bus = codec->bus;
|
|
struct hda_bus *bus = codec->bus;
|
|
@@ -3217,7 +3549,9 @@ void snd_hda_power_up(struct hda_codec *codec)
|
|
|
if (codec->power_on || codec->power_transition)
|
|
if (codec->power_on || codec->power_transition)
|
|
|
return;
|
|
return;
|
|
|
|
|
|
|
|
|
|
+ snd_hda_update_power_acct(codec);
|
|
|
codec->power_on = 1;
|
|
codec->power_on = 1;
|
|
|
|
|
+ codec->power_jiffies = jiffies;
|
|
|
if (bus->ops.pm_notify)
|
|
if (bus->ops.pm_notify)
|
|
|
bus->ops.pm_notify(bus);
|
|
bus->ops.pm_notify(bus);
|
|
|
hda_call_codec_resume(codec);
|
|
hda_call_codec_resume(codec);
|
|
@@ -3229,9 +3563,13 @@ EXPORT_SYMBOL_HDA(snd_hda_power_up);
|
|
|
#define power_save(codec) \
|
|
#define power_save(codec) \
|
|
|
((codec)->bus->power_save ? *(codec)->bus->power_save : 0)
|
|
((codec)->bus->power_save ? *(codec)->bus->power_save : 0)
|
|
|
|
|
|
|
|
-#define power_save(codec) \
|
|
|
|
|
- ((codec)->bus->power_save ? *(codec)->bus->power_save : 0)
|
|
|
|
|
-
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * 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.
|
|
|
|
|
+ */
|
|
|
void snd_hda_power_down(struct hda_codec *codec)
|
|
void snd_hda_power_down(struct hda_codec *codec)
|
|
|
{
|
|
{
|
|
|
--codec->power_count;
|
|
--codec->power_count;
|
|
@@ -3245,6 +3583,19 @@ void snd_hda_power_down(struct hda_codec *codec)
|
|
|
}
|
|
}
|
|
|
EXPORT_SYMBOL_HDA(snd_hda_power_down);
|
|
EXPORT_SYMBOL_HDA(snd_hda_power_down);
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * snd_hda_check_amp_list_power - Check the amp list and update the power
|
|
|
|
|
+ * @codec: HD-audio codec
|
|
|
|
|
+ * @check: the object containing an AMP list and the status
|
|
|
|
|
+ * @nid: NID to check / update
|
|
|
|
|
+ *
|
|
|
|
|
+ * Check whether the given NID is in the amp list. If it's in the list,
|
|
|
|
|
+ * check the current AMP status, and update the the power-status according
|
|
|
|
|
+ * to the mute status.
|
|
|
|
|
+ *
|
|
|
|
|
+ * This function is supposed to be set or called from the check_power_status
|
|
|
|
|
+ * patch ops.
|
|
|
|
|
+ */
|
|
|
int snd_hda_check_amp_list_power(struct hda_codec *codec,
|
|
int snd_hda_check_amp_list_power(struct hda_codec *codec,
|
|
|
struct hda_loopback_check *check,
|
|
struct hda_loopback_check *check,
|
|
|
hda_nid_t nid)
|
|
hda_nid_t nid)
|
|
@@ -3286,6 +3637,10 @@ EXPORT_SYMBOL_HDA(snd_hda_check_amp_list_power);
|
|
|
/*
|
|
/*
|
|
|
* Channel mode helper
|
|
* Channel mode helper
|
|
|
*/
|
|
*/
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * snd_hda_ch_mode_info - Info callback helper for the channel mode enum
|
|
|
|
|
+ */
|
|
|
int snd_hda_ch_mode_info(struct hda_codec *codec,
|
|
int snd_hda_ch_mode_info(struct hda_codec *codec,
|
|
|
struct snd_ctl_elem_info *uinfo,
|
|
struct snd_ctl_elem_info *uinfo,
|
|
|
const struct hda_channel_mode *chmode,
|
|
const struct hda_channel_mode *chmode,
|
|
@@ -3302,6 +3657,9 @@ int snd_hda_ch_mode_info(struct hda_codec *codec,
|
|
|
}
|
|
}
|
|
|
EXPORT_SYMBOL_HDA(snd_hda_ch_mode_info);
|
|
EXPORT_SYMBOL_HDA(snd_hda_ch_mode_info);
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * snd_hda_ch_mode_get - Get callback helper for the channel mode enum
|
|
|
|
|
+ */
|
|
|
int snd_hda_ch_mode_get(struct hda_codec *codec,
|
|
int snd_hda_ch_mode_get(struct hda_codec *codec,
|
|
|
struct snd_ctl_elem_value *ucontrol,
|
|
struct snd_ctl_elem_value *ucontrol,
|
|
|
const struct hda_channel_mode *chmode,
|
|
const struct hda_channel_mode *chmode,
|
|
@@ -3320,6 +3678,9 @@ int snd_hda_ch_mode_get(struct hda_codec *codec,
|
|
|
}
|
|
}
|
|
|
EXPORT_SYMBOL_HDA(snd_hda_ch_mode_get);
|
|
EXPORT_SYMBOL_HDA(snd_hda_ch_mode_get);
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * snd_hda_ch_mode_put - Put callback helper for the channel mode enum
|
|
|
|
|
+ */
|
|
|
int snd_hda_ch_mode_put(struct hda_codec *codec,
|
|
int snd_hda_ch_mode_put(struct hda_codec *codec,
|
|
|
struct snd_ctl_elem_value *ucontrol,
|
|
struct snd_ctl_elem_value *ucontrol,
|
|
|
const struct hda_channel_mode *chmode,
|
|
const struct hda_channel_mode *chmode,
|
|
@@ -3344,6 +3705,10 @@ EXPORT_SYMBOL_HDA(snd_hda_ch_mode_put);
|
|
|
/*
|
|
/*
|
|
|
* input MUX helper
|
|
* input MUX helper
|
|
|
*/
|
|
*/
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * snd_hda_input_mux_info_info - Info callback helper for the input-mux enum
|
|
|
|
|
+ */
|
|
|
int snd_hda_input_mux_info(const struct hda_input_mux *imux,
|
|
int snd_hda_input_mux_info(const struct hda_input_mux *imux,
|
|
|
struct snd_ctl_elem_info *uinfo)
|
|
struct snd_ctl_elem_info *uinfo)
|
|
|
{
|
|
{
|
|
@@ -3362,6 +3727,9 @@ int snd_hda_input_mux_info(const struct hda_input_mux *imux,
|
|
|
}
|
|
}
|
|
|
EXPORT_SYMBOL_HDA(snd_hda_input_mux_info);
|
|
EXPORT_SYMBOL_HDA(snd_hda_input_mux_info);
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * snd_hda_input_mux_info_put - Put callback helper for the input-mux enum
|
|
|
|
|
+ */
|
|
|
int snd_hda_input_mux_put(struct hda_codec *codec,
|
|
int snd_hda_input_mux_put(struct hda_codec *codec,
|
|
|
const struct hda_input_mux *imux,
|
|
const struct hda_input_mux *imux,
|
|
|
struct snd_ctl_elem_value *ucontrol,
|
|
struct snd_ctl_elem_value *ucontrol,
|
|
@@ -3421,8 +3789,29 @@ static void cleanup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-/*
|
|
|
|
|
- * open the digital out in the exclusive mode
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * snd_hda_bus_reboot_notify - call the reboot notifier of each codec
|
|
|
|
|
+ * @bus: HD-audio bus
|
|
|
|
|
+ */
|
|
|
|
|
+void snd_hda_bus_reboot_notify(struct hda_bus *bus)
|
|
|
|
|
+{
|
|
|
|
|
+ struct hda_codec *codec;
|
|
|
|
|
+
|
|
|
|
|
+ if (!bus)
|
|
|
|
|
+ return;
|
|
|
|
|
+ list_for_each_entry(codec, &bus->codec_list, list) {
|
|
|
|
|
+#ifdef CONFIG_SND_HDA_POWER_SAVE
|
|
|
|
|
+ if (!codec->power_on)
|
|
|
|
|
+ continue;
|
|
|
|
|
+#endif
|
|
|
|
|
+ if (codec->patch_ops.reboot_notify)
|
|
|
|
|
+ codec->patch_ops.reboot_notify(codec);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+EXPORT_SYMBOL_HDA(snd_hda_bus_reboot_notify);
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * snd_hda_multi_out_dig_open - open the digital out in the exclusive mode
|
|
|
*/
|
|
*/
|
|
|
int snd_hda_multi_out_dig_open(struct hda_codec *codec,
|
|
int snd_hda_multi_out_dig_open(struct hda_codec *codec,
|
|
|
struct hda_multi_out *mout)
|
|
struct hda_multi_out *mout)
|
|
@@ -3437,6 +3826,9 @@ int snd_hda_multi_out_dig_open(struct hda_codec *codec,
|
|
|
}
|
|
}
|
|
|
EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_open);
|
|
EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_open);
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * snd_hda_multi_out_dig_prepare - prepare the digital out stream
|
|
|
|
|
+ */
|
|
|
int snd_hda_multi_out_dig_prepare(struct hda_codec *codec,
|
|
int snd_hda_multi_out_dig_prepare(struct hda_codec *codec,
|
|
|
struct hda_multi_out *mout,
|
|
struct hda_multi_out *mout,
|
|
|
unsigned int stream_tag,
|
|
unsigned int stream_tag,
|
|
@@ -3450,6 +3842,9 @@ int snd_hda_multi_out_dig_prepare(struct hda_codec *codec,
|
|
|
}
|
|
}
|
|
|
EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_prepare);
|
|
EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_prepare);
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * snd_hda_multi_out_dig_cleanup - clean-up the digital out stream
|
|
|
|
|
+ */
|
|
|
int snd_hda_multi_out_dig_cleanup(struct hda_codec *codec,
|
|
int snd_hda_multi_out_dig_cleanup(struct hda_codec *codec,
|
|
|
struct hda_multi_out *mout)
|
|
struct hda_multi_out *mout)
|
|
|
{
|
|
{
|
|
@@ -3460,8 +3855,8 @@ int snd_hda_multi_out_dig_cleanup(struct hda_codec *codec,
|
|
|
}
|
|
}
|
|
|
EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_cleanup);
|
|
EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_cleanup);
|
|
|
|
|
|
|
|
-/*
|
|
|
|
|
- * release the digital out
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * snd_hda_multi_out_dig_close - release the digital out stream
|
|
|
*/
|
|
*/
|
|
|
int snd_hda_multi_out_dig_close(struct hda_codec *codec,
|
|
int snd_hda_multi_out_dig_close(struct hda_codec *codec,
|
|
|
struct hda_multi_out *mout)
|
|
struct hda_multi_out *mout)
|
|
@@ -3473,8 +3868,12 @@ int snd_hda_multi_out_dig_close(struct hda_codec *codec,
|
|
|
}
|
|
}
|
|
|
EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_close);
|
|
EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_close);
|
|
|
|
|
|
|
|
-/*
|
|
|
|
|
- * set up more restrictions for analog out
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * snd_hda_multi_out_analog_open - open analog outputs
|
|
|
|
|
+ *
|
|
|
|
|
+ * Open analog outputs and set up the hw-constraints.
|
|
|
|
|
+ * If the digital outputs can be opened as slave, open the digital
|
|
|
|
|
+ * outputs, too.
|
|
|
*/
|
|
*/
|
|
|
int snd_hda_multi_out_analog_open(struct hda_codec *codec,
|
|
int snd_hda_multi_out_analog_open(struct hda_codec *codec,
|
|
|
struct hda_multi_out *mout,
|
|
struct hda_multi_out *mout,
|
|
@@ -3519,9 +3918,11 @@ int snd_hda_multi_out_analog_open(struct hda_codec *codec,
|
|
|
}
|
|
}
|
|
|
EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_open);
|
|
EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_open);
|
|
|
|
|
|
|
|
-/*
|
|
|
|
|
- * set up the i/o for analog out
|
|
|
|
|
- * when the digital out is available, copy the front out to digital out, too.
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * snd_hda_multi_out_analog_prepare - Preapre the analog outputs.
|
|
|
|
|
+ *
|
|
|
|
|
+ * Set up the i/o for analog out.
|
|
|
|
|
+ * When the digital out is available, copy the front out to digital out, too.
|
|
|
*/
|
|
*/
|
|
|
int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
|
|
int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
|
|
|
struct hda_multi_out *mout,
|
|
struct hda_multi_out *mout,
|
|
@@ -3578,8 +3979,8 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
|
|
|
}
|
|
}
|
|
|
EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_prepare);
|
|
EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_prepare);
|
|
|
|
|
|
|
|
-/*
|
|
|
|
|
- * clean up the setting for analog out
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * snd_hda_multi_out_analog_cleanup - clean up the setting for analog out
|
|
|
*/
|
|
*/
|
|
|
int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec,
|
|
int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec,
|
|
|
struct hda_multi_out *mout)
|
|
struct hda_multi_out *mout)
|
|
@@ -3965,8 +4366,14 @@ EXPORT_SYMBOL_HDA(snd_hda_resume);
|
|
|
* generic arrays
|
|
* generic arrays
|
|
|
*/
|
|
*/
|
|
|
|
|
|
|
|
-/* get a new element from the given array
|
|
|
|
|
- * if it exceeds the pre-allocated array size, re-allocate the array
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * snd_array_new - get a new element from the given array
|
|
|
|
|
+ * @array: the array object
|
|
|
|
|
+ *
|
|
|
|
|
+ * Get a new element from the given array. If it exceeds the
|
|
|
|
|
+ * pre-allocated array size, re-allocate the array.
|
|
|
|
|
+ *
|
|
|
|
|
+ * Returns NULL if allocation failed.
|
|
|
*/
|
|
*/
|
|
|
void *snd_array_new(struct snd_array *array)
|
|
void *snd_array_new(struct snd_array *array)
|
|
|
{
|
|
{
|
|
@@ -3990,7 +4397,10 @@ void *snd_array_new(struct snd_array *array)
|
|
|
}
|
|
}
|
|
|
EXPORT_SYMBOL_HDA(snd_array_new);
|
|
EXPORT_SYMBOL_HDA(snd_array_new);
|
|
|
|
|
|
|
|
-/* free the given array elements */
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * snd_array_free - free the given array elements
|
|
|
|
|
+ * @array: the array object
|
|
|
|
|
+ */
|
|
|
void snd_array_free(struct snd_array *array)
|
|
void snd_array_free(struct snd_array *array)
|
|
|
{
|
|
{
|
|
|
kfree(array->list);
|
|
kfree(array->list);
|
|
@@ -4000,7 +4410,12 @@ void snd_array_free(struct snd_array *array)
|
|
|
}
|
|
}
|
|
|
EXPORT_SYMBOL_HDA(snd_array_free);
|
|
EXPORT_SYMBOL_HDA(snd_array_free);
|
|
|
|
|
|
|
|
-/*
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * snd_print_pcm_rates - Print the supported PCM rates to the string buffer
|
|
|
|
|
+ * @pcm: PCM caps bits
|
|
|
|
|
+ * @buf: the string buffer to write
|
|
|
|
|
+ * @buflen: the max buffer length
|
|
|
|
|
+ *
|
|
|
* used by hda_proc.c and hda_eld.c
|
|
* used by hda_proc.c and hda_eld.c
|
|
|
*/
|
|
*/
|
|
|
void snd_print_pcm_rates(int pcm, char *buf, int buflen)
|
|
void snd_print_pcm_rates(int pcm, char *buf, int buflen)
|
|
@@ -4019,6 +4434,14 @@ void snd_print_pcm_rates(int pcm, char *buf, int buflen)
|
|
|
}
|
|
}
|
|
|
EXPORT_SYMBOL_HDA(snd_print_pcm_rates);
|
|
EXPORT_SYMBOL_HDA(snd_print_pcm_rates);
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * snd_print_pcm_bits - Print the supported PCM fmt bits to the string buffer
|
|
|
|
|
+ * @pcm: PCM caps bits
|
|
|
|
|
+ * @buf: the string buffer to write
|
|
|
|
|
+ * @buflen: the max buffer length
|
|
|
|
|
+ *
|
|
|
|
|
+ * used by hda_proc.c and hda_eld.c
|
|
|
|
|
+ */
|
|
|
void snd_print_pcm_bits(int pcm, char *buf, int buflen)
|
|
void snd_print_pcm_bits(int pcm, char *buf, int buflen)
|
|
|
{
|
|
{
|
|
|
static unsigned int bits[] = { 8, 16, 20, 24, 32 };
|
|
static unsigned int bits[] = { 8, 16, 20, 24, 32 };
|