diff --git a/arch/arm/boot/dts/overlays/Makefile b/arch/arm/boot/dts/overlays/Makefile index d4f31b76931d69..e859ed32e2d713 100644 --- a/arch/arm/boot/dts/overlays/Makefile +++ b/arch/arm/boot/dts/overlays/Makefile @@ -15,6 +15,7 @@ endif dtbo-$(RPI_DT_OVERLAYS) += adau1977-adc.dtbo dtbo-$(RPI_DT_OVERLAYS) += ads1015.dtbo dtbo-$(RPI_DT_OVERLAYS) += ads7846.dtbo +dtbo-$(RPI_DT_OVERLAYS) += akkordion-es9023-audio.dtbo dtbo-$(RPI_DT_OVERLAYS) += akkordion-iqdacplus.dtbo dtbo-$(RPI_DT_OVERLAYS) += at86rf233.dtbo dtbo-$(RPI_DT_OVERLAYS) += audioinjector-wm8731-audio.dtbo @@ -25,15 +26,18 @@ dtbo-$(RPI_DT_OVERLAYS) += dpi24.dtbo dtbo-$(RPI_DT_OVERLAYS) += dwc-otg.dtbo dtbo-$(RPI_DT_OVERLAYS) += dwc2.dtbo dtbo-$(RPI_DT_OVERLAYS) += enc28j60.dtbo +dtbo-$(RPI_DT_OVERLAYS) += es9023-audio.dtbo dtbo-$(RPI_DT_OVERLAYS) += gpio-ir.dtbo dtbo-$(RPI_DT_OVERLAYS) += gpio-poweroff.dtbo dtbo-$(RPI_DT_OVERLAYS) += hifiberry-amp.dtbo dtbo-$(RPI_DT_OVERLAYS) += hifiberry-dac.dtbo dtbo-$(RPI_DT_OVERLAYS) += hifiberry-dacplus.dtbo +dtbo-$(RPI_DT_OVERLAYS) += hifiberry-dacpluslight-es9023-audio.dtbo dtbo-$(RPI_DT_OVERLAYS) += hifiberry-digi.dtbo dtbo-$(RPI_DT_OVERLAYS) += hifiberry-digi-pro.dtbo dtbo-$(RPI_DT_OVERLAYS) += hy28a.dtbo dtbo-$(RPI_DT_OVERLAYS) += hy28b.dtbo +dtbo-$(RPI_DT_OVERLAYS) += i-sabre-dac-es9023-audio.dtbo dtbo-$(RPI_DT_OVERLAYS) += i2c-gpio.dtbo dtbo-$(RPI_DT_OVERLAYS) += i2c-mux.dtbo dtbo-$(RPI_DT_OVERLAYS) += i2c-pwm-pca9685a.dtbo @@ -48,6 +52,7 @@ dtbo-$(RPI_DT_OVERLAYS) += iqaudio-digi-wm8804-audio.dtbo dtbo-$(RPI_DT_OVERLAYS) += justboom-dac.dtbo dtbo-$(RPI_DT_OVERLAYS) += justboom-digi.dtbo dtbo-$(RPI_DT_OVERLAYS) += lirc-rpi.dtbo +dtbo-$(RPI_DT_OVERLAYS) += mamboberry-dacplus-es9023-audio.dtbo dtbo-$(RPI_DT_OVERLAYS) += mcp23017.dtbo dtbo-$(RPI_DT_OVERLAYS) += mcp2515-can0.dtbo dtbo-$(RPI_DT_OVERLAYS) += mcp2515-can1.dtbo diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README index 5e103331e50604..6e48fff33efbf5 100644 --- a/arch/arm/boot/dts/overlays/README +++ b/arch/arm/boot/dts/overlays/README @@ -215,6 +215,26 @@ Params: cs SPI bus Chip Select (default 1) www.kernel.org/doc/Documentation/devicetree/bindings/input/ads7846.txt +Name: akkordion-es9023-audio +Info: Configures the Digital Dreamtime Akkordion Music Player (with ESS Sabre + ES9023 DAC). +Load: dtoverlay=akkordion-es9023-audio, +Params: 384k Instructs the es9023 codec driver to support + 352k8 and 384k sample rates. + bclk_ratio_int_div Use bclk_ratio=50 for 16/24bps and + bclk_ratio=100 for 32bps media when sample + rate is a multiple of 8kHz and less than + 192kHz. Which causes the selection of the 19M2 + OSC as the parent for the PCM clock with an + integer divider, rather than PLLD with + fractional divider and MASH noise shaping. + card_name Override the default, "Akkordion", card name. + dai_name Override the default, "Akkordion DAC", + dai name. + dai_stream_name Override the default, "Akkordion DAC HiFi", + dai stream name. + + Name: akkordion-iqdacplus Info: Configures the Digital Dreamtime Akkordion Music Player (based on the OEM IQAudIO DAC+ or DAC Zero module). @@ -314,6 +334,24 @@ Params: int_pin GPIO used for INT (default 25) speed SPI bus speed (default 12000000) +Name: es9023-audio +Info: Configures a generic board or HAT using ESS Sabre ES9023 DAC +Load: dtoverlay=es9023-audio, +Params: 384k Instructs the es9023 codec driver to support + 352k8 and 384k sample rates. + bclk_ratio_int_div Use bclk_ratio=50 for 16/24bps and + bclk_ratio=100 for 32bps media when sample + rate is a multiple of 8kHz and less than + 192kHz. Which causes the selection of the 19M2 + OSC as the parent for the PCM clock with an + integer divider, rather than PLLD with + fractional divider and MASH noise shaping. + card_name Override the default, "es9023", card name. + dai_name Override the default, "ES9023 DAC" dai name. + dai_stream_name Override the default, "ES9023 DAC HiFi", + dai stream name. + + Name: gpio-ir Info: Use GPIO pin as rc-core style infrared receiver input. The rc-core- based gpio_ir_recv driver maps received keys directly to a @@ -376,6 +414,26 @@ Params: 24db_digital_gain Allow gain to be applied via the PCM512x codec master for bit clock and frame clock. +Name: hifiberry-dacpluslight-es9023-audio +Info: Configures the HiFiBerry DAC+ Light audio card +Load: dtoverlay=hifiberry-dacpluslight-es9023-audio, +Params: 384k Instructs the es9023 codec driver to support + 352k8 and 384k sample rates. + bclk_ratio_int_div Use bclk_ratio=50 for 16/24bps and + bclk_ratio=100 for 32bps media when sample + rate is a multiple of 8kHz and less than + 192kHz. Which causes the selection of the 19M2 + OSC as the parent for the PCM clock with an + integer divider, rather than PLLD with + fractional divider and MASH noise shaping. + card_name Override the default, "snd_rpi_hifiberry_dac", + card name. + dai_name Override the default, "HifiBerry DAC", + dai name. + dai_stream_name Override the default, "HifiBerry DAC HiFi", + dai stream name. + + Name: hifiberry-digi Info: Configures the HifiBerry Digi and Digi+ audio card Load: dtoverlay=hifiberry-digi @@ -426,6 +484,24 @@ Params: speed Display SPI bus speed ledgpio GPIO used to control backlight +Name: i-sabre-dac-es9023-audio +Info: Configures the Audiophonics I-Sabre DAC +Load: dtoverlay=i-sabre-dac-es9023-audio, +Params: 384k Instructs the es9023 codec driver to support + 352k8 and 384k sample rates. + bclk_ratio_int_div Use bclk_ratio=50 for 16/24bps and + bclk_ratio=100 for 32bps media when sample + rate is a multiple of 8kHz and less than + 192kHz. Which causes the selection of the 19M2 + OSC as the parent for the PCM clock with an + integer divider, rather than PLLD with + fractional divider and MASH noise shaping. + card_name Override the default, "ISabre", card name. + dai_name Override the default, "ISabre DAC", dai name. + dai_stream_name Override the default, "ISabre DAC HiFi", + dai stream name. + + Name: i2c-gpio Info: Adds support for software i2c controller on gpio pins Load: dtoverlay=i2c-gpio,= @@ -619,6 +695,25 @@ Params: gpio_out_pin GPIO for output (default "17") (default "off") +Name: mamboberry-dacplus-es9023-audio +Info: Configures the Collybia Mamboberry HiFi DAC+ +Load: dtoverlay=mamboberry-dacplus-es9023-audio, +Params: 384k Instructs the es9023 codec driver to support + 352k8 and 384k sample rates. + bclk_ratio_int_div Use bclk_ratio=50 for 16/24bps and + bclk_ratio=100 for 32bps media when sample + rate is a multiple of 8kHz and less than + 192kHz. Which causes the selection of the 19M2 + OSC as the parent for the PCM clock with an + integer divider, rather than PLLD with + fractional divider and MASH noise shaping. + card_name Override the default, "Mamboberry", card name. + dai_name Override the default, "Mamboberry DAC+", + dai name. + dai_stream_name Override the default, "Mamboberry DAC+ HiFi", + dai stream name. + + Name: mcp23017 Info: Configures the MCP23017 I2C GPIO expander Load: dtoverlay=mcp23017,= diff --git a/arch/arm/boot/dts/overlays/akkordion-es9023-audio-overlay.dts b/arch/arm/boot/dts/overlays/akkordion-es9023-audio-overlay.dts new file mode 100644 index 00000000000000..af9a3bd79e50f1 --- /dev/null +++ b/arch/arm/boot/dts/overlays/akkordion-es9023-audio-overlay.dts @@ -0,0 +1,57 @@ +// Definitions for Digital Dreamtime Akkordion using ESS Sabre ES9023 DAC +/dts-v1/; +/plugin/; + +/ { + compatible = "brcm,bcm2708"; + + fragment@0 { + target = <&i2s>; + __overlay__ { + status = "okay"; + }; + }; + + fragment@1 { + target-path = "/"; + __overlay__ { + es9023_codec: es9023-codec { + #sound-dai-cells = <0>; + compatible = "ess,es9023"; + status = "okay"; + }; + }; + }; + + fragment@2 { + target = <&sound>; + es9023_dac: __overlay__ { + compatible = "digitaldreamtime,es9023-akkordion-dac"; + /* + * These are the default names that will be + * applied by the es9023-dac machine driver + * based on the compatible parameter. + * + * es9023-dac,card-name = "Akkordion" + * es9023-dac,dai-name = "Akkordion DAC"; + * es9023-dac,dai-stream-name = "Akkordion DAC HiFi"; + */ + status = "okay"; + es9023-dac,cpu { + sound-dai = <&i2s>; + }; + es9023-dac,codec { + sound-dai = <&es9023_codec>; + }; + }; + }; + + __overrides__ { + 384k = <&es9023_codec>,"es9023,384k?"; + bclk_ratio_int_div = + <&es9023_dac>,"es9023-dac,bclk-ratio-int-div?"; + card_name = <&es9023_dac>,"es9023-dac,card-name"; + dai_name = <&es9023_dac>,"es9023-dac,dai-name"; + dai_stream_name = <&es9023_dac>,"es9023-dac,dai-stream-name"; + }; +}; diff --git a/arch/arm/boot/dts/overlays/es9023-audio-overlay.dts b/arch/arm/boot/dts/overlays/es9023-audio-overlay.dts new file mode 100644 index 00000000000000..842f9853bbcc45 --- /dev/null +++ b/arch/arm/boot/dts/overlays/es9023-audio-overlay.dts @@ -0,0 +1,64 @@ +// Definitions for a generic board or HAT using ESS Sabre ES9023 DAC + +// NB. Manufacturers of ES9023 DAC boards wishing to use their own ALSA names +// in preference to the generic names defined here, should copy this +// file, rename and edit it. Do not change the card, dai, and dai stream +// names being set below, in this generic es9023-audio overlay! +// (eg. akkordion-es9023-audio and i-sabre-dac-es9023-audio.) + +/dts-v1/; +/plugin/; + +/ { + compatible = "brcm,bcm2708"; + + fragment@0 { + target = <&i2s>; + __overlay__ { + status = "okay"; + }; + }; + + fragment@1 { + target-path = "/"; + __overlay__ { + es9023_codec: es9023-codec { + #sound-dai-cells = <0>; + compatible = "ess,es9023"; + status = "okay"; + }; + }; + }; + + fragment@2 { + target = <&sound>; + es9023_dac: __overlay__ { + compatible = "es9023-dac"; + /* + * These are the default names that will be + * applied by the es9023-dac machine driver + * based on the compatible parameter. + * + * es9023-dac,card-name = "es9023"; + * es9023-dac,dai-name = "ES9023 DAC"; + * es9023-dac,dai-stream-name = "ES9023 DAC HiFi"; + */ + status = "okay"; + es9023-dac,cpu { + sound-dai = <&i2s>; + }; + es9023-dac,codec { + sound-dai = <&es9023_codec>; + }; + }; + }; + + __overrides__ { + 384k = <&es9023_codec>,"es9023,384k?"; + bclk_ratio_int_div = + <&es9023_dac>,"es9023-dac,bclk-ratio-int-div?"; + card_name = <&es9023_dac>,"es9023-dac,card-name"; + dai_name = <&es9023_dac>,"es9023-dac,dai-name"; + dai_stream_name = <&es9023_dac>,"es9023-dac,dai-stream-name"; + }; +}; diff --git a/arch/arm/boot/dts/overlays/hifiberry-dacpluslight-es9023-audio-overlay.dts b/arch/arm/boot/dts/overlays/hifiberry-dacpluslight-es9023-audio-overlay.dts new file mode 100644 index 00000000000000..71d6d294579973 --- /dev/null +++ b/arch/arm/boot/dts/overlays/hifiberry-dacpluslight-es9023-audio-overlay.dts @@ -0,0 +1,57 @@ +// Definitions for HiFiBerry DAC+ Light using ESS Sabre ES9023 DAC +/dts-v1/; +/plugin/; + +/ { + compatible = "brcm,bcm2708"; + + fragment@0 { + target = <&i2s>; + __overlay__ { + status = "okay"; + }; + }; + + fragment@1 { + target-path = "/"; + __overlay__ { + es9023_codec: es9023-codec { + #sound-dai-cells = <0>; + compatible = "ess,es9023"; + status = "okay"; + }; + }; + }; + + fragment@2 { + target = <&sound>; + es9023_dac: __overlay__ { + compatible = "hifiberry,es9023-dacpluslight"; + /* + * These are the default names that will be + * applied by the es9023-dac machine driver + * based on the compatible parameter. + * + * es9023-dac,card-name = "snd_rpi_hifiberry_dac"; + * es9023-dac,dai-name = "HifiBerry DAC"; + * es9023-dac,dai-stream-name = "HifiBerry DAC HiFi"; + */ + status = "okay"; + es9023-dac,cpu { + sound-dai = <&i2s>; + }; + es9023-dac,codec { + sound-dai = <&es9023_codec>; + }; + }; + }; + + __overrides__ { + 384k = <&es9023_codec>,"es9023,384k?"; + bclk_ratio_int_div = + <&es9023_dac>,"es9023-dac,bclk-ratio-int-div?"; + card_name = <&es9023_dac>,"es9023-dac,card-name"; + dai_name = <&es9023_dac>,"es9023-dac,dai-name"; + dai_stream_name = <&es9023_dac>,"es9023-dac,dai-stream-name"; + }; +}; diff --git a/arch/arm/boot/dts/overlays/i-sabre-dac-es9023-audio-overlay.dts b/arch/arm/boot/dts/overlays/i-sabre-dac-es9023-audio-overlay.dts new file mode 100644 index 00000000000000..9a16dcc53b8d0d --- /dev/null +++ b/arch/arm/boot/dts/overlays/i-sabre-dac-es9023-audio-overlay.dts @@ -0,0 +1,57 @@ +// Definitions for Audiophonics I-Sabre DAC using ESS Sabre ES9023 DAC +/dts-v1/; +/plugin/; + +/ { + compatible = "brcm,bcm2708"; + + fragment@0 { + target = <&i2s>; + __overlay__ { + status = "okay"; + }; + }; + + fragment@1 { + target-path = "/"; + __overlay__ { + es9023_codec: es9023-codec { + #sound-dai-cells = <0>; + compatible = "ess,es9023"; + status = "okay"; + }; + }; + }; + + fragment@2 { + target = <&sound>; + es9023_dac: __overlay__ { + compatible = "audiphonics,es9023-i-sabre-dac"; + /* + * These are the default names that will be + * applied by the es9023-dac machine driver + * based on the compatible parameter. + * + * es9023-dac,card-name = "ISabre"; + * es9023-dac,dai-name = "ISabre DAC"; + * es9023-dac,dai-stream-name = "ISabre DAC HiFi"; + */ + status = "okay"; + es9023-dac,cpu { + sound-dai = <&i2s>; + }; + es9023-dac,codec { + sound-dai = <&es9023_codec>; + }; + }; + }; + + __overrides__ { + 384k = <&es9023_codec>,"es9023,384k?"; + bclk_ratio_int_div = + <&es9023_dac>,"es9023-dac,bclk-ratio-int-div?"; + card_name = <&es9023_dac>,"es9023-dac,card-name"; + dai_name = <&es9023_dac>,"es9023-dac,dai-name"; + dai_stream_name = <&es9023_dac>,"es9023-dac,dai-stream-name"; + }; +}; diff --git a/arch/arm/boot/dts/overlays/mamboberry-dacplus-es9023-audio-overlay.dts b/arch/arm/boot/dts/overlays/mamboberry-dacplus-es9023-audio-overlay.dts new file mode 100644 index 00000000000000..047ee2daa71f01 --- /dev/null +++ b/arch/arm/boot/dts/overlays/mamboberry-dacplus-es9023-audio-overlay.dts @@ -0,0 +1,57 @@ +// Definitions for Collybia MamboBerry HiFi DAC+ using ESS Sabre ES9023 DAC +/dts-v1/; +/plugin/; + +/ { + compatible = "brcm,bcm2708"; + + fragment@0 { + target = <&i2s>; + __overlay__ { + status = "okay"; + }; + }; + + fragment@1 { + target-path = "/"; + __overlay__ { + es9023_codec: es9023-codec { + #sound-dai-cells = <0>; + compatible = "ess,es9023"; + status = "okay"; + }; + }; + }; + + fragment@2 { + target = <&sound>; + es9023_dac: __overlay__ { + compatible = "collybia,es9023-mamboberry-dacplus"; + /* + * These are the default names that will be + * applied by the es9023-dac machine driver + * based on the compatible parameter. + * + * es9023-dac,card-name = "Mamboberry"; + * es9023-dac,dai-name = "Mamboberry DAC+"; + * es9023-dac,dai-stream-name = "Mamboberry DAC+ HiFi"; + */ + status = "okay"; + es9023-dac,cpu { + sound-dai = <&i2s>; + }; + es9023-dac,codec { + sound-dai = <&es9023_codec>; + }; + }; + }; + + __overrides__ { + 384k = <&es9023_codec>,"es9023,384k?"; + bclk_ratio_int_div = + <&es9023_dac>,"es9023-dac,bclk-ratio-int-div?"; + card_name = <&es9023_dac>,"es9023-dac,card-name"; + dai_name = <&es9023_dac>,"es9023-dac,dai-name"; + dai_stream_name = <&es9023_dac>,"es9023-dac,dai-stream-name"; + }; +}; diff --git a/arch/arm/configs/bcm2709_defconfig b/arch/arm/configs/bcm2709_defconfig index fafe9d3df0075f..a2babfb9327a74 100644 --- a/arch/arm/configs/bcm2709_defconfig +++ b/arch/arm/configs/bcm2709_defconfig @@ -860,6 +860,7 @@ CONFIG_SND_USB_CAIAQ_INPUT=y CONFIG_SND_USB_6FIRE=m CONFIG_SND_SOC=m CONFIG_SND_BCM2835_SOC_I2S=m +CONFIG_SND_BCM2708_SOC_ES9023_DAC=m CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI=m diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig index b1310f6af34296..8b98d2eb07b913 100644 --- a/arch/arm/configs/bcmrpi_defconfig +++ b/arch/arm/configs/bcmrpi_defconfig @@ -852,6 +852,7 @@ CONFIG_SND_USB_CAIAQ_INPUT=y CONFIG_SND_USB_6FIRE=m CONFIG_SND_SOC=m CONFIG_SND_BCM2835_SOC_I2S=m +CONFIG_SND_BCM2708_SOC_ES9023_DAC=m CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC=m CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS=m CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI=m diff --git a/sound/soc/bcm/Kconfig b/sound/soc/bcm/Kconfig index 8873fd8adce1d1..0891a4e0d9a80c 100644 --- a/sound/soc/bcm/Kconfig +++ b/sound/soc/bcm/Kconfig @@ -8,6 +8,15 @@ config SND_BCM2835_SOC_I2S the BCM2835 I2S interface. You will also need to select the audio interfaces to support below. +config SND_BCM2708_SOC_ES9023_DAC + tristate "Support for ESS Sabre ES9023 DAC" + depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S + select SND_SOC_ES9023 + help + Say Y or M if you want to add support for boards using the ESS Sabre + ES9023 DAC. eg. Audiophonics I-Sabre, Collybia MamboBerry HiFi DAC+, + Digital Dreamtime Akkordion and HiFiBerry DAC+ Light. + config SND_BCM2708_SOC_HIFIBERRY_DAC tristate "Support for HifiBerry DAC" depends on SND_BCM2708_SOC_I2S || SND_BCM2835_SOC_I2S diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile index 17f70f95132223..343dd1f1a3588f 100644 --- a/sound/soc/bcm/Makefile +++ b/sound/soc/bcm/Makefile @@ -5,6 +5,7 @@ obj-$(CONFIG_SND_BCM2835_SOC_I2S) += snd-soc-bcm2835-i2s.o # BCM2708 Machine Support snd-soc-adau1977-adc-objs := adau1977-adc.o +snd-soc-es9023-dac-objs := es9023_dac.o snd-soc-hifiberry-dac-objs := hifiberry_dac.o snd-soc-hifiberry-dacplus-objs := hifiberry_dacplus.o snd-soc-hifiberry-digi-objs := hifiberry_digi.o @@ -21,6 +22,7 @@ snd-soc-digidac1-soundcard-objs := digidac1-soundcard.o snd-soc-dionaudio-loco-objs := dionaudio_loco.o obj-$(CONFIG_SND_BCM2708_SOC_ADAU1977_ADC) += snd-soc-adau1977-adc.o +obj-$(CONFIG_SND_BCM2708_SOC_ES9023_DAC) += snd-soc-es9023-dac.o obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DAC) += snd-soc-hifiberry-dac.o obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DACPLUS) += snd-soc-hifiberry-dacplus.o obj-$(CONFIG_SND_BCM2708_SOC_HIFIBERRY_DIGI) += snd-soc-hifiberry-digi.o diff --git a/sound/soc/bcm/es9023_dac.c b/sound/soc/bcm/es9023_dac.c new file mode 100644 index 00000000000000..042453e212f19c --- /dev/null +++ b/sound/soc/bcm/es9023_dac.c @@ -0,0 +1,279 @@ +/* + * ASoC Machine Driver for ESS Sabre ES9023 DAC + * + * Author: Clive Messer + * Copyright 2014 + * + * based on the HiFiBerry DAC driver + * by Florian Meier Copyright 2013 + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include + +struct es9023_dac_priv { + bool bclk_ratio_int_div; + struct snd_soc_dai_link dai; + struct snd_soc_card card; +}; + +struct es9023_dac_variant { + char *compatible; + char *card_name; + char *dai_name; + char *dai_stream_name; +}; + +#define COMPAT_GENERIC "es9023-dac" +#define COMPAT_ISABRE "audiphonics,es9023-i-sabre-dac" +#define COMPAT_MAMBO "collybia,es9023-mamboberry-dacplus" +#define COMPAT_AKK "digitaldreamtime,es9023-akkordion-dac" +#define COMPAT_HBLIGHT "hifiberry,es9023-dacpluslight" + +static const struct es9023_dac_variant es9023_dac_variants[] = { + { /* generic */ + .compatible = COMPAT_GENERIC, + .card_name = "ES9023", + .dai_name = "ES9023 DAC", + .dai_stream_name = "ES9023 DAC HiFi", + }, + { /* AudioPhonics ISabre */ + .compatible = COMPAT_ISABRE, + .card_name = "ISabre", + .dai_name = "ISabre DAC", + .dai_stream_name = "ISabre DAC HiFi", + }, + { /* MamboBerry DAC+ */ + .compatible = COMPAT_MAMBO, + .card_name = "Mamboberry", + .dai_name = "Mamboberry DAC", + .dai_stream_name = "Mamboberry DAC HiFi", + }, + { /* Digital Dreamtime Akkordion */ + .compatible = COMPAT_AKK, + .card_name = "Akkordion", + .dai_name = "Akkordion DAC", + .dai_stream_name = "Akkordion DAC HiFi", + }, + { /* HiFiBerry DAC+ Light */ + .compatible = COMPAT_HBLIGHT, + .card_name = "snd_rpi_hifiberry_dac", + .dai_name = "HifiBerry DAC", + .dai_stream_name = "HifiBerry DAC HiFi", + }, +}; + +static const struct es9023_dac_variant *snd_rpi_es9023_dac_get_variant( + struct device_node *np) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(es9023_dac_variants); i++) { + if (of_device_is_compatible(np, + es9023_dac_variants[i].compatible)) + return &es9023_dac_variants[i]; + } + + return &es9023_dac_variants[0]; +} + +static int snd_rpi_es9023_dac_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct es9023_dac_priv *priv = snd_soc_card_get_drvdata(rtd->card); + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + + snd_pcm_format_t format = params_format(params); + unsigned int sample_bits = snd_pcm_format_width(format); + unsigned int sample_freq = params_rate(params); + unsigned int channels = params_channels(params); + unsigned int physical_bits = + snd_pcm_format_physical_width(format); + unsigned int bclk_ratio = sample_bits * channels; + + if (priv->bclk_ratio_int_div && channels == 2 && + sample_freq < 192000 && sample_freq % 8000 == 0) { + if (sample_bits == 16 || sample_bits == 24) + bclk_ratio = 50; + else if (sample_bits == 32) + bclk_ratio = 100; + } + + dev_dbg(rtd->dev, "%s: frequency=%u, format=%s, sample_bits=%u, " + "physical_bits=%u, channels=%u. Setting bclk_ratio=%u.\n", + __func__, sample_freq, snd_pcm_format_name(format), + sample_bits, physical_bits, channels, bclk_ratio); + + return snd_soc_dai_set_bclk_ratio(cpu_dai, bclk_ratio); +} + +/* machine stream operations */ +static struct snd_soc_ops snd_rpi_es9023_dac_ops = { + .hw_params = snd_rpi_es9023_dac_hw_params, +}; + +static int snd_rpi_es9023_dac_sub_parse_of(struct device_node *np, + struct device_node **p_node, const char **name) +{ + struct of_phandle_args args; + int ret; + + ret = of_parse_phandle_with_args(np, "sound-dai", + "#sound-dai-cells", 0, &args); + if (ret) + return ret; + + *p_node = args.np; + + ret = snd_soc_of_get_dai_name(np, name); + if (ret < 0) + return ret; + + return 0; +} + +static int snd_rpi_es9023_dac_probe(struct platform_device *pdev) +{ + char prop[128]; + char *prefix = "es9023-dac,"; + const struct es9023_dac_variant *variant; + struct device_node *codec_np, *cpu_np, *np = pdev->dev.of_node; + struct es9023_dac_priv *priv; + int ret = 0; + + snprintf(prop, sizeof(prop), "%scpu", prefix); + cpu_np = of_get_child_by_name(np, prop); + if (!cpu_np) { + dev_err(&pdev->dev, "%s: failed to find %s DT node\n", + __func__, prop); + ret = -EINVAL; + goto cpu_end; + } + + snprintf(prop, sizeof(prop), "%scodec", prefix); + codec_np = of_get_child_by_name(np, prop); + if (!codec_np) { + dev_err(&pdev->dev, "%s: failed to find %s DT node\n", + __func__, prop); + ret = -EINVAL; + goto end; + } + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) { + ret = -ENOMEM; + goto end; + } + + /* priv->dai.cpu_dai_name = "bcm2708-i2s.0"; */ + ret = snd_rpi_es9023_dac_sub_parse_of(cpu_np, + &priv->dai.cpu_of_node, + &priv->dai.cpu_dai_name); + if (ret != 0) { + dev_err(&pdev->dev, "%s: failed to get cpu dai name: %d\n", + __func__, ret); + goto end; + } + priv->dai.cpu_dai_name = NULL; + + /* priv->dai.platform_name = "bcm2708-i2s.0"; */ + priv->dai.platform_of_node = priv->dai.cpu_of_node; + + /* priv->dai.codec_name = "es9023-codec"; */ + /* priv->dai.codec_dai_name = "es9023-hifi"; */ + ret = snd_rpi_es9023_dac_sub_parse_of(codec_np, + &priv->dai.codec_of_node, + &priv->dai.codec_dai_name); + if (ret != 0) { + dev_err(&pdev->dev, "%s: failed to get codec dai name: %d\n", + __func__, ret); + goto end; + } + + priv->dai.dai_fmt = SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS; + + priv->dai.ops = &snd_rpi_es9023_dac_ops; + + priv->card.dai_link = &priv->dai; + priv->card.dev = &pdev->dev; + priv->card.num_links = 1; + priv->card.owner = THIS_MODULE; + + snprintf(prop, sizeof(prop), "%sbclk-ratio-int-div", prefix); + priv->bclk_ratio_int_div = of_property_read_bool(np, prop); + + variant = snd_rpi_es9023_dac_get_variant(np); + + snprintf(prop, sizeof(prop), "%scard-name", prefix); + if (of_property_read_string(np, prop, &priv->card.name)) + priv->card.name = variant->card_name; + + snprintf(prop, sizeof(prop), "%sdai-name", prefix); + if (of_property_read_string(np, prop, &priv->dai.name)) + priv->dai.name = variant->dai_name; + + snprintf(prop, sizeof(prop), "%sdai-stream-name", prefix); + if (of_property_read_string(np, prop, &priv->dai.stream_name)) + priv->dai.stream_name = variant->dai_stream_name; + + platform_set_drvdata(pdev, &priv->card); + snd_soc_card_set_drvdata(&priv->card, priv); + + ret = devm_snd_soc_register_card(&pdev->dev, &priv->card); + if (ret) + dev_err(&pdev->dev, "%s: snd_soc_register_card failed: %d\n", + __func__, ret); + +end: + of_node_put(codec_np); +cpu_end: + of_node_put(cpu_np); + + return ret; +} + +static const struct of_device_id snd_rpi_es9023_dac_of_match[] = { + /* generic */ + { .compatible = COMPAT_GENERIC, }, + /* Manufacturer compatible definitions BELOW! */ + { .compatible = COMPAT_ISABRE, }, + { .compatible = COMPAT_MAMBO, }, + { .compatible = COMPAT_AKK, }, + { .compatible = COMPAT_HBLIGHT, }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, snd_rpi_es9023_dac_of_match); + +static struct platform_driver snd_rpi_es9023_dac_driver = { + .driver = { + .name = "snd-es9023-dac", + .owner = THIS_MODULE, + .of_match_table = snd_rpi_es9023_dac_of_match, + }, + .probe = snd_rpi_es9023_dac_probe, +}; + +module_platform_driver(snd_rpi_es9023_dac_driver); + +MODULE_AUTHOR("Clive Messer "); +MODULE_DESCRIPTION("ASoC ESS Sabre ES9023 card driver"); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index fe32ccaaaebe9c..e31144d96c458c 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -65,6 +65,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_BT_SCO select SND_SOC_ES8328_SPI if SPI_MASTER select SND_SOC_ES8328_I2C if I2C + select SND_SOC_ES9023 select SND_SOC_GTM601 select SND_SOC_ICS43432 select SND_SOC_ISABELLE if I2C @@ -468,6 +469,9 @@ config SND_SOC_ES8328_SPI tristate select SND_SOC_ES8328 +config SND_SOC_ES9023 + tristate "ESS Sabre ES9023 CODEC" + config SND_SOC_GTM601 tristate 'GTM601 UMTS modem audio codec' diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index dbb213da41a16e..3750265e9aa00a 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -58,6 +58,7 @@ snd-soc-dmic-objs := dmic.o snd-soc-es8328-objs := es8328.o snd-soc-es8328-i2c-objs := es8328-i2c.o snd-soc-es8328-spi-objs := es8328-spi.o +snd-soc-es9023-objs := es9023.o snd-soc-gtm601-objs := gtm601.o snd-soc-ics43432-objs := ics43432.o snd-soc-isabelle-objs := isabelle.o @@ -256,6 +257,7 @@ obj-$(CONFIG_SND_SOC_DMIC) += snd-soc-dmic.o obj-$(CONFIG_SND_SOC_ES8328) += snd-soc-es8328.o obj-$(CONFIG_SND_SOC_ES8328_I2C)+= snd-soc-es8328-i2c.o obj-$(CONFIG_SND_SOC_ES8328_SPI)+= snd-soc-es8328-spi.o +obj-$(CONFIG_SND_SOC_ES9023) += snd-soc-es9023.o obj-$(CONFIG_SND_SOC_GTM601) += snd-soc-gtm601.o obj-$(CONFIG_SND_SOC_ICS43432) += snd-soc-ics43432.o obj-$(CONFIG_SND_SOC_ISABELLE) += snd-soc-isabelle.o diff --git a/sound/soc/codecs/es9023.c b/sound/soc/codecs/es9023.c new file mode 100644 index 00000000000000..0268516fa51874 --- /dev/null +++ b/sound/soc/codecs/es9023.c @@ -0,0 +1,141 @@ +/* + * Driver for the ESS ES9023 codec + * + * Author: Clive Messer + * Copyright 2014 + * + * based on the PCM1794A codec driver + * by Florian Meier Copyright 2013 + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + + +#include +#include +#include + +#include + +struct es9023_priv { + bool rates_384k; +}; + +static const u32 es9023_rates[] = { + 32000, 44100, 48000, 88200, 96000, 176400, 192000, +}; + +static const struct snd_pcm_hw_constraint_list es9023_constraint_rates = { + .count = ARRAY_SIZE(es9023_rates), + .list = es9023_rates, +}; + +static const u32 es9023_8x_rates[] = { + 32000, 44100, 48000, 88200, 96000, 176400, 192000, 352800, 384000, +}; + +static const struct snd_pcm_hw_constraint_list es9023_8x_constraint_rates = { + .count = ARRAY_SIZE(es9023_8x_rates), + .list = es9023_8x_rates, +}; + +static int es9023_dai_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_codec *codec = dai->codec; + struct es9023_priv *priv = snd_soc_codec_get_drvdata(codec); + int ret; + + + dev_dbg(codec->dev, "%s: set rates (32k-%s) constraint\n", __func__, + ((priv->rates_384k) ? "384k" : "192k")); + + ret = snd_pcm_hw_constraint_list(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_RATE, + ((priv->rates_384k) + ? &es9023_8x_constraint_rates + : &es9023_constraint_rates)); + if (ret != 0) { + dev_err(codec->dev, "%s: Failed to set rates constraint: %d\n", + __func__, ret); + return ret; + } + + return 0; +} + +static const struct snd_soc_dai_ops es9023_dai_ops = { + .startup = es9023_dai_startup, +}; + +static struct snd_soc_dai_driver es9023_dai = { + .name = "es9023-hifi", + .playback = { + .stream_name = "Playback", + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_KNOT, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_3LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE + }, + .ops = &es9023_dai_ops, +}; + +static struct snd_soc_codec_driver soc_codec_dev_es9023; + +static int es9023_probe(struct platform_device *pdev) +{ + struct es9023_priv *priv; + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + +#ifdef CONFIG_OF + if (pdev->dev.of_node) + priv->rates_384k = of_property_read_bool(pdev->dev.of_node, + "es9023,384k"); +#endif + + dev_set_drvdata(&pdev->dev, priv); + + return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_es9023, + &es9023_dai, 1); +} + +static int es9023_remove(struct platform_device *pdev) +{ + snd_soc_unregister_codec(&pdev->dev); + return 0; +} + +static const struct of_device_id es9023_of_match[] = { + { .compatible = "ess,es9023", }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, es9023_of_match); + +static struct platform_driver es9023_codec_driver = { + .probe = es9023_probe, + .remove = es9023_remove, + .driver = { + .name = "es9023-codec", + .owner = THIS_MODULE, + .of_match_table = es9023_of_match, + }, +}; + +module_platform_driver(es9023_codec_driver); + +MODULE_AUTHOR("Clive Messer "); +MODULE_DESCRIPTION("ASoC ESS Sabre ES9023 codec driver"); +MODULE_LICENSE("GPL v2");