Skip to content

Commit

Permalink
Merge branch 'topic/hda-modalias' into for-next
Browse files Browse the repository at this point in the history
  • Loading branch information
tiwai committed Oct 20, 2015
2 parents 9a30ae2 + b6e84c9 commit c80a1da
Show file tree
Hide file tree
Showing 22 changed files with 482 additions and 605 deletions.
8 changes: 8 additions & 0 deletions include/linux/mod_devicetable.h
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,14 @@ struct serio_device_id {
__u8 proto;
};

struct hda_device_id {
__u32 vendor_id;
__u32 rev_id;
__u8 api_version;
const char *name;
unsigned long driver_data;
};

/*
* Struct used for matching a device
*/
Expand Down
12 changes: 2 additions & 10 deletions include/sound/hdaudio.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,13 @@ struct hdac_stream;
struct hdac_device;
struct hdac_driver;
struct hdac_widget_tree;
struct hda_device_id;

/*
* exported bus type
*/
extern struct bus_type snd_hda_bus_type;

/*
* HDA device table
*/
struct hda_device_id {
__u32 vendor_id;
__u32 rev_id;
const char *name;
unsigned long driver_data;
};

/*
* generic arrays
*/
Expand Down Expand Up @@ -118,6 +109,7 @@ void snd_hdac_device_exit(struct hdac_device *dev);
int snd_hdac_device_register(struct hdac_device *codec);
void snd_hdac_device_unregister(struct hdac_device *codec);
int snd_hdac_device_set_chip_name(struct hdac_device *codec, const char *name);
int snd_hdac_codec_modalias(struct hdac_device *hdac, char *buf, size_t size);

int snd_hdac_refresh_widgets(struct hdac_device *codec);
int snd_hdac_refresh_widget_sysfs(struct hdac_device *codec);
Expand Down
7 changes: 7 additions & 0 deletions include/sound/hdaudio_ext.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,13 @@ void snd_hdac_ext_bus_device_remove(struct hdac_ext_bus *ebus);
#define hbus_to_ebus(_bus) \
container_of(_bus, struct hdac_ext_bus, bus)

#define HDA_CODEC_REV_EXT_ENTRY(_vid, _rev, _name, drv_data) \
{ .vendor_id = (_vid), .rev_id = (_rev), .name = (_name), \
.api_version = HDA_DEV_ASOC, \
.driver_data = (unsigned long)(drv_data) }
#define HDA_CODEC_EXT_ENTRY(_vid, _revid, _name, _drv_data) \
HDA_CODEC_REV_EXT_ENTRY(_vid, _revid, _name, _drv_data)

int snd_hdac_ext_bus_parse_capabilities(struct hdac_ext_bus *sbus);
void snd_hdac_ext_bus_ppcap_enable(struct hdac_ext_bus *chip, bool enable);
void snd_hdac_ext_bus_ppcap_int_enable(struct hdac_ext_bus *chip, bool enable);
Expand Down
5 changes: 5 additions & 0 deletions scripts/mod/devicetable-offsets.c
Original file line number Diff line number Diff line change
Expand Up @@ -196,5 +196,10 @@ int main(void)
DEVID_FIELD(ulpi_device_id, vendor);
DEVID_FIELD(ulpi_device_id, product);

DEVID(hda_device_id);
DEVID_FIELD(hda_device_id, vendor_id);
DEVID_FIELD(hda_device_id, rev_id);
DEVID_FIELD(hda_device_id, api_version);

return 0;
}
17 changes: 17 additions & 0 deletions scripts/mod/file2alias.c
Original file line number Diff line number Diff line change
Expand Up @@ -1250,6 +1250,23 @@ static int do_ulpi_entry(const char *filename, void *symval,
}
ADD_TO_DEVTABLE("ulpi", ulpi_device_id, do_ulpi_entry);

/* Looks like: hdaudio:vNrNaN */
static int do_hda_entry(const char *filename, void *symval, char *alias)
{
DEF_FIELD(symval, hda_device_id, vendor_id);
DEF_FIELD(symval, hda_device_id, rev_id);
DEF_FIELD(symval, hda_device_id, api_version);

strcpy(alias, "hdaudio:");
ADD(alias, "v", vendor_id != 0, vendor_id);
ADD(alias, "r", rev_id != 0, rev_id);
ADD(alias, "a", api_version != 0, api_version);

add_wildcard(alias);
return 1;
}
ADD_TO_DEVTABLE("hdaudio", hda_device_id, do_hda_entry);

