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 <assert.h> 8#include <ddktl/mmio.h> 9#include <fbl/unique_ptr.h> 10#include <soc/aml-common/aml-audio-regs.h> 11/* 12 Presently assumes stereo input with both streams multiplexed on the same 13 PDM input line. (TODO: support up to 8 channels to refactor gauss to use this) 14*/ 15 16class AmlPdmDevice { 17 18public: 19 DISALLOW_COPY_ASSIGN_AND_MOVE(AmlPdmDevice); 20 21 static fbl::unique_ptr<AmlPdmDevice> Create(ddk::MmioBuffer pdm_mmio, 22 ddk::MmioBuffer audio_mmio, 23 ee_audio_mclk_src_t pdm_clk_src, 24 uint32_t sclk_div, 25 uint32_t dclk_div, 26 aml_toddr_t toddr_dev); 27 28 // Sets the buffer/length pointers for dma engine 29 // must resize in lower 32-bits of address space 30 zx_status_t SetBuffer(zx_paddr_t buf, size_t len); 31 32 /* 33 Returns offset of dma pointer in the ring buffer 34 */ 35 uint32_t GetRingPosition(); 36 37 /* 38 Resets state of dma mechanisms and starts clocking data 39 in from pdm bus with data written to start of ring buffer 40 */ 41 uint64_t Start(); 42 43 /* 44 Stops clocking stat in off PDM bus 45 (physical pdm bus signals remain active) 46 */ 47 void Stop(); 48 49 /* 50 Synchronize the state of PDM bus signals with fifo/dma engine 51 */ 52 void Sync(); 53 54 /* 55 shuts down toddr, stops writing data to ring buffer 56 */ 57 void Shutdown(); 58 59 uint32_t fifo_depth() const { return fifo_depth_; }; 60 61private: 62 friend class fbl::unique_ptr<AmlPdmDevice>; 63 64 AmlPdmDevice(ddk::MmioBuffer pdm_mmio, ddk::MmioBuffer audio_mmio, 65 ee_audio_mclk_src_t clk_src, uint32_t sysclk_div, uint32_t dclk_div, 66 aml_toddr_t toddr, uint32_t fifo_depth) 67 : fifo_depth_(fifo_depth), 68 toddr_ch_(toddr), 69 clk_src_(clk_src), 70 sysclk_div_(sysclk_div), 71 dclk_div_(dclk_div), 72 toddr_base_(GetToddrBase(toddr)), 73 pdm_mmio_(fbl::move(pdm_mmio)), 74 audio_mmio_(fbl::move(audio_mmio)){}; 75 76 ~AmlPdmDevice() = default; 77 78 void ConfigFilters(); 79 80 /* Get the resgister block offset for our ddr block */ 81 static zx_off_t GetToddrBase(aml_toddr_t ch) { 82 switch (ch) { 83 case TODDR_A: 84 return EE_AUDIO_TODDR_A_CTRL0; 85 case TODDR_B: 86 return EE_AUDIO_TODDR_B_CTRL0; 87 case TODDR_C: 88 return EE_AUDIO_TODDR_C_CTRL0; 89 } 90 //We should never get here, but if we do, make it hard to ignore 91 ZX_PANIC("Invalid toddr channel specified!\n"); 92 return 0; 93 } 94 95 void AudioClkEna(uint32_t audio_blk_mask); 96 void AudioClkDis(uint32_t audio_blk_mask); 97 void InitRegs(); 98 void TODDREnable(); 99 void TODDRDisable(); 100 void PdmInDisable(); 101 void PdmInEnable(); 102 103 /* Get the resgister block offset for our ddr block */ 104 zx_off_t GetToddrOffset(zx_off_t off) { 105 return toddr_base_ + off; 106 } 107 const uint32_t fifo_depth_; 108 const aml_toddr_t toddr_ch_; // fromddr channel used by this instance 109 const ee_audio_mclk_src_t clk_src_; 110 const uint32_t sysclk_div_; 111 const uint32_t dclk_div_; 112 const zx_off_t toddr_base_; // base offset of frddr ch used by this instance 113 const ddk::MmioBuffer pdm_mmio_; 114 const ddk::MmioBuffer audio_mmio_; 115}; 116