Commit 8f88f025 authored by Takashi Iwai's avatar Takashi Iwai

Merge branch 'topic/hda-bus' into for-next

parents 34e72afe 820cc6cf
......@@ -4,7 +4,7 @@ snd-hda-tegra-objs := hda_tegra.o
# for haswell power well
snd-hda-intel-$(CONFIG_SND_HDA_I915) += hda_i915.o
snd-hda-codec-y := hda_codec.o hda_jack.o hda_auto_parser.o hda_sysfs.o
snd-hda-codec-y := hda_bind.o hda_codec.o hda_jack.o hda_auto_parser.o hda_sysfs.o
snd-hda-codec-$(CONFIG_PROC_FS) += hda_proc.o
snd-hda-codec-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o
snd-hda-codec-$(CONFIG_SND_HDA_INPUT_BEEP) += hda_beep.o
......
......@@ -160,6 +160,7 @@ static int snd_hda_do_attach(struct hda_beep *beep)
input_dev->name = "HDA Digital PCBeep";
input_dev->phys = beep->phys;
input_dev->id.bustype = BUS_PCI;
input_dev->dev.parent = &codec->bus->card->card_dev;
input_dev->id.vendor = codec->vendor_id >> 16;
input_dev->id.product = codec->vendor_id & 0xffff;
......@@ -168,7 +169,6 @@ static int snd_hda_do_attach(struct hda_beep *beep)
input_dev->evbit[0] = BIT_MASK(EV_SND);
input_dev->sndbit[0] = BIT_MASK(SND_BELL) | BIT_MASK(SND_TONE);
input_dev->event = snd_hda_beep_event;
input_dev->dev.parent = &codec->dev;
input_set_drvdata(input_dev, beep);
beep->dev = input_dev;
......
/*
* HD-audio codec driver binding
* Copyright (c) Takashi Iwai <tiwai@suse.de>
*/
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/mutex.h>
#include <linux/module.h>
#include <linux/export.h>
#include <linux/pm.h>
#include <sound/core.h>
#include "hda_codec.h"
#include "hda_local.h"
/* codec vendor labels */
struct hda_vendor_id {
unsigned int id;
const char *name;
};
static struct hda_vendor_id hda_vendor_ids[] = {
{ 0x1002, "ATI" },
{ 0x1013, "Cirrus Logic" },
{ 0x1057, "Motorola" },
{ 0x1095, "Silicon Image" },
{ 0x10de, "Nvidia" },
{ 0x10ec, "Realtek" },
{ 0x1102, "Creative" },
{ 0x1106, "VIA" },
{ 0x111d, "IDT" },
{ 0x11c1, "LSI" },
{ 0x11d4, "Analog Devices" },
{ 0x13f6, "C-Media" },
{ 0x14f1, "Conexant" },
{ 0x17e8, "Chrontel" },
{ 0x1854, "LG" },
{ 0x1aec, "Wolfson Microelectronics" },
{ 0x1af4, "QEMU" },
{ 0x434d, "C-Media" },
{ 0x8086, "Intel" },
{ 0x8384, "SigmaTel" },
{} /* terminator */
};
/*
* find a matching codec preset
*/
static int hda_bus_match(struct device *dev, struct device_driver *drv)
{
struct hda_codec *codec = container_of(dev, struct hda_codec, dev);
struct hda_codec_driver *driver =
container_of(drv, struct hda_codec_driver, driver);
const struct hda_codec_preset *preset;
/* check probe_id instead of vendor_id if set */
u32 id = codec->probe_id ? codec->probe_id : codec->vendor_id;
for (preset = driver->preset; preset->id; preset++) {
u32 mask = preset->mask;
if (preset->afg && preset->afg != codec->afg)
continue;
if (preset->mfg && preset->mfg != codec->mfg)
continue;
if (!mask)
mask = ~0;
if (preset->id == (id & mask) &&
(!preset->rev || preset->rev == codec->revision_id)) {
codec->preset = preset;
return 1;
}
}
return 0;
}
/* reset the codec name from the preset */
static int codec_refresh_name(struct hda_codec *codec, const char *name)
{
char tmp[16];
kfree(codec->chip_name);
if (!name) {
sprintf(tmp, "ID %x", codec->vendor_id & 0xffff);
name = tmp;
}
codec->chip_name = kstrdup(name, GFP_KERNEL);
return codec->chip_name ? 0 : -ENOMEM;
}
static int hda_codec_driver_probe(struct device *dev)
{
struct hda_codec *codec = dev_to_hda_codec(dev);
struct module *owner = dev->driver->owner;
int err;
if (WARN_ON(!codec->preset))
return -EINVAL;
err = codec_refresh_name(codec, codec->preset->name);
if (err < 0)
goto error;
if (!try_module_get(owner)) {
err = -EINVAL;
goto error;
}
err = codec->preset->patch(codec);
if (err < 0) {
module_put(owner);
goto error;
}
return 0;
error:
codec->preset = NULL;
memset(&codec->patch_ops, 0, sizeof(codec->patch_ops));
return err;
}
static int hda_codec_driver_remove(struct device *dev)
{
struct hda_codec *codec = dev_to_hda_codec(dev);
if (codec->patch_ops.free)
codec->patch_ops.free(codec);
codec->preset = NULL;
memset(&codec->patch_ops, 0, sizeof(codec->patch_ops));
module_put(dev->driver->owner);
return 0;
}
int __hda_codec_driver_register(struct hda_codec_driver *drv, const char *name,
struct module *owner)
{
drv->driver.name = name;
drv->driver.owner = owner;
drv->driver.bus = &snd_hda_bus_type;
drv->driver.probe = hda_codec_driver_probe;
drv->driver.remove = hda_codec_driver_remove;
drv->driver.pm = &hda_codec_driver_pm;
return driver_register(&drv->driver);
}
EXPORT_SYMBOL_GPL(__hda_codec_driver_register);
void hda_codec_driver_unregister(struct hda_codec_driver *drv)
{
driver_unregister(&drv->driver);
}
EXPORT_SYMBOL_GPL(hda_codec_driver_unregister);
static inline bool codec_probed(struct hda_codec *codec)
{
return device_attach(hda_codec_dev(codec)) > 0 && codec->preset;
}
/* try to auto-load and bind the codec module */
static void codec_bind_module(struct hda_codec *codec)
{
#ifdef MODULE
request_module("snd-hda-codec-id:%08x", codec->vendor_id);
if (codec_probed(codec))
return;
request_module("snd-hda-codec-id:%04x*",
(codec->vendor_id >> 16) & 0xffff);
if (codec_probed(codec))
return;
#endif
}
/* store the codec vendor name */
static int get_codec_vendor_name(struct hda_codec *codec)
{
const struct hda_vendor_id *c;
const char *vendor = NULL;
u16 vendor_id = codec->vendor_id >> 16;
char tmp[16];
for (c = hda_vendor_ids; c->id; c++) {
if (c->id == vendor_id) {
vendor = c->name;
break;
}
}
if (!vendor) {
sprintf(tmp, "Generic %04x", vendor_id);
vendor = tmp;
}
codec->vendor_name = kstrdup(vendor, GFP_KERNEL);
if (!codec->vendor_name)
return -ENOMEM;
return 0;
}
#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 */
static int codec_bind_generic(struct hda_codec *codec)
{
if (codec->probe_id)
return -ENODEV;
if (is_likely_hdmi_codec(codec)) {
codec->probe_id = HDA_CODEC_ID_GENERIC_HDMI;
#if IS_MODULE(CONFIG_SND_HDA_CODEC_HDMI)
request_module("snd-hda-codec-hdmi");
#endif
if (codec_probed(codec))
return 0;
}
codec->probe_id = HDA_CODEC_ID_GENERIC;
#if IS_MODULE(CONFIG_SND_HDA_GENERIC)
request_module("snd-hda-codec-generic");
#endif
if (codec_probed(codec))
return 0;
return -ENODEV;
}
#if IS_ENABLED(CONFIG_SND_HDA_GENERIC)
#define is_generic_config(codec) \
(codec->modelname && !strcmp(codec->modelname, "generic"))
#else
#define is_generic_config(codec) 0
#endif
/**
* 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 err;
if (!codec->vendor_name) {
err = get_codec_vendor_name(codec);
if (err < 0)
return err;
}
if (is_generic_config(codec))
codec->probe_id = HDA_CODEC_ID_GENERIC;
else
codec->probe_id = 0;
err = device_add(hda_codec_dev(codec));
if (err < 0)
return err;
if (!codec->preset)
codec_bind_module(codec);
if (!codec->preset) {
err = codec_bind_generic(codec);
if (err < 0) {
codec_err(codec, "Unable to bind the codec\n");
goto error;
}
}
/* audio codec should override the mixer name */
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 0;
error:
device_del(hda_codec_dev(codec));
return err;
}
EXPORT_SYMBOL_GPL(snd_hda_codec_configure);
/*
* bus registration
*/
struct bus_type snd_hda_bus_type = {
.name = "hdaudio",
.match = hda_bus_match,
};
static int __init hda_codec_init(void)
{
return bus_register(&snd_hda_bus_type);
}
static void __exit hda_codec_exit(void)
{
bus_unregister(&snd_hda_bus_type);
}
module_init(hda_codec_init);
module_exit(hda_codec_exit);
......@@ -26,6 +26,8 @@
#include <linux/mutex.h>
#include <linux/module.h>
#include <linux/async.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
#include <sound/core.h>
#include "hda_codec.h"
#include <sound/asoundef.h>
......@@ -40,92 +42,13 @@
#define CREATE_TRACE_POINTS
#include "hda_trace.h"
/*
* vendor / preset table
*/
struct hda_vendor_id {
unsigned int id;
const char *name;
};
/* codec vendor labels */
static struct hda_vendor_id hda_vendor_ids[] = {
{ 0x1002, "ATI" },
{ 0x1013, "Cirrus Logic" },
{ 0x1057, "Motorola" },
{ 0x1095, "Silicon Image" },
{ 0x10de, "Nvidia" },
{ 0x10ec, "Realtek" },
{ 0x1102, "Creative" },
{ 0x1106, "VIA" },
{ 0x111d, "IDT" },
{ 0x11c1, "LSI" },
{ 0x11d4, "Analog Devices" },
{ 0x13f6, "C-Media" },
{ 0x14f1, "Conexant" },
{ 0x17e8, "Chrontel" },
{ 0x1854, "LG" },
{ 0x1aec, "Wolfson Microelectronics" },
{ 0x1af4, "QEMU" },
{ 0x434d, "C-Media" },
{ 0x8086, "Intel" },
{ 0x8384, "SigmaTel" },
{} /* terminator */
};
static DEFINE_MUTEX(preset_mutex);
static LIST_HEAD(hda_preset_tables);
/**
* snd_hda_add_codec_preset - Add a codec preset to the chain
* @preset: codec preset table to add
*/
int snd_hda_add_codec_preset(struct hda_codec_preset_list *preset)
{
mutex_lock(&preset_mutex);
list_add_tail(&preset->list, &hda_preset_tables);
mutex_unlock(&preset_mutex);
return 0;
}
EXPORT_SYMBOL_GPL(snd_hda_add_codec_preset);
/**
* snd_hda_delete_codec_preset - Delete a codec preset from the chain
* @preset: codec preset table to delete
*/
int snd_hda_delete_codec_preset(struct hda_codec_preset_list *preset)
{
mutex_lock(&preset_mutex);
list_del(&preset->list);
mutex_unlock(&preset_mutex);
return 0;
}
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 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;
}
#define codec_in_pm(codec) atomic_read(&(codec)->in_pm)
#define hda_codec_is_power_on(codec) \
(!pm_runtime_suspended(hda_codec_dev(codec)))
#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(codec, state) {}
#endif
/**
......@@ -885,111 +808,6 @@ int snd_hda_bus_new(struct snd_card *card,
}
EXPORT_SYMBOL_GPL(snd_hda_bus_new);
#if IS_ENABLED(CONFIG_SND_HDA_GENERIC)
#define is_generic_config(codec) \
(codec->modelname && !strcmp(codec->modelname, "generic"))
#else
#define is_generic_config(codec) 0
#endif
#ifdef MODULE
#define HDA_MODREQ_MAX_COUNT 2 /* two request_modules()'s */
#else
#define HDA_MODREQ_MAX_COUNT 0 /* all presets are statically linked */
#endif
/*
* find a matching codec preset
*/
static const struct hda_codec_preset *
find_codec_preset(struct hda_codec *codec)
{
struct hda_codec_preset_list *tbl;
const struct hda_codec_preset *preset;
unsigned int mod_requested = 0;
again:
mutex_lock(&preset_mutex);
list_for_each_entry(tbl, &hda_preset_tables, list) {
if (!try_module_get(tbl->owner)) {
codec_err(codec, "cannot module_get\n");
continue;
}
for (preset = tbl->preset; preset->id; preset++) {
u32 mask = preset->mask;
if (preset->afg && preset->afg != codec->afg)
continue;
if (preset->mfg && preset->mfg != codec->mfg)
continue;
if (!mask)
mask = ~0;
if (preset->id == (codec->vendor_id & mask) &&
(!preset->rev ||
preset->rev == codec->revision_id)) {
mutex_unlock(&preset_mutex);
codec->owner = tbl->owner;
return preset;
}
}
module_put(tbl->owner);
}
mutex_unlock(&preset_mutex);
if (mod_requested < HDA_MODREQ_MAX_COUNT) {
if (!mod_requested)
request_module("snd-hda-codec-id:%08x",
codec->vendor_id);
else
request_module("snd-hda-codec-id:%04x*",
(codec->vendor_id >> 16) & 0xffff);
mod_requested++;
goto again;
}
return NULL;
}
/*
* get_codec_name - store the codec name
*/
static int get_codec_name(struct hda_codec *codec)
{
const struct hda_vendor_id *c;
const char *vendor = NULL;
u16 vendor_id = codec->vendor_id >> 16;
char tmp[16];
if (codec->vendor_name)
goto get_chip_name;
for (c = hda_vendor_ids; c->id; c++) {
if (c->id == vendor_id) {
vendor = c->name;
break;
}
}
if (!vendor) {
sprintf(tmp, "Generic %04x", vendor_id);
vendor = tmp;
}
codec->vendor_name = kstrdup(vendor, GFP_KERNEL);
if (!codec->vendor_name)
return -ENOMEM;
get_chip_name:
if (codec->chip_name)
return 0;
if (codec->preset && codec->preset->name)
codec->chip_name = kstrdup(codec->preset->name, GFP_KERNEL);
else {
sprintf(tmp, "ID %x", codec->vendor_id & 0xffff);
codec->chip_name = kstrdup(tmp, GFP_KERNEL);
}
if (!codec->chip_name)
return -ENOMEM;
return 0;
}
/*
* look for an AFG and MFG nodes
*/
......@@ -1300,20 +1118,6 @@ get_hda_cvt_setup(struct hda_codec *codec, hda_nid_t nid)
return p;
}
/*
* 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
*/
......@@ -1322,12 +1126,11 @@ static void snd_hda_codec_free(struct hda_codec *codec)
if (!codec)
return;
cancel_delayed_work_sync(&codec->jackpoll_work);
if (device_is_registered(hda_codec_dev(codec)))
device_del(hda_codec_dev(codec));
snd_hda_jack_tbl_clear(codec);
free_init_pincfgs(codec);
#ifdef CONFIG_PM
cancel_delayed_work(&codec->power_work);
flush_workqueue(codec->bus->workq);
#endif
list_del(&codec->list);
snd_array_free(&codec->mixers);
snd_array_free(&codec->nids);
......@@ -1335,12 +1138,8 @@ static void snd_hda_codec_free(struct hda_codec *codec)
snd_array_free(&codec->spdif_out);
remove_conn_list(codec);
codec->bus->caddr_tbl[codec->addr] = NULL;
if (codec->patch_ops.free)
codec->patch_ops.free(codec);
hda_call_pm_notify(codec, false); /* cancel leftover refcounts */
clear_bit(codec->addr, &codec->bus->codec_powered);
snd_hda_sysfs_clear(codec);
unload_parser(codec);
module_put(codec->owner);
free_hda_cache(&codec->amp_cache);
free_hda_cache(&codec->cmd_cache);
kfree(codec->vendor_name);
......@@ -1348,7 +1147,7 @@ static void snd_hda_codec_free(struct hda_codec *codec)
kfree(codec->modelname);
kfree(codec->wcaps);
codec->bus->num_codecs--;
put_device(&codec->dev);
put_device(hda_codec_dev(codec));
}
static bool snd_hda_codec_get_supported_ps(struct hda_codec *codec,
......@@ -1360,11 +1159,12 @@ static unsigned int hda_set_power_state(struct hda_codec *codec,
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);
if (device_is_registered(hda_codec_dev(codec)))
pm_runtime_enable(hda_codec_dev(codec));
/* it was powered up in snd_hda_codec_new(), now all done */
snd_hda_power_down(codec);
return 0;
}
......@@ -1373,7 +1173,6 @@ 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;
}
......@@ -1386,7 +1185,7 @@ static int snd_hda_codec_dev_free(struct snd_device *device)
/* just free the container */
static void snd_hda_codec_dev_release(struct device *dev)
{
kfree(container_of(dev, struct hda_codec, dev));
kfree(dev_to_hda_codec(dev));
}
/**
......@@ -1402,6 +1201,7 @@ int snd_hda_codec_new(struct hda_bus *bus,
struct hda_codec **codecp)
{
struct hda_codec *codec;
struct device *dev;
char component[31];
hda_nid_t fg;
int err;
......@@ -1429,14 +1229,15 @@ int snd_hda_codec_new(struct hda_bus *bus,
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 */
dev = hda_codec_dev(codec);
device_initialize(dev);
dev->parent = bus->card->dev;
dev->bus = &snd_hda_bus_type;
dev->release = snd_hda_codec_dev_release;
dev->groups = snd_hda_dev_attr_groups;
dev_set_name(dev, "hdaudioC%dD%d", bus->card->number, codec_addr);
dev_set_drvdata(dev, codec); /* for sysfs */
device_enable_async_suspend(dev);
codec->bus = bus;
codec->addr = codec_addr;
......@@ -1460,13 +1261,13 @@ int snd_hda_codec_new(struct hda_bus *bus,
codec->fixup_id = HDA_FIXUP_ID_NOT_SET;
#ifdef CONFIG_PM
spin_lock_init(&codec->power_lock);
INIT_DELAYED_WORK(&codec->power_work, hda_power_work);
/* snd_hda_codec_new() marks the codec as power-up, and leave it as is.
* the caller has to power down appropriatley after initialization
* phase.
* it's powered down later in snd_hda_codec_dev_register().
*/
hda_keep_power_on(codec);
set_bit(codec->addr, &bus->codec_powered);
pm_runtime_set_active(hda_codec_dev(codec));
pm_runtime_get_noresume(hda_codec_dev(codec));
codec->power_jiffies = jiffies;
#endif
snd_hda_sysfs_init(codec);
......@@ -1526,11 +1327,6 @@ int snd_hda_codec_new(struct hda_bus *bus,
#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);
......@@ -1587,92 +1383,6 @@ int snd_hda_codec_update_widgets(struct hda_codec *codec)
}
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
* @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 (*patch)(struct hda_codec *) = NULL;
int err;
codec->preset = find_codec_preset(codec);
if (!codec->vendor_name || !codec->chip_name) {
err = get_codec_name(codec);
if (err < 0)
return err;
}
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;
}
}
err = patch(codec);
if (err < 0) {
unload_parser(codec);
return err;
}
/* audio codec should override the mixer name */
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 0;
}
EXPORT_SYMBOL_GPL(snd_hda_codec_configure);
/* update the stream-id if changed */
static void update_pcm_stream_id(struct hda_codec *codec,
struct hda_cvt_setup *p, hda_nid_t nid,
......@@ -2725,10 +2435,7 @@ int snd_hda_codec_reset(struct hda_codec *codec)
/* OK, let it free */
cancel_delayed_work_sync(&codec->jackpoll_work);
#ifdef CONFIG_PM
cancel_delayed_work_sync(&codec->power_work);
flush_workqueue(bus->workq);
#endif
snd_hda_ctls_clear(codec);
/* release PCMs */
for (i = 0; i < codec->num_pcms; i++) {
......@@ -2739,8 +2446,9 @@ int snd_hda_codec_reset(struct hda_codec *codec)
}
}
snd_hda_detach_beep_device(codec);
if (codec->patch_ops.free)
codec->patch_ops.free(codec);
if (device_is_registered(hda_codec_dev(codec)))
device_del(hda_codec_dev(codec));
memset(&codec->patch_ops, 0, sizeof(codec->patch_ops));
snd_hda_jack_tbl_clear(codec);
codec->proc_widget_hook = NULL;
......@@ -2759,9 +2467,6 @@ 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;
/* allow device access again */
snd_hda_unlock_devices(bus);
......@@ -4167,31 +3872,40 @@ static inline void hda_exec_init_verbs(struct hda_codec *codec) {}
#endif
#ifdef CONFIG_PM
/* update the power on/off account with the current jiffies */
static void update_power_acct(struct hda_codec *codec, bool on)
{
unsigned long delta = jiffies - codec->power_jiffies;
if (on)
codec->power_on_acct += delta;
else
codec->power_off_acct += delta;
codec->power_jiffies += delta;
}
void snd_hda_update_power_acct(struct hda_codec *codec)
{
update_power_acct(codec, hda_codec_is_power_on(codec));
}
/*
* call suspend and power-down; used both from PM and power-save
* this function returns the power state in the end
*/
static unsigned int hda_call_codec_suspend(struct hda_codec *codec, bool in_wq)
static unsigned int hda_call_codec_suspend(struct hda_codec *codec)
{
unsigned int state;
codec->in_pm = 1;
atomic_inc(&codec->in_pm);
if (codec->patch_ops.suspend)
codec->patch_ops.suspend(codec);
hda_cleanup_all_streams(codec);
state = hda_set_power_state(codec, AC_PWRST_D3);
/* Cancel delayed work if we aren't currently running from it. */
if (!in_wq)
cancel_delayed_work_sync(&codec->power_work);
spin_lock(&codec->power_lock);
snd_hda_update_power_acct(codec);
trace_hda_power_down(codec);
codec->power_on = 0;
codec->power_transition = 0;
codec->power_jiffies = jiffies;
spin_unlock(&codec->power_lock);
codec->in_pm = 0;
update_power_acct(codec, true);
atomic_dec(&codec->in_pm);
return state;
}
......@@ -4216,14 +3930,13 @@ static void hda_mark_cmd_cache_dirty(struct hda_codec *codec)
*/
static void hda_call_codec_resume(struct hda_codec *codec)
{
codec->in_pm = 1;
atomic_inc(&codec->in_pm);
trace_hda_power_up(codec);
hda_mark_cmd_cache_dirty(codec);
/* set as if powered on for avoiding re-entering the resume
* in the resume / power-save sequence
*/
hda_keep_power_on(codec);
codec->power_jiffies = jiffies;
hda_set_power_state(codec, AC_PWRST_D0);
restore_shutup_pins(codec);
hda_exec_init_verbs(codec);
......@@ -4241,12 +3954,42 @@ static void hda_call_codec_resume(struct hda_codec *codec)
hda_jackpoll_work(&codec->jackpoll_work.work);
else
snd_hda_jack_report_sync(codec);
atomic_dec(&codec->in_pm);
}
static int hda_codec_runtime_suspend(struct device *dev)
{
struct hda_codec *codec = dev_to_hda_codec(dev);
unsigned int state;
int i;
cancel_delayed_work_sync(&codec->jackpoll_work);
for (i = 0; i < codec->num_pcms; i++)
snd_pcm_suspend_all(codec->pcm_info[i].pcm);
state = hda_call_codec_suspend(codec);
if (codec->d3_stop_clk && codec->epss && (state & AC_PWRST_CLK_STOP_OK))
clear_bit(codec->addr, &codec->bus->codec_powered);
return 0;
}
static int hda_codec_runtime_resume(struct device *dev)
{
struct hda_codec *codec = dev_to_hda_codec(dev);
codec->in_pm = 0;
snd_hda_power_down(codec); /* flag down before returning */
set_bit(codec->addr, &codec->bus->codec_powered);
hda_call_codec_resume(codec);
pm_runtime_mark_last_busy(dev);
return 0;
}
#endif /* CONFIG_PM */
/* referred in hda_bind.c */
const struct dev_pm_ops hda_codec_driver_pm = {
SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
pm_runtime_force_resume)
SET_RUNTIME_PM_OPS(hda_codec_runtime_suspend, hda_codec_runtime_resume,
NULL)
};
/**
* snd_hda_build_controls - build mixer controls
......@@ -4984,127 +4727,70 @@ int snd_hda_add_new_ctls(struct hda_codec *codec,
EXPORT_SYMBOL_GPL(snd_hda_add_new_ctls);
#ifdef CONFIG_PM
static void hda_power_work(struct work_struct *work)
/**
* snd_hda_power_up - Power-up the codec
* @codec: HD-audio codec
*
* Increment the usage counter and resume the device if not done yet.
*/
void snd_hda_power_up(struct hda_codec *codec)
{
struct hda_codec *codec =
container_of(work, struct hda_codec, power_work.work);
struct hda_bus *bus = codec->bus;
unsigned int state;
struct device *dev = hda_codec_dev(codec);
spin_lock(&codec->power_lock);
if (codec->power_transition > 0) { /* during power-up sequence? */
spin_unlock(&codec->power_lock);
return;
}
if (!codec->power_on || codec->power_count) {
codec->power_transition = 0;
spin_unlock(&codec->power_lock);
if (codec_in_pm(codec))
return;
}
spin_unlock(&codec->power_lock);
state = hda_call_codec_suspend(codec, true);
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)
{
spin_lock(&codec->power_lock);
codec->power_count++;
codec->power_on = 1;
codec->power_jiffies = jiffies;
spin_unlock(&codec->power_lock);
hda_call_pm_notify(codec, true);
pm_runtime_get_sync(dev);
}
EXPORT_SYMBOL_GPL(snd_hda_power_up);
/* 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;
}
/* Transition to powered up, if wait_power_down then wait for a pending
* transition to D3 to complete. A pending D3 transition is indicated
* with power_transition == -1. */
/* call this with codec->power_lock held! */
static void __snd_hda_power_up(struct hda_codec *codec, bool wait_power_down)
/**
* snd_hda_power_down - Power-down the codec
* @codec: HD-audio codec
*
* Decrement the usage counter and schedules the autosuspend if none used.
*/
void snd_hda_power_down(struct hda_codec *codec)
{
/* Return if power_on or transitioning to power_on, unless currently
* powering down. */
if ((codec->power_on || codec->power_transition > 0) &&
!(wait_power_down && codec->power_transition < 0))
return;
spin_unlock(&codec->power_lock);
cancel_delayed_work_sync(&codec->power_work);
struct device *dev = hda_codec_dev(codec);
spin_lock(&codec->power_lock);
/* If the power down delayed work was cancelled above before starting,
* then there is no need to go through power up here.
*/
if (codec->power_on) {
if (codec->power_transition < 0)
codec->power_transition = 0;
if (codec_in_pm(codec))
return;
}
trace_hda_power_up(codec);
snd_hda_update_power_acct(codec);
codec->power_on = 1;
codec->power_jiffies = jiffies;
codec->power_transition = 1; /* avoid reentrance */
spin_unlock(&codec->power_lock);
hda_call_codec_resume(codec);
spin_lock(&codec->power_lock);
codec->power_transition = 0;
pm_runtime_mark_last_busy(dev);
pm_runtime_put_autosuspend(dev);
}
EXPORT_SYMBOL_GPL(snd_hda_power_down);
#define power_save(codec) \
((codec)->bus->power_save ? *(codec)->bus->power_save : 0)
/* Transition to powered down */
static void __snd_hda_power_down(struct hda_codec *codec)
static void codec_set_power_save(struct hda_codec *codec, int delay)
{
if (!codec->power_on || codec->power_count || codec->power_transition)
return;
struct device *dev = hda_codec_dev(codec);
if (power_save(codec)) {
codec->power_transition = -1; /* avoid reentrance */
queue_delayed_work(codec->bus->workq, &codec->power_work,
msecs_to_jiffies(power_save(codec) * 1000));
if (delay > 0) {
pm_runtime_set_autosuspend_delay(dev, delay);
pm_runtime_use_autosuspend(dev);
pm_runtime_allow(dev);
if (!pm_runtime_suspended(dev))
pm_runtime_mark_last_busy(dev);
} else {
pm_runtime_dont_use_autosuspend(dev);
pm_runtime_forbid(dev);
}
}
/**
* snd_hda_power_save - Power-up/down/sync the codec
* @codec: HD-audio codec
* @delta: the counter delta to change
* @d3wait: sync for D3 transition complete
* snd_hda_set_power_save - reprogram autosuspend for the given delay
* @bus: HD-audio bus
* @delay: autosuspend delay in msec, 0 = off
*
* Change the power-up counter via @delta, and power up or down the hardware
* appropriately. For the power-down, queue to the delayed action.
* Passing zero to @delta means to synchronize the power state.
* Synchronize the runtime PM autosuspend state from the power_save option.
*/
void snd_hda_power_save(struct hda_codec *codec, int delta, bool d3wait)
void snd_hda_set_power_save(struct hda_bus *bus, int delay)
{
spin_lock(&codec->power_lock);
codec->power_count += delta;
trace_hda_power_count(codec);
if (delta > 0)
__snd_hda_power_up(codec, d3wait);
else
__snd_hda_power_down(codec);
spin_unlock(&codec->power_lock);
struct hda_codec *c;
list_for_each_entry(c, &bus->codec_list, list)
codec_set_power_save(c, delay);
}
EXPORT_SYMBOL_GPL(snd_hda_power_save);
EXPORT_SYMBOL_GPL(snd_hda_set_power_save);
/**
* snd_hda_check_amp_list_power - Check the amp list and update the power
......@@ -5157,88 +4843,6 @@ int snd_hda_check_amp_list_power(struct hda_codec *codec,
EXPORT_SYMBOL_GPL(snd_hda_check_amp_list_power);
#endif
/*
* Channel mode helper
*/
/**
* snd_hda_ch_mode_info - Info callback helper for the channel mode enum
* @codec: the HDA codec
* @uinfo: pointer to get/store the data
* @chmode: channel mode array
* @num_chmodes: channel mode array size
*/
int snd_hda_ch_mode_info(struct hda_codec *codec,
struct snd_ctl_elem_info *uinfo,
const struct hda_channel_mode *chmode,
int num_chmodes)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
uinfo->value.enumerated.items = num_chmodes;
if (uinfo->value.enumerated.item >= num_chmodes)
uinfo->value.enumerated.item = num_chmodes - 1;
sprintf(uinfo->value.enumerated.name, "%dch",
chmode[uinfo->value.enumerated.item].channels);
return 0;
}
EXPORT_SYMBOL_GPL(snd_hda_ch_mode_info);
/**
* snd_hda_ch_mode_get - Get callback helper for the channel mode enum
* @codec: the HDA codec
* @ucontrol: pointer to get/store the data
* @chmode: channel mode array
* @num_chmodes: channel mode array size
* @max_channels: max number of channels
*/
int snd_hda_ch_mode_get(struct hda_codec *codec,
struct snd_ctl_elem_value *ucontrol,
const struct hda_channel_mode *chmode,
int num_chmodes,
int max_channels)
{
int i;
for (i = 0; i < num_chmodes; i++) {
if (max_channels == chmode[i].channels) {
ucontrol->value.enumerated.item[0] = i;
break;
}
}
return 0;
}
EXPORT_SYMBOL_GPL(snd_hda_ch_mode_get);
/**
* snd_hda_ch_mode_put - Put callback helper for the channel mode enum
* @codec: the HDA codec
* @ucontrol: pointer to get/store the data
* @chmode: channel mode array
* @num_chmodes: channel mode array size
* @max_channelsp: pointer to store the max channels
*/
int snd_hda_ch_mode_put(struct hda_codec *codec,
struct snd_ctl_elem_value *ucontrol,
const struct hda_channel_mode *chmode,
int num_chmodes,
int *max_channelsp)
{
unsigned int mode;
mode = ucontrol->value.enumerated.item[0];
if (mode >= num_chmodes)
return -EINVAL;
if (*max_channelsp == chmode[mode].channels)
return 0;
/* change the current channel setting */
*max_channelsp = chmode[mode].channels;
if (chmode[mode].sequence)
snd_hda_sequence_write_cache(codec, chmode[mode].sequence);
return 1;
}
EXPORT_SYMBOL_GPL(snd_hda_ch_mode_put);
/*
* input MUX helper
*/
......@@ -5780,77 +5384,26 @@ int snd_hda_add_imux_item(struct hda_codec *codec,
}
EXPORT_SYMBOL_GPL(snd_hda_add_imux_item);
#ifdef CONFIG_PM
/*
* 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
*
* Returns 0 if successful.
* snd_hda_bus_reset - Reset the bus
* @bus: HD-audio bus
*/
int snd_hda_suspend(struct hda_bus *bus)
void snd_hda_bus_reset(struct hda_bus *bus)
{
struct hda_codec *codec;
ASYNC_DOMAIN_EXCLUSIVE(domain);
list_for_each_entry(codec, &bus->codec_list, list) {
/* FIXME: maybe a better way needed for forced reset */
cancel_delayed_work_sync(&codec->jackpoll_work);
#ifdef CONFIG_PM
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_GPL(snd_hda_suspend);
/**
* snd_hda_resume - resume the codecs
* @bus: the HDA bus
*
* Returns 0 if successful.
*/
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) {
if (bus->num_codecs > 1)
async_schedule_domain(hda_async_resume, codec, &domain);
else
hda_call_codec_suspend(codec);
hda_call_codec_resume(codec);
}
#endif
}
if (bus->num_codecs > 1)
async_synchronize_full_domain(&domain);
return 0;
}
EXPORT_SYMBOL_GPL(snd_hda_resume);
#endif /* CONFIG_PM */
EXPORT_SYMBOL_GPL(snd_hda_bus_reset);
/*
* generic arrays
......
......@@ -83,10 +83,6 @@ struct hda_bus_ops {
struct hda_pcm *pcm);
/* reset bus for retry verb */
void (*bus_reset)(struct hda_bus *bus);
#ifdef CONFIG_PM
/* notify power-up/down from codec to controller */
void (*pm_notify)(struct hda_bus *bus, bool power_up);
#endif
#ifdef CONFIG_SND_HDA_DSP_LOADER
/* prepare DSP transfer */
int (*load_dsp_prepare)(struct hda_bus *bus, unsigned int format,
......@@ -122,7 +118,6 @@ struct hda_bus {
void *private_data;
struct pci_dev *pci;
const char *modelname;
int *power_save;
struct hda_bus_ops ops;
/* codec linked list */
......@@ -151,10 +146,10 @@ struct hda_bus {
unsigned int rirb_error:1; /* error in codec communication */
unsigned int response_reset:1; /* controller was reset */
unsigned int in_reset:1; /* during reset operation */
unsigned int power_keep_link_on:1; /* don't power off HDA link */
unsigned int no_response_fallback:1; /* don't fallback at RIRB error */
int primary_dig_out_type; /* primary digital out PCM type */
unsigned long codec_powered; /* bit flags of powered codecs */
};
/*
......@@ -174,15 +169,22 @@ struct hda_codec_preset {
int (*patch)(struct hda_codec *codec);
};
struct hda_codec_preset_list {
#define HDA_CODEC_ID_GENERIC_HDMI 0x00000101
#define HDA_CODEC_ID_GENERIC 0x00000201
struct hda_codec_driver {
struct device_driver driver;
const struct hda_codec_preset *preset;
struct module *owner;
struct list_head list;
};
/* initial hook */
int snd_hda_add_codec_preset(struct hda_codec_preset_list *preset);
int snd_hda_delete_codec_preset(struct hda_codec_preset_list *preset);
int __hda_codec_driver_register(struct hda_codec_driver *drv, const char *name,
struct module *owner);
#define hda_codec_driver_register(drv) \
__hda_codec_driver_register(drv, KBUILD_MODNAME, THIS_MODULE)
void hda_codec_driver_unregister(struct hda_codec_driver *drv);
#define module_hda_codec_driver(drv) \
module_driver(drv, hda_codec_driver_register, \
hda_codec_driver_unregister)
/* ops set by the preset patch */
struct hda_codec_ops {
......@@ -286,11 +288,10 @@ struct hda_codec {
u32 vendor_id;
u32 subsystem_id;
u32 revision_id;
u32 probe_id; /* overridden id for probing */
/* detected preset */
const struct hda_codec_preset *preset;
struct module *owner;
int (*parser)(struct hda_codec *codec);
const char *vendor_name; /* codec vendor name */
const char *chip_name; /* codec chip name */
const char *modelname; /* model name for preset */
......@@ -366,17 +367,11 @@ struct hda_codec {
unsigned int dp_mst:1; /* support DP1.2 Multi-stream transport */
unsigned int dump_coef:1; /* dump processing coefs in codec proc file */
#ifdef CONFIG_PM
unsigned int power_on :1; /* current (global) power-state */
unsigned int d3_stop_clk:1; /* support D3 operation without BCLK */
unsigned int pm_up_notified:1; /* PM notified to controller */
unsigned int in_pm:1; /* suspend/resume being performed */
int power_transition; /* power-state in transition */
int power_count; /* current (global) power refcount */
struct delayed_work power_work; /* delayed task for powerdown */
atomic_t in_pm; /* suspend/resume being performed */
unsigned long power_on_acct;
unsigned long power_off_acct;
unsigned long power_jiffies;
spinlock_t power_lock;
#endif
/* filter the requested power state per nid */
......@@ -408,6 +403,11 @@ struct hda_codec {
struct snd_array verbs;
};
#define dev_to_hda_codec(_dev) container_of(_dev, struct hda_codec, dev)
#define hda_codec_dev(_dev) (&(_dev)->dev)
extern struct bus_type snd_hda_bus_type;
/* direction */
enum {
HDA_INPUT, HDA_OUTPUT
......@@ -556,14 +556,12 @@ void snd_hda_codec_set_power_to_all(struct hda_codec *codec, hda_nid_t fg,
int snd_hda_lock_devices(struct hda_bus *bus);
void snd_hda_unlock_devices(struct hda_bus *bus);
void snd_hda_bus_reset(struct hda_bus *bus);
/*
* power management
*/
#ifdef CONFIG_PM
int snd_hda_suspend(struct hda_bus *bus);
int snd_hda_resume(struct hda_bus *bus);
#endif
extern const struct dev_pm_ops hda_codec_driver_pm;
static inline
int hda_call_check_power_status(struct hda_codec *codec, hda_nid_t nid)
......@@ -586,64 +584,16 @@ const char *snd_hda_get_jack_location(u32 cfg);
* power saving
*/
#ifdef CONFIG_PM
void snd_hda_power_save(struct hda_codec *codec, int delta, bool d3wait);
void snd_hda_power_up(struct hda_codec *codec);
void snd_hda_power_down(struct hda_codec *codec);
void snd_hda_set_power_save(struct hda_bus *bus, int delay);
void snd_hda_update_power_acct(struct hda_codec *codec);
#else
static inline void snd_hda_power_save(struct hda_codec *codec, int delta,
bool d3wait) {}
static inline void snd_hda_power_up(struct hda_codec *codec) {}
static inline void snd_hda_power_down(struct hda_codec *codec) {}
static inline void snd_hda_set_power_save(struct hda_bus *bus, int delay) {}
#endif
/**
* snd_hda_power_up - Power-up the codec
* @codec: HD-audio codec
*
* Increment the power-up counter and power up the hardware really when
* not turned on yet.
*/
static inline void snd_hda_power_up(struct hda_codec *codec)
{
snd_hda_power_save(codec, 1, false);
}
/**
* snd_hda_power_up_d3wait - Power-up the codec after waiting for any pending
* D3 transition to complete. This differs from snd_hda_power_up() when
* power_transition == -1. snd_hda_power_up sees this case as a nop,
* snd_hda_power_up_d3wait waits for the D3 transition to complete then powers
* back up.
* @codec: HD-audio codec
*
* Cancel any power down operation hapenning on the work queue, then power up.
*/
static inline void snd_hda_power_up_d3wait(struct hda_codec *codec)
{
snd_hda_power_save(codec, 1, true);
}
/**
* snd_hda_power_down - Power-down the codec
* @codec: HD-audio codec
*
* Decrement the power-up counter and schedules the power-off work if
* the counter rearches to zero.
*/
static inline void snd_hda_power_down(struct hda_codec *codec)
{
snd_hda_power_save(codec, -1, false);
}
/**
* snd_hda_power_sync - Synchronize the power-save status
* @codec: HD-audio codec
*
* Synchronize the actual power state with the power account;
* called when power_save parameter is changed
*/
static inline void snd_hda_power_sync(struct hda_codec *codec)
{
snd_hda_power_save(codec, 0, false);
}
#ifdef CONFIG_SND_HDA_PATCH_LOADER
/*
* patch firmware
......
......@@ -258,11 +258,18 @@ static void azx_timecounter_init(struct snd_pcm_substream *substream,
tc->cycle_last = last;
}
static inline struct hda_pcm_stream *
to_hda_pcm_stream(struct snd_pcm_substream *substream)
{
struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
return &apcm->info->stream[substream->stream];
}
static u64 azx_adjust_codec_delay(struct snd_pcm_substream *substream,
u64 nsec)
{
struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream];
struct hda_pcm_stream *hinfo = to_hda_pcm_stream(substream);
u64 codec_frames, codec_nsecs;
if (!hinfo->ops.get_delay)
......@@ -398,7 +405,7 @@ static int azx_setup_periods(struct azx *chip,
static int azx_pcm_close(struct snd_pcm_substream *substream)
{
struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream];
struct hda_pcm_stream *hinfo = to_hda_pcm_stream(substream);
struct azx *chip = apcm->chip;
struct azx_dev *azx_dev = get_azx_dev(substream);
unsigned long flags;
......@@ -440,7 +447,7 @@ static int azx_pcm_hw_free(struct snd_pcm_substream *substream)
struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
struct azx_dev *azx_dev = get_azx_dev(substream);
struct azx *chip = apcm->chip;
struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream];
struct hda_pcm_stream *hinfo = to_hda_pcm_stream(substream);
int err;
/* reset BDL address */
......@@ -467,7 +474,7 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
struct azx *chip = apcm->chip;
struct azx_dev *azx_dev = get_azx_dev(substream);
struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream];
struct hda_pcm_stream *hinfo = to_hda_pcm_stream(substream);
struct snd_pcm_runtime *runtime = substream->runtime;
unsigned int bufsize, period_bytes, format_val, stream_tag;
int err;
......@@ -707,7 +714,7 @@ unsigned int azx_get_position(struct azx *chip,
if (substream->runtime) {
struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
struct hda_pcm_stream *hinfo = apcm->hinfo[stream];
struct hda_pcm_stream *hinfo = to_hda_pcm_stream(substream);
if (chip->get_delay[stream])
delay += chip->get_delay[stream](chip, azx_dev, pos);
......@@ -790,7 +797,7 @@ static struct snd_pcm_hardware azx_pcm_hw = {
static int azx_pcm_open(struct snd_pcm_substream *substream)
{
struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream];
struct hda_pcm_stream *hinfo = to_hda_pcm_stream(substream);
struct azx *chip = apcm->chip;
struct azx_dev *azx_dev;
struct snd_pcm_runtime *runtime = substream->runtime;
......@@ -836,7 +843,7 @@ static int azx_pcm_open(struct snd_pcm_substream *substream)
buff_step);
snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
buff_step);
snd_hda_power_up_d3wait(apcm->codec);
snd_hda_power_up(apcm->codec);
err = hinfo->ops.open(hinfo, apcm->codec, substream);
if (err < 0) {
azx_release_device(azx_dev);
......@@ -904,6 +911,7 @@ static void azx_pcm_free(struct snd_pcm *pcm)
struct azx_pcm *apcm = pcm->private_data;
if (apcm) {
list_del(&apcm->list);
apcm->info->pcm = NULL;
kfree(apcm);
}
}
......@@ -940,6 +948,7 @@ static int azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec,
apcm->chip = chip;
apcm->pcm = pcm;
apcm->codec = codec;
apcm->info = cpcm;
pcm->private_data = apcm;
pcm->private_free = azx_pcm_free;
if (cpcm->pcm_type == HDA_PCM_TYPE_MODEM)
......@@ -947,7 +956,6 @@ static int azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec,
list_add_tail(&apcm->list, &chip->pcm_list);
cpcm->pcm = pcm;
for (s = 0; s < 2; s++) {
apcm->hinfo[s] = &cpcm->stream[s];
if (cpcm->stream[s].substreams)
snd_pcm_set_ops(pcm, s, &azx_pcm_ops);
}
......@@ -958,9 +966,6 @@ static int azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec,
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
chip->card->dev,
size, MAX_PREALLOC_SIZE);
/* link to codec */
for (s = 0; s < 2; s++)
pcm->streams[s].dev.parent = &codec->dev;
return 0;
}
......@@ -1778,34 +1783,11 @@ static void azx_bus_reset(struct hda_bus *bus)
bus->in_reset = 1;
azx_stop_chip(chip);
azx_init_chip(chip, true);
#ifdef CONFIG_PM
if (chip->initialized) {
struct azx_pcm *p;
list_for_each_entry(p, &chip->pcm_list, list)
snd_pcm_suspend_all(p->pcm);
snd_hda_suspend(chip->bus);
snd_hda_resume(chip->bus);
}
#endif
if (chip->initialized)
snd_hda_bus_reset(chip->bus);
bus->in_reset = 0;
}
#ifdef CONFIG_PM
/* power-up/down the controller */
static void azx_power_notify(struct hda_bus *bus, bool power_up)
{
struct azx *chip = bus->private_data;
if (!azx_has_pm_runtime(chip))
return;
if (power_up)
pm_runtime_get_sync(chip->card->dev);
else
pm_runtime_put_sync(chip->card->dev);
}
#endif
static int get_jackpoll_interval(struct azx *chip)
{
int i;
......@@ -1832,9 +1814,6 @@ static struct hda_bus_ops bus_ops = {
.get_response = azx_get_response,
.attach_pcm = azx_attach_pcm_stream,
.bus_reset = azx_bus_reset,
#ifdef CONFIG_PM
.pm_notify = azx_power_notify,
#endif
#ifdef CONFIG_SND_HDA_DSP_LOADER
.load_dsp_prepare = azx_load_dsp_prepare,
.load_dsp_trigger = azx_load_dsp_trigger,
......@@ -1843,7 +1822,7 @@ static struct hda_bus_ops bus_ops = {
};
/* HD-audio bus initialization */
int azx_bus_create(struct azx *chip, const char *model, int *power_save_to)
int azx_bus_create(struct azx *chip, const char *model)
{
struct hda_bus *bus;
int err;
......@@ -1857,9 +1836,6 @@ int azx_bus_create(struct azx *chip, const char *model, int *power_save_to)
bus->pci = chip->pci;
bus->modelname = model;
bus->ops = bus_ops;
#ifdef CONFIG_PM
bus->power_save = power_save_to;
#endif
if (chip->driver_caps & AZX_DCAPS_RIRB_DELAY) {
dev_dbg(chip->card->dev, "Enable delay in RIRB handling\n");
......
......@@ -283,7 +283,7 @@ struct azx_pcm {
struct azx *chip;
struct snd_pcm *pcm;
struct hda_codec *codec;
struct hda_pcm_stream *hinfo[2];
struct hda_pcm *info;
struct list_head list;
};
......@@ -432,7 +432,7 @@ void azx_enter_link_reset(struct azx *chip);
irqreturn_t azx_interrupt(int irq, void *dev_id);
/* Codec interface */
int azx_bus_create(struct azx *chip, const char *model, int *power_save_to);
int azx_bus_create(struct azx *chip, const char *model);
int azx_probe_codecs(struct azx *chip, unsigned int max_slots);
int azx_codec_configure(struct azx *chip);
int azx_init_stream(struct azx *chip);
......
......@@ -5524,13 +5524,11 @@ static const struct hda_codec_ops generic_patch_ops = {
#endif
};
/**
/*
* snd_hda_parse_generic_codec - Generic codec parser
* @codec: the HDA codec
*
* This should be called from the HDA codec core.
*/
int snd_hda_parse_generic_codec(struct hda_codec *codec)
static int snd_hda_parse_generic_codec(struct hda_codec *codec)
{
struct hda_gen_spec *spec;
int err;
......@@ -5556,7 +5554,17 @@ int snd_hda_parse_generic_codec(struct hda_codec *codec)
snd_hda_gen_free(codec);
return err;
}
EXPORT_SYMBOL_GPL(snd_hda_parse_generic_codec);
static const struct hda_codec_preset snd_hda_preset_generic[] = {
{ .id = HDA_CODEC_ID_GENERIC, .patch = snd_hda_parse_generic_codec },
{} /* terminator */
};
static struct hda_codec_driver generic_driver = {
.preset = snd_hda_preset_generic,
};
module_hda_codec_driver(generic_driver);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Generic HD-audio codec parser");
......@@ -116,9 +116,6 @@ int snd_hda_create_hwdep(struct hda_codec *codec)
hwdep->ops.ioctl_compat = hda_hwdep_ioctl_compat;
#endif
/* link to codec */
hwdep->dev.parent = &codec->dev;
/* for sysfs */
hwdep->dev.groups = snd_hda_dev_attr_groups;
dev_set_drvdata(&hwdep->dev, codec);
......
......@@ -173,7 +173,6 @@ static struct kernel_param_ops param_ops_xint = {
#define param_check_xint param_check_int
static int power_save = CONFIG_SND_HDA_POWER_SAVE_DEFAULT;
static int *power_save_addr = &power_save;
module_param(power_save, xint, 0644);
MODULE_PARM_DESC(power_save, "Automatic power-saving timeout "
"(in second, 0 = disable).");
......@@ -186,7 +185,7 @@ static bool power_save_controller = 1;
module_param(power_save_controller, bool, 0644);
MODULE_PARM_DESC(power_save_controller, "Reset controller in power save mode.");
#else
static int *power_save_addr;
#define power_save 0
#endif /* CONFIG_PM */
static int align_buffer_size = -1;
......@@ -740,7 +739,6 @@ static int param_set_xint(const char *val, const struct kernel_param *kp)
{
struct hda_intel *hda;
struct azx *chip;
struct hda_codec *c;
int prev = power_save;
int ret = param_set_int(val, kp);
......@@ -752,8 +750,7 @@ static int param_set_xint(const char *val, const struct kernel_param *kp)
chip = &hda->chip;
if (!chip->bus || chip->disabled)
continue;
list_for_each_entry(c, &chip->bus->codec_list, list)
snd_hda_power_sync(c);
snd_hda_set_power_save(chip->bus, power_save * 1000);
}
mutex_unlock(&card_list_lock);
return 0;
......@@ -772,7 +769,6 @@ static int azx_suspend(struct device *dev)
struct snd_card *card = dev_get_drvdata(dev);
struct azx *chip;
struct hda_intel *hda;
struct azx_pcm *p;
if (!card)
return 0;
......@@ -784,10 +780,6 @@ static int azx_suspend(struct device *dev)
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
azx_clear_irq_pending(chip);
list_for_each_entry(p, &chip->pcm_list, list)
snd_pcm_suspend_all(p->pcm);
if (chip->initialized)
snd_hda_suspend(chip->bus);
azx_stop_chip(chip);
azx_enter_link_reset(chip);
if (chip->irq >= 0) {
......@@ -830,7 +822,6 @@ static int azx_resume(struct device *dev)
azx_init_chip(chip, true);
snd_hda_resume(chip->bus);
snd_power_change_state(card, SNDRV_CTL_POWER_D0);
return 0;
}
......@@ -927,7 +918,8 @@ static int azx_runtime_idle(struct device *dev)
if (chip->disabled || hda->init_failed)
return 0;
if (!power_save_controller || !azx_has_pm_runtime(chip))
if (!power_save_controller || !azx_has_pm_runtime(chip) ||
chip->bus->codec_powered)
return -EBUSY;
return 0;
......@@ -1612,19 +1604,6 @@ static int azx_first_init(struct azx *chip)
return 0;
}
static void power_down_all_codecs(struct azx *chip)
{
#ifdef CONFIG_PM
/* The codecs were powered up in snd_hda_codec_new().
* Now all initialization done, so turn them down if possible
*/
struct hda_codec *codec;
list_for_each_entry(codec, &chip->bus->codec_list, list) {
snd_hda_power_down(codec);
}
#endif
}
#ifdef CONFIG_SND_HDA_PATCH_LOADER
/* callback from request_firmware_nowait() */
static void azx_firmware_cb(const struct firmware *fw, void *context)
......@@ -1893,7 +1872,7 @@ static int azx_probe_continue(struct azx *chip)
#endif
/* create codec instances */
err = azx_bus_create(chip, model[dev], power_save_addr);
err = azx_bus_create(chip, model[dev]);
if (err < 0)
goto out_free;
......@@ -1934,9 +1913,9 @@ static int azx_probe_continue(struct azx *chip)
goto out_free;
chip->running = 1;
power_down_all_codecs(chip);
azx_notifier_register(chip);
azx_add_card_list(chip);
snd_hda_set_power_save(chip->bus, power_save * 1000);
if (azx_has_pm_runtime(chip) || hda->use_vga_switcheroo)
pm_runtime_put_noidle(&pci->dev);
......
......@@ -272,29 +272,6 @@ int snd_hda_add_imux_item(struct hda_codec *codec,
struct hda_input_mux *imux, const char *label,
int index, int *type_index_ret);
/*
* Channel mode helper
*/
struct hda_channel_mode {
int channels;
const struct hda_verb *sequence;
};
int snd_hda_ch_mode_info(struct hda_codec *codec,
struct snd_ctl_elem_info *uinfo,
const struct hda_channel_mode *chmode,
int num_chmodes);
int snd_hda_ch_mode_get(struct hda_codec *codec,
struct snd_ctl_elem_value *ucontrol,
const struct hda_channel_mode *chmode,
int num_chmodes,
int max_channels);
int snd_hda_ch_mode_put(struct hda_codec *codec,
struct snd_ctl_elem_value *ucontrol,
const struct hda_channel_mode *chmode,
int num_chmodes,
int *max_channelsp);
/*
* Multi-channel / digital-out PCM helper
*/
......@@ -350,12 +327,6 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec,
struct hda_multi_out *mout);
/*
* generic codec parser
*/
int snd_hda_parse_generic_codec(struct hda_codec *codec);
int snd_hda_parse_hdmi_codec(struct hda_codec *codec);
/*
* generic proc interface
*/
......@@ -783,9 +754,13 @@ void snd_print_channel_allocation(int spk_alloc, char *buf, int buflen);
/*
*/
#define codec_err(codec, fmt, args...) dev_err(&(codec)->dev, fmt, ##args)
#define codec_warn(codec, fmt, args...) dev_warn(&(codec)->dev, fmt, ##args)
#define codec_info(codec, fmt, args...) dev_info(&(codec)->dev, fmt, ##args)
#define codec_dbg(codec, fmt, args...) dev_dbg(&(codec)->dev, fmt, ##args)
#define codec_err(codec, fmt, args...) \
dev_err(hda_codec_dev(codec), fmt, ##args)
#define codec_warn(codec, fmt, args...) \
dev_warn(hda_codec_dev(codec), fmt, ##args)
#define codec_info(codec, fmt, args...) \
dev_info(hda_codec_dev(codec), fmt, ##args)
#define codec_dbg(codec, fmt, args...) \
dev_dbg(hda_codec_dev(codec), fmt, ##args)
#endif /* __SOUND_HDA_LOCAL_H */
......@@ -81,7 +81,7 @@ module_param(power_save, bint, 0644);
MODULE_PARM_DESC(power_save,
"Automatic power-saving timeout (in seconds, 0 = disable).");
#else
static int power_save = 0;
#define power_save 0
#endif
/*
......@@ -249,14 +249,9 @@ static int hda_tegra_suspend(struct device *dev)
{
struct snd_card *card = dev_get_drvdata(dev);
struct azx *chip = card->private_data;
struct azx_pcm *p;
struct hda_tegra *hda = container_of(chip, struct hda_tegra, chip);
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
list_for_each_entry(p, &chip->pcm_list, list)
snd_pcm_suspend_all(p->pcm);
if (chip->initialized)
snd_hda_suspend(chip->bus);
azx_stop_chip(chip);
azx_enter_link_reset(chip);
......@@ -277,7 +272,6 @@ static int hda_tegra_resume(struct device *dev)
azx_init_chip(chip, 1);
snd_hda_resume(chip->bus);
snd_power_change_state(card, SNDRV_CTL_POWER_D0);
return 0;
......@@ -343,17 +337,6 @@ static int hda_tegra_init_chip(struct azx *chip, struct platform_device *pdev)
return 0;
}
/*
* The codecs were powered up in snd_hda_codec_new().
* Now all initialization done, so turn them down if possible
*/
static void power_down_all_codecs(struct azx *chip)
{
struct hda_codec *codec;
list_for_each_entry(codec, &chip->bus->codec_list, list)
snd_hda_power_down(codec);
}
static int hda_tegra_first_init(struct azx *chip, struct platform_device *pdev)
{
struct snd_card *card = chip->card;
......@@ -502,7 +485,7 @@ static int hda_tegra_probe(struct platform_device *pdev)
goto out_free;
/* create codec instances */
err = azx_bus_create(chip, NULL, &power_save);
err = azx_bus_create(chip, NULL);
if (err < 0)
goto out_free;
......@@ -529,8 +512,8 @@ static int hda_tegra_probe(struct platform_device *pdev)
goto out_free;
chip->running = 1;
power_down_all_codecs(chip);
azx_notifier_register(chip);
snd_hda_set_power_save(chip->bus, power_save * 1000);
return 0;
......
......@@ -87,30 +87,6 @@ DEFINE_EVENT(hda_power, hda_power_up,
TP_PROTO(struct hda_codec *codec),
TP_ARGS(codec)
);
TRACE_EVENT(hda_power_count,
TP_PROTO(struct hda_codec *codec),
TP_ARGS(codec),
TP_STRUCT__entry(
__field( unsigned int, card )
__field( unsigned int, addr )
__field( int, power_count )
__field( int, power_on )
__field( int, power_transition )
),
TP_fast_assign(
__entry->card = (codec)->bus->card->number;
__entry->addr = (codec)->addr;
__entry->power_count = (codec)->power_count;
__entry->power_on = (codec)->power_on;
__entry->power_transition = (codec)->power_transition;
),
TP_printk("[%d:%d] power_count=%d, power_on=%d, power_transition=%d",
__entry->card, __entry->addr, __entry->power_count,
__entry->power_on, __entry->power_transition)
);
#endif /* CONFIG_PM */
TRACE_EVENT(hda_unsol_event,
......
......@@ -1194,20 +1194,8 @@ MODULE_ALIAS("snd-hda-codec-id:11d4*");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Analog Devices HD-audio codec");
static struct hda_codec_preset_list analog_list = {
static struct hda_codec_driver analog_driver = {
.preset = snd_hda_preset_analog,
.owner = THIS_MODULE,
};
static int __init patch_analog_init(void)
{
return snd_hda_add_codec_preset(&analog_list);
}
static void __exit patch_analog_exit(void)
{
snd_hda_delete_codec_preset(&analog_list);
}
module_init(patch_analog_init)
module_exit(patch_analog_exit)
module_hda_codec_driver(analog_driver);
......@@ -98,20 +98,8 @@ MODULE_ALIAS("snd-hda-codec-id:1102000d");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Creative CA0110-IBG HD-audio codec");
static struct hda_codec_preset_list ca0110_list = {
static struct hda_codec_driver ca0110_driver = {
.preset = snd_hda_preset_ca0110,
.owner = THIS_MODULE,
};
static int __init patch_ca0110_init(void)
{
return snd_hda_add_codec_preset(&ca0110_list);
}
static void __exit patch_ca0110_exit(void)
{
snd_hda_delete_codec_preset(&ca0110_list);
}
module_init(patch_ca0110_init)
module_exit(patch_ca0110_exit)
module_hda_codec_driver(ca0110_driver);
......@@ -4702,20 +4702,8 @@ MODULE_ALIAS("snd-hda-codec-id:11020011");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Creative Sound Core3D codec");
static struct hda_codec_preset_list ca0132_list = {
static struct hda_codec_driver ca0132_driver = {
.preset = snd_hda_preset_ca0132,
.owner = THIS_MODULE,
};
static int __init patch_ca0132_init(void)
{
return snd_hda_add_codec_preset(&ca0132_list);
}
static void __exit patch_ca0132_exit(void)
{
snd_hda_delete_codec_preset(&ca0132_list);
}
module_init(patch_ca0132_init)
module_exit(patch_ca0132_exit)
module_hda_codec_driver(ca0132_driver);
......@@ -1221,20 +1221,8 @@ MODULE_ALIAS("snd-hda-codec-id:10134213");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Cirrus Logic HD-audio codec");
static struct hda_codec_preset_list cirrus_list = {
static struct hda_codec_driver cirrus_driver = {
.preset = snd_hda_preset_cirrus,
.owner = THIS_MODULE,
};
static int __init patch_cirrus_init(void)
{
return snd_hda_add_codec_preset(&cirrus_list);
}
static void __exit patch_cirrus_exit(void)
{
snd_hda_delete_codec_preset(&cirrus_list);
}
module_init(patch_cirrus_init)
module_exit(patch_cirrus_exit)
module_hda_codec_driver(cirrus_driver);
......@@ -137,20 +137,8 @@ MODULE_ALIAS("snd-hda-codec-id:434d4980");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("C-Media HD-audio codec");
static struct hda_codec_preset_list cmedia_list = {
static struct hda_codec_driver cmedia_driver = {
.preset = snd_hda_preset_cmedia,
.owner = THIS_MODULE,
};
static int __init patch_cmedia_init(void)
{
return snd_hda_add_codec_preset(&cmedia_list);
}
static void __exit patch_cmedia_exit(void)
{
snd_hda_delete_codec_preset(&cmedia_list);
}
module_init(patch_cmedia_init)
module_exit(patch_cmedia_exit)
module_hda_codec_driver(cmedia_driver);
......@@ -1018,20 +1018,8 @@ MODULE_ALIAS("snd-hda-codec-id:14f151d7");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Conexant HD-audio codec");
static struct hda_codec_preset_list conexant_list = {
static struct hda_codec_driver conexant_driver = {
.preset = snd_hda_preset_conexant,
.owner = THIS_MODULE,
};
static int __init patch_conexant_init(void)
{
return snd_hda_add_codec_preset(&conexant_list);
}
static void __exit patch_conexant_exit(void)
{
snd_hda_delete_codec_preset(&conexant_list);
}
module_init(patch_conexant_init)
module_exit(patch_conexant_exit)
module_hda_codec_driver(conexant_driver);
......@@ -3300,15 +3300,6 @@ static int patch_via_hdmi(struct hda_codec *codec)
return patch_simple_hdmi(codec, VIAHDMI_CVT_NID, VIAHDMI_PIN_NID);
}
/*
* called from hda_codec.c for generic HDMI support
*/
int snd_hda_parse_hdmi_codec(struct hda_codec *codec)
{
return patch_generic_hdmi(codec);
}
EXPORT_SYMBOL_GPL(snd_hda_parse_hdmi_codec);
/*
* patch entries
*/
......@@ -3373,6 +3364,8 @@ static const struct hda_codec_preset snd_hda_preset_hdmi[] = {
{ .id = 0x80862882, .name = "Valleyview2 HDMI", .patch = patch_generic_hdmi },
{ .id = 0x80862883, .name = "Braswell HDMI", .patch = patch_generic_hdmi },
{ .id = 0x808629fb, .name = "Crestline HDMI", .patch = patch_generic_hdmi },
/* special ID for generic HDMI */
{ .id = HDA_CODEC_ID_GENERIC_HDMI, .patch = patch_generic_hdmi },
{} /* terminator */
};
......@@ -3442,20 +3435,8 @@ MODULE_ALIAS("snd-hda-codec-intelhdmi");
MODULE_ALIAS("snd-hda-codec-nvhdmi");
MODULE_ALIAS("snd-hda-codec-atihdmi");
static struct hda_codec_preset_list intel_list = {
static struct hda_codec_driver hdmi_driver = {
.preset = snd_hda_preset_hdmi,
.owner = THIS_MODULE,
};
static int __init patch_hdmi_init(void)
{
return snd_hda_add_codec_preset(&intel_list);
}
static void __exit patch_hdmi_exit(void)
{
snd_hda_delete_codec_preset(&intel_list);
}
module_init(patch_hdmi_init)
module_exit(patch_hdmi_exit)
module_hda_codec_driver(hdmi_driver);
......@@ -6521,20 +6521,8 @@ MODULE_ALIAS("snd-hda-codec-id:10ec*");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Realtek HD-audio codec");
static struct hda_codec_preset_list realtek_list = {
static struct hda_codec_driver realtek_driver = {
.preset = snd_hda_preset_realtek,
.owner = THIS_MODULE,
};
static int __init patch_realtek_init(void)
{
return snd_hda_add_codec_preset(&realtek_list);
}
static void __exit patch_realtek_exit(void)
{
snd_hda_delete_codec_preset(&realtek_list);
}
module_init(patch_realtek_init)
module_exit(patch_realtek_exit)
module_hda_codec_driver(realtek_driver);
......@@ -319,20 +319,8 @@ MODULE_ALIAS("snd-hda-codec-id:18540018");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Si3054 HD-audio modem codec");
static struct hda_codec_preset_list si3054_list = {
static struct hda_codec_driver si3054_driver = {
.preset = snd_hda_preset_si3054,
.owner = THIS_MODULE,
};
static int __init patch_si3054_init(void)
{
return snd_hda_add_codec_preset(&si3054_list);
}
static void __exit patch_si3054_exit(void)
{
snd_hda_delete_codec_preset(&si3054_list);
}
module_init(patch_si3054_init)
module_exit(patch_si3054_exit)
module_hda_codec_driver(si3054_driver);
......@@ -2132,8 +2132,10 @@ static void stac92hd83xxx_fixup_hp_mic_led(struct hda_codec *codec,
if (action == HDA_FIXUP_ACT_PRE_PROBE) {
spec->mic_mute_led_gpio = 0x08; /* GPIO3 */
#ifdef CONFIG_PM
/* resetting controller clears GPIO, so we need to keep on */
codec->bus->power_keep_link_on = 1;
codec->d3_stop_clk = 0;
#endif
}
}
......@@ -5091,20 +5093,8 @@ MODULE_ALIAS("snd-hda-codec-id:111d*");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("IDT/Sigmatel HD-audio codec");
static struct hda_codec_preset_list sigmatel_list = {
static struct hda_codec_driver sigmatel_driver = {
.preset = snd_hda_preset_sigmatel,
.owner = THIS_MODULE,
};
static int __init patch_sigmatel_init(void)
{
return snd_hda_add_codec_preset(&sigmatel_list);
}
static void __exit patch_sigmatel_exit(void)
{
snd_hda_delete_codec_preset(&sigmatel_list);
}
module_init(patch_sigmatel_init)
module_exit(patch_sigmatel_exit)
module_hda_codec_driver(sigmatel_driver);
......@@ -1884,23 +1884,11 @@ static const struct hda_codec_preset snd_hda_preset_via[] = {
MODULE_ALIAS("snd-hda-codec-id:1106*");
static struct hda_codec_preset_list via_list = {
static struct hda_codec_driver via_driver = {
.preset = snd_hda_preset_via,
.owner = THIS_MODULE,
};
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("VIA HD-audio codec");
static int __init patch_via_init(void)
{
return snd_hda_add_codec_preset(&via_list);
}
static void __exit patch_via_exit(void)
{
snd_hda_delete_codec_preset(&via_list);
}
module_init(patch_via_init)
module_exit(patch_via_exit)
module_hda_codec_driver(via_driver);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment