diff --git a/zircon/system/dev/audio/sherlock-tdm-output/BUILD.gn b/zircon/system/dev/audio/sherlock-tdm-output/BUILD.gn index 7ce3c28ece3f8d3c30f14792a6270ce4e6278da3..8e7191ab5d71c73b08d9668ff8d11438a185de71 100644 --- a/zircon/system/dev/audio/sherlock-tdm-output/BUILD.gn +++ b/zircon/system/dev/audio/sherlock-tdm-output/BUILD.gn @@ -5,12 +5,11 @@ driver("sherlock-tdm-output") { sources = [ "audio-stream-out.cpp", - "binding.c", "tas5720.cpp", "tas5760.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-bus", diff --git a/zircon/system/dev/audio/sherlock-tdm-output/audio-stream-out.cpp b/zircon/system/dev/audio/sherlock-tdm-output/audio-stream-out.cpp index ce4cf650f4a5823ec7320c03a52577fb5e7f58bb..0e38fd101ab02ab22e077dee87d9e9bf7d0c0e66 100644 --- a/zircon/system/dev/audio/sherlock-tdm-output/audio-stream-out.cpp +++ b/zircon/system/dev/audio/sherlock-tdm-output/audio-stream-out.cpp @@ -2,7 +2,10 @@ // 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/platform-defs.h> +#include <ddk/protocol/composite.h> #include <ddktl/pdev.h> #include <soc/aml-t931/t931-gpio.h> @@ -11,6 +14,16 @@ namespace audio { namespace sherlock { +enum { + COMPONENT_PDEV, + COMPONENT_FAULT_GPIO, + COMPONENT_ENABLE_GPIO, + COMPONENT_I2C_0, + COMPONENT_I2C_1, + COMPONENT_I2C_2, // Optional + COMPONENT_COUNT, +}; + // Expects L+R for tweeters + L+R for the 1 Woofer (mixed in HW). // The user must perform crossover filtering on these channels. constexpr size_t kNumberOfChannels = 4; @@ -23,12 +36,28 @@ SherlockAudioStreamOut::SherlockAudioStreamOut(zx_device_t* parent) } zx_status_t SherlockAudioStreamOut::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) - 1) { + 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; } - size_t actual = 0; - zx_status_t status = device_get_metadata(parent(), DEVICE_METADATA_PRIVATE, &codecs_types_, + status = device_get_metadata(parent(), DEVICE_METADATA_PRIVATE, &codecs_types_, sizeof(metadata::Codec), &actual); if (status != ZX_OK || sizeof(metadata::Codec) != actual) { zxlogf(ERROR, "%s device_get_metadata failed %d\n", __FILE__, status); @@ -42,12 +71,12 @@ zx_status_t SherlockAudioStreamOut::InitPdev() { if (!ac.check()) { return ZX_ERR_NO_MEMORY; } - codecs_[0] = Tas5760::Create(pdev_, 0); + codecs_[0] = Tas5760::Create(components[COMPONENT_I2C_0]); if (!codecs_[0]) { zxlogf(ERROR, "%s could not get tas5760\n", __func__); return ZX_ERR_NO_RESOURCES; } - codecs_[1] = Tas5720::Create(pdev_, 1); + codecs_[1] = Tas5720::Create(components[COMPONENT_I2C_1]); if (!codecs_[1]) { zxlogf(ERROR, "%s could not get tas5720\n", __func__); return ZX_ERR_NO_RESOURCES; @@ -60,7 +89,7 @@ zx_status_t SherlockAudioStreamOut::InitPdev() { return ZX_ERR_NO_MEMORY; } for (uint32_t i = 0; i < 3; ++i) { - codecs_[i] = Tas5720::Create(pdev_, i); + codecs_[i] = Tas5720::Create(components[COMPONENT_I2C_0 + i]); if (!codecs_[i]) { zxlogf(ERROR, "%s could not get tas5720\n", __func__); return ZX_ERR_NO_RESOURCES; @@ -71,8 +100,8 @@ zx_status_t SherlockAudioStreamOut::InitPdev() { 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__); @@ -363,11 +392,7 @@ zx_status_t SherlockAudioStreamOut::InitBuffer(size_t size) { return ZX_OK; } -} // sherlock -} // 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::sherlock::SherlockAudioStreamOut>(device); if (stream == nullptr) { @@ -376,3 +401,23 @@ extern "C" zx_status_t audio_bind(void* ctx, zx_device_t* device, void** cookie) 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; +}(); + +} // sherlock +} // audio + +// clang-format off +ZIRCON_DRIVER_BEGIN(aml_sherlock_tdm, audio::sherlock::driver_ops, "zircon", "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_T931), + BI_MATCH_IF(EQ, BIND_PLATFORM_DEV_DID, PDEV_DID_AMLOGIC_TDM), +ZIRCON_DRIVER_END(aml_sherlock_tdm) +// clang-format on + diff --git a/zircon/system/dev/audio/sherlock-tdm-output/binding.c b/zircon/system/dev/audio/sherlock-tdm-output/binding.c deleted file mode 100644 index aa66d03847214a2641860d639fa2dc7e4a14c10d..0000000000000000000000000000000000000000 --- a/zircon/system/dev/audio/sherlock-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_sherlock_tdm, aml_tdm_driver_ops, "zircon", "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_T931), - BI_MATCH_IF(EQ, BIND_PLATFORM_DEV_DID, PDEV_DID_AMLOGIC_TDM), -ZIRCON_DRIVER_END(aml_sherlock_tdm) -// clang-format on diff --git a/zircon/system/dev/audio/sherlock-tdm-output/tas5720.cpp b/zircon/system/dev/audio/sherlock-tdm-output/tas5720.cpp index 8461f9594ce913a1ece0a3f64dce8738f9858fd8..3f999c23cd6c593912e8612b2ef1ec4d8a06bc84 100644 --- a/zircon/system/dev/audio/sherlock-tdm-output/tas5720.cpp +++ b/zircon/system/dev/audio/sherlock-tdm-output/tas5720.cpp @@ -26,13 +26,7 @@ constexpr uint8_t kRegDigitalClipper1 = 0x11; // clang-format on // static -fbl::unique_ptr<Tas5720> Tas5720::Create(ddk::PDev pdev, uint32_t index) { - auto i2c = pdev.GetI2c(index); - if (!i2c.is_valid()) { - zxlogf(ERROR, "%s pdev_get_protocol failed\n", __FUNCTION__); - return nullptr; - } - +fbl::unique_ptr<Tas5720> Tas5720::Create(ddk::I2cChannel i2c) { fbl::AllocChecker ac; auto ptr = fbl::make_unique_checked<Tas5720>(&ac, i2c); if (!ac.check()) { diff --git a/zircon/system/dev/audio/sherlock-tdm-output/tas5720.h b/zircon/system/dev/audio/sherlock-tdm-output/tas5720.h index a1d00831201da68d3be4b15cb761ea19e99cf41a..f8e8911ef34ac1c53b5f6f75766e6bda68e6a578 100644 --- a/zircon/system/dev/audio/sherlock-tdm-output/tas5720.h +++ b/zircon/system/dev/audio/sherlock-tdm-output/tas5720.h @@ -14,7 +14,7 @@ namespace audio { class Tas5720 final : public Codec { public: - static fbl::unique_ptr<Tas5720> Create(ddk::PDev pdev, uint32_t index); + static fbl::unique_ptr<Tas5720> Create(ddk::I2cChannel i2c); explicit Tas5720(const ddk::I2cChannel& i2c) : i2c_(i2c) {} diff --git a/zircon/system/dev/audio/sherlock-tdm-output/tas5760.cpp b/zircon/system/dev/audio/sherlock-tdm-output/tas5760.cpp index 293b07e37aec623c599f02cc35c6d8137aeae63d..7e91b928ef3e2b0dccc21a3a27756b1951543d9a 100644 --- a/zircon/system/dev/audio/sherlock-tdm-output/tas5760.cpp +++ b/zircon/system/dev/audio/sherlock-tdm-output/tas5760.cpp @@ -27,13 +27,7 @@ constexpr uint8_t kRegDigitalClipper1 = 0x11; // clang-format on // static -fbl::unique_ptr<Tas5760> Tas5760::Create(ddk::PDev pdev, uint32_t index) { - auto i2c = pdev.GetI2c(index); - if (!i2c.is_valid()) { - zxlogf(ERROR, "%s pdev_get_protocol failed\n", __func__); - return nullptr; - } - +fbl::unique_ptr<Tas5760> Tas5760::Create(ddk::I2cChannel i2c) { fbl::AllocChecker ac; auto ptr = fbl::make_unique_checked<Tas5760>(&ac, i2c); if (!ac.check()) { diff --git a/zircon/system/dev/audio/sherlock-tdm-output/tas5760.h b/zircon/system/dev/audio/sherlock-tdm-output/tas5760.h index 561bab3f6588dac5a9ea5a584856e877aebf1a0d..0225bb048f1e7ebc711bbba6b998ddefe511b8ae 100644 --- a/zircon/system/dev/audio/sherlock-tdm-output/tas5760.h +++ b/zircon/system/dev/audio/sherlock-tdm-output/tas5760.h @@ -14,7 +14,7 @@ namespace audio { class Tas5760 final : public Codec { public: - static fbl::unique_ptr<Tas5760> Create(ddk::PDev pdev, uint32_t index); + static fbl::unique_ptr<Tas5760> Create(ddk::I2cChannel i2c); explicit Tas5760(const ddk::I2cChannel& i2c) : i2c_(i2c) {} diff --git a/zircon/system/dev/board/sherlock/sherlock-audio.cpp b/zircon/system/dev/board/sherlock/sherlock-audio.cpp index 29c16f233e78d2c166d836efc6013ce3f390cbb7..c6aa548d1b30a7edf48abe74dbfcf4f1d798627e 100644 --- a/zircon/system/dev/board/sherlock/sherlock-audio.cpp +++ b/zircon/system/dev/board/sherlock/sherlock-audio.cpp @@ -2,8 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "sherlock.h" - +#include <ddk/binding.h> #include <ddk/debug.h> #include <ddk/device.h> #include <ddk/platform-defs.h> @@ -13,21 +12,12 @@ #include <soc/aml-t931/t931-gpio.h> #include <soc/aml-t931/t931-hw.h> +#include "sherlock.h" +#include "sherlock-gpios.h" + namespace sherlock { zx_status_t Sherlock::AudioInit() { - - static constexpr pbus_gpio_t audio_gpios[] = { - { - // AUDIO_SOC_FAULT_L - .gpio = T931_GPIOZ(8), - }, - { - // SOC_AUDIO_EN - .gpio = T931_GPIOH(7), - }, - }; - static constexpr pbus_mmio_t audio_mmios[] = { { .base = T931_EE_AUDIO_BASE, @@ -50,32 +40,6 @@ zx_status_t Sherlock::AudioInit() { }, }; - static constexpr pbus_i2c_channel_t p2_codecs_i2cs[] = { - { - .bus_id = SHERLOCK_I2C_A0_0, - .address = 0x6c, // Tweeters. - }, - { - .bus_id = SHERLOCK_I2C_A0_0, - .address = 0x6f, // Woofer. - }, - }; - - static constexpr pbus_i2c_channel_t evt_codecs_i2cs[] = { - { - .bus_id = SHERLOCK_I2C_A0_0, - .address = 0x6c, // Tweeter left. - }, - { - .bus_id = SHERLOCK_I2C_A0_0, - .address = 0x6d, // Tweeter right. - }, - { - .bus_id = SHERLOCK_I2C_A0_0, - .address = 0x6f, // Woofer. - }, - }; - pdev_board_info_t board_info = {}; zx_status_t status = pbus_.GetBoardInfo(&board_info); if (status != ZX_OK) { @@ -85,10 +49,8 @@ zx_status_t Sherlock::AudioInit() { // We treat EVT and higher the same (having 3 TAS5720s). metadata::Codec out_codec = metadata::Codec::Tas5720x3; - if (board_info.board_revision < BOARD_REV_P2) { - return ZX_ERR_NOT_SUPPORTED; // For audio we don't support boards revision lower than P2. - } else if (board_info.board_revision < BOARD_REV_EVT1) { - out_codec = metadata::Codec::Tas5760_Tas5720; // We treat all P2 variants the same. + if (board_info.board_revision < BOARD_REV_EVT1) { + return ZX_ERR_NOT_SUPPORTED; // For audio we don't support boards revision lower than EVT. } pbus_metadata_t out_metadata[] = { @@ -99,13 +61,65 @@ zx_status_t Sherlock::AudioInit() { }, }; + constexpr zx_bind_inst_t root_match[] = { + BI_MATCH(), + }; + constexpr 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), + }; + constexpr 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), + }; + constexpr zx_bind_inst_t tweeter_left_i2c_match[] = { + BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_I2C), + BI_ABORT_IF(NE, BIND_I2C_BUS_ID, SHERLOCK_I2C_A0_0), + BI_MATCH_IF(EQ, BIND_I2C_ADDRESS, 0x6c), + }; + constexpr zx_bind_inst_t tweeter_right_i2c_match[] = { + BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_I2C), + BI_ABORT_IF(NE, BIND_I2C_BUS_ID, SHERLOCK_I2C_A0_0), + BI_MATCH_IF(EQ, BIND_I2C_ADDRESS, 0x6d), + }; + constexpr zx_bind_inst_t woofer_i2c_match[] = { + BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_I2C), + BI_ABORT_IF(NE, BIND_I2C_BUS_ID, SHERLOCK_I2C_A0_0), + BI_MATCH_IF(EQ, BIND_I2C_ADDRESS, 0x6f), + }; + const device_component_part_t fault_gpio_component[] = { + { countof(root_match), root_match }, + { countof(fault_gpio_match), fault_gpio_match }, + }; + const device_component_part_t enable_gpio_component[] = { + { countof(root_match), root_match }, + { countof(enable_gpio_match), enable_gpio_match }, + }; + const device_component_part_t tweeter_left_i2c_component[] = { + { countof(root_match), root_match }, + { countof(tweeter_left_i2c_match), tweeter_left_i2c_match }, + }; + const device_component_part_t tweeter_right_i2c_component[] = { + { countof(root_match), root_match }, + { countof(tweeter_right_i2c_match), tweeter_right_i2c_match }, + }; + const device_component_part_t woofer_i2c_component[] = { + { countof(root_match), root_match }, + { countof(woofer_i2c_match), woofer_i2c_match }, + }; + const device_component_t components[] = { + { countof(fault_gpio_component), fault_gpio_component }, + { countof(enable_gpio_component), enable_gpio_component }, + { countof(tweeter_left_i2c_component), tweeter_left_i2c_component }, + { countof(tweeter_right_i2c_component), tweeter_right_i2c_component }, + { countof(woofer_i2c_component), woofer_i2c_component }, + }; + pbus_dev_t tdm_dev = {}; tdm_dev.name = "SherlockAudio"; tdm_dev.vid = PDEV_VID_AMLOGIC; tdm_dev.pid = PDEV_PID_AMLOGIC_T931; tdm_dev.did = PDEV_DID_AMLOGIC_TDM; - tdm_dev.gpio_list = audio_gpios; - tdm_dev.gpio_count = countof(audio_gpios); tdm_dev.mmio_list = audio_mmios; tdm_dev.mmio_count = countof(audio_mmios); tdm_dev.bti_list = tdm_btis; @@ -113,14 +127,6 @@ zx_status_t Sherlock::AudioInit() { tdm_dev.metadata_list = out_metadata; tdm_dev.metadata_count = countof(out_metadata); - if (board_info.board_revision < BOARD_REV_EVT1) { - tdm_dev.i2c_channel_list = p2_codecs_i2cs; - tdm_dev.i2c_channel_count = countof(p2_codecs_i2cs); - } else { - tdm_dev.i2c_channel_list = evt_codecs_i2cs; - tdm_dev.i2c_channel_count = countof(evt_codecs_i2cs); - } - static constexpr pbus_mmio_t pdm_mmios[] = { { .base = T931_EE_PDM_BASE, @@ -149,7 +155,6 @@ zx_status_t Sherlock::AudioInit() { pdm_dev.bti_list = pdm_btis; pdm_dev.bti_count = countof(pdm_btis); - aml_hiu_dev_t hiu; status = s905d2_hiu_init(&hiu); if (status != ZX_OK) { @@ -180,7 +185,7 @@ zx_status_t Sherlock::AudioInit() { gpio_impl_.ConfigOut(T931_GPIOH(7), 1); // SOC_AUDIO_EN. - status = pbus_.DeviceAdd(&tdm_dev); + status = pbus_.CompositeDeviceAdd(&tdm_dev, components, countof(components), UINT32_MAX); if (status != ZX_OK) { zxlogf(ERROR, "%s pbus_.DeviceAdd failed %d\n", __FUNCTION__, status); return status; diff --git a/zircon/system/dev/board/sherlock/sherlock-gpio.cpp b/zircon/system/dev/board/sherlock/sherlock-gpio.cpp index e5ad6607c8ecbc82f41b89db955c0c2413779400..2ad9c2a3727c68115da372000ed3b25d8e5cef19 100644 --- a/zircon/system/dev/board/sherlock/sherlock-gpio.cpp +++ b/zircon/system/dev/board/sherlock/sherlock-gpio.cpp @@ -77,6 +77,9 @@ static const gpio_pin_t gpio_pins[] = { // For touch screen. { GPIO_TOUCH_INTERRUPT }, { GPIO_TOUCH_RESET }, + // For audio out. + { GPIO_AUDIO_SOC_FAULT_L }, + { GPIO_SOC_AUDIO_EN }, }; static const pbus_metadata_t gpio_metadata[] = { diff --git a/zircon/system/dev/board/sherlock/sherlock-gpios.h b/zircon/system/dev/board/sherlock/sherlock-gpios.h index 83171e62590162322235cfb3be9289c903a91e11..7905e2cc0c5981e106738724fcf64c64491b10d5 100644 --- a/zircon/system/dev/board/sherlock/sherlock-gpios.h +++ b/zircon/system/dev/board/sherlock/sherlock-gpios.h @@ -11,3 +11,5 @@ #define GPIO_PANEL_DETECT T931_GPIOH(0) #define GPIO_TOUCH_INTERRUPT T931_GPIOZ(1) #define GPIO_TOUCH_RESET T931_GPIOZ(9) +#define GPIO_AUDIO_SOC_FAULT_L T931_GPIOZ(8) +#define GPIO_SOC_AUDIO_EN T931_GPIOH(7) diff --git a/zircon/system/dev/board/sherlock/sherlock-i2c.cpp b/zircon/system/dev/board/sherlock/sherlock-i2c.cpp index 185515bbc3b5d868d88756bcfeccb764d06bec2b..994809f2e1ff8a2bc5a46db613d063dee637810c 100644 --- a/zircon/system/dev/board/sherlock/sherlock-i2c.cpp +++ b/zircon/system/dev/board/sherlock/sherlock-i2c.cpp @@ -64,6 +64,30 @@ static const i2c_channel_t i2c_channels[] = { .pid = 0, .did = 0, }, + // Tweeter left + { + .bus_id = SHERLOCK_I2C_A0_0, + .address = 0x6c, + .vid = 0, + .pid = 0, + .did = 0, + }, + // Tweeter right + { + .bus_id = SHERLOCK_I2C_A0_0, + .address = 0x6d, + .vid = 0, + .pid = 0, + .did = 0, + }, + // Woofer + { + .bus_id = SHERLOCK_I2C_A0_0, + .address = 0x6f, + .vid = 0, + .pid = 0, + .did = 0, + }, }; static const pbus_metadata_t i2c_metadata[] = {