/* Does namelen bytes of name exactly match the symbol? */
static bool sym_is(const char *name, unsigned namelen, const char *symbol)
{
Expand Down
13 changes: 13 additions & 0 deletions sound/hda/hda_bus_type.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <linux/init.h>
#include <linux/device.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/export.h>
#include <sound/hdaudio.h>

Expand Down Expand Up @@ -63,9 +64,21 @@ static int hda_bus_match(struct device *dev, struct device_driver *drv)
return 1;
}

static int hda_uevent(struct device *dev, struct kobj_uevent_env *env)
{
char modalias[32];

snd_hdac_codec_modalias(dev_to_hdac_dev(dev), modalias,
sizeof(modalias));
if (add_uevent_var(env, "MODALIAS=%s", modalias))
return -ENOMEM;
return 0;
}

struct bus_type snd_hda_bus_type = {
.name = "hdaudio",
.match = hda_bus_match,
.uevent = hda_uevent,
};
EXPORT_SYMBOL_GPL(snd_hda_bus_type);

Expand Down
15 changes: 15 additions & 0 deletions sound/hda/hdac_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,21 @@ int snd_hdac_device_set_chip_name(struct hdac_device *codec, const char *name)
}
EXPORT_SYMBOL_GPL(snd_hdac_device_set_chip_name);

/**
* snd_hdac_codec_modalias - give the module alias name
* @codec: HDAC device
* @buf: string buffer to store
* @size: string buffer size
*
* Returns the size of string, like snprintf(), or a negative error code.
*/
int snd_hdac_codec_modalias(struct hdac_device *codec, char *buf, size_t size)
{
return snprintf(buf, size, "hdaudio:v%08Xr%08Xa%02X\n",
codec->vendor_id, codec->revision_id, codec->type);
}
EXPORT_SYMBOL_GPL(snd_hdac_codec_modalias);

