linux/sound/soc/intel/baytrail/sst-baytrail-ipc.c
<<
>>
Prefs
   1/*
   2 * Intel Baytrail SST IPC Support
   3 * Copyright (c) 2014, Intel Corporation.
   4 *
   5 * This program is free software; you can redistribute it and/or modify it
   6 * under the terms and conditions of the GNU General Public License,
   7 * version 2, as published by the Free Software Foundation.
   8 *
   9 * This program is distributed in the hope it will be useful, but WITHOUT
  10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  12 * more details.
  13 */
  14
  15#include <linux/types.h>
  16#include <linux/kernel.h>
  17#include <linux/list.h>
  18#include <linux/device.h>
  19#include <linux/wait.h>
  20#include <linux/spinlock.h>
  21#include <linux/workqueue.h>
  22#include <linux/export.h>
  23#include <linux/slab.h>
  24#include <linux/delay.h>
  25#include <linux/platform_device.h>
  26#include <linux/firmware.h>
  27#include <linux/io.h>
  28#include <asm/div64.h>
  29
  30#include "sst-baytrail-ipc.h"
  31#include "../common/sst-dsp.h"
  32#include "../common/sst-dsp-priv.h"
  33#include "../common/sst-ipc.h"
  34
  35/* IPC message timeout */
  36#define IPC_TIMEOUT_MSECS       300
  37#define IPC_BOOT_MSECS          200
  38
  39#define IPC_EMPTY_LIST_SIZE     8
  40
  41/* IPC header bits */
  42#define IPC_HEADER_MSG_ID_MASK  0xff
  43#define IPC_HEADER_MSG_ID(x)    ((x) & IPC_HEADER_MSG_ID_MASK)
  44#define IPC_HEADER_STR_ID_SHIFT 8
  45#define IPC_HEADER_STR_ID_MASK  0x1f
  46#define IPC_HEADER_STR_ID(x)    (((x) & 0x1f) << IPC_HEADER_STR_ID_SHIFT)
  47#define IPC_HEADER_LARGE_SHIFT  13
  48#define IPC_HEADER_LARGE(x)     (((x) & 0x1) << IPC_HEADER_LARGE_SHIFT)
  49#define IPC_HEADER_DATA_SHIFT   16
  50#define IPC_HEADER_DATA_MASK    0x3fff
  51#define IPC_HEADER_DATA(x)      (((x) & 0x3fff) << IPC_HEADER_DATA_SHIFT)
  52
  53/* mask for differentiating between notification and reply message */
  54#define IPC_NOTIFICATION        (0x1 << 7)
  55
  56/* I2L Stream config/control msgs */
  57#define IPC_IA_ALLOC_STREAM     0x20
  58#define IPC_IA_FREE_STREAM      0x21
  59#define IPC_IA_PAUSE_STREAM     0x24
  60#define IPC_IA_RESUME_STREAM    0x25
  61#define IPC_IA_DROP_STREAM      0x26
  62#define IPC_IA_START_STREAM     0x30
  63
  64/* notification messages */
  65#define IPC_IA_FW_INIT_CMPLT    0x81
  66#define IPC_SST_PERIOD_ELAPSED  0x97
  67
  68/* IPC messages between host and ADSP */
  69struct sst_byt_address_info {
  70        u32 addr;
  71        u32 size;
  72} __packed;
  73
  74struct sst_byt_str_type {
  75        u8 codec_type;
  76        u8 str_type;
  77        u8 operation;
  78        u8 protected_str;
  79        u8 time_slots;
  80        u8 reserved;
  81        u16 result;
  82} __packed;
  83
  84struct sst_byt_pcm_params {
  85        u8 num_chan;
  86        u8 pcm_wd_sz;
  87        u8 use_offload_path;
  88        u8 reserved;
  89        u32 sfreq;
  90        u8 channel_map[8];
  91} __packed;
  92
  93struct sst_byt_frames_info {
  94        u16 num_entries;
  95        u16 rsrvd;
  96        u32 frag_size;
  97        struct sst_byt_address_info ring_buf_info[8];
  98} __packed;
  99
 100struct sst_byt_alloc_params {
 101        struct sst_byt_str_type str_type;
 102        struct sst_byt_pcm_params pcm_params;
 103        struct sst_byt_frames_info frame_info;
 104} __packed;
 105
 106struct sst_byt_alloc_response {
 107        struct sst_byt_str_type str_type;
 108        u8 reserved[88];
 109} __packed;
 110
 111struct sst_byt_start_stream_params {
 112        u32 byte_offset;
 113} __packed;
 114
 115struct sst_byt_tstamp {
 116        u64 ring_buffer_counter;
 117        u64 hardware_counter;
 118        u64 frames_decoded;
 119        u64 bytes_decoded;
 120        u64 bytes_copied;
 121        u32 sampling_frequency;
 122        u32 channel_peak[8];
 123} __packed;
 124
 125struct sst_byt_fw_version {
 126        u8 build;
 127        u8 minor;
 128        u8 major;
 129        u8 type;
 130} __packed;
 131
 132struct sst_byt_fw_build_info {
 133        u8 date[16];
 134        u8 time[16];
 135} __packed;
 136
 137struct sst_byt_fw_init {
 138        struct sst_byt_fw_version fw_version;
 139        struct sst_byt_fw_build_info build_info;
 140        u16 result;
 141        u8 module_id;
 142        u8 debug_info;
 143} __packed;
 144
 145struct sst_byt_stream;
 146struct sst_byt;
 147
 148/* stream infomation */
 149struct sst_byt_stream {
 150        struct list_head node;
 151
 152        /* configuration */
 153        struct sst_byt_alloc_params request;
 154        struct sst_byt_alloc_response reply;
 155
 156        /* runtime info */
 157        struct sst_byt *byt;
 158        int str_id;
 159        bool commited;
 160        bool running;
 161
 162        /* driver callback */
 163        u32 (*notify_position)(struct sst_byt_stream *stream, void *data);
 164        void *pdata;
 165};
 166
 167/* SST Baytrail IPC data */
 168struct sst_byt {
 169        struct device *dev;
 170        struct sst_dsp *dsp;
 171
 172        /* stream */
 173        struct list_head stream_list;
 174
 175        /* boot */
 176        wait_queue_head_t boot_wait;
 177        bool boot_complete;
 178        struct sst_fw *fw;
 179
 180        /* IPC messaging */
 181        struct sst_generic_ipc ipc;
 182};
 183
 184static inline u64 sst_byt_header(int msg_id, int data, bool large, int str_id)
 185{
 186        return IPC_HEADER_MSG_ID(msg_id) | IPC_HEADER_STR_ID(str_id) |
 187               IPC_HEADER_LARGE(large) | IPC_HEADER_DATA(data) |
 188               SST_BYT_IPCX_BUSY;
 189}
 190
 191static inline u16 sst_byt_header_msg_id(u64 header)
 192{
 193        return header & IPC_HEADER_MSG_ID_MASK;
 194}
 195
 196static inline u8 sst_byt_header_str_id(u64 header)
 197{
 198        return (header >> IPC_HEADER_STR_ID_SHIFT) & IPC_HEADER_STR_ID_MASK;
 199}
 200
 201static inline u16 sst_byt_header_data(u64 header)
 202{
 203        return (header >> IPC_HEADER_DATA_SHIFT) & IPC_HEADER_DATA_MASK;
 204}
 205
 206static struct sst_byt_stream *sst_byt_get_stream(struct sst_byt *byt,
 207                                                 int stream_id)
 208{
 209        struct sst_byt_stream *stream;
 210
 211        list_for_each_entry(stream, &byt->stream_list, node) {
 212                if (stream->str_id == stream_id)
 213                        return stream;
 214        }
 215
 216        return NULL;
 217}
 218
 219static void sst_byt_stream_update(struct sst_byt *byt, struct ipc_message *msg)
 220{
 221        struct sst_byt_stream *stream;
 222        u64 header = msg->header;
 223        u8 stream_id = sst_byt_header_str_id(header);
 224        u8 stream_msg = sst_byt_header_msg_id(header);
 225
 226        stream = sst_byt_get_stream(byt, stream_id);
 227        if (stream == NULL)
 228                return;
 229
 230        switch (stream_msg) {
 231        case IPC_IA_DROP_STREAM:
 232        case IPC_IA_PAUSE_STREAM:
 233        case IPC_IA_FREE_STREAM:
 234                stream->running = false;
 235                break;
 236        case IPC_IA_START_STREAM:
 237        case IPC_IA_RESUME_STREAM:
 238                stream->running = true;
 239                break;
 240        }
 241}
 242
 243static int sst_byt_process_reply(struct sst_byt *byt, u64 header)
 244{
 245        struct ipc_message *msg;
 246
 247        msg = sst_ipc_reply_find_msg(&byt->ipc, header);
 248        if (msg == NULL)
 249                return 1;
 250
 251        if (header & IPC_HEADER_LARGE(true)) {
 252                msg->rx_size = sst_byt_header_data(header);
 253                sst_dsp_inbox_read(byt->dsp, msg->rx_data, msg->rx_size);
 254        }
 255
 256        /* update any stream states */
 257        sst_byt_stream_update(byt, msg);
 258
 259        list_del(&msg->list);
 260        /* wake up */
 261        sst_ipc_tx_msg_reply_complete(&byt->ipc, msg);
 262
 263        return 1;
 264}
 265
 266static void sst_byt_fw_ready(struct sst_byt *byt, u64 header)
 267{
 268        dev_dbg(byt->dev, "ipc: DSP is ready 0x%llX\n", header);
 269
 270        byt->boot_complete = true;
 271        wake_up(&byt->boot_wait);
 272}
 273
 274static int sst_byt_process_notification(struct sst_byt *byt,
 275                                        unsigned long *flags)
 276{
 277        struct sst_dsp *sst = byt->dsp;
 278        struct sst_byt_stream *stream;
 279        u64 header;
 280        u8 msg_id, stream_id;
 281        int handled = 1;
 282
 283        header = sst_dsp_shim_read64_unlocked(sst, SST_IPCD);
 284        msg_id = sst_byt_header_msg_id(header);
 285
 286        switch (msg_id) {
 287        case IPC_SST_PERIOD_ELAPSED:
 288                stream_id = sst_byt_header_str_id(header);
 289                stream = sst_byt_get_stream(byt, stream_id);
 290                if (stream && stream->running && stream->notify_position) {
 291                        spin_unlock_irqrestore(&sst->spinlock, *flags);
 292                        stream->notify_position(stream, stream->pdata);
 293                        spin_lock_irqsave(&sst->spinlock, *flags);
 294                }
 295                break;
 296        case IPC_IA_FW_INIT_CMPLT:
 297                sst_byt_fw_ready(byt, header);
 298                break;
 299        }
 300
 301        return handled;
 302}
 303
 304static irqreturn_t sst_byt_irq_thread(int irq, void *context)
 305{
 306        struct sst_dsp *sst = (struct sst_dsp *) context;
 307        struct sst_byt *byt = sst_dsp_get_thread_context(sst);
 308        struct sst_generic_ipc *ipc = &byt->ipc;
 309        u64 header;
 310        unsigned long flags;
 311
 312        spin_lock_irqsave(&sst->spinlock, flags);
 313
 314        header = sst_dsp_shim_read64_unlocked(sst, SST_IPCD);
 315        if (header & SST_BYT_IPCD_BUSY) {
 316                if (header & IPC_NOTIFICATION) {
 317                        /* message from ADSP */
 318                        sst_byt_process_notification(byt, &flags);
 319                } else {
 320                        /* reply from ADSP */
 321                        sst_byt_process_reply(byt, header);
 322                }
 323                /*
 324                 * clear IPCD BUSY bit and set DONE bit. Tell DSP we have
 325                 * processed the message and can accept new. Clear data part
 326                 * of the header
 327                 */
 328                sst_dsp_shim_update_bits64_unlocked(sst, SST_IPCD,
 329                        SST_BYT_IPCD_DONE | SST_BYT_IPCD_BUSY |
 330                        IPC_HEADER_DATA(IPC_HEADER_DATA_MASK),
 331                        SST_BYT_IPCD_DONE);
 332                /* unmask message request interrupts */
 333                sst_dsp_shim_update_bits64_unlocked(sst, SST_IMRX,
 334                        SST_BYT_IMRX_REQUEST, 0);
 335        }
 336
 337        spin_unlock_irqrestore(&sst->spinlock, flags);
 338
 339        /* continue to send any remaining messages... */
 340        schedule_work(&ipc->kwork);
 341
 342        return IRQ_HANDLED;
 343}
 344
 345/* stream API */
 346struct sst_byt_stream *sst_byt_stream_new(struct sst_byt *byt, int id,
 347        u32 (*notify_position)(struct sst_byt_stream *stream, void *data),
 348        void *data)
 349{
 350        struct sst_byt_stream *stream;
 351        struct sst_dsp *sst = byt->dsp;
 352        unsigned long flags;
 353
 354        stream = kzalloc(sizeof(*stream), GFP_KERNEL);
 355        if (stream == NULL)
 356                return NULL;
 357
 358        spin_lock_irqsave(&sst->spinlock, flags);
 359        list_add(&stream->node, &byt->stream_list);
 360        stream->notify_position = notify_position;
 361        stream->pdata = data;
 362        stream->byt = byt;
 363        stream->str_id = id;
 364        spin_unlock_irqrestore(&sst->spinlock, flags);
 365
 366        return stream;
 367}
 368
 369int sst_byt_stream_set_bits(struct sst_byt *byt, struct sst_byt_stream *stream,
 370                            int bits)
 371{
 372        stream->request.pcm_params.pcm_wd_sz = bits;
 373        return 0;
 374}
 375
 376int sst_byt_stream_set_channels(struct sst_byt *byt,
 377                                struct sst_byt_stream *stream, u8 channels)
 378{
 379        stream->request.pcm_params.num_chan = channels;
 380        return 0;
 381}
 382
 383int sst_byt_stream_set_rate(struct sst_byt *byt, struct sst_byt_stream *stream,
 384                            unsigned int rate)
 385{
 386        stream->request.pcm_params.sfreq = rate;
 387        return 0;
 388}
 389
 390/* stream sonfiguration */
 391int sst_byt_stream_type(struct sst_byt *byt, struct sst_byt_stream *stream,
 392                        int codec_type, int stream_type, int operation)
 393{
 394        stream->request.str_type.codec_type = codec_type;
 395        stream->request.str_type.str_type = stream_type;
 396        stream->request.str_type.operation = operation;
 397        stream->request.str_type.time_slots = 0xc;
 398
 399        return 0;
 400}
 401
 402int sst_byt_stream_buffer(struct sst_byt *byt, struct sst_byt_stream *stream,
 403                          uint32_t buffer_addr, uint32_t buffer_size)
 404{
 405        stream->request.frame_info.num_entries = 1;
 406        stream->request.frame_info.ring_buf_info[0].addr = buffer_addr;
 407        stream->request.frame_info.ring_buf_info[0].size = buffer_size;
 408        /* calculate bytes per 4 ms fragment */
 409        stream->request.frame_info.frag_size =
 410                stream->request.pcm_params.sfreq *
 411                stream->request.pcm_params.num_chan *
 412                stream->request.pcm_params.pcm_wd_sz / 8 *
 413                4 / 1000;
 414        return 0;
 415}
 416
 417int sst_byt_stream_commit(struct sst_byt *byt, struct sst_byt_stream *stream)
 418{
 419        struct sst_byt_alloc_params *str_req = &stream->request;
 420        struct sst_byt_alloc_response *reply = &stream->reply;
 421        u64 header;
 422        int ret;
 423
 424        header = sst_byt_header(IPC_IA_ALLOC_STREAM,
 425                                sizeof(*str_req) + sizeof(u32),
 426                                true, stream->str_id);
 427        ret = sst_ipc_tx_message_wait(&byt->ipc, header, str_req,
 428                                      sizeof(*str_req),
 429                                      reply, sizeof(*reply));
 430        if (ret < 0) {
 431                dev_err(byt->dev, "ipc: error stream commit failed\n");
 432                return ret;
 433        }
 434
 435        stream->commited = true;
 436
 437        return 0;
 438}
 439
 440int sst_byt_stream_free(struct sst_byt *byt, struct sst_byt_stream *stream)
 441{
 442        u64 header;
 443        int ret = 0;
 444        struct sst_dsp *sst = byt->dsp;
 445        unsigned long flags;
 446
 447        if (!stream->commited)
 448                goto out;
 449
 450        header = sst_byt_header(IPC_IA_FREE_STREAM, 0, false, stream->str_id);
 451        ret = sst_ipc_tx_message_wait(&byt->ipc, header, NULL, 0, NULL, 0);
 452        if (ret < 0) {
 453                dev_err(byt->dev, "ipc: free stream %d failed\n",
 454                        stream->str_id);
 455                return -EAGAIN;
 456        }
 457
 458        stream->commited = false;
 459out:
 460        spin_lock_irqsave(&sst->spinlock, flags);
 461        list_del(&stream->node);
 462        kfree(stream);
 463        spin_unlock_irqrestore(&sst->spinlock, flags);
 464
 465        return ret;
 466}
 467
 468static int sst_byt_stream_operations(struct sst_byt *byt, int type,
 469                                     int stream_id, int wait)
 470{
 471        u64 header;
 472
 473        header = sst_byt_header(type, 0, false, stream_id);
 474        if (wait)
 475                return sst_ipc_tx_message_wait(&byt->ipc, header, NULL,
 476                                                0, NULL, 0);
 477        else
 478                return sst_ipc_tx_message_nowait(&byt->ipc, header,
 479                                                NULL, 0);
 480}
 481
 482/* stream ALSA trigger operations */
 483int sst_byt_stream_start(struct sst_byt *byt, struct sst_byt_stream *stream,
 484                         u32 start_offset)
 485{
 486        struct sst_byt_start_stream_params start_stream;
 487        void *tx_msg;
 488        size_t size;
 489        u64 header;
 490        int ret;
 491
 492        start_stream.byte_offset = start_offset;
 493        header = sst_byt_header(IPC_IA_START_STREAM,
 494                                sizeof(start_stream) + sizeof(u32),
 495                                true, stream->str_id);
 496        tx_msg = &start_stream;
 497        size = sizeof(start_stream);
 498
 499        ret = sst_ipc_tx_message_nowait(&byt->ipc, header, tx_msg, size);
 500        if (ret < 0)
 501                dev_err(byt->dev, "ipc: error failed to start stream %d\n",
 502                        stream->str_id);
 503
 504        return ret;
 505}
 506
 507int sst_byt_stream_stop(struct sst_byt *byt, struct sst_byt_stream *stream)
 508{
 509        int ret;
 510
 511        /* don't stop streams that are not commited */
 512        if (!stream->commited)
 513                return 0;
 514
 515        ret = sst_byt_stream_operations(byt, IPC_IA_DROP_STREAM,
 516                                        stream->str_id, 0);
 517        if (ret < 0)
 518                dev_err(byt->dev, "ipc: error failed to stop stream %d\n",
 519                        stream->str_id);
 520        return ret;
 521}
 522
 523int sst_byt_stream_pause(struct sst_byt *byt, struct sst_byt_stream *stream)
 524{
 525        int ret;
 526
 527        ret = sst_byt_stream_operations(byt, IPC_IA_PAUSE_STREAM,
 528                                        stream->str_id, 0);
 529        if (ret < 0)
 530                dev_err(byt->dev, "ipc: error failed to pause stream %d\n",
 531                        stream->str_id);
 532
 533        return ret;
 534}
 535
 536int sst_byt_stream_resume(struct sst_byt *byt, struct sst_byt_stream *stream)
 537{
 538        int ret;
 539
 540        ret = sst_byt_stream_operations(byt, IPC_IA_RESUME_STREAM,
 541                                        stream->str_id, 0);
 542        if (ret < 0)
 543                dev_err(byt->dev, "ipc: error failed to resume stream %d\n",
 544                        stream->str_id);
 545
 546        return ret;
 547}
 548
 549int sst_byt_get_dsp_position(struct sst_byt *byt,
 550                             struct sst_byt_stream *stream, int buffer_size)
 551{
 552        struct sst_dsp *sst = byt->dsp;
 553        struct sst_byt_tstamp fw_tstamp;
 554        u8 str_id = stream->str_id;
 555        u32 tstamp_offset;
 556
 557        tstamp_offset = SST_BYT_TIMESTAMP_OFFSET + str_id * sizeof(fw_tstamp);
 558        memcpy_fromio(&fw_tstamp,
 559                      sst->addr.lpe + tstamp_offset, sizeof(fw_tstamp));
 560
 561        return do_div(fw_tstamp.ring_buffer_counter, buffer_size);
 562}
 563
 564struct sst_dsp *sst_byt_get_dsp(struct sst_byt *byt)
 565{
 566        return byt->dsp;
 567}
 568
 569static struct sst_dsp_device byt_dev = {
 570        .thread = sst_byt_irq_thread,
 571        .ops = &sst_byt_ops,
 572};
 573
 574int sst_byt_dsp_suspend_late(struct device *dev, struct sst_pdata *pdata)
 575{
 576        struct sst_byt *byt = pdata->dsp;
 577
 578        dev_dbg(byt->dev, "dsp reset\n");
 579        sst_dsp_reset(byt->dsp);
 580        sst_ipc_drop_all(&byt->ipc);
 581        dev_dbg(byt->dev, "dsp in reset\n");
 582
 583        dev_dbg(byt->dev, "free all blocks and unload fw\n");
 584        sst_fw_unload(byt->fw);
 585
 586        return 0;
 587}
 588EXPORT_SYMBOL_GPL(sst_byt_dsp_suspend_late);
 589
 590int sst_byt_dsp_boot(struct device *dev, struct sst_pdata *pdata)
 591{
 592        struct sst_byt *byt = pdata->dsp;
 593        int ret;
 594
 595        dev_dbg(byt->dev, "reload dsp fw\n");
 596
 597        sst_dsp_reset(byt->dsp);
 598
 599        ret = sst_fw_reload(byt->fw);
 600        if (ret <  0) {
 601                dev_err(dev, "error: failed to reload firmware\n");
 602                return ret;
 603        }
 604
 605        /* wait for DSP boot completion */
 606        byt->boot_complete = false;
 607        sst_dsp_boot(byt->dsp);
 608        dev_dbg(byt->dev, "dsp booting...\n");
 609
 610        return 0;
 611}
 612EXPORT_SYMBOL_GPL(sst_byt_dsp_boot);
 613
 614int sst_byt_dsp_wait_for_ready(struct device *dev, struct sst_pdata *pdata)
 615{
 616        struct sst_byt *byt = pdata->dsp;
 617        int err;
 618
 619        dev_dbg(byt->dev, "wait for dsp reboot\n");
 620
 621        err = wait_event_timeout(byt->boot_wait, byt->boot_complete,
 622                                 msecs_to_jiffies(IPC_BOOT_MSECS));
 623        if (err == 0) {
 624                dev_err(byt->dev, "ipc: error DSP boot timeout\n");
 625                return -EIO;
 626        }
 627
 628        dev_dbg(byt->dev, "dsp rebooted\n");
 629        return 0;
 630}
 631EXPORT_SYMBOL_GPL(sst_byt_dsp_wait_for_ready);
 632
 633static void byt_tx_msg(struct sst_generic_ipc *ipc, struct ipc_message *msg)
 634{
 635        if (msg->header & IPC_HEADER_LARGE(true))
 636                sst_dsp_outbox_write(ipc->dsp, msg->tx_data, msg->tx_size);
 637
 638        sst_dsp_shim_write64_unlocked(ipc->dsp, SST_IPCX, msg->header);
 639}
 640
 641static void byt_shim_dbg(struct sst_generic_ipc *ipc, const char *text)
 642{
 643        struct sst_dsp *sst = ipc->dsp;
 644        u64 isr, ipcd, imrx, ipcx;
 645
 646        ipcx = sst_dsp_shim_read64_unlocked(sst, SST_IPCX);
 647        isr = sst_dsp_shim_read64_unlocked(sst, SST_ISRX);
 648        ipcd = sst_dsp_shim_read64_unlocked(sst, SST_IPCD);
 649        imrx = sst_dsp_shim_read64_unlocked(sst, SST_IMRX);
 650
 651        dev_err(ipc->dev,
 652                "ipc: --%s-- ipcx 0x%llx isr 0x%llx ipcd 0x%llx imrx 0x%llx\n",
 653                text, ipcx, isr, ipcd, imrx);
 654}
 655
 656static void byt_tx_data_copy(struct ipc_message *msg, char *tx_data,
 657        size_t tx_size)
 658{
 659        /* msg content = lower 32-bit of the header + data */
 660        *(u32 *)msg->tx_data = (u32)(msg->header & (u32)-1);
 661        memcpy(msg->tx_data + sizeof(u32), tx_data, tx_size);
 662        msg->tx_size += sizeof(u32);
 663}
 664
 665static u64 byt_reply_msg_match(u64 header, u64 *mask)
 666{
 667        /* match reply to message sent based on msg and stream IDs */
 668        *mask = IPC_HEADER_MSG_ID_MASK |
 669               IPC_HEADER_STR_ID_MASK << IPC_HEADER_STR_ID_SHIFT;
 670        header &= *mask;
 671
 672        return header;
 673}
 674
 675static bool byt_is_dsp_busy(struct sst_dsp *dsp)
 676{
 677        u64 ipcx;
 678
 679        ipcx = sst_dsp_shim_read_unlocked(dsp, SST_IPCX);
 680        return (ipcx & (SST_IPCX_BUSY | SST_IPCX_DONE));
 681}
 682
 683int sst_byt_dsp_init(struct device *dev, struct sst_pdata *pdata)
 684{
 685        struct sst_byt *byt;
 686        struct sst_generic_ipc *ipc;
 687        struct sst_fw *byt_sst_fw;
 688        struct sst_byt_fw_init init;
 689        int err;
 690
 691        dev_dbg(dev, "initialising Byt DSP IPC\n");
 692
 693        byt = devm_kzalloc(dev, sizeof(*byt), GFP_KERNEL);
 694        if (byt == NULL)
 695                return -ENOMEM;
 696
 697        byt->dev = dev;
 698
 699        ipc = &byt->ipc;
 700        ipc->dev = dev;
 701        ipc->ops.tx_msg = byt_tx_msg;
 702        ipc->ops.shim_dbg = byt_shim_dbg;
 703        ipc->ops.tx_data_copy = byt_tx_data_copy;
 704        ipc->ops.reply_msg_match = byt_reply_msg_match;
 705        ipc->ops.is_dsp_busy = byt_is_dsp_busy;
 706        ipc->tx_data_max_size = IPC_MAX_MAILBOX_BYTES;
 707        ipc->rx_data_max_size = IPC_MAX_MAILBOX_BYTES;
 708
 709        err = sst_ipc_init(ipc);
 710        if (err != 0)
 711                goto ipc_init_err;
 712
 713        INIT_LIST_HEAD(&byt->stream_list);
 714        init_waitqueue_head(&byt->boot_wait);
 715        byt_dev.thread_context = byt;
 716
 717        /* init SST shim */
 718        byt->dsp = sst_dsp_new(dev, &byt_dev, pdata);
 719        if (byt->dsp == NULL) {
 720                err = -ENODEV;
 721                goto dsp_new_err;
 722        }
 723
 724        ipc->dsp = byt->dsp;
 725
 726        /* keep the DSP in reset state for base FW loading */
 727        sst_dsp_reset(byt->dsp);
 728
 729        byt_sst_fw = sst_fw_new(byt->dsp, pdata->fw, byt);
 730        if (byt_sst_fw  == NULL) {
 731                err = -ENODEV;
 732                dev_err(dev, "error: failed to load firmware\n");
 733                goto fw_err;
 734        }
 735
 736        /* wait for DSP boot completion */
 737        sst_dsp_boot(byt->dsp);
 738        err = wait_event_timeout(byt->boot_wait, byt->boot_complete,
 739                                 msecs_to_jiffies(IPC_BOOT_MSECS));
 740        if (err == 0) {
 741                err = -EIO;
 742                dev_err(byt->dev, "ipc: error DSP boot timeout\n");
 743                goto boot_err;
 744        }
 745
 746        /* show firmware information */
 747        sst_dsp_inbox_read(byt->dsp, &init, sizeof(init));
 748        dev_info(byt->dev, "FW version: %02x.%02x.%02x.%02x\n",
 749                 init.fw_version.major, init.fw_version.minor,
 750                 init.fw_version.build, init.fw_version.type);
 751        dev_info(byt->dev, "Build type: %x\n", init.fw_version.type);
 752        dev_info(byt->dev, "Build date: %s %s\n",
 753                 init.build_info.date, init.build_info.time);
 754
 755        pdata->dsp = byt;
 756        byt->fw = byt_sst_fw;
 757
 758        return 0;
 759
 760boot_err:
 761        sst_dsp_reset(byt->dsp);
 762        sst_fw_free(byt_sst_fw);
 763fw_err:
 764        sst_dsp_free(byt->dsp);
 765dsp_new_err:
 766        sst_ipc_fini(ipc);
 767ipc_init_err:
 768
 769        return err;
 770}
 771EXPORT_SYMBOL_GPL(sst_byt_dsp_init);
 772
 773void sst_byt_dsp_free(struct device *dev, struct sst_pdata *pdata)
 774{
 775        struct sst_byt *byt = pdata->dsp;
 776
 777        sst_dsp_reset(byt->dsp);
 778        sst_fw_free_all(byt->dsp);
 779        sst_dsp_free(byt->dsp);
 780        sst_ipc_fini(&byt->ipc);
 781}
 782EXPORT_SYMBOL_GPL(sst_byt_dsp_free);
 783