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/vmalloc.h>
  25#include <linux/workqueue.h>
  26#include <linux/debugfs.h>
  27#include <sound/core.h>
  28#include <sound/pcm.h>
  29#include <sound/pcm_params.h>
  30#include <sound/soc.h>
  31#include <sound/jack.h>
  32#include <sound/initval.h>
  33#include <sound/tlv.h>
  34
  35#include "wm_adsp.h"
  36
  37#define adsp_crit(_dsp, fmt, ...) \
  38        dev_crit(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__)
  39#define adsp_err(_dsp, fmt, ...) \
  40        dev_err(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__)
  41#define adsp_warn(_dsp, fmt, ...) \
  42        dev_warn(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__)
  43#define adsp_info(_dsp, fmt, ...) \
  44        dev_info(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__)
  45#define adsp_dbg(_dsp, fmt, ...) \
  46        dev_dbg(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__)
  47
  48#define ADSP1_CONTROL_1                   0x00
  49#define ADSP1_CONTROL_2                   0x02
  50#define ADSP1_CONTROL_3                   0x03
  51#define ADSP1_CONTROL_4                   0x04
  52#define ADSP1_CONTROL_5                   0x06
  53#define ADSP1_CONTROL_6                   0x07
  54#define ADSP1_CONTROL_7                   0x08
  55#define ADSP1_CONTROL_8                   0x09
  56#define ADSP1_CONTROL_9                   0x0A
  57#define ADSP1_CONTROL_10                  0x0B
  58#define ADSP1_CONTROL_11                  0x0C
  59#define ADSP1_CONTROL_12                  0x0D
  60#define ADSP1_CONTROL_13                  0x0F
  61#define ADSP1_CONTROL_14                  0x10
  62#define ADSP1_CONTROL_15                  0x11
  63#define ADSP1_CONTROL_16                  0x12
  64#define ADSP1_CONTROL_17                  0x13
  65#define ADSP1_CONTROL_18                  0x14
  66#define ADSP1_CONTROL_19                  0x16
  67#define ADSP1_CONTROL_20                  0x17
  68#define ADSP1_CONTROL_21                  0x18
  69#define ADSP1_CONTROL_22                  0x1A
  70#define ADSP1_CONTROL_23                  0x1B
  71#define ADSP1_CONTROL_24                  0x1C
  72#define ADSP1_CONTROL_25                  0x1E
  73#define ADSP1_CONTROL_26                  0x20
  74#define ADSP1_CONTROL_27                  0x21
  75#define ADSP1_CONTROL_28                  0x22
  76#define ADSP1_CONTROL_29                  0x23
  77#define ADSP1_CONTROL_30                  0x24
  78#define ADSP1_CONTROL_31                  0x26
  79
  80/*
  81 * ADSP1 Control 19
  82 */
  83#define ADSP1_WDMA_BUFFER_LENGTH_MASK     0x00FF  /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */
  84#define ADSP1_WDMA_BUFFER_LENGTH_SHIFT         0  /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */
  85#define ADSP1_WDMA_BUFFER_LENGTH_WIDTH         8  /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */
  86
  87
  88/*
  89 * ADSP1 Control 30
  90 */
  91#define ADSP1_DBG_CLK_ENA                 0x0008  /* DSP1_DBG_CLK_ENA */
  92#define ADSP1_DBG_CLK_ENA_MASK            0x0008  /* DSP1_DBG_CLK_ENA */
  93#define ADSP1_DBG_CLK_ENA_SHIFT                3  /* DSP1_DBG_CLK_ENA */
  94#define ADSP1_DBG_CLK_ENA_WIDTH                1  /* DSP1_DBG_CLK_ENA */
  95#define ADSP1_SYS_ENA                     0x0004  /* DSP1_SYS_ENA */
  96#define ADSP1_SYS_ENA_MASK                0x0004  /* DSP1_SYS_ENA */
  97#define ADSP1_SYS_ENA_SHIFT                    2  /* DSP1_SYS_ENA */
  98#define ADSP1_SYS_ENA_WIDTH                    1  /* DSP1_SYS_ENA */
  99#define ADSP1_CORE_ENA                    0x0002  /* DSP1_CORE_ENA */
 100#define ADSP1_CORE_ENA_MASK               0x0002  /* DSP1_CORE_ENA */
 101#define ADSP1_CORE_ENA_SHIFT                   1  /* DSP1_CORE_ENA */
 102#define ADSP1_CORE_ENA_WIDTH                   1  /* DSP1_CORE_ENA */
 103#define ADSP1_START                       0x0001  /* DSP1_START */
 104#define ADSP1_START_MASK                  0x0001  /* DSP1_START */
 105#define ADSP1_START_SHIFT                      0  /* DSP1_START */
 106#define ADSP1_START_WIDTH                      1  /* DSP1_START */
 107
 108/*
 109 * ADSP1 Control 31
 110 */
 111#define ADSP1_CLK_SEL_MASK                0x0007  /* CLK_SEL_ENA */
 112#define ADSP1_CLK_SEL_SHIFT                    0  /* CLK_SEL_ENA */
 113#define ADSP1_CLK_SEL_WIDTH                    3  /* CLK_SEL_ENA */
 114
 115#define ADSP2_CONTROL        0x0
 116#define ADSP2_CLOCKING       0x1
 117#define ADSP2_STATUS1        0x4
 118#define ADSP2_WDMA_CONFIG_1 0x30
 119#define ADSP2_WDMA_CONFIG_2 0x31
 120#define ADSP2_RDMA_CONFIG_1 0x34
 121
 122#define ADSP2_SCRATCH0        0x40
 123#define ADSP2_SCRATCH1        0x41
 124#define ADSP2_SCRATCH2        0x42
 125#define ADSP2_SCRATCH3        0x43
 126
 127/*
 128 * ADSP2 Control
 129 */
 130
 131#define ADSP2_MEM_ENA                     0x0010  /* DSP1_MEM_ENA */
 132#define ADSP2_MEM_ENA_MASK                0x0010  /* DSP1_MEM_ENA */
 133#define ADSP2_MEM_ENA_SHIFT                    4  /* DSP1_MEM_ENA */
 134#define ADSP2_MEM_ENA_WIDTH                    1  /* DSP1_MEM_ENA */
 135#define ADSP2_SYS_ENA                     0x0004  /* DSP1_SYS_ENA */
 136#define ADSP2_SYS_ENA_MASK                0x0004  /* DSP1_SYS_ENA */
 137#define ADSP2_SYS_ENA_SHIFT                    2  /* DSP1_SYS_ENA */
 138#define ADSP2_SYS_ENA_WIDTH                    1  /* DSP1_SYS_ENA */
 139#define ADSP2_CORE_ENA                    0x0002  /* DSP1_CORE_ENA */
 140#define ADSP2_CORE_ENA_MASK               0x0002  /* DSP1_CORE_ENA */
 141#define ADSP2_CORE_ENA_SHIFT                   1  /* DSP1_CORE_ENA */
 142#define ADSP2_CORE_ENA_WIDTH                   1  /* DSP1_CORE_ENA */
 143#define ADSP2_START                       0x0001  /* DSP1_START */
 144#define ADSP2_START_MASK                  0x0001  /* DSP1_START */
 145#define ADSP2_START_SHIFT                      0  /* DSP1_START */
 146#define ADSP2_START_WIDTH                      1  /* DSP1_START */
 147
 148/*
 149 * ADSP2 clocking
 150 */
 151#define ADSP2_CLK_SEL_MASK                0x0007  /* CLK_SEL_ENA */
 152#define ADSP2_CLK_SEL_SHIFT                    0  /* CLK_SEL_ENA */
 153#define ADSP2_CLK_SEL_WIDTH                    3  /* CLK_SEL_ENA */
 154
 155/*
 156 * ADSP2 Status 1
 157 */
 158#define ADSP2_RAM_RDY                     0x0001
 159#define ADSP2_RAM_RDY_MASK                0x0001
 160#define ADSP2_RAM_RDY_SHIFT                    0
 161#define ADSP2_RAM_RDY_WIDTH                    1
 162
 163#define ADSP_MAX_STD_CTRL_SIZE               512
 164
 165struct wm_adsp_buf {
 166        struct list_head list;
 167        void *buf;
 168};
 169
 170static struct wm_adsp_buf *wm_adsp_buf_alloc(const void *src, size_t len,
 171                                             struct list_head *list)
 172{
 173        struct wm_adsp_buf *buf = kzalloc(sizeof(*buf), GFP_KERNEL);
 174
 175        if (buf == NULL)
 176                return NULL;
 177
 178        buf->buf = vmalloc(len);
 179        if (!buf->buf) {
 180                vfree(buf);
 181                return NULL;
 182        }
 183        memcpy(buf->buf, src, len);
 184
 185        if (list)
 186                list_add_tail(&buf->list, list);
 187
 188        return buf;
 189}
 190
 191static void wm_adsp_buf_free(struct list_head *list)
 192{
 193        while (!list_empty(list)) {
 194                struct wm_adsp_buf *buf = list_first_entry(list,
 195                                                           struct wm_adsp_buf,
 196                                                           list);
 197                list_del(&buf->list);
 198                vfree(buf->buf);
 199                kfree(buf);
 200        }
 201}
 202
 203#define WM_ADSP_FW_MBC_VSS  0
 204#define WM_ADSP_FW_HIFI     1
 205#define WM_ADSP_FW_TX       2
 206#define WM_ADSP_FW_TX_SPK   3
 207#define WM_ADSP_FW_RX       4
 208#define WM_ADSP_FW_RX_ANC   5
 209#define WM_ADSP_FW_CTRL     6
 210#define WM_ADSP_FW_ASR      7
 211#define WM_ADSP_FW_TRACE    8
 212#define WM_ADSP_FW_SPK_PROT 9
 213#define WM_ADSP_FW_MISC     10
 214
 215#define WM_ADSP_NUM_FW      11
 216
 217static const char *wm_adsp_fw_text[WM_ADSP_NUM_FW] = {
 218        [WM_ADSP_FW_MBC_VSS] =  "MBC/VSS",
 219        [WM_ADSP_FW_HIFI] =     "MasterHiFi",
 220        [WM_ADSP_FW_TX] =       "Tx",
 221        [WM_ADSP_FW_TX_SPK] =   "Tx Speaker",
 222        [WM_ADSP_FW_RX] =       "Rx",
 223        [WM_ADSP_FW_RX_ANC] =   "Rx ANC",
 224        [WM_ADSP_FW_CTRL] =     "Voice Ctrl",
 225        [WM_ADSP_FW_ASR] =      "ASR Assist",
 226        [WM_ADSP_FW_TRACE] =    "Dbg Trace",
 227        [WM_ADSP_FW_SPK_PROT] = "Protection",
 228        [WM_ADSP_FW_MISC] =     "Misc",
 229};
 230
 231struct wm_adsp_system_config_xm_hdr {
 232        __be32 sys_enable;
 233        __be32 fw_id;
 234        __be32 fw_rev;
 235        __be32 boot_status;
 236        __be32 watchdog;
 237        __be32 dma_buffer_size;
 238        __be32 rdma[6];
 239        __be32 wdma[8];
 240        __be32 build_job_name[3];
 241        __be32 build_job_number;
 242};
 243
 244struct wm_adsp_alg_xm_struct {
 245        __be32 magic;
 246        __be32 smoothing;
 247        __be32 threshold;
 248        __be32 host_buf_ptr;
 249        __be32 start_seq;
 250        __be32 high_water_mark;
 251        __be32 low_water_mark;
 252        __be64 smoothed_power;
 253};
 254
 255struct wm_adsp_buffer {
 256        __be32 X_buf_base;              /* XM base addr of first X area */
 257        __be32 X_buf_size;              /* Size of 1st X area in words */
 258        __be32 X_buf_base2;             /* XM base addr of 2nd X area */
 259        __be32 X_buf_brk;               /* Total X size in words */
 260        __be32 Y_buf_base;              /* YM base addr of Y area */
 261        __be32 wrap;                    /* Total size X and Y in words */
 262        __be32 high_water_mark;         /* Point at which IRQ is asserted */
 263        __be32 irq_count;               /* bits 1-31 count IRQ assertions */
 264        __be32 irq_ack;                 /* acked IRQ count, bit 0 enables IRQ */
 265        __be32 next_write_index;        /* word index of next write */
 266        __be32 next_read_index;         /* word index of next read */
 267        __be32 error;                   /* error if any */
 268        __be32 oldest_block_index;      /* word index of oldest surviving */
 269        __be32 requested_rewind;        /* how many blocks rewind was done */
 270        __be32 reserved_space;          /* internal */
 271        __be32 min_free;                /* min free space since stream start */
 272        __be32 blocks_written[2];       /* total blocks written (64 bit) */
 273        __be32 words_written[2];        /* total words written (64 bit) */
 274};
 275
 276struct wm_adsp_compr;
 277
 278struct wm_adsp_compr_buf {
 279        struct wm_adsp *dsp;
 280        struct wm_adsp_compr *compr;
 281
 282        struct wm_adsp_buffer_region *regions;
 283        u32 host_buf_ptr;
 284
 285        u32 error;
 286        u32 irq_count;
 287        int read_index;
 288        int avail;
 289};
 290
 291struct wm_adsp_compr {
 292        struct wm_adsp *dsp;
 293        struct wm_adsp_compr_buf *buf;
 294
 295        struct snd_compr_stream *stream;
 296        struct snd_compressed_buffer size;
 297
 298        u32 *raw_buf;
 299        unsigned int copied_total;
 300
 301        unsigned int sample_rate;
 302};
 303
 304#define WM_ADSP_DATA_WORD_SIZE         3
 305
 306#define WM_ADSP_MIN_FRAGMENTS          1
 307#define WM_ADSP_MAX_FRAGMENTS          256
 308#define WM_ADSP_MIN_FRAGMENT_SIZE      (64 * WM_ADSP_DATA_WORD_SIZE)
 309#define WM_ADSP_MAX_FRAGMENT_SIZE      (4096 * WM_ADSP_DATA_WORD_SIZE)
 310
 311#define WM_ADSP_ALG_XM_STRUCT_MAGIC    0x49aec7
 312
 313#define HOST_BUFFER_FIELD(field) \
 314        (offsetof(struct wm_adsp_buffer, field) / sizeof(__be32))
 315
 316#define ALG_XM_FIELD(field) \
 317        (offsetof(struct wm_adsp_alg_xm_struct, field) / sizeof(__be32))
 318
 319static int wm_adsp_buffer_init(struct wm_adsp *dsp);
 320static int wm_adsp_buffer_free(struct wm_adsp *dsp);
 321
 322struct wm_adsp_buffer_region {
 323        unsigned int offset;
 324        unsigned int cumulative_size;
 325        unsigned int mem_type;
 326        unsigned int base_addr;
 327};
 328
 329struct wm_adsp_buffer_region_def {
 330        unsigned int mem_type;
 331        unsigned int base_offset;
 332        unsigned int size_offset;
 333};
 334
 335static const struct wm_adsp_buffer_region_def default_regions[] = {
 336        {
 337                .mem_type = WMFW_ADSP2_XM,
 338                .base_offset = HOST_BUFFER_FIELD(X_buf_base),
 339                .size_offset = HOST_BUFFER_FIELD(X_buf_size),
 340        },
 341        {
 342                .mem_type = WMFW_ADSP2_XM,
 343                .base_offset = HOST_BUFFER_FIELD(X_buf_base2),
 344                .size_offset = HOST_BUFFER_FIELD(X_buf_brk),
 345        },
 346        {
 347                .mem_type = WMFW_ADSP2_YM,
 348                .base_offset = HOST_BUFFER_FIELD(Y_buf_base),
 349                .size_offset = HOST_BUFFER_FIELD(wrap),
 350        },
 351};
 352
 353struct wm_adsp_fw_caps {
 354        u32 id;
 355        struct snd_codec_desc desc;
 356        int num_regions;
 357        const struct wm_adsp_buffer_region_def *region_defs;
 358};
 359
 360static const struct wm_adsp_fw_caps ctrl_caps[] = {
 361        {
 362                .id = SND_AUDIOCODEC_BESPOKE,
 363                .desc = {
 364                        .max_ch = 1,
 365                        .sample_rates = { 16000 },
 366                        .num_sample_rates = 1,
 367                        .formats = SNDRV_PCM_FMTBIT_S16_LE,
 368                },
 369                .num_regions = ARRAY_SIZE(default_regions),
 370                .region_defs = default_regions,
 371        },
 372};
 373
 374static const struct wm_adsp_fw_caps trace_caps[] = {
 375        {
 376                .id = SND_AUDIOCODEC_BESPOKE,
 377                .desc = {
 378                        .max_ch = 8,
 379                        .sample_rates = {
 380                                4000, 8000, 11025, 12000, 16000, 22050,
 381                                24000, 32000, 44100, 48000, 64000, 88200,
 382                                96000, 176400, 192000
 383                        },
 384                        .num_sample_rates = 15,
 385                        .formats = SNDRV_PCM_FMTBIT_S16_LE,
 386                },
 387                .num_regions = ARRAY_SIZE(default_regions),
 388                .region_defs = default_regions,
 389        },
 390};
 391
 392static const struct {
 393        const char *file;
 394        int compr_direction;
 395        int num_caps;
 396        const struct wm_adsp_fw_caps *caps;
 397        bool voice_trigger;
 398} wm_adsp_fw[WM_ADSP_NUM_FW] = {
 399        [WM_ADSP_FW_MBC_VSS] =  { .file = "mbc-vss" },
 400        [WM_ADSP_FW_HIFI] =     { .file = "hifi" },
 401        [WM_ADSP_FW_TX] =       { .file = "tx" },
 402        [WM_ADSP_FW_TX_SPK] =   { .file = "tx-spk" },
 403        [WM_ADSP_FW_RX] =       { .file = "rx" },
 404        [WM_ADSP_FW_RX_ANC] =   { .file = "rx-anc" },
 405        [WM_ADSP_FW_CTRL] =     {
 406                .file = "ctrl",
 407                .compr_direction = SND_COMPRESS_CAPTURE,
 408                .num_caps = ARRAY_SIZE(ctrl_caps),
 409                .caps = ctrl_caps,
 410                .voice_trigger = true,
 411        },
 412        [WM_ADSP_FW_ASR] =      { .file = "asr" },
 413        [WM_ADSP_FW_TRACE] =    {
 414                .file = "trace",
 415                .compr_direction = SND_COMPRESS_CAPTURE,
 416                .num_caps = ARRAY_SIZE(trace_caps),
 417                .caps = trace_caps,
 418        },
 419        [WM_ADSP_FW_SPK_PROT] = { .file = "spk-prot" },
 420        [WM_ADSP_FW_MISC] =     { .file = "misc" },
 421};
 422
 423struct wm_coeff_ctl_ops {
 424        int (*xget)(struct snd_kcontrol *kcontrol,
 425                    struct snd_ctl_elem_value *ucontrol);
 426        int (*xput)(struct snd_kcontrol *kcontrol,
 427                    struct snd_ctl_elem_value *ucontrol);
 428        int (*xinfo)(struct snd_kcontrol *kcontrol,
 429                     struct snd_ctl_elem_info *uinfo);
 430};
 431
 432struct wm_coeff_ctl {
 433        const char *name;
 434        const char *fw_name;
 435        struct wm_adsp_alg_region alg_region;
 436        struct wm_coeff_ctl_ops ops;
 437        struct wm_adsp *dsp;
 438        unsigned int enabled:1;
 439        struct list_head list;
 440        void *cache;
 441        unsigned int offset;
 442        size_t len;
 443        unsigned int set:1;
 444        struct snd_kcontrol *kcontrol;
 445        struct soc_bytes_ext bytes_ext;
 446        unsigned int flags;
 447};
 448
 449#ifdef CONFIG_DEBUG_FS
 450static void wm_adsp_debugfs_save_wmfwname(struct wm_adsp *dsp, const char *s)
 451{
 452        char *tmp = kasprintf(GFP_KERNEL, "%s\n", s);
 453
 454        kfree(dsp->wmfw_file_name);
 455        dsp->wmfw_file_name = tmp;
 456}
 457
 458static void wm_adsp_debugfs_save_binname(struct wm_adsp *dsp, const char *s)
 459{
 460        char *tmp = kasprintf(GFP_KERNEL, "%s\n", s);
 461
 462        kfree(dsp->bin_file_name);
 463        dsp->bin_file_name = tmp;
 464}
 465
 466static void wm_adsp_debugfs_clear(struct wm_adsp *dsp)
 467{
 468        kfree(dsp->wmfw_file_name);
 469        kfree(dsp->bin_file_name);
 470        dsp->wmfw_file_name = NULL;
 471        dsp->bin_file_name = NULL;
 472}
 473
 474static ssize_t wm_adsp_debugfs_wmfw_read(struct file *file,
 475                                         char __user *user_buf,
 476                                         size_t count, loff_t *ppos)
 477{
 478        struct wm_adsp *dsp = file->private_data;
 479        ssize_t ret;
 480
 481        mutex_lock(&dsp->pwr_lock);
 482
 483        if (!dsp->wmfw_file_name || !dsp->running)
 484                ret = 0;
 485        else
 486                ret = simple_read_from_buffer(user_buf, count, ppos,
 487                                              dsp->wmfw_file_name,
 488                                              strlen(dsp->wmfw_file_name));
 489
 490        mutex_unlock(&dsp->pwr_lock);
 491        return ret;
 492}
 493
 494static ssize_t wm_adsp_debugfs_bin_read(struct file *file,
 495                                        char __user *user_buf,
 496                                        size_t count, loff_t *ppos)
 497{
 498        struct wm_adsp *dsp = file->private_data;
 499        ssize_t ret;
 500
 501        mutex_lock(&dsp->pwr_lock);
 502
 503        if (!dsp->bin_file_name || !dsp->running)
 504                ret = 0;
 505        else
 506                ret = simple_read_from_buffer(user_buf, count, ppos,
 507                                              dsp->bin_file_name,
 508                                              strlen(dsp->bin_file_name));
 509
 510        mutex_unlock(&dsp->pwr_lock);
 511        return ret;
 512}
 513
 514static const struct {
 515        const char *name;
 516        const struct file_operations fops;
 517} wm_adsp_debugfs_fops[] = {
 518        {
 519                .name = "wmfw_file_name",
 520                .fops = {
 521                        .open = simple_open,
 522                        .read = wm_adsp_debugfs_wmfw_read,
 523                },
 524        },
 525        {
 526                .name = "bin_file_name",
 527                .fops = {
 528                        .open = simple_open,
 529                        .read = wm_adsp_debugfs_bin_read,
 530                },
 531        },
 532};
 533
 534static void wm_adsp2_init_debugfs(struct wm_adsp *dsp,
 535                                  struct snd_soc_codec *codec)
 536{
 537        struct dentry *root = NULL;
 538        char *root_name;
 539        int i;
 540
 541        if (!codec->component.debugfs_root) {
 542                adsp_err(dsp, "No codec debugfs root\n");
 543                goto err;
 544        }
 545
 546        root_name = kmalloc(PAGE_SIZE, GFP_KERNEL);
 547        if (!root_name)
 548                goto err;
 549
 550        snprintf(root_name, PAGE_SIZE, "dsp%d", dsp->num);
 551        root = debugfs_create_dir(root_name, codec->component.debugfs_root);
 552        kfree(root_name);
 553
 554        if (!root)
 555                goto err;
 556
 557        if (!debugfs_create_bool("running", S_IRUGO, root, &dsp->running))
 558                goto err;
 559
 560        if (!debugfs_create_x32("fw_id", S_IRUGO, root, &dsp->fw_id))
 561                goto err;
 562
 563        if (!debugfs_create_x32("fw_version", S_IRUGO, root,
 564                                &dsp->fw_id_version))
 565                goto err;
 566
 567        for (i = 0; i < ARRAY_SIZE(wm_adsp_debugfs_fops); ++i) {
 568                if (!debugfs_create_file(wm_adsp_debugfs_fops[i].name,
 569                                         S_IRUGO, root, dsp,
 570                                         &wm_adsp_debugfs_fops[i].fops))
 571                        goto err;
 572        }
 573
 574        dsp->debugfs_root = root;
 575        return;
 576
 577err:
 578        debugfs_remove_recursive(root);
 579        adsp_err(dsp, "Failed to create debugfs\n");
 580}
 581
 582static void wm_adsp2_cleanup_debugfs(struct wm_adsp *dsp)
 583{
 584        wm_adsp_debugfs_clear(dsp);
 585        debugfs_remove_recursive(dsp->debugfs_root);
 586}
 587#else
 588static inline void wm_adsp2_init_debugfs(struct wm_adsp *dsp,
 589                                         struct snd_soc_codec *codec)
 590{
 591}
 592
 593static inline void wm_adsp2_cleanup_debugfs(struct wm_adsp *dsp)
 594{
 595}
 596
 597static inline void wm_adsp_debugfs_save_wmfwname(struct wm_adsp *dsp,
 598                                                 const char *s)
 599{
 600}
 601
 602static inline void wm_adsp_debugfs_save_binname(struct wm_adsp *dsp,
 603                                                const char *s)
 604{
 605}
 606
 607static inline void wm_adsp_debugfs_clear(struct wm_adsp *dsp)
 608{
 609}
 610#endif
 611
 612static int wm_adsp_fw_get(struct snd_kcontrol *kcontrol,
 613                          struct snd_ctl_elem_value *ucontrol)
 614{
 615        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 616        struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
 617        struct wm_adsp *dsp = snd_soc_codec_get_drvdata(codec);
 618
 619        ucontrol->value.enumerated.item[0] = dsp[e->shift_l].fw;
 620
 621        return 0;
 622}
 623
 624static int wm_adsp_fw_put(struct snd_kcontrol *kcontrol,
 625                          struct snd_ctl_elem_value *ucontrol)
 626{
 627        struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
 628        struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
 629        struct wm_adsp *dsp = snd_soc_codec_get_drvdata(codec);
 630        int ret = 0;
 631
 632        if (ucontrol->value.enumerated.item[0] == dsp[e->shift_l].fw)
 633                return 0;
 634
 635        if (ucontrol->value.enumerated.item[0] >= WM_ADSP_NUM_FW)
 636                return -EINVAL;
 637
 638        mutex_lock(&dsp[e->shift_l].pwr_lock);
 639
 640        if (dsp[e->shift_l].running || dsp[e->shift_l].compr)
 641                ret = -EBUSY;
 642        else
 643                dsp[e->shift_l].fw = ucontrol->value.enumerated.item[0];
 644
 645        mutex_unlock(&dsp[e->shift_l].pwr_lock);
 646
 647        return ret;
 648}
 649
 650static const struct soc_enum wm_adsp_fw_enum[] = {
 651        SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
 652        SOC_ENUM_SINGLE(0, 1, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
 653        SOC_ENUM_SINGLE(0, 2, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
 654        SOC_ENUM_SINGLE(0, 3, ARRAY_SIZE(wm_adsp_fw_text), wm_adsp_fw_text),
 655};
 656
 657const struct snd_kcontrol_new wm_adsp_fw_controls[] = {
 658        SOC_ENUM_EXT("DSP1 Firmware", wm_adsp_fw_enum[0],
 659                     wm_adsp_fw_get, wm_adsp_fw_put),
 660        SOC_ENUM_EXT("DSP2 Firmware", wm_adsp_fw_enum[1],
 661                     wm_adsp_fw_get, wm_adsp_fw_put),
 662        SOC_ENUM_EXT("DSP3 Firmware", wm_adsp_fw_enum[2],
 663                     wm_adsp_fw_get, wm_adsp_fw_put),
 664        SOC_ENUM_EXT("DSP4 Firmware", wm_adsp_fw_enum[3],
 665                     wm_adsp_fw_get, wm_adsp_fw_put),
 666};
 667EXPORT_SYMBOL_GPL(wm_adsp_fw_controls);
 668
 669static struct wm_adsp_region const *wm_adsp_find_region(struct wm_adsp *dsp,
 670                                                        int type)
 671{
 672        int i;
 673
 674        for (i = 0; i < dsp->num_mems; i++)
 675                if (dsp->mem[i].type == type)
 676                        return &dsp->mem[i];
 677
 678        return NULL;
 679}
 680
 681static unsigned int wm_adsp_region_to_reg(struct wm_adsp_region const *mem,
 682                                          unsigned int offset)
 683{
 684        if (WARN_ON(!mem))
 685                return offset;
 686        switch (mem->type) {
 687        case WMFW_ADSP1_PM:
 688                return mem->base + (offset * 3);
 689        case WMFW_ADSP1_DM:
 690                return mem->base + (offset * 2);
 691        case WMFW_ADSP2_XM:
 692                return mem->base + (offset * 2);
 693        case WMFW_ADSP2_YM:
 694                return mem->base + (offset * 2);
 695        case WMFW_ADSP1_ZM:
 696                return mem->base + (offset * 2);
 697        default:
 698                WARN(1, "Unknown memory region type");
 699                return offset;
 700        }
 701}
 702
 703static void wm_adsp2_show_fw_status(struct wm_adsp *dsp)
 704{
 705        u16 scratch[4];
 706        int ret;
 707
 708        ret = regmap_raw_read(dsp->regmap, dsp->base + ADSP2_SCRATCH0,
 709                                scratch, sizeof(scratch));
 710        if (ret) {
 711                adsp_err(dsp, "Failed to read SCRATCH regs: %d\n", ret);
 712                return;
 713        }
 714
 715        adsp_dbg(dsp, "FW SCRATCH 0:0x%x 1:0x%x 2:0x%x 3:0x%x\n",
 716                 be16_to_cpu(scratch[0]),
 717                 be16_to_cpu(scratch[1]),
 718                 be16_to_cpu(scratch[2]),
 719                 be16_to_cpu(scratch[3]));
 720}
 721
 722static inline struct wm_coeff_ctl *bytes_ext_to_ctl(struct soc_bytes_ext *ext)
 723{
 724        return container_of(ext, struct wm_coeff_ctl, bytes_ext);
 725}
 726
 727static int wm_coeff_info(struct snd_kcontrol *kctl,
 728                         struct snd_ctl_elem_info *uinfo)
 729{
 730        struct soc_bytes_ext *bytes_ext =
 731                (struct soc_bytes_ext *)kctl->private_value;
 732        struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext);
 733
 734        uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
 735        uinfo->count = ctl->len;
 736        return 0;
 737}
 738
 739static int wm_coeff_write_control(struct wm_coeff_ctl *ctl,
 740                                  const void *buf, size_t len)
 741{
 742        struct wm_adsp_alg_region *alg_region = &ctl->alg_region;
 743        const struct wm_adsp_region *mem;
 744        struct wm_adsp *dsp = ctl->dsp;
 745        void *scratch;
 746        int ret;
 747        unsigned int reg;
 748
 749        mem = wm_adsp_find_region(dsp, alg_region->type);
 750        if (!mem) {
 751                adsp_err(dsp, "No base for region %x\n",
 752                         alg_region->type);
 753                return -EINVAL;
 754        }
 755
 756        reg = ctl->alg_region.base + ctl->offset;
 757        reg = wm_adsp_region_to_reg(mem, reg);
 758
 759        scratch = kmemdup(buf, len, GFP_KERNEL | GFP_DMA);
 760        if (!scratch)
 761                return -ENOMEM;
 762
 763        ret = regmap_raw_write(dsp->regmap, reg, scratch,
 764                               len);
 765        if (ret) {
 766                adsp_err(dsp, "Failed to write %zu bytes to %x: %d\n",
 767                         len, reg, ret);
 768                kfree(scratch);
 769                return ret;
 770        }
 771        adsp_dbg(dsp, "Wrote %zu bytes to %x\n", len, reg);
 772
 773        kfree(scratch);
 774
 775        return 0;
 776}
 777
 778static int wm_coeff_put(struct snd_kcontrol *kctl,
 779                        struct snd_ctl_elem_value *ucontrol)
 780{
 781        struct soc_bytes_ext *bytes_ext =
 782                (struct soc_bytes_ext *)kctl->private_value;
 783        struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext);
 784        char *p = ucontrol->value.bytes.data;
 785        int ret = 0;
 786
 787        mutex_lock(&ctl->dsp->pwr_lock);
 788
 789        memcpy(ctl->cache, p, ctl->len);
 790
 791        ctl->set = 1;
 792        if (ctl->enabled)
 793                ret = wm_coeff_write_control(ctl, p, ctl->len);
 794
 795        mutex_unlock(&ctl->dsp->pwr_lock);
 796
 797        return ret;
 798}
 799
 800static int wm_coeff_tlv_put(struct snd_kcontrol *kctl,
 801                            const unsigned int __user *bytes, unsigned int size)
 802{
 803        struct soc_bytes_ext *bytes_ext =
 804                (struct soc_bytes_ext *)kctl->private_value;
 805        struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext);
 806        int ret = 0;
 807
 808        mutex_lock(&ctl->dsp->pwr_lock);
 809
 810        if (copy_from_user(ctl->cache, bytes, size)) {
 811                ret = -EFAULT;
 812        } else {
 813                ctl->set = 1;
 814                if (ctl->enabled)
 815                        ret = wm_coeff_write_control(ctl, ctl->cache, size);
 816        }
 817
 818        mutex_unlock(&ctl->dsp->pwr_lock);
 819
 820        return ret;
 821}
 822
 823static int wm_coeff_read_control(struct wm_coeff_ctl *ctl,
 824                                 void *buf, size_t len)
 825{
 826        struct wm_adsp_alg_region *alg_region = &ctl->alg_region;
 827        const struct wm_adsp_region *mem;
 828        struct wm_adsp *dsp = ctl->dsp;
 829        void *scratch;
 830        int ret;
 831        unsigned int reg;
 832
 833        mem = wm_adsp_find_region(dsp, alg_region->type);
 834        if (!mem) {
 835                adsp_err(dsp, "No base for region %x\n",
 836                         alg_region->type);
 837                return -EINVAL;
 838        }
 839
 840        reg = ctl->alg_region.base + ctl->offset;
 841        reg = wm_adsp_region_to_reg(mem, reg);
 842
 843        scratch = kmalloc(len, GFP_KERNEL | GFP_DMA);
 844        if (!scratch)
 845                return -ENOMEM;
 846
 847        ret = regmap_raw_read(dsp->regmap, reg, scratch, len);
 848        if (ret) {
 849                adsp_err(dsp, "Failed to read %zu bytes from %x: %d\n",
 850                         len, reg, ret);
 851                kfree(scratch);
 852                return ret;
 853        }
 854        adsp_dbg(dsp, "Read %zu bytes from %x\n", len, reg);
 855
 856        memcpy(buf, scratch, len);
 857        kfree(scratch);
 858
 859        return 0;
 860}
 861
 862static int wm_coeff_get(struct snd_kcontrol *kctl,
 863                        struct snd_ctl_elem_value *ucontrol)
 864{
 865        struct soc_bytes_ext *bytes_ext =
 866                (struct soc_bytes_ext *)kctl->private_value;
 867        struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext);
 868        char *p = ucontrol->value.bytes.data;
 869        int ret = 0;
 870
 871        mutex_lock(&ctl->dsp->pwr_lock);
 872
 873        if (ctl->flags & WMFW_CTL_FLAG_VOLATILE) {
 874                if (ctl->enabled)
 875                        ret = wm_coeff_read_control(ctl, p, ctl->len);
 876                else
 877                        ret = -EPERM;
 878        } else {
 879                if (!ctl->flags && ctl->enabled)
 880                        ret = wm_coeff_read_control(ctl, ctl->cache, ctl->len);
 881
 882                memcpy(p, ctl->cache, ctl->len);
 883        }
 884
 885        mutex_unlock(&ctl->dsp->pwr_lock);
 886
 887        return ret;
 888}
 889
 890static int wm_coeff_tlv_get(struct snd_kcontrol *kctl,
 891                            unsigned int __user *bytes, unsigned int size)
 892{
 893        struct soc_bytes_ext *bytes_ext =
 894                (struct soc_bytes_ext *)kctl->private_value;
 895        struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext);
 896        int ret = 0;
 897
 898        mutex_lock(&ctl->dsp->pwr_lock);
 899
 900        if (ctl->flags & WMFW_CTL_FLAG_VOLATILE) {
 901                if (ctl->enabled)
 902                        ret = wm_coeff_read_control(ctl, ctl->cache, size);
 903                else
 904                        ret = -EPERM;
 905        } else {
 906                if (!ctl->flags && ctl->enabled)
 907                        ret = wm_coeff_read_control(ctl, ctl->cache, size);
 908        }
 909
 910        if (!ret && copy_to_user(bytes, ctl->cache, size))
 911                ret = -EFAULT;
 912
 913        mutex_unlock(&ctl->dsp->pwr_lock);
 914
 915        return ret;
 916}
 917
 918struct wmfw_ctl_work {
 919        struct wm_adsp *dsp;
 920        struct wm_coeff_ctl *ctl;
 921        struct work_struct work;
 922};
 923
 924static unsigned int wmfw_convert_flags(unsigned int in, unsigned int len)
 925{
 926        unsigned int out, rd, wr, vol;
 927
 928        if (len > ADSP_MAX_STD_CTRL_SIZE) {
 929                rd = SNDRV_CTL_ELEM_ACCESS_TLV_READ;
 930                wr = SNDRV_CTL_ELEM_ACCESS_TLV_WRITE;
 931                vol = SNDRV_CTL_ELEM_ACCESS_VOLATILE;
 932
 933                out = SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK;
 934        } else {
 935                rd = SNDRV_CTL_ELEM_ACCESS_READ;
 936                wr = SNDRV_CTL_ELEM_ACCESS_WRITE;
 937                vol = SNDRV_CTL_ELEM_ACCESS_VOLATILE;
 938
 939                out = 0;
 940        }
 941
 942        if (in) {
 943                if (in & WMFW_CTL_FLAG_READABLE)
 944                        out |= rd;
 945                if (in & WMFW_CTL_FLAG_WRITEABLE)
 946                        out |= wr;
 947                if (in & WMFW_CTL_FLAG_VOLATILE)
 948                        out |= vol;
 949        } else {
 950                out |= rd | wr | vol;
 951        }
 952
 953        return out;
 954}
 955
 956static int wmfw_add_ctl(struct wm_adsp *dsp, struct wm_coeff_ctl *ctl)
 957{
 958        struct snd_kcontrol_new *kcontrol;
 959        int ret;
 960
 961        if (!ctl || !ctl->name)
 962                return -EINVAL;
 963
 964        kcontrol = kzalloc(sizeof(*kcontrol), GFP_KERNEL);
 965        if (!kcontrol)
 966                return -ENOMEM;
 967        kcontrol->iface = SNDRV_CTL_ELEM_IFACE_MIXER;
 968
 969        kcontrol->name = ctl->name;
 970        kcontrol->info = wm_coeff_info;
 971        kcontrol->get = wm_coeff_get;
 972        kcontrol->put = wm_coeff_put;
 973        kcontrol->iface = SNDRV_CTL_ELEM_IFACE_MIXER;
 974        kcontrol->tlv.c = snd_soc_bytes_tlv_callback;
 975        kcontrol->private_value = (unsigned long)&ctl->bytes_ext;
 976
 977        ctl->bytes_ext.max = ctl->len;
 978        ctl->bytes_ext.get = wm_coeff_tlv_get;
 979        ctl->bytes_ext.put = wm_coeff_tlv_put;
 980
 981        kcontrol->access = wmfw_convert_flags(ctl->flags, ctl->len);
 982
 983        ret = snd_soc_add_card_controls(dsp->card, kcontrol, 1);
 984        if (ret < 0)
 985                goto err_kcontrol;
 986
 987        kfree(kcontrol);
 988
 989        ctl->kcontrol = snd_soc_card_get_kcontrol(dsp->card, ctl->name);
 990
 991        return 0;
 992
 993err_kcontrol:
 994        kfree(kcontrol);
 995        return ret;
 996}
 997
 998static int wm_coeff_init_control_caches(struct wm_adsp *dsp)
 999{
1000        struct wm_coeff_ctl *ctl;
1001        int ret;
1002
1003        list_for_each_entry(ctl, &dsp->ctl_list, list) {
1004                if (!ctl->enabled || ctl->set)
1005                        continue;
1006                if (ctl->flags & WMFW_CTL_FLAG_VOLATILE)
1007                        continue;
1008
1009                ret = wm_coeff_read_control(ctl, ctl->cache, ctl->len);
1010                if (ret < 0)
1011                        return ret;
1012        }
1013
1014        return 0;
1015}
1016
1017static int wm_coeff_sync_controls(struct wm_adsp *dsp)
1018{
1019        struct wm_coeff_ctl *ctl;
1020        int ret;
1021
1022        list_for_each_entry(ctl, &dsp->ctl_list, list) {
1023                if (!ctl->enabled)
1024                        continue;
1025                if (ctl->set && !(ctl->flags & WMFW_CTL_FLAG_VOLATILE)) {
1026                        ret = wm_coeff_write_control(ctl, ctl->cache, ctl->len);
1027                        if (ret < 0)
1028                                return ret;
1029                }
1030        }
1031
1032        return 0;
1033}
1034
1035static void wm_adsp_ctl_work(struct work_struct *work)
1036{
1037        struct wmfw_ctl_work *ctl_work = container_of(work,
1038                                                      struct wmfw_ctl_work,
1039                                                      work);
1040
1041        wmfw_add_ctl(ctl_work->dsp, ctl_work->ctl);
1042        kfree(ctl_work);
1043}
1044
1045static void wm_adsp_free_ctl_blk(struct wm_coeff_ctl *ctl)
1046{
1047        kfree(ctl->cache);
1048        kfree(ctl->name);
1049        kfree(ctl);
1050}
1051
1052static int wm_adsp_create_control(struct wm_adsp *dsp,
1053                                  const struct wm_adsp_alg_region *alg_region,
1054                                  unsigned int offset, unsigned int len,
1055                                  const char *subname, unsigned int subname_len,
1056                                  unsigned int flags)
1057{
1058        struct wm_coeff_ctl *ctl;
1059        struct wmfw_ctl_work *ctl_work;
1060        char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
1061        char *region_name;
1062        int ret;
1063
1064        if (flags & WMFW_CTL_FLAG_SYS)
1065                return 0;
1066
1067        switch (alg_region->type) {
1068        case WMFW_ADSP1_PM:
1069                region_name = "PM";
1070                break;
1071        case WMFW_ADSP1_DM:
1072                region_name = "DM";
1073                break;
1074        case WMFW_ADSP2_XM:
1075                region_name = "XM";
1076                break;
1077        case WMFW_ADSP2_YM:
1078                region_name = "YM";
1079                break;
1080        case WMFW_ADSP1_ZM:
1081                region_name = "ZM";
1082                break;
1083        default:
1084                adsp_err(dsp, "Unknown region type: %d\n", alg_region->type);
1085                return -EINVAL;
1086        }
1087
1088        switch (dsp->fw_ver) {
1089        case 0:
1090        case 1:
1091                snprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "DSP%d %s %x",
1092                         dsp->num, region_name, alg_region->alg);
1093                break;
1094        default:
1095                ret = snprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN,
1096                                "DSP%d%c %.12s %x", dsp->num, *region_name,
1097                                wm_adsp_fw_text[dsp->fw], alg_region->alg);
1098
1099                /* Truncate the subname from the start if it is too long */
1100                if (subname) {
1101                        int avail = SNDRV_CTL_ELEM_ID_NAME_MAXLEN - ret - 2;
1102                        int skip = 0;
1103
1104                        if (subname_len > avail)
1105                                skip = subname_len - avail;
1106
1107                        snprintf(name + ret,
1108                                 SNDRV_CTL_ELEM_ID_NAME_MAXLEN - ret, " %.*s",
1109                                 subname_len - skip, subname + skip);
1110                }
1111                break;
1112        }
1113
1114        list_for_each_entry(ctl, &dsp->ctl_list, list) {
1115                if (!strcmp(ctl->name, name)) {
1116                        if (!ctl->enabled)
1117                                ctl->enabled = 1;
1118                        return 0;
1119                }
1120        }
1121
1122        ctl = kzalloc(sizeof(*ctl), GFP_KERNEL);
1123        if (!ctl)
1124                return -ENOMEM;
1125        ctl->fw_name = wm_adsp_fw_text[dsp->fw];
1126        ctl->alg_region = *alg_region;
1127        ctl->name = kmemdup(name, strlen(name) + 1, GFP_KERNEL);
1128        if (!ctl->name) {
1129                ret = -ENOMEM;
1130                goto err_ctl;
1131        }
1132        ctl->enabled = 1;
1133        ctl->set = 0;
1134        ctl->ops.xget = wm_coeff_get;
1135        ctl->ops.xput = wm_coeff_put;
1136        ctl->dsp = dsp;
1137
1138        ctl->flags = flags;
1139        ctl->offset = offset;
1140        ctl->len = len;
1141        ctl->cache = kzalloc(ctl->len, GFP_KERNEL);
1142        if (!ctl->cache) {
1143                ret = -ENOMEM;
1144                goto err_ctl_name;
1145        }
1146
1147        list_add(&ctl->list, &dsp->ctl_list);
1148
1149        ctl_work = kzalloc(sizeof(*ctl_work), GFP_KERNEL);
1150        if (!ctl_work) {
1151                ret = -ENOMEM;
1152                goto err_ctl_cache;
1153        }
1154
1155        ctl_work->dsp = dsp;
1156        ctl_work->ctl = ctl;
1157        INIT_WORK(&ctl_work->work, wm_adsp_ctl_work);
1158        schedule_work(&ctl_work->work);
1159
1160        return 0;
1161
1162err_ctl_cache:
1163        kfree(ctl->cache);
1164err_ctl_name:
1165        kfree(ctl->name);
1166err_ctl:
1167        kfree(ctl);
1168
1169        return ret;
1170}
1171
1172struct wm_coeff_parsed_alg {
1173        int id;
1174        const u8 *name;
1175        int name_len;
1176        int ncoeff;
1177};
1178
1179struct wm_coeff_parsed_coeff {
1180        int offset;
1181        int mem_type;
1182        const u8 *name;
1183        int name_len;
1184        int ctl_type;
1185        int flags;
1186        int len;
1187};
1188
1189static int wm_coeff_parse_string(int bytes, const u8 **pos, const u8 **str)
1190{
1191        int length;
1192
1193        switch (bytes) {
1194        case 1:
1195                length = **pos;
1196                break;
1197        case 2:
1198                length = le16_to_cpu(*((__le16 *)*pos));
1199                break;
1200        default:
1201                return 0;
1202        }
1203
1204        if (str)
1205                *str = *pos + bytes;
1206
1207        *pos += ((length + bytes) + 3) & ~0x03;
1208
1209        return length;
1210}
1211
1212static int wm_coeff_parse_int(int bytes, const u8 **pos)
1213{
1214        int val = 0;
1215
1216        switch (bytes) {
1217        case 2:
1218                val = le16_to_cpu(*((__le16 *)*pos));
1219                break;
1220        case 4:
1221                val = le32_to_cpu(*((__le32 *)*pos));
1222                break;
1223        default:
1224                break;
1225        }
1226
1227        *pos += bytes;
1228
1229        return val;
1230}
1231
1232static inline void wm_coeff_parse_alg(struct wm_adsp *dsp, const u8 **data,
1233                                      struct wm_coeff_parsed_alg *blk)
1234{
1235        const struct wmfw_adsp_alg_data *raw;
1236
1237        switch (dsp->fw_ver) {
1238        case 0:
1239        case 1:
1240                raw = (const struct wmfw_adsp_alg_data *)*data;
1241                *data = raw->data;
1242
1243                blk->id = le32_to_cpu(raw->id);
1244                blk->name = raw->name;
1245                blk->name_len = strlen(raw->name);
1246                blk->ncoeff = le32_to_cpu(raw->ncoeff);
1247                break;
1248        default:
1249                blk->id = wm_coeff_parse_int(sizeof(raw->id), data);
1250                blk->name_len = wm_coeff_parse_string(sizeof(u8), data,
1251                                                      &blk->name);
1252                wm_coeff_parse_string(sizeof(u16), data, NULL);
1253                blk->ncoeff = wm_coeff_parse_int(sizeof(raw->ncoeff), data);
1254                break;
1255        }
1256
1257        adsp_dbg(dsp, "Algorithm ID: %#x\n", blk->id);
1258        adsp_dbg(dsp, "Algorithm name: %.*s\n", blk->name_len, blk->name);
1259        adsp_dbg(dsp, "# of coefficient descriptors: %#x\n", blk->ncoeff);
1260}
1261
1262static inline void wm_coeff_parse_coeff(struct wm_adsp *dsp, const u8 **data,
1263                                        struct wm_coeff_parsed_coeff *blk)
1264{
1265        const struct wmfw_adsp_coeff_data *raw;
1266        const u8 *tmp;
1267        int length;
1268
1269        switch (dsp->fw_ver) {
1270        case 0:
1271        case 1:
1272                raw = (const struct wmfw_adsp_coeff_data *)*data;
1273                *data = *data + sizeof(raw->hdr) + le32_to_cpu(raw->hdr.size);
1274
1275                blk->offset = le16_to_cpu(raw->hdr.offset);
1276                blk->mem_type = le16_to_cpu(raw->hdr.type);
1277                blk->name = raw->name;
1278                blk->name_len = strlen(raw->name);
1279                blk->ctl_type = le16_to_cpu(raw->ctl_type);
1280                blk->flags = le16_to_cpu(raw->flags);
1281                blk->len = le32_to_cpu(raw->len);
1282                break;
1283        default:
1284                tmp = *data;
1285                blk->offset = wm_coeff_parse_int(sizeof(raw->hdr.offset), &tmp);
1286                blk->mem_type = wm_coeff_parse_int(sizeof(raw->hdr.type), &tmp);
1287                length = wm_coeff_parse_int(sizeof(raw->hdr.size), &tmp);
1288                blk->name_len = wm_coeff_parse_string(sizeof(u8), &tmp,
1289                                                      &blk->name);
1290                wm_coeff_parse_string(sizeof(u8), &tmp, NULL);
1291                wm_coeff_parse_string(sizeof(u16), &tmp, NULL);
1292                blk->ctl_type = wm_coeff_parse_int(sizeof(raw->ctl_type), &tmp);
1293                blk->flags = wm_coeff_parse_int(sizeof(raw->flags), &tmp);
1294                blk->len = wm_coeff_parse_int(sizeof(raw->len), &tmp);
1295
1296                *data = *data + sizeof(raw->hdr) + length;
1297                break;
1298        }
1299
1300        adsp_dbg(dsp, "\tCoefficient type: %#x\n", blk->mem_type);
1301        adsp_dbg(dsp, "\tCoefficient offset: %#x\n", blk->offset);
1302        adsp_dbg(dsp, "\tCoefficient name: %.*s\n", blk->name_len, blk->name);
1303        adsp_dbg(dsp, "\tCoefficient flags: %#x\n", blk->flags);
1304        adsp_dbg(dsp, "\tALSA control type: %#x\n", blk->ctl_type);
1305        adsp_dbg(dsp, "\tALSA control len: %#x\n", blk->len);
1306}
1307
1308static int wm_adsp_parse_coeff(struct wm_adsp *dsp,
1309                               const struct wmfw_region *region)
1310{
1311        struct wm_adsp_alg_region alg_region = {};
1312        struct wm_coeff_parsed_alg alg_blk;
1313        struct wm_coeff_parsed_coeff coeff_blk;
1314        const u8 *data = region->data;
1315        int i, ret;
1316
1317        wm_coeff_parse_alg(dsp, &data, &alg_blk);
1318        for (i = 0; i < alg_blk.ncoeff; i++) {
1319                wm_coeff_parse_coeff(dsp, &data, &coeff_blk);
1320
1321                switch (coeff_blk.ctl_type) {
1322                case SNDRV_CTL_ELEM_TYPE_BYTES:
1323                        break;
1324                default:
1325                        adsp_err(dsp, "Unknown control type: %d\n",
1326                                 coeff_blk.ctl_type);
1327                        return -EINVAL;
1328                }
1329
1330                alg_region.type = coeff_blk.mem_type;
1331                alg_region.alg = alg_blk.id;
1332
1333                ret = wm_adsp_create_control(dsp, &alg_region,
1334                                             coeff_blk.offset,
1335                                             coeff_blk.len,
1336                                             coeff_blk.name,
1337                                             coeff_blk.name_len,
1338                                             coeff_blk.flags);
1339                if (ret < 0)
1340                        adsp_err(dsp, "Failed to create control: %.*s, %d\n",
1341                                 coeff_blk.name_len, coeff_blk.name, ret);
1342        }
1343
1344        return 0;
1345}
1346
1347static int wm_adsp_load(struct wm_adsp *dsp)
1348{
1349        LIST_HEAD(buf_list);
1350        const struct firmware *firmware;
1351        struct regmap *regmap = dsp->regmap;
1352        unsigned int pos = 0;
1353        const struct wmfw_header *header;
1354        const struct wmfw_adsp1_sizes *adsp1_sizes;
1355        const struct wmfw_adsp2_sizes *adsp2_sizes;
1356        const struct wmfw_footer *footer;
1357        const struct wmfw_region *region;
1358        const struct wm_adsp_region *mem;
1359        const char *region_name;
1360        char *file, *text;
1361        struct wm_adsp_buf *buf;
1362        unsigned int reg;
1363        int regions = 0;
1364        int ret, offset, type, sizes;
1365
1366        file = kzalloc(PAGE_SIZE, GFP_KERNEL);
1367        if (file == NULL)
1368                return -ENOMEM;
1369
1370        snprintf(file, PAGE_SIZE, "%s-dsp%d-%s.wmfw", dsp->part, dsp->num,
1371                 wm_adsp_fw[dsp->fw].file);
1372        file[PAGE_SIZE - 1] = '\0';
1373
1374        ret = request_firmware(&firmware, file, dsp->dev);
1375        if (ret != 0) {
1376                adsp_err(dsp, "Failed to request '%s'\n", file);
1377                goto out;
1378        }
1379        ret = -EINVAL;
1380
1381        pos = sizeof(*header) + sizeof(*adsp1_sizes) + sizeof(*footer);
1382        if (pos >= firmware->size) {
1383                adsp_err(dsp, "%s: file too short, %zu bytes\n",
1384                         file, firmware->size);
1385                goto out_fw;
1386        }
1387
1388        header = (void *)&firmware->data[0];
1389
1390        if (memcmp(&header->magic[0], "WMFW", 4) != 0) {
1391                adsp_err(dsp, "%s: invalid magic\n", file);
1392                goto out_fw;
1393        }
1394
1395        switch (header->ver) {
1396        case 0:
1397                adsp_warn(dsp, "%s: Depreciated file format %d\n",
1398                          file, header->ver);
1399                break;
1400        case 1:
1401        case 2:
1402                break;
1403        default:
1404                adsp_err(dsp, "%s: unknown file format %d\n",
1405                         file, header->ver);
1406                goto out_fw;
1407        }
1408
1409        adsp_info(dsp, "Firmware version: %d\n", header->ver);
1410        dsp->fw_ver = header->ver;
1411
1412        if (header->core != dsp->type) {
1413                adsp_err(dsp, "%s: invalid core %d != %d\n",
1414                         file, header->core, dsp->type);
1415                goto out_fw;
1416        }
1417
1418        switch (dsp->type) {
1419        case WMFW_ADSP1:
1420                pos = sizeof(*header) + sizeof(*adsp1_sizes) + sizeof(*footer);
1421                adsp1_sizes = (void *)&(header[1]);
1422                footer = (void *)&(adsp1_sizes[1]);
1423                sizes = sizeof(*adsp1_sizes);
1424
1425                adsp_dbg(dsp, "%s: %d DM, %d PM, %d ZM\n",
1426                         file, le32_to_cpu(adsp1_sizes->dm),
1427                         le32_to_cpu(adsp1_sizes->pm),
1428                         le32_to_cpu(adsp1_sizes->zm));
1429                break;
1430
1431        case WMFW_ADSP2:
1432                pos = sizeof(*header) + sizeof(*adsp2_sizes) + sizeof(*footer);
1433                adsp2_sizes = (void *)&(header[1]);
1434                footer = (void *)&(adsp2_sizes[1]);
1435                sizes = sizeof(*adsp2_sizes);
1436
1437                adsp_dbg(dsp, "%s: %d XM, %d YM %d PM, %d ZM\n",
1438                         file, le32_to_cpu(adsp2_sizes->xm),
1439                         le32_to_cpu(adsp2_sizes->ym),
1440                         le32_to_cpu(adsp2_sizes->pm),
1441                         le32_to_cpu(adsp2_sizes->zm));
1442                break;
1443
1444        default:
1445                WARN(1, "Unknown DSP type");
1446                goto out_fw;
1447        }
1448
1449        if (le32_to_cpu(header->len) != sizeof(*header) +
1450            sizes + sizeof(*footer)) {
1451                adsp_err(dsp, "%s: unexpected header length %d\n",
1452                         file, le32_to_cpu(header->len));
1453                goto out_fw;
1454        }
1455
1456        adsp_dbg(dsp, "%s: timestamp %llu\n", file,
1457                 le64_to_cpu(footer->timestamp));
1458
1459        while (pos < firmware->size &&
1460               pos - firmware->size > sizeof(*region)) {
1461                region = (void *)&(firmware->data[pos]);
1462                region_name = "Unknown";
1463                reg = 0;
1464                text = NULL;
1465                offset = le32_to_cpu(region->offset) & 0xffffff;
1466                type = be32_to_cpu(region->type) & 0xff;
1467                mem = wm_adsp_find_region(dsp, type);
1468
1469                switch (type) {
1470                case WMFW_NAME_TEXT:
1471                        region_name = "Firmware name";
1472                        text = kzalloc(le32_to_cpu(region->len) + 1,
1473                                       GFP_KERNEL);
1474                        break;
1475                case WMFW_ALGORITHM_DATA:
1476                        region_name = "Algorithm";
1477                        ret = wm_adsp_parse_coeff(dsp, region);
1478                        if (ret != 0)
1479                                goto out_fw;
1480                        break;
1481                case WMFW_INFO_TEXT:
1482                        region_name = "Information";
1483                        text = kzalloc(le32_to_cpu(region->len) + 1,
1484                                       GFP_KERNEL);
1485                        break;
1486                case WMFW_ABSOLUTE:
1487                        region_name = "Absolute";
1488                        reg = offset;
1489                        break;
1490                case WMFW_ADSP1_PM:
1491                        region_name = "PM";
1492                        reg = wm_adsp_region_to_reg(mem, offset);
1493                        break;
1494                case WMFW_ADSP1_DM:
1495                        region_name = "DM";
1496                        reg = wm_adsp_region_to_reg(mem, offset);
1497                        break;
1498                case WMFW_ADSP2_XM:
1499                        region_name = "XM";
1500                        reg = wm_adsp_region_to_reg(mem, offset);
1501                        break;
1502                case WMFW_ADSP2_YM:
1503                        region_name = "YM";
1504                        reg = wm_adsp_region_to_reg(mem, offset);
1505                        break;
1506                case WMFW_ADSP1_ZM:
1507                        region_name = "ZM";
1508                        reg = wm_adsp_region_to_reg(mem, offset);
1509                        break;
1510                default:
1511                        adsp_warn(dsp,
1512                                  "%s.%d: Unknown region type %x at %d(%x)\n",
1513                                  file, regions, type, pos, pos);
1514                        break;
1515                }
1516
1517                adsp_dbg(dsp, "%s.%d: %d bytes at %d in %s\n", file,
1518                         regions, le32_to_cpu(region->len), offset,
1519                         region_name);
1520
1521                if (text) {
1522                        memcpy(text, region->data, le32_to_cpu(region->len));
1523                        adsp_info(dsp, "%s: %s\n", file, text);
1524                        kfree(text);
1525                }
1526
1527                if (reg) {
1528                        buf = wm_adsp_buf_alloc(region->data,
1529                                                le32_to_cpu(region->len),
1530                                                &buf_list);
1531                        if (!buf) {
1532                                adsp_err(dsp, "Out of memory\n");
1533                                ret = -ENOMEM;
1534                                goto out_fw;
1535                        }
1536
1537                        ret = regmap_raw_write_async(regmap, reg, buf->buf,
1538                                                     le32_to_cpu(region->len));
1539                        if (ret != 0) {
1540                                adsp_err(dsp,
1541                                        "%s.%d: Failed to write %d bytes at %d in %s: %d\n",
1542                                        file, regions,
1543                                        le32_to_cpu(region->len), offset,
1544                                        region_name, ret);
1545                                goto out_fw;
1546                        }
1547                }
1548
1549                pos += le32_to_cpu(region->len) + sizeof(*region);
1550                regions++;
1551        }
1552
1553        ret = regmap_async_complete(regmap);
1554        if (ret != 0) {
1555                adsp_err(dsp, "Failed to complete async write: %d\n", ret);
1556                goto out_fw;
1557        }
1558
1559        if (pos > firmware->size)
1560                adsp_warn(dsp, "%s.%d: %zu bytes at end of file\n",
1561                          file, regions, pos - firmware->size);
1562
1563        wm_adsp_debugfs_save_wmfwname(dsp, file);
1564
1565out_fw:
1566        regmap_async_complete(regmap);
1567        wm_adsp_buf_free(&buf_list);
1568        release_firmware(firmware);
1569out:
1570        kfree(file);
1571
1572        return ret;
1573}
1574
1575static void wm_adsp_ctl_fixup_base(struct wm_adsp *dsp,
1576                                  const struct wm_adsp_alg_region *alg_region)
1577{
1578        struct wm_coeff_ctl *ctl;
1579
1580        list_for_each_entry(ctl, &dsp->ctl_list, list) {
1581                if (ctl->fw_name == wm_adsp_fw_text[dsp->fw] &&
1582                    alg_region->alg == ctl->alg_region.alg &&
1583                    alg_region->type == ctl->alg_region.type) {
1584                        ctl->alg_region.base = alg_region->base;
1585                }
1586        }
1587}
1588
1589static void *wm_adsp_read_algs(struct wm_adsp *dsp, size_t n_algs,
1590                               unsigned int pos, unsigned int len)
1591{
1592        void *alg;
1593        int ret;
1594        __be32 val;
1595
1596        if (n_algs == 0) {
1597                adsp_err(dsp, "No algorithms\n");
1598                return ERR_PTR(-EINVAL);
1599        }
1600
1601        if (n_algs > 1024) {
1602                adsp_err(dsp, "Algorithm count %zx excessive\n", n_algs);
1603                return ERR_PTR(-EINVAL);
1604        }
1605
1606        /* Read the terminator first to validate the length */
1607        ret = regmap_raw_read(dsp->regmap, pos + len, &val, sizeof(val));
1608        if (ret != 0) {
1609                adsp_err(dsp, "Failed to read algorithm list end: %d\n",
1610                        ret);
1611                return ERR_PTR(ret);
1612        }
1613
1614        if (be32_to_cpu(val) != 0xbedead)
1615                adsp_warn(dsp, "Algorithm list end %x 0x%x != 0xbeadead\n",
1616                          pos + len, be32_to_cpu(val));
1617
1618        alg = kzalloc(len * 2, GFP_KERNEL | GFP_DMA);
1619        if (!alg)
1620                return ERR_PTR(-ENOMEM);
1621
1622        ret = regmap_raw_read(dsp->regmap, pos, alg, len * 2);
1623        if (ret != 0) {
1624                adsp_err(dsp, "Failed to read algorithm list: %d\n", ret);
1625                kfree(alg);
1626                return ERR_PTR(ret);
1627        }
1628
1629        return alg;
1630}
1631
1632static struct wm_adsp_alg_region *
1633        wm_adsp_find_alg_region(struct wm_adsp *dsp, int type, unsigned int id)
1634{
1635        struct wm_adsp_alg_region *alg_region;
1636
1637        list_for_each_entry(alg_region, &dsp->alg_regions, list) {
1638                if (id == alg_region->alg && type == alg_region->type)
1639                        return alg_region;
1640        }
1641
1642        return NULL;
1643}
1644
1645static struct wm_adsp_alg_region *wm_adsp_create_region(struct wm_adsp *dsp,
1646                                                        int type, __be32 id,
1647                                                        __be32 base)
1648{
1649        struct wm_adsp_alg_region *alg_region;
1650
1651        alg_region = kzalloc(sizeof(*alg_region), GFP_KERNEL);
1652        if (!alg_region)
1653                return ERR_PTR(-ENOMEM);
1654
1655        alg_region->type = type;
1656        alg_region->alg = be32_to_cpu(id);
1657        alg_region->base = be32_to_cpu(base);
1658
1659        list_add_tail(&alg_region->list, &dsp->alg_regions);
1660
1661        if (dsp->fw_ver > 0)
1662                wm_adsp_ctl_fixup_base(dsp, alg_region);
1663
1664        return alg_region;
1665}
1666
1667static void wm_adsp_free_alg_regions(struct wm_adsp *dsp)
1668{
1669        struct wm_adsp_alg_region *alg_region;
1670
1671        while (!list_empty(&dsp->alg_regions)) {
1672                alg_region = list_first_entry(&dsp->alg_regions,
1673                                              struct wm_adsp_alg_region,
1674                                              list);
1675                list_del(&alg_region->list);
1676                kfree(alg_region);
1677        }
1678}
1679
1680static int wm_adsp1_setup_algs(struct wm_adsp *dsp)
1681{
1682        struct wmfw_adsp1_id_hdr adsp1_id;
1683        struct wmfw_adsp1_alg_hdr *adsp1_alg;
1684        struct wm_adsp_alg_region *alg_region;
1685        const struct wm_adsp_region *mem;
1686        unsigned int pos, len;
1687        size_t n_algs;
1688        int i, ret;
1689
1690        mem = wm_adsp_find_region(dsp, WMFW_ADSP1_DM);
1691        if (WARN_ON(!mem))
1692                return -EINVAL;
1693
1694        ret = regmap_raw_read(dsp->regmap, mem->base, &adsp1_id,
1695                              sizeof(adsp1_id));
1696        if (ret != 0) {
1697                adsp_err(dsp, "Failed to read algorithm info: %d\n",
1698                         ret);
1699                return ret;
1700        }
1701
1702        n_algs = be32_to_cpu(adsp1_id.n_algs);
1703        dsp->fw_id = be32_to_cpu(adsp1_id.fw.id);
1704        adsp_info(dsp, "Firmware: %x v%d.%d.%d, %zu algorithms\n",
1705                  dsp->fw_id,
1706                  (be32_to_cpu(adsp1_id.fw.ver) & 0xff0000) >> 16,
1707                  (be32_to_cpu(adsp1_id.fw.ver) & 0xff00) >> 8,
1708                  be32_to_cpu(adsp1_id.fw.ver) & 0xff,
1709                  n_algs);
1710
1711        alg_region = wm_adsp_create_region(dsp, WMFW_ADSP1_ZM,
1712                                           adsp1_id.fw.id, adsp1_id.zm);
1713        if (IS_ERR(alg_region))
1714                return PTR_ERR(alg_region);
1715
1716        alg_region = wm_adsp_create_region(dsp, WMFW_ADSP1_DM,
1717                                           adsp1_id.fw.id, adsp1_id.dm);
1718        if (IS_ERR(alg_region))
1719                return PTR_ERR(alg_region);
1720
1721        pos = sizeof(adsp1_id) / 2;
1722        len = (sizeof(*adsp1_alg) * n_algs) / 2;
1723
1724        adsp1_alg = wm_adsp_read_algs(dsp, n_algs, mem->base + pos, len);
1725        if (IS_ERR(adsp1_alg))
1726                return PTR_ERR(adsp1_alg);
1727
1728        for (i = 0; i < n_algs; i++) {
1729                adsp_info(dsp, "%d: ID %x v%d.%d.%d DM@%x ZM@%x\n",
1730                          i, be32_to_cpu(adsp1_alg[i].alg.id),
1731                          (be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff0000) >> 16,
1732                          (be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff00) >> 8,
1733                          be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff,
1734                          be32_to_cpu(adsp1_alg[i].dm),
1735                          be32_to_cpu(adsp1_alg[i].zm));
1736
1737                alg_region = wm_adsp_create_region(dsp, WMFW_ADSP1_DM,
1738                                                   adsp1_alg[i].alg.id,
1739                                                   adsp1_alg[i].dm);
1740                if (IS_ERR(alg_region)) {
1741                        ret = PTR_ERR(alg_region);
1742                        goto out;
1743                }
1744                if (dsp->fw_ver == 0) {
1745                        if (i + 1 < n_algs) {
1746                                len = be32_to_cpu(adsp1_alg[i + 1].dm);
1747                                len -= be32_to_cpu(adsp1_alg[i].dm);
1748                                len *= 4;
1749                                wm_adsp_create_control(dsp, alg_region, 0,
1750                                                       len, NULL, 0, 0);
1751                        } else {
1752                                adsp_warn(dsp, "Missing length info for region DM with ID %x\n",
1753                                          be32_to_cpu(adsp1_alg[i].alg.id));
1754                        }
1755                }
1756
1757                alg_region = wm_adsp_create_region(dsp, WMFW_ADSP1_ZM,
1758                                                   adsp1_alg[i].alg.id,
1759                                                   adsp1_alg[i].zm);
1760                if (IS_ERR(alg_region)) {
1761                        ret = PTR_ERR(alg_region);
1762                        goto out;
1763                }
1764                if (dsp->fw_ver == 0) {
1765                        if (i + 1 < n_algs) {
1766                                len = be32_to_cpu(adsp1_alg[i + 1].zm);
1767                                len -= be32_to_cpu(adsp1_alg[i].zm);
1768                                len *= 4;
1769                                wm_adsp_create_control(dsp, alg_region, 0,
1770                                                       len, NULL, 0, 0);
1771                        } else {
1772                                adsp_warn(dsp, "Missing length info for region ZM with ID %x\n",
1773                                          be32_to_cpu(adsp1_alg[i].alg.id));
1774                        }
1775                }
1776        }
1777
1778out:
1779        kfree(adsp1_alg);
1780        return ret;
1781}
1782
1783static int wm_adsp2_setup_algs(struct wm_adsp *dsp)
1784{
1785        struct wmfw_adsp2_id_hdr adsp2_id;
1786        struct wmfw_adsp2_alg_hdr *adsp2_alg;
1787        struct wm_adsp_alg_region *alg_region;
1788        const struct wm_adsp_region *mem;
1789        unsigned int pos, len;
1790        size_t n_algs;
1791        int i, ret;
1792
1793        mem = wm_adsp_find_region(dsp, WMFW_ADSP2_XM);
1794        if (WARN_ON(!mem))
1795                return -EINVAL;
1796
1797        ret = regmap_raw_read(dsp->regmap, mem->base, &adsp2_id,
1798                              sizeof(adsp2_id));
1799        if (ret != 0) {
1800                adsp_err(dsp, "Failed to read algorithm info: %d\n",
1801                         ret);
1802                return ret;
1803        }
1804
1805        n_algs = be32_to_cpu(adsp2_id.n_algs);
1806        dsp->fw_id = be32_to_cpu(adsp2_id.fw.id);
1807        dsp->fw_id_version = be32_to_cpu(adsp2_id.fw.ver);
1808        adsp_info(dsp, "Firmware: %x v%d.%d.%d, %zu algorithms\n",
1809                  dsp->fw_id,
1810                  (dsp->fw_id_version & 0xff0000) >> 16,
1811                  (dsp->fw_id_version & 0xff00) >> 8,
1812                  dsp->fw_id_version & 0xff,
1813                  n_algs);
1814
1815        alg_region = wm_adsp_create_region(dsp, WMFW_ADSP2_XM,
1816                                           adsp2_id.fw.id, adsp2_id.xm);
1817        if (IS_ERR(alg_region))
1818                return PTR_ERR(alg_region);
1819
1820        alg_region = wm_adsp_create_region(dsp, WMFW_ADSP2_YM,
1821                                           adsp2_id.fw.id, adsp2_id.ym);
1822        if (IS_ERR(alg_region))
1823                return PTR_ERR(alg_region);
1824
1825        alg_region = wm_adsp_create_region(dsp, WMFW_ADSP2_ZM,
1826                                           adsp2_id.fw.id, adsp2_id.zm);
1827        if (IS_ERR(alg_region))
1828                return PTR_ERR(alg_region);
1829
1830        pos = sizeof(adsp2_id) / 2;
1831        len = (sizeof(*adsp2_alg) * n_algs) / 2;
1832
1833        adsp2_alg = wm_adsp_read_algs(dsp, n_algs, mem->base + pos, len);
1834        if (IS_ERR(adsp2_alg))
1835                return PTR_ERR(adsp2_alg);
1836
1837        for (i = 0; i < n_algs; i++) {
1838                adsp_info(dsp,
1839                          "%d: ID %x v%d.%d.%d XM@%x YM@%x ZM@%x\n",
1840                          i, be32_to_cpu(adsp2_alg[i].alg.id),
1841                          (be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff0000) >> 16,
1842                          (be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff00) >> 8,
1843                          be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff,
1844                          be32_to_cpu(adsp2_alg[i].xm),
1845                          be32_to_cpu(adsp2_alg[i].ym),
1846                          be32_to_cpu(adsp2_alg[i].zm));
1847
1848                alg_region = wm_adsp_create_region(dsp, WMFW_ADSP2_XM,
1849                                                   adsp2_alg[i].alg.id,
1850                                                   adsp2_alg[i].xm);
1851                if (IS_ERR(alg_region)) {
1852                        ret = PTR_ERR(alg_region);
1853                        goto out;
1854                }
1855                if (dsp->fw_ver == 0) {
1856                        if (i + 1 < n_algs) {
1857                                len = be32_to_cpu(adsp2_alg[i + 1].xm);
1858                                len -= be32_to_cpu(adsp2_alg[i].xm);
1859                                len *= 4;
1860                                wm_adsp_create_control(dsp, alg_region, 0,
1861                                                       len, NULL, 0, 0);
1862                        } else {
1863                                adsp_warn(dsp, "Missing length info for region XM with ID %x\n",
1864                                          be32_to_cpu(adsp2_alg[i].alg.id));
1865                        }
1866                }
1867
1868                alg_region = wm_adsp_create_region(dsp, WMFW_ADSP2_YM,
1869                                                   adsp2_alg[i].alg.id,
1870                                                   adsp2_alg[i].ym);
1871                if (IS_ERR(alg_region)) {
1872                        ret = PTR_ERR(alg_region);
1873                        goto out;
1874                }
1875                if (dsp->fw_ver == 0) {
1876                        if (i + 1 < n_algs) {
1877                                len = be32_to_cpu(adsp2_alg[i + 1].ym);
1878                                len -= be32_to_cpu(adsp2_alg[i].ym);
1879                                len *= 4;
1880                                wm_adsp_create_control(dsp, alg_region, 0,
1881                                                       len, NULL, 0, 0);
1882                        } else {
1883                                adsp_warn(dsp, "Missing length info for region YM with ID %x\n",
1884                                          be32_to_cpu(adsp2_alg[i].alg.id));
1885                        }
1886                }
1887
1888                alg_region = wm_adsp_create_region(dsp, WMFW_ADSP2_ZM,
1889                                                   adsp2_alg[i].alg.id,
1890                                                   adsp2_alg[i].zm);
1891                if (IS_ERR(alg_region)) {
1892                        ret = PTR_ERR(alg_region);
1893                        goto out;
1894                }
1895                if (dsp->fw_ver == 0) {
1896                        if (i + 1 < n_algs) {
1897                                len = be32_to_cpu(adsp2_alg[i + 1].zm);
1898                                len -= be32_to_cpu(adsp2_alg[i].zm);
1899                                len *= 4;
1900                                wm_adsp_create_control(dsp, alg_region, 0,
1901                                                       len, NULL, 0, 0);
1902                        } else {
1903                                adsp_warn(dsp, "Missing length info for region ZM with ID %x\n",
1904                                          be32_to_cpu(adsp2_alg[i].alg.id));
1905                        }
1906                }
1907        }
1908
1909out:
1910        kfree(adsp2_alg);
1911        return ret;
1912}
1913
1914static int wm_adsp_load_coeff(struct wm_adsp *dsp)
1915{
1916        LIST_HEAD(buf_list);
1917        struct regmap *regmap = dsp->regmap;
1918        struct wmfw_coeff_hdr *hdr;
1919        struct wmfw_coeff_item *blk;
1920        const struct firmware *firmware;
1921        const struct wm_adsp_region *mem;
1922        struct wm_adsp_alg_region *alg_region;
1923        const char *region_name;
1924        int ret, pos, blocks, type, offset, reg;
1925        char *file;
1926        struct wm_adsp_buf *buf;
1927
1928        file = kzalloc(PAGE_SIZE, GFP_KERNEL);
1929        if (file == NULL)
1930                return -ENOMEM;
1931
1932        snprintf(file, PAGE_SIZE, "%s-dsp%d-%s.bin", dsp->part, dsp->num,
1933                 wm_adsp_fw[dsp->fw].file);
1934        file[PAGE_SIZE - 1] = '\0';
1935
1936        ret = request_firmware(&firmware, file, dsp->dev);
1937        if (ret != 0) {
1938                adsp_warn(dsp, "Failed to request '%s'\n", file);
1939                ret = 0;
1940                goto out;
1941        }
1942        ret = -EINVAL;
1943
1944        if (sizeof(*hdr) >= firmware->size) {
1945                adsp_err(dsp, "%s: file too short, %zu bytes\n",
1946                        file, firmware->size);
1947                goto out_fw;
1948        }
1949
1950        hdr = (void *)&firmware->data[0];
1951        if (memcmp(hdr->magic, "WMDR", 4) != 0) {
1952                adsp_err(dsp, "%s: invalid magic\n", file);
1953                goto out_fw;
1954        }
1955
1956        switch (be32_to_cpu(hdr->rev) & 0xff) {
1957        case 1:
1958                break;
1959        default:
1960                adsp_err(dsp, "%s: Unsupported coefficient file format %d\n",
1961                         file, be32_to_cpu(hdr->rev) & 0xff);
1962                ret = -EINVAL;
1963                goto out_fw;
1964        }
1965
1966        adsp_dbg(dsp, "%s: v%d.%d.%d\n", file,
1967                (le32_to_cpu(hdr->ver) >> 16) & 0xff,
1968                (le32_to_cpu(hdr->ver) >>  8) & 0xff,
1969                le32_to_cpu(hdr->ver) & 0xff);
1970
1971        pos = le32_to_cpu(hdr->len);
1972
1973        blocks = 0;
1974        while (pos < firmware->size &&
1975               pos - firmware->size > sizeof(*blk)) {
1976                blk = (void *)(&firmware->data[pos]);
1977
1978                type = le16_to_cpu(blk->type);
1979                offset = le16_to_cpu(blk->offset);
1980
1981                adsp_dbg(dsp, "%s.%d: %x v%d.%d.%d\n",
1982                         file, blocks, le32_to_cpu(blk->id),
1983                         (le32_to_cpu(blk->ver) >> 16) & 0xff,
1984                         (le32_to_cpu(blk->ver) >>  8) & 0xff,
1985                         le32_to_cpu(blk->ver) & 0xff);
1986                adsp_dbg(dsp, "%s.%d: %d bytes at 0x%x in %x\n",
1987                         file, blocks, le32_to_cpu(blk->len), offset, type);
1988
1989                reg = 0;
1990                region_name = "Unknown";
1991                switch (type) {
1992                case (WMFW_NAME_TEXT << 8):
1993                case (WMFW_INFO_TEXT << 8):
1994                        break;
1995                case (WMFW_ABSOLUTE << 8):
1996                        /*
1997                         * Old files may use this for global
1998                         * coefficients.
1999                         */
2000                        if (le32_to_cpu(blk->id) == dsp->fw_id &&
2001                            offset == 0) {
2002                                region_name = "global coefficients";
2003                                mem = wm_adsp_find_region(dsp, type);
2004                                if (!mem) {
2005                                        adsp_err(dsp, "No ZM\n");
2006                                        break;
2007                                }
2008                                reg = wm_adsp_region_to_reg(mem, 0);
2009
2010                        } else {
2011                                region_name = "register";
2012                                reg = offset;
2013                        }
2014                        break;
2015
2016                case WMFW_ADSP1_DM:
2017                case WMFW_ADSP1_ZM:
2018                case WMFW_ADSP2_XM:
2019                case WMFW_ADSP2_YM:
2020                        adsp_dbg(dsp, "%s.%d: %d bytes in %x for %x\n",
2021                                 file, blocks, le32_to_cpu(blk->len),
2022                                 type, le32_to_cpu(blk->id));
2023
2024                        mem = wm_adsp_find_region(dsp, type);
2025                        if (!mem) {
2026                                adsp_err(dsp, "No base for region %x\n", type);
2027                                break;
2028                        }
2029
2030                        alg_region = wm_adsp_find_alg_region(dsp, type,
2031                                                le32_to_cpu(blk->id));
2032                        if (alg_region) {
2033                                reg = alg_region->base;
2034                                reg = wm_adsp_region_to_reg(mem, reg);
2035                                reg += offset;
2036                        } else {
2037                                adsp_err(dsp, "No %x for algorithm %x\n",
2038                                         type, le32_to_cpu(blk->id));
2039                        }
2040                        break;
2041
2042                default:
2043                        adsp_err(dsp, "%s.%d: Unknown region type %x at %d\n",
2044                                 file, blocks, type, pos);
2045                        break;
2046                }
2047
2048                if (reg) {
2049                        buf = wm_adsp_buf_alloc(blk->data,
2050                                                le32_to_cpu(blk->len),
2051                                                &buf_list);
2052                        if (!buf) {
2053                                adsp_err(dsp, "Out of memory\n");
2054                                ret = -ENOMEM;
2055                                goto out_fw;
2056                        }
2057
2058                        adsp_dbg(dsp, "%s.%d: Writing %d bytes at %x\n",
2059                                 file, blocks, le32_to_cpu(blk->len),
2060                                 reg);
2061                        ret = regmap_raw_write_async(regmap, reg, buf->buf,
2062                                                     le32_to_cpu(blk->len));
2063                        if (ret != 0) {
2064                                adsp_err(dsp,
2065                                        "%s.%d: Failed to write to %x in %s: %d\n",
2066                                        file, blocks, reg, region_name, ret);
2067                        }
2068                }
2069
2070                pos += (le32_to_cpu(blk->len) + sizeof(*blk) + 3) & ~0x03;
2071                blocks++;
2072        }
2073
2074        ret = regmap_async_complete(regmap);
2075        if (ret != 0)
2076                adsp_err(dsp, "Failed to complete async write: %d\n", ret);
2077
2078        if (pos > firmware->size)
2079                adsp_warn(dsp, "%s.%d: %zu bytes at end of file\n",
2080                          file, blocks, pos - firmware->size);
2081
2082        wm_adsp_debugfs_save_binname(dsp, file);
2083
2084out_fw:
2085        regmap_async_complete(regmap);
2086        release_firmware(firmware);
2087        wm_adsp_buf_free(&buf_list);
2088out:
2089        kfree(file);
2090        return ret;
2091}
2092
2093int wm_adsp1_init(struct wm_adsp *dsp)
2094{
2095        INIT_LIST_HEAD(&dsp->alg_regions);
2096
2097        mutex_init(&dsp->pwr_lock);
2098
2099        return 0;
2100}
2101EXPORT_SYMBOL_GPL(wm_adsp1_init);
2102
2103int wm_adsp1_event(struct snd_soc_dapm_widget *w,
2104                   struct snd_kcontrol *kcontrol,
2105                   int event)
2106{
2107        struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
2108        struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec);
2109        struct wm_adsp *dsp = &dsps[w->shift];
2110        struct wm_coeff_ctl *ctl;
2111        int ret;
2112        unsigned int val;
2113
2114        dsp->card = codec->component.card;
2115
2116        mutex_lock(&dsp->pwr_lock);
2117
2118        switch (event) {
2119        case SND_SOC_DAPM_POST_PMU:
2120                regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
2121                                   ADSP1_SYS_ENA, ADSP1_SYS_ENA);
2122
2123                /*
2124                 * For simplicity set the DSP clock rate to be the
2125                 * SYSCLK rate rather than making it configurable.
2126                 */
2127                if (dsp->sysclk_reg) {
2128                        ret = regmap_read(dsp->regmap, dsp->sysclk_reg, &val);
2129                        if (ret != 0) {
2130                                adsp_err(dsp, "Failed to read SYSCLK state: %d\n",
2131                                ret);
2132                                goto err_mutex;
2133                        }
2134
2135                        val = (val & dsp->sysclk_mask) >> dsp->sysclk_shift;
2136
2137                        ret = regmap_update_bits(dsp->regmap,
2138                                                 dsp->base + ADSP1_CONTROL_31,
2139                                                 ADSP1_CLK_SEL_MASK, val);
2140                        if (ret != 0) {
2141                                adsp_err(dsp, "Failed to set clock rate: %d\n",
2142                                         ret);
2143                                goto err_mutex;
2144                        }
2145                }
2146
2147                ret = wm_adsp_load(dsp);
2148                if (ret != 0)
2149                        goto err_ena;
2150
2151                ret = wm_adsp1_setup_algs(dsp);
2152                if (ret != 0)
2153                        goto err_ena;
2154
2155                ret = wm_adsp_load_coeff(dsp);
2156                if (ret != 0)
2157                        goto err_ena;
2158
2159                /* Initialize caches for enabled and unset controls */
2160                ret = wm_coeff_init_control_caches(dsp);
2161                if (ret != 0)
2162                        goto err_ena;
2163
2164                /* Sync set controls */
2165                ret = wm_coeff_sync_controls(dsp);
2166                if (ret != 0)
2167                        goto err_ena;
2168
2169                /* Start the core running */
2170                regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
2171                                   ADSP1_CORE_ENA | ADSP1_START,
2172                                   ADSP1_CORE_ENA | ADSP1_START);
2173                break;
2174
2175        case SND_SOC_DAPM_PRE_PMD:
2176                /* Halt the core */
2177                regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
2178                                   ADSP1_CORE_ENA | ADSP1_START, 0);
2179
2180                regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_19,
2181                                   ADSP1_WDMA_BUFFER_LENGTH_MASK, 0);
2182
2183                regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
2184                                   ADSP1_SYS_ENA, 0);
2185
2186                list_for_each_entry(ctl, &dsp->ctl_list, list)
2187                        ctl->enabled = 0;
2188
2189
2190                wm_adsp_free_alg_regions(dsp);
2191                break;
2192
2193        default:
2194                break;
2195        }
2196
2197        mutex_unlock(&dsp->pwr_lock);
2198
2199        return 0;
2200
2201err_ena:
2202        regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
2203                           ADSP1_SYS_ENA, 0);
2204err_mutex:
2205        mutex_unlock(&dsp->pwr_lock);
2206
2207        return ret;
2208}
2209EXPORT_SYMBOL_GPL(wm_adsp1_event);
2210
2211static int wm_adsp2_ena(struct wm_adsp *dsp)
2212{
2213        unsigned int val;
2214        int ret, count;
2215
2216        ret = regmap_update_bits_async(dsp->regmap, dsp->base + ADSP2_CONTROL,
2217                                       ADSP2_SYS_ENA, ADSP2_SYS_ENA);
2218        if (ret != 0)
2219                return ret;
2220
2221        /* Wait for the RAM to start, should be near instantaneous */
2222        for (count = 0; count < 10; ++count) {
2223                ret = regmap_read(dsp->regmap, dsp->base + ADSP2_STATUS1, &val);
2224                if (ret != 0)
2225                        return ret;
2226
2227                if (val & ADSP2_RAM_RDY)
2228                        break;
2229
2230                msleep(1);
2231        }
2232
2233        if (!(val & ADSP2_RAM_RDY)) {
2234                adsp_err(dsp, "Failed to start DSP RAM\n");
2235                return -EBUSY;
2236        }
2237
2238        adsp_dbg(dsp, "RAM ready after %d polls\n", count);
2239
2240        return 0;
2241}
2242
2243static void wm_adsp2_boot_work(struct work_struct *work)
2244{
2245        struct wm_adsp *dsp = container_of(work,
2246                                           struct wm_adsp,
2247                                           boot_work);
2248        int ret;
2249
2250        mutex_lock(&dsp->pwr_lock);
2251
2252        ret = wm_adsp2_ena(dsp);
2253        if (ret != 0)
2254                goto err_mutex;
2255
2256        ret = wm_adsp_load(dsp);
2257        if (ret != 0)
2258                goto err_ena;
2259
2260        ret = wm_adsp2_setup_algs(dsp);
2261        if (ret != 0)
2262                goto err_ena;
2263
2264        ret = wm_adsp_load_coeff(dsp);
2265        if (ret != 0)
2266                goto err_ena;
2267
2268        /* Initialize caches for enabled and unset controls */
2269        ret = wm_coeff_init_control_caches(dsp);
2270        if (ret != 0)
2271                goto err_ena;
2272
2273        /* Sync set controls */
2274        ret = wm_coeff_sync_controls(dsp);
2275        if (ret != 0)
2276                goto err_ena;
2277
2278        dsp->running = true;
2279
2280        mutex_unlock(&dsp->pwr_lock);
2281
2282        return;
2283
2284err_ena:
2285        regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
2286                           ADSP2_SYS_ENA | ADSP2_CORE_ENA | ADSP2_START, 0);
2287err_mutex:
2288        mutex_unlock(&dsp->pwr_lock);
2289}
2290
2291static void wm_adsp2_set_dspclk(struct wm_adsp *dsp, unsigned int freq)
2292{
2293        int ret;
2294
2295        ret = regmap_update_bits_async(dsp->regmap,
2296                                       dsp->base + ADSP2_CLOCKING,
2297                                       ADSP2_CLK_SEL_MASK,
2298                                       freq << ADSP2_CLK_SEL_SHIFT);
2299        if (ret != 0)
2300                adsp_err(dsp, "Failed to set clock rate: %d\n", ret);
2301}
2302
2303int wm_adsp2_early_event(struct snd_soc_dapm_widget *w,
2304                         struct snd_kcontrol *kcontrol, int event,
2305                         unsigned int freq)
2306{
2307        struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
2308        struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec);
2309        struct wm_adsp *dsp = &dsps[w->shift];
2310
2311        dsp->card = codec->component.card;
2312
2313        switch (event) {
2314        case SND_SOC_DAPM_PRE_PMU:
2315                wm_adsp2_set_dspclk(dsp, freq);
2316                queue_work(system_unbound_wq, &dsp->boot_work);
2317                break;
2318        default:
2319                break;
2320        }
2321
2322        return 0;
2323}
2324EXPORT_SYMBOL_GPL(wm_adsp2_early_event);
2325
2326int wm_adsp2_event(struct snd_soc_dapm_widget *w,
2327                   struct snd_kcontrol *kcontrol, int event)
2328{
2329        struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
2330        struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec);
2331        struct wm_adsp *dsp = &dsps[w->shift];
2332        struct wm_coeff_ctl *ctl;
2333        int ret;
2334
2335        switch (event) {
2336        case SND_SOC_DAPM_POST_PMU:
2337                flush_work(&dsp->boot_work);
2338
2339                if (!dsp->running)
2340                        return -EIO;
2341
2342                ret = regmap_update_bits(dsp->regmap,
2343                                         dsp->base + ADSP2_CONTROL,
2344                                         ADSP2_CORE_ENA | ADSP2_START,
2345                                         ADSP2_CORE_ENA | ADSP2_START);
2346                if (ret != 0)
2347                        goto err;
2348
2349                mutex_lock(&dsp->pwr_lock);
2350
2351                if (wm_adsp_fw[dsp->fw].num_caps != 0)
2352                        ret = wm_adsp_buffer_init(dsp);
2353
2354                mutex_unlock(&dsp->pwr_lock);
2355
2356                break;
2357
2358        case SND_SOC_DAPM_PRE_PMD:
2359                /* Log firmware state, it can be useful for analysis */
2360                wm_adsp2_show_fw_status(dsp);
2361
2362                mutex_lock(&dsp->pwr_lock);
2363
2364                wm_adsp_debugfs_clear(dsp);
2365
2366                dsp->fw_id = 0;
2367                dsp->fw_id_version = 0;
2368                dsp->running = false;
2369
2370                regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
2371                                   ADSP2_CORE_ENA | ADSP2_START, 0);
2372
2373                /* Make sure DMAs are quiesced */
2374                regmap_write(dsp->regmap, dsp->base + ADSP2_RDMA_CONFIG_1, 0);
2375                regmap_write(dsp->regmap, dsp->base + ADSP2_WDMA_CONFIG_1, 0);
2376                regmap_write(dsp->regmap, dsp->base + ADSP2_WDMA_CONFIG_2, 0);
2377
2378                regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
2379                                   ADSP2_SYS_ENA, 0);
2380
2381                list_for_each_entry(ctl, &dsp->ctl_list, list)
2382                        ctl->enabled = 0;
2383
2384                wm_adsp_free_alg_regions(dsp);
2385
2386                if (wm_adsp_fw[dsp->fw].num_caps != 0)
2387                        wm_adsp_buffer_free(dsp);
2388
2389                mutex_unlock(&dsp->pwr_lock);
2390
2391                adsp_dbg(dsp, "Shutdown complete\n");
2392                break;
2393
2394        default:
2395                break;
2396        }
2397
2398        return 0;
2399err:
2400        regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
2401                           ADSP2_SYS_ENA | ADSP2_CORE_ENA | ADSP2_START, 0);
2402        return ret;
2403}
2404EXPORT_SYMBOL_GPL(wm_adsp2_event);
2405
2406int wm_adsp2_codec_probe(struct wm_adsp *dsp, struct snd_soc_codec *codec)
2407{
2408        wm_adsp2_init_debugfs(dsp, codec);
2409
2410        return snd_soc_add_codec_controls(codec,
2411                                          &wm_adsp_fw_controls[dsp->num - 1],
2412                                          1);
2413}
2414EXPORT_SYMBOL_GPL(wm_adsp2_codec_probe);
2415
2416int wm_adsp2_codec_remove(struct wm_adsp *dsp, struct snd_soc_codec *codec)
2417{
2418        wm_adsp2_cleanup_debugfs(dsp);
2419
2420        return 0;
2421}
2422EXPORT_SYMBOL_GPL(wm_adsp2_codec_remove);
2423
2424int wm_adsp2_init(struct wm_adsp *dsp)
2425{
2426        int ret;
2427
2428        /*
2429         * Disable the DSP memory by default when in reset for a small
2430         * power saving.
2431         */
2432        ret = regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
2433                                 ADSP2_MEM_ENA, 0);
2434        if (ret != 0) {
2435                adsp_err(dsp, "Failed to clear memory retention: %d\n", ret);
2436                return ret;
2437        }
2438
2439        INIT_LIST_HEAD(&dsp->alg_regions);
2440        INIT_LIST_HEAD(&dsp->ctl_list);
2441        INIT_WORK(&dsp->boot_work, wm_adsp2_boot_work);
2442
2443        mutex_init(&dsp->pwr_lock);
2444
2445        return 0;
2446}
2447EXPORT_SYMBOL_GPL(wm_adsp2_init);
2448
2449void wm_adsp2_remove(struct wm_adsp *dsp)
2450{
2451        struct wm_coeff_ctl *ctl;
2452
2453        while (!list_empty(&dsp->ctl_list)) {
2454                ctl = list_first_entry(&dsp->ctl_list, struct wm_coeff_ctl,
2455                                        list);
2456                list_del(&ctl->list);
2457                wm_adsp_free_ctl_blk(ctl);
2458        }
2459}
2460EXPORT_SYMBOL_GPL(wm_adsp2_remove);
2461
2462static inline int wm_adsp_compr_attached(struct wm_adsp_compr *compr)
2463{
2464        return compr->buf != NULL;
2465}
2466
2467static int wm_adsp_compr_attach(struct wm_adsp_compr *compr)
2468{
2469        /*
2470         * Note this will be more complex once each DSP can support multiple
2471         * streams
2472         */
2473        if (!compr->dsp->buffer)
2474                return -EINVAL;
2475
2476        compr->buf = compr->dsp->buffer;
2477        compr->buf->compr = compr;
2478
2479        return 0;
2480}
2481
2482static void wm_adsp_compr_detach(struct wm_adsp_compr *compr)
2483{
2484        if (!compr)
2485                return;
2486
2487        /* Wake the poll so it can see buffer is no longer attached */
2488        if (compr->stream)
2489                snd_compr_fragment_elapsed(compr->stream);
2490
2491        if (wm_adsp_compr_attached(compr)) {
2492                compr->buf->compr = NULL;
2493                compr->buf = NULL;
2494        }
2495}
2496
2497int wm_adsp_compr_open(struct wm_adsp *dsp, struct snd_compr_stream *stream)
2498{
2499        struct wm_adsp_compr *compr;
2500        int ret = 0;
2501
2502        mutex_lock(&dsp->pwr_lock);
2503
2504        if (wm_adsp_fw[dsp->fw].num_caps == 0) {
2505                adsp_err(dsp, "Firmware does not support compressed API\n");
2506                ret = -ENXIO;
2507                goto out;
2508        }
2509
2510        if (wm_adsp_fw[dsp->fw].compr_direction != stream->direction) {
2511                adsp_err(dsp, "Firmware does not support stream direction\n");
2512                ret = -EINVAL;
2513                goto out;
2514        }
2515
2516        if (dsp->compr) {
2517                /* It is expect this limitation will be removed in future */
2518                adsp_err(dsp, "Only a single stream supported per DSP\n");
2519                ret = -EBUSY;
2520                goto out;
2521        }
2522
2523        compr = kzalloc(sizeof(*compr), GFP_KERNEL);
2524        if (!compr) {
2525                ret = -ENOMEM;
2526                goto out;
2527        }
2528
2529        compr->dsp = dsp;
2530        compr->stream = stream;
2531
2532        dsp->compr = compr;
2533
2534        stream->runtime->private_data = compr;
2535
2536out:
2537        mutex_unlock(&dsp->pwr_lock);
2538
2539        return ret;
2540}
2541EXPORT_SYMBOL_GPL(wm_adsp_compr_open);
2542
2543int wm_adsp_compr_free(struct snd_compr_stream *stream)
2544{
2545        struct wm_adsp_compr *compr = stream->runtime->private_data;
2546        struct wm_adsp *dsp = compr->dsp;
2547
2548        mutex_lock(&dsp->pwr_lock);
2549
2550        wm_adsp_compr_detach(compr);
2551        dsp->compr = NULL;
2552
2553        kfree(compr->raw_buf);
2554        kfree(compr);
2555
2556        mutex_unlock(&dsp->pwr_lock);
2557
2558        return 0;
2559}
2560EXPORT_SYMBOL_GPL(wm_adsp_compr_free);
2561
2562static int wm_adsp_compr_check_params(struct snd_compr_stream *stream,
2563                                      struct snd_compr_params *params)
2564{
2565        struct wm_adsp_compr *compr = stream->runtime->private_data;
2566        struct wm_adsp *dsp = compr->dsp;
2567        const struct wm_adsp_fw_caps *caps;
2568        const struct snd_codec_desc *desc;
2569        int i, j;
2570
2571        if (params->buffer.fragment_size < WM_ADSP_MIN_FRAGMENT_SIZE ||
2572            params->buffer.fragment_size > WM_ADSP_MAX_FRAGMENT_SIZE ||
2573            params->buffer.fragments < WM_ADSP_MIN_FRAGMENTS ||
2574            params->buffer.fragments > WM_ADSP_MAX_FRAGMENTS ||
2575            params->buffer.fragment_size % WM_ADSP_DATA_WORD_SIZE) {
2576                adsp_err(dsp, "Invalid buffer fragsize=%d fragments=%d\n",
2577                         params->buffer.fragment_size,
2578                         params->buffer.fragments);
2579
2580                return -EINVAL;
2581        }
2582
2583        for (i = 0; i < wm_adsp_fw[dsp->fw].num_caps; i++) {
2584                caps = &wm_adsp_fw[dsp->fw].caps[i];
2585                desc = &caps->desc;
2586
2587                if (caps->id != params->codec.id)
2588                        continue;
2589
2590                if (stream->direction == SND_COMPRESS_PLAYBACK) {
2591                        if (desc->max_ch < params->codec.ch_out)
2592                                continue;
2593                } else {
2594                        if (desc->max_ch < params->codec.ch_in)
2595                                continue;
2596                }
2597
2598                if (!(desc->formats & (1 << params->codec.format)))
2599                        continue;
2600
2601                for (j = 0; j < desc->num_sample_rates; ++j)
2602                        if (desc->sample_rates[j] == params->codec.sample_rate)
2603                                return 0;
2604        }
2605
2606        adsp_err(dsp, "Invalid params id=%u ch=%u,%u rate=%u fmt=%u\n",
2607                 params->codec.id, params->codec.ch_in, params->codec.ch_out,
2608                 params->codec.sample_rate, params->codec.format);
2609        return -EINVAL;
2610}
2611
2612static inline unsigned int wm_adsp_compr_frag_words(struct wm_adsp_compr *compr)
2613{
2614        return compr->size.fragment_size / WM_ADSP_DATA_WORD_SIZE;
2615}
2616
2617int wm_adsp_compr_set_params(struct snd_compr_stream *stream,
2618                             struct snd_compr_params *params)
2619{
2620        struct wm_adsp_compr *compr = stream->runtime->private_data;
2621        unsigned int size;
2622        int ret;
2623
2624        ret = wm_adsp_compr_check_params(stream, params);
2625        if (ret)
2626                return ret;
2627
2628        compr->size = params->buffer;
2629
2630        adsp_dbg(compr->dsp, "fragment_size=%d fragments=%d\n",
2631                 compr->size.fragment_size, compr->size.fragments);
2632
2633        size = wm_adsp_compr_frag_words(compr) * sizeof(*compr->raw_buf);
2634        compr->raw_buf = kmalloc(size, GFP_DMA | GFP_KERNEL);
2635        if (!compr->raw_buf)
2636                return -ENOMEM;
2637
2638        compr->sample_rate = params->codec.sample_rate;
2639
2640        return 0;
2641}
2642EXPORT_SYMBOL_GPL(wm_adsp_compr_set_params);
2643
2644int wm_adsp_compr_get_caps(struct snd_compr_stream *stream,
2645                           struct snd_compr_caps *caps)
2646{
2647        struct wm_adsp_compr *compr = stream->runtime->private_data;
2648        int fw = compr->dsp->fw;
2649        int i;
2650
2651        if (wm_adsp_fw[fw].caps) {
2652                for (i = 0; i < wm_adsp_fw[fw].num_caps; i++)
2653                        caps->codecs[i] = wm_adsp_fw[fw].caps[i].id;
2654
2655                caps->num_codecs = i;
2656                caps->direction = wm_adsp_fw[fw].compr_direction;
2657
2658                caps->min_fragment_size = WM_ADSP_MIN_FRAGMENT_SIZE;
2659                caps->max_fragment_size = WM_ADSP_MAX_FRAGMENT_SIZE;
2660                caps->min_fragments = WM_ADSP_MIN_FRAGMENTS;
2661                caps->max_fragments = WM_ADSP_MAX_FRAGMENTS;
2662        }
2663
2664        return 0;
2665}
2666EXPORT_SYMBOL_GPL(wm_adsp_compr_get_caps);
2667
2668static int wm_adsp_read_data_block(struct wm_adsp *dsp, int mem_type,
2669                                   unsigned int mem_addr,
2670                                   unsigned int num_words, u32 *data)
2671{
2672        struct wm_adsp_region const *mem = wm_adsp_find_region(dsp, mem_type);
2673        unsigned int i, reg;
2674        int ret;
2675
2676        if (!mem)
2677                return -EINVAL;
2678
2679        reg = wm_adsp_region_to_reg(mem, mem_addr);
2680
2681        ret = regmap_raw_read(dsp->regmap, reg, data,
2682                              sizeof(*data) * num_words);
2683        if (ret < 0)
2684                return ret;
2685
2686        for (i = 0; i < num_words; ++i)
2687                data[i] = be32_to_cpu(data[i]) & 0x00ffffffu;
2688
2689        return 0;
2690}
2691
2692static inline int wm_adsp_read_data_word(struct wm_adsp *dsp, int mem_type,
2693                                         unsigned int mem_addr, u32 *data)
2694{
2695        return wm_adsp_read_data_block(dsp, mem_type, mem_addr, 1, data);
2696}
2697
2698static int wm_adsp_write_data_word(struct wm_adsp *dsp, int mem_type,
2699                                   unsigned int mem_addr, u32 data)
2700{
2701        struct wm_adsp_region const *mem = wm_adsp_find_region(dsp, mem_type);
2702        unsigned int reg;
2703
2704        if (!mem)
2705                return -EINVAL;
2706
2707        reg = wm_adsp_region_to_reg(mem, mem_addr);
2708
2709        data = cpu_to_be32(data & 0x00ffffffu);
2710
2711        return regmap_raw_write(dsp->regmap, reg, &data, sizeof(data));
2712}
2713
2714static inline int wm_adsp_buffer_read(struct wm_adsp_compr_buf *buf,
2715                                      unsigned int field_offset, u32 *data)
2716{
2717        return wm_adsp_read_data_word(buf->dsp, WMFW_ADSP2_XM,
2718                                      buf->host_buf_ptr + field_offset, data);
2719}
2720
2721static inline int wm_adsp_buffer_write(struct wm_adsp_compr_buf *buf,
2722                                       unsigned int field_offset, u32 data)
2723{
2724        return wm_adsp_write_data_word(buf->dsp, WMFW_ADSP2_XM,
2725                                       buf->host_buf_ptr + field_offset, data);
2726}
2727
2728static int wm_adsp_buffer_locate(struct wm_adsp_compr_buf *buf)
2729{
2730        struct wm_adsp_alg_region *alg_region;
2731        struct wm_adsp *dsp = buf->dsp;
2732        u32 xmalg, addr, magic;
2733        int i, ret;
2734
2735        alg_region = wm_adsp_find_alg_region(dsp, WMFW_ADSP2_XM, dsp->fw_id);
2736        xmalg = sizeof(struct wm_adsp_system_config_xm_hdr) / sizeof(__be32);
2737
2738        addr = alg_region->base + xmalg + ALG_XM_FIELD(magic);
2739        ret = wm_adsp_read_data_word(dsp, WMFW_ADSP2_XM, addr, &magic);
2740        if (ret < 0)
2741                return ret;
2742
2743        if (magic != WM_ADSP_ALG_XM_STRUCT_MAGIC)
2744                return -EINVAL;
2745
2746        addr = alg_region->base + xmalg + ALG_XM_FIELD(host_buf_ptr);
2747        for (i = 0; i < 5; ++i) {
2748                ret = wm_adsp_read_data_word(dsp, WMFW_ADSP2_XM, addr,
2749                                             &buf->host_buf_ptr);
2750                if (ret < 0)
2751                        return ret;
2752
2753                if (buf->host_buf_ptr)
2754                        break;
2755
2756                usleep_range(1000, 2000);
2757        }
2758
2759        if (!buf->host_buf_ptr)
2760                return -EIO;
2761
2762        adsp_dbg(dsp, "host_buf_ptr=%x\n", buf->host_buf_ptr);
2763
2764        return 0;
2765}
2766
2767static int wm_adsp_buffer_populate(struct wm_adsp_compr_buf *buf)
2768{
2769        const struct wm_adsp_fw_caps *caps = wm_adsp_fw[buf->dsp->fw].caps;
2770        struct wm_adsp_buffer_region *region;
2771        u32 offset = 0;
2772        int i, ret;
2773
2774        for (i = 0; i < caps->num_regions; ++i) {
2775                region = &buf->regions[i];
2776
2777                region->offset = offset;
2778                region->mem_type = caps->region_defs[i].mem_type;
2779
2780                ret = wm_adsp_buffer_read(buf, caps->region_defs[i].base_offset,
2781                                          &region->base_addr);
2782                if (ret < 0)
2783                        return ret;
2784
2785                ret = wm_adsp_buffer_read(buf, caps->region_defs[i].size_offset,
2786                                          &offset);
2787                if (ret < 0)
2788                        return ret;
2789
2790                region->cumulative_size = offset;
2791
2792                adsp_dbg(buf->dsp,
2793                         "region=%d type=%d base=%04x off=%04x size=%04x\n",
2794                         i, region->mem_type, region->base_addr,
2795                         region->offset, region->cumulative_size);
2796        }
2797
2798        return 0;
2799}
2800
2801static int wm_adsp_buffer_init(struct wm_adsp *dsp)
2802{
2803        struct wm_adsp_compr_buf *buf;
2804        int ret;
2805
2806        buf = kzalloc(sizeof(*buf), GFP_KERNEL);
2807        if (!buf)
2808                return -ENOMEM;
2809
2810        buf->dsp = dsp;
2811        buf->read_index = -1;
2812        buf->irq_count = 0xFFFFFFFF;
2813
2814        ret = wm_adsp_buffer_locate(buf);
2815        if (ret < 0) {
2816                adsp_err(dsp, "Failed to acquire host buffer: %d\n", ret);
2817                goto err_buffer;
2818        }
2819
2820        buf->regions = kcalloc(wm_adsp_fw[dsp->fw].caps->num_regions,
2821                               sizeof(*buf->regions), GFP_KERNEL);
2822        if (!buf->regions) {
2823                ret = -ENOMEM;
2824                goto err_buffer;
2825        }
2826
2827        ret = wm_adsp_buffer_populate(buf);
2828        if (ret < 0) {
2829                adsp_err(dsp, "Failed to populate host buffer: %d\n", ret);
2830                goto err_regions;
2831        }
2832
2833        dsp->buffer = buf;
2834
2835        return 0;
2836
2837err_regions:
2838        kfree(buf->regions);
2839err_buffer:
2840        kfree(buf);
2841        return ret;
2842}
2843
2844static int wm_adsp_buffer_free(struct wm_adsp *dsp)
2845{
2846        if (dsp->buffer) {
2847                wm_adsp_compr_detach(dsp->buffer->compr);
2848
2849                kfree(dsp->buffer->regions);
2850                kfree(dsp->buffer);
2851
2852                dsp->buffer = NULL;
2853        }
2854
2855        return 0;
2856}
2857
2858int wm_adsp_compr_trigger(struct snd_compr_stream *stream, int cmd)
2859{
2860        struct wm_adsp_compr *compr = stream->runtime->private_data;
2861        struct wm_adsp *dsp = compr->dsp;
2862        int ret = 0;
2863
2864        adsp_dbg(dsp, "Trigger: %d\n", cmd);
2865
2866        mutex_lock(&dsp->pwr_lock);
2867
2868        switch (cmd) {
2869        case SNDRV_PCM_TRIGGER_START:
2870                if (wm_adsp_compr_attached(compr))
2871                        break;
2872
2873                ret = wm_adsp_compr_attach(compr);
2874                if (ret < 0) {
2875                        adsp_err(dsp, "Failed to link buffer and stream: %d\n",
2876                                 ret);
2877                        break;
2878                }
2879
2880                /* Trigger the IRQ at one fragment of data */
2881                ret = wm_adsp_buffer_write(compr->buf,
2882                                           HOST_BUFFER_FIELD(high_water_mark),
2883                                           wm_adsp_compr_frag_words(compr));
2884                if (ret < 0) {
2885                        adsp_err(dsp, "Failed to set high water mark: %d\n",
2886                                 ret);
2887                        break;
2888                }
2889                break;
2890        case SNDRV_PCM_TRIGGER_STOP:
2891                break;
2892        default:
2893                ret = -EINVAL;
2894                break;
2895        }
2896
2897        mutex_unlock(&dsp->pwr_lock);
2898
2899        return ret;
2900}
2901EXPORT_SYMBOL_GPL(wm_adsp_compr_trigger);
2902
2903static inline int wm_adsp_buffer_size(struct wm_adsp_compr_buf *buf)
2904{
2905        int last_region = wm_adsp_fw[buf->dsp->fw].caps->num_regions - 1;
2906
2907        return buf->regions[last_region].cumulative_size;
2908}
2909
2910static int wm_adsp_buffer_update_avail(struct wm_adsp_compr_buf *buf)
2911{
2912        u32 next_read_index, next_write_index;
2913        int write_index, read_index, avail;
2914        int ret;
2915
2916        /* Only sync read index if we haven't already read a valid index */
2917        if (buf->read_index < 0) {
2918                ret = wm_adsp_buffer_read(buf,
2919                                HOST_BUFFER_FIELD(next_read_index),
2920                                &next_read_index);
2921                if (ret < 0)
2922                        return ret;
2923
2924                read_index = sign_extend32(next_read_index, 23);
2925
2926                if (read_index < 0) {
2927                        adsp_dbg(buf->dsp, "Avail check on unstarted stream\n");
2928                        return 0;
2929                }
2930
2931                buf->read_index = read_index;
2932        }
2933
2934        ret = wm_adsp_buffer_read(buf, HOST_BUFFER_FIELD(next_write_index),
2935                        &next_write_index);
2936        if (ret < 0)
2937                return ret;
2938
2939        write_index = sign_extend32(next_write_index, 23);
2940
2941        avail = write_index - buf->read_index;
2942        if (avail < 0)
2943                avail += wm_adsp_buffer_size(buf);
2944
2945        adsp_dbg(buf->dsp, "readindex=0x%x, writeindex=0x%x, avail=%d\n",
2946                 buf->read_index, write_index, avail * WM_ADSP_DATA_WORD_SIZE);
2947
2948        buf->avail = avail;
2949
2950        return 0;
2951}
2952
2953static int wm_adsp_buffer_get_error(struct wm_adsp_compr_buf *buf)
2954{
2955        int ret;
2956
2957        ret = wm_adsp_buffer_read(buf, HOST_BUFFER_FIELD(error), &buf->error);
2958        if (ret < 0) {
2959                adsp_err(buf->dsp, "Failed to check buffer error: %d\n", ret);
2960                return ret;
2961        }
2962        if (buf->error != 0) {
2963                adsp_err(buf->dsp, "Buffer error occurred: %d\n", buf->error);
2964                return -EIO;
2965        }
2966
2967        return 0;
2968}
2969
2970int wm_adsp_compr_handle_irq(struct wm_adsp *dsp)
2971{
2972        struct wm_adsp_compr_buf *buf;
2973        struct wm_adsp_compr *compr;
2974        int ret = 0;
2975
2976        mutex_lock(&dsp->pwr_lock);
2977
2978        buf = dsp->buffer;
2979        compr = dsp->compr;
2980
2981        if (!buf) {
2982                ret = -ENODEV;
2983                goto out;
2984        }
2985
2986        adsp_dbg(dsp, "Handling buffer IRQ\n");
2987
2988        ret = wm_adsp_buffer_get_error(buf);
2989        if (ret < 0)
2990                goto out_notify; /* Wake poll to report error */
2991
2992        ret = wm_adsp_buffer_read(buf, HOST_BUFFER_FIELD(irq_count),
2993                                  &buf->irq_count);
2994        if (ret < 0) {
2995                adsp_err(dsp, "Failed to get irq_count: %d\n", ret);
2996                goto out;
2997        }
2998
2999        ret = wm_adsp_buffer_update_avail(buf);
3000        if (ret < 0) {
3001                adsp_err(dsp, "Error reading avail: %d\n", ret);
3002                goto out;
3003        }
3004
3005        if (wm_adsp_fw[dsp->fw].voice_trigger && buf->irq_count == 2)
3006                ret = WM_ADSP_COMPR_VOICE_TRIGGER;
3007
3008out_notify:
3009        if (compr && compr->stream)
3010                snd_compr_fragment_elapsed(compr->stream);
3011
3012out:
3013        mutex_unlock(&dsp->pwr_lock);
3014
3015        return ret;
3016}
3017EXPORT_SYMBOL_GPL(wm_adsp_compr_handle_irq);
3018
3019static int wm_adsp_buffer_reenable_irq(struct wm_adsp_compr_buf *buf)
3020{
3021        if (buf->irq_count & 0x01)
3022                return 0;
3023
3024        adsp_dbg(buf->dsp, "Enable IRQ(0x%x) for next fragment\n",
3025                 buf->irq_count);
3026
3027        buf->irq_count |= 0x01;
3028
3029        return wm_adsp_buffer_write(buf, HOST_BUFFER_FIELD(irq_ack),
3030                                    buf->irq_count);
3031}
3032
3033int wm_adsp_compr_pointer(struct snd_compr_stream *stream,
3034                          struct snd_compr_tstamp *tstamp)
3035{
3036        struct wm_adsp_compr *compr = stream->runtime->private_data;
3037        struct wm_adsp *dsp = compr->dsp;
3038        struct wm_adsp_compr_buf *buf;
3039        int ret = 0;
3040
3041        adsp_dbg(dsp, "Pointer request\n");
3042
3043        mutex_lock(&dsp->pwr_lock);
3044
3045        buf = compr->buf;
3046
3047        if (!compr->buf || compr->buf->error) {
3048                snd_compr_stop_error(stream, SNDRV_PCM_STATE_XRUN);
3049                ret = -EIO;
3050                goto out;
3051        }
3052
3053        if (buf->avail < wm_adsp_compr_frag_words(compr)) {
3054                ret = wm_adsp_buffer_update_avail(buf);
3055                if (ret < 0) {
3056                        adsp_err(dsp, "Error reading avail: %d\n", ret);
3057                        goto out;
3058                }
3059
3060                /*
3061                 * If we really have less than 1 fragment available tell the
3062                 * DSP to inform us once a whole fragment is available.
3063                 */
3064                if (buf->avail < wm_adsp_compr_frag_words(compr)) {
3065                        ret = wm_adsp_buffer_get_error(buf);
3066                        if (ret < 0) {
3067                                if (compr->buf->error)
3068                                        snd_compr_stop_error(stream,
3069                                                        SNDRV_PCM_STATE_XRUN);
3070                                goto out;
3071                        }
3072
3073                        ret = wm_adsp_buffer_reenable_irq(buf);
3074                        if (ret < 0) {
3075                                adsp_err(dsp,
3076                                         "Failed to re-enable buffer IRQ: %d\n",
3077                                         ret);
3078                                goto out;
3079                        }
3080                }
3081        }
3082
3083        tstamp->copied_total = compr->copied_total;
3084        tstamp->copied_total += buf->avail * WM_ADSP_DATA_WORD_SIZE;
3085        tstamp->sampling_rate = compr->sample_rate;
3086
3087out:
3088        mutex_unlock(&dsp->pwr_lock);
3089
3090        return ret;
3091}
3092EXPORT_SYMBOL_GPL(wm_adsp_compr_pointer);
3093
3094static int wm_adsp_buffer_capture_block(struct wm_adsp_compr *compr, int target)
3095{
3096        struct wm_adsp_compr_buf *buf = compr->buf;
3097        u8 *pack_in = (u8 *)compr->raw_buf;
3098        u8 *pack_out = (u8 *)compr->raw_buf;
3099        unsigned int adsp_addr;
3100        int mem_type, nwords, max_read;
3101        int i, j, ret;
3102
3103        /* Calculate read parameters */
3104        for (i = 0; i < wm_adsp_fw[buf->dsp->fw].caps->num_regions; ++i)
3105                if (buf->read_index < buf->regions[i].cumulative_size)
3106                        break;
3107
3108        if (i == wm_adsp_fw[buf->dsp->fw].caps->num_regions)
3109                return -EINVAL;
3110
3111        mem_type = buf->regions[i].mem_type;
3112        adsp_addr = buf->regions[i].base_addr +
3113                    (buf->read_index - buf->regions[i].offset);
3114
3115        max_read = wm_adsp_compr_frag_words(compr);
3116        nwords = buf->regions[i].cumulative_size - buf->read_index;
3117
3118        if (nwords > target)
3119                nwords = target;
3120        if (nwords > buf->avail)
3121                nwords = buf->avail;
3122        if (nwords > max_read)
3123                nwords = max_read;
3124        if (!nwords)
3125                return 0;
3126
3127        /* Read data from DSP */
3128        ret = wm_adsp_read_data_block(buf->dsp, mem_type, adsp_addr,
3129                                      nwords, compr->raw_buf);
3130        if (ret < 0)
3131                return ret;
3132
3133        /* Remove the padding bytes from the data read from the DSP */
3134        for (i = 0; i < nwords; i++) {
3135                for (j = 0; j < WM_ADSP_DATA_WORD_SIZE; j++)
3136                        *pack_out++ = *pack_in++;
3137
3138                pack_in += sizeof(*(compr->raw_buf)) - WM_ADSP_DATA_WORD_SIZE;
3139        }
3140
3141        /* update read index to account for words read */
3142        buf->read_index += nwords;
3143        if (buf->read_index == wm_adsp_buffer_size(buf))
3144                buf->read_index = 0;
3145
3146        ret = wm_adsp_buffer_write(buf, HOST_BUFFER_FIELD(next_read_index),
3147                                   buf->read_index);
3148        if (ret < 0)
3149                return ret;
3150
3151        /* update avail to account for words read */
3152        buf->avail -= nwords;
3153
3154        return nwords;
3155}
3156
3157static int wm_adsp_compr_read(struct wm_adsp_compr *compr,
3158                              char __user *buf, size_t count)
3159{
3160        struct wm_adsp *dsp = compr->dsp;
3161        int ntotal = 0;
3162        int nwords, nbytes;
3163
3164        adsp_dbg(dsp, "Requested read of %zu bytes\n", count);
3165
3166        if (!compr->buf || compr->buf->error) {
3167                snd_compr_stop_error(compr->stream, SNDRV_PCM_STATE_XRUN);
3168                return -EIO;
3169        }
3170
3171        count /= WM_ADSP_DATA_WORD_SIZE;
3172
3173        do {
3174                nwords = wm_adsp_buffer_capture_block(compr, count);
3175                if (nwords < 0) {
3176                        adsp_err(dsp, "Failed to capture block: %d\n", nwords);
3177                        return nwords;
3178                }
3179
3180                nbytes = nwords * WM_ADSP_DATA_WORD_SIZE;
3181
3182                adsp_dbg(dsp, "Read %d bytes\n", nbytes);
3183
3184                if (copy_to_user(buf + ntotal, compr->raw_buf, nbytes)) {
3185                        adsp_err(dsp, "Failed to copy data to user: %d, %d\n",
3186                                 ntotal, nbytes);
3187                        return -EFAULT;
3188                }
3189
3190                count -= nwords;
3191                ntotal += nbytes;
3192        } while (nwords > 0 && count > 0);
3193
3194        compr->copied_total += ntotal;
3195
3196        return ntotal;
3197}
3198
3199int wm_adsp_compr_copy(struct snd_compr_stream *stream, char __user *buf,
3200                       size_t count)
3201{
3202        struct wm_adsp_compr *compr = stream->runtime->private_data;
3203        struct wm_adsp *dsp = compr->dsp;
3204        int ret;
3205
3206        mutex_lock(&dsp->pwr_lock);
3207
3208        if (stream->direction == SND_COMPRESS_CAPTURE)
3209                ret = wm_adsp_compr_read(compr, buf, count);
3210        else
3211                ret = -ENOTSUPP;
3212
3213        mutex_unlock(&dsp->pwr_lock);
3214
3215        return ret;
3216}
3217EXPORT_SYMBOL_GPL(wm_adsp_compr_copy);
3218
3219MODULE_LICENSE("GPL v2");
3220