/**
* snd_hdac_make_cmd - compose a 32bit command word to be sent to the
* HD-audio controller
Expand Down
8 changes: 8 additions & 0 deletions sound/hda/hdac_sysfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,13 @@ CODEC_ATTR(mfg);
CODEC_ATTR_STR(vendor_name);
CODEC_ATTR_STR(chip_name);

static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
return snd_hdac_codec_modalias(dev_to_hdac_dev(dev), buf, 256);
}
static DEVICE_ATTR_RO(modalias);

static struct attribute *hdac_dev_attrs[] = {
&dev_attr_type.attr,
&dev_attr_vendor_id.attr,
Expand All @@ -54,6 +61,7 @@ static struct attribute *hdac_dev_attrs[] = {
&dev_attr_mfg.attr,
&dev_attr_vendor_name.attr,
&dev_attr_chip_name.attr,
&dev_attr_modalias.attr,
NULL
};

Expand Down
32 changes: 18 additions & 14 deletions sound/pci/hda/hda_bind.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,22 @@
#include "hda_local.h"

/*
* find a matching codec preset
* find a matching codec id
*/
static int hda_codec_match(struct hdac_device *dev, struct hdac_driver *drv)
{
struct hda_codec *codec = container_of(dev, struct hda_codec, core);
struct hda_codec_driver *driver =
container_of(drv, struct hda_codec_driver, core);
const struct hda_codec_preset *preset;
const struct hda_device_id *list;
/* check probe_id instead of vendor_id if set */
u32 id = codec->probe_id ? codec->probe_id : codec->core.vendor_id;
u32 rev_id = codec->core.revision_id;

for (preset = driver->preset; preset->id; preset++) {
if (preset->id == id &&
(!preset->rev || preset->rev == codec->core.revision_id)) {
codec->preset = preset;
for (list = driver->id; list->vendor_id; list++) {
if (list->vendor_id == id &&
(!list->rev_id || list->rev_id == rev_id)) {
codec->preset = list;
return 1;
}
}
Expand Down Expand Up @@ -77,6 +78,7 @@ static int hda_codec_driver_probe(struct device *dev)
{
struct hda_codec *codec = dev_to_hda_codec(dev);
struct module *owner = dev->driver->owner;
hda_codec_patch_t patch;
int err;

if (WARN_ON(!codec->preset))
Expand All @@ -94,9 +96,12 @@ static int hda_codec_driver_probe(struct device *dev)
goto error;
}

err = codec->preset->patch(codec);
if (err < 0)
goto error_module;
patch = (hda_codec_patch_t)codec->preset->driver_data;
if (patch) {
err = patch(codec);
if (err < 0)
goto error_module;
}

err = snd_hda_codec_build_pcms(codec);
if (err < 0)
Expand Down Expand Up @@ -173,11 +178,10 @@ 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->core.vendor_id);
if (codec_probed(codec))
return;
request_module("snd-hda-codec-id:%04x*",
(codec->core.vendor_id >> 16) & 0xffff);
char modalias[32];

snd_hdac_codec_modalias(&codec->core, modalias, sizeof(modalias));
request_module(modalias);
if (codec_probed(codec))
return;
#endif
Expand Down
19 changes: 11 additions & 8 deletions sound/pci/hda/hda_codec.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#define __SOUND_HDA_CODEC_H

#include <linux/kref.h>
#include <linux/mod_devicetable.h>
#include <sound/info.h>
#include <sound/control.h>
#include <sound/pcm.h>
Expand Down Expand Up @@ -81,19 +82,21 @@ struct hda_bus {
* Known codecs have the patch to build and set up the controls/PCMs
* better than the generic parser.
*/
struct hda_codec_preset {
unsigned int id;
unsigned int rev;
const char *name;
int (*patch)(struct hda_codec *codec);
};
typedef int (*hda_codec_patch_t)(struct hda_codec *);

#define HDA_CODEC_ID_GENERIC_HDMI 0x00000101
#define HDA_CODEC_ID_GENERIC 0x00000201

#define HDA_CODEC_REV_ENTRY(_vid, _rev, _name, _patch) \
{ .vendor_id = (_vid), .rev_id = (_rev), .name = (_name), \
.api_version = HDA_DEV_LEGACY, \
.driver_data = (unsigned long)(_patch) }
#define HDA_CODEC_ENTRY(_vid, _name, _patch) \
HDA_CODEC_REV_ENTRY(_vid, 0, _name, _patch)

struct hda_codec_driver {
struct hdac_driver core;
const struct hda_codec_preset *preset;
const struct hda_device_id *id;
};

int __hda_codec_driver_register(struct hda_codec_driver *drv, const char *name,
Expand Down Expand Up @@ -184,7 +187,7 @@ struct hda_codec {
u32 probe_id; /* overridden id for probing */

/* detected preset */
const struct hda_codec_preset *preset;
const struct hda_device_id *preset;
const char *modelname; /* model name for preset */

/* set by patch */
Expand Down
7 changes: 4 additions & 3 deletions sound/pci/hda/hda_generic.c
Original file line number Diff line number Diff line change
Expand Up @@ -5877,13 +5877,14 @@ static int snd_hda_parse_generic_codec(struct hda_codec *codec)
return err;
}

static const struct hda_codec_preset snd_hda_preset_generic[] = {
{ .id = HDA_CODEC_ID_GENERIC, .patch = snd_hda_parse_generic_codec },
static const struct hda_device_id snd_hda_id_generic[] = {
HDA_CODEC_ENTRY(HDA_CODEC_ID_GENERIC, "Generic", snd_hda_parse_generic_codec),
{} /* terminator */
};
MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_generic);

static struct hda_codec_driver generic_driver = {
.preset = snd_hda_preset_generic,
.id = snd_hda_id_generic,
};

module_hda_codec_driver(generic_driver);
Expand Down
37 changes: 18 additions & 19 deletions sound/pci/hda/patch_analog.c
Original file line number Diff line number Diff line change
Expand Up @@ -1165,32 +1165,31 @@ static int patch_ad1882(struct hda_codec *codec)
/*
* patch entries
*/
static const struct hda_codec_preset snd_hda_preset_analog[] = {
{ .id = 0x11d4184a, .name = "AD1884A", .patch = patch_ad1884 },
{ .id = 0x11d41882, .name = "AD1882", .patch = patch_ad1882 },
{ .id = 0x11d41883, .name = "AD1883", .patch = patch_ad1884 },
{ .id = 0x11d41884, .name = "AD1884", .patch = patch_ad1884 },
{ .id = 0x11d4194a, .name = "AD1984A", .patch = patch_ad1884 },
{ .id = 0x11d4194b, .name = "AD1984B", .patch = patch_ad1884 },
{ .id = 0x11d41981, .name = "AD1981", .patch = patch_ad1981 },
{ .id = 0x11d41983, .name = "AD1983", .patch = patch_ad1983 },
{ .id = 0x11d41984, .name = "AD1984", .patch = patch_ad1884 },
{ .id = 0x11d41986, .name = "AD1986A", .patch = patch_ad1986a },
{ .id = 0x11d41988, .name = "AD1988", .patch = patch_ad1988 },
{ .id = 0x11d4198b, .name = "AD1988B", .patch = patch_ad1988 },
{ .id = 0x11d4882a, .name = "AD1882A", .patch = patch_ad1882 },
{ .id = 0x11d4989a, .name = "AD1989A", .patch = patch_ad1988 },
{ .id = 0x11d4989b, .name = "AD1989B", .patch = patch_ad1988 },
static const struct hda_device_id snd_hda_id_analog[] = {
HDA_CODEC_ENTRY(0x11d4184a, "AD1884A", patch_ad1884),
HDA_CODEC_ENTRY(0x11d41882, "AD1882", patch_ad1882),
HDA_CODEC_ENTRY(0x11d41883, "AD1883", patch_ad1884),
HDA_CODEC_ENTRY(0x11d41884, "AD1884", patch_ad1884),
HDA_CODEC_ENTRY(0x11d4194a, "AD1984A", patch_ad1884),
HDA_CODEC_ENTRY(0x11d4194b, "AD1984B", patch_ad1884),
HDA_CODEC_ENTRY(0x11d41981, "AD1981", patch_ad1981),
HDA_CODEC_ENTRY(0x11d41983, "AD1983", patch_ad1983),
HDA_CODEC_ENTRY(0x11d41984, "AD1984", patch_ad1884),
HDA_CODEC_ENTRY(0x11d41986, "AD1986A", patch_ad1986a),
HDA_CODEC_ENTRY(0x11d41988, "AD1988", patch_ad1988),
HDA_CODEC_ENTRY(0x11d4198b, "AD1988B", patch_ad1988),
HDA_CODEC_ENTRY(0x11d4882a, "AD1882A", patch_ad1882),
HDA_CODEC_ENTRY(0x11d4989a, "AD1989A", patch_ad1988),
HDA_CODEC_ENTRY(0x11d4989b, "AD1989B", patch_ad1988),
{} /* terminator */
};

MODULE_ALIAS("snd-hda-codec-id:11d4*");
MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_analog);

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Analog Devices HD-audio codec");

static struct hda_codec_driver analog_driver = {
.preset = snd_hda_preset_analog,
.id = snd_hda_id_analog,
};

module_hda_codec_driver(analog_driver);
15 changes: 6 additions & 9 deletions sound/pci/hda/patch_ca0110.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,22 +83,19 @@ static int patch_ca0110(struct hda_codec *codec)
/*
* patch entries
*/
static const struct hda_codec_preset snd_hda_preset_ca0110[] = {
{ .id = 0x1102000a, .name = "CA0110-IBG", .patch = patch_ca0110 },
{ .id = 0x1102000b, .name = "CA0110-IBG", .patch = patch_ca0110 },
{ .id = 0x1102000d, .name = "SB0880 X-Fi", .patch = patch_ca0110 },
static const struct hda_device_id snd_hda_id_ca0110[] = {
HDA_CODEC_ENTRY(0x1102000a, "CA0110-IBG", patch_ca0110),
HDA_CODEC_ENTRY(0x1102000b, "CA0110-IBG", patch_ca0110),
HDA_CODEC_ENTRY(0x1102000d, "SB0880 X-Fi", patch_ca0110),
{} /* terminator */
};

MODULE_ALIAS("snd-hda-codec-id:1102000a");
MODULE_ALIAS("snd-hda-codec-id:1102000b");
MODULE_ALIAS("snd-hda-codec-id:1102000d");
MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_ca0110);

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Creative CA0110-IBG HD-audio codec");

static struct hda_codec_driver ca0110_driver = {
.preset = snd_hda_preset_ca0110,
.id = snd_hda_id_ca0110,
};

module_hda_codec_driver(ca0110_driver);
Loading

0 comments on commit c80a1da

Please sign in to comment.