aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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};