Skip to content

Commit

Permalink
ALSA: hda - Add sysfs entries to hwdep devices
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Takashi Iwai committed Oct 13, 2008
1 parent 6c1f45e commit d7ffba1
Show file tree
Hide file tree
Showing 3 changed files with 177 additions and 2 deletions.
17 changes: 15 additions & 2 deletions sound/pci/hda/hda_codec.c
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,20 @@ static int snd_hda_bus_dev_free(struct snd_device *device)
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
* @card: the card entry
Expand All @@ -408,6 +422,7 @@ int __devinit snd_hda_bus_new(struct snd_card *card,
struct hda_bus *bus;
int err;
static struct snd_device_ops dev_ops = {
.dev_register = snd_hda_bus_dev_register,
.dev_free = snd_hda_bus_dev_free,
};

Expand Down Expand Up @@ -686,9 +701,7 @@ int __devinit snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
}
snd_hda_codec_proc_new(codec);

#ifdef CONFIG_SND_HDA_HWDEP
snd_hda_create_hwdep(codec);
#endif

sprintf(component, "HDA:%08x,%08x,%08x", codec->vendor_id,
codec->subsystem_id, codec->revision_id);
Expand Down
157 changes: 157 additions & 0 deletions sound/pci/hda/hda_hwdep.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "hda_codec.h"
#include "hda_local.h"
#include <sound/hda_hwdep.h>
#include <sound/minors.h>

/*
* write/read an out-of-bound verb
Expand Down Expand Up @@ -119,3 +120,159 @@ int __devinit snd_hda_create_hwdep(struct hda_codec *codec)

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;
}
5 changes: 5 additions & 0 deletions sound/pci/hda/hda_local.h
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,12 @@ void snd_hda_ctls_clear(struct hda_codec *codec);
/*
* hwdep interface
*/
#ifdef CONFIG_SND_HDA_HWDEP
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
Expand Down

0 comments on commit d7ffba1

Please sign in to comment.