mixer: add support for TLV based byte controls

Add tinyasla support for bytes controls with TLV type

Signed-off-by: Mythri P K <mythri.p.k@intel.com>
Signed-off-by: Samreen Nilofer <samreen.nilofer@intel.com>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
(cherry picked from commit 45b2d047b8c2f4d9d1d87244f7f981db8234c906)
diff --git a/mixer.c b/mixer.c
index eee3575..4b3d14f 100644
--- a/mixer.c
+++ b/mixer.c
@@ -334,7 +334,7 @@
 int mixer_ctl_get_array(struct mixer_ctl *ctl, void *array, size_t count)
 {
     struct snd_ctl_elem_value ev;
-    int ret;
+    int ret = 0;
     size_t size;
     void *source;
 
@@ -344,21 +344,41 @@
     memset(&ev, 0, sizeof(ev));
     ev.id.numid = ctl->info->id.numid;
 
-    ret = ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_READ, &ev);
-    if (ret < 0)
-        return ret;
-
     switch (ctl->info->type) {
     case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
     case SNDRV_CTL_ELEM_TYPE_INTEGER:
+        ret = ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_READ, &ev);
+        if (ret < 0)
+            return ret;
         size = sizeof(ev.value.integer.value[0]);
         source = ev.value.integer.value;
         break;
 
     case SNDRV_CTL_ELEM_TYPE_BYTES:
-        size = sizeof(ev.value.bytes.data[0]);
-        source = ev.value.bytes.data;
-        break;
+        /* check if this is new bytes TLV */
+        if (ctl->info->access & SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE) {
+            struct snd_ctl_tlv *tlv;
+            int ret;
+
+            tlv = calloc(1, sizeof(*tlv) + count);
+            tlv->numid = ctl->info->id.numid;
+            tlv->length = count;
+            ret = ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_TLV_READ, tlv);
+
+            source = tlv->tlv;
+            memcpy(array, source, count);
+
+            free(tlv);
+
+            return ret;
+        } else {
+            ret = ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_READ, &ev);
+            if (ret < 0)
+                return ret;
+            size = sizeof(ev.value.bytes.data[0]);
+            source = ev.value.bytes.data;
+            break;
+        }
 
     case SNDRV_CTL_ELEM_TYPE_IEC958:
         size = sizeof(ev.value.iec958);
@@ -432,8 +452,23 @@
         break;
 
     case SNDRV_CTL_ELEM_TYPE_BYTES:
-        size = sizeof(ev.value.bytes.data[0]);
-        dest = ev.value.bytes.data;
+        /* check if this is new bytes TLV */
+        if (ctl->info->access & SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE) {
+            struct snd_ctl_tlv *tlv;
+            int ret = 0;
+            tlv = calloc(1, sizeof(*tlv) + count);
+            tlv->numid = ctl->info->id.numid;
+            tlv->length = count;
+            memcpy(tlv->tlv, array, count);
+
+            ret = ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_TLV_WRITE, tlv);
+            free(tlv);
+
+            return ret;
+        } else {
+            size = sizeof(ev.value.bytes.data[0]);
+            dest = ev.value.bytes.data;
+        }
         break;
 
     case SNDRV_CTL_ELEM_TYPE_IEC958: