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