cregit-Linux how code gets into the kernel

Release 4.8 sound/hda/hdac_sysfs.c

Directory: sound/hda
/*
 * sysfs support for HD-audio core device
 */

#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/device.h>
#include <sound/core.h>
#include <sound/hdaudio.h>
#include "local.h"


struct hdac_widget_tree {
	
struct kobject *root;
	
struct kobject *afg;
	
struct kobject **nodes;
};


#define CODEC_ATTR(type)					\
static ssize_t type##_show(struct device *dev,                  \
                           struct device_attribute *attr,       \
                           char *buf)                           \
{                                                               \
        struct hdac_device *codec = dev_to_hdac_dev(dev);       \
        return sprintf(buf, "0x%x\n", codec->type);             \
} \
static DEVICE_ATTR_RO(type)


#define CODEC_ATTR_STR(type)					\
static ssize_t type##_show(struct device *dev,                  \
                             struct device_attribute *attr,     \
                                        char *buf)              \
{                                                               \
        struct hdac_device *codec = dev_to_hdac_dev(dev);       \
        return sprintf(buf, "%s\n",                             \
                       codec->type ? codec->type : "");         \
} \
static DEVICE_ATTR_RO(type)


CODEC_ATTR(type);

CODEC_ATTR(vendor_id);

CODEC_ATTR(subsystem_id);

CODEC_ATTR(revision_id);

CODEC_ATTR(afg);

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); }

Contributors

PersonTokensPropCommitsCommitProp
subhransu s. prustysubhransu s. prusty33100.00%1100.00%
Total33100.00%1100.00%

static DEVICE_ATTR_RO(modalias); static struct attribute *hdac_dev_attrs[] = { &dev_attr_type.attr, &dev_attr_vendor_id.attr, &dev_attr_subsystem_id.attr, &dev_attr_revision_id.attr, &dev_attr_afg.attr, &dev_attr_mfg.attr, &dev_attr_vendor_name.attr, &dev_attr_chip_name.attr, &dev_attr_modalias.attr, NULL }; static struct attribute_group hdac_dev_attr_group = { .attrs = hdac_dev_attrs, }; const struct attribute_group *hdac_dev_attr_groups[] = { &hdac_dev_attr_group, NULL }; /* * Widget tree sysfs * * This is a tree showing the attributes of each widget. It appears like * /sys/bus/hdaudioC0D0/widgets/04/caps */ struct widget_attribute; struct widget_attribute { struct attribute attr; ssize_t (*show)(struct hdac_device *codec, hda_nid_t nid, struct widget_attribute *attr, char *buf); ssize_t (*store)(struct hdac_device *codec, hda_nid_t nid, struct widget_attribute *attr, const char *buf, size_t count); };
static int get_codec_nid(struct kobject *kobj, struct hdac_device **codecp) { struct device *dev = kobj_to_dev(kobj->parent->parent); int nid; ssize_t ret; ret = kstrtoint(kobj->name, 16, &nid); if (ret < 0) return ret; *codecp = dev_to_hdac_dev(dev); return nid; }

Contributors

PersonTokensPropCommitsCommitProp
takashi iwaitakashi iwai71100.00%1100.00%
Total71100.00%1100.00%


static ssize_t widget_attr_show(struct kobject *kobj, struct attribute *attr, char *buf) { struct widget_attribute *wid_attr = container_of(attr, struct widget_attribute, attr); struct hdac_device *codec; int nid; if (!wid_attr->show) return -EIO; nid = get_codec_nid(kobj, &codec); if (nid < 0) return nid; return wid_attr->show(codec, nid, wid_attr, buf); }

Contributors

PersonTokensPropCommitsCommitProp
takashi iwaitakashi iwai87100.00%1100.00%
Total87100.00%1100.00%


static ssize_t widget_attr_store(struct kobject *kobj, struct attribute *attr, const char *buf, size_t count) { struct widget_attribute *wid_attr = container_of(attr, struct widget_attribute, attr); struct hdac_device *codec; int nid; if (!wid_attr->store) return -EIO; nid = get_codec_nid(kobj, &codec); if (nid < 0) return nid; return wid_attr->store(codec, nid, wid_attr, buf, count); }

Contributors

PersonTokensPropCommitsCommitProp
takashi iwaitakashi iwai93100.00%1100.00%
Total93100.00%1100.00%

static const struct sysfs_ops widget_sysfs_ops = { .show = widget_attr_show, .store = widget_attr_store, };
static void widget_release(struct kobject *kobj) { kfree(kobj); }

Contributors

PersonTokensPropCommitsCommitProp
takashi iwaitakashi iwai16100.00%1100.00%
Total16100.00%1100.00%

static struct kobj_type widget_ktype = { .release = widget_release, .sysfs_ops = &widget_sysfs_ops, }; #define WIDGET_ATTR_RO(_name) \ struct widget_attribute wid_attr_##_name = __ATTR_RO(_name) #define WIDGET_ATTR_RW(_name) \ struct widget_attribute wid_attr_##_name = __ATTR_RW(_name)
static ssize_t caps_show(struct hdac_device *codec, hda_nid_t nid, struct widget_attribute *attr, char *buf) { return sprintf(buf, "0x%08x\n", get_wcaps(codec, nid)); }

