ALSA: hda - Add sysfs entries to hwdep devices
Added the sysfs entries to hwdep devices so that the new features like reconfiguration can be done via sysfs. Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
@@ -393,6 +393,20 @@ static int snd_hda_bus_dev_free(struct snd_device *device)
|
|||||||
return snd_hda_bus_free(bus);
|
return snd_hda_bus_free(bus);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_SND_HDA_HWDEP
|
||||||
|
static int snd_hda_bus_dev_register(struct snd_device *device)
|
||||||
|
{
|
||||||
|
struct hda_bus *bus = device->device_data;
|
||||||
|
struct hda_codec *codec;
|
||||||
|
list_for_each_entry(codec, &bus->codec_list, list) {
|
||||||
|
snd_hda_hwdep_add_sysfs(codec);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#define snd_hda_bus_dev_register NULL
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* snd_hda_bus_new - create a HDA bus
|
* snd_hda_bus_new - create a HDA bus
|
||||||
* @card: the card entry
|
* @card: the card entry
|
||||||
@@ -408,6 +422,7 @@ int __devinit snd_hda_bus_new(struct snd_card *card,
|
|||||||
struct hda_bus *bus;
|
struct hda_bus *bus;
|
||||||
int err;
|
int err;
|
||||||
static struct snd_device_ops dev_ops = {
|
static struct snd_device_ops dev_ops = {
|
||||||
|
.dev_register = snd_hda_bus_dev_register,
|
||||||
.dev_free = snd_hda_bus_dev_free,
|
.dev_free = snd_hda_bus_dev_free,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -686,9 +701,7 @@ int __devinit snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
|
|||||||
}
|
}
|
||||||
snd_hda_codec_proc_new(codec);
|
snd_hda_codec_proc_new(codec);
|
||||||
|
|
||||||
#ifdef CONFIG_SND_HDA_HWDEP
|
|
||||||
snd_hda_create_hwdep(codec);
|
snd_hda_create_hwdep(codec);
|
||||||
#endif
|
|
||||||
|
|
||||||
sprintf(component, "HDA:%08x,%08x,%08x", codec->vendor_id,
|
sprintf(component, "HDA:%08x,%08x,%08x", codec->vendor_id,
|
||||||
codec->subsystem_id, codec->revision_id);
|
codec->subsystem_id, codec->revision_id);
|
||||||
|
@@ -27,6 +27,7 @@
|
|||||||
#include "hda_codec.h"
|
#include "hda_codec.h"
|
||||||
#include "hda_local.h"
|
#include "hda_local.h"
|
||||||
#include <sound/hda_hwdep.h>
|
#include <sound/hda_hwdep.h>
|
||||||
|
#include <sound/minors.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* write/read an out-of-bound verb
|
* write/read an out-of-bound verb
|
||||||
@@ -119,3 +120,159 @@ int __devinit snd_hda_create_hwdep(struct hda_codec *codec)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* sysfs interface
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int clear_codec(struct hda_codec *codec)
|
||||||
|
{
|
||||||
|
snd_hda_codec_reset(codec);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int reconfig_codec(struct hda_codec *codec)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
snd_printk(KERN_INFO "hda-codec: reconfiguring\n");
|
||||||
|
snd_hda_codec_reset(codec);
|
||||||
|
err = snd_hda_codec_configure(codec);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
/* rebuild PCMs */
|
||||||
|
err = snd_hda_build_pcms(codec->bus);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
/* rebuild mixers */
|
||||||
|
err = snd_hda_codec_build_controls(codec);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* allocate a string at most len chars, and remove the trailing EOL
|
||||||
|
*/
|
||||||
|
static char *kstrndup_noeol(const char *src, size_t len)
|
||||||
|
{
|
||||||
|
char *s = kstrndup(src, len, GFP_KERNEL);
|
||||||
|
char *p;
|
||||||
|
if (!s)
|
||||||
|
return NULL;
|
||||||
|
p = strchr(s, '\n');
|
||||||
|
if (p)
|
||||||
|
*p = 0;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define CODEC_INFO_SHOW(type) \
|
||||||
|
static ssize_t type##_show(struct device *dev, \
|
||||||
|
struct device_attribute *attr, \
|
||||||
|
char *buf) \
|
||||||
|
{ \
|
||||||
|
struct snd_hwdep *hwdep = dev_get_drvdata(dev); \
|
||||||
|
struct hda_codec *codec = hwdep->private_data; \
|
||||||
|
return sprintf(buf, "0x%x\n", codec->type); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define CODEC_INFO_STR_SHOW(type) \
|
||||||
|
static ssize_t type##_show(struct device *dev, \
|
||||||
|
struct device_attribute *attr, \
|
||||||
|
char *buf) \
|
||||||
|
{ \
|
||||||
|
struct snd_hwdep *hwdep = dev_get_drvdata(dev); \
|
||||||
|
struct hda_codec *codec = hwdep->private_data; \
|
||||||
|
return sprintf(buf, "%s\n", \
|
||||||
|
codec->type ? codec->type : ""); \
|
||||||
|
}
|
||||||
|
|
||||||
|
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(name);
|
||||||
|
CODEC_INFO_STR_SHOW(modelname);
|
||||||
|
|
||||||
|
#define CODEC_INFO_STORE(type) \
|
||||||
|
static ssize_t type##_store(struct device *dev, \
|
||||||
|
struct device_attribute *attr, \
|
||||||
|
const char *buf, size_t count) \
|
||||||
|
{ \
|
||||||
|
struct snd_hwdep *hwdep = dev_get_drvdata(dev); \
|
||||||
|
struct hda_codec *codec = hwdep->private_data; \
|
||||||
|
char *after; \
|
||||||
|
codec->type = simple_strtoul(buf, &after, 0); \
|
||||||
|
return count; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define CODEC_INFO_STR_STORE(type) \
|
||||||
|
static ssize_t type##_store(struct device *dev, \
|
||||||
|
struct device_attribute *attr, \
|
||||||
|
const char *buf, size_t count) \
|
||||||
|
{ \
|
||||||
|
struct snd_hwdep *hwdep = dev_get_drvdata(dev); \
|
||||||
|
struct hda_codec *codec = hwdep->private_data; \
|
||||||
|
char *s = kstrndup_noeol(buf, 64); \
|
||||||
|
if (!s) \
|
||||||
|
return -ENOMEM; \
|
||||||
|
kfree(codec->type); \
|
||||||
|
codec->type = s; \
|
||||||
|
return count; \
|
||||||
|
}
|
||||||
|
|
||||||
|
CODEC_INFO_STORE(vendor_id);
|
||||||
|
CODEC_INFO_STORE(subsystem_id);
|
||||||
|
CODEC_INFO_STORE(revision_id);
|
||||||
|
CODEC_INFO_STR_STORE(name);
|
||||||
|
CODEC_INFO_STR_STORE(modelname);
|
||||||
|
|
||||||
|
#define CODEC_ACTION_STORE(type) \
|
||||||
|
static ssize_t type##_store(struct device *dev, \
|
||||||
|
struct device_attribute *attr, \
|
||||||
|
const char *buf, size_t count) \
|
||||||
|
{ \
|
||||||
|
struct snd_hwdep *hwdep = dev_get_drvdata(dev); \
|
||||||
|
struct hda_codec *codec = hwdep->private_data; \
|
||||||
|
int err = 0; \
|
||||||
|
if (*buf) \
|
||||||
|
err = type##_codec(codec); \
|
||||||
|
return err < 0 ? err : count; \
|
||||||
|
}
|
||||||
|
|
||||||
|
CODEC_ACTION_STORE(reconfig);
|
||||||
|
CODEC_ACTION_STORE(clear);
|
||||||
|
|
||||||
|
#define CODEC_ATTR_RW(type) \
|
||||||
|
__ATTR(type, 0644, type##_show, type##_store)
|
||||||
|
#define CODEC_ATTR_RO(type) \
|
||||||
|
__ATTR_RO(type)
|
||||||
|
#define CODEC_ATTR_WO(type) \
|
||||||
|
__ATTR(type, 0200, NULL, type##_store)
|
||||||
|
|
||||||
|
static struct device_attribute codec_attrs[] = {
|
||||||
|
CODEC_ATTR_RW(vendor_id),
|
||||||
|
CODEC_ATTR_RW(subsystem_id),
|
||||||
|
CODEC_ATTR_RW(revision_id),
|
||||||
|
CODEC_ATTR_RO(afg),
|
||||||
|
CODEC_ATTR_RO(mfg),
|
||||||
|
CODEC_ATTR_RW(name),
|
||||||
|
CODEC_ATTR_RW(modelname),
|
||||||
|
CODEC_ATTR_WO(reconfig),
|
||||||
|
CODEC_ATTR_WO(clear),
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* create sysfs files on hwdep directory
|
||||||
|
*/
|
||||||
|
int snd_hda_hwdep_add_sysfs(struct hda_codec *codec)
|
||||||
|
{
|
||||||
|
struct snd_hwdep *hwdep = codec->hwdep;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(codec_attrs); i++)
|
||||||
|
snd_add_device_sysfs_file(SNDRV_DEVICE_TYPE_HWDEP, hwdep->card,
|
||||||
|
hwdep->device, &codec_attrs[i]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@@ -401,7 +401,12 @@ void snd_hda_ctls_clear(struct hda_codec *codec);
|
|||||||
/*
|
/*
|
||||||
* hwdep interface
|
* hwdep interface
|
||||||
*/
|
*/
|
||||||
|
#ifdef CONFIG_SND_HDA_HWDEP
|
||||||
int snd_hda_create_hwdep(struct hda_codec *codec);
|
int snd_hda_create_hwdep(struct hda_codec *codec);
|
||||||
|
int snd_hda_hwdep_add_sysfs(struct hda_codec *codec);
|
||||||
|
#else
|
||||||
|
static inline int snd_hda_create_hwdep(struct hda_codec *codec) { return 0; }
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* power-management
|
* power-management
|
||||||
|
Reference in New Issue
Block a user