1// Copyright 2018 The Fuchsia Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#pragma once 6 7#include <fbl/intrusive_double_list.h> 8#include <lib/sync/completion.h> 9#include <zircon/thread_annotations.h> 10 11#include <intel-hda/utils/intel-audio-dsp-ipc.h> 12 13#include "debug-logging.h" 14 15namespace audio { 16namespace intel_hda { 17 18class IntelAudioDsp; 19 20class IntelDspIpc { 21public: 22 IntelDspIpc(IntelAudioDsp& dsp); 23 24 const char* log_prefix() const { return log_prefix_; } 25 26 class Txn : public fbl::DoublyLinkedListable<Txn*> { 27 public: 28 Txn(const void* tx, size_t txs, void* rx, size_t rxs) 29 : tx_data(tx), tx_size(txs), rx_data(rx), rx_size(rxs) { } 30 Txn(uint32_t pri, uint32_t ext, const void* tx, size_t txs, void* rx, size_t rxs) 31 : request(pri, ext), tx_data(tx), tx_size(txs), rx_data(rx), rx_size(rxs) { } 32 33 DISALLOW_NEW; 34 35 bool success() { 36 return done && reply.status() == MsgStatus::IPC_SUCCESS; 37 } 38 39 IpcMessage request; 40 IpcMessage reply; 41 42 bool done = false; 43 44 const void* tx_data = nullptr; 45 size_t tx_size = 0; 46 void* rx_data = nullptr; 47 size_t rx_size = 0; 48 size_t rx_actual = 0; 49 50 sync_completion_t completion; 51 }; 52 53 void SetLogPrefix(const char* new_prefix); 54 55 zx_status_t WaitForFirmwareReady(zx_duration_t timeout) { 56 return sync_completion_wait(&fw_ready_completion_, timeout); 57 } 58 void Shutdown(); 59 60 // Library & Module Management IPC 61 zx_status_t InitInstance(uint16_t module_id, uint8_t instance_id, ProcDomain proc_domain, 62 uint8_t core_id, uint8_t ppl_instance_id, uint16_t param_block_size, 63 const void* param_data); 64 zx_status_t LargeConfigGet(Txn* txn, uint16_t module_id, uint8_t instance_id, 65 uint8_t large_param_id, uint32_t data_off_size); 66 zx_status_t Bind(uint16_t src_module_id, uint8_t src_instance_id, uint8_t src_queue, 67 uint16_t dst_module_id, uint8_t dst_instance_id, uint8_t dst_queue); 68 69 // Pipeline Management IPC 70 zx_status_t CreatePipeline(uint8_t instance_id, uint8_t ppl_priority, 71 uint16_t ppl_mem_size, bool lp); 72 zx_status_t SetPipelineState(uint8_t ppl_id, PipelineState state, bool sync_stop_start); 73 74 // Process responses from DSP 75 void ProcessIpc(const IpcMessage& message); 76 void ProcessIpcNotification(const IpcMessage& reply); 77 void ProcessIpcReply(const IpcMessage& reply); 78 void ProcessLargeConfigGetReply(Txn* txn); 79 80private: 81 // Send an IPC message and wait for response 82 zx_status_t SendIpcWait(Txn* txn); 83 84 void SendIpc(const Txn& txn); 85 86 zx_status_t dsp_to_zx_status(MsgStatus status) { 87 return (status == MsgStatus::IPC_SUCCESS) ? ZX_OK : ZX_ERR_INTERNAL; 88 } 89 90 // Log prefix storage 91 char log_prefix_[LOG_PREFIX_STORAGE] = { 0 }; 92 93 // Pending IPC 94 fbl::Mutex ipc_lock_; 95 fbl::DoublyLinkedList<Txn*> ipc_queue_ TA_GUARDED(ipc_lock_); 96 97 // A reference to the owning DSP 98 IntelAudioDsp& dsp_; 99 100 // Used to wait for firmware ready 101 sync_completion_t fw_ready_completion_; 102}; 103 104} // namespace intel_hda 105} // namespace audio 106