Currently the TLV topology structure is targeted at only supporting the DB scale data. This patch extends support for the other TLV types so they can be easily added at a later stage. TLV structure is moved to common topology control header since it's a common field for controls and can be processed in a general way. Users must set a proper access flag for a control since it's used to decide if the TLV field is valid and if a TLV callback is needed. Removed the following fields from topology TLV struct: - size/count: type can decide the size. - numid: not needed to initialize TLV for kcontrol. - data: replaced by the type specific struct. Added TLV structure to generic control header and removed TLV structure from mixer control.
Unified · Split
| @@ -137,11 +137,19 @@ struct snd_soc_tplg_private { · 136 unmodified lines | |||
| 137 | /* | 137 | /* |
| 138 | * Kcontrol TLV data. | 138 | * Kcontrol TLV data. |
| 139 | */ | 139 | */ |
| 140 | struct snd_soc_tplg_tlv_dbscale { | ||
| 141 | __le32 min; | ||
| 142 | __le32 step; | ||
| 143 | __le32 mute; | ||
| 144 | } __attribute__((packed)); | ||
| 145 | |||
| 140 | struct snd_soc_tplg_ctl_tlv { | 146 | struct snd_soc_tplg_ctl_tlv { |
| 141 | __le32 size; /* in bytes aligned to 4 */ | 147 | __le32 size; /* in bytes of this structure */ |
| 142 | __le32 numid; /* control element numeric identification */ | 148 | __le32 type; /* SNDRV_CTL_TLVT_*, type of TLV */ |
| 143 | __le32 count; /* number of elem in data array */ | 149 | union { |
| 144 | __le32 data[SND_SOC_TPLG_TLV_SIZE]; | 150 | __le32 data[SND_SOC_TPLG_TLV_SIZE]; |
| 151 | struct snd_soc_tplg_tlv_dbscale scale; | ||
| 152 | }; | ||
| 145 | } __attribute__((packed)); | 153 | } __attribute__((packed)); |
| 146 | 154 | ||
| 147 | /* | 155 | /* |
| @@ -172,7 +180,7 @@ struct snd_soc_tplg_ctl_hdr { · 24 unmodified lines | |||
| 172 | char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; | 180 | char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; |
| 173 | __le32 access; | 181 | __le32 access; |
| 174 | struct snd_soc_tplg_kcontrol_ops_id ops; | 182 | struct snd_soc_tplg_kcontrol_ops_id ops; |
| 175 | __le32 tlv_size; /* non zero means control has TLV data */ | 183 | struct snd_soc_tplg_ctl_tlv tlv; |
| 176 | } __attribute__((packed)); | 184 | } __attribute__((packed)); |
| 177 | 185 | ||
| 178 | /* | 186 | /* |
| @@ -260,7 +268,6 @@ struct snd_soc_tplg_mixer_control { · 81 unmodified lines | |||
| 260 | __le32 invert; | 268 | __le32 invert; |
| 261 | __le32 num_channels; | 269 | __le32 num_channels; |
| 262 | struct snd_soc_tplg_channel channel[SND_SOC_TPLG_MAX_CHAN]; | 270 | struct snd_soc_tplg_channel channel[SND_SOC_TPLG_MAX_CHAN]; |
| 263 | struct snd_soc_tplg_ctl_tlv tlv; | ||
| 264 | struct snd_soc_tplg_private priv; | 271 | struct snd_soc_tplg_private priv; |
| 265 | } __attribute__((packed)); | 272 | } __attribute__((packed)); |
| 266 | 273 | ||
| @@ -33,6 +33,7 @@ · 32 unmodified lines | |||
| 33 | #include <sound/soc.h> | 33 | #include <sound/soc.h> |
| 34 | #include <sound/soc-dapm.h> | 34 | #include <sound/soc-dapm.h> |
| 35 | #include <sound/soc-topology.h> | 35 | #include <sound/soc-topology.h> |
| 36 | #include <sound/tlv.h> | ||
| 36 | 37 | ||
| 37 | /* | 38 | /* |
| 38 | * We make several passes over the data (since it wont necessarily be ordered) | 39 | * We make several passes over the data (since it wont necessarily be ordered) |
| @@ -579,28 +580,51 @@ static int soc_tplg_init_kcontrol(struct soc_tplg *tplg, · 540 unmodified lines | |||
| 579 | return 0; | 580 | return 0; |
| 580 | } | 581 | } |
| 581 | 582 | ||
| 583 | |||
| 584 | static int soc_tplg_create_tlv_db_scale(struct soc_tplg *tplg, | ||
| 585 | struct snd_kcontrol_new *kc, struct snd_soc_tplg_tlv_dbscale *scale) | ||
| 586 | { | ||
| 587 | unsigned int item_len = 2 * sizeof(unsigned int); | ||
| 588 | unsigned int *p; | ||
| 589 | |||
| 590 | p = kzalloc(item_len + 2 * sizeof(unsigned int), GFP_KERNEL); | ||
| 591 | if (!p) | ||
| 592 | return -ENOMEM; | ||
| 593 | |||
| 594 | p[0] = SNDRV_CTL_TLVT_DB_SCALE; | ||
| 595 | p[1] = item_len; | ||
| 596 | p[2] = scale->min; | ||
| 597 | p[3] = (scale->step & TLV_DB_SCALE_MASK) | ||
| 598 | | (scale->mute ? TLV_DB_SCALE_MUTE : 0); | ||
| 599 | |||
| 600 | kc->tlv.p = (void *)p; | ||
| 601 | return 0; | ||
| 602 | } | ||
| 603 | |||
| 582 | static int soc_tplg_create_tlv(struct soc_tplg *tplg, | 604 | static int soc_tplg_create_tlv(struct soc_tplg *tplg, |
| 583 | struct snd_kcontrol_new *kc, struct snd_soc_tplg_ctl_tlv *tplg_tlv) | 605 | struct snd_kcontrol_new *kc, struct snd_soc_tplg_ctl_hdr *tc) |
| 584 | { | 606 | { |
| 585 | struct snd_ctl_tlv *tlv; | 607 | struct snd_soc_tplg_ctl_tlv *tplg_tlv; |
| 586 | int size; | ||
| 587 | 608 | ||
| 588 | if (tplg_tlv->count == 0) | 609 | if (!(tc->access & SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE)) |
| 589 | return 0; | 610 | return 0; |
| 590 | 611 | ||
| 591 | size = ((tplg_tlv->count + (sizeof(unsigned int) - 1)) & | 612 | if (tc->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) { |
| 592 | ~(sizeof(unsigned int) - 1)); | 613 | kc->tlv.c = snd_soc_bytes_tlv_callback; |
| 593 | tlv = kzalloc(sizeof(*tlv) + size, GFP_KERNEL); | 614 | } else { |
| 594 | if (tlv == NULL) | 615 | tplg_tlv = &tc->tlv; |
| 595 | return -ENOMEM; | 616 | switch (tplg_tlv->type) { |
| 596 | 617 | case SNDRV_CTL_TLVT_DB_SCALE: | |
| 597 | dev_dbg(tplg->dev, " created TLV type %d size %d bytes\n", | 618 | return soc_tplg_create_tlv_db_scale(tplg, kc, |
| 598 | tplg_tlv->numid, size); | 619 | &tplg_tlv->scale); |
| 599 | 620 | ||
| 600 | tlv->numid = tplg_tlv->numid; | 621 | /* TODO: add support for other TLV types */ |
| 601 | tlv->length = size; | 622 | default: |
| 602 | memcpy(&tlv->tlv[0], tplg_tlv->data, size); | 623 | dev_dbg(tplg->dev, "Unsupported TLV type %d\n", |
| 603 | kc->tlv.p = (void *)tlv; | 624 | tplg_tlv->type); |
| 625 | return -EINVAL; | ||
| 626 | } | ||
| 627 | } | ||
| 604 | 628 | ||
| 605 | return 0; | 629 | return 0; |
| 606 | } | 630 | } |
| @@ -772,7 +796,7 @@ static int soc_tplg_dmixer_create(struct soc_tplg *tplg, unsigned int count, · 165 unmodified lines | |||
| 772 | } | 796 | } |
| 773 | 797 | ||
| 774 | /* create any TLV data */ | 798 | /* create any TLV data */ |
| 775 | soc_tplg_create_tlv(tplg, &kc, &mc->tlv); | 799 | soc_tplg_create_tlv(tplg, &kc, &mc->hdr); |
| 776 | 800 | ||
| 777 | /* register control here */ | 801 | /* register control here */ |
| 778 | err = soc_tplg_add_kcontrol(tplg, &kc, | 802 | err = soc_tplg_add_kcontrol(tplg, &kc, |