linux/sound/soc/codecs/wm_adsp.c
<<
>>
Prefs
   1/*
   2 * wm_adsp.c  --  Wolfson ADSP support
   3 *
   4 * Copyright 2012 Wolfson Microelectronics plc
   5 *
   6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License version 2 as
  10 * published by the Free Software Foundation.
  11 */
  12
  13#include <linux/module.h>
  14#include <linux/moduleparam.h>
  15#include <linux/init.h>
  16#include <linux/delay.h>
  17#include <linux/firmware.h>
  18#include <linux/list.h>
  19#include <linux/pm.h>
  20#include <linux/pm_runtime.h>
  21#include <linux/regmap.h>
  22#include <linux/regulator/consumer.h>
  23#include <linux/slab.h>
  24#include <linux/workqueue.h>
  25#include <sound/core.h>
  26#include <sound/pcm.h>
  27#include <sound/pcm_params.h>
  28#include <sound/soc.h>
  29#include <sound/jack.h>
  30#include <sound/initval.h>
  31#include <sound/tlv.h>
  32
  33#include <linux/mfd/arizona/registers.h>
  34
  35#include "arizona.h"
  36#include "wm_adsp.h"
  37
  38#define adsp_crit(_dsp, fmt, ...) \
  39        dev_crit(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__)
  40#define adsp_err(_dsp, fmt, ...) \
  41        dev_err(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__)
  42#define adsp_warn(_dsp, fmt, ...) \
  43        dev_warn(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__)
  44#define adsp_info(_dsp, fmt, ...) \
  45        dev_info(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__)
  46#define adsp_dbg(_dsp, fmt, ...) \
  47        dev_dbg(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__)
  48
  49#define ADSP1_CONTROL_1                   0x00
  50#define ADSP1_CONTROL_2                   0x02
  51#define ADSP1_CONTROL_3                   0x03
  52#define ADSP1_CONTROL_4                   0x04
  53#define ADSP1_CONTROL_5                   0x06
  54#define ADSP1_CONTROL_6                   0x07
  55#define ADSP1_CONTROL_7                   0x08
  56#define ADSP1_CONTROL_8                   0x09
  57#define ADSP1_CONTROL_9                   0x0A
  58#define ADSP1_CONTROL_10                  0x0B
  59#define ADSP1_CONTROL_11                  0x0C
  60#define ADSP1_CONTROL_12                  0x0D
  61#define ADSP1_CONTROL_13                  0x0F
  62#define ADSP1_CONTROL_14                  0x10
  63#define ADSP1_CONTROL_15                  0x11
  64#define ADSP1_CONTROL_16                  0x12
  65#define ADSP1_CONTROL_17                  0x13
  66#define ADSP1_CONTROL_18                  0x14
  67#define ADSP1_CONTROL_19                  0x16
  68#define ADSP1_CONTROL_20                  0x17
  69#define ADSP1_CONTROL_21                  0x18
  70#define ADSP1_CONTROL_22                  0x1A
  71#define ADSP1_CONTROL_23                  0x1B
  72#define ADSP1_CONTROL_24                  0x1C
  73#define ADSP1_CONTROL_25                  0x1E
  74#define ADSP1_CONTROL_26                  0x20
  75#define ADSP1_CONTROL_27                  0x21
  76#define ADSP1_CONTROL_28                  0x22
  77#define ADSP1_CONTROL_29                  0x23
  78#define ADSP1_CONTROL_30                  0x24
  79#define ADSP1_CONTROL_31                  0x26
  80
  81/*
  82 * ADSP1 Control 19
  83 */
  84#define ADSP1_WDMA_BUFFER_LENGTH_MASK     0x00FF  /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */
  85#define ADSP1_WDMA_BUFFER_LENGTH_SHIFT         0  /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */
  86#define ADSP1_WDMA_BUFFER_LENGTH_WIDTH         8  /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */
  87
  88
  89/*
  90 * ADSP1 Control 30
  91 */
  92#define ADSP1_DBG_CLK_ENA                 0x0008  /* DSP1_DBG_CLK_ENA */
  93#define ADSP1_DBG_CLK_ENA_MASK            0x0008  /* DSP1_DBG_CLK_ENA */
  94#define ADSP1_DBG_CLK_ENA_SHIFT                3  /* DSP1_DBG_CLK_ENA */
  95#define ADSP1_DBG_CLK_ENA_WIDTH                1  /* DSP1_DBG_CLK_ENA */
  96#define ADSP1_SYS_ENA                     0x0004  /* DSP1_SYS_ENA */
  97#define ADSP1_SYS_ENA_MASK                0x0004  /* DSP1_SYS_ENA */
  98#define ADSP1_SYS_ENA_SHIFT                    2  /* DSP1_SYS_ENA */
  99#define ADSP1_SYS_ENA_WIDTH                    1  /* DSP1_SYS_ENA */
 100#define ADSP1_CORE_ENA                    0x0002  /* DSP1_CORE_ENA */
 101#define ADSP1_CORE_ENA_MASK               0x0002  /* DSP1_CORE_ENA */
 102#define ADSP1_CORE_ENA_SHIFT                   1  /* DSP1_CORE_ENA */
 103#define ADSP1_CORE_ENA_WIDTH                   1  /* DSP1_CORE_ENA */
 104#define ADSP1_START                       0x0001  /* DSP1_START */
 105#define ADSP1_START_MASK                  0x0001  /* DSP1_START */
 106#define ADSP1_START_SHIFT                      0  /* DSP1_START */
 107#define ADSP1_START_WIDTH                      1  /* DSP1_START */
 108
 109/*
 110 * ADSP1 Control 31
 111 */
 112#define ADSP1_CLK_SEL_MASK                0x0007  /* CLK_SEL_ENA */
 113#define ADSP1_CLK_SEL_SHIFT                    0  /* CLK_SEL_ENA */
 114#define ADSP1_CLK_SEL_WIDTH                    3  /* CLK_SEL_ENA */
 115
 116#define ADSP2_CONTROL        0x0
 117#define ADSP2_CLOCKING       0x1
 118#define ADSP2_STATUS1        0x4
 119#define ADSP2_WDMA_CONFIG_1 0x30
 120#define ADSP2_WDMA_CONFIG_2 0x31
 121#define ADSP2_RDMA_CONFIG_1 0x34
 122
 123/*
 124 * ADSP2 Control
 125 */
 126
 127#define ADSP2_MEM_ENA                     0x0010  /* DSP1_MEM_ENA */
 128#define ADSP2_MEM_ENA_MASK                0x0010  /* DSP1_MEM_ENA */
 129#define ADSP2_MEM_ENA_SHIFT                    4  /* DSP1_MEM_ENA */
 130#define ADSP2_MEM_ENA_WIDTH                    1  /* DSP1_MEM_ENA */
 131#define ADSP2_SYS_ENA                     0x0004  /* DSP1_SYS_ENA */
 132#define ADSP2_SYS_ENA_MASK                0x0004  /* DSP1_SYS_ENA */
 133#define ADSP2_SYS_ENA_SHIFT                    2  /* DSP1_SYS_ENA */
 134#define ADSP2_SYS_ENA_WIDTH                    1  /* DSP1_SYS_ENA */
 135#define ADSP2_CORE_ENA                    0x0002  /* DSP1_CORE_ENA */
 136#define ADSP2_CORE_ENA_MASK               0x0002  /* DSP1_CORE_ENA */
 137#define ADSP2_CORE_ENA_SHIFT                   1  /* DSP1_CORE_ENA */
 138#define ADSP2_CORE_ENA_WIDTH                   1  /* DSP1_CORE_ENA */
 139#define ADSP2_START                       0x0001  /* DSP1_START */
 140#define ADSP2_START_MASK                  0x0001  /* DSP1_START */
 141#define ADSP2_START_SHIFT                      0  /* DSP1_START */
 142#define ADSP2_START_WIDTH                      1  /* DSP1_START */
 143
 144/*
 145 * ADSP2 clocking
 146 */
 147#define ADSP2_CLK_SEL_MASK                0x0007  /* CLK_SEL_ENA */
 148#define ADSP2_CLK_SEL_SHIFT                    0  /* CLK_SEL_ENA */
 149#define ADSP2_CLK_SEL_WIDTH                    3  /* CLK_SEL_ENA */
 150
 151/*
 152 * ADSP2 Status 1
 153 */
 154#define ADSP2_RAM_RDY                     0x0001
 155#define ADSP2_RAM_RDY_MASK                0x0001
 156#define ADSP2_RAM_RDY_SHIFT                    0
 157#define ADSP2_RAM_RDY_WIDTH                    1
 158
 159struct wm_adsp_buf {
 160        struct list_head list;
 161        void *buf;
 162};
 163
 164static struct wm_adsp_buf *wm_adsp_buf_alloc(const void *src, size_t len,
 165                                             struct list_head *list)
 166{
 167        struct wm_adsp_buf *buf = kzalloc(sizeof(*buf), GFP_KERNEL);
 168
 169        if (buf == NULL)
 170                return NULL;
 171
 172        buf->buf = kmemdup(src, len, GFP_KERNEL | GFP_DMA);
 173        if (!buf->buf) {
 174                kfree(buf);
 175                return NULL;
 176        }
 177
 178        if (list)
 179                list_add_tail(&buf->list, list);
 180
 181        return buf;
 182}
 183
 184static void wm_adsp_buf_free(struct list_head *list)
 185{
 186        while (!list_empty(list)) {
 187                struct wm_adsp_buf *buf = list_first_entry(list,
 188                                                           struct wm_adsp_buf,
 189                                                           list);
 190                list_del(&buf->list);
 191                kfree(buf->buf);
 192                kfree(buf);
 193        }
 194}
 195
 196#define WM_ADSP_NUM_FW 4
 197
 198#define WM_ADSP_FW_MBC_VSS 0
 199#define WM_ADSP_FW_TX      1
 200#define WM_ADSP_FW_TX_SPK  2
 201#define WM_ADSP_FW_RX_ANC  3
 202
 203static const char *wm_adsp_fw_text[WM_ADSP_NUM_FW] = {
 204        [WM_ADSP_FW_MBC_VSS] = "MBC/VSS",
 205        [WM_ADSP_FW_TX] =      "Tx",
 206        [WM_ADSP_FW_TX_SPK] =  "Tx Speaker",
 207        [WM_ADSP_FW_RX_ANC] =  "Rx ANC",
 208};
 209
 210static struct {
 211        const char *file;
 212} wm_adsp_fw[WM_ADSP_NUM_FW] = {
 213        [WM_ADSP_FW_MBC_VSS] = { .file = "mbc-vss" },
 214        [WM_ADSP_FW_TX] =      { .file = "tx" },
 215        [WM_ADSP_FW_TX_SPK] =  { .file = "tx-spk" },
 216        [WM_ADSP_FW_RX_ANC] =  { .file = "rx-anc" },
 217};
 218
 219struct wm_coeff_ctl_ops {
 220        int (*xget)(struct snd_kcontrol *kcontrol,
 221                    struct snd_ctl_elem_value *ucontrol);
 222        int (*xput)(struct snd_kcontrol *kcontrol,
 223                    struct snd_ctl_elem_value *ucontrol);
 224        int (*xinfo)(struct snd_kcontrol *kcontrol,
 225                     struct snd_ctl_elem_info *uinfo);
 226};
 227
 228struct wm_coeff_ctl {
 229        const char *name;
 230        struct wm_adsp_alg_region region;
 231        struct wm_coeff_ctl_ops ops;
 232        struct wm_adsp *adsp;
 233        void *private;
 234        unsigned int enabled:1;
 235        struct list_head list;
 236        void *cache;
 237        size_t len;
 238        unsigned int set:1;
 239        struct snd_kcontrol *kcontrol;
 240};
 241
 242static int wm_adsp_fw_get(struct snd_kcontrol *kcontrol,
 243                          struct snd_ctl_elem_value *ucontrol)
 244{
 245        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
 246        struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
 247        struct wm_adsp *adsp = snd_soc_codec_get_drvdata(codec);
 248
 249        ucontrol->value.integer.value[0] = adsp[e->shift_l].fw;
 250
 251        return 0;
 252}
 253
 254static int wm_adsp_fw_put(struct snd_kcontrol *kcontrol,
 255                          struct snd_ctl_elem_value *ucontrol)
 256{
 257        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
 258        struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
 259        struct wm_adsp *adsp = snd_soc_codec_get_drvdata(codec);
 260
 261        if (ucontrol->value.integer.value[0] == adsp[e->shift_l].fw)
 262                return 0;
 263
 264        if (ucontrol->value.integer.value[0] >= WM_ADSP_NUM_FW)
 265                return -EINVAL;
 266
 267        if (adsp[e->shift_l].running)
 268                return -EBUSY;
 269
 270        adsp[e->shift_l].fw = ucontrol->value.integer.value[0];
 271
 272        return 0;
 273}
 274
 275static const struct soc_enum wm_adsp_fw_enum[] = {
 276        SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
 277        SOC_ENUM_SINGLE(0, 1, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
 278        SOC_ENUM_SINGLE(0, 2, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
 279        SOC_ENUM_SINGLE(0, 3, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
 280};
 281
 282const struct snd_kcontrol_new wm_adsp1_fw_controls[] = {
 283        SOC_ENUM_EXT("DSP1 Firmware", wm_adsp_fw_enum[0],
 284                     wm_adsp_fw_get, wm_adsp_fw_put),
 285        SOC_ENUM_EXT("DSP2 Firmware", wm_adsp_fw_enum[1],
 286                     wm_adsp_fw_get, wm_adsp_fw_put),
 287        SOC_ENUM_EXT("DSP3 Firmware", wm_adsp_fw_enum[2],
 288                     wm_adsp_fw_get, wm_adsp_fw_put),
 289};
 290EXPORT_SYMBOL_GPL(wm_adsp1_fw_controls);
 291
 292#if IS_ENABLED(CONFIG_SND_SOC_ARIZONA)
 293static const struct soc_enum wm_adsp2_rate_enum[] = {
 294        SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP1_CONTROL_1,
 295                              ARIZONA_DSP1_RATE_SHIFT, 0xf,
 296                              ARIZONA_RATE_ENUM_SIZE,
 297                              arizona_rate_text, arizona_rate_val),
 298        SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP2_CONTROL_1,
 299                              ARIZONA_DSP1_RATE_SHIFT, 0xf,
 300                              ARIZONA_RATE_ENUM_SIZE,
 301                              arizona_rate_text, arizona_rate_val),
 302        SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP3_CONTROL_1,
 303                              ARIZONA_DSP1_RATE_SHIFT, 0xf,
 304                              ARIZONA_RATE_ENUM_SIZE,
 305                              arizona_rate_text, arizona_rate_val),
 306        SOC_VALUE_ENUM_SINGLE(ARIZONA_DSP4_CONTROL_1,
 307                              ARIZONA_DSP1_RATE_SHIFT, 0xf,
 308                              ARIZONA_RATE_ENUM_SIZE,
 309                              arizona_rate_text, arizona_rate_val),
 310};
 311
 312const struct snd_kcontrol_new wm_adsp2_fw_controls[] = {
 313        SOC_ENUM_EXT("DSP1 Firmware", wm_adsp_fw_enum[0],
 314                     wm_adsp_fw_get, wm_adsp_fw_put),
 315        SOC_ENUM("DSP1 Rate", wm_adsp2_rate_enum[0]),
 316        SOC_ENUM_EXT("DSP2 Firmware", wm_adsp_fw_enum[1],
 317                     wm_adsp_fw_get, wm_adsp_fw_put),
 318        SOC_ENUM("DSP2 Rate", wm_adsp2_rate_enum[1]),
 319        SOC_ENUM_EXT("DSP3 Firmware", wm_adsp_fw_enum[2],
 320                     wm_adsp_fw_get, wm_adsp_fw_put),
 321        SOC_ENUM("DSP3 Rate", wm_adsp2_rate_enum[2]),
 322        SOC_ENUM_EXT("DSP4 Firmware", wm_adsp_fw_enum[3],
 323                     wm_adsp_fw_get, wm_adsp_fw_put),
 324        SOC_ENUM("DSP4 Rate", wm_adsp2_rate_enum[3]),
 325};
 326EXPORT_SYMBOL_GPL(wm_adsp2_fw_controls);
 327#endif
 328
 329static struct wm_adsp_region const *wm_adsp_find_region(struct wm_adsp *dsp,
 330                                                        int type)
 331{
 332        int i;
 333
 334        for (i = 0; i < dsp->num_mems; i++)
 335                if (dsp->mem[i].type == type)
 336                        return &dsp->mem[i];
 337
 338        return NULL;
 339}
 340
 341static unsigned int wm_adsp_region_to_reg(struct wm_adsp_region const *region,
 342                                          unsigned int offset)
 343{
 344        if (WARN_ON(!region))
 345                return offset;
 346        switch (region->type) {
 347        case WMFW_ADSP1_PM:
 348                return region->base + (offset * 3);
 349        case WMFW_ADSP1_DM:
 350                return region->base + (offset * 2);
 351        case WMFW_ADSP2_XM:
 352                return region->base + (offset * 2);
 353        case WMFW_ADSP2_YM:
 354                return region->base + (offset * 2);
 355        case WMFW_ADSP1_ZM:
 356                return region->base + (offset * 2);
 357        default:
 358                WARN(1, "Unknown memory region type");
 359                return offset;
 360        }
 361}
 362
 363static int wm_coeff_info(struct snd_kcontrol *kcontrol,
 364                         struct snd_ctl_elem_info *uinfo)
 365{
 366        struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kcontrol->private_value;
 367
 368        uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
 369        uinfo->count = ctl->len;
 370        return 0;
 371}
 372
 373static int wm_coeff_write_control(struct snd_kcontrol *kcontrol,
 374                                  const void *buf, size_t len)
 375{
 376        struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kcontrol->private_value;
 377        struct wm_adsp_alg_region *region = &ctl->region;
 378        const struct wm_adsp_region *mem;
 379        struct wm_adsp *adsp = ctl->adsp;
 380        void *scratch;
 381        int ret;
 382        unsigned int reg;
 383
 384        mem = wm_adsp_find_region(adsp, region->type);
 385        if (!mem) {
 386                adsp_err(adsp, "No base for region %x\n",
 387                         region->type);
 388                return -EINVAL;
 389        }
 390
 391        reg = ctl->region.base;
 392        reg = wm_adsp_region_to_reg(mem, reg);
 393
 394        scratch = kmemdup(buf, ctl->len, GFP_KERNEL | GFP_DMA);
 395        if (!scratch)
 396                return -ENOMEM;
 397
 398        ret = regmap_raw_write(adsp->regmap, reg, scratch,
 399                               ctl->len);
 400        if (ret) {
 401                adsp_err(adsp, "Failed to write %zu bytes to %x: %d\n",
 402                         ctl->len, reg, ret);
 403                kfree(scratch);
 404                return ret;
 405        }
 406        adsp_dbg(adsp, "Wrote %zu bytes to %x\n", ctl->len, reg);
 407
 408        kfree(scratch);
 409
 410        return 0;
 411}
 412
 413static int wm_coeff_put(struct snd_kcontrol *kcontrol,
 414                        struct snd_ctl_elem_value *ucontrol)
 415{
 416        struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kcontrol->private_value;
 417        char *p = ucontrol->value.bytes.data;
 418
 419        memcpy(ctl->cache, p, ctl->len);
 420
 421        if (!ctl->enabled) {
 422                ctl->set = 1;
 423                return 0;
 424        }
 425
 426        return wm_coeff_write_control(kcontrol, p, ctl->len);
 427}
 428
 429static int wm_coeff_read_control(struct snd_kcontrol *kcontrol,
 430                                 void *buf, size_t len)
 431{
 432        struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kcontrol->private_value;
 433        struct wm_adsp_alg_region *region = &ctl->region;
 434        const struct wm_adsp_region *mem;
 435        struct wm_adsp *adsp = ctl->adsp;
 436        void *scratch;
 437        int ret;
 438        unsigned int reg;
 439
 440        mem = wm_adsp_find_region(adsp, region->type);
 441        if (!mem) {
 442                adsp_err(adsp, "No base for region %x\n",
 443                         region->type);
 444                return -EINVAL;
 445        }
 446
 447        reg = ctl->region.base;
 448        reg = wm_adsp_region_to_reg(mem, reg);
 449
 450        scratch = kmalloc(ctl->len, GFP_KERNEL | GFP_DMA);
 451        if (!scratch)
 452                return -ENOMEM;
 453
 454        ret = regmap_raw_read(adsp->regmap, reg, scratch, ctl->len);
 455        if (ret) {
 456                adsp_err(adsp, "Failed to read %zu bytes from %x: %d\n",
 457                         ctl->len, reg, ret);
 458                kfree(scratch);
 459                return ret;
 460        }
 461        adsp_dbg(adsp, "Read %zu bytes from %x\n", ctl->len, reg);
 462
 463        memcpy(buf, scratch, ctl->len);
 464        kfree(scratch);
 465
 466        return 0;
 467}
 468
 469static int wm_coeff_get(struct snd_kcontrol *kcontrol,
 470                        struct snd_ctl_elem_value *ucontrol)
 471{
 472        struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kcontrol->private_value;
 473        char *p = ucontrol->value.bytes.data;
 474
 475        memcpy(p, ctl->cache, ctl->len);
 476        return 0;
 477}
 478
 479struct wmfw_ctl_work {
 480        struct wm_adsp *adsp;
 481        struct wm_coeff_ctl *ctl;
 482        struct work_struct work;
 483};
 484
 485static int wmfw_add_ctl(struct wm_adsp *adsp, struct wm_coeff_ctl *ctl)
 486{
 487        struct snd_kcontrol_new *kcontrol;
 488        int ret;
 489
 490        if (!ctl || !ctl->name)
 491                return -EINVAL;
 492
 493        kcontrol = kzalloc(sizeof(*kcontrol), GFP_KERNEL);
 494        if (!kcontrol)
 495                return -ENOMEM;
 496        kcontrol->iface = SNDRV_CTL_ELEM_IFACE_MIXER;
 497
 498        kcontrol->name = ctl->name;
 499        kcontrol->info = wm_coeff_info;
 500        kcontrol->get = wm_coeff_get;
 501        kcontrol->put = wm_coeff_put;
 502        kcontrol->private_value = (unsigned long)ctl;
 503
 504        ret = snd_soc_add_card_controls(adsp->card,
 505                                        kcontrol, 1);
 506        if (ret < 0)
 507                goto err_kcontrol;
 508
 509        kfree(kcontrol);
 510
 511        ctl->kcontrol = snd_soc_card_get_kcontrol(adsp->card,
 512                                                  ctl->name);
 513
 514        list_add(&ctl->list, &adsp->ctl_list);
 515        return 0;
 516
 517err_kcontrol:
 518        kfree(kcontrol);
 519        return ret;
 520}
 521
 522static int wm_adsp_load(struct wm_adsp *dsp)
 523{
 524        LIST_HEAD(buf_list);
 525        const struct firmware *firmware;
 526        struct regmap *regmap = dsp->regmap;
 527        unsigned int pos = 0;
 528        const struct wmfw_header *header;
 529        const struct wmfw_adsp1_sizes *adsp1_sizes;
 530        const struct wmfw_adsp2_sizes *adsp2_sizes;
 531        const struct wmfw_footer *footer;
 532        const struct wmfw_region *region;
 533        const struct wm_adsp_region *mem;
 534        const char *region_name;
 535        char *file, *text;
 536        struct wm_adsp_buf *buf;
 537        unsigned int reg;
 538        int regions = 0;
 539        int ret, offset, type, sizes;
 540
 541        file = kzalloc(PAGE_SIZE, GFP_KERNEL);
 542        if (file == NULL)
 543                return -ENOMEM;
 544
 545        snprintf(file, PAGE_SIZE, "%s-dsp%d-%s.wmfw", dsp->part, dsp->num,
 546                 wm_adsp_fw[dsp->fw].file);
 547        file[PAGE_SIZE - 1] = '\0';
 548
 549        ret = request_firmware(&firmware, file, dsp->dev);
 550        if (ret != 0) {
 551                adsp_err(dsp, "Failed to request '%s'\n", file);
 552                goto out;
 553        }
 554        ret = -EINVAL;
 555
 556        pos = sizeof(*header) + sizeof(*adsp1_sizes) + sizeof(*footer);
 557        if (pos >= firmware->size) {
 558                adsp_err(dsp, "%s: file too short, %zu bytes\n",
 559                         file, firmware->size);
 560                goto out_fw;
 561        }
 562
 563        header = (void*)&firmware->data[0];
 564
 565        if (memcmp(&header->magic[0], "WMFW", 4) != 0) {
 566                adsp_err(dsp, "%s: invalid magic\n", file);
 567                goto out_fw;
 568        }
 569
 570        if (header->ver != 0) {
 571                adsp_err(dsp, "%s: unknown file format %d\n",
 572                         file, header->ver);
 573                goto out_fw;
 574        }
 575        adsp_info(dsp, "Firmware version: %d\n", header->ver);
 576
 577        if (header->core != dsp->type) {
 578                adsp_err(dsp, "%s: invalid core %d != %d\n",
 579                         file, header->core, dsp->type);
 580                goto out_fw;
 581        }
 582
 583        switch (dsp->type) {
 584        case WMFW_ADSP1:
 585                pos = sizeof(*header) + sizeof(*adsp1_sizes) + sizeof(*footer);
 586                adsp1_sizes = (void *)&(header[1]);
 587                footer = (void *)&(adsp1_sizes[1]);
 588                sizes = sizeof(*adsp1_sizes);
 589
 590                adsp_dbg(dsp, "%s: %d DM, %d PM, %d ZM\n",
 591                         file, le32_to_cpu(adsp1_sizes->dm),
 592                         le32_to_cpu(adsp1_sizes->pm),
 593                         le32_to_cpu(adsp1_sizes->zm));
 594                break;
 595
 596        case WMFW_ADSP2:
 597                pos = sizeof(*header) + sizeof(*adsp2_sizes) + sizeof(*footer);
 598                adsp2_sizes = (void *)&(header[1]);
 599                footer = (void *)&(adsp2_sizes[1]);
 600                sizes = sizeof(*adsp2_sizes);
 601
 602                adsp_dbg(dsp, "%s: %d XM, %d YM %d PM, %d ZM\n",
 603                         file, le32_to_cpu(adsp2_sizes->xm),
 604                         le32_to_cpu(adsp2_sizes->ym),
 605                         le32_to_cpu(adsp2_sizes->pm),
 606                         le32_to_cpu(adsp2_sizes->zm));
 607                break;
 608
 609        default:
 610                WARN(1, "Unknown DSP type");
 611                goto out_fw;
 612        }
 613
 614        if (le32_to_cpu(header->len) != sizeof(*header) +
 615            sizes + sizeof(*footer)) {
 616                adsp_err(dsp, "%s: unexpected header length %d\n",
 617                         file, le32_to_cpu(header->len));
 618                goto out_fw;
 619        }
 620
 621        adsp_dbg(dsp, "%s: timestamp %llu\n", file,
 622                 le64_to_cpu(footer->timestamp));
 623
 624        while (pos < firmware->size &&
 625               pos - firmware->size > sizeof(*region)) {
 626                region = (void *)&(firmware->data[pos]);
 627                region_name = "Unknown";
 628                reg = 0;
 629                text = NULL;
 630                offset = le32_to_cpu(region->offset) & 0xffffff;
 631                type = be32_to_cpu(region->type) & 0xff;
 632                mem = wm_adsp_find_region(dsp, type);
 633                
 634                switch (type) {
 635                case WMFW_NAME_TEXT:
 636                        region_name = "Firmware name";
 637                        text = kzalloc(le32_to_cpu(region->len) + 1,
 638                                       GFP_KERNEL);
 639                        break;
 640                case WMFW_INFO_TEXT:
 641                        region_name = "Information";
 642                        text = kzalloc(le32_to_cpu(region->len) + 1,
 643                                       GFP_KERNEL);
 644                        break;
 645                case WMFW_ABSOLUTE:
 646                        region_name = "Absolute";
 647                        reg = offset;
 648                        break;
 649                case WMFW_ADSP1_PM:
 650                        region_name = "PM";
 651                        reg = wm_adsp_region_to_reg(mem, offset);
 652                        break;
 653                case WMFW_ADSP1_DM:
 654                        region_name = "DM";
 655                        reg = wm_adsp_region_to_reg(mem, offset);
 656                        break;
 657                case WMFW_ADSP2_XM:
 658                        region_name = "XM";
 659                        reg = wm_adsp_region_to_reg(mem, offset);
 660                        break;
 661                case WMFW_ADSP2_YM:
 662                        region_name = "YM";
 663                        reg = wm_adsp_region_to_reg(mem, offset);
 664                        break;
 665                case WMFW_ADSP1_ZM:
 666                        region_name = "ZM";
 667                        reg = wm_adsp_region_to_reg(mem, offset);
 668                        break;
 669                default:
 670                        adsp_warn(dsp,
 671                                  "%s.%d: Unknown region type %x at %d(%x)\n",
 672                                  file, regions, type, pos, pos);
 673                        break;
 674                }
 675
 676                adsp_dbg(dsp, "%s.%d: %d bytes at %d in %s\n", file,
 677                         regions, le32_to_cpu(region->len), offset,
 678                         region_name);
 679
 680                if (text) {
 681                        memcpy(text, region->data, le32_to_cpu(region->len));
 682                        adsp_info(dsp, "%s: %s\n", file, text);
 683                        kfree(text);
 684                }
 685
 686                if (reg) {
 687                        buf = wm_adsp_buf_alloc(region->data,
 688                                                le32_to_cpu(region->len),
 689                                                &buf_list);
 690                        if (!buf) {
 691                                adsp_err(dsp, "Out of memory\n");
 692                                ret = -ENOMEM;
 693                                goto out_fw;
 694                        }
 695
 696                        ret = regmap_raw_write_async(regmap, reg, buf->buf,
 697                                                     le32_to_cpu(region->len));
 698                        if (ret != 0) {
 699                                adsp_err(dsp,
 700                                        "%s.%d: Failed to write %d bytes at %d in %s: %d\n",
 701                                        file, regions,
 702                                        le32_to_cpu(region->len), offset,
 703                                        region_name, ret);
 704                                goto out_fw;
 705                        }
 706                }
 707
 708                pos += le32_to_cpu(region->len) + sizeof(*region);
 709                regions++;
 710        }
 711
 712        ret = regmap_async_complete(regmap);
 713        if (ret != 0) {
 714                adsp_err(dsp, "Failed to complete async write: %d\n", ret);
 715                goto out_fw;
 716        }
 717
 718        if (pos > firmware->size)
 719                adsp_warn(dsp, "%s.%d: %zu bytes at end of file\n",
 720                          file, regions, pos - firmware->size);
 721
 722out_fw:
 723        regmap_async_complete(regmap);
 724        wm_adsp_buf_free(&buf_list);
 725        release_firmware(firmware);
 726out:
 727        kfree(file);
 728
 729        return ret;
 730}
 731
 732static int wm_coeff_init_control_caches(struct wm_adsp *adsp)
 733{
 734        struct wm_coeff_ctl *ctl;
 735        int ret;
 736
 737        list_for_each_entry(ctl, &adsp->ctl_list, list) {
 738                if (!ctl->enabled || ctl->set)
 739                        continue;
 740                ret = wm_coeff_read_control(ctl->kcontrol,
 741                                            ctl->cache,
 742                                            ctl->len);
 743                if (ret < 0)
 744                        return ret;
 745        }
 746
 747        return 0;
 748}
 749
 750static int wm_coeff_sync_controls(struct wm_adsp *adsp)
 751{
 752        struct wm_coeff_ctl *ctl;
 753        int ret;
 754
 755        list_for_each_entry(ctl, &adsp->ctl_list, list) {
 756                if (!ctl->enabled)
 757                        continue;
 758                if (ctl->set) {
 759                        ret = wm_coeff_write_control(ctl->kcontrol,
 760                                                     ctl->cache,
 761                                                     ctl->len);
 762                        if (ret < 0)
 763                                return ret;
 764                }
 765        }
 766
 767        return 0;
 768}
 769
 770static void wm_adsp_ctl_work(struct work_struct *work)
 771{
 772        struct wmfw_ctl_work *ctl_work = container_of(work,
 773                                                      struct wmfw_ctl_work,
 774                                                      work);
 775
 776        wmfw_add_ctl(ctl_work->adsp, ctl_work->ctl);
 777        kfree(ctl_work);
 778}
 779
 780static int wm_adsp_create_control(struct wm_adsp *dsp,
 781                                  const struct wm_adsp_alg_region *region)
 782
 783{
 784        struct wm_coeff_ctl *ctl;
 785        struct wmfw_ctl_work *ctl_work;
 786        char *name;
 787        char *region_name;
 788        int ret;
 789
 790        name = kmalloc(PAGE_SIZE, GFP_KERNEL);
 791        if (!name)
 792                return -ENOMEM;
 793
 794        switch (region->type) {
 795        case WMFW_ADSP1_PM:
 796                region_name = "PM";
 797                break;
 798        case WMFW_ADSP1_DM:
 799                region_name = "DM";
 800                break;
 801        case WMFW_ADSP2_XM:
 802                region_name = "XM";
 803                break;
 804        case WMFW_ADSP2_YM:
 805                region_name = "YM";
 806                break;
 807        case WMFW_ADSP1_ZM:
 808                region_name = "ZM";
 809                break;
 810        default:
 811                ret = -EINVAL;
 812                goto err_name;
 813        }
 814
 815        snprintf(name, PAGE_SIZE, "DSP%d %s %x",
 816                 dsp->num, region_name, region->alg);
 817
 818        list_for_each_entry(ctl, &dsp->ctl_list,
 819                            list) {
 820                if (!strcmp(ctl->name, name)) {
 821                        if (!ctl->enabled)
 822                                ctl->enabled = 1;
 823                        goto found;
 824                }
 825        }
 826
 827        ctl = kzalloc(sizeof(*ctl), GFP_KERNEL);
 828        if (!ctl) {
 829                ret = -ENOMEM;
 830                goto err_name;
 831        }
 832        ctl->region = *region;
 833        ctl->name = kmemdup(name, strlen(name) + 1, GFP_KERNEL);
 834        if (!ctl->name) {
 835                ret = -ENOMEM;
 836                goto err_ctl;
 837        }
 838        ctl->enabled = 1;
 839        ctl->set = 0;
 840        ctl->ops.xget = wm_coeff_get;
 841        ctl->ops.xput = wm_coeff_put;
 842        ctl->adsp = dsp;
 843
 844        ctl->len = region->len;
 845        ctl->cache = kzalloc(ctl->len, GFP_KERNEL);
 846        if (!ctl->cache) {
 847                ret = -ENOMEM;
 848                goto err_ctl_name;
 849        }
 850
 851        ctl_work = kzalloc(sizeof(*ctl_work), GFP_KERNEL);
 852        if (!ctl_work) {
 853                ret = -ENOMEM;
 854                goto err_ctl_cache;
 855        }
 856
 857        ctl_work->adsp = dsp;
 858        ctl_work->ctl = ctl;
 859        INIT_WORK(&ctl_work->work, wm_adsp_ctl_work);
 860        schedule_work(&ctl_work->work);
 861
 862found:
 863        kfree(name);
 864
 865        return 0;
 866
 867err_ctl_cache:
 868        kfree(ctl->cache);
 869err_ctl_name:
 870        kfree(ctl->name);
 871err_ctl:
 872        kfree(ctl);
 873err_name:
 874        kfree(name);
 875        return ret;
 876}
 877
 878static int wm_adsp_setup_algs(struct wm_adsp *dsp)
 879{
 880        struct regmap *regmap = dsp->regmap;
 881        struct wmfw_adsp1_id_hdr adsp1_id;
 882        struct wmfw_adsp2_id_hdr adsp2_id;
 883        struct wmfw_adsp1_alg_hdr *adsp1_alg;
 884        struct wmfw_adsp2_alg_hdr *adsp2_alg;
 885        void *alg, *buf;
 886        struct wm_adsp_alg_region *region;
 887        const struct wm_adsp_region *mem;
 888        unsigned int pos, term;
 889        size_t algs, buf_size;
 890        __be32 val;
 891        int i, ret;
 892
 893        switch (dsp->type) {
 894        case WMFW_ADSP1:
 895                mem = wm_adsp_find_region(dsp, WMFW_ADSP1_DM);
 896                break;
 897        case WMFW_ADSP2:
 898                mem = wm_adsp_find_region(dsp, WMFW_ADSP2_XM);
 899                break;
 900        default:
 901                mem = NULL;
 902                break;
 903        }
 904
 905        if (WARN_ON(!mem))
 906                return -EINVAL;
 907
 908        switch (dsp->type) {
 909        case WMFW_ADSP1:
 910                ret = regmap_raw_read(regmap, mem->base, &adsp1_id,
 911                                      sizeof(adsp1_id));
 912                if (ret != 0) {
 913                        adsp_err(dsp, "Failed to read algorithm info: %d\n",
 914                                 ret);
 915                        return ret;
 916                }
 917
 918                buf = &adsp1_id;
 919                buf_size = sizeof(adsp1_id);
 920
 921                algs = be32_to_cpu(adsp1_id.algs);
 922                dsp->fw_id = be32_to_cpu(adsp1_id.fw.id);
 923                adsp_info(dsp, "Firmware: %x v%d.%d.%d, %zu algorithms\n",
 924                          dsp->fw_id,
 925                          (be32_to_cpu(adsp1_id.fw.ver) & 0xff0000) >> 16,
 926                          (be32_to_cpu(adsp1_id.fw.ver) & 0xff00) >> 8,
 927                          be32_to_cpu(adsp1_id.fw.ver) & 0xff,
 928                          algs);
 929
 930                region = kzalloc(sizeof(*region), GFP_KERNEL);
 931                if (!region)
 932                        return -ENOMEM;
 933                region->type = WMFW_ADSP1_ZM;
 934                region->alg = be32_to_cpu(adsp1_id.fw.id);
 935                region->base = be32_to_cpu(adsp1_id.zm);
 936                list_add_tail(&region->list, &dsp->alg_regions);
 937
 938                region = kzalloc(sizeof(*region), GFP_KERNEL);
 939                if (!region)
 940                        return -ENOMEM;
 941                region->type = WMFW_ADSP1_DM;
 942                region->alg = be32_to_cpu(adsp1_id.fw.id);
 943                region->base = be32_to_cpu(adsp1_id.dm);
 944                list_add_tail(&region->list, &dsp->alg_regions);
 945
 946                pos = sizeof(adsp1_id) / 2;
 947                term = pos + ((sizeof(*adsp1_alg) * algs) / 2);
 948                break;
 949
 950        case WMFW_ADSP2:
 951                ret = regmap_raw_read(regmap, mem->base, &adsp2_id,
 952                                      sizeof(adsp2_id));
 953                if (ret != 0) {
 954                        adsp_err(dsp, "Failed to read algorithm info: %d\n",
 955                                 ret);
 956                        return ret;
 957                }
 958
 959                buf = &adsp2_id;
 960                buf_size = sizeof(adsp2_id);
 961
 962                algs = be32_to_cpu(adsp2_id.algs);
 963                dsp->fw_id = be32_to_cpu(adsp2_id.fw.id);
 964                adsp_info(dsp, "Firmware: %x v%d.%d.%d, %zu algorithms\n",
 965                          dsp->fw_id,
 966                          (be32_to_cpu(adsp2_id.fw.ver) & 0xff0000) >> 16,
 967                          (be32_to_cpu(adsp2_id.fw.ver) & 0xff00) >> 8,
 968                          be32_to_cpu(adsp2_id.fw.ver) & 0xff,
 969                          algs);
 970
 971                region = kzalloc(sizeof(*region), GFP_KERNEL);
 972                if (!region)
 973                        return -ENOMEM;
 974                region->type = WMFW_ADSP2_XM;
 975                region->alg = be32_to_cpu(adsp2_id.fw.id);
 976                region->base = be32_to_cpu(adsp2_id.xm);
 977                list_add_tail(&region->list, &dsp->alg_regions);
 978
 979                region = kzalloc(sizeof(*region), GFP_KERNEL);
 980                if (!region)
 981                        return -ENOMEM;
 982                region->type = WMFW_ADSP2_YM;
 983                region->alg = be32_to_cpu(adsp2_id.fw.id);
 984                region->base = be32_to_cpu(adsp2_id.ym);
 985                list_add_tail(&region->list, &dsp->alg_regions);
 986
 987                region = kzalloc(sizeof(*region), GFP_KERNEL);
 988                if (!region)
 989                        return -ENOMEM;
 990                region->type = WMFW_ADSP2_ZM;
 991                region->alg = be32_to_cpu(adsp2_id.fw.id);
 992                region->base = be32_to_cpu(adsp2_id.zm);
 993                list_add_tail(&region->list, &dsp->alg_regions);
 994
 995                pos = sizeof(adsp2_id) / 2;
 996                term = pos + ((sizeof(*adsp2_alg) * algs) / 2);
 997                break;
 998
 999        default:
1000                WARN(1, "Unknown DSP type");
1001                return -EINVAL;
1002        }
1003
1004        if (algs == 0) {
1005                adsp_err(dsp, "No algorithms\n");
1006                return -EINVAL;
1007        }
1008
1009        if (algs > 1024) {
1010                adsp_err(dsp, "Algorithm count %zx excessive\n", algs);
1011                print_hex_dump_bytes(dev_name(dsp->dev), DUMP_PREFIX_OFFSET,
1012                                     buf, buf_size);
1013                return -EINVAL;
1014        }
1015
1016        /* Read the terminator first to validate the length */
1017        ret = regmap_raw_read(regmap, mem->base + term, &val, sizeof(val));
1018        if (ret != 0) {
1019                adsp_err(dsp, "Failed to read algorithm list end: %d\n",
1020                        ret);
1021                return ret;
1022        }
1023
1024        if (be32_to_cpu(val) != 0xbedead)
1025                adsp_warn(dsp, "Algorithm list end %x 0x%x != 0xbeadead\n",
1026                          term, be32_to_cpu(val));
1027
1028        alg = kzalloc((term - pos) * 2, GFP_KERNEL | GFP_DMA);
1029        if (!alg)
1030                return -ENOMEM;
1031
1032        ret = regmap_raw_read(regmap, mem->base + pos, alg, (term - pos) * 2);
1033        if (ret != 0) {
1034                adsp_err(dsp, "Failed to read algorithm list: %d\n",
1035                        ret);
1036                goto out;
1037        }
1038
1039        adsp1_alg = alg;
1040        adsp2_alg = alg;
1041
1042        for (i = 0; i < algs; i++) {
1043                switch (dsp->type) {
1044                case WMFW_ADSP1:
1045                        adsp_info(dsp, "%d: ID %x v%d.%d.%d DM@%x ZM@%x\n",
1046                                  i, be32_to_cpu(adsp1_alg[i].alg.id),
1047                                  (be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff0000) >> 16,
1048                                  (be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff00) >> 8,
1049                                  be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff,
1050                                  be32_to_cpu(adsp1_alg[i].dm),
1051                                  be32_to_cpu(adsp1_alg[i].zm));
1052
1053                        region = kzalloc(sizeof(*region), GFP_KERNEL);
1054                        if (!region)
1055                                return -ENOMEM;
1056                        region->type = WMFW_ADSP1_DM;
1057                        region->alg = be32_to_cpu(adsp1_alg[i].alg.id);
1058                        region->base = be32_to_cpu(adsp1_alg[i].dm);
1059                        region->len = 0;
1060                        list_add_tail(&region->list, &dsp->alg_regions);
1061                        if (i + 1 < algs) {
1062                                region->len = be32_to_cpu(adsp1_alg[i + 1].dm);
1063                                region->len -= be32_to_cpu(adsp1_alg[i].dm);
1064                                region->len *= 4;
1065                                wm_adsp_create_control(dsp, region);
1066                        } else {
1067                                adsp_warn(dsp, "Missing length info for region DM with ID %x\n",
1068                                          be32_to_cpu(adsp1_alg[i].alg.id));
1069                        }
1070
1071                        region = kzalloc(sizeof(*region), GFP_KERNEL);
1072                        if (!region)
1073                                return -ENOMEM;
1074                        region->type = WMFW_ADSP1_ZM;
1075                        region->alg = be32_to_cpu(adsp1_alg[i].alg.id);
1076                        region->base = be32_to_cpu(adsp1_alg[i].zm);
1077                        region->len = 0;
1078                        list_add_tail(&region->list, &dsp->alg_regions);
1079                        if (i + 1 < algs) {
1080                                region->len = be32_to_cpu(adsp1_alg[i + 1].zm);
1081                                region->len -= be32_to_cpu(adsp1_alg[i].zm);
1082                                region->len *= 4;
1083                                wm_adsp_create_control(dsp, region);
1084                        } else {
1085                                adsp_warn(dsp, "Missing length info for region ZM with ID %x\n",
1086                                          be32_to_cpu(adsp1_alg[i].alg.id));
1087                        }
1088                        break;
1089
1090                case WMFW_ADSP2:
1091                        adsp_info(dsp,
1092                                  "%d: ID %x v%d.%d.%d XM@%x YM@%x ZM@%x\n",
1093                                  i, be32_to_cpu(adsp2_alg[i].alg.id),
1094                                  (be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff0000) >> 16,
1095                                  (be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff00) >> 8,
1096                                  be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff,
1097                                  be32_to_cpu(adsp2_alg[i].xm),
1098                                  be32_to_cpu(adsp2_alg[i].ym),
1099                                  be32_to_cpu(adsp2_alg[i].zm));
1100
1101                        region = kzalloc(sizeof(*region), GFP_KERNEL);
1102                        if (!region)
1103                                return -ENOMEM;
1104                        region->type = WMFW_ADSP2_XM;
1105                        region->alg = be32_to_cpu(adsp2_alg[i].alg.id);
1106                        region->base = be32_to_cpu(adsp2_alg[i].xm);
1107                        region->len = 0;
1108                        list_add_tail(&region->list, &dsp->alg_regions);
1109                        if (i + 1 < algs) {
1110                                region->len = be32_to_cpu(adsp2_alg[i + 1].xm);
1111                                region->len -= be32_to_cpu(adsp2_alg[i].xm);
1112                                region->len *= 4;
1113                                wm_adsp_create_control(dsp, region);
1114                        } else {
1115                                adsp_warn(dsp, "Missing length info for region XM with ID %x\n",
1116                                          be32_to_cpu(adsp2_alg[i].alg.id));
1117                        }
1118
1119                        region = kzalloc(sizeof(*region), GFP_KERNEL);
1120                        if (!region)
1121                                return -ENOMEM;
1122                        region->type = WMFW_ADSP2_YM;
1123                        region->alg = be32_to_cpu(adsp2_alg[i].alg.id);
1124                        region->base = be32_to_cpu(adsp2_alg[i].ym);
1125                        region->len = 0;
1126                        list_add_tail(&region->list, &dsp->alg_regions);
1127                        if (i + 1 < algs) {
1128                                region->len = be32_to_cpu(adsp2_alg[i + 1].ym);
1129                                region->len -= be32_to_cpu(adsp2_alg[i].ym);
1130                                region->len *= 4;
1131                                wm_adsp_create_control(dsp, region);
1132                        } else {
1133                                adsp_warn(dsp, "Missing length info for region YM with ID %x\n",
1134                                          be32_to_cpu(adsp2_alg[i].alg.id));
1135                        }
1136
1137                        region = kzalloc(sizeof(*region), GFP_KERNEL);
1138                        if (!region)
1139                                return -ENOMEM;
1140                        region->type = WMFW_ADSP2_ZM;
1141                        region->alg = be32_to_cpu(adsp2_alg[i].alg.id);
1142                        region->base = be32_to_cpu(adsp2_alg[i].zm);
1143                        region->len = 0;
1144                        list_add_tail(&region->list, &dsp->alg_regions);
1145                        if (i + 1 < algs) {
1146                                region->len = be32_to_cpu(adsp2_alg[i + 1].zm);
1147                                region->len -= be32_to_cpu(adsp2_alg[i].zm);
1148                                region->len *= 4;
1149                                wm_adsp_create_control(dsp, region);
1150                        } else {
1151                                adsp_warn(dsp, "Missing length info for region ZM with ID %x\n",
1152                                          be32_to_cpu(adsp2_alg[i].alg.id));
1153                        }
1154                        break;
1155                }
1156        }
1157
1158out:
1159        kfree(alg);
1160        return ret;
1161}
1162
1163static int wm_adsp_load_coeff(struct wm_adsp *dsp)
1164{
1165        LIST_HEAD(buf_list);
1166        struct regmap *regmap = dsp->regmap;
1167        struct wmfw_coeff_hdr *hdr;
1168        struct wmfw_coeff_item *blk;
1169        const struct firmware *firmware;
1170        const struct wm_adsp_region *mem;
1171        struct wm_adsp_alg_region *alg_region;
1172        const char *region_name;
1173        int ret, pos, blocks, type, offset, reg;
1174        char *file;
1175        struct wm_adsp_buf *buf;
1176        int tmp;
1177
1178        file = kzalloc(PAGE_SIZE, GFP_KERNEL);
1179        if (file == NULL)
1180                return -ENOMEM;
1181
1182        snprintf(file, PAGE_SIZE, "%s-dsp%d-%s.bin", dsp->part, dsp->num,
1183                 wm_adsp_fw[dsp->fw].file);
1184        file[PAGE_SIZE - 1] = '\0';
1185
1186        ret = request_firmware(&firmware, file, dsp->dev);
1187        if (ret != 0) {
1188                adsp_warn(dsp, "Failed to request '%s'\n", file);
1189                ret = 0;
1190                goto out;
1191        }
1192        ret = -EINVAL;
1193
1194        if (sizeof(*hdr) >= firmware->size) {
1195                adsp_err(dsp, "%s: file too short, %zu bytes\n",
1196                        file, firmware->size);
1197                goto out_fw;
1198        }
1199
1200        hdr = (void*)&firmware->data[0];
1201        if (memcmp(hdr->magic, "WMDR", 4) != 0) {
1202                adsp_err(dsp, "%s: invalid magic\n", file);
1203                goto out_fw;
1204        }
1205
1206        switch (be32_to_cpu(hdr->rev) & 0xff) {
1207        case 1:
1208                break;
1209        default:
1210                adsp_err(dsp, "%s: Unsupported coefficient file format %d\n",
1211                         file, be32_to_cpu(hdr->rev) & 0xff);
1212                ret = -EINVAL;
1213                goto out_fw;
1214        }
1215
1216        adsp_dbg(dsp, "%s: v%d.%d.%d\n", file,
1217                (le32_to_cpu(hdr->ver) >> 16) & 0xff,
1218                (le32_to_cpu(hdr->ver) >>  8) & 0xff,
1219                le32_to_cpu(hdr->ver) & 0xff);
1220
1221        pos = le32_to_cpu(hdr->len);
1222
1223        blocks = 0;
1224        while (pos < firmware->size &&
1225               pos - firmware->size > sizeof(*blk)) {
1226                blk = (void*)(&firmware->data[pos]);
1227
1228                type = le16_to_cpu(blk->type);
1229                offset = le16_to_cpu(blk->offset);
1230
1231                adsp_dbg(dsp, "%s.%d: %x v%d.%d.%d\n",
1232                         file, blocks, le32_to_cpu(blk->id),
1233                         (le32_to_cpu(blk->ver) >> 16) & 0xff,
1234                         (le32_to_cpu(blk->ver) >>  8) & 0xff,
1235                         le32_to_cpu(blk->ver) & 0xff);
1236                adsp_dbg(dsp, "%s.%d: %d bytes at 0x%x in %x\n",
1237                         file, blocks, le32_to_cpu(blk->len), offset, type);
1238
1239                reg = 0;
1240                region_name = "Unknown";
1241                switch (type) {
1242                case (WMFW_NAME_TEXT << 8):
1243                case (WMFW_INFO_TEXT << 8):
1244                        break;
1245                case (WMFW_ABSOLUTE << 8):
1246                        /*
1247                         * Old files may use this for global
1248                         * coefficients.
1249                         */
1250                        if (le32_to_cpu(blk->id) == dsp->fw_id &&
1251                            offset == 0) {
1252                                region_name = "global coefficients";
1253                                mem = wm_adsp_find_region(dsp, type);
1254                                if (!mem) {
1255                                        adsp_err(dsp, "No ZM\n");
1256                                        break;
1257                                }
1258                                reg = wm_adsp_region_to_reg(mem, 0);
1259
1260                        } else {
1261                                region_name = "register";
1262                                reg = offset;
1263                        }
1264                        break;
1265
1266                case WMFW_ADSP1_DM:
1267                case WMFW_ADSP1_ZM:
1268                case WMFW_ADSP2_XM:
1269                case WMFW_ADSP2_YM:
1270                        adsp_dbg(dsp, "%s.%d: %d bytes in %x for %x\n",
1271                                 file, blocks, le32_to_cpu(blk->len),
1272                                 type, le32_to_cpu(blk->id));
1273
1274                        mem = wm_adsp_find_region(dsp, type);
1275                        if (!mem) {
1276                                adsp_err(dsp, "No base for region %x\n", type);
1277                                break;
1278                        }
1279
1280                        reg = 0;
1281                        list_for_each_entry(alg_region,
1282                                            &dsp->alg_regions, list) {
1283                                if (le32_to_cpu(blk->id) == alg_region->alg &&
1284                                    type == alg_region->type) {
1285                                        reg = alg_region->base;
1286                                        reg = wm_adsp_region_to_reg(mem,
1287                                                                    reg);
1288                                        reg += offset;
1289                                        break;
1290                                }
1291                        }
1292
1293                        if (reg == 0)
1294                                adsp_err(dsp, "No %x for algorithm %x\n",
1295                                         type, le32_to_cpu(blk->id));
1296                        break;
1297
1298                default:
1299                        adsp_err(dsp, "%s.%d: Unknown region type %x at %d\n",
1300                                 file, blocks, type, pos);
1301                        break;
1302                }
1303
1304                if (reg) {
1305                        buf = wm_adsp_buf_alloc(blk->data,
1306                                                le32_to_cpu(blk->len),
1307                                                &buf_list);
1308                        if (!buf) {
1309                                adsp_err(dsp, "Out of memory\n");
1310                                ret = -ENOMEM;
1311                                goto out_fw;
1312                        }
1313
1314                        adsp_dbg(dsp, "%s.%d: Writing %d bytes at %x\n",
1315                                 file, blocks, le32_to_cpu(blk->len),
1316                                 reg);
1317                        ret = regmap_raw_write_async(regmap, reg, buf->buf,
1318                                                     le32_to_cpu(blk->len));
1319                        if (ret != 0) {
1320                                adsp_err(dsp,
1321                                        "%s.%d: Failed to write to %x in %s: %d\n",
1322                                        file, blocks, reg, region_name, ret);
1323                        }
1324                }
1325
1326                tmp = le32_to_cpu(blk->len) % 4;
1327                if (tmp)
1328                        pos += le32_to_cpu(blk->len) + (4 - tmp) + sizeof(*blk);
1329                else
1330                        pos += le32_to_cpu(blk->len) + sizeof(*blk);
1331
1332                blocks++;
1333        }
1334
1335        ret = regmap_async_complete(regmap);
1336        if (ret != 0)
1337                adsp_err(dsp, "Failed to complete async write: %d\n", ret);
1338
1339        if (pos > firmware->size)
1340                adsp_warn(dsp, "%s.%d: %zu bytes at end of file\n",
1341                          file, blocks, pos - firmware->size);
1342
1343out_fw:
1344        release_firmware(firmware);
1345        wm_adsp_buf_free(&buf_list);
1346out:
1347        kfree(file);
1348        return ret;
1349}
1350
1351int wm_adsp1_init(struct wm_adsp *adsp)
1352{
1353        INIT_LIST_HEAD(&adsp->alg_regions);
1354
1355        return 0;
1356}
1357EXPORT_SYMBOL_GPL(wm_adsp1_init);
1358
1359int wm_adsp1_event(struct snd_soc_dapm_widget *w,
1360                   struct snd_kcontrol *kcontrol,
1361                   int event)
1362{
1363        struct snd_soc_codec *codec = w->codec;
1364        struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec);
1365        struct wm_adsp *dsp = &dsps[w->shift];
1366        struct wm_adsp_alg_region *alg_region;
1367        struct wm_coeff_ctl *ctl;
1368        int ret;
1369        int val;
1370
1371        dsp->card = codec->card;
1372
1373        switch (event) {
1374        case SND_SOC_DAPM_POST_PMU:
1375                regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
1376                                   ADSP1_SYS_ENA, ADSP1_SYS_ENA);
1377
1378                /*
1379                 * For simplicity set the DSP clock rate to be the
1380                 * SYSCLK rate rather than making it configurable.
1381                 */
1382                if(dsp->sysclk_reg) {
1383                        ret = regmap_read(dsp->regmap, dsp->sysclk_reg, &val);
1384                        if (ret != 0) {
1385                                adsp_err(dsp, "Failed to read SYSCLK state: %d\n",
1386                                ret);
1387                                return ret;
1388                        }
1389
1390                        val = (val & dsp->sysclk_mask)
1391                                >> dsp->sysclk_shift;
1392
1393                        ret = regmap_update_bits(dsp->regmap,
1394                                                 dsp->base + ADSP1_CONTROL_31,
1395                                                 ADSP1_CLK_SEL_MASK, val);
1396                        if (ret != 0) {
1397                                adsp_err(dsp, "Failed to set clock rate: %d\n",
1398                                         ret);
1399                                return ret;
1400                        }
1401                }
1402
1403                ret = wm_adsp_load(dsp);
1404                if (ret != 0)
1405                        goto err;
1406
1407                ret = wm_adsp_setup_algs(dsp);
1408                if (ret != 0)
1409                        goto err;
1410
1411                ret = wm_adsp_load_coeff(dsp);
1412                if (ret != 0)
1413                        goto err;
1414
1415                /* Initialize caches for enabled and unset controls */
1416                ret = wm_coeff_init_control_caches(dsp);
1417                if (ret != 0)
1418                        goto err;
1419
1420                /* Sync set controls */
1421                ret = wm_coeff_sync_controls(dsp);
1422                if (ret != 0)
1423                        goto err;
1424
1425                /* Start the core running */
1426                regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
1427                                   ADSP1_CORE_ENA | ADSP1_START,
1428                                   ADSP1_CORE_ENA | ADSP1_START);
1429                break;
1430
1431        case SND_SOC_DAPM_PRE_PMD:
1432                /* Halt the core */
1433                regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
1434                                   ADSP1_CORE_ENA | ADSP1_START, 0);
1435
1436                regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_19,
1437                                   ADSP1_WDMA_BUFFER_LENGTH_MASK, 0);
1438
1439                regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
1440                                   ADSP1_SYS_ENA, 0);
1441
1442                list_for_each_entry(ctl, &dsp->ctl_list, list)
1443                        ctl->enabled = 0;
1444
1445                while (!list_empty(&dsp->alg_regions)) {
1446                        alg_region = list_first_entry(&dsp->alg_regions,
1447                                                      struct wm_adsp_alg_region,
1448                                                      list);
1449                        list_del(&alg_region->list);
1450                        kfree(alg_region);
1451                }
1452                break;
1453
1454        default:
1455                break;
1456        }
1457
1458        return 0;
1459
1460err:
1461        regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
1462                           ADSP1_SYS_ENA, 0);
1463        return ret;
1464}
1465EXPORT_SYMBOL_GPL(wm_adsp1_event);
1466
1467static int wm_adsp2_ena(struct wm_adsp *dsp)
1468{
1469        unsigned int val;
1470        int ret, count;
1471
1472        ret = regmap_update_bits_async(dsp->regmap, dsp->base + ADSP2_CONTROL,
1473                                       ADSP2_SYS_ENA, ADSP2_SYS_ENA);
1474        if (ret != 0)
1475                return ret;
1476
1477        /* Wait for the RAM to start, should be near instantaneous */
1478        for (count = 0; count < 10; ++count) {
1479                ret = regmap_read(dsp->regmap, dsp->base + ADSP2_STATUS1,
1480                                  &val);
1481                if (ret != 0)
1482                        return ret;
1483
1484                if (val & ADSP2_RAM_RDY)
1485                        break;
1486
1487                msleep(1);
1488        }
1489
1490        if (!(val & ADSP2_RAM_RDY)) {
1491                adsp_err(dsp, "Failed to start DSP RAM\n");
1492                return -EBUSY;
1493        }
1494
1495        adsp_dbg(dsp, "RAM ready after %d polls\n", count);
1496
1497        return 0;
1498}
1499
1500static void wm_adsp2_boot_work(struct work_struct *work)
1501{
1502        struct wm_adsp *dsp = container_of(work,
1503                                           struct wm_adsp,
1504                                           boot_work);
1505        int ret;
1506        unsigned int val;
1507
1508        /*
1509         * For simplicity set the DSP clock rate to be the
1510         * SYSCLK rate rather than making it configurable.
1511         */
1512        ret = regmap_read(dsp->regmap, ARIZONA_SYSTEM_CLOCK_1, &val);
1513        if (ret != 0) {
1514                adsp_err(dsp, "Failed to read SYSCLK state: %d\n", ret);
1515                return;
1516        }
1517        val = (val & ARIZONA_SYSCLK_FREQ_MASK)
1518                >> ARIZONA_SYSCLK_FREQ_SHIFT;
1519
1520        ret = regmap_update_bits_async(dsp->regmap,
1521                                       dsp->base + ADSP2_CLOCKING,
1522                                       ADSP2_CLK_SEL_MASK, val);
1523        if (ret != 0) {
1524                adsp_err(dsp, "Failed to set clock rate: %d\n", ret);
1525                return;
1526        }
1527
1528        if (dsp->dvfs) {
1529                ret = regmap_read(dsp->regmap,
1530                                  dsp->base + ADSP2_CLOCKING, &val);
1531                if (ret != 0) {
1532                        dev_err(dsp->dev, "Failed to read clocking: %d\n", ret);
1533                        return;
1534                }
1535
1536                if ((val & ADSP2_CLK_SEL_MASK) >= 3) {
1537                        ret = regulator_enable(dsp->dvfs);
1538                        if (ret != 0) {
1539                                dev_err(dsp->dev,
1540                                        "Failed to enable supply: %d\n",
1541                                        ret);
1542                                return;
1543                        }
1544
1545                        ret = regulator_set_voltage(dsp->dvfs,
1546                                                    1800000,
1547                                                    1800000);
1548                        if (ret != 0) {
1549                                dev_err(dsp->dev,
1550                                        "Failed to raise supply: %d\n",
1551                                        ret);
1552                                return;
1553                        }
1554                }
1555        }
1556
1557        ret = wm_adsp2_ena(dsp);
1558        if (ret != 0)
1559                return;
1560
1561        ret = wm_adsp_load(dsp);
1562        if (ret != 0)
1563                goto err;
1564
1565        ret = wm_adsp_setup_algs(dsp);
1566        if (ret != 0)
1567                goto err;
1568
1569        ret = wm_adsp_load_coeff(dsp);
1570        if (ret != 0)
1571                goto err;
1572
1573        /* Initialize caches for enabled and unset controls */
1574        ret = wm_coeff_init_control_caches(dsp);
1575        if (ret != 0)
1576                goto err;
1577
1578        /* Sync set controls */
1579        ret = wm_coeff_sync_controls(dsp);
1580        if (ret != 0)
1581                goto err;
1582
1583        ret = regmap_update_bits_async(dsp->regmap,
1584                                       dsp->base + ADSP2_CONTROL,
1585                                       ADSP2_CORE_ENA,
1586                                       ADSP2_CORE_ENA);
1587        if (ret != 0)
1588                goto err;
1589
1590        dsp->running = true;
1591
1592        return;
1593
1594err:
1595        regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
1596                           ADSP2_SYS_ENA | ADSP2_CORE_ENA | ADSP2_START, 0);
1597}
1598
1599int wm_adsp2_early_event(struct snd_soc_dapm_widget *w,
1600                   struct snd_kcontrol *kcontrol, int event)
1601{
1602        struct snd_soc_codec *codec = w->codec;
1603        struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec);
1604        struct wm_adsp *dsp = &dsps[w->shift];
1605
1606        dsp->card = codec->card;
1607
1608        switch (event) {
1609        case SND_SOC_DAPM_PRE_PMU:
1610                queue_work(system_unbound_wq, &dsp->boot_work);
1611                break;
1612        default:
1613                break;
1614        };
1615
1616        return 0;
1617}
1618EXPORT_SYMBOL_GPL(wm_adsp2_early_event);
1619
1620int wm_adsp2_event(struct snd_soc_dapm_widget *w,
1621                   struct snd_kcontrol *kcontrol, int event)
1622{
1623        struct snd_soc_codec *codec = w->codec;
1624        struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec);
1625        struct wm_adsp *dsp = &dsps[w->shift];
1626        struct wm_adsp_alg_region *alg_region;
1627        struct wm_coeff_ctl *ctl;
1628        int ret;
1629
1630        switch (event) {
1631        case SND_SOC_DAPM_POST_PMU:
1632                flush_work(&dsp->boot_work);
1633
1634                if (!dsp->running)
1635                        return -EIO;
1636
1637                ret = regmap_update_bits(dsp->regmap,
1638                                         dsp->base + ADSP2_CONTROL,
1639                                         ADSP2_START,
1640                                         ADSP2_START);
1641                if (ret != 0)
1642                        goto err;
1643                break;
1644
1645        case SND_SOC_DAPM_PRE_PMD:
1646                dsp->running = false;
1647
1648                regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
1649                                   ADSP2_SYS_ENA | ADSP2_CORE_ENA |
1650                                   ADSP2_START, 0);
1651
1652                /* Make sure DMAs are quiesced */
1653                regmap_write(dsp->regmap, dsp->base + ADSP2_WDMA_CONFIG_1, 0);
1654                regmap_write(dsp->regmap, dsp->base + ADSP2_WDMA_CONFIG_2, 0);
1655                regmap_write(dsp->regmap, dsp->base + ADSP2_RDMA_CONFIG_1, 0);
1656
1657                if (dsp->dvfs) {
1658                        ret = regulator_set_voltage(dsp->dvfs, 1200000,
1659                                                    1800000);
1660                        if (ret != 0)
1661                                dev_warn(dsp->dev,
1662                                         "Failed to lower supply: %d\n",
1663                                         ret);
1664
1665                        ret = regulator_disable(dsp->dvfs);
1666                        if (ret != 0)
1667                                dev_err(dsp->dev,
1668                                        "Failed to enable supply: %d\n",
1669                                        ret);
1670                }
1671
1672                list_for_each_entry(ctl, &dsp->ctl_list, list)
1673                        ctl->enabled = 0;
1674
1675                while (!list_empty(&dsp->alg_regions)) {
1676                        alg_region = list_first_entry(&dsp->alg_regions,
1677                                                      struct wm_adsp_alg_region,
1678                                                      list);
1679                        list_del(&alg_region->list);
1680                        kfree(alg_region);
1681                }
1682                break;
1683
1684        default:
1685                break;
1686        }
1687
1688        return 0;
1689err:
1690        regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
1691                           ADSP2_SYS_ENA | ADSP2_CORE_ENA | ADSP2_START, 0);
1692        return ret;
1693}
1694EXPORT_SYMBOL_GPL(wm_adsp2_event);
1695
1696int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs)
1697{
1698        int ret;
1699
1700        /*
1701         * Disable the DSP memory by default when in reset for a small
1702         * power saving.
1703         */
1704        ret = regmap_update_bits(adsp->regmap, adsp->base + ADSP2_CONTROL,
1705                                 ADSP2_MEM_ENA, 0);
1706        if (ret != 0) {
1707                adsp_err(adsp, "Failed to clear memory retention: %d\n", ret);
1708                return ret;
1709        }
1710
1711        INIT_LIST_HEAD(&adsp->alg_regions);
1712        INIT_LIST_HEAD(&adsp->ctl_list);
1713        INIT_WORK(&adsp->boot_work, wm_adsp2_boot_work);
1714
1715        if (dvfs) {
1716                adsp->dvfs = devm_regulator_get(adsp->dev, "DCVDD");
1717                if (IS_ERR(adsp->dvfs)) {
1718                        ret = PTR_ERR(adsp->dvfs);
1719                        dev_err(adsp->dev, "Failed to get DCVDD: %d\n", ret);
1720                        return ret;
1721                }
1722
1723                ret = regulator_enable(adsp->dvfs);
1724                if (ret != 0) {
1725                        dev_err(adsp->dev, "Failed to enable DCVDD: %d\n",
1726                                ret);
1727                        return ret;
1728                }
1729
1730                ret = regulator_set_voltage(adsp->dvfs, 1200000, 1800000);
1731                if (ret != 0) {
1732                        dev_err(adsp->dev, "Failed to initialise DVFS: %d\n",
1733                                ret);
1734                        return ret;
1735                }
1736
1737                ret = regulator_disable(adsp->dvfs);
1738                if (ret != 0) {
1739                        dev_err(adsp->dev, "Failed to disable DCVDD: %d\n",
1740                                ret);
1741                        return ret;
1742                }
1743        }
1744
1745        return 0;
1746}
1747EXPORT_SYMBOL_GPL(wm_adsp2_init);
1748