[dev][astro-tdm-output] Convert to composite device driver
astro-tdm-output now uses composite protocol to access I2C and GPIOs.
TEST: "audio record" and "audio play" on astro
Change-Id: I92f8c387f9806ba29f26929b1fc13d39f8b0c5ee
diff --git a/zircon/system/dev/audio/astro-tdm-output/BUILD.gn b/zircon/system/dev/audio/astro-tdm-output/BUILD.gn
index 99bd4c4..a20f016 100644
--- a/zircon/system/dev/audio/astro-tdm-output/BUILD.gn
+++ b/zircon/system/dev/audio/astro-tdm-output/BUILD.gn
@@ -5,11 +5,10 @@
driver("astro-tdm-output") {
sources = [
"audio-stream-out.cpp",
- "binding.c",
"tas27xx.cpp",
]
deps = [
- "$zx/system/banjo/ddk-protocol-clock",
+ "$zx/system/banjo/ddk-protocol-composite",
"$zx/system/banjo/ddk-protocol-gpio",
"$zx/system/banjo/ddk-protocol-i2c",
"$zx/system/banjo/ddk-protocol-platform-device",
diff --git a/zircon/system/dev/audio/astro-tdm-output/audio-stream-out.cpp b/zircon/system/dev/audio/astro-tdm-output/audio-stream-out.cpp
index e4450fb..56216f8 100644
--- a/zircon/system/dev/audio/astro-tdm-output/audio-stream-out.cpp
+++ b/zircon/system/dev/audio/astro-tdm-output/audio-stream-out.cpp
@@ -3,7 +3,10 @@
// found in the LICENSE file.
#include "audio-stream-out.h"
+#include <ddk/binding.h>
#include <ddk/debug.h>
+#include <ddk/platform-defs.h>
+#include <ddk/protocol/composite.h>
#include <math.h>
#include <optional>
@@ -12,27 +15,52 @@
namespace audio {
namespace astro {
+enum {
+ COMPONENT_PDEV,
+ COMPONENT_I2C,
+ COMPONENT_FAULT_GPIO,
+ COMPONENT_ENABLE_GPIO,
+ COMPONENT_COUNT,
+};
+
// Calculate ring buffer size for 1 second of 16-bit, 48kHz, stereo.
constexpr size_t RB_SIZE = fbl::round_up<size_t, size_t>(48000 * 2 * 2u, PAGE_SIZE);
AstroAudioStreamOut::AstroAudioStreamOut(zx_device_t* parent)
- : SimpleAudioStream(parent, false), pdev_(parent) {
+ : SimpleAudioStream(parent, false) {
}
zx_status_t AstroAudioStreamOut::InitPDev() {
+ composite_protocol_t composite;
+
+ auto status = device_get_protocol(parent(), ZX_PROTOCOL_COMPOSITE, &composite);
+ if (status != ZX_OK) {
+ zxlogf(ERROR, "Could not get composite protocol\n");
+ return status;
+ }
+
+ zx_device_t* components[COMPONENT_COUNT] = {};
+ size_t actual;
+ composite_get_components(&composite, components, countof(components), &actual);
+ if (actual < countof(components)) {
+ zxlogf(ERROR, "could not get components\n");
+ return ZX_ERR_NOT_SUPPORTED;
+ }
+
+ pdev_ = components[COMPONENT_PDEV];
if (!pdev_.is_valid()) {
return ZX_ERR_NO_RESOURCES;
}
- audio_fault_ = pdev_.GetGpio(0);
- audio_en_ = pdev_.GetGpio(1);
+ audio_fault_ = components[COMPONENT_FAULT_GPIO];
+ audio_en_ = components[COMPONENT_ENABLE_GPIO];
if (!audio_fault_.is_valid() || !audio_en_.is_valid()) {
zxlogf(ERROR, "%s failed to allocate gpio\n", __func__);
return ZX_ERR_NO_RESOURCES;
}
- auto i2c = pdev_.GetI2c(0);
+ ddk::I2cChannel i2c = components[COMPONENT_I2C];
if (!i2c.is_valid()) {
zxlogf(ERROR, "%s failed to allocate i2c\n", __func__);
return ZX_ERR_NO_RESOURCES;
@@ -43,7 +71,7 @@
return ZX_ERR_NO_RESOURCES;
}
- zx_status_t status = pdev_.GetBti(0, &bti_);
+ status = pdev_.GetBti(0, &bti_);
if (status != ZX_OK) {
zxlogf(ERROR, "%s could not obtain bti - %d\n", __func__, status);
return status;
@@ -277,11 +305,7 @@
return ZX_OK;
}
-} //astro
-} //audio
-
-extern "C" zx_status_t audio_bind(void* ctx, zx_device_t* device, void** cookie) {
-
+static zx_status_t audio_bind(void* ctx, zx_device_t* device) {
auto stream =
audio::SimpleAudioStream::Create<audio::astro::AstroAudioStreamOut>(device);
if (stream == nullptr) {
@@ -292,3 +316,23 @@
return ZX_OK;
}
+
+static zx_driver_ops_t driver_ops = [](){
+ zx_driver_ops_t ops = {};
+ ops.version = DRIVER_OPS_VERSION;
+ ops.bind = audio_bind;
+ return ops;
+}();
+
+} //astro
+} //audio
+
+
+// clang-format off
+ZIRCON_DRIVER_BEGIN(aml_tdm, audio::astro::driver_ops, "aml-tdm-out", "0.1", 4)
+ BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_COMPOSITE),
+ BI_ABORT_IF(NE, BIND_PLATFORM_DEV_VID, PDEV_VID_AMLOGIC),
+ BI_ABORT_IF(NE, BIND_PLATFORM_DEV_PID, PDEV_PID_AMLOGIC_S905D2),
+ BI_MATCH_IF(EQ, BIND_PLATFORM_DEV_DID, PDEV_DID_AMLOGIC_TDM),
+ZIRCON_DRIVER_END(aml_tdm)
+// clang-format on
diff --git a/zircon/system/dev/audio/astro-tdm-output/binding.c b/zircon/system/dev/audio/astro-tdm-output/binding.c
deleted file mode 100644
index 4519cbe..0000000
--- a/zircon/system/dev/audio/astro-tdm-output/binding.c
+++ /dev/null
@@ -1,22 +0,0 @@
-// 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 <ddk/binding.h>
-#include <ddk/driver.h>
-#include <ddk/platform-defs.h>
-
-extern zx_status_t audio_bind(void* ctx, zx_device_t* parent);
-
-static zx_driver_ops_t aml_tdm_driver_ops = {
- .version = DRIVER_OPS_VERSION,
- .bind = audio_bind,
-};
-
-// clang-format off
-ZIRCON_DRIVER_BEGIN(aml_tdm, aml_tdm_driver_ops, "aml-tdm-out", "0.1", 3)
- BI_ABORT_IF(NE, BIND_PLATFORM_DEV_VID, PDEV_VID_AMLOGIC),
- BI_ABORT_IF(NE, BIND_PLATFORM_DEV_PID, PDEV_PID_AMLOGIC_S905D2),
- BI_MATCH_IF(EQ, BIND_PLATFORM_DEV_DID, PDEV_DID_AMLOGIC_TDM),
-ZIRCON_DRIVER_END(aml_tdm)
- // clang-format on
diff --git a/zircon/system/dev/board/astro/astro-audio.c b/zircon/system/dev/board/astro/astro-audio.c
index f6a4ee3..8c60699 100644
--- a/zircon/system/dev/board/astro/astro-audio.c
+++ b/zircon/system/dev/board/astro/astro-audio.c
@@ -2,6 +2,7 @@
// 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/platform-defs.h>
@@ -12,19 +13,9 @@
#include <limits.h>
#include "astro.h"
+#include "astro-gpios.h"
//clang-format off
-static const pbus_gpio_t audio_gpios[] = {
- {
- // AUDIO_SOC_FAULT_L
- .gpio = S905D2_GPIOA(4),
- },
- {
- // SOC_AUDIO_EN
- .gpio = S905D2_GPIOA(5),
- },
-};
-
static const pbus_mmio_t audio_mmios[] = {
{
@@ -40,28 +31,51 @@
},
};
-static const pbus_i2c_channel_t codec_i2c[] = {
- {
- .bus_id = 2,
- .address = 0x48,
- },
-};
-
static pbus_dev_t aml_tdm_dev = {
.name = "AstroAudio",
.vid = PDEV_VID_AMLOGIC,
.pid = PDEV_PID_AMLOGIC_S905D2,
.did = PDEV_DID_AMLOGIC_TDM,
- .gpio_list = audio_gpios,
- .gpio_count = countof(audio_gpios),
- .i2c_channel_list = codec_i2c,
- .i2c_channel_count = countof(codec_i2c),
.mmio_list = audio_mmios,
.mmio_count = countof(audio_mmios),
.bti_list = tdm_btis,
.bti_count = countof(tdm_btis),
};
+static const zx_bind_inst_t root_match[] = {
+ BI_MATCH(),
+};
+static const zx_bind_inst_t i2c_match[] = {
+ BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_I2C),
+ BI_ABORT_IF(NE, BIND_I2C_BUS_ID, ASTRO_I2C_3),
+ BI_MATCH_IF(EQ, BIND_I2C_ADDRESS, I2C_AUDIO_CODEC_ADDR),
+};
+static const zx_bind_inst_t fault_gpio_match[] = {
+ BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_GPIO),
+ BI_MATCH_IF(EQ, BIND_GPIO_PIN, GPIO_AUDIO_SOC_FAULT_L),
+};
+static const zx_bind_inst_t enable_gpio_match[] = {
+ BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_GPIO),
+ BI_MATCH_IF(EQ, BIND_GPIO_PIN, GPIO_SOC_AUDIO_EN),
+};
+static const device_component_part_t i2c_component[] = {
+ { countof(root_match), root_match },
+ { countof(i2c_match), i2c_match },
+};
+static const device_component_part_t fault_gpio_component[] = {
+ { countof(root_match), root_match },
+ { countof(fault_gpio_match), fault_gpio_match },
+};
+static const device_component_part_t enable_gpio_component[] = {
+ { countof(root_match), root_match },
+ { countof(enable_gpio_match), enable_gpio_match },
+};
+static const device_component_t components[] = {
+ { countof(i2c_component), i2c_component },
+ { countof(fault_gpio_component), fault_gpio_component },
+ { countof(enable_gpio_component), enable_gpio_component },
+};
+
//PDM input configurations
static const pbus_mmio_t pdm_mmios[] = {
{
@@ -125,7 +139,8 @@
gpio_impl_config_out(&bus->gpio, S905D2_GPIOA(5), 1);
- status = pbus_device_add(&bus->pbus, &aml_tdm_dev);
+ status = pbus_composite_device_add(&bus->pbus, &aml_tdm_dev, components, countof(components),
+ UINT32_MAX);
if (status != ZX_OK) {
zxlogf(ERROR, "astro_tdm_init: pbus_device_add failed: %d\n", status);
return status;
diff --git a/zircon/system/dev/board/astro/astro-gpio.c b/zircon/system/dev/board/astro/astro-gpio.c
index 0efa08d..99bd2c2 100644
--- a/zircon/system/dev/board/astro/astro-gpio.c
+++ b/zircon/system/dev/board/astro/astro-gpio.c
@@ -84,6 +84,9 @@
{ GPIO_TOUCH_RESET },
// For light sensor.
{ GPIO_LIGHT_INTERRUPT },
+ // For audio.
+ { GPIO_AUDIO_SOC_FAULT_L },
+ { GPIO_SOC_AUDIO_EN },
};
static const pbus_metadata_t gpio_metadata[] = {
diff --git a/zircon/system/dev/board/astro/astro-gpios.h b/zircon/system/dev/board/astro/astro-gpios.h
index b07bf9e..84ceeb3 100644
--- a/zircon/system/dev/board/astro/astro-gpios.h
+++ b/zircon/system/dev/board/astro/astro-gpios.h
@@ -12,3 +12,5 @@
#define GPIO_TOUCH_INTERRUPT S905D2_GPIOZ(4)
#define GPIO_TOUCH_RESET S905D2_GPIOZ(9)
#define GPIO_LIGHT_INTERRUPT S905D2_GPIOAO(5)
+#define GPIO_AUDIO_SOC_FAULT_L S905D2_GPIOA(4)
+#define GPIO_SOC_AUDIO_EN S905D2_GPIOA(5)
diff --git a/zircon/system/dev/board/astro/astro-i2c.c b/zircon/system/dev/board/astro/astro-i2c.c
index 6e5496c..11f1e85 100644
--- a/zircon/system/dev/board/astro/astro-i2c.c
+++ b/zircon/system/dev/board/astro/astro-i2c.c
@@ -71,6 +71,12 @@
.address = I2C_AMBIENTLIGHT_ADDR,
// binds as composite device
},
+ // Audio output
+ {
+ .bus_id = ASTRO_I2C_3,
+ .address = I2C_AUDIO_CODEC_ADDR,
+ // binds as composite device
+ },
};
static const pbus_metadata_t i2c_metadata[] = {
diff --git a/zircon/system/dev/board/astro/astro.h b/zircon/system/dev/board/astro/astro.h
index 0e4041c..fa323f0 100644
--- a/zircon/system/dev/board/astro/astro.h
+++ b/zircon/system/dev/board/astro/astro.h
@@ -84,6 +84,7 @@
#define I2C_BACKLIGHT_ADDR (0x2C)
#define I2C_FOCALTECH_TOUCH_ADDR (0x38)
#define I2C_AMBIENTLIGHT_ADDR (0x39)
+#define I2C_AUDIO_CODEC_ADDR (0x48)
#define I2C_GOODIX_TOUCH_ADDR (0x5d)
// astro-touch.c