Contributors

PersonTokensPropCommitsCommitProp
takashi iwaitakashi iwai38100.00%1100.00%
Total38100.00%1100.00%


static ssize_t pin_caps_show(struct hdac_device *codec, hda_nid_t nid, struct widget_attribute *attr, char *buf) { if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_PIN) return 0; return sprintf(buf, "0x%08x\n", snd_hdac_read_parm(codec, nid, AC_PAR_PIN_CAP)); }

Contributors

PersonTokensPropCommitsCommitProp
takashi iwaitakashi iwai57100.00%1100.00%
Total57100.00%1100.00%


static ssize_t pin_cfg_show(struct hdac_device *codec, hda_nid_t nid, struct widget_attribute *attr, char *buf) { unsigned int val; if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_PIN) return 0; if (snd_hdac_read(codec, nid, AC_VERB_GET_CONFIG_DEFAULT, 0, &val)) return 0; return sprintf(buf, "0x%08x\n", val); }

Contributors

PersonTokensPropCommitsCommitProp
takashi iwaitakashi iwai73100.00%1100.00%
Total73100.00%1100.00%


static bool has_pcm_cap(struct hdac_device *codec, hda_nid_t nid) { if (nid == codec->afg || nid == codec->mfg) return true; switch (get_wcaps_type(get_wcaps(codec, nid))) { case AC_WID_AUD_OUT: case AC_WID_AUD_IN: return true; default: return false; } }

Contributors

PersonTokensPropCommitsCommitProp
takashi iwaitakashi iwai58100.00%1100.00%
Total58100.00%1100.00%


static ssize_t pcm_caps_show(struct hdac_device *codec, hda_nid_t nid, struct widget_attribute *attr, char *buf) { if (!has_pcm_cap(codec, nid)) return 0; return sprintf(buf, "0x%08x\n", snd_hdac_read_parm(codec, nid, AC_PAR_PCM)); }

Contributors

PersonTokensPropCommitsCommitProp
takashi iwaitakashi iwai53100.00%1100.00%
Total53100.00%1100.00%


static ssize_t pcm_formats_show(struct hdac_device *codec, hda_nid_t nid, struct widget_attribute *attr, char *buf) { if (!has_pcm_cap(codec, nid)) return 0; return sprintf(buf, "0x%08x\n", snd_hdac_read_parm(codec, nid, AC_PAR_STREAM)); }

Contributors

PersonTokensPropCommitsCommitProp
takashi iwaitakashi iwai53100.00%1100.00%
Total53100.00%1100.00%


static ssize_t amp_in_caps_show(struct hdac_device *codec, hda_nid_t nid, struct widget_attribute *attr, char *buf) { if (nid != codec->afg && !(get_wcaps(codec, nid) & AC_WCAP_IN_AMP)) return 0; return sprintf(buf, "0x%08x\n", snd_hdac_read_parm(codec, nid, AC_PAR_AMP_IN_CAP)); }

Contributors

PersonTokensPropCommitsCommitProp
takashi iwaitakashi iwai63100.00%1100.00%
Total63100.00%1100.00%


static ssize_t amp_out_caps_show(struct hdac_device *codec, hda_nid_t nid, struct widget_attribute *attr, char *buf) { if (nid != codec->afg && !(get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)) return 0; return sprintf(buf, "0x%08x\n", snd_hdac_read_parm(codec, nid, AC_PAR_AMP_OUT_CAP)); }

Contributors

PersonTokensPropCommitsCommitProp
takashi iwaitakashi iwai63100.00%1100.00%
Total63100.00%1100.00%


static ssize_t power_caps_show(struct hdac_device *codec, hda_nid_t nid, struct widget_attribute *attr, char *buf) { if (nid != codec->afg && !(get_wcaps(codec, nid) & AC_WCAP_POWER)) return 0; return sprintf(buf, "0x%08x\n", snd_hdac_read_parm(codec, nid, AC_PAR_POWER_STATE)); }

Contributors

PersonTokensPropCommitsCommitProp
takashi iwaitakashi iwai63100.00%1100.00%
Total63100.00%1100.00%


static ssize_t gpio_caps_show(struct hdac_device *codec, hda_nid_t nid, struct widget_attribute *attr, char *buf) { return sprintf(buf, "0x%08x\n", snd_hdac_read_parm(codec, nid, AC_PAR_GPIO_CAP)); }

Contributors

PersonTokensPropCommitsCommitProp
takashi iwaitakashi iwai40100.00%1100.00%
Total40100.00%1100.00%


