// Copyright 2018 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 "nhlt.h"

#include <inttypes.h>
#include <limits.h>
#include <zircon/process.h>

#include <ddk/debug.h>
#include <ddk/device.h>

#include "errors.h"

/**
 * Reference:
 *
 * Intel Smart Sound Technology Audio DSP Non-HD Audio ACPI High Level Design
 * Architecture Guide/Overview
 * Revision 0.7
 * November 2015
 *
 * 561555_SST Non-HD Audio ACPI HLD v0 7_DRAFT.pdf
 */

static const uint8_t NHLT_UUID[] = {
    /* 0000 */ 0x6E, 0x88, 0x9F, 0xA6, 0xEB, 0x6C, 0x94, 0x45,
    /* 0008 */ 0xA4, 0x1F, 0x7B, 0x5D, 0xCE, 0x24, 0xC5, 0x53};

zx_status_t nhlt_publish_metadata(zx_device_t* dev, uint8_t bbn, uint64_t adr, ACPI_HANDLE object) {
  zx_status_t status = ZX_OK;

  // parameters
  ACPI_OBJECT objs[] = {
      {
          // uuid
          .Buffer.Type = ACPI_TYPE_BUFFER,
          .Buffer.Length = sizeof(NHLT_UUID),
          .Buffer.Pointer = (void*)NHLT_UUID,
      },
      {
          // revision id
          .Integer.Type = ACPI_TYPE_INTEGER,
          .Integer.Value = 1,
      },
      {
          // function id
          .Integer.Type = ACPI_TYPE_INTEGER,
          .Integer.Value = 1,
      },
  };
  ACPI_OBJECT_LIST params = {
      .Count = countof(objs),
      .Pointer = objs,
  };

  // output buffer
  ACPI_BUFFER out = {
      .Length = ACPI_ALLOCATE_BUFFER,
      .Pointer = NULL,
  };

  // Fetch the NHLT resource
  ACPI_STATUS acpi_status = AcpiEvaluateObject(object, (char*)"_DSM", &params, &out);
  if (acpi_status != AE_OK) {
    zxlogf(ERROR, "acpi: failed to fetch NHLT blob (acpi_status 0x%x)\n", acpi_status);
    return acpi_to_zx_status(acpi_status);
  }

  ACPI_OBJECT* out_obj = out.Pointer;
  if (out_obj->Type != ACPI_TYPE_BUFFER) {
    zxlogf(ERROR, "acpi: unexpected object type (%u) for NHLT blob\n", out_obj->Type);
    status = ZX_ERR_INTERNAL;
    goto out;
  }

  ACPI_RESOURCE* res = NULL;
  acpi_status = AcpiBufferToResource(out_obj->Buffer.Pointer, out_obj->Buffer.Length, &res);
  if (acpi_status != AE_OK) {
    zxlogf(ERROR, "acpi: failed to parse NHLT resource (acpi_status 0x%x)\n", acpi_status);
    status = acpi_to_zx_status(acpi_status);
    goto out;
  }

  if (res->Type != ACPI_RESOURCE_TYPE_ADDRESS64) {
    zxlogf(ERROR, "acpi: unexpected NHLT resource type (%u)\n", res->Type);
    status = ZX_ERR_INTERNAL;
    goto out;
  }

  zx_paddr_t paddr = (zx_paddr_t)res->Data.Address64.Address.Minimum;
  size_t size = (size_t)res->Data.Address64.Address.AddressLength;

  // Read the blob
  zx_handle_t vmo;
  zx_paddr_t page_start = ROUNDDOWN(paddr, PAGE_SIZE);
  size_t page_offset = (paddr & (PAGE_SIZE - 1));
  size_t page_size = ROUNDUP(page_offset + size, PAGE_SIZE);
  // Please do not use get_root_resource() in new code. See ZX-1467.
  status = zx_vmo_create_physical(get_root_resource(), page_start, page_size, &vmo);
  if (status != ZX_OK) {
    zxlogf(ERROR, "acpi: failed to create NHLT VMO (res %d)\n", status);
    goto out;
  }

  // We cannot read physical VMOs directly and must map it
  zx_vaddr_t vaddr = 0;
  status = zx_vmar_map(zx_vmar_root_self(), ZX_VM_PERM_READ, 0, vmo, 0, page_size, &vaddr);
  if (status != ZX_OK) {
    zxlogf(ERROR, "acpi: failed to map NHLT blob (res %d)\n", status);
    goto out;
  }
  void* nhlt = (void*)(vaddr + page_offset);

  // Publish the NHLT as metadata on the future PCI device node...
  // The canonical path to the PCI device is /dev/sys/pci/<b:d.f>
  char path[PATH_MAX];
  snprintf(path, sizeof(path), "/dev/sys/pci/%02x:%02x.%01x", bbn, (unsigned)((adr >> 16) & 0xFFFF),
           (unsigned)(adr & 0xFFFF));
  status = device_publish_metadata(dev, path, *(uint32_t*)"NHLT", nhlt, size);
  if (status != ZX_OK) {
    zxlogf(ERROR, "acpi: failed to publish NHLT metadata (res %d)\n", status);
  }

  zxlogf(TRACE, "acpi: published NHLT metadata for device at %s\n", path);

  zx_vmar_unmap(zx_vmar_root_self(), vaddr, ROUNDUP(size, PAGE_SIZE));
out:
  ACPI_FREE(out.Pointer);
  return status;
}
