1 From: Takashi Iwai <tiwai@suse.de>
2 Subject: ALSA: hda - Support sync after writing a verb
6 This patch adds a debug mode to make the codec communication
7 synchronous. Define SND_HDA_SUPPORT_SYNC_WRITE in hda_codec.c,
8 and the call of snd_hda_codec_write*() will become synchronous,
9 i.e. wait for the reply from the codec at each time issuing a verb.
11 Signed-off-by: Takashi Iwai <tiwai@suse.de>
14 sound/pci/hda/hda_codec.c | 87 +++++++++++++++++++++++++---------------------
15 1 file changed, 49 insertions(+), 38 deletions(-)
17 --- a/sound/pci/hda/hda_codec.c
18 +++ b/sound/pci/hda/hda_codec.c
20 >> AC_DEFCFG_DEVICE_SHIFT];
24 + * Send and receive a verb
26 +static int codec_exec_verb(struct hda_codec *codec, unsigned int cmd,
29 + struct hda_bus *bus = codec->bus;
34 + snd_hda_power_up(codec);
35 + mutex_lock(&bus->cmd_mutex);
36 + err = bus->ops.command(bus, cmd);
38 + *res = bus->ops.get_response(bus);
39 + mutex_unlock(&bus->cmd_mutex);
40 + snd_hda_power_down(codec);
45 * snd_hda_codec_read - send a command and get the response
46 * @codec: the HDA codec
49 unsigned int verb, unsigned int parm)
51 - struct hda_bus *bus = codec->bus;
52 + unsigned cmd = make_codec_cmd(codec, nid, direct, verb, parm);
55 - res = make_codec_cmd(codec, nid, direct, verb, parm);
56 - snd_hda_power_up(codec);
57 - mutex_lock(&bus->cmd_mutex);
58 - if (!bus->ops.command(bus, res))
59 - res = bus->ops.get_response(bus);
61 - res = (unsigned int)-1;
62 - mutex_unlock(&bus->cmd_mutex);
63 - snd_hda_power_down(codec);
64 + codec_exec_verb(codec, cmd, &res);
68 +/* Define the below to send and receive verbs synchronously.
69 + * If you often get any codec communication errors, this is worth to try.
71 +#define SND_HDA_SUPPORT_SYNC_WRITE
74 * snd_hda_codec_write - send a single command without waiting for response
75 * @codec: the HDA codec
77 int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int direct,
78 unsigned int verb, unsigned int parm)
80 - struct hda_bus *bus = codec->bus;
81 + unsigned int cmd = make_codec_cmd(codec, nid, direct, verb, parm);
82 +#ifdef SND_HDA_SUPPORT_SYNC_WRITE
86 - res = make_codec_cmd(codec, nid, direct, verb, parm);
87 - snd_hda_power_up(codec);
88 - mutex_lock(&bus->cmd_mutex);
89 - err = bus->ops.command(bus, res);
90 - mutex_unlock(&bus->cmd_mutex);
91 - snd_hda_power_down(codec);
93 + return codec_exec_verb(codec, cmd, &res);
95 + return codec_exec_verb(codec, cmd, NULL);
100 @@ -1876,24 +1889,22 @@
101 int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
102 int direct, unsigned int verb, unsigned int parm)
104 - struct hda_bus *bus = codec->bus;
107 + int err = snd_hda_codec_write(codec, nid, direct, verb, parm);
108 + struct hda_cache_head *c;
111 - res = make_codec_cmd(codec, nid, direct, verb, parm);
112 - snd_hda_power_up(codec);
113 - mutex_lock(&bus->cmd_mutex);
114 - err = bus->ops.command(bus, res);
116 - struct hda_cache_head *c;
117 - u32 key = build_cmd_cache_key(nid, verb);
118 - c = get_alloc_hash(&codec->cmd_cache, key);
122 - mutex_unlock(&bus->cmd_mutex);
123 - snd_hda_power_down(codec);
127 + /* parm may contain the verb stuff for get/set amp */
128 + verb = verb | (parm >> 8);
130 + key = build_cmd_cache_key(nid, verb);
131 + mutex_lock(&codec->bus->cmd_mutex);
132 + c = get_alloc_hash(&codec->cmd_cache, key);
135 + mutex_unlock(&codec->bus->cmd_mutex);
139 /* resume the all commands from the cache */