text: // Copyright 2017 The Fuchsia Authors. All rights reserved.
  // Use of this source code is governed by a BSD-style license that can be
  // found in the LICENSE file.
  
  #include "a113-pdm.h"
  
  #include <ddk/debug.h>
  #include <unistd.h>
  
  // Filter configuration
  static const int lpf1[] = {
      0x000014, 0xffffb2, 0xfffed9, 0xfffdce, 0xfffd45, 0xfffe32, 0x000147,
      0x000645, 0x000b86, 0x000e21, 0x000ae3, 0x000000, 0xffeece, 0xffdca8,
      0xffd212, 0xffd7d1, 0xfff2a7, 0x001f4c, 0x0050c2, 0x0072aa, 0x006ff1,
      0x003c32, 0xffdc4e, 0xff6a18, 0xff0fef, 0xfefbaf, 0xff4c40, 0x000000,
      0x00ebc8, 0x01c077, 0x02209e, 0x01c1a4, 0x008e60, 0xfebe52, 0xfcd690,
      0xfb8fa5, 0xfba498, 0xfd9812, 0x0181ce, 0x06f5f3, 0x0d112f, 0x12a958,
      0x169686, 0x18000e, 0x169686, 0x12a958, 0x0d112f, 0x06f5f3, 0x0181ce,
      0xfd9812, 0xfba498, 0xfb8fa5, 0xfcd690, 0xfebe52, 0x008e60, 0x01c1a4,
      0x02209e, 0x01c077, 0x00ebc8, 0x000000, 0xff4c40, 0xfefbaf, 0xff0fef,
      0xff6a18, 0xffdc4e, 0x003c32, 0x006ff1, 0x0072aa, 0x0050c2, 0x001f4c,
      0xfff2a7, 0xffd7d1, 0xffd212, 0xffdca8, 0xffeece, 0x000000, 0x000ae3,
      0x000e21, 0x000b86, 0x000645, 0x000147, 0xfffe32, 0xfffd45, 0xfffdce,
      0xfffed9, 0xffffb2, 0x000014,
  };
  
  static const int lpf3[] = {
      0x000000, 0x000081, 0x000000, 0xfffedb, 0x000000, 0x00022d, 0x000000,
      0xfffc46, 0x000000, 0x0005f7, 0x000000, 0xfff6eb, 0x000000, 0x000d4e,
      0x000000, 0xffed1e, 0x000000, 0x001a1c, 0x000000, 0xffdcb0, 0x000000,
      0x002ede, 0x000000, 0xffc2d1, 0x000000, 0x004ebe, 0x000000, 0xff9beb,
      0x000000, 0x007dd7, 0x000000, 0xff633a, 0x000000, 0x00c1d2, 0x000000,
      0xff11d5, 0x000000, 0x012368, 0x000000, 0xfe9c45, 0x000000, 0x01b252,
      0x000000, 0xfdebf6, 0x000000, 0x0290b8, 0x000000, 0xfcca0d, 0x000000,
      0x041d7c, 0x000000, 0xfa8152, 0x000000, 0x07e9c6, 0x000000, 0xf28fb5,
      0x000000, 0x28b216, 0x3fffde, 0x28b216, 0x000000, 0xf28fb5, 0x000000,
      0x07e9c6, 0x000000, 0xfa8152, 0x000000, 0x041d7c, 0x000000, 0xfcca0d,
      0x000000, 0x0290b8, 0x000000, 0xfdebf6, 0x000000, 0x01b252, 0x000000,
      0xfe9c45, 0x000000, 0x012368, 0x000000, 0xff11d5, 0x000000, 0x00c1d2,
      0x000000, 0xff633a, 0x000000, 0x007dd7, 0x000000, 0xff9beb, 0x000000,
      0x004ebe, 0x000000, 0xffc2d1, 0x000000, 0x002ede, 0x000000, 0xffdcb0,
      0x000000, 0x001a1c, 0x000000, 0xffed1e, 0x000000, 0x000d4e, 0x000000,
      0xfff6eb, 0x000000, 0x0005f7, 0x000000, 0xfffc46, 0x000000, 0x00022d,
      0x000000, 0xfffedb, 0x000000, 0x000081, 0x000000,
  };
  
  static const int lpf2[] = {
      0x00050a, 0xfff004, 0x0002c1, 0x003c12, 0xffa818, 0xffc87d, 0x010aef,
      0xff5223, 0xfebd93, 0x028f41, 0xff5c0e, 0xfc63f8, 0x055f81, 0x000000,
      0xf478a0, 0x11c5e3, 0x2ea74d, 0x11c5e3, 0xf478a0, 0x000000, 0x055f81,
      0xfc63f8, 0xff5c0e, 0x028f41, 0xfebd93, 0xff5223, 0x010aef, 0xffc87d,
      0xffa818, 0x003c12, 0x0002c1, 0xfff004, 0x00050a,
  };
  
  void a113_pdm_enable(a113_audio_device_t* audio_device, int is_enable) {
      if (is_enable) {
          a113_pdm_update_bits(audio_device, PDM_CTRL, 1 << 31, is_enable << 31);
      } else {
          a113_pdm_update_bits(audio_device, PDM_CTRL, 1 << 31 | 1 << 16,
                               0 << 31 | 0 << 16);
          // Amlogic recommend a sleep after pdm_disable. Not sure why yet. In
          // our code structure the sleep doesn't actually do anything since all
          // the code is async. Disable it for now, and revisit if we actually
          // end up seeing issues here.
          // zx_nanosleep(1);
      }
  }
  
  void a113_pdm_fifo_reset(a113_audio_device_t* audio_device) {
      // Toggle this bit for fifo reset.
      a113_pdm_update_bits(audio_device, PDM_CTRL, 1 << 16, 0 << 16);
      a113_pdm_update_bits(audio_device, PDM_CTRL, 1 << 16, 1 << 16);
  }
  
  void a113_pdm_ctrl(a113_audio_device_t* audio_device, int bitdepth) {
      a113_pdm_write(audio_device, PDM_CLKG_CTRL, 1);
  
      uint32_t mode = bitdepth == 32 ? 0 : 1;
      a113_pdm_update_bits(
          audio_device, PDM_CTRL, (0x7 << 28 | 0xff << 8 | 0xff << 0),
          (0 << 30) | (mode << 29) | (0 << 28) | (0xff << 8) | (0xff << 0));
  
      a113_pdm_write(audio_device, PDM_CHAN_CTRL,
                     ((28 << 24) | (28 << 16) | (28 << 8) | (28 << 0)));
      a113_pdm_write(audio_device, PDM_CHAN_CTRL1,
                     ((28 << 24) | (28 << 16) | (28 << 8) | (28 << 0)));
  }
  
  void a113_pdm_arb_config(a113_audio_device_t* aml_tdm_dev) {
      a113_ee_audio_write(aml_tdm_dev, EE_AUDIO_ARB_CTRL, 1 << 31 | 0xff << 0);
  }
  
  static void a113_pdm_filters_config(a113_audio_device_t* audio_device,
                                      int lpf1_len, int lpf2_len, int lpf3_len) {}
  
  static void a113_pdm_LPF_coeff(a113_audio_device_t* audio_device, int lpf1_len,
                                 const int* lpf1_coeff, int lpf2_len,
                                 const int* lpf2_coeff, int lpf3_len,
                                 const int* lpf3_coeff) {}
  
  void a113_pdm_filter_ctrl(a113_audio_device_t* audio_device) {
  
      a113_pdm_write(
          audio_device, PDM_HCIC_CTRL1,
          (0x80000000 | 0x7 | (0x8 << 4) | (0x80 << 16) | (0x11 << 24)));
  
      a113_pdm_write(audio_device, PDM_F1_CTRL,
                     (0x80000000 | 87 | (2 << 12) | (1 << 16)));
      a113_pdm_write(audio_device, PDM_F2_CTRL,
                     (0x80000000 | 33 | (2 << 12) | (0 << 16)));
      a113_pdm_write(audio_device, PDM_F3_CTRL,
                     (0x80000000 | 117 | (2 << 12) | (1 << 16)));
  
      a113_pdm_write(audio_device, PDM_HPF_CTRL,
                     (0x8000 | (0x7 << 16) | (1 << 31)));
  
      a113_pdm_write(audio_device, PDM_COEFF_ADDR, 0);
  
      for (int i = 0; i < 87; i++)
          a113_pdm_write(audio_device, PDM_COEFF_DATA, lpf1[i]);
      for (int i = 0; i < 33; i++)
          a113_pdm_write(audio_device, PDM_COEFF_DATA, lpf2[i]);
      for (int i = 0; i < 117; i++)
          a113_pdm_write(audio_device, PDM_COEFF_DATA, lpf3[i]);
  
      a113_pdm_write(audio_device, PDM_COEFF_ADDR, 0);
  }
  