Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=b3ac56364126f78cae94eb2a75b72d9ea85aca9d
Commit:     b3ac56364126f78cae94eb2a75b72d9ea85aca9d
Parent:     01751f54ff23b9d59e07f9c9ef189d4733525463
Author:     Takashi Iwai <[EMAIL PROTECTED]>
AuthorDate: Fri Aug 10 17:03:40 2007 +0200
Committer:  Jaroslav Kysela <[EMAIL PROTECTED]>
CommitDate: Tue Oct 16 15:58:41 2007 +0200

    [ALSA] hda-codec - introduce command register cache
    
    This patch adds the cache for codec command registers.
    snd_hda_codec_write_cache() and snd_hda_sequence_write_cache() do
    the write operations with caching, which values can be resumed via
    snd_hda_codec_resume_cache().
    The patch introduces only the framework, and no codec code is using
    this cache yet.  It'll be implemented in the following patch.
    
    Signed-off-by: Takashi Iwai <[EMAIL PROTECTED]>
    Signed-off-by: Jaroslav Kysela <[EMAIL PROTECTED]>
---
 sound/pci/hda/hda_codec.c |   91 +++++++++++++++++++++++++++++++++++++++++++++
 sound/pci/hda/hda_codec.h |    8 ++++
 sound/pci/hda/hda_local.h |    1 +
 3 files changed, 100 insertions(+), 0 deletions(-)

diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 46f8ab1..6652a53 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -510,6 +510,7 @@ static void snd_hda_codec_free(struct hda_codec *codec)
        if (codec->patch_ops.free)
                codec->patch_ops.free(codec);
        free_hda_cache(&codec->amp_cache);
+       free_hda_cache(&codec->cmd_cache);
        kfree(codec->wcaps);
        kfree(codec);
 }
@@ -548,6 +549,7 @@ int __devinit snd_hda_codec_new(struct hda_bus *bus, 
unsigned int codec_addr,
        codec->addr = codec_addr;
        mutex_init(&codec->spdif_mutex);
        init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info));
+       init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
 
        list_add_tail(&codec->list, &bus->codec_list);
        bus->caddr_tbl[codec_addr] = codec;
@@ -840,6 +842,29 @@ int snd_hda_codec_amp_update(struct hda_codec *codec, 
hda_nid_t nid, int ch,
        return 1;
 }
 
+/* resume the all amp commands from the cache */
+void snd_hda_codec_resume_amp(struct hda_codec *codec)
+{
+       struct hda_amp_info *buffer = codec->amp_cache.buffer;
+       int i;
+
+       for (i = 0; i < codec->amp_cache.size; i++, buffer++) {
+               u32 key = buffer->head.key;
+               hda_nid_t nid;
+               unsigned int idx, dir, ch;
+               if (!key)
+                       continue;
+               nid = key & 0xff;
+               idx = (key >> 16) & 0xff;
+               dir = (key >> 24) & 0xff;
+               for (ch = 0; ch < 2; ch++) {
+                       if (!(buffer->head.val & INFO_AMP_VOL(ch)))
+                               continue;
+                       put_vol_mute(codec, buffer, nid, ch, dir, idx,
+                                    buffer->vol[ch]);
+               }
+       }
+}
 
 /*
  * AMP control callbacks
@@ -1458,6 +1483,72 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec 
*codec, hda_nid_t nid)
 }
 
 
+/* build a 32bit cache key with the widget id and the command parameter */
+#define build_cmd_cache_key(nid, verb) ((verb << 8) | nid)
+#define get_cmd_cache_nid(key)         ((key) & 0xff)
+#define get_cmd_cache_cmd(key)         (((key) >> 8) & 0xffff)
+
+/**
+ * snd_hda_codec_write_cache - send a single command with caching
+ * @codec: the HDA codec
+ * @nid: NID to send the command
+ * @direct: direct flag
+ * @verb: the verb to send
+ * @parm: the parameter for the verb
+ *
+ * Send a single command without waiting for response.
+ *
+ * Returns 0 if successful, or a negative error code.
+ */
+int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
+                             int direct, unsigned int verb, unsigned int parm)
+{
+       int err;
+       mutex_lock(&codec->bus->cmd_mutex);
+       err = codec->bus->ops.command(codec, nid, direct, verb, parm);
+       if (!err) {
+               struct hda_cache_head *c;
+               u32 key = build_cmd_cache_key(nid, verb);
+               c = get_alloc_hash(&codec->cmd_cache, key);
+               if (c)
+                       c->val = parm;
+       }
+       mutex_unlock(&codec->bus->cmd_mutex);
+       return err;
+}
+
+/* resume the all commands from the cache */
+void snd_hda_codec_resume_cache(struct hda_codec *codec)
+{
+       struct hda_cache_head *buffer = codec->cmd_cache.buffer;
+       int i;
+
+       for (i = 0; i < codec->cmd_cache.size; i++, buffer++) {
+               u32 key = buffer->key;
+               if (!key)
+                       continue;
+               snd_hda_codec_write(codec, get_cmd_cache_nid(key), 0,
+                                   get_cmd_cache_cmd(key), buffer->val);
+       }
+}
+
+/**
+ * snd_hda_sequence_write_cache - sequence writes with caching
+ * @codec: the HDA codec
+ * @seq: VERB array to send
+ *
+ * Send the commands sequentially from the given array.
+ * Thte commands are recorded on cache for power-save and resume.
+ * The array must be terminated with NID=0.
+ */
+void snd_hda_sequence_write_cache(struct hda_codec *codec,
+                                 const struct hda_verb *seq)
+{
+       for (; seq->nid; seq++)
+               snd_hda_codec_write_cache(codec, seq->nid, 0, seq->verb,
+                                         seq->param);
+}
+
 /*
  * set power state of the codec
  */
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index 1a69743..ef94c91 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -570,6 +570,7 @@ struct hda_codec {
        u32 *wcaps;
 
        struct hda_cache_rec amp_cache; /* cache for amp access */
+       struct hda_cache_rec cmd_cache; /* cache for other commands */
 
        struct mutex spdif_mutex;
        unsigned int spdif_status;      /* IEC958 status bits */
@@ -620,6 +621,13 @@ void snd_hda_sequence_write(struct hda_codec *codec,
 /* unsolicited event */
 int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex);
 
+/* cached write */
+int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
+                             int direct, unsigned int verb, unsigned int parm);
+void snd_hda_sequence_write_cache(struct hda_codec *codec,
+                                 const struct hda_verb *seq);
+void snd_hda_codec_resume_cache(struct hda_codec *codec);
+
 /*
  * Mixer
  */
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
index fafcffe..5120897 100644
--- a/sound/pci/hda/hda_local.h
+++ b/sound/pci/hda/hda_local.h
@@ -84,6 +84,7 @@ int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t 
nid, int ch,
                           int direction, int index);
 int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
                             int direction, int idx, int mask, int val);
+void snd_hda_codec_resume_amp(struct hda_codec *codec);
 
 /* mono switch binding multiple inputs */
 #define HDA_BIND_MUTE_MONO(xname, nid, channel, indices, direction) \
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to