forked from luck/tmp_suning_uos_patched
ALSA: hda - Move a part of hda_codec stuff into hdac_device
Now some codes and functionalities of hda_codec struct are moved to hdac_device struct. A few basic attributes like the codec address, vendor ID number, FG numbers, etc are moved to hdac_device, and they are accessed like codec->core.addr. The basic verb exec functions are moved, too. Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
d068ebc25e
commit
7639a06c23
|
@ -8,6 +8,9 @@
|
|||
#include <linux/device.h>
|
||||
#include <sound/hda_verbs.h>
|
||||
|
||||
/* codec node id */
|
||||
typedef u16 hda_nid_t;
|
||||
|
||||
struct hdac_bus;
|
||||
struct hdac_device;
|
||||
struct hdac_driver;
|
||||
|
@ -26,6 +29,30 @@ struct hdac_device {
|
|||
struct hdac_bus *bus;
|
||||
unsigned int addr; /* codec address */
|
||||
struct list_head list; /* list point for bus codec_list */
|
||||
|
||||
hda_nid_t afg; /* AFG node id */
|
||||
hda_nid_t mfg; /* MFG node id */
|
||||
|
||||
/* ids */
|
||||
unsigned int vendor_id;
|
||||
unsigned int subsystem_id;
|
||||
unsigned int revision_id;
|
||||
unsigned int afg_function_id;
|
||||
unsigned int mfg_function_id;
|
||||
unsigned int afg_unsol:1;
|
||||
unsigned int mfg_unsol:1;
|
||||
|
||||
unsigned int power_caps; /* FG power caps */
|
||||
|
||||
const char *vendor_name; /* codec vendor name */
|
||||
const char *chip_name; /* codec chip name */
|
||||
|
||||
/* widgets */
|
||||
unsigned int num_nodes;
|
||||
hda_nid_t start_nid, end_nid;
|
||||
|
||||
/* misc flags */
|
||||
atomic_t in_pm; /* suspend/resume being performed */
|
||||
};
|
||||
|
||||
/* device/driver type used for matching */
|
||||
|
@ -34,8 +61,37 @@ enum {
|
|||
HDA_DEV_LEGACY,
|
||||
};
|
||||
|
||||
/* direction */
|
||||
enum {
|
||||
HDA_INPUT, HDA_OUTPUT
|
||||
};
|
||||
|
||||
#define dev_to_hdac_dev(_dev) container_of(_dev, struct hdac_device, dev)
|
||||
|
||||
int snd_hdac_device_init(struct hdac_device *dev, struct hdac_bus *bus,
|
||||
const char *name, unsigned int addr);
|
||||
void snd_hdac_device_exit(struct hdac_device *dev);
|
||||
|
||||
int snd_hdac_refresh_widgets(struct hdac_device *codec);
|
||||
|
||||
unsigned int snd_hdac_make_cmd(struct hdac_device *codec, hda_nid_t nid,
|
||||
unsigned int verb, unsigned int parm);
|
||||
int snd_hdac_read(struct hdac_device *codec, hda_nid_t nid,
|
||||
unsigned int verb, unsigned int parm, unsigned int *res);
|
||||
int snd_hdac_read_parm(struct hdac_device *codec, hda_nid_t nid, int parm);
|
||||
int snd_hdac_get_connections(struct hdac_device *codec, hda_nid_t nid,
|
||||
hda_nid_t *conn_list, int max_conns);
|
||||
int snd_hdac_get_sub_nodes(struct hdac_device *codec, hda_nid_t nid,
|
||||
hda_nid_t *start_id);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
void snd_hdac_power_up(struct hdac_device *codec);
|
||||
void snd_hdac_power_down(struct hdac_device *codec);
|
||||
#else
|
||||
static inline void snd_hdac_power_up(struct hdac_device *codec) {}
|
||||
static inline void snd_hdac_power_down(struct hdac_device *codec) {}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* HD-audio codec base driver
|
||||
*/
|
||||
|
@ -100,4 +156,14 @@ int snd_hdac_bus_add_device(struct hdac_bus *bus, struct hdac_device *codec);
|
|||
void snd_hdac_bus_remove_device(struct hdac_bus *bus,
|
||||
struct hdac_device *codec);
|
||||
|
||||
static inline void snd_hdac_codec_link_up(struct hdac_device *codec)
|
||||
{
|
||||
set_bit(codec->addr, &codec->bus->codec_powered);
|
||||
}
|
||||
|
||||
static inline void snd_hdac_codec_link_down(struct hdac_device *codec)
|
||||
{
|
||||
clear_bit(codec->addr, &codec->bus->codec_powered);
|
||||
}
|
||||
|
||||
#endif /* __SOUND_HDAUDIO_H */
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
snd-hda-core-objs := hda_bus_type.o hdac_bus.o
|
||||
snd-hda-core-objs := hda_bus_type.o hdac_bus.o hdac_device.o
|
||||
|
||||
obj-$(CONFIG_SND_HDA_CORE) += snd-hda-core.o
|
||||
|
|
471
sound/hda/hdac_device.c
Normal file
471
sound/hda/hdac_device.c
Normal file
|
@ -0,0 +1,471 @@
|
|||
/*
|
||||
* HD-audio codec core device
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <sound/hdaudio.h>
|
||||
#include "local.h"
|
||||
|
||||
static void setup_fg_nodes(struct hdac_device *codec);
|
||||
static int get_codec_vendor_name(struct hdac_device *codec);
|
||||
|
||||
static void default_release(struct device *dev)
|
||||
{
|
||||
snd_hdac_device_exit(container_of(dev, struct hdac_device, dev));
|
||||
}
|
||||
|
||||
/**
|
||||
* snd_hdac_device_init - initialize the HD-audio codec base device
|
||||
* @codec: device to initialize
|
||||
* @bus: but to attach
|
||||
* @name: device name string
|
||||
* @addr: codec address
|
||||
*
|
||||
* Returns zero for success or a negative error code.
|
||||
*
|
||||
* This function increments the runtime PM counter and marks it active.
|
||||
* The caller needs to turn it off appropriately later.
|
||||
*
|
||||
* The caller needs to set the device's release op properly by itself.
|
||||
*/
|
||||
int snd_hdac_device_init(struct hdac_device *codec, struct hdac_bus *bus,
|
||||
const char *name, unsigned int addr)
|
||||
{
|
||||
struct device *dev;
|
||||
hda_nid_t fg;
|
||||
int err;
|
||||
|
||||
dev = &codec->dev;
|
||||
device_initialize(dev);
|
||||
dev->parent = bus->dev;
|
||||
dev->bus = &snd_hda_bus_type;
|
||||
dev->release = default_release;
|
||||
dev_set_name(dev, "%s", name);
|
||||
device_enable_async_suspend(dev);
|
||||
|
||||
codec->bus = bus;
|
||||
codec->addr = addr;
|
||||
codec->type = HDA_DEV_CORE;
|
||||
pm_runtime_set_active(&codec->dev);
|
||||
pm_runtime_get_noresume(&codec->dev);
|
||||
atomic_set(&codec->in_pm, 0);
|
||||
|
||||
err = snd_hdac_bus_add_device(bus, codec);
|
||||
if (err < 0)
|
||||
goto error;
|
||||
|
||||
/* fill parameters */
|
||||
codec->vendor_id = snd_hdac_read_parm(codec, AC_NODE_ROOT,
|
||||
AC_PAR_VENDOR_ID);
|
||||
if (codec->vendor_id == -1) {
|
||||
/* read again, hopefully the access method was corrected
|
||||
* in the last read...
|
||||
*/
|
||||
codec->vendor_id = snd_hdac_read_parm(codec, AC_NODE_ROOT,
|
||||
AC_PAR_VENDOR_ID);
|
||||
}
|
||||
|
||||
codec->subsystem_id = snd_hdac_read_parm(codec, AC_NODE_ROOT,
|
||||
AC_PAR_SUBSYSTEM_ID);
|
||||
codec->revision_id = snd_hdac_read_parm(codec, AC_NODE_ROOT,
|
||||
AC_PAR_REV_ID);
|
||||
|
||||
setup_fg_nodes(codec);
|
||||
if (!codec->afg && !codec->mfg) {
|
||||
dev_err(dev, "no AFG or MFG node found\n");
|
||||
err = -ENODEV;
|
||||
goto error;
|
||||
}
|
||||
|
||||
fg = codec->afg ? codec->afg : codec->mfg;
|
||||
|
||||
err = snd_hdac_refresh_widgets(codec);
|
||||
if (err < 0)
|
||||
goto error;
|
||||
|
||||
codec->power_caps = snd_hdac_read_parm(codec, fg, AC_PAR_POWER_STATE);
|
||||
/* reread ssid if not set by parameter */
|
||||
if (codec->subsystem_id == -1)
|
||||
snd_hdac_read(codec, fg, AC_VERB_GET_SUBSYSTEM_ID, 0,
|
||||
&codec->subsystem_id);
|
||||
|
||||
err = get_codec_vendor_name(codec);
|
||||
if (err < 0)
|
||||
goto error;
|
||||
|
||||
codec->chip_name = kasprintf(GFP_KERNEL, "ID %x",
|
||||
codec->vendor_id & 0xffff);
|
||||
if (!codec->chip_name) {
|
||||
err = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
pm_runtime_put_noidle(&codec->dev);
|
||||
put_device(&codec->dev);
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_hdac_device_init);
|
||||
|
||||
/**
|
||||
* snd_hdac_device_exit - clean up the HD-audio codec base device
|
||||
* @codec: device to clean up
|
||||
*/
|
||||
void snd_hdac_device_exit(struct hdac_device *codec)
|
||||
{
|
||||
/* pm_runtime_put_noidle(&codec->dev); */
|
||||
snd_hdac_bus_remove_device(codec->bus, codec);
|
||||
kfree(codec->vendor_name);
|
||||
kfree(codec->chip_name);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_hdac_device_exit);
|
||||
|
||||
/**
|
||||
* snd_hdac_make_cmd - compose a 32bit command word to be sent to the
|
||||
* HD-audio controller
|
||||
* @codec: the codec object
|
||||
* @nid: NID to encode
|
||||
* @verb: verb to encode
|
||||
* @parm: parameter to encode
|
||||
*
|
||||
* Return an encoded command verb or -1 for error.
|
||||
*/
|
||||
unsigned int snd_hdac_make_cmd(struct hdac_device *codec, hda_nid_t nid,
|
||||
unsigned int verb, unsigned int parm)
|
||||
{
|
||||
u32 val, addr;
|
||||
|
||||
addr = codec->addr;
|
||||
if ((addr & ~0xf) || (nid & ~0x7f) ||
|
||||
(verb & ~0xfff) || (parm & ~0xffff)) {
|
||||
dev_err(&codec->dev, "out of range cmd %x:%x:%x:%x\n",
|
||||
addr, nid, verb, parm);
|
||||
return -1;
|
||||
}
|
||||
|
||||
val = addr << 28;
|
||||
val |= (u32)nid << 20;
|
||||
val |= verb << 8;
|
||||
val |= parm;
|
||||
return val;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_hdac_make_cmd);
|
||||
|
||||
/**
|
||||
* snd_hdac_read - execute a verb
|
||||
* @codec: the codec object
|
||||
* @nid: NID to execute a verb
|
||||
* @verb: verb to execute
|
||||
* @parm: parameter for a verb
|
||||
* @res: the pointer to store the result, NULL if running async
|
||||
*
|
||||
* Returns zero if successful, or a negative error code.
|
||||
*/
|
||||
int snd_hdac_read(struct hdac_device *codec, hda_nid_t nid,
|
||||
unsigned int verb, unsigned int parm, unsigned int *res)
|
||||
{
|
||||
unsigned int cmd = snd_hdac_make_cmd(codec, nid, verb, parm);
|
||||
|
||||
return snd_hdac_bus_exec_verb(codec->bus, codec->addr, cmd, res);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_hdac_read);
|
||||
|
||||
/**
|
||||
* snd_hdac_read_parm - read a codec parameter
|
||||
* @codec: the codec object
|
||||
* @nid: NID to read a parameter
|
||||
* @parm: parameter to read
|
||||
*
|
||||
* Returns -1 for error. If you need to distinguish the error more
|
||||
* strictly, use snd_hdac_read() directly.
|
||||
*/
|
||||
int snd_hdac_read_parm(struct hdac_device *codec, hda_nid_t nid, int parm)
|
||||
{
|
||||
int val;
|
||||
|
||||
if (snd_hdac_read(codec, nid, AC_VERB_PARAMETERS, parm, &val))
|
||||
return -1;
|
||||
return val;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_hdac_read_parm);
|
||||
|
||||
/**
|
||||
* snd_hdac_get_sub_nodes - get start NID and number of subtree nodes
|
||||
* @codec: the codec object
|
||||
* @nid: NID to inspect
|
||||
* @start_id: the pointer to store the starting NID
|
||||
*
|
||||
* Returns the number of subtree nodes or zero if not found.
|
||||
*/
|
||||
int snd_hdac_get_sub_nodes(struct hdac_device *codec, hda_nid_t nid,
|
||||
hda_nid_t *start_id)
|
||||
{
|
||||
unsigned int parm;
|
||||
|
||||
parm = snd_hdac_read_parm(codec, nid, AC_PAR_NODE_COUNT);
|
||||
if (parm == -1) {
|
||||
*start_id = 0;
|
||||
return 0;
|
||||
}
|
||||
*start_id = (parm >> 16) & 0x7fff;
|
||||
return (int)(parm & 0x7fff);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_hdac_get_sub_nodes);
|
||||
|
||||
/*
|
||||
* look for an AFG and MFG nodes
|
||||
*/
|
||||
static void setup_fg_nodes(struct hdac_device *codec)
|
||||
{
|
||||
int i, total_nodes, function_id;
|
||||
hda_nid_t nid;
|
||||
|
||||
total_nodes = snd_hdac_get_sub_nodes(codec, AC_NODE_ROOT, &nid);
|
||||
for (i = 0; i < total_nodes; i++, nid++) {
|
||||
function_id = snd_hdac_read_parm(codec, nid,
|
||||
AC_PAR_FUNCTION_TYPE);
|
||||
switch (function_id & 0xff) {
|
||||
case AC_GRP_AUDIO_FUNCTION:
|
||||
codec->afg = nid;
|
||||
codec->afg_function_id = function_id & 0xff;
|
||||
codec->afg_unsol = (function_id >> 8) & 1;
|
||||
break;
|
||||
case AC_GRP_MODEM_FUNCTION:
|
||||
codec->mfg = nid;
|
||||
codec->mfg_function_id = function_id & 0xff;
|
||||
codec->mfg_unsol = (function_id >> 8) & 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* snd_hdac_refresh_widgets - Reset the widget start/end nodes
|
||||
* @codec: the codec object
|
||||
*/
|
||||
int snd_hdac_refresh_widgets(struct hdac_device *codec)
|
||||
{
|
||||
hda_nid_t start_nid;
|
||||
int nums;
|
||||
|
||||
nums = snd_hdac_get_sub_nodes(codec, codec->afg, &start_nid);
|
||||
if (!start_nid || nums <= 0 || nums >= 0xff) {
|
||||
dev_err(&codec->dev, "cannot read sub nodes for FG 0x%02x\n",
|
||||
codec->afg);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
codec->num_nodes = nums;
|
||||
codec->start_nid = start_nid;
|
||||
codec->end_nid = start_nid + nums;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_hdac_refresh_widgets);
|
||||
|
||||
/* return CONNLIST_LEN parameter of the given widget */
|
||||
static unsigned int get_num_conns(struct hdac_device *codec, hda_nid_t nid)
|
||||
{
|
||||
unsigned int wcaps = get_wcaps(codec, nid);
|
||||
unsigned int parm;
|
||||
|
||||
if (!(wcaps & AC_WCAP_CONN_LIST) &&
|
||||
get_wcaps_type(wcaps) != AC_WID_VOL_KNB)
|
||||
return 0;
|
||||
|
||||
parm = snd_hdac_read_parm(codec, nid, AC_PAR_CONNLIST_LEN);
|
||||
if (parm == -1)
|
||||
parm = 0;
|
||||
return parm;
|
||||
}
|
||||
|
||||
/**
|
||||
* snd_hdac_get_connections - get a widget connection list
|
||||
* @codec: the codec object
|
||||
* @nid: NID
|
||||
* @conn_list: the array to store the results, can be NULL
|
||||
* @max_conns: the max size of the given array
|
||||
*
|
||||
* Returns the number of connected widgets, zero for no connection, or a
|
||||
* negative error code. When the number of elements don't fit with the
|
||||
* given array size, it returns -ENOSPC.
|
||||
*
|
||||
* When @conn_list is NULL, it just checks the number of connections.
|
||||
*/
|
||||
int snd_hdac_get_connections(struct hdac_device *codec, hda_nid_t nid,
|
||||
hda_nid_t *conn_list, int max_conns)
|
||||
{
|
||||
unsigned int parm;
|
||||
int i, conn_len, conns, err;
|
||||
unsigned int shift, num_elems, mask;
|
||||
hda_nid_t prev_nid;
|
||||
int null_count = 0;
|
||||
|
||||
parm = get_num_conns(codec, nid);
|
||||
if (!parm)
|
||||
return 0;
|
||||
|
||||
if (parm & AC_CLIST_LONG) {
|
||||
/* long form */
|
||||
shift = 16;
|
||||
num_elems = 2;
|
||||
} else {
|
||||
/* short form */
|
||||
shift = 8;
|
||||
num_elems = 4;
|
||||
}
|
||||
conn_len = parm & AC_CLIST_LENGTH;
|
||||
mask = (1 << (shift-1)) - 1;
|
||||
|
||||
if (!conn_len)
|
||||
return 0; /* no connection */
|
||||
|
||||
if (conn_len == 1) {
|
||||
/* single connection */
|
||||
err = snd_hdac_read(codec, nid, AC_VERB_GET_CONNECT_LIST, 0,
|
||||
&parm);
|
||||
if (err < 0)
|
||||
return err;
|
||||
if (conn_list)
|
||||
conn_list[0] = parm & mask;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* multi connection */
|
||||
conns = 0;
|
||||
prev_nid = 0;
|
||||
for (i = 0; i < conn_len; i++) {
|
||||
int range_val;
|
||||
hda_nid_t val, n;
|
||||
|
||||
if (i % num_elems == 0) {
|
||||
err = snd_hdac_read(codec, nid,
|
||||
AC_VERB_GET_CONNECT_LIST, i,
|
||||
&parm);
|
||||
if (err < 0)
|
||||
return -EIO;
|
||||
}
|
||||
range_val = !!(parm & (1 << (shift-1))); /* ranges */
|
||||
val = parm & mask;
|
||||
if (val == 0 && null_count++) { /* no second chance */
|
||||
dev_dbg(&codec->dev,
|
||||
"invalid CONNECT_LIST verb %x[%i]:%x\n",
|
||||
nid, i, parm);
|
||||
return 0;
|
||||
}
|
||||
parm >>= shift;
|
||||
if (range_val) {
|
||||
/* ranges between the previous and this one */
|
||||
if (!prev_nid || prev_nid >= val) {
|
||||
dev_warn(&codec->dev,
|
||||
"invalid dep_range_val %x:%x\n",
|
||||
prev_nid, val);
|
||||
continue;
|
||||
}
|
||||
for (n = prev_nid + 1; n <= val; n++) {
|
||||
if (conn_list) {
|
||||
if (conns >= max_conns)
|
||||
return -ENOSPC;
|
||||
conn_list[conns] = n;
|
||||
}
|
||||
conns++;
|
||||
}
|
||||
} else {
|
||||
if (conn_list) {
|
||||
if (conns >= max_conns)
|
||||
return -ENOSPC;
|
||||
conn_list[conns] = val;
|
||||
}
|
||||
conns++;
|
||||
}
|
||||
prev_nid = val;
|
||||
}
|
||||
return conns;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_hdac_get_connections);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
/**
|
||||
* snd_hdac_power_up - increment the runtime pm counter
|
||||
* @codec: the codec object
|
||||
*/
|
||||
void snd_hdac_power_up(struct hdac_device *codec)
|
||||
{
|
||||
struct device *dev = &codec->dev;
|
||||
|
||||
if (atomic_read(&codec->in_pm))
|
||||
return;
|
||||
pm_runtime_get_sync(dev);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_hdac_power_up);
|
||||
|
||||
/**
|
||||
* snd_hdac_power_up - decrement the runtime pm counter
|
||||
* @codec: the codec object
|
||||
*/
|
||||
void snd_hdac_power_down(struct hdac_device *codec)
|
||||
{
|
||||
struct device *dev = &codec->dev;
|
||||
|
||||
if (atomic_read(&codec->in_pm))
|
||||
return;
|
||||
pm_runtime_mark_last_busy(dev);
|
||||
pm_runtime_put_autosuspend(dev);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_hdac_power_down);
|
||||
#endif
|
||||
|
||||
/* 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 */
|
||||
};
|
||||
|
||||
/* store the codec vendor name */
|
||||
static int get_codec_vendor_name(struct hdac_device *codec)
|
||||
{
|
||||
const struct hda_vendor_id *c;
|
||||
u16 vendor_id = codec->vendor_id >> 16;
|
||||
|
||||
for (c = hda_vendor_ids; c->id; c++) {
|
||||
if (c->id == vendor_id) {
|
||||
codec->vendor_name = kstrdup(c->name, GFP_KERNEL);
|
||||
return codec->vendor_name ? 0 : -ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
codec->vendor_name = kasprintf(GFP_KERNEL, "Generic %04x", vendor_id);
|
||||
return codec->vendor_name ? 0 : -ENOMEM;
|
||||
}
|
19
sound/hda/local.h
Normal file
19
sound/hda/local.h
Normal file
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* Local helper macros and functions for HD-audio core drivers
|
||||
*/
|
||||
|
||||
#ifndef __HDAC_LOCAL_H
|
||||
#define __HDAC_LOCAL_H
|
||||
|
||||
#define get_wcaps(codec, nid) \
|
||||
snd_hdac_read_parm(codec, nid, AC_PAR_AUDIO_WIDGET_CAP)
|
||||
|
||||
/* get the widget type from widget capability bits */
|
||||
static inline int get_wcaps_type(unsigned int wcaps)
|
||||
{
|
||||
if (!wcaps)
|
||||
return -1; /* invalid type */
|
||||
return (wcaps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
|
||||
}
|
||||
|
||||
#endif /* __HDAC_LOCAL_H */
|
|
@ -172,7 +172,7 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec,
|
|||
const hda_nid_t *ignore_nids,
|
||||
unsigned int cond_flags)
|
||||
{
|
||||
hda_nid_t nid, end_nid;
|
||||
hda_nid_t nid;
|
||||
short seq, assoc_line_out;
|
||||
struct auto_out_pin line_out[ARRAY_SIZE(cfg->line_out_pins)];
|
||||
struct auto_out_pin speaker_out[ARRAY_SIZE(cfg->speaker_pins)];
|
||||
|
@ -189,8 +189,7 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec,
|
|||
memset(hp_out, 0, sizeof(hp_out));
|
||||
assoc_line_out = 0;
|
||||
|
||||
end_nid = codec->start_nid + codec->num_nodes;
|
||||
for (nid = codec->start_nid; nid < end_nid; nid++) {
|
||||
for_each_hda_codec_node(nid, codec) {
|
||||
unsigned int wid_caps = get_wcaps(codec, nid);
|
||||
unsigned int wid_type = get_wcaps_type(wid_caps);
|
||||
unsigned int def_conf;
|
||||
|
@ -410,7 +409,7 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec,
|
|||
* debug prints of the parsed results
|
||||
*/
|
||||
codec_info(codec, "autoconfig for %s: line_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x) type:%s\n",
|
||||
codec->chip_name, cfg->line_outs, cfg->line_out_pins[0],
|
||||
codec->core.chip_name, cfg->line_outs, cfg->line_out_pins[0],
|
||||
cfg->line_out_pins[1], cfg->line_out_pins[2],
|
||||
cfg->line_out_pins[3], cfg->line_out_pins[4],
|
||||
cfg->line_out_type == AUTO_PIN_HP_OUT ? "hp" :
|
||||
|
@ -836,33 +835,33 @@ static void apply_fixup(struct hda_codec *codec, int id, int action, int depth)
|
|||
if (action != HDA_FIXUP_ACT_PRE_PROBE || !fix->v.pins)
|
||||
break;
|
||||
codec_dbg(codec, "%s: Apply pincfg for %s\n",
|
||||
codec->chip_name, modelname);
|
||||
codec->core.chip_name, modelname);
|
||||
snd_hda_apply_pincfgs(codec, fix->v.pins);
|
||||
break;
|
||||
case HDA_FIXUP_VERBS:
|
||||
if (action != HDA_FIXUP_ACT_PROBE || !fix->v.verbs)
|
||||
break;
|
||||
codec_dbg(codec, "%s: Apply fix-verbs for %s\n",
|
||||
codec->chip_name, modelname);
|
||||
codec->core.chip_name, modelname);
|
||||
snd_hda_add_verbs(codec, fix->v.verbs);
|
||||
break;
|
||||
case HDA_FIXUP_FUNC:
|
||||
if (!fix->v.func)
|
||||
break;
|
||||
codec_dbg(codec, "%s: Apply fix-func for %s\n",
|
||||
codec->chip_name, modelname);
|
||||
codec->core.chip_name, modelname);
|
||||
fix->v.func(codec, fix, action);
|
||||
break;
|
||||
case HDA_FIXUP_PINCTLS:
|
||||
if (action != HDA_FIXUP_ACT_PROBE || !fix->v.pins)
|
||||
break;
|
||||
codec_dbg(codec, "%s: Apply pinctl for %s\n",
|
||||
codec->chip_name, modelname);
|
||||
codec->core.chip_name, modelname);
|
||||
set_pin_targets(codec, fix->v.pins);
|
||||
break;
|
||||
default:
|
||||
codec_err(codec, "%s: Invalid fixup type %d\n",
|
||||
codec->chip_name, fix->type);
|
||||
codec->core.chip_name, fix->type);
|
||||
break;
|
||||
}
|
||||
if (!fix->chained || fix->chained_before)
|
||||
|
@ -912,16 +911,16 @@ void snd_hda_pick_pin_fixup(struct hda_codec *codec,
|
|||
return;
|
||||
|
||||
for (pq = pin_quirk; pq->subvendor; pq++) {
|
||||
if ((codec->subsystem_id & 0xffff0000) != (pq->subvendor << 16))
|
||||
if ((codec->core.subsystem_id & 0xffff0000) != (pq->subvendor << 16))
|
||||
continue;
|
||||
if (codec->vendor_id != pq->codec)
|
||||
if (codec->core.vendor_id != pq->codec)
|
||||
continue;
|
||||
if (pin_config_match(codec, pq->pins)) {
|
||||
codec->fixup_id = pq->value;
|
||||
#ifdef CONFIG_SND_DEBUG_VERBOSE
|
||||
codec->fixup_name = pq->name;
|
||||
codec_dbg(codec, "%s: picked fixup %s (pin match)\n",
|
||||
codec->chip_name, codec->fixup_name);
|
||||
codec->core.chip_name, codec->fixup_name);
|
||||
#endif
|
||||
codec->fixup_list = fixlist;
|
||||
return;
|
||||
|
@ -963,7 +962,7 @@ void snd_hda_pick_fixup(struct hda_codec *codec,
|
|||
codec->fixup_name = NULL;
|
||||
codec->fixup_id = HDA_FIXUP_ID_NO_FIXUP;
|
||||
codec_dbg(codec, "%s: picked no fixup (nofixup specified)\n",
|
||||
codec->chip_name);
|
||||
codec->core.chip_name);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -974,7 +973,7 @@ void snd_hda_pick_fixup(struct hda_codec *codec,
|
|||
codec->fixup_name = models->name;
|
||||
codec->fixup_list = fixlist;
|
||||
codec_dbg(codec, "%s: picked fixup %s (model specified)\n",
|
||||
codec->chip_name, codec->fixup_name);
|
||||
codec->core.chip_name, codec->fixup_name);
|
||||
return;
|
||||
}
|
||||
models++;
|
||||
|
@ -987,7 +986,7 @@ void snd_hda_pick_fixup(struct hda_codec *codec,
|
|||
#ifdef CONFIG_SND_DEBUG_VERBOSE
|
||||
name = q->name;
|
||||
codec_dbg(codec, "%s: picked fixup %s (PCI SSID%s)\n",
|
||||
codec->chip_name, name, q->subdevice_mask ? "" : " - vendor generic");
|
||||
codec->core.chip_name, name, q->subdevice_mask ? "" : " - vendor generic");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -996,12 +995,12 @@ void snd_hda_pick_fixup(struct hda_codec *codec,
|
|||
unsigned int vendorid =
|
||||
q->subdevice | (q->subvendor << 16);
|
||||
unsigned int mask = 0xffff0000 | q->subdevice_mask;
|
||||
if ((codec->subsystem_id & mask) == (vendorid & mask)) {
|
||||
if ((codec->core.subsystem_id & mask) == (vendorid & mask)) {
|
||||
id = q->value;
|
||||
#ifdef CONFIG_SND_DEBUG_VERBOSE
|
||||
name = q->name;
|
||||
codec_dbg(codec, "%s: picked fixup %s (codec SSID)\n",
|
||||
codec->chip_name, name);
|
||||
codec->core.chip_name, name);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -165,8 +165,8 @@ static int snd_hda_do_attach(struct hda_beep *beep)
|
|||
input_dev->id.bustype = BUS_PCI;
|
||||
input_dev->dev.parent = &codec->card->card_dev;
|
||||
|
||||
input_dev->id.vendor = codec->vendor_id >> 16;
|
||||
input_dev->id.product = codec->vendor_id & 0xffff;
|
||||
input_dev->id.vendor = codec->core.vendor_id >> 16;
|
||||
input_dev->id.product = codec->core.vendor_id & 0xffff;
|
||||
input_dev->id.version = 0x01;
|
||||
|
||||
input_dev->evbit[0] = BIT_MASK(EV_SND);
|
||||
|
|
|
@ -14,36 +14,6 @@
|
|||
#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
|
||||
*/
|
||||
|
@ -54,19 +24,19 @@ static int hda_codec_match(struct hdac_device *dev, struct hdac_driver *drv)
|
|||
container_of(drv, struct hda_codec_driver, core);
|
||||
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;
|
||||
u32 id = codec->probe_id ? codec->probe_id : codec->core.vendor_id;
|
||||
|
||||
for (preset = driver->preset; preset->id; preset++) {
|
||||
u32 mask = preset->mask;
|
||||
|
||||
if (preset->afg && preset->afg != codec->afg)
|
||||
if (preset->afg && preset->afg != codec->core.afg)
|
||||
continue;
|
||||
if (preset->mfg && preset->mfg != codec->mfg)
|
||||
if (preset->mfg && preset->mfg != codec->core.mfg)
|
||||
continue;
|
||||
if (!mask)
|
||||
mask = ~0;
|
||||
if (preset->id == (id & mask) &&
|
||||
(!preset->rev || preset->rev == codec->revision_id)) {
|
||||
(!preset->rev || preset->rev == codec->core.revision_id)) {
|
||||
codec->preset = preset;
|
||||
return 1;
|
||||
}
|
||||
|
@ -86,15 +56,11 @@ static void hda_codec_unsol_event(struct hdac_device *dev, unsigned int ev)
|
|||
/* 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;
|
||||
if (name) {
|
||||
kfree(codec->core.chip_name);
|
||||
codec->core.chip_name = kstrdup(name, GFP_KERNEL);
|
||||
}
|
||||
codec->chip_name = kstrdup(name, GFP_KERNEL);
|
||||
return codec->chip_name ? 0 : -ENOMEM;
|
||||
return codec->core.chip_name ? 0 : -ENOMEM;
|
||||
}
|
||||
|
||||
static int hda_codec_driver_probe(struct device *dev)
|
||||
|
@ -192,48 +158,23 @@ static inline bool codec_probed(struct hda_codec *codec)
|
|||
static void codec_bind_module(struct hda_codec *codec)
|
||||
{
|
||||
#ifdef MODULE
|
||||
request_module("snd-hda-codec-id:%08x", codec->vendor_id);
|
||||
request_module("snd-hda-codec-id:%08x", codec->core.vendor_id);
|
||||
if (codec_probed(codec))
|
||||
return;
|
||||
request_module("snd-hda-codec-id:%04x*",
|
||||
(codec->vendor_id >> 16) & 0xffff);
|
||||
(codec->core.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;
|
||||
hda_nid_t nid;
|
||||
|
||||
for (i = 0; i < codec->num_nodes; i++, nid++) {
|
||||
for_each_hda_codec_node(nid, codec) {
|
||||
unsigned int wcaps = get_wcaps(codec, nid);
|
||||
switch (get_wcaps_type(wcaps)) {
|
||||
case AC_WID_AUD_IN:
|
||||
|
@ -294,12 +235,6 @@ 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
|
||||
|
@ -320,10 +255,10 @@ int snd_hda_codec_configure(struct hda_codec *codec)
|
|||
}
|
||||
|
||||
/* audio codec should override the mixer name */
|
||||
if (codec->afg || !*codec->card->mixername)
|
||||
if (codec->core.afg || !*codec->card->mixername)
|
||||
snprintf(codec->card->mixername,
|
||||
sizeof(codec->card->mixername),
|
||||
"%s %s", codec->vendor_name, codec->chip_name);
|
||||
sizeof(codec->card->mixername), "%s %s",
|
||||
codec->core.vendor_name, codec->core.chip_name);
|
||||
return 0;
|
||||
|
||||
error:
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
#include <sound/hda_hwdep.h>
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
#define codec_in_pm(codec) atomic_read(&(codec)->in_pm)
|
||||
#define codec_in_pm(codec) atomic_read(&(codec)->core.in_pm)
|
||||
#define hda_codec_is_power_on(codec) \
|
||||
(!pm_runtime_suspended(hda_codec_dev(codec)))
|
||||
#else
|
||||
|
@ -48,6 +48,11 @@
|
|||
#define hda_codec_is_power_on(codec) 1
|
||||
#endif
|
||||
|
||||
#define codec_has_epss(codec) \
|
||||
((codec)->core.power_caps & AC_PWRST_EPSS)
|
||||
#define codec_has_clkstop(codec) \
|
||||
((codec)->core.power_caps & AC_PWRST_CLKSTOP)
|
||||
|
||||
/**
|
||||
* snd_hda_get_jack_location - Give a location string of the jack
|
||||
* @cfg: pin default config value
|
||||
|
@ -118,30 +123,6 @@ const char *snd_hda_get_jack_type(u32 cfg)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(snd_hda_get_jack_type);
|
||||
|
||||
/*
|
||||
* Compose a 32bit command word to be sent to the HD-audio controller
|
||||
*/
|
||||
static inline unsigned int
|
||||
make_codec_cmd(struct hda_codec *codec, hda_nid_t nid, int flags,
|
||||
unsigned int verb, unsigned int parm)
|
||||
{
|
||||
unsigned int addr = codec->core.addr;
|
||||
u32 val;
|
||||
|
||||
if ((addr & ~0xf) || (nid & ~0x7f) ||
|
||||
(verb & ~0xfff) || (parm & ~0xffff)) {
|
||||
codec_err(codec, "hda-codec: out of range cmd %x:%x:%x:%x\n",
|
||||
addr, nid, verb, parm);
|
||||
return ~0;
|
||||
}
|
||||
|
||||
val = (u32)addr << 28;
|
||||
val |= (u32)nid << 20;
|
||||
val |= verb << 8;
|
||||
val |= parm;
|
||||
return val;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send and receive a verb
|
||||
*/
|
||||
|
@ -194,7 +175,7 @@ unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid,
|
|||
int flags,
|
||||
unsigned int verb, unsigned int parm)
|
||||
{
|
||||
unsigned cmd = make_codec_cmd(codec, nid, flags, verb, parm);
|
||||
unsigned int cmd = snd_hdac_make_cmd(&codec->core, nid, verb, parm);
|
||||
unsigned int res;
|
||||
if (codec_exec_verb(codec, cmd, flags, &res))
|
||||
return -1;
|
||||
|
@ -217,7 +198,7 @@ EXPORT_SYMBOL_GPL(snd_hda_codec_read);
|
|||
int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int flags,
|
||||
unsigned int verb, unsigned int parm)
|
||||
{
|
||||
unsigned int cmd = make_codec_cmd(codec, nid, flags, verb, parm);
|
||||
unsigned int cmd = snd_hdac_make_cmd(&codec->core, nid, verb, parm);
|
||||
return codec_exec_verb(codec, cmd, flags, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_hda_codec_write);
|
||||
|
@ -237,30 +218,6 @@ void snd_hda_sequence_write(struct hda_codec *codec, const struct hda_verb *seq)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(snd_hda_sequence_write);
|
||||
|
||||
/**
|
||||
* snd_hda_get_sub_nodes - get the range of sub nodes
|
||||
* @codec: the HDA codec
|
||||
* @nid: NID to parse
|
||||
* @start_id: the pointer to store the start NID
|
||||
*
|
||||
* Parse the NID and store the start NID of its sub-nodes.
|
||||
* Returns the number of sub-nodes.
|
||||
*/
|
||||
int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid,
|
||||
hda_nid_t *start_id)
|
||||
{
|
||||
unsigned int parm;
|
||||
|
||||
parm = snd_hda_param_read(codec, nid, AC_PAR_NODE_COUNT);
|
||||
if (parm == -1) {
|
||||
*start_id = 0;
|
||||
return 0;
|
||||
}
|
||||
*start_id = (parm >> 16) & 0x7fff;
|
||||
return (int)(parm & 0x7fff);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_hda_get_sub_nodes);
|
||||
|
||||
/* connection list element */
|
||||
struct hda_conn_list {
|
||||
struct list_head list;
|
||||
|
@ -401,128 +358,6 @@ int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
|
|||
}
|
||||
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)
|
||||
{
|
||||
unsigned int wcaps = get_wcaps(codec, nid);
|
||||
unsigned int parm;
|
||||
|
||||
if (!(wcaps & AC_WCAP_CONN_LIST) &&
|
||||
get_wcaps_type(wcaps) != AC_WID_VOL_KNB)
|
||||
return 0;
|
||||
|
||||
parm = snd_hda_param_read(codec, nid, AC_PAR_CONNLIST_LEN);
|
||||
if (parm == -1)
|
||||
parm = 0;
|
||||
return parm;
|
||||
}
|
||||
|
||||
int snd_hda_get_num_raw_conns(struct hda_codec *codec, hda_nid_t nid)
|
||||
{
|
||||
return snd_hda_get_raw_connections(codec, nid, NULL, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* snd_hda_get_raw_connections - copy connection list without cache
|
||||
* @codec: the HDA codec
|
||||
* @nid: NID to parse
|
||||
* @conn_list: connection list array
|
||||
* @max_conns: max. number of connections to store
|
||||
*
|
||||
* Like snd_hda_get_connections(), copy the connection list but without
|
||||
* checking through the connection-list cache.
|
||||
* Currently called only from hda_proc.c, so not exported.
|
||||
*/
|
||||
int snd_hda_get_raw_connections(struct hda_codec *codec, hda_nid_t nid,
|
||||
hda_nid_t *conn_list, int max_conns)
|
||||
{
|
||||
unsigned int parm;
|
||||
int i, conn_len, conns;
|
||||
unsigned int shift, num_elems, mask;
|
||||
hda_nid_t prev_nid;
|
||||
int null_count = 0;
|
||||
|
||||
parm = get_num_conns(codec, nid);
|
||||
if (!parm)
|
||||
return 0;
|
||||
|
||||
if (parm & AC_CLIST_LONG) {
|
||||
/* long form */
|
||||
shift = 16;
|
||||
num_elems = 2;
|
||||
} else {
|
||||
/* short form */
|
||||
shift = 8;
|
||||
num_elems = 4;
|
||||
}
|
||||
conn_len = parm & AC_CLIST_LENGTH;
|
||||
mask = (1 << (shift-1)) - 1;
|
||||
|
||||
if (!conn_len)
|
||||
return 0; /* no connection */
|
||||
|
||||
if (conn_len == 1) {
|
||||
/* single connection */
|
||||
parm = snd_hda_codec_read(codec, nid, 0,
|
||||
AC_VERB_GET_CONNECT_LIST, 0);
|
||||
if (parm == -1 && codec->bus->rirb_error)
|
||||
return -EIO;
|
||||
if (conn_list)
|
||||
conn_list[0] = parm & mask;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* multi connection */
|
||||
conns = 0;
|
||||
prev_nid = 0;
|
||||
for (i = 0; i < conn_len; i++) {
|
||||
int range_val;
|
||||
hda_nid_t val, n;
|
||||
|
||||
if (i % num_elems == 0) {
|
||||
parm = snd_hda_codec_read(codec, nid, 0,
|
||||
AC_VERB_GET_CONNECT_LIST, i);
|
||||
if (parm == -1 && codec->bus->rirb_error)
|
||||
return -EIO;
|
||||
}
|
||||
range_val = !!(parm & (1 << (shift-1))); /* ranges */
|
||||
val = parm & mask;
|
||||
if (val == 0 && null_count++) { /* no second chance */
|
||||
codec_dbg(codec,
|
||||
"invalid CONNECT_LIST verb %x[%i]:%x\n",
|
||||
nid, i, parm);
|
||||
return 0;
|
||||
}
|
||||
parm >>= shift;
|
||||
if (range_val) {
|
||||
/* ranges between the previous and this one */
|
||||
if (!prev_nid || prev_nid >= val) {
|
||||
codec_warn(codec,
|
||||
"invalid dep_range_val %x:%x\n",
|
||||
prev_nid, val);
|
||||
continue;
|
||||
}
|
||||
for (n = prev_nid + 1; n <= val; n++) {
|
||||
if (conn_list) {
|
||||
if (conns >= max_conns)
|
||||
return -ENOSPC;
|
||||
conn_list[conns] = n;
|
||||
}
|
||||
conns++;
|
||||
}
|
||||
} else {
|
||||
if (conn_list) {
|
||||
if (conns >= max_conns)
|
||||
return -ENOSPC;
|
||||
conn_list[conns] = val;
|
||||
}
|
||||
conns++;
|
||||
}
|
||||
prev_nid = val;
|
||||
}
|
||||
return conns;
|
||||
}
|
||||
|
||||
/**
|
||||
* snd_hda_override_conn_list - add/modify the connection-list to cache
|
||||
* @codec: the HDA codec
|
||||
|
@ -737,35 +572,6 @@ int snd_hda_bus_new(struct snd_card *card,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(snd_hda_bus_new);
|
||||
|
||||
/*
|
||||
* look for an AFG and MFG nodes
|
||||
*/
|
||||
static void setup_fg_nodes(struct hda_codec *codec)
|
||||
{
|
||||
int i, total_nodes, function_id;
|
||||
hda_nid_t nid;
|
||||
|
||||
total_nodes = snd_hda_get_sub_nodes(codec, AC_NODE_ROOT, &nid);
|
||||
for (i = 0; i < total_nodes; i++, nid++) {
|
||||
function_id = snd_hda_param_read(codec, nid,
|
||||
AC_PAR_FUNCTION_TYPE);
|
||||
switch (function_id & 0xff) {
|
||||
case AC_GRP_AUDIO_FUNCTION:
|
||||
codec->afg = nid;
|
||||
codec->afg_function_id = function_id & 0xff;
|
||||
codec->afg_unsol = (function_id >> 8) & 1;
|
||||
break;
|
||||
case AC_GRP_MODEM_FUNCTION:
|
||||
codec->mfg = nid;
|
||||
codec->mfg_function_id = function_id & 0xff;
|
||||
codec->mfg_unsol = (function_id >> 8) & 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* read widget caps for each widget and store in cache
|
||||
*/
|
||||
|
@ -774,13 +580,11 @@ static int read_widget_caps(struct hda_codec *codec, hda_nid_t fg_node)
|
|||
int i;
|
||||
hda_nid_t nid;
|
||||
|
||||
codec->num_nodes = snd_hda_get_sub_nodes(codec, fg_node,
|
||||
&codec->start_nid);
|
||||
codec->wcaps = kmalloc(codec->num_nodes * 4, GFP_KERNEL);
|
||||
codec->wcaps = kmalloc(codec->core.num_nodes * 4, GFP_KERNEL);
|
||||
if (!codec->wcaps)
|
||||
return -ENOMEM;
|
||||
nid = codec->start_nid;
|
||||
for (i = 0; i < codec->num_nodes; i++, nid++)
|
||||
nid = codec->core.start_nid;
|
||||
for (i = 0; i < codec->core.num_nodes; i++, nid++)
|
||||
codec->wcaps[i] = snd_hda_param_read(codec, nid,
|
||||
AC_PAR_AUDIO_WIDGET_CAP);
|
||||
return 0;
|
||||
|
@ -789,10 +593,9 @@ static int read_widget_caps(struct hda_codec *codec, hda_nid_t fg_node)
|
|||
/* read all pin default configurations and save codec->init_pins */
|
||||
static int read_pin_defaults(struct hda_codec *codec)
|
||||
{
|
||||
int i;
|
||||
hda_nid_t nid = codec->start_nid;
|
||||
hda_nid_t nid;
|
||||
|
||||
for (i = 0; i < codec->num_nodes; i++, nid++) {
|
||||
for_each_hda_codec_node(nid, codec) {
|
||||
struct hda_pincfg *pin;
|
||||
unsigned int wcaps = get_wcaps(codec, nid);
|
||||
unsigned int wid_type = get_wcaps_type(wcaps);
|
||||
|
@ -1136,9 +939,6 @@ void snd_hda_codec_cleanup_for_unbind(struct hda_codec *codec)
|
|||
remove_conn_list(codec);
|
||||
}
|
||||
|
||||
static bool snd_hda_codec_get_supported_ps(struct hda_codec *codec,
|
||||
hda_nid_t fg, unsigned int power_state);
|
||||
|
||||
static unsigned int hda_set_power_state(struct hda_codec *codec,
|
||||
unsigned int power_state);
|
||||
|
||||
|
@ -1178,12 +978,10 @@ static void snd_hda_codec_dev_release(struct device *dev)
|
|||
struct hda_codec *codec = dev_to_hda_codec(dev);
|
||||
|
||||
free_init_pincfgs(codec);
|
||||
snd_hdac_bus_remove_device(&codec->bus->core, &codec->core);
|
||||
snd_hdac_device_exit(&codec->core);
|
||||
snd_hda_sysfs_clear(codec);
|
||||
free_hda_cache(&codec->amp_cache);
|
||||
free_hda_cache(&codec->cmd_cache);
|
||||
kfree(codec->vendor_name);
|
||||
kfree(codec->chip_name);
|
||||
kfree(codec->modelname);
|
||||
kfree(codec->wcaps);
|
||||
kfree(codec);
|
||||
|
@ -1201,7 +999,6 @@ int snd_hda_codec_new(struct hda_bus *bus, struct snd_card *card,
|
|||
unsigned int codec_addr, struct hda_codec **codecp)
|
||||
{
|
||||
struct hda_codec *codec;
|
||||
struct device *dev;
|
||||
char component[31];
|
||||
hda_nid_t fg;
|
||||
int err;
|
||||
|
@ -1220,19 +1017,16 @@ int snd_hda_codec_new(struct hda_bus *bus, struct snd_card *card,
|
|||
if (!codec)
|
||||
return -ENOMEM;
|
||||
|
||||
codec->core.bus = &bus->core;
|
||||
codec->core.addr = codec_addr;
|
||||
codec->core.type = HDA_DEV_LEGACY;
|
||||
sprintf(component, "hdaudioC%dD%d", card->number, codec_addr);
|
||||
err = snd_hdac_device_init(&codec->core, &bus->core, component,
|
||||
codec_addr);
|
||||
if (err < 0) {
|
||||
kfree(codec);
|
||||
return err;
|
||||
}
|
||||
|
||||
dev = hda_codec_dev(codec);
|
||||
device_initialize(dev);
|
||||
dev->parent = bus->core.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", card->number, codec_addr);
|
||||
dev_set_drvdata(dev, codec); /* for sysfs */
|
||||
device_enable_async_suspend(dev);
|
||||
codec->core.dev.release = snd_hda_codec_dev_release;
|
||||
codec->core.type = HDA_DEV_LEGACY;
|
||||
|
||||
codec->bus = bus;
|
||||
codec->card = card;
|
||||
|
@ -1258,12 +1052,6 @@ int snd_hda_codec_new(struct hda_bus *bus, struct snd_card *card,
|
|||
codec->fixup_id = HDA_FIXUP_ID_NOT_SET;
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
/* snd_hda_codec_new() marks the codec as power-up, and leave it as is.
|
||||
* it's powered down later in snd_hda_codec_dev_register().
|
||||
*/
|
||||
set_bit(codec->core.addr, &bus->core.codec_powered);
|
||||
pm_runtime_set_active(hda_codec_dev(codec));
|
||||
pm_runtime_get_noresume(hda_codec_dev(codec));
|
||||
codec->power_jiffies = jiffies;
|
||||
#endif
|
||||
|
||||
|
@ -1277,31 +1065,7 @@ int snd_hda_codec_new(struct hda_bus *bus, struct snd_card *card,
|
|||
}
|
||||
}
|
||||
|
||||
err = snd_hdac_bus_add_device(&bus->core, &codec->core);
|
||||
if (err < 0)
|
||||
goto error;
|
||||
|
||||
codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT,
|
||||
AC_PAR_VENDOR_ID);
|
||||
if (codec->vendor_id == -1)
|
||||
/* read again, hopefully the access method was corrected
|
||||
* in the last read...
|
||||
*/
|
||||
codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT,
|
||||
AC_PAR_VENDOR_ID);
|
||||
codec->subsystem_id = snd_hda_param_read(codec, AC_NODE_ROOT,
|
||||
AC_PAR_SUBSYSTEM_ID);
|
||||
codec->revision_id = snd_hda_param_read(codec, AC_NODE_ROOT,
|
||||
AC_PAR_REV_ID);
|
||||
|
||||
setup_fg_nodes(codec);
|
||||
if (!codec->afg && !codec->mfg) {
|
||||
codec_err(codec, "no AFG or MFG node found\n");
|
||||
err = -ENODEV;
|
||||
goto error;
|
||||
}
|
||||
|
||||
fg = codec->afg ? codec->afg : codec->mfg;
|
||||
fg = codec->core.afg ? codec->core.afg : codec->core.mfg;
|
||||
err = read_widget_caps(codec, fg);
|
||||
if (err < 0)
|
||||
goto error;
|
||||
|
@ -1309,19 +1073,6 @@ int snd_hda_codec_new(struct hda_bus *bus, struct snd_card *card,
|
|||
if (err < 0)
|
||||
goto error;
|
||||
|
||||
if (!codec->subsystem_id) {
|
||||
codec->subsystem_id =
|
||||
snd_hda_codec_read(codec, fg, 0,
|
||||
AC_VERB_GET_SUBSYSTEM_ID, 0);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
codec->d3_stop_clk = snd_hda_codec_get_supported_ps(codec, fg,
|
||||
AC_PWRST_CLKSTOP);
|
||||
#endif
|
||||
codec->epss = snd_hda_codec_get_supported_ps(codec, fg,
|
||||
AC_PWRST_EPSS);
|
||||
|
||||
/* power-up all before initialization */
|
||||
hda_set_power_state(codec, AC_PWRST_D0);
|
||||
|
||||
|
@ -1329,8 +1080,8 @@ int snd_hda_codec_new(struct hda_bus *bus, struct snd_card *card,
|
|||
|
||||
snd_hda_create_hwdep(codec);
|
||||
|
||||
sprintf(component, "HDA:%08x,%08x,%08x", codec->vendor_id,
|
||||
codec->subsystem_id, codec->revision_id);
|
||||
sprintf(component, "HDA:%08x,%08x,%08x", codec->core.vendor_id,
|
||||
codec->core.subsystem_id, codec->core.revision_id);
|
||||
snd_component_add(card, component);
|
||||
|
||||
err = snd_device_new(card, SNDRV_DEV_CODEC, codec, &dev_ops);
|
||||
|
@ -1342,6 +1093,7 @@ int snd_hda_codec_new(struct hda_bus *bus, struct snd_card *card,
|
|||
return 0;
|
||||
|
||||
error:
|
||||
pm_runtime_put_noidle(hda_codec_dev(codec));
|
||||
put_device(hda_codec_dev(codec));
|
||||
return err;
|
||||
}
|
||||
|
@ -1359,11 +1111,15 @@ int snd_hda_codec_update_widgets(struct hda_codec *codec)
|
|||
hda_nid_t fg;
|
||||
int err;
|
||||
|
||||
err = snd_hdac_refresh_widgets(&codec->core);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
/* Assume the function group node does not change,
|
||||
* only the widget nodes may change.
|
||||
*/
|
||||
kfree(codec->wcaps);
|
||||
fg = codec->afg ? codec->afg : codec->mfg;
|
||||
fg = codec->core.afg ? codec->core.afg : codec->core.mfg;
|
||||
err = read_widget_caps(codec, fg);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
@ -1663,7 +1419,7 @@ static unsigned int read_amp_cap(struct hda_codec *codec, hda_nid_t nid,
|
|||
int direction)
|
||||
{
|
||||
if (!(get_wcaps(codec, nid) & AC_WCAP_AMP_OVRD))
|
||||
nid = codec->afg;
|
||||
nid = codec->core.afg;
|
||||
return snd_hda_param_read(codec, nid,
|
||||
direction == HDA_OUTPUT ?
|
||||
AC_PAR_AMP_OUT_CAP : AC_PAR_AMP_IN_CAP);
|
||||
|
@ -3664,10 +3420,9 @@ 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)
|
||||
{
|
||||
hda_nid_t nid = codec->start_nid;
|
||||
int i;
|
||||
hda_nid_t nid;
|
||||
|
||||
for (i = 0; i < codec->num_nodes; i++, nid++) {
|
||||
for_each_hda_codec_node(nid, codec) {
|
||||
unsigned int wcaps = get_wcaps(codec, nid);
|
||||
unsigned int state = power_state;
|
||||
if (!(wcaps & AC_WCAP_POWER))
|
||||
|
@ -3683,22 +3438,6 @@ void snd_hda_codec_set_power_to_all(struct hda_codec *codec, hda_nid_t fg,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(snd_hda_codec_set_power_to_all);
|
||||
|
||||
/*
|
||||
* supported power states check
|
||||
*/
|
||||
static bool snd_hda_codec_get_supported_ps(struct hda_codec *codec, hda_nid_t fg,
|
||||
unsigned int power_state)
|
||||
{
|
||||
int sup = snd_hda_param_read(codec, fg, AC_PAR_POWER_STATE);
|
||||
|
||||
if (sup == -1)
|
||||
return false;
|
||||
if (sup & power_state)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* wait until the state is reached, returns the current state
|
||||
*/
|
||||
|
@ -3738,7 +3477,7 @@ 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)
|
||||
if (nid == codec->core.afg || nid == codec->core.mfg)
|
||||
return power_state;
|
||||
if (power_state == AC_PWRST_D3 &&
|
||||
get_wcaps_type(get_wcaps(codec, nid)) == AC_WID_PIN &&
|
||||
|
@ -3758,7 +3497,7 @@ EXPORT_SYMBOL_GPL(snd_hda_codec_eapd_power_filter);
|
|||
static unsigned int hda_set_power_state(struct hda_codec *codec,
|
||||
unsigned int power_state)
|
||||
{
|
||||
hda_nid_t fg = codec->afg ? codec->afg : codec->mfg;
|
||||
hda_nid_t fg = codec->core.afg ? codec->core.afg : codec->core.mfg;
|
||||
int count;
|
||||
unsigned int state;
|
||||
int flags = 0;
|
||||
|
@ -3766,7 +3505,7 @@ 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) {
|
||||
if (codec->depop_delay < 0)
|
||||
msleep(codec->epss ? 10 : 100);
|
||||
msleep(codec_has_epss(codec) ? 10 : 100);
|
||||
else if (codec->depop_delay > 0)
|
||||
msleep(codec->depop_delay);
|
||||
flags = HDA_RW_NO_RESPONSE_FALLBACK;
|
||||
|
@ -3800,14 +3539,13 @@ static unsigned int hda_set_power_state(struct hda_codec *codec,
|
|||
*/
|
||||
static void sync_power_up_states(struct hda_codec *codec)
|
||||
{
|
||||
hda_nid_t nid = codec->start_nid;
|
||||
int i;
|
||||
hda_nid_t nid;
|
||||
|
||||
/* don't care if no filter is used */
|
||||
if (!codec->power_filter)
|
||||
return;
|
||||
|
||||
for (i = 0; i < codec->num_nodes; i++, nid++) {
|
||||
for_each_hda_codec_node(nid, codec) {
|
||||
unsigned int wcaps = get_wcaps(codec, nid);
|
||||
unsigned int target;
|
||||
if (!(wcaps & AC_WCAP_POWER))
|
||||
|
@ -3858,14 +3596,14 @@ static unsigned int hda_call_codec_suspend(struct hda_codec *codec)
|
|||
{
|
||||
unsigned int state;
|
||||
|
||||
atomic_inc(&codec->in_pm);
|
||||
atomic_inc(&codec->core.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);
|
||||
update_power_acct(codec, true);
|
||||
atomic_dec(&codec->in_pm);
|
||||
atomic_dec(&codec->core.in_pm);
|
||||
return state;
|
||||
}
|
||||
|
||||
|
@ -3890,7 +3628,7 @@ static void hda_mark_cmd_cache_dirty(struct hda_codec *codec)
|
|||
*/
|
||||
static void hda_call_codec_resume(struct hda_codec *codec)
|
||||
{
|
||||
atomic_inc(&codec->in_pm);
|
||||
atomic_inc(&codec->core.in_pm);
|
||||
|
||||
hda_mark_cmd_cache_dirty(codec);
|
||||
|
||||
|
@ -3913,7 +3651,7 @@ 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);
|
||||
atomic_dec(&codec->core.in_pm);
|
||||
}
|
||||
|
||||
static int hda_codec_runtime_suspend(struct device *dev)
|
||||
|
@ -3926,8 +3664,9 @@ static int hda_codec_runtime_suspend(struct device *dev)
|
|||
list_for_each_entry(pcm, &codec->pcm_list_head, list)
|
||||
snd_pcm_suspend_all(pcm->pcm);
|
||||
state = hda_call_codec_suspend(codec);
|
||||
if (codec->d3_stop_clk && codec->epss && (state & AC_PWRST_CLK_STOP_OK))
|
||||
clear_bit(codec->core.addr, &codec->bus->core.codec_powered);
|
||||
if (codec_has_clkstop(codec) && codec_has_epss(codec) &&
|
||||
(state & AC_PWRST_CLK_STOP_OK))
|
||||
snd_hdac_codec_link_down(&codec->core);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -3935,7 +3674,7 @@ static int hda_codec_runtime_resume(struct device *dev)
|
|||
{
|
||||
struct hda_codec *codec = dev_to_hda_codec(dev);
|
||||
|
||||
set_bit(codec->core.addr, &codec->bus->core.codec_powered);
|
||||
snd_hdac_codec_link_up(&codec->core);
|
||||
hda_call_codec_resume(codec);
|
||||
pm_runtime_mark_last_busy(dev);
|
||||
return 0;
|
||||
|
@ -4129,11 +3868,11 @@ static unsigned int get_pcm_param(struct hda_codec *codec, hda_nid_t nid,
|
|||
int dir)
|
||||
{
|
||||
unsigned int val = 0;
|
||||
if (nid != codec->afg &&
|
||||
if (nid != codec->core.afg &&
|
||||
(get_wcaps(codec, nid) & AC_WCAP_FORMAT_OVRD))
|
||||
val = snd_hda_param_read(codec, nid, AC_PAR_PCM);
|
||||
if (!val || val == -1)
|
||||
val = snd_hda_param_read(codec, codec->afg, AC_PAR_PCM);
|
||||
val = snd_hda_param_read(codec, codec->core.afg, AC_PAR_PCM);
|
||||
if (!val || val == -1)
|
||||
return 0;
|
||||
return val;
|
||||
|
@ -4150,7 +3889,7 @@ static unsigned int get_stream_param(struct hda_codec *codec, hda_nid_t nid,
|
|||
{
|
||||
unsigned int streams = snd_hda_param_read(codec, nid, AC_PAR_STREAM);
|
||||
if (!streams || streams == -1)
|
||||
streams = snd_hda_param_read(codec, codec->afg, AC_PAR_STREAM);
|
||||
streams = snd_hda_param_read(codec, codec->core.afg, AC_PAR_STREAM);
|
||||
if (!streams || streams == -1)
|
||||
return 0;
|
||||
return streams;
|
||||
|
@ -4632,39 +4371,6 @@ int snd_hda_add_new_ctls(struct hda_codec *codec,
|
|||
EXPORT_SYMBOL_GPL(snd_hda_add_new_ctls);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
/**
|
||||
* 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 device *dev = hda_codec_dev(codec);
|
||||
|
||||
if (codec_in_pm(codec))
|
||||
return;
|
||||
pm_runtime_get_sync(dev);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_hda_power_up);
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
struct device *dev = hda_codec_dev(codec);
|
||||
|
||||
if (codec_in_pm(codec))
|
||||
return;
|
||||
pm_runtime_mark_last_busy(dev);
|
||||
pm_runtime_put_autosuspend(dev);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_hda_power_down);
|
||||
|
||||
static void codec_set_power_save(struct hda_codec *codec, int delay)
|
||||
{
|
||||
struct device *dev = hda_codec_dev(codec);
|
||||
|
|
|
@ -261,24 +261,10 @@ struct hda_codec {
|
|||
struct hda_bus *bus;
|
||||
struct snd_card *card;
|
||||
unsigned int addr; /* codec addr*/
|
||||
|
||||
hda_nid_t afg; /* AFG node id */
|
||||
hda_nid_t mfg; /* MFG node id */
|
||||
|
||||
/* ids */
|
||||
u8 afg_function_id;
|
||||
u8 mfg_function_id;
|
||||
u8 afg_unsol;
|
||||
u8 mfg_unsol;
|
||||
u32 vendor_id;
|
||||
u32 subsystem_id;
|
||||
u32 revision_id;
|
||||
u32 probe_id; /* overridden id for probing */
|
||||
|
||||
/* detected preset */
|
||||
const struct hda_codec_preset *preset;
|
||||
const char *vendor_name; /* codec vendor name */
|
||||
const char *chip_name; /* codec chip name */
|
||||
const char *modelname; /* model name for preset */
|
||||
|
||||
/* set by patch */
|
||||
|
@ -295,8 +281,6 @@ struct hda_codec {
|
|||
unsigned int beep_mode;
|
||||
|
||||
/* widget capabilities cache */
|
||||
unsigned int num_nodes;
|
||||
hda_nid_t start_nid;
|
||||
u32 *wcaps;
|
||||
|
||||
struct snd_array mixers; /* list of assigned mixer elements */
|
||||
|
@ -347,14 +331,11 @@ struct hda_codec {
|
|||
unsigned int inv_eapd:1; /* broken h/w: inverted EAPD control */
|
||||
unsigned int inv_jack_detect:1; /* broken h/w: inverted detection bit */
|
||||
unsigned int pcm_format_first:1; /* PCM format must be set first */
|
||||
unsigned int epss:1; /* supporting EPSS? */
|
||||
unsigned int cached_write:1; /* write only to caches */
|
||||
unsigned int dp_mst:1; /* support DP1.2 Multi-stream transport */
|
||||
unsigned int dump_coef:1; /* dump processing coefs in codec proc file */
|
||||
unsigned int power_save_node:1; /* advanced PM for each widget */
|
||||
#ifdef CONFIG_PM
|
||||
unsigned int d3_stop_clk:1; /* support D3 operation without BCLK */
|
||||
atomic_t in_pm; /* suspend/resume being performed */
|
||||
unsigned long power_on_acct;
|
||||
unsigned long power_off_acct;
|
||||
unsigned long power_jiffies;
|
||||
|
@ -395,11 +376,6 @@ struct hda_codec {
|
|||
#define list_for_each_codec(c, bus) \
|
||||
list_for_each_entry(c, &(bus)->core.codec_list, core.list)
|
||||
|
||||
/* direction */
|
||||
enum {
|
||||
HDA_INPUT, HDA_OUTPUT
|
||||
};
|
||||
|
||||
/* snd_hda_codec_read/write optional flags */
|
||||
#define HDA_RW_NO_RESPONSE_FALLBACK (1 << 0)
|
||||
|
||||
|
@ -422,8 +398,8 @@ int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int flags,
|
|||
unsigned int verb, unsigned int parm);
|
||||
#define snd_hda_param_read(codec, nid, param) \
|
||||
snd_hda_codec_read(codec, nid, 0, AC_VERB_PARAMETERS, param)
|
||||
int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid,
|
||||
hda_nid_t *start_id);
|
||||
#define snd_hda_get_sub_nodes(codec, nid, start_nid) \
|
||||
snd_hdac_get_sub_nodes(&(codec)->core, nid, start_nid)
|
||||
int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
|
||||
hda_nid_t *conn_list, int max_conns);
|
||||
static inline int
|
||||
|
@ -431,9 +407,12 @@ snd_hda_get_num_conns(struct hda_codec *codec, hda_nid_t nid)
|
|||
{
|
||||
return snd_hda_get_connections(codec, nid, NULL, 0);
|
||||
}
|
||||
int snd_hda_get_num_raw_conns(struct hda_codec *codec, hda_nid_t nid);
|
||||
int snd_hda_get_raw_connections(struct hda_codec *codec, hda_nid_t nid,
|
||||
hda_nid_t *conn_list, int max_conns);
|
||||
|
||||
#define snd_hda_get_raw_connections(codec, nid, list, max_conns) \
|
||||
snd_hdac_get_connections(&(codec)->core, nid, list, max_conns)
|
||||
#define snd_hda_get_num_raw_conns(codec, nid) \
|
||||
snd_hdac_get_connections(&(codec)->core, nid, NULL, 0);
|
||||
|
||||
int snd_hda_get_conn_list(struct hda_codec *codec, hda_nid_t nid,
|
||||
const hda_nid_t **listp);
|
||||
int snd_hda_override_conn_list(struct hda_codec *codec, hda_nid_t nid, int nums,
|
||||
|
@ -582,14 +561,12 @@ const char *snd_hda_get_jack_location(u32 cfg);
|
|||
/*
|
||||
* power saving
|
||||
*/
|
||||
#define snd_hda_power_up(codec) snd_hdac_power_up(&(codec)->core)
|
||||
#define snd_hda_power_down(codec) snd_hdac_power_down(&(codec)->core)
|
||||
#ifdef CONFIG_PM
|
||||
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_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
|
||||
|
||||
|
|
|
@ -654,7 +654,7 @@ static bool is_active_nid(struct hda_codec *codec, hda_nid_t nid,
|
|||
int type = get_wcaps_type(get_wcaps(codec, nid));
|
||||
int i, n;
|
||||
|
||||
if (nid == codec->afg)
|
||||
if (nid == codec->core.afg)
|
||||
return true;
|
||||
|
||||
for (n = 0; n < spec->paths.used; n++) {
|
||||
|
@ -832,7 +832,7 @@ static hda_nid_t path_power_update(struct hda_codec *codec,
|
|||
|
||||
for (i = 0; i < path->depth; i++) {
|
||||
nid = path->path[i];
|
||||
if (nid == codec->afg)
|
||||
if (nid == codec->core.afg)
|
||||
continue;
|
||||
if (!allow_powerdown || is_active_nid_for_any(codec, nid))
|
||||
state = AC_PWRST_D0;
|
||||
|
@ -1897,12 +1897,11 @@ static void debug_show_configs(struct hda_codec *codec,
|
|||
static void fill_all_dac_nids(struct hda_codec *codec)
|
||||
{
|
||||
struct hda_gen_spec *spec = codec->spec;
|
||||
int i;
|
||||
hda_nid_t nid = codec->start_nid;
|
||||
hda_nid_t nid;
|
||||
|
||||
spec->num_all_dacs = 0;
|
||||
memset(spec->all_dacs, 0, sizeof(spec->all_dacs));
|
||||
for (i = 0; i < codec->num_nodes; i++, nid++) {
|
||||
for_each_hda_codec_node(nid, codec) {
|
||||
if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_AUD_OUT)
|
||||
continue;
|
||||
if (spec->num_all_dacs >= ARRAY_SIZE(spec->all_dacs)) {
|
||||
|
@ -3067,10 +3066,9 @@ static int fill_adc_nids(struct hda_codec *codec)
|
|||
hda_nid_t nid;
|
||||
hda_nid_t *adc_nids = spec->adc_nids;
|
||||
int max_nums = ARRAY_SIZE(spec->adc_nids);
|
||||
int i, nums = 0;
|
||||
int nums = 0;
|
||||
|
||||
nid = codec->start_nid;
|
||||
for (i = 0; i < codec->num_nodes; i++, nid++) {
|
||||
for_each_hda_codec_node(nid, codec) {
|
||||
unsigned int caps = get_wcaps(codec, nid);
|
||||
int type = get_wcaps_type(caps);
|
||||
|
||||
|
@ -3864,8 +3862,7 @@ static void parse_digital(struct hda_codec *codec)
|
|||
|
||||
if (spec->autocfg.dig_in_pin) {
|
||||
pin = spec->autocfg.dig_in_pin;
|
||||
dig_nid = codec->start_nid;
|
||||
for (i = 0; i < codec->num_nodes; i++, dig_nid++) {
|
||||
for_each_hda_codec_node(dig_nid, codec) {
|
||||
unsigned int wcaps = get_wcaps(codec, dig_nid);
|
||||
if (get_wcaps_type(wcaps) != AC_WID_AUD_IN)
|
||||
continue;
|
||||
|
@ -4706,7 +4703,7 @@ unsigned int snd_hda_gen_path_power_filter(struct hda_codec *codec,
|
|||
hda_nid_t nid,
|
||||
unsigned int power_state)
|
||||
{
|
||||
if (power_state != AC_PWRST_D0 || nid == codec->afg)
|
||||
if (power_state != AC_PWRST_D0 || nid == codec->core.afg)
|
||||
return power_state;
|
||||
if (get_wcaps_type(get_wcaps(codec, nid)) >= AC_WID_POWER)
|
||||
return power_state;
|
||||
|
@ -5478,7 +5475,7 @@ int snd_hda_gen_build_pcms(struct hda_codec *codec)
|
|||
|
||||
fill_pcm_stream_name(spec->stream_name_analog,
|
||||
sizeof(spec->stream_name_analog),
|
||||
" Analog", codec->chip_name);
|
||||
" Analog", codec->core.chip_name);
|
||||
info = snd_hda_codec_pcm_new(codec, "%s", spec->stream_name_analog);
|
||||
if (!info)
|
||||
return -ENOMEM;
|
||||
|
@ -5509,7 +5506,7 @@ int snd_hda_gen_build_pcms(struct hda_codec *codec)
|
|||
if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
|
||||
fill_pcm_stream_name(spec->stream_name_digital,
|
||||
sizeof(spec->stream_name_digital),
|
||||
" Digital", codec->chip_name);
|
||||
" Digital", codec->core.chip_name);
|
||||
info = snd_hda_codec_pcm_new(codec, "%s",
|
||||
spec->stream_name_digital);
|
||||
if (!info)
|
||||
|
@ -5544,7 +5541,7 @@ int snd_hda_gen_build_pcms(struct hda_codec *codec)
|
|||
if (spec->alt_dac_nid || have_multi_adcs) {
|
||||
fill_pcm_stream_name(spec->stream_name_alt_analog,
|
||||
sizeof(spec->stream_name_alt_analog),
|
||||
" Alt Analog", codec->chip_name);
|
||||
" Alt Analog", codec->core.chip_name);
|
||||
info = snd_hda_codec_pcm_new(codec, "%s",
|
||||
spec->stream_name_alt_analog);
|
||||
if (!info)
|
||||
|
|
|
@ -515,15 +515,18 @@ int snd_hda_codec_get_pin_target(struct hda_codec *codec, hda_nid_t nid);
|
|||
int snd_hda_codec_set_pin_target(struct hda_codec *codec, hda_nid_t nid,
|
||||
unsigned int val);
|
||||
|
||||
#define for_each_hda_codec_node(nid, codec) \
|
||||
for ((nid) = (codec)->core.start_nid; (nid) < (codec)->core.end_nid; (nid)++)
|
||||
|
||||
/*
|
||||
* get widget capabilities
|
||||
*/
|
||||
static inline u32 get_wcaps(struct hda_codec *codec, hda_nid_t nid)
|
||||
{
|
||||
if (nid < codec->start_nid ||
|
||||
nid >= codec->start_nid + codec->num_nodes)
|
||||
if (nid < codec->core.start_nid ||
|
||||
nid >= codec->core.start_nid + codec->core.num_nodes)
|
||||
return 0;
|
||||
return codec->wcaps[nid - codec->start_nid];
|
||||
return codec->wcaps[nid - codec->core.start_nid];
|
||||
}
|
||||
|
||||
/* get the widget type from widget capability bits */
|
||||
|
@ -547,9 +550,9 @@ static inline unsigned int get_wcaps_channels(u32 wcaps)
|
|||
static inline void snd_hda_override_wcaps(struct hda_codec *codec,
|
||||
hda_nid_t nid, u32 val)
|
||||
{
|
||||
if (nid >= codec->start_nid &&
|
||||
nid < codec->start_nid + codec->num_nodes)
|
||||
codec->wcaps[nid - codec->start_nid] = val;
|
||||
if (nid >= codec->core.start_nid &&
|
||||
nid < codec->core.start_nid + codec->core.num_nodes)
|
||||
codec->wcaps[nid - codec->core.start_nid] = val;
|
||||
}
|
||||
|
||||
u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction);
|
||||
|
|
|
@ -289,7 +289,7 @@ static void print_pin_caps(struct snd_info_buffer *buffer,
|
|||
snd_iprintf(buffer, " Balanced");
|
||||
if (caps & AC_PINCAP_HDMI) {
|
||||
/* Realtek uses this bit as a different meaning */
|
||||
if ((codec->vendor_id >> 16) == 0x10ec)
|
||||
if ((codec->core.vendor_id >> 16) == 0x10ec)
|
||||
snd_iprintf(buffer, " R/L");
|
||||
else {
|
||||
if (caps & AC_PINCAP_HBR)
|
||||
|
@ -597,7 +597,7 @@ static void print_gpio(struct snd_info_buffer *buffer,
|
|||
struct hda_codec *codec, hda_nid_t nid)
|
||||
{
|
||||
unsigned int gpio =
|
||||
snd_hda_param_read(codec, codec->afg, AC_PAR_GPIO_CAP);
|
||||
snd_hda_param_read(codec, codec->core.afg, AC_PAR_GPIO_CAP);
|
||||
unsigned int enable, direction, wake, unsol, sticky, data;
|
||||
int i, max;
|
||||
snd_iprintf(buffer, "GPIO: io=%d, o=%d, i=%d, "
|
||||
|
@ -667,13 +667,9 @@ static void print_device_list(struct snd_info_buffer *buffer,
|
|||
}
|
||||
}
|
||||
|
||||
static void print_codec_info(struct snd_info_entry *entry,
|
||||
struct snd_info_buffer *buffer)
|
||||
static void print_codec_core_info(struct hdac_device *codec,
|
||||
struct snd_info_buffer *buffer)
|
||||
{
|
||||
struct hda_codec *codec = entry->private_data;
|
||||
hda_nid_t nid;
|
||||
int i, nodes;
|
||||
|
||||
snd_iprintf(buffer, "Codec: ");
|
||||
if (codec->vendor_name && codec->chip_name)
|
||||
snd_iprintf(buffer, "%s %s\n",
|
||||
|
@ -695,29 +691,39 @@ static void print_codec_info(struct snd_info_entry *entry,
|
|||
snd_iprintf(buffer, "Modem Function Group: 0x%x\n", codec->mfg);
|
||||
else
|
||||
snd_iprintf(buffer, "No Modem Function Group found\n");
|
||||
}
|
||||
|
||||
if (! codec->afg)
|
||||
static void print_codec_info(struct snd_info_entry *entry,
|
||||
struct snd_info_buffer *buffer)
|
||||
{
|
||||
struct hda_codec *codec = entry->private_data;
|
||||
hda_nid_t nid, fg;
|
||||
int i, nodes;
|
||||
|
||||
print_codec_core_info(&codec->core, buffer);
|
||||
fg = codec->core.afg;
|
||||
if (!fg)
|
||||
return;
|
||||
snd_hda_power_up(codec);
|
||||
snd_iprintf(buffer, "Default PCM:\n");
|
||||
print_pcm_caps(buffer, codec, codec->afg);
|
||||
print_pcm_caps(buffer, codec, fg);
|
||||
snd_iprintf(buffer, "Default Amp-In caps: ");
|
||||
print_amp_caps(buffer, codec, codec->afg, HDA_INPUT);
|
||||
print_amp_caps(buffer, codec, fg, HDA_INPUT);
|
||||
snd_iprintf(buffer, "Default Amp-Out caps: ");
|
||||
print_amp_caps(buffer, codec, codec->afg, HDA_OUTPUT);
|
||||
snd_iprintf(buffer, "State of AFG node 0x%02x:\n", codec->afg);
|
||||
print_power_state(buffer, codec, codec->afg);
|
||||
print_amp_caps(buffer, codec, fg, HDA_OUTPUT);
|
||||
snd_iprintf(buffer, "State of AFG node 0x%02x:\n", fg);
|
||||
print_power_state(buffer, codec, fg);
|
||||
|
||||
nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid);
|
||||
nodes = snd_hda_get_sub_nodes(codec, fg, &nid);
|
||||
if (! nid || nodes < 0) {
|
||||
snd_iprintf(buffer, "Invalid AFG subtree\n");
|
||||
snd_hda_power_down(codec);
|
||||
return;
|
||||
}
|
||||
|
||||
print_gpio(buffer, codec, codec->afg);
|
||||
print_gpio(buffer, codec, fg);
|
||||
if (codec->proc_widget_hook)
|
||||
codec->proc_widget_hook(buffer, codec, codec->afg);
|
||||
codec->proc_widget_hook(buffer, codec, fg);
|
||||
|
||||
for (i = 0; i < nodes; i++, nid++) {
|
||||
unsigned int wid_caps =
|
||||
|
@ -860,7 +866,7 @@ int snd_hda_codec_proc_new(struct hda_codec *codec)
|
|||
struct snd_info_entry *entry;
|
||||
int err;
|
||||
|
||||
snprintf(name, sizeof(name), "codec#%d", codec->addr);
|
||||
snprintf(name, sizeof(name), "codec#%d", codec->core.addr);
|
||||
err = snd_card_proc_new(codec->card, name, &entry);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
|
|
@ -48,33 +48,33 @@ static DEVICE_ATTR_RO(power_on_acct);
|
|||
static DEVICE_ATTR_RO(power_off_acct);
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
#define CODEC_INFO_SHOW(type) \
|
||||
#define CODEC_INFO_SHOW(type, field) \
|
||||
static ssize_t type##_show(struct device *dev, \
|
||||
struct device_attribute *attr, \
|
||||
char *buf) \
|
||||
{ \
|
||||
struct hda_codec *codec = dev_get_drvdata(dev); \
|
||||
return sprintf(buf, "0x%x\n", codec->type); \
|
||||
return sprintf(buf, "0x%x\n", codec->field); \
|
||||
}
|
||||
|
||||
#define CODEC_INFO_STR_SHOW(type) \
|
||||
#define CODEC_INFO_STR_SHOW(type, field) \
|
||||
static ssize_t type##_show(struct device *dev, \
|
||||
struct device_attribute *attr, \
|
||||
char *buf) \
|
||||
{ \
|
||||
struct hda_codec *codec = dev_get_drvdata(dev); \
|
||||
return sprintf(buf, "%s\n", \
|
||||
codec->type ? codec->type : ""); \
|
||||
codec->field ? codec->field : ""); \
|
||||
}
|
||||
|
||||
CODEC_INFO_SHOW(vendor_id);
|
||||
CODEC_INFO_SHOW(subsystem_id);
|
||||
CODEC_INFO_SHOW(revision_id);
|
||||
CODEC_INFO_SHOW(afg);
|
||||
CODEC_INFO_SHOW(mfg);
|
||||
CODEC_INFO_STR_SHOW(vendor_name);
|
||||
CODEC_INFO_STR_SHOW(chip_name);
|
||||
CODEC_INFO_STR_SHOW(modelname);
|
||||
CODEC_INFO_SHOW(vendor_id, core.vendor_id);
|
||||
CODEC_INFO_SHOW(subsystem_id, core.subsystem_id);
|
||||
CODEC_INFO_SHOW(revision_id, core.revision_id);
|
||||
CODEC_INFO_SHOW(afg, core.afg);
|
||||
CODEC_INFO_SHOW(mfg, core.mfg);
|
||||
CODEC_INFO_STR_SHOW(vendor_name, core.vendor_name);
|
||||
CODEC_INFO_STR_SHOW(chip_name, core.chip_name);
|
||||
CODEC_INFO_STR_SHOW(modelname, modelname);
|
||||
|
||||
static ssize_t pin_configs_show(struct hda_codec *codec,
|
||||
struct snd_array *list,
|
||||
|
@ -170,7 +170,7 @@ static char *kstrndup_noeol(const char *src, size_t len)
|
|||
return s;
|
||||
}
|
||||
|
||||
#define CODEC_INFO_STORE(type) \
|
||||
#define CODEC_INFO_STORE(type, field) \
|
||||
static ssize_t type##_store(struct device *dev, \
|
||||
struct device_attribute *attr, \
|
||||
const char *buf, size_t count) \
|
||||
|
@ -180,11 +180,11 @@ static ssize_t type##_store(struct device *dev, \
|
|||
int err = kstrtoul(buf, 0, &val); \
|
||||
if (err < 0) \
|
||||
return err; \
|
||||
codec->type = val; \
|
||||
codec->field = val; \
|
||||
return count; \
|
||||
}
|
||||
|
||||
#define CODEC_INFO_STR_STORE(type) \
|
||||
#define CODEC_INFO_STR_STORE(type, field) \
|
||||
static ssize_t type##_store(struct device *dev, \
|
||||
struct device_attribute *attr, \
|
||||
const char *buf, size_t count) \
|
||||
|
@ -193,17 +193,17 @@ static ssize_t type##_store(struct device *dev, \
|
|||
char *s = kstrndup_noeol(buf, 64); \
|
||||
if (!s) \
|
||||
return -ENOMEM; \
|
||||
kfree(codec->type); \
|
||||
codec->type = s; \
|
||||
kfree(codec->field); \
|
||||
codec->field = s; \
|
||||
return count; \
|
||||
}
|
||||
|
||||
CODEC_INFO_STORE(vendor_id);
|
||||
CODEC_INFO_STORE(subsystem_id);
|
||||
CODEC_INFO_STORE(revision_id);
|
||||
CODEC_INFO_STR_STORE(vendor_name);
|
||||
CODEC_INFO_STR_STORE(chip_name);
|
||||
CODEC_INFO_STR_STORE(modelname);
|
||||
CODEC_INFO_STORE(vendor_id, core.vendor_id);
|
||||
CODEC_INFO_STORE(subsystem_id, core.subsystem_id);
|
||||
CODEC_INFO_STORE(revision_id, core.revision_id);
|
||||
CODEC_INFO_STR_STORE(vendor_name, core.vendor_name);
|
||||
CODEC_INFO_STR_STORE(chip_name, core.chip_name);
|
||||
CODEC_INFO_STR_STORE(modelname, modelname);
|
||||
|
||||
#define CODEC_ACTION_STORE(type) \
|
||||
static ssize_t type##_store(struct device *dev, \
|
||||
|
@ -553,9 +553,9 @@ static void parse_codec_mode(char *buf, struct hda_bus *bus,
|
|||
*codecp = NULL;
|
||||
if (sscanf(buf, "%i %i %i", &vendorid, &subid, &caddr) == 3) {
|
||||
list_for_each_codec(codec, bus) {
|
||||
if ((vendorid <= 0 || codec->vendor_id == vendorid) &&
|
||||
(subid <= 0 || codec->subsystem_id == subid) &&
|
||||
codec->addr == caddr) {
|
||||
if ((vendorid <= 0 || codec->core.vendor_id == vendorid) &&
|
||||
(subid <= 0 || codec->core.subsystem_id == subid) &&
|
||||
codec->core.addr == caddr) {
|
||||
*codecp = codec;
|
||||
break;
|
||||
}
|
||||
|
@ -595,8 +595,8 @@ static void parse_model_mode(char *buf, struct hda_bus *bus,
|
|||
static void parse_chip_name_mode(char *buf, struct hda_bus *bus,
|
||||
struct hda_codec **codecp)
|
||||
{
|
||||
kfree((*codecp)->chip_name);
|
||||
(*codecp)->chip_name = kstrdup(buf, GFP_KERNEL);
|
||||
kfree((*codecp)->core.chip_name);
|
||||
(*codecp)->core.chip_name = kstrdup(buf, GFP_KERNEL);
|
||||
}
|
||||
|
||||
#define DEFINE_PARSE_ID_MODE(name) \
|
||||
|
@ -605,7 +605,7 @@ static void parse_##name##_mode(char *buf, struct hda_bus *bus, \
|
|||
{ \
|
||||
unsigned long val; \
|
||||
if (!kstrtoul(buf, 0, &val)) \
|
||||
(*codecp)->name = val; \
|
||||
(*codecp)->core.name = val; \
|
||||
}
|
||||
|
||||
DEFINE_PARSE_ID_MODE(vendor_id);
|
||||
|
|
39
sound/pci/hda/local.h
Normal file
39
sound/pci/hda/local.h
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
*/
|
||||
|
||||
#ifndef __HDAC_LOCAL_H
|
||||
#define __HDAC_LOCAL_H
|
||||
|
||||
int hdac_read_parm(struct hdac_device *codec, hda_nid_t nid, int parm);
|
||||
|
||||
#define get_wcaps(codec, nid) \
|
||||
hdac_read_parm(codec, nid, AC_PAR_AUDIO_WIDGET_CAP)
|
||||
/* get the widget type from widget capability bits */
|
||||
static inline int get_wcaps_type(unsigned int wcaps)
|
||||
{
|
||||
if (!wcaps)
|
||||
return -1; /* invalid type */
|
||||
return (wcaps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
|
||||
}
|
||||
|
||||
#define get_pin_caps(codec, nid) \
|
||||
hdac_read_parm(codec, nid, AC_PAR_PIN_CAP)
|
||||
|
||||
static inline
|
||||
unsigned int get_pin_cfg(struct hdac_device *codec, hda_nid_t nid)
|
||||
{
|
||||
unsigned int val;
|
||||
|
||||
if (snd_hdac_read(codec, nid, AC_VERB_GET_CONFIG_DEFAULT, 0, &val))
|
||||
return -1;
|
||||
return val;
|
||||
}
|
||||
|
||||
#define get_amp_caps(codec, nid, dir) \
|
||||
hdac_read_parm(codec, nid, (dir) == HDA_OUTPUT ? \
|
||||
AC_PAR_AMP_OUT_CAP : AC_PAR_AMP_IN_CAP)
|
||||
|
||||
#define get_power_caps(codec, nid) \
|
||||
hdac_read_parm(codec, nid, AC_PAR_POWER_STATE)
|
||||
|
||||
#endif /* __HDAC_LOCAL_H */
|
|
@ -99,7 +99,7 @@ static void ad198x_power_eapd_write(struct hda_codec *codec, hda_nid_t front,
|
|||
static void ad198x_power_eapd(struct hda_codec *codec)
|
||||
{
|
||||
/* We currently only handle front, HP */
|
||||
switch (codec->vendor_id) {
|
||||
switch (codec->core.vendor_id) {
|
||||
case 0x11d41882:
|
||||
case 0x11d4882a:
|
||||
case 0x11d41884:
|
||||
|
|
|
@ -4243,13 +4243,9 @@ static void ca0132_refresh_widget_caps(struct hda_codec *codec)
|
|||
{
|
||||
struct ca0132_spec *spec = codec->spec;
|
||||
int i;
|
||||
hda_nid_t nid;
|
||||
|
||||
codec_dbg(codec, "ca0132_refresh_widget_caps.\n");
|
||||
nid = codec->start_nid;
|
||||
for (i = 0; i < codec->num_nodes; i++, nid++)
|
||||
codec->wcaps[i] = snd_hda_param_read(codec, nid,
|
||||
AC_PAR_AUDIO_WIDGET_CAP);
|
||||
snd_hda_codec_update_widgets(codec);
|
||||
|
||||
for (i = 0; i < spec->multiout.num_dacs; i++)
|
||||
refresh_amp_caps(codec, spec->dacs[i], HDA_OUTPUT);
|
||||
|
|
|
@ -103,10 +103,9 @@ static int add_beep_ctls(struct hda_codec *codec)
|
|||
static void cx_auto_parse_beep(struct hda_codec *codec)
|
||||
{
|
||||
struct conexant_spec *spec = codec->spec;
|
||||
hda_nid_t nid, end_nid;
|
||||
hda_nid_t nid;
|
||||
|
||||
end_nid = codec->start_nid + codec->num_nodes;
|
||||
for (nid = codec->start_nid; nid < end_nid; nid++)
|
||||
for_each_hda_codec_node(nid, codec)
|
||||
if (get_wcaps_type(get_wcaps(codec, nid)) == AC_WID_BEEP) {
|
||||
set_beep_amp(spec, nid, 0, HDA_OUTPUT);
|
||||
break;
|
||||
|
@ -120,10 +119,9 @@ static void cx_auto_parse_beep(struct hda_codec *codec)
|
|||
static void cx_auto_parse_eapd(struct hda_codec *codec)
|
||||
{
|
||||
struct conexant_spec *spec = codec->spec;
|
||||
hda_nid_t nid, end_nid;
|
||||
hda_nid_t nid;
|
||||
|
||||
end_nid = codec->start_nid + codec->num_nodes;
|
||||
for (nid = codec->start_nid; nid < end_nid; nid++) {
|
||||
for_each_hda_codec_node(nid, codec) {
|
||||
if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_PIN)
|
||||
continue;
|
||||
if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD))
|
||||
|
@ -848,7 +846,7 @@ static int patch_conexant_auto(struct hda_codec *codec)
|
|||
struct conexant_spec *spec;
|
||||
int err;
|
||||
|
||||
codec_info(codec, "%s: BIOS auto-probing.\n", codec->chip_name);
|
||||
codec_info(codec, "%s: BIOS auto-probing.\n", codec->core.chip_name);
|
||||
|
||||
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
|
||||
if (!spec)
|
||||
|
@ -862,7 +860,7 @@ static int patch_conexant_auto(struct hda_codec *codec)
|
|||
if (spec->dynamic_eapd)
|
||||
spec->gen.vmaster_mute.hook = cx_auto_vmaster_hook;
|
||||
|
||||
switch (codec->vendor_id) {
|
||||
switch (codec->core.vendor_id) {
|
||||
case 0x14f15045:
|
||||
codec->single_adc_amp = 1;
|
||||
spec->gen.mixer_nid = 0x17;
|
||||
|
@ -896,7 +894,7 @@ static int patch_conexant_auto(struct hda_codec *codec)
|
|||
* others may use EAPD really as an amp switch, so it might be
|
||||
* not good to expose it blindly.
|
||||
*/
|
||||
switch (codec->subsystem_id >> 16) {
|
||||
switch (codec->core.subsystem_id >> 16) {
|
||||
case 0x103c:
|
||||
spec->gen.vmaster_mute_enum = 1;
|
||||
break;
|
||||
|
|
|
@ -45,14 +45,14 @@ static bool static_hdmi_pcm;
|
|||
module_param(static_hdmi_pcm, bool, 0644);
|
||||
MODULE_PARM_DESC(static_hdmi_pcm, "Don't restrict PCM parameters per ELD info");
|
||||
|
||||
#define is_haswell(codec) ((codec)->vendor_id == 0x80862807)
|
||||
#define is_broadwell(codec) ((codec)->vendor_id == 0x80862808)
|
||||
#define is_skylake(codec) ((codec)->vendor_id == 0x80862809)
|
||||
#define is_haswell(codec) ((codec)->core.vendor_id == 0x80862807)
|
||||
#define is_broadwell(codec) ((codec)->core.vendor_id == 0x80862808)
|
||||
#define is_skylake(codec) ((codec)->core.vendor_id == 0x80862809)
|
||||
#define is_haswell_plus(codec) (is_haswell(codec) || is_broadwell(codec) \
|
||||
|| is_skylake(codec))
|
||||
|
||||
#define is_valleyview(codec) ((codec)->vendor_id == 0x80862882)
|
||||
#define is_cherryview(codec) ((codec)->vendor_id == 0x80862883)
|
||||
#define is_valleyview(codec) ((codec)->core.vendor_id == 0x80862882)
|
||||
#define is_cherryview(codec) ((codec)->core.vendor_id == 0x80862883)
|
||||
#define is_valleyview_plus(codec) (is_valleyview(codec) || is_cherryview(codec))
|
||||
|
||||
struct hdmi_spec_per_cvt {
|
||||
|
@ -1391,13 +1391,12 @@ static void intel_not_share_assigned_cvt(struct hda_codec *codec,
|
|||
hda_nid_t pin_nid, int mux_idx)
|
||||
{
|
||||
struct hdmi_spec *spec = codec->spec;
|
||||
hda_nid_t nid, end_nid;
|
||||
hda_nid_t nid;
|
||||
int cvt_idx, curr;
|
||||
struct hdmi_spec_per_cvt *per_cvt;
|
||||
|
||||
/* configure all pins, including "no physical connection" ones */
|
||||
end_nid = codec->start_nid + codec->num_nodes;
|
||||
for (nid = codec->start_nid; nid < end_nid; nid++) {
|
||||
for_each_hda_codec_node(nid, codec) {
|
||||
unsigned int wid_caps = get_wcaps(codec, nid);
|
||||
unsigned int wid_type = get_wcaps_type(wid_caps);
|
||||
|
||||
|
@ -1728,7 +1727,7 @@ static int hdmi_parse_codec(struct hda_codec *codec)
|
|||
hda_nid_t nid;
|
||||
int i, nodes;
|
||||
|
||||
nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid);
|
||||
nodes = snd_hda_get_sub_nodes(codec, codec->core.afg, &nid);
|
||||
if (!nid || nodes < 0) {
|
||||
codec_warn(codec, "HDMI: failed to get afg sub nodes\n");
|
||||
return -EINVAL;
|
||||
|
@ -2928,7 +2927,8 @@ static int patch_nvhdmi(struct hda_codec *codec)
|
|||
*/
|
||||
|
||||
#define is_amdhdmi_rev3_or_later(codec) \
|
||||
((codec)->vendor_id == 0x1002aa01 && ((codec)->revision_id & 0xff00) >= 0x0300)
|
||||
((codec)->core.vendor_id == 0x1002aa01 && \
|
||||
((codec)->core.revision_id & 0xff00) >= 0x0300)
|
||||
#define has_amd_full_remap_support(codec) is_amdhdmi_rev3_or_later(codec)
|
||||
|
||||
/* ATI/AMD specific HDA pin verbs, see the AMD HDA Verbs specification */
|
||||
|
|
|
@ -299,7 +299,7 @@ static void alc_fill_eapd_coef(struct hda_codec *codec)
|
|||
|
||||
coef = alc_get_coef0(codec);
|
||||
|
||||
switch (codec->vendor_id) {
|
||||
switch (codec->core.vendor_id) {
|
||||
case 0x10ec0262:
|
||||
alc_update_coef_idx(codec, 0x7, 0, 1<<5);
|
||||
break;
|
||||
|
@ -432,7 +432,7 @@ static void alc_auto_init_amp(struct hda_codec *codec, int type)
|
|||
snd_hda_sequence_write(codec, alc_gpio3_init_verbs);
|
||||
break;
|
||||
case ALC_INIT_DEFAULT:
|
||||
switch (codec->vendor_id) {
|
||||
switch (codec->core.vendor_id) {
|
||||
case 0x10ec0260:
|
||||
alc_update_coefex_idx(codec, 0x1a, 7, 0, 0x2010);
|
||||
break;
|
||||
|
@ -498,18 +498,18 @@ static int alc_auto_parse_customize_define(struct hda_codec *codec)
|
|||
|
||||
if (!codec->bus->pci)
|
||||
return -1;
|
||||
ass = codec->subsystem_id & 0xffff;
|
||||
ass = codec->core.subsystem_id & 0xffff;
|
||||
if (ass != codec->bus->pci->subsystem_device && (ass & 1))
|
||||
goto do_sku;
|
||||
|
||||
nid = 0x1d;
|
||||
if (codec->vendor_id == 0x10ec0260)
|
||||
if (codec->core.vendor_id == 0x10ec0260)
|
||||
nid = 0x17;
|
||||
ass = snd_hda_codec_get_pincfg(codec, nid);
|
||||
|
||||
if (!(ass & 1)) {
|
||||
codec_info(codec, "%s: SKU not ready 0x%08x\n",
|
||||
codec->chip_name, ass);
|
||||
codec->core.chip_name, ass);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -585,7 +585,7 @@ static int alc_subsystem_id(struct hda_codec *codec, const hda_nid_t *ports)
|
|||
goto do_sku;
|
||||
}
|
||||
|
||||
ass = codec->subsystem_id & 0xffff;
|
||||
ass = codec->core.subsystem_id & 0xffff;
|
||||
if (codec->bus->pci &&
|
||||
ass != codec->bus->pci->subsystem_device && (ass & 1))
|
||||
goto do_sku;
|
||||
|
@ -600,7 +600,7 @@ static int alc_subsystem_id(struct hda_codec *codec, const hda_nid_t *ports)
|
|||
* 0 : override
|
||||
*/
|
||||
nid = 0x1d;
|
||||
if (codec->vendor_id == 0x10ec0260)
|
||||
if (codec->core.vendor_id == 0x10ec0260)
|
||||
nid = 0x17;
|
||||
ass = snd_hda_codec_get_pincfg(codec, nid);
|
||||
codec_dbg(codec,
|
||||
|
@ -621,7 +621,7 @@ static int alc_subsystem_id(struct hda_codec *codec, const hda_nid_t *ports)
|
|||
return 0;
|
||||
do_sku:
|
||||
codec_dbg(codec, "realtek: Enabling init ASM_ID=0x%04x CODEC_ID=%08x\n",
|
||||
ass & 0xffff, codec->vendor_id);
|
||||
ass & 0xffff, codec->core.vendor_id);
|
||||
/*
|
||||
* 0 : override
|
||||
* 1 : Swap Jack
|
||||
|
@ -826,9 +826,9 @@ static const struct hda_codec_ops alc_patch_ops = {
|
|||
/* replace the codec chip_name with the given string */
|
||||
static int alc_codec_rename(struct hda_codec *codec, const char *name)
|
||||
{
|
||||
kfree(codec->chip_name);
|
||||
codec->chip_name = kstrdup(name, GFP_KERNEL);
|
||||
if (!codec->chip_name) {
|
||||
kfree(codec->core.chip_name);
|
||||
codec->core.chip_name = kstrdup(name, GFP_KERNEL);
|
||||
if (!codec->core.chip_name) {
|
||||
alc_free(codec);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
@ -904,7 +904,7 @@ static int alc_codec_rename_from_preset(struct hda_codec *codec)
|
|||
const struct alc_codec_rename_pci_table *q;
|
||||
|
||||
for (p = rename_tbl; p->vendor_id; p++) {
|
||||
if (p->vendor_id != codec->vendor_id)
|
||||
if (p->vendor_id != codec->core.vendor_id)
|
||||
continue;
|
||||
if ((alc_get_coef0(codec) & p->coef_mask) == p->coef_bits)
|
||||
return alc_codec_rename(codec, p->name);
|
||||
|
@ -913,7 +913,7 @@ static int alc_codec_rename_from_preset(struct hda_codec *codec)
|
|||
if (!codec->bus->pci)
|
||||
return 0;
|
||||
for (q = rename_pci_tbl; q->codec_vendor_id; q++) {
|
||||
if (q->codec_vendor_id != codec->vendor_id)
|
||||
if (q->codec_vendor_id != codec->core.vendor_id)
|
||||
continue;
|
||||
if (q->pci_subvendor != codec->bus->pci->subsystem_vendor)
|
||||
continue;
|
||||
|
@ -1785,7 +1785,7 @@ static void alc882_gpio_mute(struct hda_codec *codec, int pin, int muted)
|
|||
{
|
||||
unsigned int gpiostate, gpiomask, gpiodir;
|
||||
|
||||
gpiostate = snd_hda_codec_read(codec, codec->afg, 0,
|
||||
gpiostate = snd_hda_codec_read(codec, codec->core.afg, 0,
|
||||
AC_VERB_GET_GPIO_DATA, 0);
|
||||
|
||||
if (!muted)
|
||||
|
@ -1793,23 +1793,23 @@ static void alc882_gpio_mute(struct hda_codec *codec, int pin, int muted)
|
|||
else
|
||||
gpiostate &= ~(1 << pin);
|
||||
|
||||
gpiomask = snd_hda_codec_read(codec, codec->afg, 0,
|
||||
gpiomask = snd_hda_codec_read(codec, codec->core.afg, 0,
|
||||
AC_VERB_GET_GPIO_MASK, 0);
|
||||
gpiomask |= (1 << pin);
|
||||
|
||||
gpiodir = snd_hda_codec_read(codec, codec->afg, 0,
|
||||
gpiodir = snd_hda_codec_read(codec, codec->core.afg, 0,
|
||||
AC_VERB_GET_GPIO_DIRECTION, 0);
|
||||
gpiodir |= (1 << pin);
|
||||
|
||||
|
||||
snd_hda_codec_write(codec, codec->afg, 0,
|
||||
snd_hda_codec_write(codec, codec->core.afg, 0,
|
||||
AC_VERB_SET_GPIO_MASK, gpiomask);
|
||||
snd_hda_codec_write(codec, codec->afg, 0,
|
||||
snd_hda_codec_write(codec, codec->core.afg, 0,
|
||||
AC_VERB_SET_GPIO_DIRECTION, gpiodir);
|
||||
|
||||
msleep(1);
|
||||
|
||||
snd_hda_codec_write(codec, codec->afg, 0,
|
||||
snd_hda_codec_write(codec, codec->core.afg, 0,
|
||||
AC_VERB_SET_GPIO_DATA, gpiostate);
|
||||
}
|
||||
|
||||
|
@ -2269,7 +2269,7 @@ static int patch_alc882(struct hda_codec *codec)
|
|||
|
||||
spec = codec->spec;
|
||||
|
||||
switch (codec->vendor_id) {
|
||||
switch (codec->core.vendor_id) {
|
||||
case 0x10ec0882:
|
||||
case 0x10ec0885:
|
||||
case 0x10ec0900:
|
||||
|
@ -3067,7 +3067,7 @@ static int alc269_resume(struct hda_codec *codec)
|
|||
* in the driver.
|
||||
*/
|
||||
if (spec->gpio_led)
|
||||
snd_hda_codec_write(codec, codec->afg, 0, AC_VERB_SET_GPIO_DATA,
|
||||
snd_hda_codec_write(codec, codec->core.afg, 0, AC_VERB_SET_GPIO_DATA,
|
||||
spec->gpio_led);
|
||||
|
||||
if (spec->has_alc5505_dsp)
|
||||
|
@ -3112,8 +3112,8 @@ static void alc271_fixup_dmic(struct hda_codec *codec,
|
|||
};
|
||||
unsigned int cfg;
|
||||
|
||||
if (strcmp(codec->chip_name, "ALC271X") &&
|
||||
strcmp(codec->chip_name, "ALC269VB"))
|
||||
if (strcmp(codec->core.chip_name, "ALC271X") &&
|
||||
strcmp(codec->core.chip_name, "ALC269VB"))
|
||||
return;
|
||||
cfg = snd_hda_codec_get_pincfg(codec, 0x12);
|
||||
if (get_defcfg_connect(cfg) == AC_JACK_PORT_FIXED)
|
||||
|
@ -3479,9 +3479,9 @@ static void alc280_fixup_hp_gpio2_mic_hotkey(struct hda_codec *codec,
|
|||
}
|
||||
|
||||
snd_hda_add_verbs(codec, gpio_init);
|
||||
snd_hda_codec_write_cache(codec, codec->afg, 0,
|
||||
snd_hda_codec_write_cache(codec, codec->core.afg, 0,
|
||||
AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x04);
|
||||
snd_hda_jack_detect_enable_callback(codec, codec->afg,
|
||||
snd_hda_jack_detect_enable_callback(codec, codec->core.afg,
|
||||
gpio2_mic_hotkey_event);
|
||||
|
||||
spec->gen.vmaster_mute.hook = alc_fixup_gpio_mute_hook;
|
||||
|
@ -3564,7 +3564,7 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec)
|
|||
{}
|
||||
};
|
||||
|
||||
switch (codec->vendor_id) {
|
||||
switch (codec->core.vendor_id) {
|
||||
case 0x10ec0255:
|
||||
alc_process_coef_fw(codec, coef0255);
|
||||
break;
|
||||
|
@ -3619,7 +3619,7 @@ static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin,
|
|||
{}
|
||||
};
|
||||
|
||||
switch (codec->vendor_id) {
|
||||
switch (codec->core.vendor_id) {
|
||||
case 0x10ec0255:
|
||||
alc_write_coef_idx(codec, 0x45, 0xc489);
|
||||
snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
|
||||
|
@ -3688,7 +3688,7 @@ static void alc_headset_mode_default(struct hda_codec *codec)
|
|||
{}
|
||||
};
|
||||
|
||||
switch (codec->vendor_id) {
|
||||
switch (codec->core.vendor_id) {
|
||||
case 0x10ec0255:
|
||||
alc_process_coef_fw(codec, coef0255);
|
||||
break;
|
||||
|
@ -3742,7 +3742,7 @@ static void alc_headset_mode_ctia(struct hda_codec *codec)
|
|||
{}
|
||||
};
|
||||
|
||||
switch (codec->vendor_id) {
|
||||
switch (codec->core.vendor_id) {
|
||||
case 0x10ec0255:
|
||||
alc_process_coef_fw(codec, coef0255);
|
||||
break;
|
||||
|
@ -3796,7 +3796,7 @@ static void alc_headset_mode_omtp(struct hda_codec *codec)
|
|||
{}
|
||||
};
|
||||
|
||||
switch (codec->vendor_id) {
|
||||
switch (codec->core.vendor_id) {
|
||||
case 0x10ec0255:
|
||||
alc_process_coef_fw(codec, coef0255);
|
||||
break;
|
||||
|
@ -3841,7 +3841,7 @@ static void alc_determine_headset_type(struct hda_codec *codec)
|
|||
{}
|
||||
};
|
||||
|
||||
switch (codec->vendor_id) {
|
||||
switch (codec->core.vendor_id) {
|
||||
case 0x10ec0255:
|
||||
alc_process_coef_fw(codec, coef0255);
|
||||
msleep(300);
|
||||
|
@ -4078,7 +4078,7 @@ static unsigned int alc_power_filter_xps13(struct hda_codec *codec,
|
|||
|
||||
/* Avoid pop noises when headphones are plugged in */
|
||||
if (spec->gen.hp_jack_present)
|
||||
if (nid == codec->afg || nid == 0x02 || nid == 0x15)
|
||||
if (nid == codec->core.afg || nid == 0x02 || nid == 0x15)
|
||||
return AC_PWRST_D0;
|
||||
return power_state;
|
||||
}
|
||||
|
@ -5428,7 +5428,7 @@ static int patch_alc269(struct hda_codec *codec)
|
|||
if (has_cdefine_beep(codec))
|
||||
spec->gen.beep_nid = 0x01;
|
||||
|
||||
switch (codec->vendor_id) {
|
||||
switch (codec->core.vendor_id) {
|
||||
case 0x10ec0269:
|
||||
spec->codec_variant = ALC269_TYPE_ALC269VA;
|
||||
switch (alc_get_coef0(codec) & 0x00f0) {
|
||||
|
@ -5772,9 +5772,9 @@ static int alc662_parse_auto_config(struct hda_codec *codec)
|
|||
static const hda_nid_t alc662_ssids[] = { 0x15, 0x1b, 0x14, 0 };
|
||||
const hda_nid_t *ssids;
|
||||
|
||||
if (codec->vendor_id == 0x10ec0272 || codec->vendor_id == 0x10ec0663 ||
|
||||
codec->vendor_id == 0x10ec0665 || codec->vendor_id == 0x10ec0670 ||
|
||||
codec->vendor_id == 0x10ec0671)
|
||||
if (codec->core.vendor_id == 0x10ec0272 || codec->core.vendor_id == 0x10ec0663 ||
|
||||
codec->core.vendor_id == 0x10ec0665 || codec->core.vendor_id == 0x10ec0670 ||
|
||||
codec->core.vendor_id == 0x10ec0671)
|
||||
ssids = alc663_ssids;
|
||||
else
|
||||
ssids = alc662_ssids;
|
||||
|
@ -5819,7 +5819,7 @@ static unsigned int gpio_led_power_filter(struct hda_codec *codec,
|
|||
unsigned int power_state)
|
||||
{
|
||||
struct alc_spec *spec = codec->spec;
|
||||
if (nid == codec->afg && power_state == AC_PWRST_D3 && spec->gpio_led)
|
||||
if (nid == codec->core.afg && power_state == AC_PWRST_D3 && spec->gpio_led)
|
||||
return AC_PWRST_D0;
|
||||
return power_state;
|
||||
}
|
||||
|
@ -6317,7 +6317,7 @@ static int patch_alc662(struct hda_codec *codec)
|
|||
|
||||
alc_fix_pll_init(codec, 0x20, 0x04, 15);
|
||||
|
||||
switch (codec->vendor_id) {
|
||||
switch (codec->core.vendor_id) {
|
||||
case 0x10ec0668:
|
||||
spec->init_hook = alc668_restore_default_value;
|
||||
break;
|
||||
|
@ -6347,7 +6347,7 @@ static int patch_alc662(struct hda_codec *codec)
|
|||
goto error;
|
||||
|
||||
if (!spec->gen.no_analog && spec->gen.beep_nid) {
|
||||
switch (codec->vendor_id) {
|
||||
switch (codec->core.vendor_id) {
|
||||
case 0x10ec0662:
|
||||
set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
|
||||
break;
|
||||
|
|
|
@ -205,8 +205,8 @@ static int si3054_build_pcms(struct hda_codec *codec)
|
|||
return -ENOMEM;
|
||||
info->stream[SNDRV_PCM_STREAM_PLAYBACK] = si3054_pcm;
|
||||
info->stream[SNDRV_PCM_STREAM_CAPTURE] = si3054_pcm;
|
||||
info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = codec->mfg;
|
||||
info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = codec->mfg;
|
||||
info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = codec->core.mfg;
|
||||
info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = codec->core.mfg;
|
||||
info->pcm_type = HDA_PCM_TYPE_MODEM;
|
||||
return 0;
|
||||
}
|
||||
|
@ -223,7 +223,7 @@ static int si3054_init(struct hda_codec *codec)
|
|||
u16 val;
|
||||
|
||||
snd_hda_codec_write(codec, AC_NODE_ROOT, 0, AC_VERB_SET_CODEC_RESET, 0);
|
||||
snd_hda_codec_write(codec, codec->mfg, 0, AC_VERB_SET_STREAM_FORMAT, 0);
|
||||
snd_hda_codec_write(codec, codec->core.mfg, 0, AC_VERB_SET_STREAM_FORMAT, 0);
|
||||
SET_REG(codec, SI3054_LINE_RATE, 9600);
|
||||
SET_REG(codec, SI3054_LINE_LEVEL, SI3054_DTAG_MASK|SI3054_ATAG_MASK);
|
||||
SET_REG(codec, SI3054_EXTENDED_MID, 0);
|
||||
|
|
|
@ -299,32 +299,33 @@ static void stac_gpio_set(struct hda_codec *codec, unsigned int mask,
|
|||
unsigned int dir_mask, unsigned int data)
|
||||
{
|
||||
unsigned int gpiostate, gpiomask, gpiodir;
|
||||
hda_nid_t fg = codec->core.afg;
|
||||
|
||||
codec_dbg(codec, "%s msk %x dir %x gpio %x\n", __func__, mask, dir_mask, data);
|
||||
|
||||
gpiostate = snd_hda_codec_read(codec, codec->afg, 0,
|
||||
gpiostate = snd_hda_codec_read(codec, fg, 0,
|
||||
AC_VERB_GET_GPIO_DATA, 0);
|
||||
gpiostate = (gpiostate & ~dir_mask) | (data & dir_mask);
|
||||
|
||||
gpiomask = snd_hda_codec_read(codec, codec->afg, 0,
|
||||
gpiomask = snd_hda_codec_read(codec, fg, 0,
|
||||
AC_VERB_GET_GPIO_MASK, 0);
|
||||
gpiomask |= mask;
|
||||
|
||||
gpiodir = snd_hda_codec_read(codec, codec->afg, 0,
|
||||
gpiodir = snd_hda_codec_read(codec, fg, 0,
|
||||
AC_VERB_GET_GPIO_DIRECTION, 0);
|
||||
gpiodir |= dir_mask;
|
||||
|
||||
/* Configure GPIOx as CMOS */
|
||||
snd_hda_codec_write(codec, codec->afg, 0, 0x7e7, 0);
|
||||
snd_hda_codec_write(codec, fg, 0, 0x7e7, 0);
|
||||
|
||||
snd_hda_codec_write(codec, codec->afg, 0,
|
||||
snd_hda_codec_write(codec, fg, 0,
|
||||
AC_VERB_SET_GPIO_MASK, gpiomask);
|
||||
snd_hda_codec_read(codec, codec->afg, 0,
|
||||
snd_hda_codec_read(codec, fg, 0,
|
||||
AC_VERB_SET_GPIO_DIRECTION, gpiodir); /* sync */
|
||||
|
||||
msleep(1);
|
||||
|
||||
snd_hda_codec_read(codec, codec->afg, 0,
|
||||
snd_hda_codec_read(codec, fg, 0,
|
||||
AC_VERB_SET_GPIO_DATA, gpiostate); /* sync */
|
||||
}
|
||||
|
||||
|
@ -387,7 +388,7 @@ static unsigned int stac_vref_led_power_filter(struct hda_codec *codec,
|
|||
hda_nid_t nid,
|
||||
unsigned int power_state)
|
||||
{
|
||||
if (nid == codec->afg && power_state == AC_PWRST_D3)
|
||||
if (nid == codec->core.afg && power_state == AC_PWRST_D3)
|
||||
return AC_PWRST_D1;
|
||||
return snd_hda_gen_path_power_filter(codec, nid, power_state);
|
||||
}
|
||||
|
@ -432,7 +433,7 @@ static void stac_update_outputs(struct hda_codec *codec)
|
|||
|
||||
if (spec->gpio_mute)
|
||||
spec->gen.master_mute =
|
||||
!(snd_hda_codec_read(codec, codec->afg, 0,
|
||||
!(snd_hda_codec_read(codec, codec->core.afg, 0,
|
||||
AC_VERB_GET_GPIO_DATA, 0) & spec->gpio_mute);
|
||||
|
||||
snd_hda_gen_update_outputs(codec);
|
||||
|
@ -476,7 +477,7 @@ static void stac_toggle_power_map(struct hda_codec *codec, hda_nid_t nid,
|
|||
if (val != spec->power_map_bits) {
|
||||
spec->power_map_bits = val;
|
||||
if (do_write)
|
||||
snd_hda_codec_write(codec, codec->afg, 0,
|
||||
snd_hda_codec_write(codec, codec->core.afg, 0,
|
||||
AC_VERB_IDT_SET_POWER_MAP, val);
|
||||
}
|
||||
}
|
||||
|
@ -508,7 +509,8 @@ static void jack_update_power(struct hda_codec *codec,
|
|||
false);
|
||||
}
|
||||
|
||||
snd_hda_codec_write(codec, codec->afg, 0, AC_VERB_IDT_SET_POWER_MAP,
|
||||
snd_hda_codec_write(codec, codec->core.afg, 0,
|
||||
AC_VERB_IDT_SET_POWER_MAP,
|
||||
spec->power_map_bits);
|
||||
}
|
||||
|
||||
|
@ -517,10 +519,10 @@ static void stac_vref_event(struct hda_codec *codec,
|
|||
{
|
||||
unsigned int data;
|
||||
|
||||
data = snd_hda_codec_read(codec, codec->afg, 0,
|
||||
data = snd_hda_codec_read(codec, codec->core.afg, 0,
|
||||
AC_VERB_GET_GPIO_DATA, 0);
|
||||
/* toggle VREF state based on GPIOx status */
|
||||
snd_hda_codec_write(codec, codec->afg, 0, 0x7e0,
|
||||
snd_hda_codec_write(codec, codec->core.afg, 0, 0x7e0,
|
||||
!!(data & (1 << event->private_data)));
|
||||
}
|
||||
|
||||
|
@ -622,7 +624,7 @@ static int stac_aloopback_put(struct snd_kcontrol *kcontrol,
|
|||
/* Only return the bits defined by the shift value of the
|
||||
* first two bytes of the mask
|
||||
*/
|
||||
dac_mode = snd_hda_codec_read(codec, codec->afg, 0,
|
||||
dac_mode = snd_hda_codec_read(codec, codec->core.afg, 0,
|
||||
kcontrol->private_value & 0xFFFF, 0x0);
|
||||
dac_mode >>= spec->aloopback_shift;
|
||||
|
||||
|
@ -634,7 +636,7 @@ static int stac_aloopback_put(struct snd_kcontrol *kcontrol,
|
|||
dac_mode &= ~idx_val;
|
||||
}
|
||||
|
||||
snd_hda_codec_write_cache(codec, codec->afg, 0,
|
||||
snd_hda_codec_write_cache(codec, codec->core.afg, 0,
|
||||
kcontrol->private_value >> 16, dac_mode);
|
||||
|
||||
return 1;
|
||||
|
@ -658,11 +660,11 @@ static int stac_aloopback_put(struct snd_kcontrol *kcontrol,
|
|||
/* check whether it's a HP laptop with a docking port */
|
||||
static bool hp_bnb2011_with_dock(struct hda_codec *codec)
|
||||
{
|
||||
if (codec->vendor_id != 0x111d7605 &&
|
||||
codec->vendor_id != 0x111d76d1)
|
||||
if (codec->core.vendor_id != 0x111d7605 &&
|
||||
codec->core.vendor_id != 0x111d76d1)
|
||||
return false;
|
||||
|
||||
switch (codec->subsystem_id) {
|
||||
switch (codec->core.subsystem_id) {
|
||||
case 0x103c1618:
|
||||
case 0x103c1619:
|
||||
case 0x103c161a:
|
||||
|
@ -733,7 +735,7 @@ static void set_hp_led_gpio(struct hda_codec *codec)
|
|||
if (spec->gpio_led)
|
||||
return;
|
||||
|
||||
gpio = snd_hda_param_read(codec, codec->afg, AC_PAR_GPIO_CAP);
|
||||
gpio = snd_hda_param_read(codec, codec->core.afg, AC_PAR_GPIO_CAP);
|
||||
gpio &= AC_GPIO_IO_COUNT;
|
||||
if (gpio > 3)
|
||||
spec->gpio_led = 0x08; /* GPIO 3 */
|
||||
|
@ -777,7 +779,7 @@ static int find_mute_led_cfg(struct hda_codec *codec, int default_polarity)
|
|||
&spec->gpio_led_polarity,
|
||||
&spec->gpio_led) == 2) {
|
||||
unsigned int max_gpio;
|
||||
max_gpio = snd_hda_param_read(codec, codec->afg,
|
||||
max_gpio = snd_hda_param_read(codec, codec->core.afg,
|
||||
AC_PAR_GPIO_CAP);
|
||||
max_gpio &= AC_GPIO_IO_COUNT;
|
||||
if (spec->gpio_led < max_gpio)
|
||||
|
@ -807,7 +809,7 @@ static int find_mute_led_cfg(struct hda_codec *codec, int default_polarity)
|
|||
* we statically set the GPIO - if not a B-series system
|
||||
* and default polarity is provided
|
||||
*/
|
||||
if (!hp_blike_system(codec->subsystem_id) &&
|
||||
if (!hp_blike_system(codec->core.subsystem_id) &&
|
||||
(default_polarity == 0 || default_polarity == 1)) {
|
||||
set_hp_led_gpio(codec);
|
||||
spec->gpio_led_polarity = default_polarity;
|
||||
|
@ -2134,7 +2136,7 @@ static void stac92hd83xxx_fixup_hp_mic_led(struct hda_codec *codec,
|
|||
spec->mic_mute_led_gpio = 0x08; /* GPIO3 */
|
||||
#ifdef CONFIG_PM
|
||||
/* resetting controller clears GPIO, so we need to keep on */
|
||||
codec->d3_stop_clk = 0;
|
||||
codec->core.power_caps &= ~AC_PWRST_CLKSTOP;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -3031,9 +3033,9 @@ static void stac92hd71bxx_fixup_hp_m4(struct hda_codec *codec,
|
|||
return;
|
||||
|
||||
/* Enable VREF power saving on GPIO1 detect */
|
||||
snd_hda_codec_write_cache(codec, codec->afg, 0,
|
||||
snd_hda_codec_write_cache(codec, codec->core.afg, 0,
|
||||
AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x02);
|
||||
jack = snd_hda_jack_detect_enable_callback(codec, codec->afg,
|
||||
jack = snd_hda_jack_detect_enable_callback(codec, codec->core.afg,
|
||||
stac_vref_event);
|
||||
if (!IS_ERR(jack))
|
||||
jack->private_data = 0x02;
|
||||
|
@ -3093,7 +3095,7 @@ static void stac92hd71bxx_fixup_hp(struct hda_codec *codec,
|
|||
if (action != HDA_FIXUP_ACT_PRE_PROBE)
|
||||
return;
|
||||
|
||||
if (hp_blike_system(codec->subsystem_id)) {
|
||||
if (hp_blike_system(codec->core.subsystem_id)) {
|
||||
unsigned int pin_cfg = snd_hda_codec_get_pincfg(codec, 0x0f);
|
||||
if (get_defcfg_device(pin_cfg) == AC_JACK_LINE_OUT ||
|
||||
get_defcfg_device(pin_cfg) == AC_JACK_SPEAKER ||
|
||||
|
@ -3792,7 +3794,7 @@ static void stac927x_fixup_dell_dmic(struct hda_codec *codec,
|
|||
if (action != HDA_FIXUP_ACT_PRE_PROBE)
|
||||
return;
|
||||
|
||||
if (codec->subsystem_id != 0x1028022f) {
|
||||
if (codec->core.subsystem_id != 0x1028022f) {
|
||||
/* GPIO2 High = Enable EAPD */
|
||||
spec->eapd_mask = spec->gpio_mask = 0x04;
|
||||
spec->gpio_dir = spec->gpio_data = 0x04;
|
||||
|
@ -4053,9 +4055,9 @@ static void stac9205_fixup_dell_m43(struct hda_codec *codec,
|
|||
snd_hda_apply_pincfgs(codec, dell_9205_m43_pin_configs);
|
||||
|
||||
/* Enable unsol response for GPIO4/Dock HP connection */
|
||||
snd_hda_codec_write_cache(codec, codec->afg, 0,
|
||||
snd_hda_codec_write_cache(codec, codec->core.afg, 0,
|
||||
AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x10);
|
||||
jack = snd_hda_jack_detect_enable_callback(codec, codec->afg,
|
||||
jack = snd_hda_jack_detect_enable_callback(codec, codec->core.afg,
|
||||
stac_vref_event);
|
||||
if (!IS_ERR(jack))
|
||||
jack->private_data = 0x01;
|
||||
|
@ -4302,7 +4304,7 @@ static int stac_init(struct hda_codec *codec)
|
|||
|
||||
/* sync the power-map */
|
||||
if (spec->num_pwrs)
|
||||
snd_hda_codec_write(codec, codec->afg, 0,
|
||||
snd_hda_codec_write(codec, codec->core.afg, 0,
|
||||
AC_VERB_IDT_SET_POWER_MAP,
|
||||
spec->power_map_bits);
|
||||
|
||||
|
@ -4338,7 +4340,7 @@ static void stac_shutup(struct hda_codec *codec)
|
|||
static void stac92hd_proc_hook(struct snd_info_buffer *buffer,
|
||||
struct hda_codec *codec, hda_nid_t nid)
|
||||
{
|
||||
if (nid == codec->afg)
|
||||
if (nid == codec->core.afg)
|
||||
snd_iprintf(buffer, "Power-Map: 0x%02x\n",
|
||||
snd_hda_codec_read(codec, nid, 0,
|
||||
AC_VERB_IDT_GET_POWER_MAP, 0));
|
||||
|
@ -4349,7 +4351,7 @@ static void analog_loop_proc_hook(struct snd_info_buffer *buffer,
|
|||
unsigned int verb)
|
||||
{
|
||||
snd_iprintf(buffer, "Analog Loopback: 0x%02x\n",
|
||||
snd_hda_codec_read(codec, codec->afg, 0, verb, 0));
|
||||
snd_hda_codec_read(codec, codec->core.afg, 0, verb, 0));
|
||||
}
|
||||
|
||||
/* stac92hd71bxx, stac92hd73xx */
|
||||
|
@ -4357,21 +4359,21 @@ static void stac92hd7x_proc_hook(struct snd_info_buffer *buffer,
|
|||
struct hda_codec *codec, hda_nid_t nid)
|
||||
{
|
||||
stac92hd_proc_hook(buffer, codec, nid);
|
||||
if (nid == codec->afg)
|
||||
if (nid == codec->core.afg)
|
||||
analog_loop_proc_hook(buffer, codec, 0xfa0);
|
||||
}
|
||||
|
||||
static void stac9205_proc_hook(struct snd_info_buffer *buffer,
|
||||
struct hda_codec *codec, hda_nid_t nid)
|
||||
{
|
||||
if (nid == codec->afg)
|
||||
if (nid == codec->core.afg)
|
||||
analog_loop_proc_hook(buffer, codec, 0xfe0);
|
||||
}
|
||||
|
||||
static void stac927x_proc_hook(struct snd_info_buffer *buffer,
|
||||
struct hda_codec *codec, hda_nid_t nid)
|
||||
{
|
||||
if (nid == codec->afg)
|
||||
if (nid == codec->core.afg)
|
||||
analog_loop_proc_hook(buffer, codec, 0xfeb);
|
||||
}
|
||||
#else
|
||||
|
@ -4597,7 +4599,8 @@ static int patch_stac92hd83xxx(struct hda_codec *codec)
|
|||
if (err < 0)
|
||||
return err;
|
||||
|
||||
codec->epss = 0; /* longer delay needed for D3 */
|
||||
/* longer delay needed for D3 */
|
||||
codec->core.power_caps &= ~AC_PWRST_EPSS;
|
||||
|
||||
spec = codec->spec;
|
||||
codec->power_save_node = 1;
|
||||
|
@ -4647,7 +4650,8 @@ static int patch_stac92hd95(struct hda_codec *codec)
|
|||
if (err < 0)
|
||||
return err;
|
||||
|
||||
codec->epss = 0; /* longer delay needed for D3 */
|
||||
/* longer delay needed for D3 */
|
||||
codec->core.power_caps &= ~AC_PWRST_EPSS;
|
||||
|
||||
spec = codec->spec;
|
||||
codec->power_save_node = 1;
|
||||
|
@ -4706,14 +4710,14 @@ static int patch_stac92hd71bxx(struct hda_codec *codec)
|
|||
spec->gpio_dir = 0x01;
|
||||
spec->gpio_data = 0x01;
|
||||
|
||||
switch (codec->vendor_id) {
|
||||
switch (codec->core.vendor_id) {
|
||||
case 0x111d76b6: /* 4 Port without Analog Mixer */
|
||||
case 0x111d76b7:
|
||||
unmute_init++;
|
||||
break;
|
||||
case 0x111d7608: /* 5 Port with Analog Mixer */
|
||||
if ((codec->revision_id & 0xf) == 0 ||
|
||||
(codec->revision_id & 0xf) == 1)
|
||||
if ((codec->core.revision_id & 0xf) == 0 ||
|
||||
(codec->core.revision_id & 0xf) == 1)
|
||||
spec->stream_delay = 40; /* 40 milliseconds */
|
||||
|
||||
/* disable VSW */
|
||||
|
@ -4722,7 +4726,7 @@ static int patch_stac92hd71bxx(struct hda_codec *codec)
|
|||
snd_hda_codec_set_pincfg(codec, 0x19, 0x40f000f3);
|
||||
break;
|
||||
case 0x111d7603: /* 6 Port with Analog Mixer */
|
||||
if ((codec->revision_id & 0xf) == 1)
|
||||
if ((codec->core.revision_id & 0xf) == 1)
|
||||
spec->stream_delay = 40; /* 40 milliseconds */
|
||||
|
||||
break;
|
||||
|
|
|
@ -140,7 +140,7 @@ static struct via_spec *via_new_spec(struct hda_codec *codec)
|
|||
|
||||
static enum VIA_HDA_CODEC get_codec_type(struct hda_codec *codec)
|
||||
{
|
||||
u32 vendor_id = codec->vendor_id;
|
||||
u32 vendor_id = codec->core.vendor_id;
|
||||
u16 ven_id = vendor_id >> 16;
|
||||
u16 dev_id = vendor_id & 0xffff;
|
||||
enum VIA_HDA_CODEC codec_type;
|
||||
|
@ -335,7 +335,7 @@ static void __analog_low_current_mode(struct hda_codec *codec, bool force)
|
|||
return; /* other codecs are not supported */
|
||||
}
|
||||
/* send verb */
|
||||
snd_hda_codec_write(codec, codec->afg, 0, verb, parm);
|
||||
snd_hda_codec_write(codec, codec->core.afg, 0, verb, parm);
|
||||
}
|
||||
|
||||
static void analog_low_current_mode(struct hda_codec *codec)
|
||||
|
@ -558,7 +558,7 @@ static int vt1708_build_pcms(struct hda_codec *codec)
|
|||
int i, err;
|
||||
|
||||
err = snd_hda_gen_build_pcms(codec);
|
||||
if (err < 0 || codec->vendor_id != 0x11061708)
|
||||
if (err < 0 || codec->core.vendor_id != 0x11061708)
|
||||
return err;
|
||||
|
||||
/* We got noisy outputs on the right channel on VT1708 when
|
||||
|
@ -714,19 +714,19 @@ static int patch_vt1708S(struct hda_codec *codec)
|
|||
|
||||
/* correct names for VT1708BCE */
|
||||
if (get_codec_type(codec) == VT1708BCE) {
|
||||
kfree(codec->chip_name);
|
||||
codec->chip_name = kstrdup("VT1708BCE", GFP_KERNEL);
|
||||
kfree(codec->core.chip_name);
|
||||
codec->core.chip_name = kstrdup("VT1708BCE", GFP_KERNEL);
|
||||
snprintf(codec->card->mixername,
|
||||
sizeof(codec->card->mixername),
|
||||
"%s %s", codec->vendor_name, codec->chip_name);
|
||||
"%s %s", codec->core.vendor_name, codec->core.chip_name);
|
||||
}
|
||||
/* correct names for VT1705 */
|
||||
if (codec->vendor_id == 0x11064397) {
|
||||
kfree(codec->chip_name);
|
||||
codec->chip_name = kstrdup("VT1705", GFP_KERNEL);
|
||||
if (codec->core.vendor_id == 0x11064397) {
|
||||
kfree(codec->core.chip_name);
|
||||
codec->core.chip_name = kstrdup("VT1705", GFP_KERNEL);
|
||||
snprintf(codec->card->mixername,
|
||||
sizeof(codec->card->mixername),
|
||||
"%s %s", codec->vendor_name, codec->chip_name);
|
||||
"%s %s", codec->core.vendor_name, codec->core.chip_name);
|
||||
}
|
||||
|
||||
/* automatic parse from the BIOS config */
|
||||
|
@ -815,8 +815,7 @@ static int add_secret_dac_path(struct hda_codec *codec)
|
|||
}
|
||||
|
||||
/* find the primary DAC and add to the connection list */
|
||||
nid = codec->start_nid;
|
||||
for (i = 0; i < codec->num_nodes; i++, nid++) {
|
||||
for_each_hda_codec_node(nid, codec) {
|
||||
unsigned int caps = get_wcaps(codec, nid);
|
||||
if (get_wcaps_type(caps) == AC_WID_AUD_OUT &&
|
||||
!(caps & AC_WCAP_DIGITAL)) {
|
||||
|
|
|
@ -21,7 +21,7 @@ static acpi_status acpi_check_cb(acpi_handle handle, u32 lvl, void *context,
|
|||
static bool is_thinkpad(struct hda_codec *codec)
|
||||
{
|
||||
bool found = false;
|
||||
if (codec->subsystem_id >> 16 != 0x17aa)
|
||||
if (codec->core.subsystem_id >> 16 != 0x17aa)
|
||||
return false;
|
||||
if (ACPI_SUCCESS(acpi_get_devices("LEN0068", acpi_check_cb, &found, NULL)) && found)
|
||||
return true;
|
||||
|
|
Loading…
Reference in New Issue
Block a user