aboutsummaryrefslogtreecommitdiff
path: root/sound/pci/hda/hda_codec.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/hda/hda_codec.c')
-rw-r--r--sound/pci/hda/hda_codec.c693
1 files changed, 424 insertions, 269 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 5b6c4e3c92c..4c20277a683 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -23,9 +23,9 @@
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/slab.h>
-#include <linux/pci.h>
#include <linux/mutex.h>
#include <linux/module.h>
+#include <linux/async.h>
#include <sound/core.h>
#include "hda_codec.h"
#include <sound/asoundef.h>
@@ -67,6 +67,7 @@ static struct hda_vendor_id hda_vendor_ids[] = {
{ 0x17e8, "Chrontel" },
{ 0x1854, "LG" },
{ 0x1aec, "Wolfson Microelectronics" },
+ { 0x1af4, "QEMU" },
{ 0x434d, "C-Media" },
{ 0x8086, "Intel" },
{ 0x8384, "SigmaTel" },
@@ -83,7 +84,7 @@ int snd_hda_add_codec_preset(struct hda_codec_preset_list *preset)
mutex_unlock(&preset_mutex);
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_add_codec_preset);
+EXPORT_SYMBOL_GPL(snd_hda_add_codec_preset);
int snd_hda_delete_codec_preset(struct hda_codec_preset_list *preset)
{
@@ -92,23 +93,31 @@ int snd_hda_delete_codec_preset(struct hda_codec_preset_list *preset)
mutex_unlock(&preset_mutex);
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_delete_codec_preset);
+EXPORT_SYMBOL_GPL(snd_hda_delete_codec_preset);
#ifdef CONFIG_PM
#define codec_in_pm(codec) ((codec)->in_pm)
static void hda_power_work(struct work_struct *work);
static void hda_keep_power_on(struct hda_codec *codec);
#define hda_codec_is_power_on(codec) ((codec)->power_on)
-static inline void hda_call_pm_notify(struct hda_bus *bus, bool power_up)
+
+static void hda_call_pm_notify(struct hda_codec *codec, bool power_up)
{
+ struct hda_bus *bus = codec->bus;
+
+ if ((power_up && codec->pm_up_notified) ||
+ (!power_up && !codec->pm_up_notified))
+ return;
if (bus->ops.pm_notify)
bus->ops.pm_notify(bus, power_up);
+ codec->pm_up_notified = power_up;
}
+
#else
#define codec_in_pm(codec) 0
static inline void hda_keep_power_on(struct hda_codec *codec) {}
#define hda_codec_is_power_on(codec) 1
-#define hda_call_pm_notify(bus, state) {}
+#define hda_call_pm_notify(codec, state) {}
#endif
/**
@@ -143,7 +152,7 @@ const char *snd_hda_get_jack_location(u32 cfg)
}
return "UNKNOWN";
}
-EXPORT_SYMBOL_HDA(snd_hda_get_jack_location);
+EXPORT_SYMBOL_GPL(snd_hda_get_jack_location);
/**
* snd_hda_get_jack_connectivity - Give a connectivity string of the jack
@@ -158,7 +167,7 @@ const char *snd_hda_get_jack_connectivity(u32 cfg)
return jack_locations[(cfg >> (AC_DEFCFG_LOCATION_SHIFT + 4)) & 3];
}
-EXPORT_SYMBOL_HDA(snd_hda_get_jack_connectivity);
+EXPORT_SYMBOL_GPL(snd_hda_get_jack_connectivity);
/**
* snd_hda_get_jack_type - Give a type string of the jack
@@ -179,7 +188,7 @@ const char *snd_hda_get_jack_type(u32 cfg)
return jack_types[(cfg & AC_DEFCFG_DEVICE)
>> AC_DEFCFG_DEVICE_SHIFT];
}
-EXPORT_SYMBOL_HDA(snd_hda_get_jack_type);
+EXPORT_SYMBOL_GPL(snd_hda_get_jack_type);
/*
* Compose a 32bit command word to be sent to the HD-audio controller
@@ -192,7 +201,7 @@ make_codec_cmd(struct hda_codec *codec, hda_nid_t nid, int flags,
if ((codec->addr & ~0xf) || (nid & ~0x7f) ||
(verb & ~0xfff) || (parm & ~0xffff)) {
- printk(KERN_ERR "hda-codec: out of range cmd %x:%x:%x:%x\n",
+ codec_err(codec, "hda-codec: out of range cmd %x:%x:%x:%x\n",
codec->addr, nid, verb, parm);
return ~0;
}
@@ -240,8 +249,8 @@ static int codec_exec_verb(struct hda_codec *codec, unsigned int cmd,
snd_hda_power_down(codec);
if (!codec_in_pm(codec) && res && *res == -1 && bus->rirb_error) {
if (bus->response_reset) {
- snd_printd("hda_codec: resetting BUS due to "
- "fatal communication error\n");
+ codec_dbg(codec,
+ "resetting BUS due to fatal communication error\n");
trace_hda_bus_reset(bus);
bus->ops.bus_reset(bus);
}
@@ -275,7 +284,7 @@ unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid,
return -1;
return res;
}
-EXPORT_SYMBOL_HDA(snd_hda_codec_read);
+EXPORT_SYMBOL_GPL(snd_hda_codec_read);
/**
* snd_hda_codec_write - send a single command without waiting for response
@@ -297,7 +306,7 @@ int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int flags,
return codec_exec_verb(codec, cmd, flags,
codec->bus->sync_write ? &res : NULL);
}
-EXPORT_SYMBOL_HDA(snd_hda_codec_write);
+EXPORT_SYMBOL_GPL(snd_hda_codec_write);
/**
* snd_hda_sequence_write - sequence writes
@@ -312,7 +321,7 @@ void snd_hda_sequence_write(struct hda_codec *codec, const struct hda_verb *seq)
for (; seq->nid; seq++)
snd_hda_codec_write(codec, seq->nid, 0, seq->verb, seq->param);
}
-EXPORT_SYMBOL_HDA(snd_hda_sequence_write);
+EXPORT_SYMBOL_GPL(snd_hda_sequence_write);
/**
* snd_hda_get_sub_nodes - get the range of sub nodes
@@ -334,7 +343,7 @@ int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid,
*start_id = (parm >> 16) & 0x7fff;
return (int)(parm & 0x7fff);
}
-EXPORT_SYMBOL_HDA(snd_hda_get_sub_nodes);
+EXPORT_SYMBOL_GPL(snd_hda_get_sub_nodes);
/* connection list element */
struct hda_conn_list {
@@ -444,7 +453,7 @@ int snd_hda_get_conn_list(struct hda_codec *codec, hda_nid_t nid,
added = true;
}
}
-EXPORT_SYMBOL_HDA(snd_hda_get_conn_list);
+EXPORT_SYMBOL_GPL(snd_hda_get_conn_list);
/**
* snd_hda_get_connections - copy connection list
@@ -466,8 +475,7 @@ int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
if (len > 0 && conn_list) {
if (len > max_conns) {
- snd_printk(KERN_ERR "hda_codec: "
- "Too many connections %d for NID 0x%x\n",
+ codec_err(codec, "Too many connections %d for NID 0x%x\n",
len, nid);
return -EINVAL;
}
@@ -476,7 +484,7 @@ int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
return len;
}
-EXPORT_SYMBOL_HDA(snd_hda_get_connections);
+EXPORT_SYMBOL_GPL(snd_hda_get_connections);
/* return CONNLIST_LEN parameter of the given widget */
static unsigned int get_num_conns(struct hda_codec *codec, hda_nid_t nid)
@@ -565,8 +573,8 @@ int snd_hda_get_raw_connections(struct hda_codec *codec, hda_nid_t nid,
range_val = !!(parm & (1 << (shift-1))); /* ranges */
val = parm & mask;
if (val == 0 && null_count++) { /* no second chance */
- snd_printk(KERN_WARNING "hda_codec: "
- "invalid CONNECT_LIST verb %x[%i]:%x\n",
+ codec_dbg(codec,
+ "invalid CONNECT_LIST verb %x[%i]:%x\n",
nid, i, parm);
return 0;
}
@@ -574,7 +582,7 @@ int snd_hda_get_raw_connections(struct hda_codec *codec, hda_nid_t nid,
if (range_val) {
/* ranges between the previous and this one */
if (!prev_nid || prev_nid >= val) {
- snd_printk(KERN_WARNING "hda_codec: "
+ codec_warn(codec,
"invalid dep_range_val %x:%x\n",
prev_nid, val);
continue;
@@ -625,7 +633,7 @@ int snd_hda_override_conn_list(struct hda_codec *codec, hda_nid_t nid, int len,
return add_conn_list(codec, nid, len, list);
}
-EXPORT_SYMBOL_HDA(snd_hda_override_conn_list);
+EXPORT_SYMBOL_GPL(snd_hda_override_conn_list);
/**
* snd_hda_get_conn_index - get the connection index of the given NID
@@ -651,7 +659,7 @@ int snd_hda_get_conn_index(struct hda_codec *codec, hda_nid_t mux,
if (!recursive)
return -1;
if (recursive > 10) {
- snd_printd("hda_codec: too deep connection for 0x%x\n", nid);
+ codec_dbg(codec, "too deep connection for 0x%x\n", nid);
return -1;
}
recursive++;
@@ -664,7 +672,7 @@ int snd_hda_get_conn_index(struct hda_codec *codec, hda_nid_t mux,
}
return -1;
}
-EXPORT_SYMBOL_HDA(snd_hda_get_conn_index);
+EXPORT_SYMBOL_GPL(snd_hda_get_conn_index);
/* return DEVLIST_LEN parameter of the given widget */
@@ -760,7 +768,7 @@ int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex)
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_queue_unsol_event);
+EXPORT_SYMBOL_GPL(snd_hda_queue_unsol_event);
/*
* process queued unsolicited events
@@ -799,8 +807,7 @@ static int init_unsol_queue(struct hda_bus *bus)
unsol = kzalloc(sizeof(*unsol), GFP_KERNEL);
if (!unsol) {
- snd_printk(KERN_ERR "hda_codec: "
- "can't allocate unsolicited queue\n");
+ dev_err(bus->card->dev, "can't allocate unsolicited queue\n");
return -ENOMEM;
}
INIT_WORK(&unsol->work, process_unsol_events);
@@ -812,50 +819,36 @@ static int init_unsol_queue(struct hda_bus *bus)
/*
* destructor
*/
-static void snd_hda_codec_free(struct hda_codec *codec);
-
-static int snd_hda_bus_free(struct hda_bus *bus)
+static void snd_hda_bus_free(struct hda_bus *bus)
{
- struct hda_codec *codec, *n;
-
if (!bus)
- return 0;
+ return;
+
+ WARN_ON(!list_empty(&bus->codec_list));
if (bus->workq)
flush_workqueue(bus->workq);
if (bus->unsol)
kfree(bus->unsol);
- list_for_each_entry_safe(codec, n, &bus->codec_list, list) {
- snd_hda_codec_free(codec);
- }
if (bus->ops.private_free)
bus->ops.private_free(bus);
if (bus->workq)
destroy_workqueue(bus->workq);
+
kfree(bus);
- return 0;
}
static int snd_hda_bus_dev_free(struct snd_device *device)
{
- struct hda_bus *bus = device->device_data;
- bus->shutdown = 1;
- return snd_hda_bus_free(bus);
+ snd_hda_bus_free(device->device_data);
+ return 0;
}
-#ifdef CONFIG_SND_HDA_HWDEP
-static int snd_hda_bus_dev_register(struct snd_device *device)
+static int snd_hda_bus_dev_disconnect(struct snd_device *device)
{
struct hda_bus *bus = device->device_data;
- struct hda_codec *codec;
- list_for_each_entry(codec, &bus->codec_list, list) {
- snd_hda_hwdep_add_sysfs(codec);
- snd_hda_hwdep_add_power_sysfs(codec);
- }
+ bus->shutdown = 1;
return 0;
}
-#else
-#define snd_hda_bus_dev_register NULL
-#endif
/**
* snd_hda_bus_new - create a HDA bus
@@ -872,7 +865,7 @@ int snd_hda_bus_new(struct snd_card *card,
struct hda_bus *bus;
int err;
static struct snd_device_ops dev_ops = {
- .dev_register = snd_hda_bus_dev_register,
+ .dev_disconnect = snd_hda_bus_dev_disconnect,
.dev_free = snd_hda_bus_dev_free,
};
@@ -886,7 +879,7 @@ int snd_hda_bus_new(struct snd_card *card,
bus = kzalloc(sizeof(*bus), GFP_KERNEL);
if (bus == NULL) {
- snd_printk(KERN_ERR "can't allocate struct hda_bus\n");
+ dev_err(card->dev, "can't allocate struct hda_bus\n");
return -ENOMEM;
}
@@ -905,7 +898,7 @@ int snd_hda_bus_new(struct snd_card *card,
"hd-audio%d", card->number);
bus->workq = create_singlethread_workqueue(bus->workq_name);
if (!bus->workq) {
- snd_printk(KERN_ERR "cannot create workqueue %s\n",
+ dev_err(card->dev, "cannot create workqueue %s\n",
bus->workq_name);
kfree(bus);
return -ENOMEM;
@@ -920,9 +913,9 @@ int snd_hda_bus_new(struct snd_card *card,
*busp = bus;
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_bus_new);
+EXPORT_SYMBOL_GPL(snd_hda_bus_new);
-#ifdef CONFIG_SND_HDA_GENERIC
+#if IS_ENABLED(CONFIG_SND_HDA_GENERIC)
#define is_generic_config(codec) \
(codec->modelname && !strcmp(codec->modelname, "generic"))
#else
@@ -945,14 +938,11 @@ find_codec_preset(struct hda_codec *codec)
const struct hda_codec_preset *preset;
unsigned int mod_requested = 0;
- if (is_generic_config(codec))
- return NULL; /* use the generic parser */
-
again:
mutex_lock(&preset_mutex);
list_for_each_entry(tbl, &hda_preset_tables, list) {
if (!try_module_get(tbl->owner)) {
- snd_printk(KERN_ERR "hda_codec: cannot module_get\n");
+ codec_err(codec, "cannot module_get\n");
continue;
}
for (preset = tbl->preset; preset->id; preset++) {
@@ -1163,7 +1153,7 @@ int snd_hda_codec_set_pincfg(struct hda_codec *codec,
{
return snd_hda_add_pincfg(codec, &codec->driver_pins, nid, cfg);
}
-EXPORT_SYMBOL_HDA(snd_hda_codec_set_pincfg);
+EXPORT_SYMBOL_GPL(snd_hda_codec_set_pincfg);
/**
* snd_hda_codec_get_pincfg - Obtain a pin-default configuration
@@ -1178,7 +1168,7 @@ unsigned int snd_hda_codec_get_pincfg(struct hda_codec *codec, hda_nid_t nid)
{
struct hda_pincfg *pin;
-#ifdef CONFIG_SND_HDA_HWDEP
+#ifdef CONFIG_SND_HDA_RECONFIG
{
unsigned int cfg = 0;
mutex_lock(&codec->user_mutex);
@@ -1198,7 +1188,7 @@ unsigned int snd_hda_codec_get_pincfg(struct hda_codec *codec, hda_nid_t nid)
return pin->cfg;
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_codec_get_pincfg);
+EXPORT_SYMBOL_GPL(snd_hda_codec_get_pincfg);
/* remember the current pinctl target value */
int snd_hda_codec_set_pin_target(struct hda_codec *codec, hda_nid_t nid,
@@ -1212,7 +1202,7 @@ int snd_hda_codec_set_pin_target(struct hda_codec *codec, hda_nid_t nid,
pin->target = val;
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_codec_set_pin_target);
+EXPORT_SYMBOL_GPL(snd_hda_codec_set_pin_target);
/* return the current pinctl target value */
int snd_hda_codec_get_pin_target(struct hda_codec *codec, hda_nid_t nid)
@@ -1224,7 +1214,7 @@ int snd_hda_codec_get_pin_target(struct hda_codec *codec, hda_nid_t nid)
return 0;
return pin->target;
}
-EXPORT_SYMBOL_HDA(snd_hda_codec_get_pin_target);
+EXPORT_SYMBOL_GPL(snd_hda_codec_get_pin_target);
/**
* snd_hda_shutup_pins - Shut up all pins
@@ -1249,7 +1239,7 @@ void snd_hda_shutup_pins(struct hda_codec *codec)
}
codec->pins_shutup = 1;
}
-EXPORT_SYMBOL_HDA(snd_hda_shutup_pins);
+EXPORT_SYMBOL_GPL(snd_hda_shutup_pins);
#ifdef CONFIG_PM
/* Restore the pin controls cleared previously via snd_hda_shutup_pins() */
@@ -1293,7 +1283,7 @@ static void free_hda_cache(struct hda_cache_rec *cache);
static void free_init_pincfgs(struct hda_codec *codec)
{
snd_array_free(&codec->driver_pins);
-#ifdef CONFIG_SND_HDA_HWDEP
+#ifdef CONFIG_SND_HDA_RECONFIG
snd_array_free(&codec->user_pins);
#endif
snd_array_free(&codec->init_pins);
@@ -1330,6 +1320,20 @@ get_hda_cvt_setup(struct hda_codec *codec, hda_nid_t nid)
}
/*
+ * Dynamic symbol binding for the codec parsers
+ */
+
+#define load_parser(codec, sym) \
+ ((codec)->parser = (int (*)(struct hda_codec *))symbol_request(sym))
+
+static void unload_parser(struct hda_codec *codec)
+{
+ if (codec->parser)
+ symbol_put_addr(codec->parser);
+ codec->parser = NULL;
+}
+
+/*
* codec destructor
*/
static void snd_hda_codec_free(struct hda_codec *codec)
@@ -1352,10 +1356,9 @@ static void snd_hda_codec_free(struct hda_codec *codec)
codec->bus->caddr_tbl[codec->addr] = NULL;
if (codec->patch_ops.free)
codec->patch_ops.free(codec);
-#ifdef CONFIG_PM
- if (!codec->pm_down_notified) /* cancel leftover refcounts */
- hda_call_pm_notify(codec->bus, false);
-#endif
+ hda_call_pm_notify(codec, false); /* cancel leftover refcounts */
+ snd_hda_sysfs_clear(codec);
+ unload_parser(codec);
module_put(codec->owner);
free_hda_cache(&codec->amp_cache);
free_hda_cache(&codec->cmd_cache);
@@ -1363,7 +1366,8 @@ static void snd_hda_codec_free(struct hda_codec *codec)
kfree(codec->chip_name);
kfree(codec->modelname);
kfree(codec->wcaps);
- kfree(codec);
+ codec->bus->num_codecs--;
+ put_device(&codec->dev);
}
static bool snd_hda_codec_get_supported_ps(struct hda_codec *codec,
@@ -1372,6 +1376,38 @@ static bool snd_hda_codec_get_supported_ps(struct hda_codec *codec,
static unsigned int hda_set_power_state(struct hda_codec *codec,
unsigned int power_state);
+static int snd_hda_codec_dev_register(struct snd_device *device)
+{
+ struct hda_codec *codec = device->device_data;
+ int err = device_add(&codec->dev);
+
+ if (err < 0)
+ return err;
+ snd_hda_register_beep_device(codec);
+ return 0;
+}
+
+static int snd_hda_codec_dev_disconnect(struct snd_device *device)
+{
+ struct hda_codec *codec = device->device_data;
+
+ snd_hda_detach_beep_device(codec);
+ device_del(&codec->dev);
+ return 0;
+}
+
+static int snd_hda_codec_dev_free(struct snd_device *device)
+{
+ snd_hda_codec_free(device->device_data);
+ return 0;
+}
+
+/* just free the container */
+static void snd_hda_codec_dev_release(struct device *dev)
+{
+ kfree(container_of(dev, struct hda_codec, dev));
+}
+
/**
* snd_hda_codec_new - create a HDA codec
* @bus: the bus to assign
@@ -1388,6 +1424,11 @@ int snd_hda_codec_new(struct hda_bus *bus,
char component[31];
hda_nid_t fg;
int err;
+ static struct snd_device_ops dev_ops = {
+ .dev_register = snd_hda_codec_dev_register,
+ .dev_disconnect = snd_hda_codec_dev_disconnect,
+ .dev_free = snd_hda_codec_dev_free,
+ };
if (snd_BUG_ON(!bus))
return -EINVAL;
@@ -1395,17 +1436,27 @@ int snd_hda_codec_new(struct hda_bus *bus,
return -EINVAL;
if (bus->caddr_tbl[codec_addr]) {
- snd_printk(KERN_ERR "hda_codec: "
- "address 0x%x is already occupied\n", codec_addr);
+ dev_err(bus->card->dev,
+ "address 0x%x is already occupied\n",
+ codec_addr);
return -EBUSY;
}
codec = kzalloc(sizeof(*codec), GFP_KERNEL);
if (codec == NULL) {
- snd_printk(KERN_ERR "can't allocate struct hda_codec\n");
+ dev_err(bus->card->dev, "can't allocate struct hda_codec\n");
return -ENOMEM;
}
+ device_initialize(&codec->dev);
+ codec->dev.parent = &bus->card->card_dev;
+ codec->dev.class = sound_class;
+ codec->dev.release = snd_hda_codec_dev_release;
+ codec->dev.groups = snd_hda_dev_attr_groups;
+ dev_set_name(&codec->dev, "hdaudioC%dD%d", bus->card->number,
+ codec_addr);
+ dev_set_drvdata(&codec->dev, codec); /* for sysfs */
+
codec->bus = bus;
codec->addr = codec_addr;
mutex_init(&codec->spdif_mutex);
@@ -1424,6 +1475,7 @@ int snd_hda_codec_new(struct hda_bus *bus,
INIT_LIST_HEAD(&codec->conn_list);
INIT_DELAYED_WORK(&codec->jackpoll_work, hda_jackpoll_work);
+ codec->depop_delay = -1;
#ifdef CONFIG_PM
spin_lock_init(&codec->power_lock);
@@ -1433,18 +1485,21 @@ int snd_hda_codec_new(struct hda_bus *bus,
* phase.
*/
hda_keep_power_on(codec);
- hda_call_pm_notify(bus, true);
#endif
+ snd_hda_sysfs_init(codec);
+
if (codec->bus->modelname) {
codec->modelname = kstrdup(codec->bus->modelname, GFP_KERNEL);
if (!codec->modelname) {
- snd_hda_codec_free(codec);
- return -ENODEV;
+ err = -ENODEV;
+ goto error;
}
}
list_add_tail(&codec->list, &bus->codec_list);
+ bus->num_codecs++;
+
bus->caddr_tbl[codec_addr] = codec;
codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT,
@@ -1462,7 +1517,7 @@ int snd_hda_codec_new(struct hda_bus *bus,
setup_fg_nodes(codec);
if (!codec->afg && !codec->mfg) {
- snd_printdd("hda_codec: no AFG or MFG node found\n");
+ dev_err(bus->card->dev, "no AFG or MFG node found\n");
err = -ENODEV;
goto error;
}
@@ -1470,7 +1525,7 @@ int snd_hda_codec_new(struct hda_bus *bus,
fg = codec->afg ? codec->afg : codec->mfg;
err = read_widget_caps(codec, fg);
if (err < 0) {
- snd_printk(KERN_ERR "hda_codec: cannot malloc\n");
+ dev_err(bus->card->dev, "cannot malloc\n");
goto error;
}
err = read_pin_defaults(codec);
@@ -1486,11 +1541,14 @@ int snd_hda_codec_new(struct hda_bus *bus,
#ifdef CONFIG_PM
codec->d3_stop_clk = snd_hda_codec_get_supported_ps(codec, fg,
AC_PWRST_CLKSTOP);
- if (!codec->d3_stop_clk)
- bus->power_keep_link_on = 1;
#endif
codec->epss = snd_hda_codec_get_supported_ps(codec, fg,
AC_PWRST_EPSS);
+#ifdef CONFIG_PM
+ if (!codec->d3_stop_clk || !codec->epss)
+ bus->power_keep_link_on = 1;
+#endif
+
/* power-up all before initialization */
hda_set_power_state(codec, AC_PWRST_D0);
@@ -1503,6 +1561,10 @@ int snd_hda_codec_new(struct hda_bus *bus,
codec->subsystem_id, codec->revision_id);
snd_component_add(codec->bus->card, component);
+ err = snd_device_new(bus->card, SNDRV_DEV_CODEC, codec, &dev_ops);
+ if (err < 0)
+ goto error;
+
if (codecp)
*codecp = codec;
return 0;
@@ -1511,7 +1573,7 @@ int snd_hda_codec_new(struct hda_bus *bus,
snd_hda_codec_free(codec);
return err;
}
-EXPORT_SYMBOL_HDA(snd_hda_codec_new);
+EXPORT_SYMBOL_GPL(snd_hda_codec_new);
int snd_hda_codec_update_widgets(struct hda_codec *codec)
{
@@ -1525,7 +1587,7 @@ int snd_hda_codec_update_widgets(struct hda_codec *codec)
fg = codec->afg ? codec->afg : codec->mfg;
err = read_widget_caps(codec, fg);
if (err < 0) {
- snd_printk(KERN_ERR "hda_codec: cannot malloc\n");
+ codec_err(codec, "cannot malloc\n");
return err;
}
@@ -1534,8 +1596,33 @@ int snd_hda_codec_update_widgets(struct hda_codec *codec)
return err;
}
-EXPORT_SYMBOL_HDA(snd_hda_codec_update_widgets);
+EXPORT_SYMBOL_GPL(snd_hda_codec_update_widgets);
+
+
+#if IS_ENABLED(CONFIG_SND_HDA_CODEC_HDMI)
+/* if all audio out widgets are digital, let's assume the codec as a HDMI/DP */
+static bool is_likely_hdmi_codec(struct hda_codec *codec)
+{
+ hda_nid_t nid = codec->start_nid;
+ int i;
+ for (i = 0; i < codec->num_nodes; i++, nid++) {
+ unsigned int wcaps = get_wcaps(codec, nid);
+ switch (get_wcaps_type(wcaps)) {
+ case AC_WID_AUD_IN:
+ return false; /* HDMI parser supports only HDMI out */
+ case AC_WID_AUD_OUT:
+ if (!(wcaps & AC_WCAP_DIGITAL))
+ return false;
+ break;
+ }
+ }
+ return true;
+}
+#else
+/* no HDMI codec parser support */
+#define is_likely_hdmi_codec(codec) false
+#endif /* CONFIG_SND_HDA_CODEC_HDMI */
/**
* snd_hda_codec_configure - (Re-)configure the HD-audio codec
@@ -1548,6 +1635,7 @@ EXPORT_SYMBOL_HDA(snd_hda_codec_update_widgets);
*/
int snd_hda_codec_configure(struct hda_codec *codec)
{
+ int (*patch)(struct hda_codec *) = NULL;
int err;
codec->preset = find_codec_preset(codec);
@@ -1557,31 +1645,50 @@ int snd_hda_codec_configure(struct hda_codec *codec)
return err;
}
- if (is_generic_config(codec)) {
- err = snd_hda_parse_generic_codec(codec);
- goto patched;
- }
- if (codec->preset && codec->preset->patch) {
- err = codec->preset->patch(codec);
- goto patched;
+ if (!is_generic_config(codec) && codec->preset)
+ patch = codec->preset->patch;
+ if (!patch) {
+ unload_parser(codec); /* to be sure */
+ if (is_likely_hdmi_codec(codec)) {
+#if IS_MODULE(CONFIG_SND_HDA_CODEC_HDMI)
+ patch = load_parser(codec, snd_hda_parse_hdmi_codec);
+#elif IS_BUILTIN(CONFIG_SND_HDA_CODEC_HDMI)
+ patch = snd_hda_parse_hdmi_codec;
+#endif
+ }
+ if (!patch) {
+#if IS_MODULE(CONFIG_SND_HDA_GENERIC)
+ patch = load_parser(codec, snd_hda_parse_generic_codec);
+#elif IS_BUILTIN(CONFIG_SND_HDA_GENERIC)
+ patch = snd_hda_parse_generic_codec;
+#endif
+ }
+ if (!patch) {
+ codec_err(codec, "No codec parser is available\n");
+ return -ENODEV;
+ }
}
- /* call the default parser */
- err = snd_hda_parse_generic_codec(codec);
- if (err < 0)
- printk(KERN_ERR "hda-codec: No codec parser is available\n");
+ err = patch(codec);
+ if (err < 0) {
+ unload_parser(codec);
+ return err;
+ }
- patched:
- if (!err && codec->patch_ops.unsol_event)
+ if (codec->patch_ops.unsol_event) {
err = init_unsol_queue(codec->bus);
+ if (err < 0)
+ return err;
+ }
+
/* audio codec should override the mixer name */
- if (!err && (codec->afg || !*codec->bus->card->mixername))
+ if (codec->afg || !*codec->bus->card->mixername)
snprintf(codec->bus->card->mixername,
sizeof(codec->bus->card->mixername),
"%s %s", codec->vendor_name, codec->chip_name);
- return err;
+ return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_codec_configure);
+EXPORT_SYMBOL_GPL(snd_hda_codec_configure);
/* update the stream-id if changed */
static void update_pcm_stream_id(struct hda_codec *codec,
@@ -1641,9 +1748,9 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
if (!nid)
return;
- snd_printdd("hda_codec_setup_stream: "
- "NID=0x%x, stream=0x%x, channel=%d, format=0x%x\n",
- nid, stream_tag, channel_id, format);
+ codec_dbg(codec,
+ "hda_codec_setup_stream: NID=0x%x, stream=0x%x, channel=%d, format=0x%x\n",
+ nid, stream_tag, channel_id, format);
p = get_hda_cvt_setup(codec, nid);
if (!p)
return;
@@ -1668,7 +1775,7 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
}
}
}
-EXPORT_SYMBOL_HDA(snd_hda_codec_setup_stream);
+EXPORT_SYMBOL_GPL(snd_hda_codec_setup_stream);
static void really_cleanup_stream(struct hda_codec *codec,
struct hda_cvt_setup *q);
@@ -1690,7 +1797,7 @@ void __snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid,
if (codec->no_sticky_stream)
do_now = 1;
- snd_printdd("hda_codec_cleanup_stream: NID=0x%x\n", nid);
+ codec_dbg(codec, "hda_codec_cleanup_stream: NID=0x%x\n", nid);
p = get_hda_cvt_setup(codec, nid);
if (p) {
/* here we just clear the active flag when do_now isn't set;
@@ -1703,7 +1810,7 @@ void __snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid,
p->active = 0;
}
}
-EXPORT_SYMBOL_HDA(__snd_hda_codec_cleanup_stream);
+EXPORT_SYMBOL_GPL(__snd_hda_codec_cleanup_stream);
static void really_cleanup_stream(struct hda_codec *codec,
struct hda_cvt_setup *q)
@@ -1891,7 +1998,7 @@ u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction)
HDA_HASH_KEY(nid, direction, 0),
read_amp_cap);
}
-EXPORT_SYMBOL_HDA(query_amp_caps);
+EXPORT_SYMBOL_GPL(query_amp_caps);
/**
* snd_hda_override_amp_caps - Override the AMP capabilities
@@ -1911,7 +2018,7 @@ int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
{
return write_caps_hash(codec, HDA_HASH_KEY(nid, dir, 0), caps);
}
-EXPORT_SYMBOL_HDA(snd_hda_override_amp_caps);
+EXPORT_SYMBOL_GPL(snd_hda_override_amp_caps);
static unsigned int read_pin_cap(struct hda_codec *codec, hda_nid_t nid,
int dir)
@@ -1935,7 +2042,7 @@ u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid)
return query_caps_hash(codec, nid, 0, HDA_HASH_PINCAP_KEY(nid),
read_pin_cap);
}
-EXPORT_SYMBOL_HDA(snd_hda_query_pin_caps);
+EXPORT_SYMBOL_GPL(snd_hda_query_pin_caps);
/**
* snd_hda_override_pin_caps - Override the pin capabilities
@@ -1952,7 +2059,7 @@ int snd_hda_override_pin_caps(struct hda_codec *codec, hda_nid_t nid,
{
return write_caps_hash(codec, HDA_HASH_PINCAP_KEY(nid), caps);
}
-EXPORT_SYMBOL_HDA(snd_hda_override_pin_caps);
+EXPORT_SYMBOL_GPL(snd_hda_override_pin_caps);
/* read or sync the hash value with the current value;
* call within hash_mutex
@@ -2033,7 +2140,7 @@ int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch,
mutex_unlock(&codec->hash_mutex);
return val;
}
-EXPORT_SYMBOL_HDA(snd_hda_codec_amp_read);
+EXPORT_SYMBOL_GPL(snd_hda_codec_amp_read);
static int codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
int direction, int idx, int mask, int val,
@@ -2085,7 +2192,7 @@ int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
{
return codec_amp_update(codec, nid, ch, direction, idx, mask, val, false);
}
-EXPORT_SYMBOL_HDA(snd_hda_codec_amp_update);
+EXPORT_SYMBOL_GPL(snd_hda_codec_amp_update);
/**
* snd_hda_codec_amp_stereo - update the AMP stereo values
@@ -2111,7 +2218,7 @@ int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid,
idx, mask, val);
return ret;
}
-EXPORT_SYMBOL_HDA(snd_hda_codec_amp_stereo);
+EXPORT_SYMBOL_GPL(snd_hda_codec_amp_stereo);
/* Works like snd_hda_codec_amp_update() but it writes the value only at
* the first access. If the amp was already initialized / updated beforehand,
@@ -2122,7 +2229,7 @@ int snd_hda_codec_amp_init(struct hda_codec *codec, hda_nid_t nid, int ch,
{
return codec_amp_update(codec, nid, ch, dir, idx, mask, val, true);
}
-EXPORT_SYMBOL_HDA(snd_hda_codec_amp_init);
+EXPORT_SYMBOL_GPL(snd_hda_codec_amp_init);
int snd_hda_codec_amp_init_stereo(struct hda_codec *codec, hda_nid_t nid,
int dir, int idx, int mask, int val)
@@ -2136,7 +2243,7 @@ int snd_hda_codec_amp_init_stereo(struct hda_codec *codec, hda_nid_t nid,
idx, mask, val);
return ret;
}
-EXPORT_SYMBOL_HDA(snd_hda_codec_amp_init_stereo);
+EXPORT_SYMBOL_GPL(snd_hda_codec_amp_init_stereo);
/**
* snd_hda_codec_resume_amp - Resume all AMP commands from the cache
@@ -2179,7 +2286,7 @@ void snd_hda_codec_resume_amp(struct hda_codec *codec)
}
mutex_unlock(&codec->hash_mutex);
}
-EXPORT_SYMBOL_HDA(snd_hda_codec_resume_amp);
+EXPORT_SYMBOL_GPL(snd_hda_codec_resume_amp);
static u32 get_amp_max_value(struct hda_codec *codec, hda_nid_t nid, int dir,
unsigned int ofs)
@@ -2212,14 +2319,14 @@ int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol,
uinfo->value.integer.min = 0;
uinfo->value.integer.max = get_amp_max_value(codec, nid, dir, ofs);
if (!uinfo->value.integer.max) {
- printk(KERN_WARNING "hda_codec: "
- "num_steps = 0 for NID=0x%x (ctl = %s)\n", nid,
- kcontrol->id.name);
+ codec_warn(codec,
+ "num_steps = 0 for NID=0x%x (ctl = %s)\n",
+ nid, kcontrol->id.name);
return -EINVAL;
}
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_info);
+EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_volume_info);
static inline unsigned int
@@ -2276,7 +2383,7 @@ int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol,
*valp = read_amp_value(codec, nid, 1, dir, idx, ofs);
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_get);
+EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_volume_get);
/**
* snd_hda_mixer_amp_volume_put - Put callback for a standard AMP mixer volume
@@ -2306,7 +2413,7 @@ int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol,
snd_hda_power_down(codec);
return change;
}
-EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_put);
+EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_volume_put);
/**
* snd_hda_mixer_amp_volume_put - TLV callback for a standard AMP mixer volume
@@ -2344,7 +2451,7 @@ int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
return -EFAULT;
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_tlv);
+EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_tlv);
/**
* snd_hda_set_vmaster_tlv - Set TLV for a virtual master control
@@ -2372,7 +2479,7 @@ void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir,
tlv[2] = -nums * step;
tlv[3] = step;
}
-EXPORT_SYMBOL_HDA(snd_hda_set_vmaster_tlv);
+EXPORT_SYMBOL_GPL(snd_hda_set_vmaster_tlv);
/* find a mixer control element with the given name */
static struct snd_kcontrol *
@@ -2401,7 +2508,7 @@ struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
{
return find_mixer_ctl(codec, name, 0, 0);
}
-EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl);
+EXPORT_SYMBOL_GPL(snd_hda_find_mixer_ctl);
static int find_empty_mixer_ctl_idx(struct hda_codec *codec, const char *name,
int start_idx)
@@ -2461,7 +2568,7 @@ int snd_hda_ctl_add(struct hda_codec *codec, hda_nid_t nid,
item->flags = flags;
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_ctl_add);
+EXPORT_SYMBOL_GPL(snd_hda_ctl_add);
/**
* snd_hda_add_nid - Assign a NID to a control element
@@ -2488,11 +2595,11 @@ int snd_hda_add_nid(struct hda_codec *codec, struct snd_kcontrol *kctl,
item->nid = nid;
return 0;
}
- printk(KERN_ERR "hda-codec: no NID for mapping control %s:%d:%d\n",
- kctl->id.name, kctl->id.index, index);
+ codec_err(codec, "no NID for mapping control %s:%d:%d\n",
+ kctl->id.name, kctl->id.index, index);
return -EINVAL;
}
-EXPORT_SYMBOL_HDA(snd_hda_add_nid);
+EXPORT_SYMBOL_GPL(snd_hda_add_nid);
/**
* snd_hda_ctls_clear - Clear all controls assigned to the given codec
@@ -2543,7 +2650,7 @@ int snd_hda_lock_devices(struct hda_bus *bus)
spin_unlock(&card->files_lock);
return -EINVAL;
}
-EXPORT_SYMBOL_HDA(snd_hda_lock_devices);
+EXPORT_SYMBOL_GPL(snd_hda_lock_devices);
void snd_hda_unlock_devices(struct hda_bus *bus)
{
@@ -2554,7 +2661,7 @@ void snd_hda_unlock_devices(struct hda_bus *bus)
card->shutdown = 0;
spin_unlock(&card->files_lock);
}
-EXPORT_SYMBOL_HDA(snd_hda_unlock_devices);
+EXPORT_SYMBOL_GPL(snd_hda_unlock_devices);
/**
* snd_hda_codec_reset - Clear all objects assigned to the codec
@@ -2579,9 +2686,6 @@ int snd_hda_codec_reset(struct hda_codec *codec)
cancel_delayed_work_sync(&codec->jackpoll_work);
#ifdef CONFIG_PM
cancel_delayed_work_sync(&codec->power_work);
- codec->power_on = 0;
- codec->power_transition = 0;
- codec->power_jiffies = jiffies;
flush_workqueue(bus->workq);
#endif
snd_hda_ctls_clear(codec);
@@ -2593,6 +2697,7 @@ int snd_hda_codec_reset(struct hda_codec *codec)
bus->pcm_dev_bits);
}
}
+ snd_hda_detach_beep_device(codec);
if (codec->patch_ops.free)
codec->patch_ops.free(codec);
memset(&codec->patch_ops, 0, sizeof(codec->patch_ops));
@@ -2613,6 +2718,7 @@ int snd_hda_codec_reset(struct hda_codec *codec)
codec->preset = NULL;
codec->slave_dig_outs = NULL;
codec->spdif_status_reset = 0;
+ unload_parser(codec);
module_put(codec->owner);
codec->owner = NULL;
@@ -2634,8 +2740,7 @@ static int map_slaves(struct hda_codec *codec, const char * const *slaves,
items = codec->mixers.list;
for (i = 0; i < codec->mixers.used; i++) {
struct snd_kcontrol *sctl = items[i].kctl;
- if (!sctl || !sctl->id.name ||
- sctl->id.iface != SNDRV_CTL_ELEM_IFACE_MIXER)
+ if (!sctl || sctl->id.iface != SNDRV_CTL_ELEM_IFACE_MIXER)
continue;
for (s = slaves; *s; s++) {
char tmpname[sizeof(sctl->id.name)];
@@ -2662,7 +2767,7 @@ static int check_slave_present(void *data, struct snd_kcontrol *sctl)
}
/* guess the value corresponding to 0dB */
-static int get_kctl_0dB_offset(struct snd_kcontrol *kctl)
+static int get_kctl_0dB_offset(struct snd_kcontrol *kctl, int *step_to_check)
{
int _tlv[4];
const int *tlv = NULL;
@@ -2677,8 +2782,19 @@ static int get_kctl_0dB_offset(struct snd_kcontrol *kctl)
set_fs(fs);
} else if (kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_READ)
tlv = kctl->tlv.p;
- if (tlv && tlv[0] == SNDRV_CTL_TLVT_DB_SCALE)
- val = -tlv[2] / tlv[3];
+ if (tlv && tlv[0] == SNDRV_CTL_TLVT_DB_SCALE) {
+ int step = tlv[3];
+ step &= ~TLV_DB_SCALE_MUTE;
+ if (!step)
+ return -1;
+ if (*step_to_check && *step_to_check != step) {
+ snd_printk(KERN_ERR "hda_codec: Mismatching dB step for vmaster slave (%d!=%d)\n",
+- *step_to_check, step);
+ return -1;
+ }
+ *step_to_check = step;
+ val = -tlv[2] / step;
+ }
return val;
}
@@ -2699,7 +2815,7 @@ static int put_kctl_with_value(struct snd_kcontrol *kctl, int val)
/* initialize the slave volume with 0dB */
static int init_slave_0dB(void *data, struct snd_kcontrol *slave)
{
- int offset = get_kctl_0dB_offset(slave);
+ int offset = get_kctl_0dB_offset(slave, data);
if (offset > 0)
put_kctl_with_value(slave, offset);
return 0;
@@ -2743,7 +2859,7 @@ int __snd_hda_add_vmaster(struct hda_codec *codec, char *name,
err = map_slaves(codec, slaves, suffix, check_slave_present, NULL);
if (err != 1) {
- snd_printdd("No slave found for %s\n", name);
+ codec_dbg(codec, "No slave found for %s\n", name);
return 0;
}
kctl = snd_ctl_make_virtual_master(name, tlv);
@@ -2760,15 +2876,17 @@ int __snd_hda_add_vmaster(struct hda_codec *codec, char *name,
/* init with master mute & zero volume */
put_kctl_with_value(kctl, 0);
- if (init_slave_vol)
+ if (init_slave_vol) {
+ int step = 0;
map_slaves(codec, slaves, suffix,
- tlv ? init_slave_0dB : init_slave_unmute, kctl);
+ tlv ? init_slave_0dB : init_slave_unmute, &step);
+ }
if (ctl_ret)
*ctl_ret = kctl;
return 0;
}
-EXPORT_SYMBOL_HDA(__snd_hda_add_vmaster);
+EXPORT_SYMBOL_GPL(__snd_hda_add_vmaster);
/*
* mute-LED control using vmaster
@@ -2845,7 +2963,7 @@ int snd_hda_add_vmaster_hook(struct hda_codec *codec,
return -ENOMEM;
return snd_hda_ctl_add(codec, 0, kctl);
}
-EXPORT_SYMBOL_HDA(snd_hda_add_vmaster_hook);
+EXPORT_SYMBOL_GPL(snd_hda_add_vmaster_hook);
/*
* Call the hook with the current value for synchronization
@@ -2869,7 +2987,7 @@ void snd_hda_sync_vmaster_hook(struct hda_vmaster_mute_hook *hook)
break;
}
}
-EXPORT_SYMBOL_HDA(snd_hda_sync_vmaster_hook);
+EXPORT_SYMBOL_GPL(snd_hda_sync_vmaster_hook);
/**
@@ -2889,7 +3007,7 @@ int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol,
uinfo->value.integer.max = 1;
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_info);
+EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_switch_info);
/**
* snd_hda_mixer_amp_switch_get - Get callback for a standard AMP mixer switch
@@ -2915,7 +3033,7 @@ int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol,
HDA_AMP_MUTE) ? 0 : 1;
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_get);
+EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_switch_get);
/**
* snd_hda_mixer_amp_switch_put - Put callback for a standard AMP mixer switch
@@ -2949,7 +3067,7 @@ int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol,
snd_hda_power_down(codec);
return change;
}
-EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put);
+EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_switch_put);
/*
* bound volume controls
@@ -2981,7 +3099,7 @@ int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol,
mutex_unlock(&codec->control_mutex);
return err;
}
-EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_get);
+EXPORT_SYMBOL_GPL(snd_hda_mixer_bind_switch_get);
/**
* snd_hda_mixer_bind_switch_put - Put callback for a bound volume control
@@ -3011,7 +3129,7 @@ int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol,
mutex_unlock(&codec->control_mutex);
return err < 0 ? err : change;
}
-EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_put);
+EXPORT_SYMBOL_GPL(snd_hda_mixer_bind_switch_put);
/**
* snd_hda_mixer_bind_ctls_info - Info callback for a generic bound control
@@ -3034,7 +3152,7 @@ int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol,
mutex_unlock(&codec->control_mutex);
return err;
}
-EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_info);
+EXPORT_SYMBOL_GPL(snd_hda_mixer_bind_ctls_info);
/**
* snd_hda_mixer_bind_ctls_get - Get callback for a generic bound control
@@ -3057,7 +3175,7 @@ int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol,
mutex_unlock(&codec->control_mutex);
return err;
}
-EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_get);
+EXPORT_SYMBOL_GPL(snd_hda_mixer_bind_ctls_get);
/**
* snd_hda_mixer_bind_ctls_put - Put callback for a generic bound control
@@ -3086,7 +3204,7 @@ int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol,
mutex_unlock(&codec->control_mutex);
return err < 0 ? err : change;
}
-EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_put);
+EXPORT_SYMBOL_GPL(snd_hda_mixer_bind_ctls_put);
/**
* snd_hda_mixer_bind_tlv - TLV callback for a generic bound control
@@ -3109,7 +3227,7 @@ int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag,
mutex_unlock(&codec->control_mutex);
return err;
}
-EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_tlv);
+EXPORT_SYMBOL_GPL(snd_hda_mixer_bind_tlv);
struct hda_ctl_ops snd_hda_bind_vol = {
.info = snd_hda_mixer_amp_volume_info,
@@ -3117,7 +3235,7 @@ struct hda_ctl_ops snd_hda_bind_vol = {
.put = snd_hda_mixer_amp_volume_put,
.tlv = snd_hda_mixer_amp_tlv
};
-EXPORT_SYMBOL_HDA(snd_hda_bind_vol);
+EXPORT_SYMBOL_GPL(snd_hda_bind_vol);
struct hda_ctl_ops snd_hda_bind_sw = {
.info = snd_hda_mixer_amp_switch_info,
@@ -3125,7 +3243,7 @@ struct hda_ctl_ops snd_hda_bind_sw = {
.put = snd_hda_mixer_amp_switch_put,
.tlv = snd_hda_mixer_amp_tlv
};
-EXPORT_SYMBOL_HDA(snd_hda_bind_sw);
+EXPORT_SYMBOL_GPL(snd_hda_bind_sw);
/*
* SPDIF out controls
@@ -3407,7 +3525,7 @@ int snd_hda_create_dig_out_ctls(struct hda_codec *codec,
idx = find_empty_mixer_ctl_idx(codec, "IEC958 Playback Switch", idx);
if (idx < 0) {
- printk(KERN_ERR "hda_codec: too many IEC958 outputs\n");
+ codec_err(codec, "too many IEC958 outputs\n");
return -EBUSY;
}
spdif = snd_array_new(&codec->spdif_out);
@@ -3429,7 +3547,7 @@ int snd_hda_create_dig_out_ctls(struct hda_codec *codec,
spdif->status = convert_to_spdif_status(spdif->ctls);
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_create_dig_out_ctls);
+EXPORT_SYMBOL_GPL(snd_hda_create_dig_out_ctls);
/* get the hda_spdif_out entry from the given NID
* call within spdif_mutex lock
@@ -3446,7 +3564,7 @@ struct hda_spdif_out *snd_hda_spdif_out_of_nid(struct hda_codec *codec,
}
return NULL;
}
-EXPORT_SYMBOL_HDA(snd_hda_spdif_out_of_nid);
+EXPORT_SYMBOL_GPL(snd_hda_spdif_out_of_nid);
void snd_hda_spdif_ctls_unassign(struct hda_codec *codec, int idx)
{
@@ -3457,7 +3575,7 @@ void snd_hda_spdif_ctls_unassign(struct hda_codec *codec, int idx)
spdif->nid = (u16)-1;
mutex_unlock(&codec->spdif_mutex);
}
-EXPORT_SYMBOL_HDA(snd_hda_spdif_ctls_unassign);
+EXPORT_SYMBOL_GPL(snd_hda_spdif_ctls_unassign);
void snd_hda_spdif_ctls_assign(struct hda_codec *codec, int idx, hda_nid_t nid)
{
@@ -3473,7 +3591,7 @@ void snd_hda_spdif_ctls_assign(struct hda_codec *codec, int idx, hda_nid_t nid)
}
mutex_unlock(&codec->spdif_mutex);
}
-EXPORT_SYMBOL_HDA(snd_hda_spdif_ctls_assign);
+EXPORT_SYMBOL_GPL(snd_hda_spdif_ctls_assign);
/*
* SPDIF sharing with analog output
@@ -3521,7 +3639,7 @@ int snd_hda_create_spdif_share_sw(struct hda_codec *codec,
/* ATTENTION: here mout is passed as private_data, instead of codec */
return snd_hda_ctl_add(codec, mout->dig_out_nid, kctl);
}
-EXPORT_SYMBOL_HDA(snd_hda_create_spdif_share_sw);
+EXPORT_SYMBOL_GPL(snd_hda_create_spdif_share_sw);
/*
* SPDIF input
@@ -3611,7 +3729,7 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid)
idx = find_empty_mixer_ctl_idx(codec, "IEC958 Capture Switch", 0);
if (idx < 0) {
- printk(KERN_ERR "hda_codec: too many IEC958 inputs\n");
+ codec_err(codec, "too many IEC958 inputs\n");
return -EBUSY;
}
for (dig_mix = dig_in_ctls; dig_mix->name; dig_mix++) {
@@ -3629,7 +3747,7 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid)
AC_DIG1_ENABLE;
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_create_spdif_in_ctls);
+EXPORT_SYMBOL_GPL(snd_hda_create_spdif_in_ctls);
/*
* command cache
@@ -3680,7 +3798,7 @@ int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
mutex_unlock(&codec->bus->cmd_mutex);
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_codec_write_cache);
+EXPORT_SYMBOL_GPL(snd_hda_codec_write_cache);
/**
* snd_hda_codec_update_cache - check cache and write the cmd only when needed
@@ -3715,7 +3833,7 @@ int snd_hda_codec_update_cache(struct hda_codec *codec, hda_nid_t nid,
mutex_unlock(&codec->bus->cmd_mutex);
return snd_hda_codec_write_cache(codec, nid, flags, verb, parm);
}
-EXPORT_SYMBOL_HDA(snd_hda_codec_update_cache);
+EXPORT_SYMBOL_GPL(snd_hda_codec_update_cache);
/**
* snd_hda_codec_resume_cache - Resume the all commands from the cache
@@ -3747,7 +3865,7 @@ void snd_hda_codec_resume_cache(struct hda_codec *codec)
}
mutex_unlock(&codec->hash_mutex);
}
-EXPORT_SYMBOL_HDA(snd_hda_codec_resume_cache);
+EXPORT_SYMBOL_GPL(snd_hda_codec_resume_cache);
/**
* snd_hda_sequence_write_cache - sequence writes with caching
@@ -3765,7 +3883,7 @@ void snd_hda_sequence_write_cache(struct hda_codec *codec,
snd_hda_codec_write_cache(codec, seq->nid, 0, seq->verb,
seq->param);
}
-EXPORT_SYMBOL_HDA(snd_hda_sequence_write_cache);
+EXPORT_SYMBOL_GPL(snd_hda_sequence_write_cache);
/**
* snd_hda_codec_flush_cache - Execute all pending (cached) amps / verbs
@@ -3776,7 +3894,7 @@ void snd_hda_codec_flush_cache(struct hda_codec *codec)
snd_hda_codec_resume_amp(codec);
snd_hda_codec_resume_cache(codec);
}
-EXPORT_SYMBOL_HDA(snd_hda_codec_flush_cache);
+EXPORT_SYMBOL_GPL(snd_hda_codec_flush_cache);
void snd_hda_codec_set_power_to_all(struct hda_codec *codec, hda_nid_t fg,
unsigned int power_state)
@@ -3798,7 +3916,7 @@ void snd_hda_codec_set_power_to_all(struct hda_codec *codec, hda_nid_t fg,
state);
}
}
-EXPORT_SYMBOL_HDA(snd_hda_codec_set_power_to_all);
+EXPORT_SYMBOL_GPL(snd_hda_codec_set_power_to_all);
/*
* supported power states check
@@ -3847,6 +3965,8 @@ unsigned int snd_hda_codec_eapd_power_filter(struct hda_codec *codec,
hda_nid_t nid,
unsigned int power_state)
{
+ if (nid == codec->afg || nid == codec->mfg)
+ return power_state;
if (power_state == AC_PWRST_D3 &&
get_wcaps_type(get_wcaps(codec, nid)) == AC_WID_PIN &&
(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD)) {
@@ -3857,7 +3977,7 @@ unsigned int snd_hda_codec_eapd_power_filter(struct hda_codec *codec,
}
return power_state;
}
-EXPORT_SYMBOL_HDA(snd_hda_codec_eapd_power_filter);
+EXPORT_SYMBOL_GPL(snd_hda_codec_eapd_power_filter);
/*
* set power state of the codec, and return the power state
@@ -3872,8 +3992,10 @@ static unsigned int hda_set_power_state(struct hda_codec *codec,
/* this delay seems necessary to avoid click noise at power-down */
if (power_state == AC_PWRST_D3) {
- /* transition time less than 10ms for power down */
- msleep(codec->epss ? 10 : 100);
+ if (codec->depop_delay < 0)
+ msleep(codec->epss ? 10 : 100);
+ else if (codec->depop_delay > 0)
+ msleep(codec->depop_delay);
flags = HDA_RW_NO_RESPONSE_FALLBACK;
}
@@ -3883,9 +4005,13 @@ static unsigned int hda_set_power_state(struct hda_codec *codec,
codec->patch_ops.set_power_state(codec, fg,
power_state);
else {
- snd_hda_codec_read(codec, fg, flags,
- AC_VERB_SET_POWER_STATE,
- power_state);
+ state = power_state;
+ if (codec->power_filter)
+ state = codec->power_filter(codec, fg, state);
+ if (state == power_state || power_state != AC_PWRST_D3)
+ snd_hda_codec_read(codec, fg, flags,
+ AC_VERB_SET_POWER_STATE,
+ state);
snd_hda_codec_set_power_to_all(codec, fg, power_state);
}
state = hda_sync_power_state(codec, fg, power_state);
@@ -3922,7 +4048,7 @@ static void sync_power_up_states(struct hda_codec *codec)
}
}
-#ifdef CONFIG_SND_HDA_HWDEP
+#ifdef CONFIG_SND_HDA_RECONFIG
/* execute additional init verbs */
static void hda_exec_init_verbs(struct hda_codec *codec)
{
@@ -4030,19 +4156,20 @@ int snd_hda_build_controls(struct hda_bus *bus)
list_for_each_entry(codec, &bus->codec_list, list) {
int err = snd_hda_codec_build_controls(codec);
if (err < 0) {
- printk(KERN_ERR "hda_codec: cannot build controls "
- "for #%d (error %d)\n", codec->addr, err);
+ codec_err(codec,
+ "cannot build controls for #%d (error %d)\n",
+ codec->addr, err);
err = snd_hda_codec_reset(codec);
if (err < 0) {
- printk(KERN_ERR
- "hda_codec: cannot revert codec\n");
+ codec_err(codec,
+ "cannot revert codec\n");
return err;
}
}
}
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_build_controls);
+EXPORT_SYMBOL_GPL(snd_hda_build_controls);
/*
* add standard channel maps if not specified
@@ -4206,7 +4333,7 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate,
break;
default:
snd_printdd("invalid format width %d\n",
- snd_pcm_format_width(format));
+ snd_pcm_format_width(format));
return 0;
}
@@ -4215,7 +4342,7 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate,
return val;
}
-EXPORT_SYMBOL_HDA(snd_hda_calc_stream_format);
+EXPORT_SYMBOL_GPL(snd_hda_calc_stream_format);
static unsigned int get_pcm_param(struct hda_codec *codec, hda_nid_t nid,
int dir)
@@ -4282,10 +4409,10 @@ int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
rates |= rate_bits[i].alsa_bits;
}
if (rates == 0) {
- snd_printk(KERN_ERR "hda_codec: rates == 0 "
- "(nid=0x%x, val=0x%x, ovrd=%i)\n",
- nid, val,
- (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0);
+ codec_err(codec,
+ "rates == 0 (nid=0x%x, val=0x%x, ovrd=%i)\n",
+ nid, val,
+ (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0);
return -EIO;
}
*ratesp = rates;
@@ -4345,12 +4472,11 @@ int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
bps = 8;
}
if (formats == 0) {
- snd_printk(KERN_ERR "hda_codec: formats == 0 "
- "(nid=0x%x, val=0x%x, ovrd=%i, "
- "streams=0x%x)\n",
- nid, val,
- (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0,
- streams);
+ codec_err(codec,
+ "formats == 0 (nid=0x%x, val=0x%x, ovrd=%i, streams=0x%x)\n",
+ nid, val,
+ (wcaps & AC_WCAP_FORMAT_OVRD) ? 1 : 0,
+ streams);
return -EIO;
}
if (formatsp)
@@ -4361,7 +4487,7 @@ int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_query_supported_pcm);
+EXPORT_SYMBOL_GPL(snd_hda_query_supported_pcm);
/**
* snd_hda_is_supported_format - Check the validity of the format
@@ -4428,7 +4554,7 @@ int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid,
return 1;
}
-EXPORT_SYMBOL_HDA(snd_hda_is_supported_format);
+EXPORT_SYMBOL_GPL(snd_hda_is_supported_format);
/*
* PCM stuff
@@ -4506,7 +4632,7 @@ int snd_hda_codec_prepare(struct hda_codec *codec,
mutex_unlock(&codec->bus->prepare_mutex);
return ret;
}
-EXPORT_SYMBOL_HDA(snd_hda_codec_prepare);
+EXPORT_SYMBOL_GPL(snd_hda_codec_prepare);
void snd_hda_codec_cleanup(struct hda_codec *codec,
struct hda_pcm_stream *hinfo,
@@ -4516,7 +4642,7 @@ void snd_hda_codec_cleanup(struct hda_codec *codec,
hinfo->ops.cleanup(hinfo, codec, substream);
mutex_unlock(&codec->bus->prepare_mutex);
}
-EXPORT_SYMBOL_HDA(snd_hda_codec_cleanup);
+EXPORT_SYMBOL_GPL(snd_hda_codec_cleanup);
/* global */
const char *snd_hda_pcm_type_name[HDA_PCM_NTYPES] = {
@@ -4541,7 +4667,7 @@ static int get_empty_pcm_device(struct hda_bus *bus, unsigned int type)
int i;
if (type >= HDA_PCM_NTYPES) {
- snd_printk(KERN_WARNING "Invalid PCM type %d\n", type);
+ dev_err(bus->card->dev, "Invalid PCM type %d\n", type);
return -EINVAL;
}
@@ -4562,10 +4688,11 @@ static int get_empty_pcm_device(struct hda_bus *bus, unsigned int type)
}
#endif
- snd_printk(KERN_WARNING "Too many %s devices\n",
+ dev_warn(bus->card->dev, "Too many %s devices\n",
snd_hda_pcm_type_name[type]);
#ifndef CONFIG_SND_DYNAMIC_MINORS
- snd_printk(KERN_WARNING "Consider building the kernel with CONFIG_SND_DYNAMIC_MINORS=y\n");
+ dev_warn(bus->card->dev,
+ "Consider building the kernel with CONFIG_SND_DYNAMIC_MINORS=y\n");
#endif
return -EAGAIN;
}
@@ -4603,12 +4730,13 @@ int snd_hda_codec_build_pcms(struct hda_codec *codec)
return 0;
err = codec->patch_ops.build_pcms(codec);
if (err < 0) {
- printk(KERN_ERR "hda_codec: cannot build PCMs"
- "for #%d (error %d)\n", codec->addr, err);
+ codec_err(codec,
+ "cannot build PCMs for #%d (error %d)\n",
+ codec->addr, err);
err = snd_hda_codec_reset(codec);
if (err < 0) {
- printk(KERN_ERR
- "hda_codec: cannot revert codec\n");
+ codec_err(codec,
+ "cannot revert codec\n");
return err;
}
}
@@ -4627,9 +4755,9 @@ int snd_hda_codec_build_pcms(struct hda_codec *codec)
cpcm->device = dev;
err = snd_hda_attach_pcm(codec, cpcm);
if (err < 0) {
- printk(KERN_ERR "hda_codec: cannot attach "
- "PCM stream %d for codec #%d\n",
- dev, codec->addr);
+ codec_err(codec,
+ "cannot attach PCM stream %d for codec #%d\n",
+ dev, codec->addr);
continue; /* no fatal error */
}
}
@@ -4674,7 +4802,7 @@ int snd_hda_build_pcms(struct hda_bus *bus)
}
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_build_pcms);
+EXPORT_SYMBOL_GPL(snd_hda_build_pcms);
/**
* snd_hda_check_board_config - compare the current codec with the config table
@@ -4698,8 +4826,8 @@ int snd_hda_check_board_config(struct hda_codec *codec,
for (i = 0; i < num_configs; i++) {
if (models[i] &&
!strcmp(codec->modelname, models[i])) {
- snd_printd(KERN_INFO "hda_codec: model '%s' is "
- "selected\n", models[i]);
+ codec_info(codec, "model '%s' is selected\n",
+ models[i]);
return i;
}
}
@@ -4721,16 +4849,15 @@ int snd_hda_check_board_config(struct hda_codec *codec,
sprintf(tmp, "#%d", tbl->value);
model = tmp;
}
- snd_printdd(KERN_INFO "hda_codec: model '%s' is selected "
- "for config %x:%x (%s)\n",
- model, tbl->subvendor, tbl->subdevice,
- (tbl->name ? tbl->name : "Unknown device"));
+ codec_info(codec, "model '%s' is selected for config %x:%x (%s)\n",
+ model, tbl->subvendor, tbl->subdevice,
+ (tbl->name ? tbl->name : "Unknown device"));
#endif
return tbl->value;
}
return -1;
}
-EXPORT_SYMBOL_HDA(snd_hda_check_board_config);
+EXPORT_SYMBOL_GPL(snd_hda_check_board_config);
/**
* snd_hda_check_board_codec_sid_config - compare the current codec
@@ -4782,16 +4909,15 @@ int snd_hda_check_board_codec_sid_config(struct hda_codec *codec,
sprintf(tmp, "#%d", tbl->value);
model = tmp;
}
- snd_printdd(KERN_INFO "hda_codec: model '%s' is selected "
- "for config %x:%x (%s)\n",
- model, tbl->subvendor, tbl->subdevice,
- (tbl->name ? tbl->name : "Unknown device"));
+ codec_info(codec, "model '%s' is selected for config %x:%x (%s)\n",
+ model, tbl->subvendor, tbl->subdevice,
+ (tbl->name ? tbl->name : "Unknown device"));
#endif
return tbl->value;
}
return -1;
}
-EXPORT_SYMBOL_HDA(snd_hda_check_board_codec_sid_config);
+EXPORT_SYMBOL_GPL(snd_hda_check_board_codec_sid_config);
/**
* snd_hda_add_new_ctls - create controls from the array
@@ -4841,7 +4967,7 @@ int snd_hda_add_new_ctls(struct hda_codec *codec,
}
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_add_new_ctls);
+EXPORT_SYMBOL_GPL(snd_hda_add_new_ctls);
#ifdef CONFIG_PM
static void hda_power_work(struct work_struct *work)
@@ -4864,11 +4990,8 @@ static void hda_power_work(struct work_struct *work)
spin_unlock(&codec->power_lock);
state = hda_call_codec_suspend(codec, true);
- codec->pm_down_notified = 0;
- if (!bus->power_keep_link_on && (state & AC_PWRST_CLK_STOP_OK)) {
- codec->pm_down_notified = 1;
- hda_call_pm_notify(bus, false);
- }
+ if (!bus->power_keep_link_on && (state & AC_PWRST_CLK_STOP_OK))
+ hda_call_pm_notify(codec, false);
}
static void hda_keep_power_on(struct hda_codec *codec)
@@ -4878,6 +5001,7 @@ static void hda_keep_power_on(struct hda_codec *codec)
codec->power_on = 1;
codec->power_jiffies = jiffies;
spin_unlock(&codec->power_lock);
+ hda_call_pm_notify(codec, true);
}
/* update the power on/off account with the current jiffies */
@@ -4897,8 +5021,6 @@ void snd_hda_update_power_acct(struct hda_codec *codec)
/* call this with codec->power_lock held! */
static void __snd_hda_power_up(struct hda_codec *codec, bool wait_power_down)
{
- struct hda_bus *bus = codec->bus;
-
/* Return if power_on or transitioning to power_on, unless currently
* powering down. */
if ((codec->power_on || codec->power_transition > 0) &&
@@ -4925,11 +5047,6 @@ static void __snd_hda_power_up(struct hda_codec *codec, bool wait_power_down)
codec->power_transition = 1; /* avoid reentrance */
spin_unlock(&codec->power_lock);
- if (codec->pm_down_notified) {
- codec->pm_down_notified = 0;
- hda_call_pm_notify(bus, true);
- }
-
hda_call_codec_resume(codec);
spin_lock(&codec->power_lock);
@@ -4972,7 +5089,7 @@ void snd_hda_power_save(struct hda_codec *codec, int delta, bool d3wait)
__snd_hda_power_down(codec);
spin_unlock(&codec->power_lock);
}
-EXPORT_SYMBOL_HDA(snd_hda_power_save);
+EXPORT_SYMBOL_GPL(snd_hda_power_save);
/**
* snd_hda_check_amp_list_power - Check the amp list and update the power
@@ -5022,7 +5139,7 @@ int snd_hda_check_amp_list_power(struct hda_codec *codec,
}
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_check_amp_list_power);
+EXPORT_SYMBOL_GPL(snd_hda_check_amp_list_power);
#endif
/*
@@ -5046,7 +5163,7 @@ int snd_hda_ch_mode_info(struct hda_codec *codec,
chmode[uinfo->value.enumerated.item].channels);
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_ch_mode_info);
+EXPORT_SYMBOL_GPL(snd_hda_ch_mode_info);
/**
* snd_hda_ch_mode_get - Get callback helper for the channel mode enum
@@ -5067,7 +5184,7 @@ int snd_hda_ch_mode_get(struct hda_codec *codec,
}
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_ch_mode_get);
+EXPORT_SYMBOL_GPL(snd_hda_ch_mode_get);
/**
* snd_hda_ch_mode_put - Put callback helper for the channel mode enum
@@ -5091,7 +5208,7 @@ int snd_hda_ch_mode_put(struct hda_codec *codec,
snd_hda_sequence_write_cache(codec, chmode[mode].sequence);
return 1;
}
-EXPORT_SYMBOL_HDA(snd_hda_ch_mode_put);
+EXPORT_SYMBOL_GPL(snd_hda_ch_mode_put);
/*
* input MUX helper
@@ -5116,7 +5233,7 @@ int snd_hda_input_mux_info(const struct hda_input_mux *imux,
strcpy(uinfo->value.enumerated.name, imux->items[index].label);
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_input_mux_info);
+EXPORT_SYMBOL_GPL(snd_hda_input_mux_info);
/**
* snd_hda_input_mux_info_put - Put callback helper for the input-mux enum
@@ -5141,7 +5258,7 @@ int snd_hda_input_mux_put(struct hda_codec *codec,
*cur_val = idx;
return 1;
}
-EXPORT_SYMBOL_HDA(snd_hda_input_mux_put);
+EXPORT_SYMBOL_GPL(snd_hda_input_mux_put);
/*
@@ -5170,7 +5287,7 @@ int snd_hda_enum_helper_info(struct snd_kcontrol *kcontrol,
texts[uinfo->value.enumerated.item]);
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_enum_helper_info);
+EXPORT_SYMBOL_GPL(snd_hda_enum_helper_info);
/*
* Multi-channel / digital-out PCM helper functions
@@ -5236,7 +5353,7 @@ void snd_hda_bus_reboot_notify(struct hda_bus *bus)
codec->patch_ops.reboot_notify(codec);
}
}
-EXPORT_SYMBOL_HDA(snd_hda_bus_reboot_notify);
+EXPORT_SYMBOL_GPL(snd_hda_bus_reboot_notify);
/**
* snd_hda_multi_out_dig_open - open the digital out in the exclusive mode
@@ -5252,7 +5369,7 @@ int snd_hda_multi_out_dig_open(struct hda_codec *codec,
mutex_unlock(&codec->spdif_mutex);
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_open);
+EXPORT_SYMBOL_GPL(snd_hda_multi_out_dig_open);
/**
* snd_hda_multi_out_dig_prepare - prepare the digital out stream
@@ -5268,7 +5385,7 @@ int snd_hda_multi_out_dig_prepare(struct hda_codec *codec,
mutex_unlock(&codec->spdif_mutex);
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_prepare);
+EXPORT_SYMBOL_GPL(snd_hda_multi_out_dig_prepare);
/**
* snd_hda_multi_out_dig_cleanup - clean-up the digital out stream
@@ -5281,7 +5398,7 @@ int snd_hda_multi_out_dig_cleanup(struct hda_codec *codec,
mutex_unlock(&codec->spdif_mutex);
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_cleanup);
+EXPORT_SYMBOL_GPL(snd_hda_multi_out_dig_cleanup);
/**
* snd_hda_multi_out_dig_close - release the digital out stream
@@ -5294,7 +5411,7 @@ int snd_hda_multi_out_dig_close(struct hda_codec *codec,
mutex_unlock(&codec->spdif_mutex);
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_close);
+EXPORT_SYMBOL_GPL(snd_hda_multi_out_dig_close);
/**
* snd_hda_multi_out_analog_open - open analog outputs
@@ -5344,7 +5461,7 @@ int snd_hda_multi_out_analog_open(struct hda_codec *codec,
return snd_pcm_hw_constraint_step(substream->runtime, 0,
SNDRV_PCM_HW_PARAM_CHANNELS, 2);
}
-EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_open);
+EXPORT_SYMBOL_GPL(snd_hda_multi_out_analog_open);
/**
* snd_hda_multi_out_analog_prepare - Preapre the analog outputs.
@@ -5395,11 +5512,6 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
snd_hda_codec_setup_stream(codec,
mout->hp_out_nid[i],
stream_tag, 0, format);
- for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
- if (!mout->no_share_stream && mout->extra_out_nid[i])
- snd_hda_codec_setup_stream(codec,
- mout->extra_out_nid[i],
- stream_tag, 0, format);
/* surrounds */
for (i = 1; i < mout->num_dacs; i++) {
@@ -5410,9 +5522,23 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
0, format);
}
+
+ /* extra surrounds */
+ for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++) {
+ int ch = 0;
+ if (!mout->extra_out_nid[i])
+ break;
+ if (chs >= (i + 1) * 2)
+ ch = i * 2;
+ else if (!mout->no_share_stream)
+ break;
+ snd_hda_codec_setup_stream(codec, mout->extra_out_nid[i],
+ stream_tag, ch, format);
+ }
+
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_prepare);
+EXPORT_SYMBOL_GPL(snd_hda_multi_out_analog_prepare);
/**
* snd_hda_multi_out_analog_cleanup - clean up the setting for analog out
@@ -5443,7 +5569,7 @@ int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec,
mutex_unlock(&codec->spdif_mutex);
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_cleanup);
+EXPORT_SYMBOL_GPL(snd_hda_multi_out_analog_cleanup);
/**
* snd_hda_get_default_vref - Get the default (mic) VREF pin bits
@@ -5470,7 +5596,7 @@ unsigned int snd_hda_get_default_vref(struct hda_codec *codec, hda_nid_t pin)
return AC_PINCTL_VREF_GRD;
return AC_PINCTL_VREF_HIZ;
}
-EXPORT_SYMBOL_HDA(snd_hda_get_default_vref);
+EXPORT_SYMBOL_GPL(snd_hda_get_default_vref);
/* correct the pin ctl value for matching with the pin cap */
unsigned int snd_hda_correct_pin_ctl(struct hda_codec *codec,
@@ -5521,7 +5647,7 @@ unsigned int snd_hda_correct_pin_ctl(struct hda_codec *codec,
return val;
}
-EXPORT_SYMBOL_HDA(snd_hda_correct_pin_ctl);
+EXPORT_SYMBOL_GPL(snd_hda_correct_pin_ctl);
int _snd_hda_set_pin_ctl(struct hda_codec *codec, hda_nid_t pin,
unsigned int val, bool cached)
@@ -5535,7 +5661,7 @@ int _snd_hda_set_pin_ctl(struct hda_codec *codec, hda_nid_t pin,
return snd_hda_codec_write(codec, pin, 0,
AC_VERB_SET_PIN_WIDGET_CONTROL, val);
}
-EXPORT_SYMBOL_HDA(_snd_hda_set_pin_ctl);
+EXPORT_SYMBOL_GPL(_snd_hda_set_pin_ctl);
/**
* snd_hda_add_imux_item - Add an item to input_mux
@@ -5569,7 +5695,7 @@ int snd_hda_add_imux_item(struct hda_input_mux *imux, const char *label,
imux->num_items++;
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_add_imux_item);
+EXPORT_SYMBOL_GPL(snd_hda_add_imux_item);
#ifdef CONFIG_PM
@@ -5577,6 +5703,17 @@ EXPORT_SYMBOL_HDA(snd_hda_add_imux_item);
* power management
*/
+
+static void hda_async_suspend(void *data, async_cookie_t cookie)
+{
+ hda_call_codec_suspend(data, false);
+}
+
+static void hda_async_resume(void *data, async_cookie_t cookie)
+{
+ hda_call_codec_resume(data);
+}
+
/**
* snd_hda_suspend - suspend the codecs
* @bus: the HDA bus
@@ -5586,15 +5723,25 @@ EXPORT_SYMBOL_HDA(snd_hda_add_imux_item);
int snd_hda_suspend(struct hda_bus *bus)
{
struct hda_codec *codec;
+ ASYNC_DOMAIN_EXCLUSIVE(domain);
list_for_each_entry(codec, &bus->codec_list, list) {
cancel_delayed_work_sync(&codec->jackpoll_work);
- if (hda_codec_is_power_on(codec))
- hda_call_codec_suspend(codec, false);
+ if (hda_codec_is_power_on(codec)) {
+ if (bus->num_codecs > 1)
+ async_schedule_domain(hda_async_suspend, codec,
+ &domain);
+ else
+ hda_call_codec_suspend(codec, false);
+ }
}
+
+ if (bus->num_codecs > 1)
+ async_synchronize_full_domain(&domain);
+
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_suspend);
+EXPORT_SYMBOL_GPL(snd_hda_suspend);
/**
* snd_hda_resume - resume the codecs
@@ -5605,13 +5752,21 @@ EXPORT_SYMBOL_HDA(snd_hda_suspend);
int snd_hda_resume(struct hda_bus *bus)
{
struct hda_codec *codec;
+ ASYNC_DOMAIN_EXCLUSIVE(domain);
list_for_each_entry(codec, &bus->codec_list, list) {
- hda_call_codec_resume(codec);
+ if (bus->num_codecs > 1)
+ async_schedule_domain(hda_async_resume, codec, &domain);
+ else
+ hda_call_codec_resume(codec);
}
+
+ if (bus->num_codecs > 1)
+ async_synchronize_full_domain(&domain);
+
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_resume);
+EXPORT_SYMBOL_GPL(snd_hda_resume);
#endif /* CONFIG_PM */
/*
@@ -5645,7 +5800,7 @@ void *snd_array_new(struct snd_array *array)
}
return snd_array_elem(array, array->used++);
}
-EXPORT_SYMBOL_HDA(snd_array_new);
+EXPORT_SYMBOL_GPL(snd_array_new);
/**
* snd_array_free - free the given array elements
@@ -5658,7 +5813,7 @@ void snd_array_free(struct snd_array *array)
array->alloced = 0;
array->list = NULL;
}
-EXPORT_SYMBOL_HDA(snd_array_free);
+EXPORT_SYMBOL_GPL(snd_array_free);
/**
* snd_print_pcm_bits - Print the supported PCM fmt bits to the string buffer
@@ -5679,7 +5834,7 @@ void snd_print_pcm_bits(int pcm, char *buf, int buflen)
buf[j] = '\0'; /* necessary when j == 0 */
}
-EXPORT_SYMBOL_HDA(snd_print_pcm_bits);
+EXPORT_SYMBOL_GPL(snd_print_pcm_bits);
MODULE_DESCRIPTION("HDA codec core");
MODULE_LICENSE("GPL");