blob: 90047f4a0f78e96662e7ea9060b226c5b199f4be [file] [log] [blame]
// Copyright 2019 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/binding.h>
#include <ddk/debug.h>
#include <ddk/device.h>
#include <ddk/metadata.h>
#include <ddk/platform-defs.h>
#include <ddk/protocol/gpio.h>
#include <ddktl/metadata/audio.h>
#include <fbl/algorithm.h>
#include <limits.h>
#include <soc/as370/as370-clk.h>
#include <soc/as370/as370-gpio.h>
#include <soc/as370/as370-hw.h>
#include <soc/as370/as370-i2c.h>
#include "as370.h"
namespace board_as370 {
constexpr zx_bind_inst_t root_match[] = {
BI_MATCH(),
};
static const zx_bind_inst_t ref_out_i2c_match[] = {
BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_I2C),
BI_ABORT_IF(NE, BIND_I2C_BUS_ID, 0),
BI_MATCH_IF(EQ, BIND_I2C_ADDRESS, 0x31),
};
static const zx_bind_inst_t ref_out_codec_match[] = {
BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_CODEC),
BI_ABORT_IF(NE, BIND_PLATFORM_DEV_VID, PDEV_VID_MAXIM),
BI_MATCH_IF(EQ, BIND_PLATFORM_DEV_DID, PDEV_DID_MAXIM_MAX98373),
};
static const zx_bind_inst_t ref_out_clk_match[] = {
BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_CLOCK),
BI_MATCH_IF(EQ, BIND_CLOCK_ID, as370::As370Clk::kClkAvpll0),
};
static const device_component_part_t ref_out_i2c_component[] = {
{fbl::count_of(root_match), root_match},
{fbl::count_of(ref_out_i2c_match), ref_out_i2c_match},
};
static const device_component_part_t ref_out_codec_component[] = {
{fbl::count_of(root_match), root_match},
{fbl::count_of(ref_out_codec_match), ref_out_codec_match},
};
static const zx_bind_inst_t ref_out_enable_gpio_match[] = {
BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_GPIO),
BI_MATCH_IF(EQ, BIND_GPIO_PIN, 17),
};
static const device_component_part_t ref_out_enable_gpio_component[] = {
{countof(root_match), root_match},
{countof(ref_out_enable_gpio_match), ref_out_enable_gpio_match},
};
static const device_component_part_t ref_out_clk_component[] = {
{countof(root_match), root_match},
{countof(ref_out_clk_match), ref_out_clk_match},
};
static const device_component_t codec_components[] = {
{countof(ref_out_i2c_component), ref_out_i2c_component},
{countof(ref_out_enable_gpio_component), ref_out_enable_gpio_component},
};
static const device_component_t controller_components[] = {
{countof(ref_out_codec_component), ref_out_codec_component},
{countof(ref_out_clk_component), ref_out_clk_component},
};
zx_status_t As370::AudioInit() {
constexpr pbus_mmio_t mmios[] = {
{
.base = as370::kGlobalBase,
.length = as370::kGlobalSize,
},
{
.base = as370::kAudioDhubBase,
.length = as370::kAudioDhubSize,
},
{
.base = as370::kAudioGlobalBase,
.length = as370::kAudioGlobalSize,
},
{
.base = as370::kAudioI2sBase,
.length = as370::kAudioI2sSize,
}};
pbus_dev_t controller_out = {};
controller_out.name = "as370-audio-out";
controller_out.vid = PDEV_VID_SYNAPTICS;
controller_out.pid = PDEV_PID_SYNAPTICS_AS370;
controller_out.did = PDEV_DID_AS370_AUDIO_OUT;
controller_out.mmio_list = mmios;
controller_out.mmio_count = countof(mmios);
// Output pin assignments.
// AMP_EN.
gpio_impl_.SetAltFunction(17, 0); // mode 0 to set as GPIO.
gpio_impl_.ConfigOut(17, 0);
gpio_impl_.SetAltFunction(6, 1); // mode 1 to set as I2S1_MCLK.
gpio_impl_.SetAltFunction(0, 1); // mode 1 to set as I2S1_BCLKIO (TDM_BCLK).
gpio_impl_.SetAltFunction(1, 1); // mode 1 to set as I2S1_LRLKIO (TDM_FSYNC).
gpio_impl_.SetAltFunction(2, 1); // mode 1 to set as I2S1_DO[0] (TDM_MOSI).
// Output devices.
constexpr zx_device_prop_t props[] = {
{BIND_PLATFORM_DEV_VID, 0, PDEV_VID_MAXIM},
{BIND_PLATFORM_DEV_DID, 0, PDEV_DID_MAXIM_MAX98373}};
auto status = DdkAddComposite("audio-max98373", props, countof(props), codec_components,
countof(codec_components), UINT32_MAX);
if (status != ZX_OK) {
zxlogf(ERROR, "%s: DdkAddComposite failed %d\n", __FUNCTION__, status);
return status;
}
status = pbus_.CompositeDeviceAdd(&controller_out, controller_components,
countof(controller_components), UINT32_MAX);
if (status != ZX_OK) {
zxlogf(ERROR, "%s: CompositeDeviceAdd failed %d\n", __FUNCTION__, status);
return status;
}
return ZX_OK;
}
} // namespace board_as370