aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2009-05-26 10:07:57 -0400
committerTakashi Iwai <tiwai@suse.de>2009-05-26 11:23:46 -0400
commitaa2936f5fe060e95ae06685149645b234085a468 (patch)
treec5f25beb1e9be3fc4560446992c7a021362b9c30 /sound/pci/hda
parent8174086167d43d0fd7b21928074145ae1d15bbab (diff)
ALSA: hda - Support sync after writing a verb
This patch adds a debug mode to make the codec communication synchronous. Define SND_HDA_SUPPORT_SYNC_WRITE in hda_codec.c, and the call of snd_hda_codec_write*() will become synchronous, i.e. wait for the reply from the codec at each time issuing a verb. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda')
-rw-r--r--sound/pci/hda/hda_codec.c113
1 files changed, 61 insertions, 52 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 77385de01744..d1d5fb9d7afb 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -158,6 +158,38 @@ make_codec_cmd(struct hda_codec *codec, hda_nid_t nid, int direct,
158 return val; 158 return val;
159} 159}
160 160
161/*
162 * Send and receive a verb
163 */
164static int codec_exec_verb(struct hda_codec *codec, unsigned int cmd,
165 unsigned int *res)
166{
167 struct hda_bus *bus = codec->bus;
168 int err, repeated = 0;
169
170 if (res)
171 *res = -1;
172 snd_hda_power_up(codec);
173 mutex_lock(&bus->cmd_mutex);
174 again:
175 err = bus->ops.command(bus, cmd);
176 if (!err) {
177 if (res) {
178 *res = bus->ops.get_response(bus);
179 if (*res == -1 && bus->rirb_error) {
180 if (repeated++ < 1) {
181 snd_printd(KERN_WARNING "hda_codec: "
182 "Trying verb 0x%08x again\n", cmd);
183 goto again;
184 }
185 }
186 }
187 }
188 mutex_unlock(&bus->cmd_mutex);
189 snd_hda_power_down(codec);
190 return err;
191}
192
161/** 193/**
162 * snd_hda_codec_read - send a command and get the response 194 * snd_hda_codec_read - send a command and get the response
163 * @codec: the HDA codec 195 * @codec: the HDA codec
@@ -174,31 +206,18 @@ unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid,
174 int direct, 206 int direct,
175 unsigned int verb, unsigned int parm) 207 unsigned int verb, unsigned int parm)
176{ 208{
177 struct hda_bus *bus = codec->bus; 209 unsigned cmd = make_codec_cmd(codec, nid, direct, verb, parm);
178 unsigned int cmd, res; 210 unsigned int res;
179 int repeated = 0; 211 codec_exec_verb(codec, cmd, &res);
180
181 cmd = make_codec_cmd(codec, nid, direct, verb, parm);
182 snd_hda_power_up(codec);
183 mutex_lock(&bus->cmd_mutex);
184 again:
185 if (!bus->ops.command(bus, cmd)) {
186 res = bus->ops.get_response(bus);
187 if (res == -1 && bus->rirb_error) {
188 if (repeated++ < 1) {
189 snd_printd(KERN_WARNING "hda_codec: "
190 "Trying verb 0x%08x again\n", cmd);
191 goto again;
192 }
193 }
194 } else
195 res = (unsigned int)-1;
196 mutex_unlock(&bus->cmd_mutex);
197 snd_hda_power_down(codec);
198 return res; 212 return res;
199} 213}
200EXPORT_SYMBOL_HDA(snd_hda_codec_read); 214EXPORT_SYMBOL_HDA(snd_hda_codec_read);
201 215
216/* Define the below to send and receive verbs synchronously.
217 * If you often get any codec communication errors, this is worth to try.
218 */
219/* #define SND_HDA_SUPPORT_SYNC_WRITE */
220
202/** 221/**
203 * snd_hda_codec_write - send a single command without waiting for response 222 * snd_hda_codec_write - send a single command without waiting for response
204 * @codec: the HDA codec 223 * @codec: the HDA codec
@@ -214,17 +233,13 @@ EXPORT_SYMBOL_HDA(snd_hda_codec_read);
214int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int direct, 233int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int direct,
215 unsigned int verb, unsigned int parm) 234 unsigned int verb, unsigned int parm)
216{ 235{
217 struct hda_bus *bus = codec->bus; 236 unsigned int cmd = make_codec_cmd(codec, nid, direct, verb, parm);
237#ifdef SND_HDA_SUPPORT_SYNC_WRITE
218 unsigned int res; 238 unsigned int res;
219 int err; 239 return codec_exec_verb(codec, cmd, &res);
220 240#else
221 res = make_codec_cmd(codec, nid, direct, verb, parm); 241 return codec_exec_verb(codec, cmd, NULL);
222 snd_hda_power_up(codec); 242#endif
223 mutex_lock(&bus->cmd_mutex);
224 err = bus->ops.command(bus, res);
225 mutex_unlock(&bus->cmd_mutex);
226 snd_hda_power_down(codec);
227 return err;
228} 243}
229EXPORT_SYMBOL_HDA(snd_hda_codec_write); 244EXPORT_SYMBOL_HDA(snd_hda_codec_write);
230 245
@@ -2281,28 +2296,22 @@ EXPORT_SYMBOL_HDA(snd_hda_create_spdif_in_ctls);
2281int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid, 2296int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
2282 int direct, unsigned int verb, unsigned int parm) 2297 int direct, unsigned int verb, unsigned int parm)
2283{ 2298{
2284 struct hda_bus *bus = codec->bus; 2299 int err = snd_hda_codec_write(codec, nid, direct, verb, parm);
2285 unsigned int res; 2300 struct hda_cache_head *c;
2286 int err; 2301 u32 key;
2287 2302
2288 res = make_codec_cmd(codec, nid, direct, verb, parm); 2303 if (err < 0)
2289 snd_hda_power_up(codec); 2304 return err;
2290 mutex_lock(&bus->cmd_mutex); 2305 /* parm may contain the verb stuff for get/set amp */
2291 err = bus->ops.command(bus, res); 2306 verb = verb | (parm >> 8);
2292 if (!err) { 2307 parm &= 0xff;
2293 struct hda_cache_head *c; 2308 key = build_cmd_cache_key(nid, verb);
2294 u32 key; 2309 mutex_lock(&codec->bus->cmd_mutex);
2295 /* parm may contain the verb stuff for get/set amp */ 2310 c = get_alloc_hash(&codec->cmd_cache, key);
2296 verb = verb | (parm >> 8); 2311 if (c)
2297 parm &= 0xff; 2312 c->val = parm;
2298 key = build_cmd_cache_key(nid, verb); 2313 mutex_unlock(&codec->bus->cmd_mutex);
2299 c = get_alloc_hash(&codec->cmd_cache, key); 2314 return 0;
2300 if (c)
2301 c->val = parm;
2302 }
2303 mutex_unlock(&bus->cmd_mutex);
2304 snd_hda_power_down(codec);
2305 return err;
2306} 2315}
2307EXPORT_SYMBOL_HDA(snd_hda_codec_write_cache); 2316EXPORT_SYMBOL_HDA(snd_hda_codec_write_cache);
2308 2317