static ssize_t connections_show(struct hdac_device *codec, hda_nid_t nid, struct widget_attribute *attr, char *buf) { hda_nid_t list[32]; int i, nconns; ssize_t ret = 0; nconns = snd_hdac_get_connections(codec, nid, list, ARRAY_SIZE(list)); if (nconns <= 0) return nconns; for (i = 0; i < nconns; i++) ret += sprintf(buf + ret, "%s0x%02x", i ? " " : "", list[i]); ret += sprintf(buf + ret, "\n"); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
takashi iwaitakashi iwai113100.00%1100.00%
Total113100.00%1100.00%

static WIDGET_ATTR_RO(caps); static WIDGET_ATTR_RO(pin_caps); static WIDGET_ATTR_RO(pin_cfg); static WIDGET_ATTR_RO(pcm_caps); static WIDGET_ATTR_RO(pcm_formats); static WIDGET_ATTR_RO(amp_in_caps); static WIDGET_ATTR_RO(amp_out_caps); static WIDGET_ATTR_RO(power_caps); static WIDGET_ATTR_RO(gpio_caps); static WIDGET_ATTR_RO(connections); static struct attribute *widget_node_attrs[] = { &wid_attr_caps.attr, &wid_attr_pin_caps.attr, &wid_attr_pin_cfg.attr, &wid_attr_pcm_caps.attr, &wid_attr_pcm_formats.attr, &wid_attr_amp_in_caps.attr, &wid_attr_amp_out_caps.attr, &wid_attr_power_caps.attr, &wid_attr_connections.attr, NULL, }; static struct attribute *widget_afg_attrs[] = { &wid_attr_pcm_caps.attr, &wid_attr_pcm_formats.attr, &wid_attr_amp_in_caps.attr, &wid_attr_amp_out_caps.attr, &wid_attr_power_caps.attr, &wid_attr_gpio_caps.attr, NULL, }; static const struct attribute_group widget_node_group = { .attrs = widget_node_attrs, }; static const struct attribute_group widget_afg_group = { .attrs = widget_afg_attrs, };
static void free_widget_node(struct kobject *kobj, const struct attribute_group *group) { if (kobj) { sysfs_remove_group(kobj, group); kobject_put(kobj); } }

Contributors

PersonTokensPropCommitsCommitProp
takashi iwaitakashi iwai35100.00%1100.00%
Total35100.00%1100.00%


static void widget_tree_free(struct hdac_device *codec) { struct hdac_widget_tree *tree = codec->widgets; struct kobject **p; if (!tree) return; free_widget_node(tree->afg, &widget_afg_group); if (tree->nodes) { for (p = tree->nodes; *p; p++) free_widget_node(*p, &widget_node_group); kfree(tree->nodes); } kobject_put(tree->root); kfree(tree); codec->widgets = NULL; }

Contributors

PersonTokensPropCommitsCommitProp
takashi iwaitakashi iwai98100.00%2100.00%
Total98100.00%2100.00%


static int add_widget_node(struct kobject *parent, hda_nid_t nid, const struct attribute_group *group, struct kobject **res) { struct kobject *kobj = kzalloc(sizeof(*kobj), GFP_KERNEL); int err; if (!kobj) return -ENOMEM; kobject_init(kobj, &widget_ktype); err = kobject_add(kobj, parent, "%02x", nid); if (err < 0) return err; err = sysfs_create_group(kobj, group); if (err < 0) { kobject_put(kobj); return err; } *res = kobj; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
takashi iwaitakashi iwai117100.00%1100.00%
Total117100.00%1100.00%


static int widget_tree_create(struct hdac_device *codec) { struct hdac_widget_tree *tree; int i, err; hda_nid_t nid; tree = codec->widgets = kzalloc(sizeof(*tree), GFP_KERNEL); if (!tree) return -ENOMEM; tree->root = kobject_create_and_add("widgets", &codec->dev.kobj); if (!tree->root) return -ENOMEM; tree->nodes = kcalloc(codec->num_nodes + 1, sizeof(*tree->nodes), GFP_KERNEL); if (!tree->nodes) return -ENOMEM; for (i = 0, nid = codec->start_nid; i < codec->num_nodes; i++, nid++) { err = add_widget_node(tree->root, nid, &widget_node_group, &tree->nodes[i]); if (err < 0) return err; } if (codec->afg) { err = add_widget_node(tree->root, codec->afg, &widget_afg_group, &tree->afg); if (err < 0) return err; } kobject_uevent(tree->root, KOBJ_CHANGE); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
takashi iwaitakashi iwai218100.00%2100.00%
Total218100.00%2100.00%


int hda_widget_sysfs_init(struct hdac_device *codec) { int err; if (codec->widgets) return 0; /* already created */ err = widget_tree_create(codec); if (err < 0) { widget_tree_free(codec); return err; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
takashi iwaitakashi iwai49100.00%2100.00%
Total49100.00%2100.00%


void hda_widget_sysfs_exit(struct hdac_device *codec) { widget_tree_free(codec); }

Contributors

PersonTokensPropCommitsCommitProp
takashi iwaitakashi iwai15100.00%1100.00%
Total15100.00%1100.00%


Overall Contributors

PersonTokensPropCommitsCommitProp
takashi iwaitakashi iwai194697.79%480.00%
subhransu s. prustysubhransu s. prusty442.21%120.00%
Total1990100.00%5100.00%
Directory: sound/hda
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.