diff --git a/drivers/audio/CMakeLists.txt b/drivers/audio/CMakeLists.txt index bca0f07b86e25..e61bb0e6213be 100644 --- a/drivers/audio/CMakeLists.txt +++ b/drivers/audio/CMakeLists.txt @@ -13,6 +13,7 @@ zephyr_library_sources_ifdef(CONFIG_AUDIO_DMIC_MCUX dmic_mcux.c) zephyr_library_sources_ifdef(CONFIG_AUDIO_CODEC_WM8904 wm8904.c) zephyr_library_sources_ifdef(CONFIG_AUDIO_CODEC_WM8962 wm8962.c) zephyr_library_sources_ifdef(CONFIG_AUDIO_CODEC_CS43L22 cs43l22.c) +zephyr_library_sources_ifdef(CONFIG_AUDIO_CODEC_CS47L63 cs47l63.c) zephyr_library_sources_ifdef(CONFIG_AUDIO_CODEC_PCM1681 pcm1681.c) zephyr_library_sources_ifdef(CONFIG_AUDIO_CODEC_MAX98091 max98091.c) zephyr_library_sources_ifdef(CONFIG_AUDIO_DMIC_AMBIQ_PDM dmic_ambiq_pdm.c) diff --git a/drivers/audio/Kconfig b/drivers/audio/Kconfig index 78fb303988055..62f72bd4181b4 100644 --- a/drivers/audio/Kconfig +++ b/drivers/audio/Kconfig @@ -36,6 +36,7 @@ module-str = audio codec source "subsys/logging/Kconfig.template.log_config" source "drivers/audio/Kconfig.cs43l22" +source "drivers/audio/Kconfig.cs47l63" source "drivers/audio/Kconfig.max98091" source "drivers/audio/Kconfig.pcm1681" source "drivers/audio/Kconfig.tas6422dac" diff --git a/drivers/audio/Kconfig.cs47l63 b/drivers/audio/Kconfig.cs47l63 new file mode 100644 index 0000000000000..44cc3c966adbd --- /dev/null +++ b/drivers/audio/Kconfig.cs47l63 @@ -0,0 +1,11 @@ +# Copyright (c) 2025 Titouan Christophe +# SPDX-License-Identifier: Apache-2.0 + +config AUDIO_CODEC_CS47L63 + bool "Cirrus CS47L63 driver" + default y + select SPI + depends on DT_HAS_CIRRUS_CS47L63_ENABLED + help + Enable the driver for the Cirrus CS47L63 Low-Power Audio DSP + with Microphone Interface and Mono Differential Headphone Driver diff --git a/drivers/audio/cs47l63.c b/drivers/audio/cs47l63.c new file mode 100644 index 0000000000000..964ca840d298d --- /dev/null +++ b/drivers/audio/cs47l63.c @@ -0,0 +1,378 @@ +/* + * Copyright (c) 2025 Titouan Christophe + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include "cs47l63.h" + +#include +LOG_MODULE_REGISTER(cs47l63, CONFIG_AUDIO_CODEC_LOG_LEVEL); + +#define DT_DRV_COMPAT cirrus_cs47l63 + +struct cs47l63_config { + struct spi_dt_spec spi; + struct gpio_dt_spec reset_gpio; + struct gpio_dt_spec irq_gpio; +}; + +struct reg_value { + uint32_t reg; + uint32_t value; +}; + +#define PRINT_REG(spi, reg_name) \ + do {uint32_t value; \ + cs47l63_read_spi_regs(spi, reg_name, &value, 1); \ + LOG_INF("%20s (%4X) = %08X", &(#reg_name)[12], reg_name, value);} \ + while (0) + +static int cs47l63_read_spi_regs(const struct spi_dt_spec *spi, + uint32_t start_reg, uint32_t *values, size_t count) +{ + int ret; + /* Register address + READ bit set */ + uint32_t addr = sys_cpu_to_be32(BIT(31) | start_reg); + struct spi_buf tx_buf = {.buf = (void *) &addr, .len = sizeof(addr)}; + struct spi_buf_set tx_bufset = {.buffers = &tx_buf, .count = 1}; + uint32_t rx_padbuf[2]; + struct spi_buf rx_bufs[2] = { + /* 1 empty rx word while we write out the address + * + 1 padding word (see datasheet 4.13.1) + */ + {.buf = rx_padbuf, .len = sizeof(rx_padbuf)}, + /* The actual reading result */ + {.buf = values, .len = count * sizeof(uint32_t)}, + }; + + struct spi_buf_set rx_bufset = {.buffers = rx_bufs, .count = 2}; + + ret = spi_transceive_dt(spi, &tx_bufset, &rx_bufset); + if (ret != 0) { + LOG_ERR("Unable to read register: %d", ret); + return ret; + } + + for (size_t i = 0; i < count; i++) { + values[i] = sys_be32_to_cpu(values[i]); + } + + return 0; +} + +static int cs47l63_write_spi_blob(const struct spi_dt_spec *spi, + uint32_t addr, const uint8_t *data, size_t len) +{ + int ret; + uint32_t setup_buf[2] = { + sys_cpu_to_be32(addr & 0x7FFFFFFF), + 0, /* Padding (see datasheet 4.13.1) */ + }; + struct spi_buf tx_bufs[2] = { + {.buf = setup_buf, .len = sizeof(setup_buf)}, + {.buf = (void *) data, .len = len}, + }; + struct spi_buf_set bufset = {.buffers = tx_bufs, .count = 2}; + + ret = spi_write_dt(spi, &bufset); + if (ret != 0) { + LOG_ERR("Unable to write blob[%d]: %d", len, ret); + } + + return ret; +} + +static inline int cs47l63_write_spi_reg(const struct spi_dt_spec *spi, + uint32_t reg, uint32_t value) +{ + uint32_t encoded_value = sys_cpu_to_be32(value); + + return cs47l63_write_spi_blob(spi, reg, (const uint8_t *) &encoded_value, 4); +} + +static inline int cs47l63_update_spi_reg(const struct spi_dt_spec *spi, + uint32_t reg, uint32_t value, uint32_t mask) +{ + int ret; + uint32_t prev_value; + + ret = cs47l63_read_spi_regs(spi, reg, &prev_value, 1); + if (ret != 0) { + return ret; + } + + return cs47l63_write_spi_reg(spi, reg, (prev_value & ~mask) | (value & mask)); +} + +static inline int cs47l63_write_spi_regs(const struct spi_dt_spec *spi, + const struct reg_value *values, + size_t n_values) +{ + int ret; + + for (size_t i=0; idai_cfg.i2s.word_size; + const struct cs47l63_config *cfg = dev->config; + + if (audiocfg->dai_route != AUDIO_ROUTE_PLAYBACK) { + return -ENOTSUP; + } + + if (wordsize < 16 || wordsize > 32) { + LOG_WRN("Unsupported word size"); + return -ENOTSUP; + } + + switch (audiocfg->dai_type) { + case AUDIO_DAI_TYPE_LEFT_JUSTIFIED: + format = ASP_FMT_LEFTJUST; + break; + case AUDIO_DAI_TYPE_I2S: + format = ASP_FMT_I2S; + break; + default: + LOG_WRN("Unsupported interface type"); + return -ENOTSUP; + } + + sample_rate = cs47l63_sample_rate(audiocfg->dai_cfg.i2s.frame_clk_freq); + if (sample_rate < 0) { + return -ENOTSUP; + } + + /* Derive CLK from FLL1 @ 49.152 MHz */ + clk_config = 0x34C; + if (SAMPLE_RATE_11_025_kHz <= sample_rate && sample_rate <= SAMPLE_RATE_176_4_kHz) { + /* CLK_FRAC freq (45.1584 MHz) for 44.1kHz sample rates */ + clk_config |= BIT(15); + } + + const struct reg_value config[] = { + /* Configure SYSCLK */ + {.reg = CS47L63_REG_SYSTEM_CLOCK1, .value = clk_config}, + /* Setup channel word size and format on ASP1 */ + {.reg = CS47L63_REG_ASP1_CONTROL2, .value = (wordsize << 24) | (format << 8)}, + {.reg = CS47L63_REG_ASP1_DATA_CONTROL5, .value = wordsize}, + {.reg = CS47L63_REG_SAMPLE_RATE1, .value = sample_rate}, + /* Enable ASP1 Rx channel 1 */ + {.reg = CS47L63_REG_ASP1_ENABLES1, .value = BIT(16)}, + /* Route ASP1 Rx channel 1 to output */ + {.reg = CS47L63_REG_OUT1L_INPUT1, .value = MIXER_SRC_ASP1_RX1}, + /* Enable output path */ + {.reg = CS47L63_REG_OUTPUT_ENABLE_1, .value = BIT(1)}, + /* Unmute, 0dB out */ + {.reg = CS47L63_REG_OUT1L_VOLUME_1, .value = 0x280}, + }; + + ret = cs47l63_write_spi_regs(&cfg->spi, config, ARRAY_SIZE(config)); + if (ret != 0) { + LOG_ERR("Unable to set output configuration"); + return -EIO; + } + + return 0; +} + +static void cs47l63_start_output(const struct device *dev) +{ +} + +static void cs47l63_stop_output(const struct device *dev) +{ +} + +static int cs47l63_set_property(const struct device *dev, audio_property_t property, + audio_channel_t channel, audio_property_value_t val) +{ + const struct cs47l63_config *cfg = dev->config; + int ret; + uint32_t value, mask; + + if (channel != AUDIO_CHANNEL_HEADPHONE_LEFT) { + return -ENOTSUP; + } + + switch (property) { + case AUDIO_PROPERTY_OUTPUT_MUTE: + mask = BIT(8); + value = val.mute ? BIT(8) : 0; + break; + case AUDIO_PROPERTY_OUTPUT_VOLUME: + mask = 0xFF; + value = 0xBF * val.vol / 100; + break; + default: + return -ENOTSUP; + } + + ret = cs47l63_update_spi_reg(&cfg->spi, CS47L63_REG_OUT1L_VOLUME_1, + BIT(9)|value, BIT(9)|mask); + return (ret == 0) ? 0 : -EIO; +} + +static int cs47l63_apply_properties(const struct device *dev) +{ + return 0; +} + +static const struct audio_codec_api cs47l63_driver_api = { + .configure = cs47l63_configure, + .start_output = cs47l63_start_output, + .stop_output = cs47l63_stop_output, + .set_property = cs47l63_set_property, + .apply_properties = cs47l63_apply_properties, +}; + +static inline bool wait_gpio(const struct gpio_dt_spec *gpio, int expected_state, + int timeout_ms) +{ + while (timeout_ms-- > 0) { + if (gpio_pin_get_dt(gpio) == expected_state) { + return true; + } + + k_msleep(1); + } + + return false; +} + +static int cs47l63_init(const struct device *dev) +{ + const struct reg_value init_config[] = { + /* Configure GPIO1-4 for ASP1 (I2S function) with bus keeper */ + {.reg = CS47L63_REG_GPIO1_CTRL1, .value = 0x60000000}, + {.reg = CS47L63_REG_GPIO2_CTRL1, .value = 0x60000000}, + {.reg = CS47L63_REG_GPIO3_CTRL1, .value = 0x60000000}, + {.reg = CS47L63_REG_GPIO4_CTRL1, .value = 0x60000000}, + /* FLL1 from internal osc, no divider, "detect" defaults */ + {.reg = CS47L63_REG_FLL1_CONTROL2, .value = 0x88202004}, + /* Enable FLL1 */ + {.reg = CS47L63_REG_FLL1_CONTROL1, .value = BIT(0)}, + }; + const struct cs47l63_config *cfg = dev->config; + uint32_t devid[2]; + int ret; + + if (!spi_is_ready_dt(&cfg->spi)) { + LOG_ERR("SPI bus is not ready"); + return -ENODEV; + } + + ret = gpio_pin_configure_dt(&cfg->irq_gpio, GPIO_INPUT); + if (ret != 0) { + LOG_ERR("Unable to setup IRQ pin"); + return -EIO; + } + + /* Put device in hardware RESET */ + ret = gpio_pin_configure_dt(&cfg->reset_gpio, GPIO_OUTPUT_ACTIVE); + if (ret != 0) { + LOG_ERR("Unable to setup nreset GPIO"); + return -EIO; + } + + /* Wait for device to be in reset state */ + if (!wait_gpio(&cfg->irq_gpio, 0, 10)) { + LOG_ERR("Timed out while waiting for device reset"); + return -ETIMEDOUT; + } + + /* Release RESET state */ + ret = gpio_pin_set_dt(&cfg->reset_gpio, 0); + if (ret != 0) { + LOG_ERR("Unable to complete hw reset"); + return -EIO; + } + + /* Wait for device to be ready */ + if (!wait_gpio(&cfg->irq_gpio, 1, 10)) { + LOG_ERR("Timed out while waiting for device start"); + return -ETIMEDOUT; + } + + ret = cs47l63_read_spi_regs(&cfg->spi, CS47L63_REG_DEVID, devid, ARRAY_SIZE(devid)); + if (ret != 0) { + LOG_ERR("Error reading DEVID: %d", ret); + return -EIO; + } + + if (devid[0] != CS47L63_DEVID) { + LOG_WRN("Invalid device ID"); + return -ENODEV; + } + + LOG_DBG("Found CS47L63 rev %d.%d", (devid[1] >> 4) & 0xF, devid[1] & 0xF); + ret = cs47l63_write_spi_regs(&cfg->spi, init_config, ARRAY_SIZE(init_config)); + + return 0; +} + +#define CS47L63_SPI_OPMODE (SPI_OP_MODE_MASTER | SPI_WORD_SET(8)) + +#define CS47L63_INIT(inst) \ + static const struct cs47l63_config cs47l63_config_##inst = { \ + .spi = SPI_DT_SPEC_INST_GET(inst, CS47L63_SPI_OPMODE), \ + .reset_gpio = GPIO_DT_SPEC_INST_GET(inst, reset_gpios), \ + .irq_gpio = GPIO_DT_SPEC_INST_GET(inst, irq_gpios), \ + }; \ + DEVICE_DT_INST_DEFINE(inst, cs47l63_init, NULL, NULL, \ + &cs47l63_config_##inst, POST_KERNEL, \ + CONFIG_AUDIO_CODEC_INIT_PRIORITY, \ + &cs47l63_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(CS47L63_INIT) diff --git a/drivers/audio/cs47l63.h b/drivers/audio/cs47l63.h new file mode 100644 index 0000000000000..119307a0c6fa5 --- /dev/null +++ b/drivers/audio/cs47l63.h @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2025 Titouan Christophe + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef CS47L63_H +#define CS47L63_H + +/* Datasheet: https://statics.cirrus.com/pubs/proDatasheet/CS47L63_DS1249F2.pdf */ + +/* See datasheet Section 6: Register Map */ +#define CS47L63_REG_DEVID 0x0000 +#define CS47L63_REG_REVID 0x0004 +#define CS47L63_REG_GPIO_STATUS1 0x0C00 +#define CS47L63_REG_GPIO1_CTRL1 0x0C08 +#define CS47L63_REG_GPIO2_CTRL1 0x0C0C +#define CS47L63_REG_GPIO3_CTRL1 0x0C10 +#define CS47L63_REG_GPIO4_CTRL1 0x0C14 +#define CS47L63_REG_GPIO5_CTRL1 0x0C18 +#define CS47L63_REG_GPIO6_CTRL1 0x0C1C +#define CS47L63_REG_GPIO7_CTRL1 0x0C20 +#define CS47L63_REG_GPIO8_CTRL1 0x0C24 +#define CS47L63_REG_GPIO9_CTRL1 0x0C28 +#define CS47L63_REG_GPIO10_CTRL1 0x0C2C +#define CS47L63_REG_GPIO11_CTRL1 0x0C30 +#define CS47L63_REG_GPIO12_CTRL1 0x0C34 +#define CS47L63_REG_CLKGEN_PAD_CTRL 0x1030 +#define CS47L63_REG_CLOCK32K 0x1400 +#define CS47L63_REG_SYSTEM_CLOCK1 0X1404 +#define CS47L63_REG_SYSTEM_CLOCK2 0X1408 +#define CS47L63_REG_SAMPLE_RATE1 0x1420 +#define CS47L63_REG_SAMPLE_RATE2 0x1424 +#define CS47L63_REG_SAMPLE_RATE3 0x1428 +#define CS47L63_REG_SAMPLE_RATE4 0x142C +#define CS47L63_REG_SAMPLE_RATE_STATUS1 0x1440 +#define CS47L63_REG_SAMPLE_RATE_STATUS2 0x1444 +#define CS47L63_REG_SAMPLE_RATE_STATUS3 0x1448 +#define CS47L63_REG_SAMPLE_RATE_STATUS4 0x144C +#define CS47L63_REG_ASYNC_CLOCK1 0x1460 +#define CS47L63_REG_ASYNC_CLOCK2 0x1464 +#define CS47L63_REG_FLL1_CONTROL1 0x1C00 +#define CS47L63_REG_FLL1_CONTROL2 0x1C04 +#define CS47L63_REG_FLL1_CONTROL3 0x1C08 +#define CS47L63_REG_FLL1_CONTROL4 0x1C0C + +#define CS47L63_REG_OUTPUT_ENABLE_1 0x4804 +#define CS47L63_REG_OUTPUT_STATUS_1 0x4808 +#define CS47L63_REG_OUTPUT_CONTROL_1 0x480C +#define CS47L63_REG_OUT1L_VOLUME_1 0x4818 +#define CS47L63_REG_OUT1L_CONTROL_1 0x4820 + +#define CS47L63_REG_ASP1_ENABLES1 0x6000 +#define CS47L63_REG_ASP1_CONTROL1 0x6004 +#define CS47L63_REG_ASP1_CONTROL2 0x6008 +#define CS47L63_REG_ASP1_CONTROL3 0x600C +#define CS47L63_REG_ASP1_FRAME_CONTROL1 0x6010 +#define CS47L63_REG_ASP1_FRAME_CONTROL2 0x6014 +#define CS47L63_REG_ASP1_FRAME_CONTROL5 0x6020 +#define CS47L63_REG_ASP1_FRAME_CONTROL6 0x6024 +#define CS47L63_REG_ASP1_DATA_CONTROL1 0x6030 +#define CS47L63_REG_ASP1_DATA_CONTROL5 0x6040 + +#define CS47L63_REG_OUT1L_INPUT1 0x8100 +#define CS47L63_REG_OUT1L_INPUT2 0x8104 +#define CS47L63_REG_OUT1L_INPUT3 0x8108 +#define CS47L63_REG_OUT1L_INPUT4 0x810C + +/* See datasheet Table 4-9: Digital-Core Mixer Control Registers */ +#define MIXER_SRC_NONE 0x000 +#define MIXER_SRC_TONE_GENERATOR_1 0x004 +#define MIXER_SRC_TONE_GENERATOR_2 0x005 +#define MIXER_SRC_NOISE_GENERATOR 0x00C +#define MIXER_SRC_IN1L_SIGNAL_PATH 0x010 +#define MIXER_SRC_IN1R_SIGNAL_PATH 0x011 +#define MIXER_SRC_IN2L_SIGNAL_PATH 0x012 +#define MIXER_SRC_IN2R_SIGNAL_PATH 0x013 +#define MIXER_SRC_ASP1_RX1 0x020 +#define MIXER_SRC_ASP1_RX2 0x021 +#define MIXER_SRC_ASP1_RX3 0x022 +#define MIXER_SRC_ASP1_RX4 0x023 +#define MIXER_SRC_ASP1_RX5 0x024 +#define MIXER_SRC_ASP1_RX6 0x025 +#define MIXER_SRC_ASP1_RX7 0x026 +#define MIXER_SRC_ASP1_RX8 0x027 +#define MIXER_SRC_ASP2_RX1 0x030 +#define MIXER_SRC_ASP2_RX2 0x031 +#define MIXER_SRC_ASP2_RX3 0x032 +#define MIXER_SRC_ASP2_RX4 0x033 +#define MIXER_SRC_ASRC1_IN1_LEFT 0x088 +#define MIXER_SRC_ASRC1_IN1_RIGHT 0x089 +#define MIXER_SRC_ASRC1_IN2_LEFT 0x08A +#define MIXER_SRC_ASRC1_IN2_RIGHT 0x08B +#define MIXER_SRC_LSRC2_IN_LEFT 0x08C +#define MIXER_SRC_LSRC2_IN_RIGHT 0x08D +#define MIXER_SRC_LSRC3_IN_LEFT 0x090 +#define MIXER_SRC_LSRC3_IN_RIGHT 0x091 +#define MIXER_SRC_ISRC1_INT1 0x098 +#define MIXER_SRC_ISRC1_INT2 0x099 +#define MIXER_SRC_ISRC1_INT3 0x09A +#define MIXER_SRC_ISRC1_INT4 0x09B +#define MIXER_SRC_ISRC1_DEC1 0x09C +#define MIXER_SRC_ISRC1_DEC2 0x09D +#define MIXER_SRC_ISRC1_DEC3 0x09E +#define MIXER_SRC_ISRC1_DEC4 0x09F +#define MIXER_SRC_ISRC2_INT1 0x0A0 +#define MIXER_SRC_ISRC2_INT2 0x0A1 +#define MIXER_SRC_ISRC2_DEC1 0x0A4 +#define MIXER_SRC_ISRC2_DEC2 0x0A5 +#define MIXER_SRC_ISRC3_INT1 0x0A8 +#define MIXER_SRC_ISRC3_INT2 0x0A9 +#define MIXER_SRC_ISRC3_DEC1 0x0AC +#define MIXER_SRC_ISRC3_DEC2 0x0AD +#define MIXER_SRC_EQ1 0x0B8 +#define MIXER_SRC_EQ2 0x0B9 +#define MIXER_SRC_EQ3 0x0BA +#define MIXER_SRC_EQ4 0x0BB +#define MIXER_SRC_DRC1_LEFT 0x0C0 +#define MIXER_SRC_DRC1_RIGHT 0x0C1 +#define MIXER_SRC_DRC2_LEFT 0x0C2 +#define MIXER_SRC_DRC2_RIGHT 0x0C3 +#define MIXER_SRC_LHPF1 0x0C8 +#define MIXER_SRC_LHPF2 0x0C9 +#define MIXER_SRC_LHPF3 0x0CA +#define MIXER_SRC_LHPF4 0x0CB +#define MIXER_SRC_DSP1_CHANNEL_1 0x100 +#define MIXER_SRC_DSP1_CHANNEL_2 0x101 +#define MIXER_SRC_DSP1_CHANNEL_3 0x102 +#define MIXER_SRC_DSP1_CHANNEL_4 0x103 +#define MIXER_SRC_DSP1_CHANNEL_5 0x104 +#define MIXER_SRC_DSP1_CHANNEL_6 0x105 +#define MIXER_SRC_DSP1_CHANNEL_7 0x106 +#define MIXER_SRC_DSP1_CHANNEL_8 0x107 + +/* See datasheet Table 4-37: ASP Digital Audio Data Control */ +#define ASP_FMT_TDM1 0x00 +#define ASP_FMT_TDM0 0x01 +#define ASP_FMT_I2S 0x02 +#define ASP_FMT_LEFTJUST 0x03 +#define ASP_FMT_TDM1_5 0x04 + +/* See datasheet Table 4-46: SYSCLK Frequency Selection */ +#define SAMPLE_RATE_NONE 0x00 +#define SAMPLE_RATE_12_kHz 0x01 +#define SAMPLE_RATE_24_kHz 0x02 +#define SAMPLE_RATE_48_kHz 0x03 +#define SAMPLE_RATE_96_kHz 0x04 +#define SAMPLE_RATE_192_kHz 0x05 +#define SAMPLE_RATE_11_025_kHz 0x09 +#define SAMPLE_RATE_22_05_kHz 0x0A +#define SAMPLE_RATE_44_1_kHz 0x0B +#define SAMPLE_RATE_88_2_kHz 0x0C +#define SAMPLE_RATE_176_4_kHz 0x0D +#define SAMPLE_RATE_8_kHz 0x11 +#define SAMPLE_RATE_16_kHz 0x12 +#define SAMPLE_RATE_32_kHz 0x13 + +/* See datasheet Table 4-48: Clocking Control */ +#define SYSCLK_SRC_MCLK1 0x00 +#define SYSCLK_SRC_MCLK2 0x01 +#define SYSCLK_SRC_FLL1x2 0x04 +#define SYSCLK_SRC_FLL2x2 0x05 +#define SYSCLK_SRC_ASP1_BCLK 0x08 +#define SYSCLK_SRC_ASP2_BCLK 0x09 +#define SYSCLK_SRC_FLL1 0x0C +#define SYSCLK_SRC_FLL2 0x0D + +/* See datasheet Table 4-69: Device ID */ +#define CS47L63_DEVID 0x47A63 + +#endif diff --git a/dts/bindings/sound/cirrus,cs47l63.yaml b/dts/bindings/audio/cirrus,cs47l63.yaml similarity index 100% rename from dts/bindings/sound/cirrus,cs47l63.yaml rename to dts/bindings/audio/cirrus,cs47l63.yaml diff --git a/samples/drivers/i2s/i2s_codec/boards/nrf5340_audio_dk_nrf5340_cpuapp.overlay b/samples/drivers/i2s/i2s_codec/boards/nrf5340_audio_dk_nrf5340_cpuapp.overlay new file mode 100644 index 0000000000000..c5150e1625ce5 --- /dev/null +++ b/samples/drivers/i2s/i2s_codec/boards/nrf5340_audio_dk_nrf5340_cpuapp.overlay @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2025 Titouan Christophe + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + i2s-codec-tx = &i2s0; + }; +}; + +audio_codec: &cs47l63 {};