blob: 8df664285ea5e34d443e56ac6224facbbce1d0d9 [file] [log] [blame]
// 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 <ddk/debug.h>
#include <ddk/device.h>
#include <ddk/protocol/platform-device-lib.h>
#include <zircon/assert.h>
#include <zircon/types.h>
#include <hw/reg.h>
#include "a113-audio-device.h"
#define REGDUMPEEAUDIO(regval) \
zxlogf(INFO, #regval " = 0x%08x\n", \
a113_ee_audio_read(audio_device, regval));
#define REGDUMPPDM(regval) \
zxlogf(INFO, #regval " = 0x%08x\n", \
a113_ee_audio_read(audio_device, regval));
void a113_pdm_dump_registers(a113_audio_device_t* audio_device) {
REGDUMPPDM(PDM_CTRL)
REGDUMPPDM(PDM_HCIC_CTRL1)
REGDUMPPDM(PDM_HCIC_CTRL2)
REGDUMPPDM(PDM_F1_CTRL)
REGDUMPPDM(PDM_F2_CTRL)
REGDUMPPDM(PDM_F3_CTRL)
REGDUMPPDM(PDM_HPF_CTRL)
REGDUMPPDM(PDM_CHAN_CTRL)
REGDUMPPDM(PDM_CHAN_CTRL1)
REGDUMPPDM(PDM_COEFF_ADDR)
REGDUMPPDM(PDM_COEFF_DATA)
REGDUMPPDM(PDM_CLKG_CTRL)
REGDUMPPDM(PDM_STS)
REGDUMPEEAUDIO(EE_AUDIO_CLK_GATE_EN)
REGDUMPEEAUDIO(EE_AUDIO_CLK_PDMIN_CTRL0)
REGDUMPEEAUDIO(EE_AUDIO_CLK_PDMIN_CTRL1)
REGDUMPEEAUDIO(EE_AUDIO_TODDR_B_CTRL0)
REGDUMPEEAUDIO(EE_AUDIO_TODDR_B_CTRL1)
REGDUMPEEAUDIO(EE_AUDIO_TODDR_B_START_ADDR)
REGDUMPEEAUDIO(EE_AUDIO_TODDR_B_FINISH_ADDR)
REGDUMPEEAUDIO(EE_AUDIO_TODDR_B_INT_ADDR)
REGDUMPEEAUDIO(EE_AUDIO_TODDR_B_STATUS1)
REGDUMPEEAUDIO(EE_AUDIO_TODDR_B_STATUS2)
REGDUMPEEAUDIO(EE_AUDIO_TODDR_B_START_ADDRB)
REGDUMPEEAUDIO(EE_AUDIO_TODDR_B_FINISH_ADDRB)
}
uint32_t a113_pdm_read(a113_audio_device_t* audio_device, uint32_t reg) {
return readl((uint32_t*)audio_device->pdm_mmio.vaddr + reg);
}
void a113_pdm_write(a113_audio_device_t* audio_device, uint32_t reg, uint32_t value) {
return writel(value, (uint32_t*)audio_device->pdm_mmio.vaddr + reg);
}
void a113_pdm_update_bits(a113_audio_device_t* audio_device, uint32_t reg,
uint32_t mask, uint32_t value) {
uint32_t register_value = a113_pdm_read(audio_device, reg);
register_value &= ~mask;
register_value |= value & mask;
a113_pdm_write(audio_device, reg, register_value);
}
uint32_t a113_ee_audio_read(a113_audio_device_t* audio_device, uint32_t reg) {
return readl((uint32_t*)audio_device->ee_audio_mmio.vaddr + reg);
}
void a113_ee_audio_write(a113_audio_device_t* audio_device, uint32_t reg, uint32_t value) {
return writel(value, (uint32_t*)audio_device->ee_audio_mmio.vaddr + reg);
}
void a113_ee_audio_update_bits(a113_audio_device_t* audio_device, uint32_t reg,
uint32_t mask, uint32_t value) {
uint32_t register_value = a113_ee_audio_read(audio_device, reg);
register_value &= ~mask;
register_value |= value & mask;
a113_ee_audio_write(audio_device, reg, register_value);
}
// Map registers to our address space for future access, and do some very basic
// hardware initialization such as setting clocks.
zx_status_t a113_audio_device_init(a113_audio_device_t* audio_device,
zx_device_t* parent) {
ZX_DEBUG_ASSERT(audio_device);
ZX_DEBUG_ASSERT(parent);
zx_status_t status = device_get_protocol(parent, ZX_PROTOCOL_PDEV,
&audio_device->pdev);
if (status != ZX_OK) {
goto init_fail;
}
// Map EE_AUDIO registers to our address space.
status = pdev_map_mmio_buffer(&audio_device->pdev, 0 /* EE_AUDIO */,
ZX_CACHE_POLICY_UNCACHED_DEVICE,
&audio_device->ee_audio_mmio);
if (status != ZX_OK) {
zxlogf(ERROR, "a113_audio_device_init: pdev_map_mmio_buffer failed\n");
goto init_fail;
}
// Set clocks. This is done before mapping the PDM registers to our address
// space. The PDM register is not accessible before the pdm_sysclk is
// running.
a113_ee_audio_write(audio_device, EE_AUDIO_CLK_PDMIN_CTRL0,
(1 << 31) | (2 << 24) | 79);
a113_ee_audio_write(audio_device, EE_AUDIO_CLK_PDMIN_CTRL1,
(1 << 31) | (2 << 24) | 0);
a113_ee_audio_write(audio_device, EE_AUDIO_CLK_GATE_EN, 0x000fffff);
// Map the PDM registers to our address space.
status = pdev_map_mmio_buffer(&audio_device->pdev, 1 /* PDM */,
ZX_CACHE_POLICY_UNCACHED_DEVICE,
&audio_device->pdm_mmio);
if (status != ZX_OK) {
zxlogf(ERROR, "a113_audio_device_init: pdev_map_mmio_buffer failed\n");
goto init_fail;
}
return ZX_OK;
init_fail:
if (audio_device) {
mmio_buffer_release(&audio_device->ee_audio_mmio);
mmio_buffer_release(&audio_device->pdm_mmio);
};
return status;
}