aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2008-07-30 09:01:46 -0400
committerTakashi Iwai <tiwai@suse.de>2008-10-12 20:43:03 -0400
commit11aeff082ad9bd00e8475bf1630c3264344d3764 (patch)
treefc00a9f4ccaa392032f09acbbd7d460f2e4d17de /sound/pci
parentd7ffba19ce4c1b153d502a89d829400bf76d6c11 (diff)
ALSA: hda - Add init_verbs entries
This patch enables the additional init verbs for each codec. The verbs can be entered via hwdep sysfs file. These verbs are executed at reconfiguring the codec for non-standard setups like overriding the pin-defcfg. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci')
-rw-r--r--sound/pci/hda/hda_codec.c13
-rw-r--r--sound/pci/hda/hda_codec.h3
-rw-r--r--sound/pci/hda/hda_hwdep.c37
3 files changed, 53 insertions, 0 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 0741eda78a5e..9a8adc600a57 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -1941,6 +1941,17 @@ static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
1941 } 1941 }
1942} 1942}
1943 1943
1944#ifdef CONFIG_SND_HDA_HWDEP
1945/* execute additional init verbs */
1946static void hda_exec_init_verbs(struct hda_codec *codec)
1947{
1948 if (codec->init_verbs.list)
1949 snd_hda_sequence_write(codec, codec->init_verbs.list);
1950}
1951#else
1952static inline void hda_exec_init_verbs(struct hda_codec *codec) {}
1953#endif
1954
1944#ifdef SND_HDA_NEEDS_RESUME 1955#ifdef SND_HDA_NEEDS_RESUME
1945/* 1956/*
1946 * call suspend and power-down; used both from PM and power-save 1957 * call suspend and power-down; used both from PM and power-save
@@ -1967,6 +1978,7 @@ static void hda_call_codec_resume(struct hda_codec *codec)
1967 hda_set_power_state(codec, 1978 hda_set_power_state(codec,
1968 codec->afg ? codec->afg : codec->mfg, 1979 codec->afg ? codec->afg : codec->mfg,
1969 AC_PWRST_D0); 1980 AC_PWRST_D0);
1981 hda_exec_init_verbs(codec);
1970 if (codec->patch_ops.resume) 1982 if (codec->patch_ops.resume)
1971 codec->patch_ops.resume(codec); 1983 codec->patch_ops.resume(codec);
1972 else { 1984 else {
@@ -2008,6 +2020,7 @@ int snd_hda_codec_build_controls(struct hda_codec *codec)
2008 hda_set_power_state(codec, 2020 hda_set_power_state(codec,
2009 codec->afg ? codec->afg : codec->mfg, 2021 codec->afg ? codec->afg : codec->mfg,
2010 AC_PWRST_D0); 2022 AC_PWRST_D0);
2023 hda_exec_init_verbs(codec);
2011 /* continue to initialize... */ 2024 /* continue to initialize... */
2012 if (codec->patch_ops.init) 2025 if (codec->patch_ops.init)
2013 err = codec->patch_ops.init(codec); 2026 err = codec->patch_ops.init(codec);
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index ce9f69bde328..38a9bb6bafb0 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -751,7 +751,10 @@ struct hda_codec {
751 unsigned int spdif_in_enable; /* SPDIF input enable? */ 751 unsigned int spdif_in_enable; /* SPDIF input enable? */
752 hda_nid_t *slave_dig_outs; /* optional digital out slave widgets */ 752 hda_nid_t *slave_dig_outs; /* optional digital out slave widgets */
753 753
754#ifdef CONFIG_SND_HDA_HWDEP
754 struct snd_hwdep *hwdep; /* assigned hwdep device */ 755 struct snd_hwdep *hwdep; /* assigned hwdep device */
756 struct snd_array init_verbs; /* additional init verbs */
757#endif
755 758
756 /* misc flags */ 759 /* misc flags */
757 unsigned int spdif_status_reset :1; /* needs to toggle SPDIF for each 760 unsigned int spdif_status_reset :1; /* needs to toggle SPDIF for each
diff --git a/sound/pci/hda/hda_hwdep.c b/sound/pci/hda/hda_hwdep.c
index 214772c8b556..f3400d75eba4 100644
--- a/sound/pci/hda/hda_hwdep.c
+++ b/sound/pci/hda/hda_hwdep.c
@@ -96,6 +96,17 @@ static int hda_hwdep_open(struct snd_hwdep *hw, struct file *file)
96 return 0; 96 return 0;
97} 97}
98 98
99static void clear_hwdep_elements(struct hda_codec *codec)
100{
101 /* clear init verbs */
102 snd_array_free(&codec->init_verbs);
103}
104
105static void hwdep_free(struct snd_hwdep *hwdep)
106{
107 clear_hwdep_elements(hwdep->private_data);
108}
109
99int __devinit snd_hda_create_hwdep(struct hda_codec *codec) 110int __devinit snd_hda_create_hwdep(struct hda_codec *codec)
100{ 111{
101 char hwname[16]; 112 char hwname[16];
@@ -110,6 +121,7 @@ int __devinit snd_hda_create_hwdep(struct hda_codec *codec)
110 sprintf(hwdep->name, "HDA Codec %d", codec->addr); 121 sprintf(hwdep->name, "HDA Codec %d", codec->addr);
111 hwdep->iface = SNDRV_HWDEP_IFACE_HDA; 122 hwdep->iface = SNDRV_HWDEP_IFACE_HDA;
112 hwdep->private_data = codec; 123 hwdep->private_data = codec;
124 hwdep->private_free = hwdep_free;
113 hwdep->exclusive = 1; 125 hwdep->exclusive = 1;
114 126
115 hwdep->ops.open = hda_hwdep_open; 127 hwdep->ops.open = hda_hwdep_open;
@@ -118,6 +130,8 @@ int __devinit snd_hda_create_hwdep(struct hda_codec *codec)
118 hwdep->ops.ioctl_compat = hda_hwdep_ioctl_compat; 130 hwdep->ops.ioctl_compat = hda_hwdep_ioctl_compat;
119#endif 131#endif
120 132
133 snd_array_init(&codec->init_verbs, sizeof(struct hda_verb), 32);
134
121 return 0; 135 return 0;
122} 136}
123 137
@@ -128,6 +142,7 @@ int __devinit snd_hda_create_hwdep(struct hda_codec *codec)
128static int clear_codec(struct hda_codec *codec) 142static int clear_codec(struct hda_codec *codec)
129{ 143{
130 snd_hda_codec_reset(codec); 144 snd_hda_codec_reset(codec);
145 clear_hwdep_elements(codec);
131 return 0; 146 return 0;
132} 147}
133 148
@@ -244,6 +259,27 @@ static ssize_t type##_store(struct device *dev, \
244CODEC_ACTION_STORE(reconfig); 259CODEC_ACTION_STORE(reconfig);
245CODEC_ACTION_STORE(clear); 260CODEC_ACTION_STORE(clear);
246 261
262static ssize_t init_verbs_store(struct device *dev,
263 struct device_attribute *attr,
264 const char *buf, size_t count)
265{
266 struct snd_hwdep *hwdep = dev_get_drvdata(dev);
267 struct hda_codec *codec = hwdep->private_data;
268 char *p;
269 struct hda_verb verb, *v;
270
271 verb.nid = simple_strtoul(buf, &p, 0);
272 verb.verb = simple_strtoul(p, &p, 0);
273 verb.param = simple_strtoul(p, &p, 0);
274 if (!verb.nid || !verb.verb || !verb.param)
275 return -EINVAL;
276 v = snd_array_new(&codec->init_verbs);
277 if (!v)
278 return -ENOMEM;
279 *v = verb;
280 return count;
281}
282
247#define CODEC_ATTR_RW(type) \ 283#define CODEC_ATTR_RW(type) \
248 __ATTR(type, 0644, type##_show, type##_store) 284 __ATTR(type, 0644, type##_show, type##_store)
249#define CODEC_ATTR_RO(type) \ 285#define CODEC_ATTR_RO(type) \
@@ -259,6 +295,7 @@ static struct device_attribute codec_attrs[] = {
259 CODEC_ATTR_RO(mfg), 295 CODEC_ATTR_RO(mfg),
260 CODEC_ATTR_RW(name), 296 CODEC_ATTR_RW(name),
261 CODEC_ATTR_RW(modelname), 297 CODEC_ATTR_RW(modelname),
298 CODEC_ATTR_WO(init_verbs),
262 CODEC_ATTR_WO(reconfig), 299 CODEC_ATTR_WO(reconfig),
263 CODEC_ATTR_WO(clear), 300 CODEC_ATTR_WO(clear),
264}; 301};