^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * sysfs interface for HD-audio codec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 2014 Takashi Iwai <tiwai@suse.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * split from hda_hwdep.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/compat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/ctype.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <sound/core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <sound/hda_codec.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include "hda_local.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <sound/hda_hwdep.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <sound/minors.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) /* hint string pair */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) struct hda_hint {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) const char *key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) const char *val; /* contained in the same alloc as key */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #ifdef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) static ssize_t power_on_acct_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) struct hda_codec *codec = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) snd_hda_update_power_acct(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) return sprintf(buf, "%u\n", jiffies_to_msecs(codec->power_on_acct));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) static ssize_t power_off_acct_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) struct hda_codec *codec = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) snd_hda_update_power_acct(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) return sprintf(buf, "%u\n", jiffies_to_msecs(codec->power_off_acct));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) static DEVICE_ATTR_RO(power_on_acct);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) static DEVICE_ATTR_RO(power_off_acct);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #endif /* CONFIG_PM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define CODEC_INFO_SHOW(type, field) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) static ssize_t type##_show(struct device *dev, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) struct device_attribute *attr, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) char *buf) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) struct hda_codec *codec = dev_get_drvdata(dev); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) return sprintf(buf, "0x%x\n", codec->field); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define CODEC_INFO_STR_SHOW(type, field) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) static ssize_t type##_show(struct device *dev, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) struct device_attribute *attr, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) char *buf) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) struct hda_codec *codec = dev_get_drvdata(dev); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) return sprintf(buf, "%s\n", \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) codec->field ? codec->field : ""); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) CODEC_INFO_SHOW(vendor_id, core.vendor_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) CODEC_INFO_SHOW(subsystem_id, core.subsystem_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) CODEC_INFO_SHOW(revision_id, core.revision_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) CODEC_INFO_SHOW(afg, core.afg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) CODEC_INFO_SHOW(mfg, core.mfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) CODEC_INFO_STR_SHOW(vendor_name, core.vendor_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) CODEC_INFO_STR_SHOW(chip_name, core.chip_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) CODEC_INFO_STR_SHOW(modelname, modelname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) static ssize_t pin_configs_show(struct hda_codec *codec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) struct snd_array *list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) const struct hda_pincfg *pin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) int i, len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) mutex_lock(&codec->user_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) snd_array_for_each(list, i, pin) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) len += sprintf(buf + len, "0x%02x 0x%08x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) pin->nid, pin->cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) mutex_unlock(&codec->user_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) static ssize_t init_pin_configs_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) struct hda_codec *codec = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) return pin_configs_show(codec, &codec->init_pins, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) static ssize_t driver_pin_configs_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) struct hda_codec *codec = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) return pin_configs_show(codec, &codec->driver_pins, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) #ifdef CONFIG_SND_HDA_RECONFIG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) * sysfs interface
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) static int clear_codec(struct hda_codec *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) err = snd_hda_codec_reset(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) codec_err(codec, "The codec is being used, can't free.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) snd_hda_sysfs_clear(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) static int reconfig_codec(struct hda_codec *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) snd_hda_power_up(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) codec_info(codec, "hda-codec: reconfiguring\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) err = snd_hda_codec_reset(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) codec_err(codec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) "The codec is being used, can't reconfigure.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) err = device_reprobe(hda_codec_dev(codec));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) err = snd_card_register(codec->card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) snd_hda_power_down(codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) * allocate a string at most len chars, and remove the trailing EOL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) static char *kstrndup_noeol(const char *src, size_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) char *s = kstrndup(src, len, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) char *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) if (!s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) p = strchr(s, '\n');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) if (p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) *p = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) return s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) #define CODEC_INFO_STORE(type, field) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) static ssize_t type##_store(struct device *dev, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) struct device_attribute *attr, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) const char *buf, size_t count) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) struct hda_codec *codec = dev_get_drvdata(dev); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) unsigned long val; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) int err = kstrtoul(buf, 0, &val); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) if (err < 0) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) return err; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) codec->field = val; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) return count; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) #define CODEC_INFO_STR_STORE(type, field) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) static ssize_t type##_store(struct device *dev, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) struct device_attribute *attr, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) const char *buf, size_t count) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) struct hda_codec *codec = dev_get_drvdata(dev); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) char *s = kstrndup_noeol(buf, 64); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) if (!s) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) return -ENOMEM; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) kfree(codec->field); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) codec->field = s; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) return count; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) CODEC_INFO_STORE(vendor_id, core.vendor_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) CODEC_INFO_STORE(subsystem_id, core.subsystem_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) CODEC_INFO_STORE(revision_id, core.revision_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) CODEC_INFO_STR_STORE(vendor_name, core.vendor_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) CODEC_INFO_STR_STORE(chip_name, core.chip_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) CODEC_INFO_STR_STORE(modelname, modelname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) #define CODEC_ACTION_STORE(type) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) static ssize_t type##_store(struct device *dev, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) struct device_attribute *attr, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) const char *buf, size_t count) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) struct hda_codec *codec = dev_get_drvdata(dev); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) int err = 0; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) if (*buf) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) err = type##_codec(codec); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) return err < 0 ? err : count; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) CODEC_ACTION_STORE(reconfig);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) CODEC_ACTION_STORE(clear);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) static ssize_t init_verbs_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) struct hda_codec *codec = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) const struct hda_verb *v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) int i, len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) mutex_lock(&codec->user_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) snd_array_for_each(&codec->init_verbs, i, v) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) len += scnprintf(buf + len, PAGE_SIZE - len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) "0x%02x 0x%03x 0x%04x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) v->nid, v->verb, v->param);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) mutex_unlock(&codec->user_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) static int parse_init_verbs(struct hda_codec *codec, const char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) struct hda_verb *v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) int nid, verb, param;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) if (sscanf(buf, "%i %i %i", &nid, &verb, ¶m) != 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) if (!nid || !verb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) mutex_lock(&codec->user_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) v = snd_array_new(&codec->init_verbs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) if (!v) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) mutex_unlock(&codec->user_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) v->nid = nid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) v->verb = verb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) v->param = param;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) mutex_unlock(&codec->user_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) static ssize_t init_verbs_store(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) struct hda_codec *codec = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) int err = parse_init_verbs(codec, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) static ssize_t hints_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) struct hda_codec *codec = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) const struct hda_hint *hint;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) int i, len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) mutex_lock(&codec->user_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) snd_array_for_each(&codec->hints, i, hint) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) len += scnprintf(buf + len, PAGE_SIZE - len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) "%s = %s\n", hint->key, hint->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) mutex_unlock(&codec->user_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) static struct hda_hint *get_hint(struct hda_codec *codec, const char *key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) struct hda_hint *hint;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) snd_array_for_each(&codec->hints, i, hint) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) if (!strcmp(hint->key, key))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) return hint;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) static void remove_trail_spaces(char *str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) char *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) if (!*str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) p = str + strlen(str) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) for (; isspace(*p); p--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) *p = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) if (p == str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) #define MAX_HINTS 1024
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) static int parse_hints(struct hda_codec *codec, const char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) char *key, *val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) struct hda_hint *hint;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) buf = skip_spaces(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) if (!*buf || *buf == '#' || *buf == '\n')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) if (*buf == '=')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) key = kstrndup_noeol(buf, 1024);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) if (!key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) /* extract key and val */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) val = strchr(key, '=');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) if (!val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) kfree(key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) *val++ = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) val = skip_spaces(val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) remove_trail_spaces(key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) remove_trail_spaces(val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) mutex_lock(&codec->user_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) hint = get_hint(codec, key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) if (hint) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) /* replace */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) kfree(hint->key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) hint->key = key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) hint->val = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) goto unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) /* allocate a new hint entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) if (codec->hints.used >= MAX_HINTS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) hint = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) hint = snd_array_new(&codec->hints);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) if (hint) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) hint->key = key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) hint->val = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) mutex_unlock(&codec->user_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) kfree(key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) static ssize_t hints_store(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) struct hda_codec *codec = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) int err = parse_hints(codec, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) static ssize_t user_pin_configs_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) struct hda_codec *codec = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) return pin_configs_show(codec, &codec->user_pins, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) #define MAX_PIN_CONFIGS 32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) static int parse_user_pin_configs(struct hda_codec *codec, const char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) int nid, cfg, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) if (sscanf(buf, "%i %i", &nid, &cfg) != 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) if (!nid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) mutex_lock(&codec->user_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) err = snd_hda_add_pincfg(codec, &codec->user_pins, nid, cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) mutex_unlock(&codec->user_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) static ssize_t user_pin_configs_store(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) struct hda_codec *codec = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) int err = parse_user_pin_configs(codec, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) /* sysfs attributes exposed only when CONFIG_SND_HDA_RECONFIG=y */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) static DEVICE_ATTR_RW(init_verbs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) static DEVICE_ATTR_RW(hints);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) static DEVICE_ATTR_RW(user_pin_configs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) static DEVICE_ATTR_WO(reconfig);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) static DEVICE_ATTR_WO(clear);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) * snd_hda_get_hint - Look for hint string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) * @codec: the HDA codec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) * @key: the hint key string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) * Look for a hint key/value pair matching with the given key string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) * and returns the value string. If nothing found, returns NULL.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) const char *snd_hda_get_hint(struct hda_codec *codec, const char *key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) struct hda_hint *hint = get_hint(codec, key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) return hint ? hint->val : NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) EXPORT_SYMBOL_GPL(snd_hda_get_hint);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) * snd_hda_get_bool_hint - Get a boolean hint value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) * @codec: the HDA codec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) * @key: the hint key string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) * Look for a hint key/value pair matching with the given key string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) * and returns a boolean value parsed from the value. If no matching
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) * key is found, return a negative value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) int snd_hda_get_bool_hint(struct hda_codec *codec, const char *key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) const char *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) mutex_lock(&codec->user_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) p = snd_hda_get_hint(codec, key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) if (!p || !*p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) ret = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) switch (toupper(*p)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) case 'T': /* true */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) case 'Y': /* yes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) case '1':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) ret = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) mutex_unlock(&codec->user_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) EXPORT_SYMBOL_GPL(snd_hda_get_bool_hint);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) * snd_hda_get_int_hint - Get an integer hint value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) * @codec: the HDA codec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) * @key: the hint key string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) * @valp: pointer to store a value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) * Look for a hint key/value pair matching with the given key string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) * and stores the integer value to @valp. If no matching key is found,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) * return a negative error code. Otherwise it returns zero.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) int snd_hda_get_int_hint(struct hda_codec *codec, const char *key, int *valp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) const char *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) unsigned long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) mutex_lock(&codec->user_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) p = snd_hda_get_hint(codec, key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) if (!p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) ret = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) else if (kstrtoul(p, 0, &val))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) *valp = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) mutex_unlock(&codec->user_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) EXPORT_SYMBOL_GPL(snd_hda_get_int_hint);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) #endif /* CONFIG_SND_HDA_RECONFIG */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) * common sysfs attributes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) #ifdef CONFIG_SND_HDA_RECONFIG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) #define RECONFIG_DEVICE_ATTR(name) DEVICE_ATTR_RW(name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) #define RECONFIG_DEVICE_ATTR(name) DEVICE_ATTR_RO(name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) static RECONFIG_DEVICE_ATTR(vendor_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) static RECONFIG_DEVICE_ATTR(subsystem_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) static RECONFIG_DEVICE_ATTR(revision_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) static DEVICE_ATTR_RO(afg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) static DEVICE_ATTR_RO(mfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) static RECONFIG_DEVICE_ATTR(vendor_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) static RECONFIG_DEVICE_ATTR(chip_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) static RECONFIG_DEVICE_ATTR(modelname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) static DEVICE_ATTR_RO(init_pin_configs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) static DEVICE_ATTR_RO(driver_pin_configs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) #ifdef CONFIG_SND_HDA_PATCH_LOADER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) /* parser mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) LINE_MODE_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) LINE_MODE_CODEC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) LINE_MODE_MODEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) LINE_MODE_PINCFG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) LINE_MODE_VERB,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) LINE_MODE_HINT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) LINE_MODE_VENDOR_ID,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) LINE_MODE_SUBSYSTEM_ID,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) LINE_MODE_REVISION_ID,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) LINE_MODE_CHIP_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) NUM_LINE_MODES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) static inline int strmatch(const char *a, const char *b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) return strncasecmp(a, b, strlen(b)) == 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) /* parse the contents after the line "[codec]"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) * accept only the line with three numbers, and assign the current codec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) static void parse_codec_mode(char *buf, struct hda_bus *bus,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) struct hda_codec **codecp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) int vendorid, subid, caddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) struct hda_codec *codec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) *codecp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) if (sscanf(buf, "%i %i %i", &vendorid, &subid, &caddr) == 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) list_for_each_codec(codec, bus) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) if ((vendorid <= 0 || codec->core.vendor_id == vendorid) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) (subid <= 0 || codec->core.subsystem_id == subid) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) codec->core.addr == caddr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) *codecp = codec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) /* parse the contents after the other command tags, [pincfg], [verb],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) * [vendor_id], [subsystem_id], [revision_id], [chip_name], [hint] and [model]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) * just pass to the sysfs helper (only when any codec was specified)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) static void parse_pincfg_mode(char *buf, struct hda_bus *bus,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) struct hda_codec **codecp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) parse_user_pin_configs(*codecp, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) static void parse_verb_mode(char *buf, struct hda_bus *bus,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) struct hda_codec **codecp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) parse_init_verbs(*codecp, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) static void parse_hint_mode(char *buf, struct hda_bus *bus,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) struct hda_codec **codecp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) parse_hints(*codecp, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) static void parse_model_mode(char *buf, struct hda_bus *bus,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) struct hda_codec **codecp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) kfree((*codecp)->modelname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) (*codecp)->modelname = kstrdup(buf, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) static void parse_chip_name_mode(char *buf, struct hda_bus *bus,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) struct hda_codec **codecp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) snd_hda_codec_set_name(*codecp, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) #define DEFINE_PARSE_ID_MODE(name) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) static void parse_##name##_mode(char *buf, struct hda_bus *bus, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) struct hda_codec **codecp) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) unsigned long val; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) if (!kstrtoul(buf, 0, &val)) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) (*codecp)->core.name = val; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) DEFINE_PARSE_ID_MODE(vendor_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) DEFINE_PARSE_ID_MODE(subsystem_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) DEFINE_PARSE_ID_MODE(revision_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) struct hda_patch_item {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) const char *tag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) const char *alias;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) void (*parser)(char *buf, struct hda_bus *bus, struct hda_codec **retc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) static const struct hda_patch_item patch_items[NUM_LINE_MODES] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) [LINE_MODE_CODEC] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) .tag = "[codec]",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) .parser = parse_codec_mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) [LINE_MODE_MODEL] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) .tag = "[model]",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) .parser = parse_model_mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) [LINE_MODE_VERB] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) .tag = "[verb]",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) .alias = "[init_verbs]",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) .parser = parse_verb_mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) [LINE_MODE_PINCFG] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) .tag = "[pincfg]",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) .alias = "[user_pin_configs]",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) .parser = parse_pincfg_mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) [LINE_MODE_HINT] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) .tag = "[hint]",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) .alias = "[hints]",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) .parser = parse_hint_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) [LINE_MODE_VENDOR_ID] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) .tag = "[vendor_id]",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) .parser = parse_vendor_id_mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) [LINE_MODE_SUBSYSTEM_ID] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) .tag = "[subsystem_id]",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) .parser = parse_subsystem_id_mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) [LINE_MODE_REVISION_ID] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) .tag = "[revision_id]",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) .parser = parse_revision_id_mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) [LINE_MODE_CHIP_NAME] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) .tag = "[chip_name]",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) .parser = parse_chip_name_mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) /* check the line starting with '[' -- change the parser mode accodingly */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) static int parse_line_mode(char *buf, struct hda_bus *bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) for (i = 0; i < ARRAY_SIZE(patch_items); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) if (!patch_items[i].tag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) if (strmatch(buf, patch_items[i].tag))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) return i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) if (patch_items[i].alias && strmatch(buf, patch_items[i].alias))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) return i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) return LINE_MODE_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) /* copy one line from the buffer in fw, and update the fields in fw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) * return zero if it reaches to the end of the buffer, or non-zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) * if successfully copied a line
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) * the spaces at the beginning and the end of the line are stripped
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) static int get_line_from_fw(char *buf, int size, size_t *fw_size_p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) const void **fw_data_p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) size_t fw_size = *fw_size_p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) const char *p = *fw_data_p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) while (isspace(*p) && fw_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) p++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) fw_size--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) if (!fw_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) for (len = 0; len < fw_size; len++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) if (!*p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) if (*p == '\n') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) p++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) len++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) if (len < size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) *buf++ = *p++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) *buf = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) *fw_size_p = fw_size - len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) *fw_data_p = p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) remove_trail_spaces(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) * snd_hda_load_patch - load a "patch" firmware file and parse it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) * @bus: HD-audio bus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) * @fw_size: the firmware byte size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) * @fw_buf: the firmware data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) int snd_hda_load_patch(struct hda_bus *bus, size_t fw_size, const void *fw_buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) char buf[128];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) struct hda_codec *codec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) int line_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) line_mode = LINE_MODE_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) codec = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) while (get_line_from_fw(buf, sizeof(buf) - 1, &fw_size, &fw_buf)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) if (!*buf || *buf == '#' || *buf == '\n')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) if (*buf == '[')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) line_mode = parse_line_mode(buf, bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) else if (patch_items[line_mode].parser &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) (codec || line_mode <= LINE_MODE_CODEC))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) patch_items[line_mode].parser(buf, bus, &codec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) EXPORT_SYMBOL_GPL(snd_hda_load_patch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) #endif /* CONFIG_SND_HDA_PATCH_LOADER */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) * sysfs entries
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) static struct attribute *hda_dev_attrs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) &dev_attr_vendor_id.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) &dev_attr_subsystem_id.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) &dev_attr_revision_id.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) &dev_attr_afg.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) &dev_attr_mfg.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) &dev_attr_vendor_name.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) &dev_attr_chip_name.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) &dev_attr_modelname.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) &dev_attr_init_pin_configs.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) &dev_attr_driver_pin_configs.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) #ifdef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) &dev_attr_power_on_acct.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) &dev_attr_power_off_acct.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) #ifdef CONFIG_SND_HDA_RECONFIG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) &dev_attr_init_verbs.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) &dev_attr_hints.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) &dev_attr_user_pin_configs.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) &dev_attr_reconfig.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) &dev_attr_clear.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) static const struct attribute_group hda_dev_attr_group = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) .attrs = hda_dev_attrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) const struct attribute_group *snd_hda_dev_attr_groups[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) &hda_dev_attr_group,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) void snd_hda_sysfs_init(struct hda_codec *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) mutex_init(&codec->user_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) #ifdef CONFIG_SND_HDA_RECONFIG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) snd_array_init(&codec->init_verbs, sizeof(struct hda_verb), 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) snd_array_init(&codec->hints, sizeof(struct hda_hint), 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) snd_array_init(&codec->user_pins, sizeof(struct hda_pincfg), 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) void snd_hda_sysfs_clear(struct hda_codec *codec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) #ifdef CONFIG_SND_HDA_RECONFIG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) struct hda_hint *hint;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) /* clear init verbs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) snd_array_free(&codec->init_verbs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) /* clear hints */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) snd_array_for_each(&codec->hints, i, hint) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) kfree(hint->key); /* we don't need to free hint->val */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) snd_array_free(&codec->hints);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) snd_array_free(&codec->user_pins);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) }