linux/sound/soc/codecs/cros_ec_codec.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright 2019 Google, Inc.
   4 *
   5 * ChromeOS Embedded Controller codec driver.
   6 *
   7 * This driver uses the cros-ec interface to communicate with the ChromeOS
   8 * EC for audio function.
   9 */
  10
  11#include <crypto/sha2.h>
  12#include <linux/acpi.h>
  13#include <linux/delay.h>
  14#include <linux/device.h>
  15#include <linux/io.h>
  16#include <linux/jiffies.h>
  17#include <linux/kernel.h>
  18#include <linux/module.h>
  19#include <linux/of.h>
  20#include <linux/of_address.h>
  21#include <linux/platform_data/cros_ec_commands.h>
  22#include <linux/platform_data/cros_ec_proto.h>
  23#include <linux/platform_device.h>
  24#include <sound/pcm.h>
  25#include <sound/pcm_params.h>
  26#include <sound/soc.h>
  27#include <sound/tlv.h>
  28
  29struct cros_ec_codec_priv {
  30        struct device *dev;
  31        struct cros_ec_device *ec_device;
  32
  33        /* common */
  34        uint32_t ec_capabilities;
  35
  36        uint64_t ec_shm_addr;
  37        uint32_t ec_shm_len;
  38
  39        uint64_t ap_shm_phys_addr;
  40        uint32_t ap_shm_len;
  41        uint64_t ap_shm_addr;
  42        uint64_t ap_shm_last_alloc;
  43
  44        /* DMIC */
  45        atomic_t dmic_probed;
  46
  47        /* I2S_RX */
  48        uint32_t i2s_rx_bclk_ratio;
  49
  50        /* WoV */
  51        bool wov_enabled;
  52        uint8_t *wov_audio_shm_p;
  53        uint32_t wov_audio_shm_len;
  54        uint8_t wov_audio_shm_type;
  55        uint8_t *wov_lang_shm_p;
  56        uint32_t wov_lang_shm_len;
  57        uint8_t wov_lang_shm_type;
  58
  59        struct mutex wov_dma_lock;
  60        uint8_t wov_buf[64000];
  61        uint32_t wov_rp, wov_wp;
  62        size_t wov_dma_offset;
  63        bool wov_burst_read;
  64        struct snd_pcm_substream *wov_substream;
  65        struct delayed_work wov_copy_work;
  66        struct notifier_block wov_notifier;
  67};
  68
  69static int ec_codec_capable(struct cros_ec_codec_priv *priv, uint8_t cap)
  70{
  71        return priv->ec_capabilities & BIT(cap);
  72}
  73
  74static int send_ec_host_command(struct cros_ec_device *ec_dev, uint32_t cmd,
  75                                uint8_t *out, size_t outsize,
  76                                uint8_t *in, size_t insize)
  77{
  78        int ret;
  79        struct cros_ec_command *msg;
  80
  81        msg = kmalloc(sizeof(*msg) + max(outsize, insize), GFP_KERNEL);
  82        if (!msg)
  83                return -ENOMEM;
  84
  85        msg->version = 0;
  86        msg->command = cmd;
  87        msg->outsize = outsize;
  88        msg->insize = insize;
  89
  90        if (outsize)
  91                memcpy(msg->data, out, outsize);
  92
  93        ret = cros_ec_cmd_xfer_status(ec_dev, msg);
  94        if (ret < 0)
  95                goto error;
  96
  97        if (in && insize)
  98                memcpy(in, msg->data, insize);
  99
 100        ret = 0;
 101error:
 102        kfree(msg);
 103        return ret;
 104}
 105
 106static int dmic_get_gain(struct snd_kcontrol *kcontrol,
 107                         struct snd_ctl_elem_value *ucontrol)
 108{
 109        struct snd_soc_component *component =
 110                snd_soc_kcontrol_component(kcontrol);
 111        struct cros_ec_codec_priv *priv =
 112                snd_soc_component_get_drvdata(component);
 113        struct ec_param_ec_codec_dmic p;
 114        struct ec_response_ec_codec_dmic_get_gain_idx r;
 115        int ret;
 116
 117        p.cmd = EC_CODEC_DMIC_GET_GAIN_IDX;
 118        p.get_gain_idx_param.channel = EC_CODEC_DMIC_CHANNEL_0;
 119        ret = send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_DMIC,
 120                                   (uint8_t *)&p, sizeof(p),
 121                                   (uint8_t *)&r, sizeof(r));
 122        if (ret < 0)
 123                return ret;
 124        ucontrol->value.integer.value[0] = r.gain;
 125
 126        p.cmd = EC_CODEC_DMIC_GET_GAIN_IDX;
 127        p.get_gain_idx_param.channel = EC_CODEC_DMIC_CHANNEL_1;
 128        ret = send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_DMIC,
 129                                   (uint8_t *)&p, sizeof(p),
 130                                   (uint8_t *)&r, sizeof(r));
 131        if (ret < 0)
 132                return ret;
 133        ucontrol->value.integer.value[1] = r.gain;
 134
 135        return 0;
 136}
 137
 138static int dmic_put_gain(struct snd_kcontrol *kcontrol,
 139                         struct snd_ctl_elem_value *ucontrol)
 140{
 141        struct snd_soc_component *component =
 142                snd_soc_kcontrol_component(kcontrol);
 143        struct cros_ec_codec_priv *priv =
 144                snd_soc_component_get_drvdata(component);
 145        struct soc_mixer_control *control =
 146                (struct soc_mixer_control *)kcontrol->private_value;
 147        int max_dmic_gain = control->max;
 148        int left = ucontrol->value.integer.value[0];
 149        int right = ucontrol->value.integer.value[1];
 150        struct ec_param_ec_codec_dmic p;
 151        int ret;
 152
 153        if (left > max_dmic_gain || right > max_dmic_gain)
 154                return -EINVAL;
 155
 156        dev_dbg(component->dev, "set mic gain to %u, %u\n", left, right);
 157
 158        p.cmd = EC_CODEC_DMIC_SET_GAIN_IDX;
 159        p.set_gain_idx_param.channel = EC_CODEC_DMIC_CHANNEL_0;
 160        p.set_gain_idx_param.gain = left;
 161        ret = send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_DMIC,
 162                                   (uint8_t *)&p, sizeof(p), NULL, 0);
 163        if (ret < 0)
 164                return ret;
 165
 166        p.cmd = EC_CODEC_DMIC_SET_GAIN_IDX;
 167        p.set_gain_idx_param.channel = EC_CODEC_DMIC_CHANNEL_1;
 168        p.set_gain_idx_param.gain = right;
 169        return send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_DMIC,
 170                                    (uint8_t *)&p, sizeof(p), NULL, 0);
 171}
 172
 173static const DECLARE_TLV_DB_SCALE(dmic_gain_tlv, 0, 100, 0);
 174
 175enum {
 176        DMIC_CTL_GAIN = 0,
 177};
 178
 179static struct snd_kcontrol_new dmic_controls[] = {
 180        [DMIC_CTL_GAIN] =
 181                SOC_DOUBLE_EXT_TLV("EC Mic Gain", SND_SOC_NOPM, SND_SOC_NOPM,
 182                                   0, 0, 0, dmic_get_gain, dmic_put_gain,
 183                                   dmic_gain_tlv),
 184};
 185
 186static int dmic_probe(struct snd_soc_component *component)
 187{
 188        struct cros_ec_codec_priv *priv =
 189                snd_soc_component_get_drvdata(component);
 190        struct device *dev = priv->dev;
 191        struct soc_mixer_control *control;
 192        struct ec_param_ec_codec_dmic p;
 193        struct ec_response_ec_codec_dmic_get_max_gain r;
 194        int ret;
 195
 196        if (!atomic_add_unless(&priv->dmic_probed, 1, 1))
 197                return 0;
 198
 199        p.cmd = EC_CODEC_DMIC_GET_MAX_GAIN;
 200
 201        ret = send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_DMIC,
 202                                   (uint8_t *)&p, sizeof(p),
 203                                   (uint8_t *)&r, sizeof(r));
 204        if (ret < 0) {
 205                dev_warn(dev, "get_max_gain() unsupported\n");
 206                return 0;
 207        }
 208
 209        dev_dbg(dev, "max gain = %d\n", r.max_gain);
 210
 211        control = (struct soc_mixer_control *)
 212                dmic_controls[DMIC_CTL_GAIN].private_value;
 213        control->max = r.max_gain;
 214        control->platform_max = r.max_gain;
 215
 216        return snd_soc_add_component_controls(component,
 217                        &dmic_controls[DMIC_CTL_GAIN], 1);
 218}
 219
 220static int i2s_rx_hw_params(struct snd_pcm_substream *substream,
 221                            struct snd_pcm_hw_params *params,
 222                            struct snd_soc_dai *dai)
 223{
 224        struct snd_soc_component *component = dai->component;
 225        struct cros_ec_codec_priv *priv =
 226                snd_soc_component_get_drvdata(component);
 227        struct ec_param_ec_codec_i2s_rx p;
 228        enum ec_codec_i2s_rx_sample_depth depth;
 229        uint32_t bclk;
 230        int ret;
 231
 232        if (params_rate(params) != 48000)
 233                return -EINVAL;
 234
 235        switch (params_format(params)) {
 236        case SNDRV_PCM_FORMAT_S16_LE:
 237                depth = EC_CODEC_I2S_RX_SAMPLE_DEPTH_16;
 238                break;
 239        case SNDRV_PCM_FORMAT_S24_LE:
 240                depth = EC_CODEC_I2S_RX_SAMPLE_DEPTH_24;
 241                break;
 242        default:
 243                return -EINVAL;
 244        }
 245
 246        dev_dbg(component->dev, "set depth to %u\n", depth);
 247
 248        p.cmd = EC_CODEC_I2S_RX_SET_SAMPLE_DEPTH;
 249        p.set_sample_depth_param.depth = depth;
 250        ret = send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_I2S_RX,
 251                                   (uint8_t *)&p, sizeof(p), NULL, 0);
 252        if (ret < 0)
 253                return ret;
 254
 255        if (priv->i2s_rx_bclk_ratio)
 256                bclk = params_rate(params) * priv->i2s_rx_bclk_ratio;
 257        else
 258                bclk = snd_soc_params_to_bclk(params);
 259
 260        dev_dbg(component->dev, "set bclk to %u\n", bclk);
 261
 262        p.cmd = EC_CODEC_I2S_RX_SET_BCLK;
 263        p.set_bclk_param.bclk = bclk;
 264        return send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_I2S_RX,
 265                                    (uint8_t *)&p, sizeof(p), NULL, 0);
 266}
 267
 268static int i2s_rx_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio)
 269{
 270        struct snd_soc_component *component = dai->component;
 271        struct cros_ec_codec_priv *priv =
 272                snd_soc_component_get_drvdata(component);
 273
 274        priv->i2s_rx_bclk_ratio = ratio;
 275        return 0;
 276}
 277
 278static int i2s_rx_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 279{
 280        struct snd_soc_component *component = dai->component;
 281        struct cros_ec_codec_priv *priv =
 282                snd_soc_component_get_drvdata(component);
 283        struct ec_param_ec_codec_i2s_rx p;
 284        enum ec_codec_i2s_rx_daifmt daifmt;
 285
 286        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
 287        case SND_SOC_DAIFMT_CBS_CFS:
 288                break;
 289        default:
 290                return -EINVAL;
 291        }
 292
 293        switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
 294        case SND_SOC_DAIFMT_NB_NF:
 295                break;
 296        default:
 297                return -EINVAL;
 298        }
 299
 300        switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
 301        case SND_SOC_DAIFMT_I2S:
 302                daifmt = EC_CODEC_I2S_RX_DAIFMT_I2S;
 303                break;
 304        case SND_SOC_DAIFMT_RIGHT_J:
 305                daifmt = EC_CODEC_I2S_RX_DAIFMT_RIGHT_J;
 306                break;
 307        case SND_SOC_DAIFMT_LEFT_J:
 308                daifmt = EC_CODEC_I2S_RX_DAIFMT_LEFT_J;
 309                break;
 310        default:
 311                return -EINVAL;
 312        }
 313
 314        dev_dbg(component->dev, "set format to %u\n", daifmt);
 315
 316        p.cmd = EC_CODEC_I2S_RX_SET_DAIFMT;
 317        p.set_daifmt_param.daifmt = daifmt;
 318        return send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_I2S_RX,
 319                                    (uint8_t *)&p, sizeof(p), NULL, 0);
 320}
 321
 322static const struct snd_soc_dai_ops i2s_rx_dai_ops = {
 323        .hw_params = i2s_rx_hw_params,
 324        .set_fmt = i2s_rx_set_fmt,
 325        .set_bclk_ratio = i2s_rx_set_bclk_ratio,
 326};
 327
 328static int i2s_rx_event(struct snd_soc_dapm_widget *w,
 329                        struct snd_kcontrol *kcontrol, int event)
 330{
 331        struct snd_soc_component *component =
 332                snd_soc_dapm_to_component(w->dapm);
 333        struct cros_ec_codec_priv *priv =
 334                snd_soc_component_get_drvdata(component);
 335        struct ec_param_ec_codec_i2s_rx p = {};
 336
 337        switch (event) {
 338        case SND_SOC_DAPM_PRE_PMU:
 339                dev_dbg(component->dev, "enable I2S RX\n");
 340                p.cmd = EC_CODEC_I2S_RX_ENABLE;
 341                break;
 342        case SND_SOC_DAPM_PRE_PMD:
 343                dev_dbg(component->dev, "disable I2S RX\n");
 344                p.cmd = EC_CODEC_I2S_RX_DISABLE;
 345                break;
 346        default:
 347                return 0;
 348        }
 349
 350        return send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_I2S_RX,
 351                                    (uint8_t *)&p, sizeof(p), NULL, 0);
 352}
 353
 354static struct snd_soc_dapm_widget i2s_rx_dapm_widgets[] = {
 355        SND_SOC_DAPM_INPUT("DMIC"),
 356        SND_SOC_DAPM_SUPPLY("I2S RX Enable", SND_SOC_NOPM, 0, 0, i2s_rx_event,
 357                            SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
 358        SND_SOC_DAPM_AIF_OUT("I2S RX", "I2S Capture", 0, SND_SOC_NOPM, 0, 0),
 359};
 360
 361static struct snd_soc_dapm_route i2s_rx_dapm_routes[] = {
 362        {"I2S RX", NULL, "DMIC"},
 363        {"I2S RX", NULL, "I2S RX Enable"},
 364};
 365
 366static struct snd_soc_dai_driver i2s_rx_dai_driver = {
 367        .name = "EC Codec I2S RX",
 368        .capture = {
 369                .stream_name = "I2S Capture",
 370                .channels_min = 2,
 371                .channels_max = 2,
 372                .rates = SNDRV_PCM_RATE_48000,
 373                .formats = SNDRV_PCM_FMTBIT_S16_LE |
 374                        SNDRV_PCM_FMTBIT_S24_LE,
 375        },
 376        .ops = &i2s_rx_dai_ops,
 377};
 378
 379static int i2s_rx_probe(struct snd_soc_component *component)
 380{
 381        return dmic_probe(component);
 382}
 383
 384static const struct snd_soc_component_driver i2s_rx_component_driver = {
 385        .probe                  = i2s_rx_probe,
 386        .dapm_widgets           = i2s_rx_dapm_widgets,
 387        .num_dapm_widgets       = ARRAY_SIZE(i2s_rx_dapm_widgets),
 388        .dapm_routes            = i2s_rx_dapm_routes,
 389        .num_dapm_routes        = ARRAY_SIZE(i2s_rx_dapm_routes),
 390};
 391
 392static void *wov_map_shm(struct cros_ec_codec_priv *priv,
 393                         uint8_t shm_id, uint32_t *len, uint8_t *type)
 394{
 395        struct ec_param_ec_codec p;
 396        struct ec_response_ec_codec_get_shm_addr r;
 397        uint32_t req, offset;
 398
 399        p.cmd = EC_CODEC_GET_SHM_ADDR;
 400        p.get_shm_addr_param.shm_id = shm_id;
 401        if (send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC,
 402                                 (uint8_t *)&p, sizeof(p),
 403                                 (uint8_t *)&r, sizeof(r)) < 0) {
 404                dev_err(priv->dev, "failed to EC_CODEC_GET_SHM_ADDR\n");
 405                return NULL;
 406        }
 407
 408        dev_dbg(priv->dev, "phys_addr=%#llx, len=%#x\n", r.phys_addr, r.len);
 409
 410        *len = r.len;
 411        *type = r.type;
 412
 413        switch (r.type) {
 414        case EC_CODEC_SHM_TYPE_EC_RAM:
 415                return (void __force *)devm_ioremap_wc(priv->dev,
 416                                r.phys_addr + priv->ec_shm_addr, r.len);
 417        case EC_CODEC_SHM_TYPE_SYSTEM_RAM:
 418                if (r.phys_addr) {
 419                        dev_err(priv->dev, "unknown status\n");
 420                        return NULL;
 421                }
 422
 423                req = round_up(r.len, PAGE_SIZE);
 424                dev_dbg(priv->dev, "round up from %u to %u\n", r.len, req);
 425
 426                if (priv->ap_shm_last_alloc + req >
 427                    priv->ap_shm_phys_addr + priv->ap_shm_len) {
 428                        dev_err(priv->dev, "insufficient space for AP SHM\n");
 429                        return NULL;
 430                }
 431
 432                dev_dbg(priv->dev, "alloc AP SHM addr=%#llx, len=%#x\n",
 433                        priv->ap_shm_last_alloc, req);
 434
 435                p.cmd = EC_CODEC_SET_SHM_ADDR;
 436                p.set_shm_addr_param.phys_addr = priv->ap_shm_last_alloc;
 437                p.set_shm_addr_param.len = req;
 438                p.set_shm_addr_param.shm_id = shm_id;
 439                if (send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC,
 440                                         (uint8_t *)&p, sizeof(p),
 441                                         NULL, 0) < 0) {
 442                        dev_err(priv->dev, "failed to EC_CODEC_SET_SHM_ADDR\n");
 443                        return NULL;
 444                }
 445
 446                /*
 447                 * Note: EC codec only requests for `r.len' but we allocate
 448                 * round up PAGE_SIZE `req'.
 449                 */
 450                offset = priv->ap_shm_last_alloc - priv->ap_shm_phys_addr;
 451                priv->ap_shm_last_alloc += req;
 452
 453                return (void *)(uintptr_t)(priv->ap_shm_addr + offset);
 454        default:
 455                return NULL;
 456        }
 457}
 458
 459static bool wov_queue_full(struct cros_ec_codec_priv *priv)
 460{
 461        return ((priv->wov_wp + 1) % sizeof(priv->wov_buf)) == priv->wov_rp;
 462}
 463
 464static size_t wov_queue_size(struct cros_ec_codec_priv *priv)
 465{
 466        if (priv->wov_wp >= priv->wov_rp)
 467                return priv->wov_wp - priv->wov_rp;
 468        else
 469                return sizeof(priv->wov_buf) - priv->wov_rp + priv->wov_wp;
 470}
 471
 472static void wov_queue_dequeue(struct cros_ec_codec_priv *priv, size_t len)
 473{
 474        struct snd_pcm_runtime *runtime = priv->wov_substream->runtime;
 475        size_t req;
 476
 477        while (len) {
 478                req = min(len, runtime->dma_bytes - priv->wov_dma_offset);
 479                if (priv->wov_wp >= priv->wov_rp)
 480                        req = min(req, (size_t)priv->wov_wp - priv->wov_rp);
 481                else
 482                        req = min(req, sizeof(priv->wov_buf) - priv->wov_rp);
 483
 484                memcpy(runtime->dma_area + priv->wov_dma_offset,
 485                       priv->wov_buf + priv->wov_rp, req);
 486
 487                priv->wov_dma_offset += req;
 488                if (priv->wov_dma_offset == runtime->dma_bytes)
 489                        priv->wov_dma_offset = 0;
 490
 491                priv->wov_rp += req;
 492                if (priv->wov_rp == sizeof(priv->wov_buf))
 493                        priv->wov_rp = 0;
 494
 495                len -= req;
 496        }
 497
 498        snd_pcm_period_elapsed(priv->wov_substream);
 499}
 500
 501static void wov_queue_try_dequeue(struct cros_ec_codec_priv *priv)
 502{
 503        size_t period_bytes = snd_pcm_lib_period_bytes(priv->wov_substream);
 504
 505        while (period_bytes && wov_queue_size(priv) >= period_bytes) {
 506                wov_queue_dequeue(priv, period_bytes);
 507                period_bytes = snd_pcm_lib_period_bytes(priv->wov_substream);
 508        }
 509}
 510
 511static void wov_queue_enqueue(struct cros_ec_codec_priv *priv,
 512                              uint8_t *addr, size_t len, bool iomem)
 513{
 514        size_t req;
 515
 516        while (len) {
 517                if (wov_queue_full(priv)) {
 518                        wov_queue_try_dequeue(priv);
 519
 520                        if (wov_queue_full(priv)) {
 521                                dev_err(priv->dev, "overrun detected\n");
 522                                return;
 523                        }
 524                }
 525
 526                if (priv->wov_wp >= priv->wov_rp)
 527                        req = sizeof(priv->wov_buf) - priv->wov_wp;
 528                else
 529                        /* Note: waste 1-byte to differentiate full and empty */
 530                        req = priv->wov_rp - priv->wov_wp - 1;
 531                req = min(req, len);
 532
 533                if (iomem)
 534                        memcpy_fromio(priv->wov_buf + priv->wov_wp,
 535                                      (void __force __iomem *)addr, req);
 536                else
 537                        memcpy(priv->wov_buf + priv->wov_wp, addr, req);
 538
 539                priv->wov_wp += req;
 540                if (priv->wov_wp == sizeof(priv->wov_buf))
 541                        priv->wov_wp = 0;
 542
 543                addr += req;
 544                len -= req;
 545        }
 546
 547        wov_queue_try_dequeue(priv);
 548}
 549
 550static int wov_read_audio_shm(struct cros_ec_codec_priv *priv)
 551{
 552        struct ec_param_ec_codec_wov p;
 553        struct ec_response_ec_codec_wov_read_audio_shm r;
 554        int ret;
 555
 556        p.cmd = EC_CODEC_WOV_READ_AUDIO_SHM;
 557        ret = send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_WOV,
 558                                   (uint8_t *)&p, sizeof(p),
 559                                   (uint8_t *)&r, sizeof(r));
 560        if (ret) {
 561                dev_err(priv->dev, "failed to EC_CODEC_WOV_READ_AUDIO_SHM\n");
 562                return ret;
 563        }
 564
 565        if (!r.len)
 566                dev_dbg(priv->dev, "no data, sleep\n");
 567        else
 568                wov_queue_enqueue(priv, priv->wov_audio_shm_p + r.offset, r.len,
 569                        priv->wov_audio_shm_type == EC_CODEC_SHM_TYPE_EC_RAM);
 570        return -EAGAIN;
 571}
 572
 573static int wov_read_audio(struct cros_ec_codec_priv *priv)
 574{
 575        struct ec_param_ec_codec_wov p;
 576        struct ec_response_ec_codec_wov_read_audio r;
 577        int remain = priv->wov_burst_read ? 16000 : 320;
 578        int ret;
 579
 580        while (remain >= 0) {
 581                p.cmd = EC_CODEC_WOV_READ_AUDIO;
 582                ret = send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_WOV,
 583                                           (uint8_t *)&p, sizeof(p),
 584                                           (uint8_t *)&r, sizeof(r));
 585                if (ret) {
 586                        dev_err(priv->dev,
 587                                "failed to EC_CODEC_WOV_READ_AUDIO\n");
 588                        return ret;
 589                }
 590
 591                if (!r.len) {
 592                        dev_dbg(priv->dev, "no data, sleep\n");
 593                        priv->wov_burst_read = false;
 594                        break;
 595                }
 596
 597                wov_queue_enqueue(priv, r.buf, r.len, false);
 598                remain -= r.len;
 599        }
 600
 601        return -EAGAIN;
 602}
 603
 604static void wov_copy_work(struct work_struct *w)
 605{
 606        struct cros_ec_codec_priv *priv =
 607                container_of(w, struct cros_ec_codec_priv, wov_copy_work.work);
 608        int ret;
 609
 610        mutex_lock(&priv->wov_dma_lock);
 611        if (!priv->wov_substream) {
 612                dev_warn(priv->dev, "no pcm substream\n");
 613                goto leave;
 614        }
 615
 616        if (ec_codec_capable(priv, EC_CODEC_CAP_WOV_AUDIO_SHM))
 617                ret = wov_read_audio_shm(priv);
 618        else
 619                ret = wov_read_audio(priv);
 620
 621        if (ret == -EAGAIN)
 622                schedule_delayed_work(&priv->wov_copy_work,
 623                                      msecs_to_jiffies(10));
 624        else if (ret)
 625                dev_err(priv->dev, "failed to read audio data\n");
 626leave:
 627        mutex_unlock(&priv->wov_dma_lock);
 628}
 629
 630static int wov_enable_get(struct snd_kcontrol *kcontrol,
 631                          struct snd_ctl_elem_value *ucontrol)
 632{
 633        struct snd_soc_component *c = snd_soc_kcontrol_component(kcontrol);
 634        struct cros_ec_codec_priv *priv = snd_soc_component_get_drvdata(c);
 635
 636        ucontrol->value.integer.value[0] = priv->wov_enabled;
 637        return 0;
 638}
 639
 640static int wov_enable_put(struct snd_kcontrol *kcontrol,
 641                          struct snd_ctl_elem_value *ucontrol)
 642{
 643        struct snd_soc_component *c = snd_soc_kcontrol_component(kcontrol);
 644        struct cros_ec_codec_priv *priv = snd_soc_component_get_drvdata(c);
 645        int enabled = ucontrol->value.integer.value[0];
 646        struct ec_param_ec_codec_wov p;
 647        int ret;
 648
 649        if (priv->wov_enabled != enabled) {
 650                if (enabled)
 651                        p.cmd = EC_CODEC_WOV_ENABLE;
 652                else
 653                        p.cmd = EC_CODEC_WOV_DISABLE;
 654
 655                ret = send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_WOV,
 656                                           (uint8_t *)&p, sizeof(p), NULL, 0);
 657                if (ret) {
 658                        dev_err(priv->dev, "failed to %s wov\n",
 659                                enabled ? "enable" : "disable");
 660                        return ret;
 661                }
 662
 663                priv->wov_enabled = enabled;
 664        }
 665
 666        return 0;
 667}
 668
 669static int wov_set_lang_shm(struct cros_ec_codec_priv *priv,
 670                            uint8_t *buf, size_t size, uint8_t *digest)
 671{
 672        struct ec_param_ec_codec_wov p;
 673        struct ec_param_ec_codec_wov_set_lang_shm *pp = &p.set_lang_shm_param;
 674        int ret;
 675
 676        if (size > priv->wov_lang_shm_len) {
 677                dev_err(priv->dev, "no enough SHM size: %d\n",
 678                        priv->wov_lang_shm_len);
 679                return -EIO;
 680        }
 681
 682        switch (priv->wov_lang_shm_type) {
 683        case EC_CODEC_SHM_TYPE_EC_RAM:
 684                memcpy_toio((void __force __iomem *)priv->wov_lang_shm_p,
 685                            buf, size);
 686                memset_io((void __force __iomem *)priv->wov_lang_shm_p + size,
 687                          0, priv->wov_lang_shm_len - size);
 688                break;
 689        case EC_CODEC_SHM_TYPE_SYSTEM_RAM:
 690                memcpy(priv->wov_lang_shm_p, buf, size);
 691                memset(priv->wov_lang_shm_p + size, 0,
 692                       priv->wov_lang_shm_len - size);
 693
 694                /* make sure write to memory before calling host command */
 695                wmb();
 696                break;
 697        }
 698
 699        p.cmd = EC_CODEC_WOV_SET_LANG_SHM;
 700        memcpy(pp->hash, digest, SHA256_DIGEST_SIZE);
 701        pp->total_len = size;
 702        ret = send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_WOV,
 703                                   (uint8_t *)&p, sizeof(p), NULL, 0);
 704        if (ret) {
 705                dev_err(priv->dev, "failed to EC_CODEC_WOV_SET_LANG_SHM\n");
 706                return ret;
 707        }
 708
 709        return 0;
 710}
 711
 712static int wov_set_lang(struct cros_ec_codec_priv *priv,
 713                        uint8_t *buf, size_t size, uint8_t *digest)
 714{
 715        struct ec_param_ec_codec_wov p;
 716        struct ec_param_ec_codec_wov_set_lang *pp = &p.set_lang_param;
 717        size_t i, req;
 718        int ret;
 719
 720        for (i = 0; i < size; i += req) {
 721                req = min(size - i, ARRAY_SIZE(pp->buf));
 722
 723                p.cmd = EC_CODEC_WOV_SET_LANG;
 724                memcpy(pp->hash, digest, SHA256_DIGEST_SIZE);
 725                pp->total_len = size;
 726                pp->offset = i;
 727                memcpy(pp->buf, buf + i, req);
 728                pp->len = req;
 729                ret = send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_WOV,
 730                                           (uint8_t *)&p, sizeof(p), NULL, 0);
 731                if (ret) {
 732                        dev_err(priv->dev, "failed to EC_CODEC_WOV_SET_LANG\n");
 733                        return ret;
 734                }
 735        }
 736
 737        return 0;
 738}
 739
 740static int wov_hotword_model_put(struct snd_kcontrol *kcontrol,
 741                                 const unsigned int __user *bytes,
 742                                 unsigned int size)
 743{
 744        struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
 745        struct cros_ec_codec_priv *priv =
 746                snd_soc_component_get_drvdata(component);
 747        struct ec_param_ec_codec_wov p;
 748        struct ec_response_ec_codec_wov_get_lang r;
 749        uint8_t digest[SHA256_DIGEST_SIZE];
 750        uint8_t *buf;
 751        int ret;
 752
 753        /* Skips the TLV header. */
 754        bytes += 2;
 755        size -= 8;
 756
 757        dev_dbg(priv->dev, "%s: size=%d\n", __func__, size);
 758
 759        buf = memdup_user(bytes, size);
 760        if (IS_ERR(buf))
 761                return PTR_ERR(buf);
 762
 763        sha256(buf, size, digest);
 764        dev_dbg(priv->dev, "hash=%*phN\n", SHA256_DIGEST_SIZE, digest);
 765
 766        p.cmd = EC_CODEC_WOV_GET_LANG;
 767        ret = send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_WOV,
 768                                   (uint8_t *)&p, sizeof(p),
 769                                   (uint8_t *)&r, sizeof(r));
 770        if (ret)
 771                goto leave;
 772
 773        if (memcmp(digest, r.hash, SHA256_DIGEST_SIZE) == 0) {
 774                dev_dbg(priv->dev, "not updated");
 775                goto leave;
 776        }
 777
 778        if (ec_codec_capable(priv, EC_CODEC_CAP_WOV_LANG_SHM))
 779                ret = wov_set_lang_shm(priv, buf, size, digest);
 780        else
 781                ret = wov_set_lang(priv, buf, size, digest);
 782
 783leave:
 784        kfree(buf);
 785        return ret;
 786}
 787
 788static struct snd_kcontrol_new wov_controls[] = {
 789        SOC_SINGLE_BOOL_EXT("Wake-on-Voice Switch", 0,
 790                            wov_enable_get, wov_enable_put),
 791        SND_SOC_BYTES_TLV("Hotword Model", 0x11000, NULL,
 792                          wov_hotword_model_put),
 793};
 794
 795static struct snd_soc_dai_driver wov_dai_driver = {
 796        .name = "Wake on Voice",
 797        .capture = {
 798                .stream_name = "WoV Capture",
 799                .channels_min = 1,
 800                .channels_max = 1,
 801                .rates = SNDRV_PCM_RATE_16000,
 802                .formats = SNDRV_PCM_FMTBIT_S16_LE,
 803        },
 804};
 805
 806static int wov_host_event(struct notifier_block *nb,
 807                          unsigned long queued_during_suspend, void *notify)
 808{
 809        struct cros_ec_codec_priv *priv =
 810                container_of(nb, struct cros_ec_codec_priv, wov_notifier);
 811        u32 host_event;
 812
 813        dev_dbg(priv->dev, "%s\n", __func__);
 814
 815        host_event = cros_ec_get_host_event(priv->ec_device);
 816        if (host_event & EC_HOST_EVENT_MASK(EC_HOST_EVENT_WOV)) {
 817                schedule_delayed_work(&priv->wov_copy_work, 0);
 818                return NOTIFY_OK;
 819        } else {
 820                return NOTIFY_DONE;
 821        }
 822}
 823
 824static int wov_probe(struct snd_soc_component *component)
 825{
 826        struct cros_ec_codec_priv *priv =
 827                snd_soc_component_get_drvdata(component);
 828        int ret;
 829
 830        mutex_init(&priv->wov_dma_lock);
 831        INIT_DELAYED_WORK(&priv->wov_copy_work, wov_copy_work);
 832
 833        priv->wov_notifier.notifier_call = wov_host_event;
 834        ret = blocking_notifier_chain_register(
 835                        &priv->ec_device->event_notifier, &priv->wov_notifier);
 836        if (ret)
 837                return ret;
 838
 839        if (ec_codec_capable(priv, EC_CODEC_CAP_WOV_LANG_SHM)) {
 840                priv->wov_lang_shm_p = wov_map_shm(priv,
 841                                EC_CODEC_SHM_ID_WOV_LANG,
 842                                &priv->wov_lang_shm_len,
 843                                &priv->wov_lang_shm_type);
 844                if (!priv->wov_lang_shm_p)
 845                        return -EFAULT;
 846        }
 847
 848        if (ec_codec_capable(priv, EC_CODEC_CAP_WOV_AUDIO_SHM)) {
 849                priv->wov_audio_shm_p = wov_map_shm(priv,
 850                                EC_CODEC_SHM_ID_WOV_AUDIO,
 851                                &priv->wov_audio_shm_len,
 852                                &priv->wov_audio_shm_type);
 853                if (!priv->wov_audio_shm_p)
 854                        return -EFAULT;
 855        }
 856
 857        return dmic_probe(component);
 858}
 859
 860static void wov_remove(struct snd_soc_component *component)
 861{
 862        struct cros_ec_codec_priv *priv =
 863                snd_soc_component_get_drvdata(component);
 864
 865        blocking_notifier_chain_unregister(
 866                        &priv->ec_device->event_notifier, &priv->wov_notifier);
 867}
 868
 869static int wov_pcm_open(struct snd_soc_component *component,
 870                        struct snd_pcm_substream *substream)
 871{
 872        static const struct snd_pcm_hardware hw_param = {
 873                .info = SNDRV_PCM_INFO_MMAP |
 874                        SNDRV_PCM_INFO_INTERLEAVED |
 875                        SNDRV_PCM_INFO_MMAP_VALID,
 876                .formats = SNDRV_PCM_FMTBIT_S16_LE,
 877                .rates = SNDRV_PCM_RATE_16000,
 878                .channels_min = 1,
 879                .channels_max = 1,
 880                .period_bytes_min = PAGE_SIZE,
 881                .period_bytes_max = 0x20000 / 8,
 882                .periods_min = 8,
 883                .periods_max = 8,
 884                .buffer_bytes_max = 0x20000,
 885        };
 886
 887        return snd_soc_set_runtime_hwparams(substream, &hw_param);
 888}
 889
 890static int wov_pcm_hw_params(struct snd_soc_component *component,
 891                             struct snd_pcm_substream *substream,
 892                             struct snd_pcm_hw_params *hw_params)
 893{
 894        struct cros_ec_codec_priv *priv =
 895                snd_soc_component_get_drvdata(component);
 896
 897        mutex_lock(&priv->wov_dma_lock);
 898        priv->wov_substream = substream;
 899        priv->wov_rp = priv->wov_wp = 0;
 900        priv->wov_dma_offset = 0;
 901        priv->wov_burst_read = true;
 902        mutex_unlock(&priv->wov_dma_lock);
 903
 904        return 0;
 905}
 906
 907static int wov_pcm_hw_free(struct snd_soc_component *component,
 908                           struct snd_pcm_substream *substream)
 909{
 910        struct cros_ec_codec_priv *priv =
 911                snd_soc_component_get_drvdata(component);
 912
 913        mutex_lock(&priv->wov_dma_lock);
 914        wov_queue_dequeue(priv, wov_queue_size(priv));
 915        priv->wov_substream = NULL;
 916        mutex_unlock(&priv->wov_dma_lock);
 917
 918        cancel_delayed_work_sync(&priv->wov_copy_work);
 919
 920        return 0;
 921}
 922
 923static snd_pcm_uframes_t wov_pcm_pointer(struct snd_soc_component *component,
 924                                         struct snd_pcm_substream *substream)
 925{
 926        struct snd_pcm_runtime *runtime = substream->runtime;
 927        struct cros_ec_codec_priv *priv =
 928                snd_soc_component_get_drvdata(component);
 929
 930        return bytes_to_frames(runtime, priv->wov_dma_offset);
 931}
 932
 933static int wov_pcm_new(struct snd_soc_component *component,
 934                       struct snd_soc_pcm_runtime *rtd)
 935{
 936        snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_VMALLOC,
 937                                       NULL, 0, 0);
 938        return 0;
 939}
 940
 941static const struct snd_soc_component_driver wov_component_driver = {
 942        .probe          = wov_probe,
 943        .remove         = wov_remove,
 944        .controls       = wov_controls,
 945        .num_controls   = ARRAY_SIZE(wov_controls),
 946        .open           = wov_pcm_open,
 947        .hw_params      = wov_pcm_hw_params,
 948        .hw_free        = wov_pcm_hw_free,
 949        .pointer        = wov_pcm_pointer,
 950        .pcm_construct  = wov_pcm_new,
 951};
 952
 953static int cros_ec_codec_platform_probe(struct platform_device *pdev)
 954{
 955        struct device *dev = &pdev->dev;
 956        struct cros_ec_device *ec_device = dev_get_drvdata(pdev->dev.parent);
 957        struct cros_ec_codec_priv *priv;
 958        struct ec_param_ec_codec p;
 959        struct ec_response_ec_codec_get_capabilities r;
 960        int ret;
 961#ifdef CONFIG_OF
 962        struct device_node *node;
 963        struct resource res;
 964        u64 ec_shm_size;
 965        const __be32 *regaddr_p;
 966#endif
 967
 968        priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
 969        if (!priv)
 970                return -ENOMEM;
 971
 972#ifdef CONFIG_OF
 973        regaddr_p = of_get_address(dev->of_node, 0, &ec_shm_size, NULL);
 974        if (regaddr_p) {
 975                priv->ec_shm_addr = of_read_number(regaddr_p, 2);
 976                priv->ec_shm_len = ec_shm_size;
 977
 978                dev_dbg(dev, "ec_shm_addr=%#llx len=%#x\n",
 979                        priv->ec_shm_addr, priv->ec_shm_len);
 980        }
 981
 982        node = of_parse_phandle(dev->of_node, "memory-region", 0);
 983        if (node) {
 984                ret = of_address_to_resource(node, 0, &res);
 985                if (!ret) {
 986                        priv->ap_shm_phys_addr = res.start;
 987                        priv->ap_shm_len = resource_size(&res);
 988                        priv->ap_shm_addr =
 989                                (uint64_t)(uintptr_t)devm_ioremap_wc(
 990                                        dev, priv->ap_shm_phys_addr,
 991                                        priv->ap_shm_len);
 992                        priv->ap_shm_last_alloc = priv->ap_shm_phys_addr;
 993
 994                        dev_dbg(dev, "ap_shm_phys_addr=%#llx len=%#x\n",
 995                                priv->ap_shm_phys_addr, priv->ap_shm_len);
 996                }
 997        }
 998#endif
 999
1000        priv->dev = dev;
1001        priv->ec_device = ec_device;
1002        atomic_set(&priv->dmic_probed, 0);
1003
1004        p.cmd = EC_CODEC_GET_CAPABILITIES;
1005        ret = send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC,
1006                                   (uint8_t *)&p, sizeof(p),
1007                                   (uint8_t *)&r, sizeof(r));
1008        if (ret) {
1009                dev_err(dev, "failed to EC_CODEC_GET_CAPABILITIES\n");
1010                return ret;
1011        }
1012        priv->ec_capabilities = r.capabilities;
1013
1014        /* Reset EC codec i2s rx. */
1015        p.cmd = EC_CODEC_I2S_RX_RESET;
1016        ret = send_ec_host_command(priv->ec_device, EC_CMD_EC_CODEC_I2S_RX,
1017                                   (uint8_t *)&p, sizeof(p), NULL, 0);
1018        if (ret == -ENOPROTOOPT) {
1019                dev_info(dev,
1020                         "Missing reset command. Please update EC firmware.\n");
1021        } else if (ret) {
1022                dev_err(dev, "failed to EC_CODEC_I2S_RESET: %d\n", ret);
1023                return ret;
1024        }
1025
1026        platform_set_drvdata(pdev, priv);
1027
1028        ret = devm_snd_soc_register_component(dev, &i2s_rx_component_driver,
1029                                              &i2s_rx_dai_driver, 1);
1030        if (ret)
1031                return ret;
1032
1033        return devm_snd_soc_register_component(dev, &wov_component_driver,
1034                                               &wov_dai_driver, 1);
1035}
1036
1037#ifdef CONFIG_OF
1038static const struct of_device_id cros_ec_codec_of_match[] = {
1039        { .compatible = "google,cros-ec-codec" },
1040        {},
1041};
1042MODULE_DEVICE_TABLE(of, cros_ec_codec_of_match);
1043#endif
1044
1045#ifdef CONFIG_ACPI
1046static const struct acpi_device_id cros_ec_codec_acpi_id[] = {
1047        { "GOOG0013", 0 },
1048        { }
1049};
1050MODULE_DEVICE_TABLE(acpi, cros_ec_codec_acpi_id);
1051#endif
1052
1053static struct platform_driver cros_ec_codec_platform_driver = {
1054        .driver = {
1055                .name = "cros-ec-codec",
1056                .of_match_table = of_match_ptr(cros_ec_codec_of_match),
1057                .acpi_match_table = ACPI_PTR(cros_ec_codec_acpi_id),
1058        },
1059        .probe = cros_ec_codec_platform_probe,
1060};
1061
1062module_platform_driver(cros_ec_codec_platform_driver);
1063
1064MODULE_LICENSE("GPL v2");
1065MODULE_DESCRIPTION("ChromeOS EC codec driver");
1066MODULE_AUTHOR("Cheng-Yi Chiang <cychiang@chromium.org>");
1067MODULE_ALIAS("platform:cros-ec-codec");
1068