Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge remote-tracking branches 'asoc/topic/hisilicon', 'asoc/topic/iio', 'asoc/topic/max98373' and 'asoc/topic/max98926' into asoc-next

+3755 -35
+16
Documentation/ABI/testing/sysfs-bus-iio-dfsdm-adc-stm32
··· 1 + What: /sys/bus/iio/devices/iio:deviceX/in_voltage_spi_clk_freq 2 + KernelVersion: 4.14 3 + Contact: arnaud.pouliquen@st.com 4 + Description: 5 + For audio purpose only. 6 + Used by audio driver to set/get the spi input frequency. 7 + This is mandatory if DFSDM is slave on SPI bus, to 8 + provide information on the SPI clock frequency during runtime 9 + Notice that the SPI frequency should be a multiple of sample 10 + frequency to ensure the precision. 11 + if DFSDM input is SPI master 12 + Reading SPI clkout frequency, 13 + error on writing 14 + If DFSDM input is SPI Slave: 15 + Reading returns value previously set. 16 + Writing value before starting conversions.
+13
Documentation/devicetree/bindings/iio/adc/sigma-delta-modulator.txt
··· 1 + Device-Tree bindings for sigma delta modulator 2 + 3 + Required properties: 4 + - compatible: should be "ads1201", "sd-modulator". "sd-modulator" can be use 5 + as a generic SD modulator if modulator not specified in compatible list. 6 + - #io-channel-cells = <1>: See the IIO bindings section "IIO consumers". 7 + 8 + Example node: 9 + 10 + ads1202: adc@0 { 11 + compatible = "sd-modulator"; 12 + #io-channel-cells = <1>; 13 + };
+128
Documentation/devicetree/bindings/iio/adc/st,stm32-dfsdm-adc.txt
··· 1 + STMicroelectronics STM32 DFSDM ADC device driver 2 + 3 + 4 + STM32 DFSDM ADC is a sigma delta analog-to-digital converter dedicated to 5 + interface external sigma delta modulators to STM32 micro controllers. 6 + It is mainly targeted for: 7 + - Sigma delta modulators (motor control, metering...) 8 + - PDM microphones (audio digital microphone) 9 + 10 + It features up to 8 serial digital interfaces (SPI or Manchester) and 11 + up to 4 filters on stm32h7. 12 + 13 + Each child node match with a filter instance. 14 + 15 + Contents of a STM32 DFSDM root node: 16 + ------------------------------------ 17 + Required properties: 18 + - compatible: Should be "st,stm32h7-dfsdm". 19 + - reg: Offset and length of the DFSDM block register set. 20 + - clocks: IP and serial interfaces clocking. Should be set according 21 + to rcc clock ID and "clock-names". 22 + - clock-names: Input clock name "dfsdm" must be defined, 23 + "audio" is optional. If defined CLKOUT is based on the audio 24 + clock, else "dfsdm" is used. 25 + - #interrupt-cells = <1>; 26 + - #address-cells = <1>; 27 + - #size-cells = <0>; 28 + 29 + Optional properties: 30 + - spi-max-frequency: Requested only for SPI master mode. 31 + SPI clock OUT frequency (Hz). This clock must be set according 32 + to "clock" property. Frequency must be a multiple of the rcc 33 + clock frequency. If not, SPI CLKOUT frequency will not be 34 + accurate. 35 + 36 + Contents of a STM32 DFSDM child nodes: 37 + -------------------------------------- 38 + 39 + Required properties: 40 + - compatible: Must be: 41 + "st,stm32-dfsdm-adc" for sigma delta ADCs 42 + "st,stm32-dfsdm-dmic" for audio digital microphone. 43 + - reg: Specifies the DFSDM filter instance used. 44 + - interrupts: IRQ lines connected to each DFSDM filter instance. 45 + - st,adc-channels: List of single-ended channels muxed for this ADC. 46 + valid values: 47 + "st,stm32h7-dfsdm" compatibility: 0 to 7. 48 + - st,adc-channel-names: List of single-ended channel names. 49 + - st,filter-order: SinC filter order from 0 to 5. 50 + 0: FastSinC 51 + [1-5]: order 1 to 5. 52 + For audio purpose it is recommended to use order 3 to 5. 53 + - #io-channel-cells = <1>: See the IIO bindings section "IIO consumers". 54 + 55 + Required properties for "st,stm32-dfsdm-adc" compatibility: 56 + - io-channels: From common IIO binding. Used to pipe external sigma delta 57 + modulator or internal ADC output to DFSDM channel. 58 + This is not required for "st,stm32-dfsdm-pdm" compatibility as 59 + PDM microphone is binded in Audio DT node. 60 + 61 + Required properties for "st,stm32-dfsdm-pdm" compatibility: 62 + - #sound-dai-cells: Must be set to 0. 63 + - dma: DMA controller phandle and DMA request line associated to the 64 + filter instance (specified by the field "reg") 65 + - dma-names: Must be "rx" 66 + 67 + Optional properties: 68 + - st,adc-channel-types: Single-ended channel input type. 69 + - "SPI_R": SPI with data on rising edge (default) 70 + - "SPI_F": SPI with data on falling edge 71 + - "MANCH_R": manchester codec, rising edge = logic 0 72 + - "MANCH_F": manchester codec, falling edge = logic 1 73 + - st,adc-channel-clk-src: Conversion clock source. 74 + - "CLKIN": external SPI clock (CLKIN x) 75 + - "CLKOUT": internal SPI clock (CLKOUT) (default) 76 + - "CLKOUT_F": internal SPI clock divided by 2 (falling edge). 77 + - "CLKOUT_R": internal SPI clock divided by 2 (rising edge). 78 + 79 + - st,adc-alt-channel: Must be defined if two sigma delta modulator are 80 + connected on same SPI input. 81 + If not set, channel n is connected to SPI input n. 82 + If set, channel n is connected to SPI input n + 1. 83 + 84 + - st,filter0-sync: Set to 1 to synchronize with DFSDM filter instance 0. 85 + Used for multi microphones synchronization. 86 + 87 + Example of a sigma delta adc connected on DFSDM SPI port 0 88 + and a pdm microphone connected on DFSDM SPI port 1: 89 + 90 + ads1202: simple_sd_adc@0 { 91 + compatible = "ads1202"; 92 + #io-channel-cells = <1>; 93 + }; 94 + 95 + dfsdm: dfsdm@40017000 { 96 + compatible = "st,stm32h7-dfsdm"; 97 + reg = <0x40017000 0x400>; 98 + clocks = <&rcc DFSDM1_CK>; 99 + clock-names = "dfsdm"; 100 + #interrupt-cells = <1>; 101 + #address-cells = <1>; 102 + #size-cells = <0>; 103 + 104 + dfsdm_adc0: filter@0 { 105 + compatible = "st,stm32-dfsdm-adc"; 106 + #io-channel-cells = <1>; 107 + reg = <0>; 108 + interrupts = <110>; 109 + st,adc-channels = <0>; 110 + st,adc-channel-names = "sd_adc0"; 111 + st,adc-channel-types = "SPI_F"; 112 + st,adc-channel-clk-src = "CLKOUT"; 113 + io-channels = <&ads1202 0>; 114 + st,filter-order = <3>; 115 + }; 116 + dfsdm_pdm1: filter@1 { 117 + compatible = "st,stm32-dfsdm-dmic"; 118 + reg = <1>; 119 + interrupts = <111>; 120 + dmas = <&dmamux1 102 0x400 0x00>; 121 + dma-names = "rx"; 122 + st,adc-channels = <1>; 123 + st,adc-channel-names = "dmic1"; 124 + st,adc-channel-types = "SPI_R"; 125 + st,adc-channel-clk-src = "CLKOUT"; 126 + st,filter-order = <5>; 127 + }; 128 + }
+40
Documentation/devicetree/bindings/sound/max98373.txt
··· 1 + Maxim Integrated MAX98373 Speaker Amplifier 2 + 3 + This device supports I2C. 4 + 5 + Required properties: 6 + 7 + - compatible : "maxim,max98373" 8 + 9 + - reg : the I2C address of the device. 10 + 11 + Optional properties: 12 + 13 + - maxim,vmon-slot-no : slot number used to send voltage information 14 + or in inteleave mode this will be used as 15 + interleave slot. 16 + slot range : 0 ~ 15, Default : 0 17 + 18 + - maxim,imon-slot-no : slot number used to send current information 19 + slot range : 0 ~ 15, Default : 0 20 + 21 + - maxim,spkfb-slot-no : slot number used to send speaker feedback information 22 + slot range : 0 ~ 15, Default : 0 23 + 24 + - maxim,interleave-mode : For cases where a single combined channel 25 + for the I/V sense data is not sufficient, the device can also be configured 26 + to share a single data output channel on alternating frames. 27 + In this configuration, the current and voltage data will be frame interleaved 28 + on a single output channel. 29 + Boolean, define to enable the interleave mode, Default : false 30 + 31 + Example: 32 + 33 + codec: max98373@31 { 34 + compatible = "maxim,max98373"; 35 + reg = <0x31>; 36 + maxim,vmon-slot-no = <0>; 37 + maxim,imon-slot-no = <1>; 38 + maxim,spkfb-slot-no = <2>; 39 + maxim,interleave-mode; 40 + };
+51
Documentation/driver-api/iio/hw-consumer.rst
··· 1 + =========== 2 + HW consumer 3 + =========== 4 + An IIO device can be directly connected to another device in hardware. in this 5 + case the buffers between IIO provider and IIO consumer are handled by hardware. 6 + The Industrial I/O HW consumer offers a way to bond these IIO devices without 7 + software buffer for data. The implementation can be found under 8 + :file:`drivers/iio/buffer/hw-consumer.c` 9 + 10 + 11 + * struct :c:type:`iio_hw_consumer` — Hardware consumer structure 12 + * :c:func:`iio_hw_consumer_alloc` — Allocate IIO hardware consumer 13 + * :c:func:`iio_hw_consumer_free` — Free IIO hardware consumer 14 + * :c:func:`iio_hw_consumer_enable` — Enable IIO hardware consumer 15 + * :c:func:`iio_hw_consumer_disable` — Disable IIO hardware consumer 16 + 17 + 18 + HW consumer setup 19 + ================= 20 + 21 + As standard IIO device the implementation is based on IIO provider/consumer. 22 + A typical IIO HW consumer setup looks like this:: 23 + 24 + static struct iio_hw_consumer *hwc; 25 + 26 + static const struct iio_info adc_info = { 27 + .read_raw = adc_read_raw, 28 + }; 29 + 30 + static int adc_read_raw(struct iio_dev *indio_dev, 31 + struct iio_chan_spec const *chan, int *val, 32 + int *val2, long mask) 33 + { 34 + ret = iio_hw_consumer_enable(hwc); 35 + 36 + /* Acquire data */ 37 + 38 + ret = iio_hw_consumer_disable(hwc); 39 + } 40 + 41 + static int adc_probe(struct platform_device *pdev) 42 + { 43 + hwc = devm_iio_hw_consumer_alloc(&iio->dev); 44 + } 45 + 46 + More details 47 + ============ 48 + .. kernel-doc:: include/linux/iio/hw-consumer.h 49 + .. kernel-doc:: drivers/iio/buffer/industrialio-hw-consumer.c 50 + :export: 51 +
+1
Documentation/driver-api/iio/index.rst
··· 15 15 buffers 16 16 triggers 17 17 triggered-buffers 18 + hw-consumer
+37
drivers/iio/adc/Kconfig
··· 629 629 To compile this driver as a module, choose M here: the 630 630 module will be called spear_adc. 631 631 632 + config SD_ADC_MODULATOR 633 + tristate "Generic sigma delta modulator" 634 + depends on OF 635 + select IIO_BUFFER 636 + select IIO_TRIGGERED_BUFFER 637 + help 638 + Select this option to enables sigma delta modulator. This driver can 639 + support generic sigma delta modulators. 640 + 641 + This driver can also be built as a module. If so, the module 642 + will be called sd_adc_modulator. 643 + 632 644 config STM32_ADC_CORE 633 645 tristate "STMicroelectronics STM32 adc core" 634 646 depends on ARCH_STM32 || COMPILE_TEST ··· 667 655 668 656 This driver can also be built as a module. If so, the module 669 657 will be called stm32-adc. 658 + 659 + config STM32_DFSDM_CORE 660 + tristate "STMicroelectronics STM32 DFSDM core" 661 + depends on (ARCH_STM32 && OF) || COMPILE_TEST 662 + select REGMAP 663 + select REGMAP_MMIO 664 + help 665 + Select this option to enable the driver for STMicroelectronics 666 + STM32 digital filter for sigma delta converter. 667 + 668 + This driver can also be built as a module. If so, the module 669 + will be called stm32-dfsdm-core. 670 + 671 + config STM32_DFSDM_ADC 672 + tristate "STMicroelectronics STM32 dfsdm adc" 673 + depends on (ARCH_STM32 && OF) || COMPILE_TEST 674 + select STM32_DFSDM_CORE 675 + select REGMAP_MMIO 676 + select IIO_BUFFER_HW_CONSUMER 677 + help 678 + Select this option to support ADCSigma delta modulator for 679 + STMicroelectronics STM32 digital filter for sigma delta converter. 680 + 681 + This driver can also be built as a module. If so, the module 682 + will be called stm32-dfsdm-adc. 670 683 671 684 config STX104 672 685 tristate "Apex Embedded Systems STX104 driver"
+3
drivers/iio/adc/Makefile
··· 64 64 obj-$(CONFIG_SUN4I_GPADC) += sun4i-gpadc-iio.o 65 65 obj-$(CONFIG_STM32_ADC_CORE) += stm32-adc-core.o 66 66 obj-$(CONFIG_STM32_ADC) += stm32-adc.o 67 + obj-$(CONFIG_STM32_DFSDM_CORE) += stm32-dfsdm-core.o 68 + obj-$(CONFIG_STM32_DFSDM_ADC) += stm32-dfsdm-adc.o 67 69 obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o 68 70 obj-$(CONFIG_TI_ADC0832) += ti-adc0832.o 69 71 obj-$(CONFIG_TI_ADC084S021) += ti-adc084s021.o ··· 84 82 obj-$(CONFIG_VIPERBOARD_ADC) += viperboard_adc.o 85 83 xilinx-xadc-y := xilinx-xadc-core.o xilinx-xadc-events.o 86 84 obj-$(CONFIG_XILINX_XADC) += xilinx-xadc.o 85 + obj-$(CONFIG_SD_ADC_MODULATOR) += sd_adc_modulator.o
+68
drivers/iio/adc/sd_adc_modulator.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Generic sigma delta modulator driver 4 + * 5 + * Copyright (C) 2017, STMicroelectronics - All Rights Reserved 6 + * Author: Arnaud Pouliquen <arnaud.pouliquen@st.com>. 7 + */ 8 + 9 + #include <linux/iio/iio.h> 10 + #include <linux/iio/triggered_buffer.h> 11 + #include <linux/module.h> 12 + #include <linux/of_device.h> 13 + 14 + static const struct iio_info iio_sd_mod_iio_info; 15 + 16 + static const struct iio_chan_spec iio_sd_mod_ch = { 17 + .type = IIO_VOLTAGE, 18 + .indexed = 1, 19 + .scan_type = { 20 + .sign = 'u', 21 + .realbits = 1, 22 + .shift = 0, 23 + }, 24 + }; 25 + 26 + static int iio_sd_mod_probe(struct platform_device *pdev) 27 + { 28 + struct device *dev = &pdev->dev; 29 + struct iio_dev *iio; 30 + 31 + iio = devm_iio_device_alloc(dev, 0); 32 + if (!iio) 33 + return -ENOMEM; 34 + 35 + iio->dev.parent = dev; 36 + iio->dev.of_node = dev->of_node; 37 + iio->name = dev_name(dev); 38 + iio->info = &iio_sd_mod_iio_info; 39 + iio->modes = INDIO_BUFFER_HARDWARE; 40 + 41 + iio->num_channels = 1; 42 + iio->channels = &iio_sd_mod_ch; 43 + 44 + platform_set_drvdata(pdev, iio); 45 + 46 + return devm_iio_device_register(&pdev->dev, iio); 47 + } 48 + 49 + static const struct of_device_id sd_adc_of_match[] = { 50 + { .compatible = "sd-modulator" }, 51 + { .compatible = "ads1201" }, 52 + { } 53 + }; 54 + MODULE_DEVICE_TABLE(of, sd_adc_of_match); 55 + 56 + static struct platform_driver iio_sd_mod_adc = { 57 + .driver = { 58 + .name = "iio_sd_adc_mod", 59 + .of_match_table = of_match_ptr(sd_adc_of_match), 60 + }, 61 + .probe = iio_sd_mod_probe, 62 + }; 63 + 64 + module_platform_driver(iio_sd_mod_adc); 65 + 66 + MODULE_DESCRIPTION("Basic sigma delta modulator"); 67 + MODULE_AUTHOR("Arnaud Pouliquen <arnaud.pouliquen@st.com>"); 68 + MODULE_LICENSE("GPL v2");
+1205
drivers/iio/adc/stm32-dfsdm-adc.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * This file is the ADC part of the STM32 DFSDM driver 4 + * 5 + * Copyright (C) 2017, STMicroelectronics - All Rights Reserved 6 + * Author: Arnaud Pouliquen <arnaud.pouliquen@st.com>. 7 + */ 8 + 9 + #include <linux/dmaengine.h> 10 + #include <linux/dma-mapping.h> 11 + #include <linux/interrupt.h> 12 + #include <linux/iio/buffer.h> 13 + #include <linux/iio/hw-consumer.h> 14 + #include <linux/iio/iio.h> 15 + #include <linux/iio/sysfs.h> 16 + #include <linux/module.h> 17 + #include <linux/of_device.h> 18 + #include <linux/platform_device.h> 19 + #include <linux/regmap.h> 20 + #include <linux/slab.h> 21 + 22 + #include "stm32-dfsdm.h" 23 + 24 + #define DFSDM_DMA_BUFFER_SIZE (4 * PAGE_SIZE) 25 + 26 + /* Conversion timeout */ 27 + #define DFSDM_TIMEOUT_US 100000 28 + #define DFSDM_TIMEOUT (msecs_to_jiffies(DFSDM_TIMEOUT_US / 1000)) 29 + 30 + /* Oversampling attribute default */ 31 + #define DFSDM_DEFAULT_OVERSAMPLING 100 32 + 33 + /* Oversampling max values */ 34 + #define DFSDM_MAX_INT_OVERSAMPLING 256 35 + #define DFSDM_MAX_FL_OVERSAMPLING 1024 36 + 37 + /* Max sample resolutions */ 38 + #define DFSDM_MAX_RES BIT(31) 39 + #define DFSDM_DATA_RES BIT(23) 40 + 41 + enum sd_converter_type { 42 + DFSDM_AUDIO, 43 + DFSDM_IIO, 44 + }; 45 + 46 + struct stm32_dfsdm_dev_data { 47 + int type; 48 + int (*init)(struct iio_dev *indio_dev); 49 + unsigned int num_channels; 50 + const struct regmap_config *regmap_cfg; 51 + }; 52 + 53 + struct stm32_dfsdm_adc { 54 + struct stm32_dfsdm *dfsdm; 55 + const struct stm32_dfsdm_dev_data *dev_data; 56 + unsigned int fl_id; 57 + unsigned int ch_id; 58 + 59 + /* ADC specific */ 60 + unsigned int oversamp; 61 + struct iio_hw_consumer *hwc; 62 + struct completion completion; 63 + u32 *buffer; 64 + 65 + /* Audio specific */ 66 + unsigned int spi_freq; /* SPI bus clock frequency */ 67 + unsigned int sample_freq; /* Sample frequency after filter decimation */ 68 + int (*cb)(const void *data, size_t size, void *cb_priv); 69 + void *cb_priv; 70 + 71 + /* DMA */ 72 + u8 *rx_buf; 73 + unsigned int bufi; /* Buffer current position */ 74 + unsigned int buf_sz; /* Buffer size */ 75 + struct dma_chan *dma_chan; 76 + dma_addr_t dma_buf; 77 + }; 78 + 79 + struct stm32_dfsdm_str2field { 80 + const char *name; 81 + unsigned int val; 82 + }; 83 + 84 + /* DFSDM channel serial interface type */ 85 + static const struct stm32_dfsdm_str2field stm32_dfsdm_chan_type[] = { 86 + { "SPI_R", 0 }, /* SPI with data on rising edge */ 87 + { "SPI_F", 1 }, /* SPI with data on falling edge */ 88 + { "MANCH_R", 2 }, /* Manchester codec, rising edge = logic 0 */ 89 + { "MANCH_F", 3 }, /* Manchester codec, falling edge = logic 1 */ 90 + {}, 91 + }; 92 + 93 + /* DFSDM channel clock source */ 94 + static const struct stm32_dfsdm_str2field stm32_dfsdm_chan_src[] = { 95 + /* External SPI clock (CLKIN x) */ 96 + { "CLKIN", DFSDM_CHANNEL_SPI_CLOCK_EXTERNAL }, 97 + /* Internal SPI clock (CLKOUT) */ 98 + { "CLKOUT", DFSDM_CHANNEL_SPI_CLOCK_INTERNAL }, 99 + /* Internal SPI clock divided by 2 (falling edge) */ 100 + { "CLKOUT_F", DFSDM_CHANNEL_SPI_CLOCK_INTERNAL_DIV2_FALLING }, 101 + /* Internal SPI clock divided by 2 (falling edge) */ 102 + { "CLKOUT_R", DFSDM_CHANNEL_SPI_CLOCK_INTERNAL_DIV2_RISING }, 103 + {}, 104 + }; 105 + 106 + static int stm32_dfsdm_str2val(const char *str, 107 + const struct stm32_dfsdm_str2field *list) 108 + { 109 + const struct stm32_dfsdm_str2field *p = list; 110 + 111 + for (p = list; p && p->name; p++) 112 + if (!strcmp(p->name, str)) 113 + return p->val; 114 + 115 + return -EINVAL; 116 + } 117 + 118 + static int stm32_dfsdm_set_osrs(struct stm32_dfsdm_filter *fl, 119 + unsigned int fast, unsigned int oversamp) 120 + { 121 + unsigned int i, d, fosr, iosr; 122 + u64 res; 123 + s64 delta; 124 + unsigned int m = 1; /* multiplication factor */ 125 + unsigned int p = fl->ford; /* filter order (ford) */ 126 + 127 + pr_debug("%s: Requested oversampling: %d\n", __func__, oversamp); 128 + /* 129 + * This function tries to compute filter oversampling and integrator 130 + * oversampling, base on oversampling ratio requested by user. 131 + * 132 + * Decimation d depends on the filter order and the oversampling ratios. 133 + * ford: filter order 134 + * fosr: filter over sampling ratio 135 + * iosr: integrator over sampling ratio 136 + */ 137 + if (fl->ford == DFSDM_FASTSINC_ORDER) { 138 + m = 2; 139 + p = 2; 140 + } 141 + 142 + /* 143 + * Look for filter and integrator oversampling ratios which allows 144 + * to reach 24 bits data output resolution. 145 + * Leave as soon as if exact resolution if reached. 146 + * Otherwise the higher resolution below 32 bits is kept. 147 + */ 148 + for (fosr = 1; fosr <= DFSDM_MAX_FL_OVERSAMPLING; fosr++) { 149 + for (iosr = 1; iosr <= DFSDM_MAX_INT_OVERSAMPLING; iosr++) { 150 + if (fast) 151 + d = fosr * iosr; 152 + else if (fl->ford == DFSDM_FASTSINC_ORDER) 153 + d = fosr * (iosr + 3) + 2; 154 + else 155 + d = fosr * (iosr - 1 + p) + p; 156 + 157 + if (d > oversamp) 158 + break; 159 + else if (d != oversamp) 160 + continue; 161 + /* 162 + * Check resolution (limited to signed 32 bits) 163 + * res <= 2^31 164 + * Sincx filters: 165 + * res = m * fosr^p x iosr (with m=1, p=ford) 166 + * FastSinc filter 167 + * res = m * fosr^p x iosr (with m=2, p=2) 168 + */ 169 + res = fosr; 170 + for (i = p - 1; i > 0; i--) { 171 + res = res * (u64)fosr; 172 + if (res > DFSDM_MAX_RES) 173 + break; 174 + } 175 + if (res > DFSDM_MAX_RES) 176 + continue; 177 + res = res * (u64)m * (u64)iosr; 178 + if (res > DFSDM_MAX_RES) 179 + continue; 180 + 181 + delta = res - DFSDM_DATA_RES; 182 + 183 + if (res >= fl->res) { 184 + fl->res = res; 185 + fl->fosr = fosr; 186 + fl->iosr = iosr; 187 + fl->fast = fast; 188 + pr_debug("%s: fosr = %d, iosr = %d\n", 189 + __func__, fl->fosr, fl->iosr); 190 + } 191 + 192 + if (!delta) 193 + return 0; 194 + } 195 + } 196 + 197 + if (!fl->fosr) 198 + return -EINVAL; 199 + 200 + return 0; 201 + } 202 + 203 + static int stm32_dfsdm_start_channel(struct stm32_dfsdm *dfsdm, 204 + unsigned int ch_id) 205 + { 206 + return regmap_update_bits(dfsdm->regmap, DFSDM_CHCFGR1(ch_id), 207 + DFSDM_CHCFGR1_CHEN_MASK, 208 + DFSDM_CHCFGR1_CHEN(1)); 209 + } 210 + 211 + static void stm32_dfsdm_stop_channel(struct stm32_dfsdm *dfsdm, 212 + unsigned int ch_id) 213 + { 214 + regmap_update_bits(dfsdm->regmap, DFSDM_CHCFGR1(ch_id), 215 + DFSDM_CHCFGR1_CHEN_MASK, DFSDM_CHCFGR1_CHEN(0)); 216 + } 217 + 218 + static int stm32_dfsdm_chan_configure(struct stm32_dfsdm *dfsdm, 219 + struct stm32_dfsdm_channel *ch) 220 + { 221 + unsigned int id = ch->id; 222 + struct regmap *regmap = dfsdm->regmap; 223 + int ret; 224 + 225 + ret = regmap_update_bits(regmap, DFSDM_CHCFGR1(id), 226 + DFSDM_CHCFGR1_SITP_MASK, 227 + DFSDM_CHCFGR1_SITP(ch->type)); 228 + if (ret < 0) 229 + return ret; 230 + ret = regmap_update_bits(regmap, DFSDM_CHCFGR1(id), 231 + DFSDM_CHCFGR1_SPICKSEL_MASK, 232 + DFSDM_CHCFGR1_SPICKSEL(ch->src)); 233 + if (ret < 0) 234 + return ret; 235 + return regmap_update_bits(regmap, DFSDM_CHCFGR1(id), 236 + DFSDM_CHCFGR1_CHINSEL_MASK, 237 + DFSDM_CHCFGR1_CHINSEL(ch->alt_si)); 238 + } 239 + 240 + static int stm32_dfsdm_start_filter(struct stm32_dfsdm *dfsdm, 241 + unsigned int fl_id) 242 + { 243 + int ret; 244 + 245 + /* Enable filter */ 246 + ret = regmap_update_bits(dfsdm->regmap, DFSDM_CR1(fl_id), 247 + DFSDM_CR1_DFEN_MASK, DFSDM_CR1_DFEN(1)); 248 + if (ret < 0) 249 + return ret; 250 + 251 + /* Start conversion */ 252 + return regmap_update_bits(dfsdm->regmap, DFSDM_CR1(fl_id), 253 + DFSDM_CR1_RSWSTART_MASK, 254 + DFSDM_CR1_RSWSTART(1)); 255 + } 256 + 257 + static void stm32_dfsdm_stop_filter(struct stm32_dfsdm *dfsdm, unsigned int fl_id) 258 + { 259 + /* Disable conversion */ 260 + regmap_update_bits(dfsdm->regmap, DFSDM_CR1(fl_id), 261 + DFSDM_CR1_DFEN_MASK, DFSDM_CR1_DFEN(0)); 262 + } 263 + 264 + static int stm32_dfsdm_filter_configure(struct stm32_dfsdm *dfsdm, 265 + unsigned int fl_id, unsigned int ch_id) 266 + { 267 + struct regmap *regmap = dfsdm->regmap; 268 + struct stm32_dfsdm_filter *fl = &dfsdm->fl_list[fl_id]; 269 + int ret; 270 + 271 + /* Average integrator oversampling */ 272 + ret = regmap_update_bits(regmap, DFSDM_FCR(fl_id), DFSDM_FCR_IOSR_MASK, 273 + DFSDM_FCR_IOSR(fl->iosr - 1)); 274 + if (ret) 275 + return ret; 276 + 277 + /* Filter order and Oversampling */ 278 + ret = regmap_update_bits(regmap, DFSDM_FCR(fl_id), DFSDM_FCR_FOSR_MASK, 279 + DFSDM_FCR_FOSR(fl->fosr - 1)); 280 + if (ret) 281 + return ret; 282 + 283 + ret = regmap_update_bits(regmap, DFSDM_FCR(fl_id), DFSDM_FCR_FORD_MASK, 284 + DFSDM_FCR_FORD(fl->ford)); 285 + if (ret) 286 + return ret; 287 + 288 + /* No scan mode supported for the moment */ 289 + ret = regmap_update_bits(regmap, DFSDM_CR1(fl_id), DFSDM_CR1_RCH_MASK, 290 + DFSDM_CR1_RCH(ch_id)); 291 + if (ret) 292 + return ret; 293 + 294 + return regmap_update_bits(regmap, DFSDM_CR1(fl_id), 295 + DFSDM_CR1_RSYNC_MASK, 296 + DFSDM_CR1_RSYNC(fl->sync_mode)); 297 + } 298 + 299 + static int stm32_dfsdm_channel_parse_of(struct stm32_dfsdm *dfsdm, 300 + struct iio_dev *indio_dev, 301 + struct iio_chan_spec *ch) 302 + { 303 + struct stm32_dfsdm_channel *df_ch; 304 + const char *of_str; 305 + int chan_idx = ch->scan_index; 306 + int ret, val; 307 + 308 + ret = of_property_read_u32_index(indio_dev->dev.of_node, 309 + "st,adc-channels", chan_idx, 310 + &ch->channel); 311 + if (ret < 0) { 312 + dev_err(&indio_dev->dev, 313 + " Error parsing 'st,adc-channels' for idx %d\n", 314 + chan_idx); 315 + return ret; 316 + } 317 + if (ch->channel >= dfsdm->num_chs) { 318 + dev_err(&indio_dev->dev, 319 + " Error bad channel number %d (max = %d)\n", 320 + ch->channel, dfsdm->num_chs); 321 + return -EINVAL; 322 + } 323 + 324 + ret = of_property_read_string_index(indio_dev->dev.of_node, 325 + "st,adc-channel-names", chan_idx, 326 + &ch->datasheet_name); 327 + if (ret < 0) { 328 + dev_err(&indio_dev->dev, 329 + " Error parsing 'st,adc-channel-names' for idx %d\n", 330 + chan_idx); 331 + return ret; 332 + } 333 + 334 + df_ch = &dfsdm->ch_list[ch->channel]; 335 + df_ch->id = ch->channel; 336 + 337 + ret = of_property_read_string_index(indio_dev->dev.of_node, 338 + "st,adc-channel-types", chan_idx, 339 + &of_str); 340 + if (!ret) { 341 + val = stm32_dfsdm_str2val(of_str, stm32_dfsdm_chan_type); 342 + if (val < 0) 343 + return val; 344 + } else { 345 + val = 0; 346 + } 347 + df_ch->type = val; 348 + 349 + ret = of_property_read_string_index(indio_dev->dev.of_node, 350 + "st,adc-channel-clk-src", chan_idx, 351 + &of_str); 352 + if (!ret) { 353 + val = stm32_dfsdm_str2val(of_str, stm32_dfsdm_chan_src); 354 + if (val < 0) 355 + return val; 356 + } else { 357 + val = 0; 358 + } 359 + df_ch->src = val; 360 + 361 + ret = of_property_read_u32_index(indio_dev->dev.of_node, 362 + "st,adc-alt-channel", chan_idx, 363 + &df_ch->alt_si); 364 + if (ret < 0) 365 + df_ch->alt_si = 0; 366 + 367 + return 0; 368 + } 369 + 370 + static ssize_t dfsdm_adc_audio_get_spiclk(struct iio_dev *indio_dev, 371 + uintptr_t priv, 372 + const struct iio_chan_spec *chan, 373 + char *buf) 374 + { 375 + struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); 376 + 377 + return snprintf(buf, PAGE_SIZE, "%d\n", adc->spi_freq); 378 + } 379 + 380 + static ssize_t dfsdm_adc_audio_set_spiclk(struct iio_dev *indio_dev, 381 + uintptr_t priv, 382 + const struct iio_chan_spec *chan, 383 + const char *buf, size_t len) 384 + { 385 + struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); 386 + struct stm32_dfsdm_filter *fl = &adc->dfsdm->fl_list[adc->fl_id]; 387 + struct stm32_dfsdm_channel *ch = &adc->dfsdm->ch_list[adc->ch_id]; 388 + unsigned int sample_freq = adc->sample_freq; 389 + unsigned int spi_freq; 390 + int ret; 391 + 392 + dev_err(&indio_dev->dev, "enter %s\n", __func__); 393 + /* If DFSDM is master on SPI, SPI freq can not be updated */ 394 + if (ch->src != DFSDM_CHANNEL_SPI_CLOCK_EXTERNAL) 395 + return -EPERM; 396 + 397 + ret = kstrtoint(buf, 0, &spi_freq); 398 + if (ret) 399 + return ret; 400 + 401 + if (!spi_freq) 402 + return -EINVAL; 403 + 404 + if (sample_freq) { 405 + if (spi_freq % sample_freq) 406 + dev_warn(&indio_dev->dev, 407 + "Sampling rate not accurate (%d)\n", 408 + spi_freq / (spi_freq / sample_freq)); 409 + 410 + ret = stm32_dfsdm_set_osrs(fl, 0, (spi_freq / sample_freq)); 411 + if (ret < 0) { 412 + dev_err(&indio_dev->dev, 413 + "No filter parameters that match!\n"); 414 + return ret; 415 + } 416 + } 417 + adc->spi_freq = spi_freq; 418 + 419 + return len; 420 + } 421 + 422 + static int stm32_dfsdm_start_conv(struct stm32_dfsdm_adc *adc, bool dma) 423 + { 424 + struct regmap *regmap = adc->dfsdm->regmap; 425 + int ret; 426 + unsigned int dma_en = 0, cont_en = 0; 427 + 428 + ret = stm32_dfsdm_start_channel(adc->dfsdm, adc->ch_id); 429 + if (ret < 0) 430 + return ret; 431 + 432 + ret = stm32_dfsdm_filter_configure(adc->dfsdm, adc->fl_id, 433 + adc->ch_id); 434 + if (ret < 0) 435 + goto stop_channels; 436 + 437 + if (dma) { 438 + /* Enable DMA transfer*/ 439 + dma_en = DFSDM_CR1_RDMAEN(1); 440 + /* Enable conversion triggered by SPI clock*/ 441 + cont_en = DFSDM_CR1_RCONT(1); 442 + } 443 + /* Enable DMA transfer*/ 444 + ret = regmap_update_bits(regmap, DFSDM_CR1(adc->fl_id), 445 + DFSDM_CR1_RDMAEN_MASK, dma_en); 446 + if (ret < 0) 447 + goto stop_channels; 448 + 449 + /* Enable conversion triggered by SPI clock*/ 450 + ret = regmap_update_bits(regmap, DFSDM_CR1(adc->fl_id), 451 + DFSDM_CR1_RCONT_MASK, cont_en); 452 + if (ret < 0) 453 + goto stop_channels; 454 + 455 + ret = stm32_dfsdm_start_filter(adc->dfsdm, adc->fl_id); 456 + if (ret < 0) 457 + goto stop_channels; 458 + 459 + return 0; 460 + 461 + stop_channels: 462 + regmap_update_bits(regmap, DFSDM_CR1(adc->fl_id), 463 + DFSDM_CR1_RDMAEN_MASK, 0); 464 + 465 + regmap_update_bits(regmap, DFSDM_CR1(adc->fl_id), 466 + DFSDM_CR1_RCONT_MASK, 0); 467 + stm32_dfsdm_stop_channel(adc->dfsdm, adc->fl_id); 468 + 469 + return ret; 470 + } 471 + 472 + static void stm32_dfsdm_stop_conv(struct stm32_dfsdm_adc *adc) 473 + { 474 + struct regmap *regmap = adc->dfsdm->regmap; 475 + 476 + stm32_dfsdm_stop_filter(adc->dfsdm, adc->fl_id); 477 + 478 + /* Clean conversion options */ 479 + regmap_update_bits(regmap, DFSDM_CR1(adc->fl_id), 480 + DFSDM_CR1_RDMAEN_MASK, 0); 481 + 482 + regmap_update_bits(regmap, DFSDM_CR1(adc->fl_id), 483 + DFSDM_CR1_RCONT_MASK, 0); 484 + 485 + stm32_dfsdm_stop_channel(adc->dfsdm, adc->ch_id); 486 + } 487 + 488 + static int stm32_dfsdm_set_watermark(struct iio_dev *indio_dev, 489 + unsigned int val) 490 + { 491 + struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); 492 + unsigned int watermark = DFSDM_DMA_BUFFER_SIZE / 2; 493 + 494 + /* 495 + * DMA cyclic transfers are used, buffer is split into two periods. 496 + * There should be : 497 + * - always one buffer (period) DMA is working on 498 + * - one buffer (period) driver pushed to ASoC side. 499 + */ 500 + watermark = min(watermark, val * (unsigned int)(sizeof(u32))); 501 + adc->buf_sz = watermark * 2; 502 + 503 + return 0; 504 + } 505 + 506 + static unsigned int stm32_dfsdm_adc_dma_residue(struct stm32_dfsdm_adc *adc) 507 + { 508 + struct dma_tx_state state; 509 + enum dma_status status; 510 + 511 + status = dmaengine_tx_status(adc->dma_chan, 512 + adc->dma_chan->cookie, 513 + &state); 514 + if (status == DMA_IN_PROGRESS) { 515 + /* Residue is size in bytes from end of buffer */ 516 + unsigned int i = adc->buf_sz - state.residue; 517 + unsigned int size; 518 + 519 + /* Return available bytes */ 520 + if (i >= adc->bufi) 521 + size = i - adc->bufi; 522 + else 523 + size = adc->buf_sz + i - adc->bufi; 524 + 525 + return size; 526 + } 527 + 528 + return 0; 529 + } 530 + 531 + static void stm32_dfsdm_audio_dma_buffer_done(void *data) 532 + { 533 + struct iio_dev *indio_dev = data; 534 + struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); 535 + int available = stm32_dfsdm_adc_dma_residue(adc); 536 + size_t old_pos; 537 + 538 + /* 539 + * FIXME: In Kernel interface does not support cyclic DMA buffer,and 540 + * offers only an interface to push data samples per samples. 541 + * For this reason IIO buffer interface is not used and interface is 542 + * bypassed using a private callback registered by ASoC. 543 + * This should be a temporary solution waiting a cyclic DMA engine 544 + * support in IIO. 545 + */ 546 + 547 + dev_dbg(&indio_dev->dev, "%s: pos = %d, available = %d\n", __func__, 548 + adc->bufi, available); 549 + old_pos = adc->bufi; 550 + 551 + while (available >= indio_dev->scan_bytes) { 552 + u32 *buffer = (u32 *)&adc->rx_buf[adc->bufi]; 553 + 554 + /* Mask 8 LSB that contains the channel ID */ 555 + *buffer = (*buffer & 0xFFFFFF00) << 8; 556 + available -= indio_dev->scan_bytes; 557 + adc->bufi += indio_dev->scan_bytes; 558 + if (adc->bufi >= adc->buf_sz) { 559 + if (adc->cb) 560 + adc->cb(&adc->rx_buf[old_pos], 561 + adc->buf_sz - old_pos, adc->cb_priv); 562 + adc->bufi = 0; 563 + old_pos = 0; 564 + } 565 + } 566 + if (adc->cb) 567 + adc->cb(&adc->rx_buf[old_pos], adc->bufi - old_pos, 568 + adc->cb_priv); 569 + } 570 + 571 + static int stm32_dfsdm_adc_dma_start(struct iio_dev *indio_dev) 572 + { 573 + struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); 574 + struct dma_async_tx_descriptor *desc; 575 + dma_cookie_t cookie; 576 + int ret; 577 + 578 + if (!adc->dma_chan) 579 + return -EINVAL; 580 + 581 + dev_dbg(&indio_dev->dev, "%s size=%d watermark=%d\n", __func__, 582 + adc->buf_sz, adc->buf_sz / 2); 583 + 584 + /* Prepare a DMA cyclic transaction */ 585 + desc = dmaengine_prep_dma_cyclic(adc->dma_chan, 586 + adc->dma_buf, 587 + adc->buf_sz, adc->buf_sz / 2, 588 + DMA_DEV_TO_MEM, 589 + DMA_PREP_INTERRUPT); 590 + if (!desc) 591 + return -EBUSY; 592 + 593 + desc->callback = stm32_dfsdm_audio_dma_buffer_done; 594 + desc->callback_param = indio_dev; 595 + 596 + cookie = dmaengine_submit(desc); 597 + ret = dma_submit_error(cookie); 598 + if (ret) { 599 + dmaengine_terminate_all(adc->dma_chan); 600 + return ret; 601 + } 602 + 603 + /* Issue pending DMA requests */ 604 + dma_async_issue_pending(adc->dma_chan); 605 + 606 + return 0; 607 + } 608 + 609 + static int stm32_dfsdm_postenable(struct iio_dev *indio_dev) 610 + { 611 + struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); 612 + int ret; 613 + 614 + /* Reset adc buffer index */ 615 + adc->bufi = 0; 616 + 617 + ret = stm32_dfsdm_start_dfsdm(adc->dfsdm); 618 + if (ret < 0) 619 + return ret; 620 + 621 + ret = stm32_dfsdm_start_conv(adc, true); 622 + if (ret) { 623 + dev_err(&indio_dev->dev, "Can't start conversion\n"); 624 + goto stop_dfsdm; 625 + } 626 + 627 + if (adc->dma_chan) { 628 + ret = stm32_dfsdm_adc_dma_start(indio_dev); 629 + if (ret) { 630 + dev_err(&indio_dev->dev, "Can't start DMA\n"); 631 + goto err_stop_conv; 632 + } 633 + } 634 + 635 + return 0; 636 + 637 + err_stop_conv: 638 + stm32_dfsdm_stop_conv(adc); 639 + stop_dfsdm: 640 + stm32_dfsdm_stop_dfsdm(adc->dfsdm); 641 + 642 + return ret; 643 + } 644 + 645 + static int stm32_dfsdm_predisable(struct iio_dev *indio_dev) 646 + { 647 + struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); 648 + 649 + if (adc->dma_chan) 650 + dmaengine_terminate_all(adc->dma_chan); 651 + 652 + stm32_dfsdm_stop_conv(adc); 653 + 654 + stm32_dfsdm_stop_dfsdm(adc->dfsdm); 655 + 656 + return 0; 657 + } 658 + 659 + static const struct iio_buffer_setup_ops stm32_dfsdm_buffer_setup_ops = { 660 + .postenable = &stm32_dfsdm_postenable, 661 + .predisable = &stm32_dfsdm_predisable, 662 + }; 663 + 664 + /** 665 + * stm32_dfsdm_get_buff_cb() - register a callback that will be called when 666 + * DMA transfer period is achieved. 667 + * 668 + * @iio_dev: Handle to IIO device. 669 + * @cb: Pointer to callback function: 670 + * - data: pointer to data buffer 671 + * - size: size in byte of the data buffer 672 + * - private: pointer to consumer private structure. 673 + * @private: Pointer to consumer private structure. 674 + */ 675 + int stm32_dfsdm_get_buff_cb(struct iio_dev *iio_dev, 676 + int (*cb)(const void *data, size_t size, 677 + void *private), 678 + void *private) 679 + { 680 + struct stm32_dfsdm_adc *adc; 681 + 682 + if (!iio_dev) 683 + return -EINVAL; 684 + adc = iio_priv(iio_dev); 685 + 686 + adc->cb = cb; 687 + adc->cb_priv = private; 688 + 689 + return 0; 690 + } 691 + EXPORT_SYMBOL_GPL(stm32_dfsdm_get_buff_cb); 692 + 693 + /** 694 + * stm32_dfsdm_release_buff_cb - unregister buffer callback 695 + * 696 + * @iio_dev: Handle to IIO device. 697 + */ 698 + int stm32_dfsdm_release_buff_cb(struct iio_dev *iio_dev) 699 + { 700 + struct stm32_dfsdm_adc *adc; 701 + 702 + if (!iio_dev) 703 + return -EINVAL; 704 + adc = iio_priv(iio_dev); 705 + 706 + adc->cb = NULL; 707 + adc->cb_priv = NULL; 708 + 709 + return 0; 710 + } 711 + EXPORT_SYMBOL_GPL(stm32_dfsdm_release_buff_cb); 712 + 713 + static int stm32_dfsdm_single_conv(struct iio_dev *indio_dev, 714 + const struct iio_chan_spec *chan, int *res) 715 + { 716 + struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); 717 + long timeout; 718 + int ret; 719 + 720 + reinit_completion(&adc->completion); 721 + 722 + adc->buffer = res; 723 + 724 + ret = stm32_dfsdm_start_dfsdm(adc->dfsdm); 725 + if (ret < 0) 726 + return ret; 727 + 728 + ret = regmap_update_bits(adc->dfsdm->regmap, DFSDM_CR2(adc->fl_id), 729 + DFSDM_CR2_REOCIE_MASK, DFSDM_CR2_REOCIE(1)); 730 + if (ret < 0) 731 + goto stop_dfsdm; 732 + 733 + ret = stm32_dfsdm_start_conv(adc, false); 734 + if (ret < 0) { 735 + regmap_update_bits(adc->dfsdm->regmap, DFSDM_CR2(adc->fl_id), 736 + DFSDM_CR2_REOCIE_MASK, DFSDM_CR2_REOCIE(0)); 737 + goto stop_dfsdm; 738 + } 739 + 740 + timeout = wait_for_completion_interruptible_timeout(&adc->completion, 741 + DFSDM_TIMEOUT); 742 + 743 + /* Mask IRQ for regular conversion achievement*/ 744 + regmap_update_bits(adc->dfsdm->regmap, DFSDM_CR2(adc->fl_id), 745 + DFSDM_CR2_REOCIE_MASK, DFSDM_CR2_REOCIE(0)); 746 + 747 + if (timeout == 0) 748 + ret = -ETIMEDOUT; 749 + else if (timeout < 0) 750 + ret = timeout; 751 + else 752 + ret = IIO_VAL_INT; 753 + 754 + stm32_dfsdm_stop_conv(adc); 755 + 756 + stop_dfsdm: 757 + stm32_dfsdm_stop_dfsdm(adc->dfsdm); 758 + 759 + return ret; 760 + } 761 + 762 + static int stm32_dfsdm_write_raw(struct iio_dev *indio_dev, 763 + struct iio_chan_spec const *chan, 764 + int val, int val2, long mask) 765 + { 766 + struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); 767 + struct stm32_dfsdm_filter *fl = &adc->dfsdm->fl_list[adc->fl_id]; 768 + struct stm32_dfsdm_channel *ch = &adc->dfsdm->ch_list[adc->ch_id]; 769 + unsigned int spi_freq = adc->spi_freq; 770 + int ret = -EINVAL; 771 + 772 + switch (mask) { 773 + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: 774 + ret = stm32_dfsdm_set_osrs(fl, 0, val); 775 + if (!ret) 776 + adc->oversamp = val; 777 + 778 + return ret; 779 + 780 + case IIO_CHAN_INFO_SAMP_FREQ: 781 + if (!val) 782 + return -EINVAL; 783 + if (ch->src != DFSDM_CHANNEL_SPI_CLOCK_EXTERNAL) 784 + spi_freq = adc->dfsdm->spi_master_freq; 785 + 786 + if (spi_freq % val) 787 + dev_warn(&indio_dev->dev, 788 + "Sampling rate not accurate (%d)\n", 789 + spi_freq / (spi_freq / val)); 790 + 791 + ret = stm32_dfsdm_set_osrs(fl, 0, (spi_freq / val)); 792 + if (ret < 0) { 793 + dev_err(&indio_dev->dev, 794 + "Not able to find parameter that match!\n"); 795 + return ret; 796 + } 797 + adc->sample_freq = val; 798 + 799 + return 0; 800 + } 801 + 802 + return -EINVAL; 803 + } 804 + 805 + static int stm32_dfsdm_read_raw(struct iio_dev *indio_dev, 806 + struct iio_chan_spec const *chan, int *val, 807 + int *val2, long mask) 808 + { 809 + struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); 810 + int ret; 811 + 812 + switch (mask) { 813 + case IIO_CHAN_INFO_RAW: 814 + ret = iio_hw_consumer_enable(adc->hwc); 815 + if (ret < 0) { 816 + dev_err(&indio_dev->dev, 817 + "%s: IIO enable failed (channel %d)\n", 818 + __func__, chan->channel); 819 + return ret; 820 + } 821 + ret = stm32_dfsdm_single_conv(indio_dev, chan, val); 822 + iio_hw_consumer_disable(adc->hwc); 823 + if (ret < 0) { 824 + dev_err(&indio_dev->dev, 825 + "%s: Conversion failed (channel %d)\n", 826 + __func__, chan->channel); 827 + return ret; 828 + } 829 + return IIO_VAL_INT; 830 + 831 + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: 832 + *val = adc->oversamp; 833 + 834 + return IIO_VAL_INT; 835 + 836 + case IIO_CHAN_INFO_SAMP_FREQ: 837 + *val = adc->sample_freq; 838 + 839 + return IIO_VAL_INT; 840 + } 841 + 842 + return -EINVAL; 843 + } 844 + 845 + static const struct iio_info stm32_dfsdm_info_audio = { 846 + .hwfifo_set_watermark = stm32_dfsdm_set_watermark, 847 + .read_raw = stm32_dfsdm_read_raw, 848 + .write_raw = stm32_dfsdm_write_raw, 849 + }; 850 + 851 + static const struct iio_info stm32_dfsdm_info_adc = { 852 + .read_raw = stm32_dfsdm_read_raw, 853 + .write_raw = stm32_dfsdm_write_raw, 854 + }; 855 + 856 + static irqreturn_t stm32_dfsdm_irq(int irq, void *arg) 857 + { 858 + struct stm32_dfsdm_adc *adc = arg; 859 + struct iio_dev *indio_dev = iio_priv_to_dev(adc); 860 + struct regmap *regmap = adc->dfsdm->regmap; 861 + unsigned int status, int_en; 862 + 863 + regmap_read(regmap, DFSDM_ISR(adc->fl_id), &status); 864 + regmap_read(regmap, DFSDM_CR2(adc->fl_id), &int_en); 865 + 866 + if (status & DFSDM_ISR_REOCF_MASK) { 867 + /* Read the data register clean the IRQ status */ 868 + regmap_read(regmap, DFSDM_RDATAR(adc->fl_id), adc->buffer); 869 + complete(&adc->completion); 870 + } 871 + 872 + if (status & DFSDM_ISR_ROVRF_MASK) { 873 + if (int_en & DFSDM_CR2_ROVRIE_MASK) 874 + dev_warn(&indio_dev->dev, "Overrun detected\n"); 875 + regmap_update_bits(regmap, DFSDM_ICR(adc->fl_id), 876 + DFSDM_ICR_CLRROVRF_MASK, 877 + DFSDM_ICR_CLRROVRF_MASK); 878 + } 879 + 880 + return IRQ_HANDLED; 881 + } 882 + 883 + /* 884 + * Define external info for SPI Frequency and audio sampling rate that can be 885 + * configured by ASoC driver through consumer.h API 886 + */ 887 + static const struct iio_chan_spec_ext_info dfsdm_adc_audio_ext_info[] = { 888 + /* spi_clk_freq : clock freq on SPI/manchester bus used by channel */ 889 + { 890 + .name = "spi_clk_freq", 891 + .shared = IIO_SHARED_BY_TYPE, 892 + .read = dfsdm_adc_audio_get_spiclk, 893 + .write = dfsdm_adc_audio_set_spiclk, 894 + }, 895 + {}, 896 + }; 897 + 898 + static void stm32_dfsdm_dma_release(struct iio_dev *indio_dev) 899 + { 900 + struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); 901 + 902 + if (adc->dma_chan) { 903 + dma_free_coherent(adc->dma_chan->device->dev, 904 + DFSDM_DMA_BUFFER_SIZE, 905 + adc->rx_buf, adc->dma_buf); 906 + dma_release_channel(adc->dma_chan); 907 + } 908 + } 909 + 910 + static int stm32_dfsdm_dma_request(struct iio_dev *indio_dev) 911 + { 912 + struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); 913 + struct dma_slave_config config = { 914 + .src_addr = (dma_addr_t)adc->dfsdm->phys_base + 915 + DFSDM_RDATAR(adc->fl_id), 916 + .src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES, 917 + }; 918 + int ret; 919 + 920 + adc->dma_chan = dma_request_slave_channel(&indio_dev->dev, "rx"); 921 + if (!adc->dma_chan) 922 + return -EINVAL; 923 + 924 + adc->rx_buf = dma_alloc_coherent(adc->dma_chan->device->dev, 925 + DFSDM_DMA_BUFFER_SIZE, 926 + &adc->dma_buf, GFP_KERNEL); 927 + if (!adc->rx_buf) { 928 + ret = -ENOMEM; 929 + goto err_release; 930 + } 931 + 932 + ret = dmaengine_slave_config(adc->dma_chan, &config); 933 + if (ret) 934 + goto err_free; 935 + 936 + return 0; 937 + 938 + err_free: 939 + dma_free_coherent(adc->dma_chan->device->dev, DFSDM_DMA_BUFFER_SIZE, 940 + adc->rx_buf, adc->dma_buf); 941 + err_release: 942 + dma_release_channel(adc->dma_chan); 943 + 944 + return ret; 945 + } 946 + 947 + static int stm32_dfsdm_adc_chan_init_one(struct iio_dev *indio_dev, 948 + struct iio_chan_spec *ch) 949 + { 950 + struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); 951 + int ret; 952 + 953 + ret = stm32_dfsdm_channel_parse_of(adc->dfsdm, indio_dev, ch); 954 + if (ret < 0) 955 + return ret; 956 + 957 + ch->type = IIO_VOLTAGE; 958 + ch->indexed = 1; 959 + 960 + /* 961 + * IIO_CHAN_INFO_RAW: used to compute regular conversion 962 + * IIO_CHAN_INFO_OVERSAMPLING_RATIO: used to set oversampling 963 + */ 964 + ch->info_mask_separate = BIT(IIO_CHAN_INFO_RAW); 965 + ch->info_mask_shared_by_all = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO); 966 + 967 + if (adc->dev_data->type == DFSDM_AUDIO) { 968 + ch->scan_type.sign = 's'; 969 + ch->ext_info = dfsdm_adc_audio_ext_info; 970 + } else { 971 + ch->scan_type.sign = 'u'; 972 + } 973 + ch->scan_type.realbits = 24; 974 + ch->scan_type.storagebits = 32; 975 + adc->ch_id = ch->channel; 976 + 977 + return stm32_dfsdm_chan_configure(adc->dfsdm, 978 + &adc->dfsdm->ch_list[ch->channel]); 979 + } 980 + 981 + static int stm32_dfsdm_audio_init(struct iio_dev *indio_dev) 982 + { 983 + struct iio_chan_spec *ch; 984 + struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); 985 + struct stm32_dfsdm_channel *d_ch; 986 + int ret; 987 + 988 + indio_dev->modes |= INDIO_BUFFER_SOFTWARE; 989 + indio_dev->setup_ops = &stm32_dfsdm_buffer_setup_ops; 990 + 991 + ch = devm_kzalloc(&indio_dev->dev, sizeof(*ch), GFP_KERNEL); 992 + if (!ch) 993 + return -ENOMEM; 994 + 995 + ch->scan_index = 0; 996 + 997 + ret = stm32_dfsdm_adc_chan_init_one(indio_dev, ch); 998 + if (ret < 0) { 999 + dev_err(&indio_dev->dev, "Channels init failed\n"); 1000 + return ret; 1001 + } 1002 + ch->info_mask_separate = BIT(IIO_CHAN_INFO_SAMP_FREQ); 1003 + 1004 + d_ch = &adc->dfsdm->ch_list[adc->ch_id]; 1005 + if (d_ch->src != DFSDM_CHANNEL_SPI_CLOCK_EXTERNAL) 1006 + adc->spi_freq = adc->dfsdm->spi_master_freq; 1007 + 1008 + indio_dev->num_channels = 1; 1009 + indio_dev->channels = ch; 1010 + 1011 + return stm32_dfsdm_dma_request(indio_dev); 1012 + } 1013 + 1014 + static int stm32_dfsdm_adc_init(struct iio_dev *indio_dev) 1015 + { 1016 + struct iio_chan_spec *ch; 1017 + struct stm32_dfsdm_adc *adc = iio_priv(indio_dev); 1018 + int num_ch; 1019 + int ret, chan_idx; 1020 + 1021 + adc->oversamp = DFSDM_DEFAULT_OVERSAMPLING; 1022 + ret = stm32_dfsdm_set_osrs(&adc->dfsdm->fl_list[adc->fl_id], 0, 1023 + adc->oversamp); 1024 + if (ret < 0) 1025 + return ret; 1026 + 1027 + num_ch = of_property_count_u32_elems(indio_dev->dev.of_node, 1028 + "st,adc-channels"); 1029 + if (num_ch < 0 || num_ch > adc->dfsdm->num_chs) { 1030 + dev_err(&indio_dev->dev, "Bad st,adc-channels\n"); 1031 + return num_ch < 0 ? num_ch : -EINVAL; 1032 + } 1033 + 1034 + /* Bind to SD modulator IIO device */ 1035 + adc->hwc = devm_iio_hw_consumer_alloc(&indio_dev->dev); 1036 + if (IS_ERR(adc->hwc)) 1037 + return -EPROBE_DEFER; 1038 + 1039 + ch = devm_kcalloc(&indio_dev->dev, num_ch, sizeof(*ch), 1040 + GFP_KERNEL); 1041 + if (!ch) 1042 + return -ENOMEM; 1043 + 1044 + for (chan_idx = 0; chan_idx < num_ch; chan_idx++) { 1045 + ch->scan_index = chan_idx; 1046 + ret = stm32_dfsdm_adc_chan_init_one(indio_dev, ch); 1047 + if (ret < 0) { 1048 + dev_err(&indio_dev->dev, "Channels init failed\n"); 1049 + return ret; 1050 + } 1051 + } 1052 + 1053 + indio_dev->num_channels = num_ch; 1054 + indio_dev->channels = ch; 1055 + 1056 + init_completion(&adc->completion); 1057 + 1058 + return 0; 1059 + } 1060 + 1061 + static const struct stm32_dfsdm_dev_data stm32h7_dfsdm_adc_data = { 1062 + .type = DFSDM_IIO, 1063 + .init = stm32_dfsdm_adc_init, 1064 + }; 1065 + 1066 + static const struct stm32_dfsdm_dev_data stm32h7_dfsdm_audio_data = { 1067 + .type = DFSDM_AUDIO, 1068 + .init = stm32_dfsdm_audio_init, 1069 + }; 1070 + 1071 + static const struct of_device_id stm32_dfsdm_adc_match[] = { 1072 + { 1073 + .compatible = "st,stm32-dfsdm-adc", 1074 + .data = &stm32h7_dfsdm_adc_data, 1075 + }, 1076 + { 1077 + .compatible = "st,stm32-dfsdm-dmic", 1078 + .data = &stm32h7_dfsdm_audio_data, 1079 + }, 1080 + {} 1081 + }; 1082 + 1083 + static int stm32_dfsdm_adc_probe(struct platform_device *pdev) 1084 + { 1085 + struct device *dev = &pdev->dev; 1086 + struct stm32_dfsdm_adc *adc; 1087 + struct device_node *np = dev->of_node; 1088 + const struct stm32_dfsdm_dev_data *dev_data; 1089 + struct iio_dev *iio; 1090 + char *name; 1091 + int ret, irq, val; 1092 + 1093 + 1094 + dev_data = of_device_get_match_data(dev); 1095 + iio = devm_iio_device_alloc(dev, sizeof(*adc)); 1096 + if (!iio) { 1097 + dev_err(dev, "%s: Failed to allocate IIO\n", __func__); 1098 + return -ENOMEM; 1099 + } 1100 + 1101 + adc = iio_priv(iio); 1102 + adc->dfsdm = dev_get_drvdata(dev->parent); 1103 + 1104 + iio->dev.parent = dev; 1105 + iio->dev.of_node = np; 1106 + iio->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE; 1107 + 1108 + platform_set_drvdata(pdev, adc); 1109 + 1110 + ret = of_property_read_u32(dev->of_node, "reg", &adc->fl_id); 1111 + if (ret != 0) { 1112 + dev_err(dev, "Missing reg property\n"); 1113 + return -EINVAL; 1114 + } 1115 + 1116 + name = devm_kzalloc(dev, sizeof("dfsdm-adc0"), GFP_KERNEL); 1117 + if (!name) 1118 + return -ENOMEM; 1119 + if (dev_data->type == DFSDM_AUDIO) { 1120 + iio->info = &stm32_dfsdm_info_audio; 1121 + snprintf(name, sizeof("dfsdm-pdm0"), "dfsdm-pdm%d", adc->fl_id); 1122 + } else { 1123 + iio->info = &stm32_dfsdm_info_adc; 1124 + snprintf(name, sizeof("dfsdm-adc0"), "dfsdm-adc%d", adc->fl_id); 1125 + } 1126 + iio->name = name; 1127 + 1128 + /* 1129 + * In a first step IRQs generated for channels are not treated. 1130 + * So IRQ associated to filter instance 0 is dedicated to the Filter 0. 1131 + */ 1132 + irq = platform_get_irq(pdev, 0); 1133 + ret = devm_request_irq(dev, irq, stm32_dfsdm_irq, 1134 + 0, pdev->name, adc); 1135 + if (ret < 0) { 1136 + dev_err(dev, "Failed to request IRQ\n"); 1137 + return ret; 1138 + } 1139 + 1140 + ret = of_property_read_u32(dev->of_node, "st,filter-order", &val); 1141 + if (ret < 0) { 1142 + dev_err(dev, "Failed to set filter order\n"); 1143 + return ret; 1144 + } 1145 + 1146 + adc->dfsdm->fl_list[adc->fl_id].ford = val; 1147 + 1148 + ret = of_property_read_u32(dev->of_node, "st,filter0-sync", &val); 1149 + if (!ret) 1150 + adc->dfsdm->fl_list[adc->fl_id].sync_mode = val; 1151 + 1152 + adc->dev_data = dev_data; 1153 + ret = dev_data->init(iio); 1154 + if (ret < 0) 1155 + return ret; 1156 + 1157 + ret = iio_device_register(iio); 1158 + if (ret < 0) 1159 + goto err_cleanup; 1160 + 1161 + dev_err(dev, "of_platform_populate\n"); 1162 + if (dev_data->type == DFSDM_AUDIO) { 1163 + ret = of_platform_populate(np, NULL, NULL, dev); 1164 + if (ret < 0) { 1165 + dev_err(dev, "Failed to find an audio DAI\n"); 1166 + goto err_unregister; 1167 + } 1168 + } 1169 + 1170 + return 0; 1171 + 1172 + err_unregister: 1173 + iio_device_unregister(iio); 1174 + err_cleanup: 1175 + stm32_dfsdm_dma_release(iio); 1176 + 1177 + return ret; 1178 + } 1179 + 1180 + static int stm32_dfsdm_adc_remove(struct platform_device *pdev) 1181 + { 1182 + struct stm32_dfsdm_adc *adc = platform_get_drvdata(pdev); 1183 + struct iio_dev *indio_dev = iio_priv_to_dev(adc); 1184 + 1185 + if (adc->dev_data->type == DFSDM_AUDIO) 1186 + of_platform_depopulate(&pdev->dev); 1187 + iio_device_unregister(indio_dev); 1188 + stm32_dfsdm_dma_release(indio_dev); 1189 + 1190 + return 0; 1191 + } 1192 + 1193 + static struct platform_driver stm32_dfsdm_adc_driver = { 1194 + .driver = { 1195 + .name = "stm32-dfsdm-adc", 1196 + .of_match_table = stm32_dfsdm_adc_match, 1197 + }, 1198 + .probe = stm32_dfsdm_adc_probe, 1199 + .remove = stm32_dfsdm_adc_remove, 1200 + }; 1201 + module_platform_driver(stm32_dfsdm_adc_driver); 1202 + 1203 + MODULE_DESCRIPTION("STM32 sigma delta ADC"); 1204 + MODULE_AUTHOR("Arnaud Pouliquen <arnaud.pouliquen@st.com>"); 1205 + MODULE_LICENSE("GPL v2");
+302
drivers/iio/adc/stm32-dfsdm-core.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * This file is part the core part STM32 DFSDM driver 4 + * 5 + * Copyright (C) 2017, STMicroelectronics - All Rights Reserved 6 + * Author(s): Arnaud Pouliquen <arnaud.pouliquen@st.com> for STMicroelectronics. 7 + */ 8 + 9 + #include <linux/clk.h> 10 + #include <linux/iio/iio.h> 11 + #include <linux/iio/sysfs.h> 12 + #include <linux/interrupt.h> 13 + #include <linux/module.h> 14 + #include <linux/of_device.h> 15 + #include <linux/regmap.h> 16 + #include <linux/slab.h> 17 + 18 + #include "stm32-dfsdm.h" 19 + 20 + struct stm32_dfsdm_dev_data { 21 + unsigned int num_filters; 22 + unsigned int num_channels; 23 + const struct regmap_config *regmap_cfg; 24 + }; 25 + 26 + #define STM32H7_DFSDM_NUM_FILTERS 4 27 + #define STM32H7_DFSDM_NUM_CHANNELS 8 28 + 29 + static bool stm32_dfsdm_volatile_reg(struct device *dev, unsigned int reg) 30 + { 31 + if (reg < DFSDM_FILTER_BASE_ADR) 32 + return false; 33 + 34 + /* 35 + * Mask is done on register to avoid to list registers of all 36 + * filter instances. 37 + */ 38 + switch (reg & DFSDM_FILTER_REG_MASK) { 39 + case DFSDM_CR1(0) & DFSDM_FILTER_REG_MASK: 40 + case DFSDM_ISR(0) & DFSDM_FILTER_REG_MASK: 41 + case DFSDM_JDATAR(0) & DFSDM_FILTER_REG_MASK: 42 + case DFSDM_RDATAR(0) & DFSDM_FILTER_REG_MASK: 43 + return true; 44 + } 45 + 46 + return false; 47 + } 48 + 49 + static const struct regmap_config stm32h7_dfsdm_regmap_cfg = { 50 + .reg_bits = 32, 51 + .val_bits = 32, 52 + .reg_stride = sizeof(u32), 53 + .max_register = 0x2B8, 54 + .volatile_reg = stm32_dfsdm_volatile_reg, 55 + .fast_io = true, 56 + }; 57 + 58 + static const struct stm32_dfsdm_dev_data stm32h7_dfsdm_data = { 59 + .num_filters = STM32H7_DFSDM_NUM_FILTERS, 60 + .num_channels = STM32H7_DFSDM_NUM_CHANNELS, 61 + .regmap_cfg = &stm32h7_dfsdm_regmap_cfg, 62 + }; 63 + 64 + struct dfsdm_priv { 65 + struct platform_device *pdev; /* platform device */ 66 + 67 + struct stm32_dfsdm dfsdm; /* common data exported for all instances */ 68 + 69 + unsigned int spi_clk_out_div; /* SPI clkout divider value */ 70 + atomic_t n_active_ch; /* number of current active channels */ 71 + 72 + struct clk *clk; /* DFSDM clock */ 73 + struct clk *aclk; /* audio clock */ 74 + }; 75 + 76 + /** 77 + * stm32_dfsdm_start_dfsdm - start global dfsdm interface. 78 + * 79 + * Enable interface if n_active_ch is not null. 80 + * @dfsdm: Handle used to retrieve dfsdm context. 81 + */ 82 + int stm32_dfsdm_start_dfsdm(struct stm32_dfsdm *dfsdm) 83 + { 84 + struct dfsdm_priv *priv = container_of(dfsdm, struct dfsdm_priv, dfsdm); 85 + struct device *dev = &priv->pdev->dev; 86 + unsigned int clk_div = priv->spi_clk_out_div; 87 + int ret; 88 + 89 + if (atomic_inc_return(&priv->n_active_ch) == 1) { 90 + ret = clk_prepare_enable(priv->clk); 91 + if (ret < 0) { 92 + dev_err(dev, "Failed to start clock\n"); 93 + goto error_ret; 94 + } 95 + if (priv->aclk) { 96 + ret = clk_prepare_enable(priv->aclk); 97 + if (ret < 0) { 98 + dev_err(dev, "Failed to start audio clock\n"); 99 + goto disable_clk; 100 + } 101 + } 102 + 103 + /* Output the SPI CLKOUT (if clk_div == 0 clock if OFF) */ 104 + ret = regmap_update_bits(dfsdm->regmap, DFSDM_CHCFGR1(0), 105 + DFSDM_CHCFGR1_CKOUTDIV_MASK, 106 + DFSDM_CHCFGR1_CKOUTDIV(clk_div)); 107 + if (ret < 0) 108 + goto disable_aclk; 109 + 110 + /* Global enable of DFSDM interface */ 111 + ret = regmap_update_bits(dfsdm->regmap, DFSDM_CHCFGR1(0), 112 + DFSDM_CHCFGR1_DFSDMEN_MASK, 113 + DFSDM_CHCFGR1_DFSDMEN(1)); 114 + if (ret < 0) 115 + goto disable_aclk; 116 + } 117 + 118 + dev_dbg(dev, "%s: n_active_ch %d\n", __func__, 119 + atomic_read(&priv->n_active_ch)); 120 + 121 + return 0; 122 + 123 + disable_aclk: 124 + clk_disable_unprepare(priv->aclk); 125 + disable_clk: 126 + clk_disable_unprepare(priv->clk); 127 + 128 + error_ret: 129 + atomic_dec(&priv->n_active_ch); 130 + 131 + return ret; 132 + } 133 + EXPORT_SYMBOL_GPL(stm32_dfsdm_start_dfsdm); 134 + 135 + /** 136 + * stm32_dfsdm_stop_dfsdm - stop global DFSDM interface. 137 + * 138 + * Disable interface if n_active_ch is null 139 + * @dfsdm: Handle used to retrieve dfsdm context. 140 + */ 141 + int stm32_dfsdm_stop_dfsdm(struct stm32_dfsdm *dfsdm) 142 + { 143 + struct dfsdm_priv *priv = container_of(dfsdm, struct dfsdm_priv, dfsdm); 144 + int ret; 145 + 146 + if (atomic_dec_and_test(&priv->n_active_ch)) { 147 + /* Global disable of DFSDM interface */ 148 + ret = regmap_update_bits(dfsdm->regmap, DFSDM_CHCFGR1(0), 149 + DFSDM_CHCFGR1_DFSDMEN_MASK, 150 + DFSDM_CHCFGR1_DFSDMEN(0)); 151 + if (ret < 0) 152 + return ret; 153 + 154 + /* Stop SPI CLKOUT */ 155 + ret = regmap_update_bits(dfsdm->regmap, DFSDM_CHCFGR1(0), 156 + DFSDM_CHCFGR1_CKOUTDIV_MASK, 157 + DFSDM_CHCFGR1_CKOUTDIV(0)); 158 + if (ret < 0) 159 + return ret; 160 + 161 + clk_disable_unprepare(priv->clk); 162 + if (priv->aclk) 163 + clk_disable_unprepare(priv->aclk); 164 + } 165 + dev_dbg(&priv->pdev->dev, "%s: n_active_ch %d\n", __func__, 166 + atomic_read(&priv->n_active_ch)); 167 + 168 + return 0; 169 + } 170 + EXPORT_SYMBOL_GPL(stm32_dfsdm_stop_dfsdm); 171 + 172 + static int stm32_dfsdm_parse_of(struct platform_device *pdev, 173 + struct dfsdm_priv *priv) 174 + { 175 + struct device_node *node = pdev->dev.of_node; 176 + struct resource *res; 177 + unsigned long clk_freq; 178 + unsigned int spi_freq, rem; 179 + int ret; 180 + 181 + if (!node) 182 + return -EINVAL; 183 + 184 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 185 + if (!res) { 186 + dev_err(&pdev->dev, "Failed to get memory resource\n"); 187 + return -ENODEV; 188 + } 189 + priv->dfsdm.phys_base = res->start; 190 + priv->dfsdm.base = devm_ioremap_resource(&pdev->dev, res); 191 + 192 + /* 193 + * "dfsdm" clock is mandatory for DFSDM peripheral clocking. 194 + * "dfsdm" or "audio" clocks can be used as source clock for 195 + * the SPI clock out signal and internal processing, depending 196 + * on use case. 197 + */ 198 + priv->clk = devm_clk_get(&pdev->dev, "dfsdm"); 199 + if (IS_ERR(priv->clk)) { 200 + dev_err(&pdev->dev, "No stm32_dfsdm_clk clock found\n"); 201 + return -EINVAL; 202 + } 203 + 204 + priv->aclk = devm_clk_get(&pdev->dev, "audio"); 205 + if (IS_ERR(priv->aclk)) 206 + priv->aclk = NULL; 207 + 208 + if (priv->aclk) 209 + clk_freq = clk_get_rate(priv->aclk); 210 + else 211 + clk_freq = clk_get_rate(priv->clk); 212 + 213 + /* SPI clock out frequency */ 214 + ret = of_property_read_u32(pdev->dev.of_node, "spi-max-frequency", 215 + &spi_freq); 216 + if (ret < 0) { 217 + /* No SPI master mode */ 218 + return 0; 219 + } 220 + 221 + priv->spi_clk_out_div = div_u64_rem(clk_freq, spi_freq, &rem) - 1; 222 + priv->dfsdm.spi_master_freq = spi_freq; 223 + 224 + if (rem) { 225 + dev_warn(&pdev->dev, "SPI clock not accurate\n"); 226 + dev_warn(&pdev->dev, "%ld = %d * %d + %d\n", 227 + clk_freq, spi_freq, priv->spi_clk_out_div + 1, rem); 228 + } 229 + 230 + return 0; 231 + }; 232 + 233 + static const struct of_device_id stm32_dfsdm_of_match[] = { 234 + { 235 + .compatible = "st,stm32h7-dfsdm", 236 + .data = &stm32h7_dfsdm_data, 237 + }, 238 + {} 239 + }; 240 + MODULE_DEVICE_TABLE(of, stm32_dfsdm_of_match); 241 + 242 + static int stm32_dfsdm_probe(struct platform_device *pdev) 243 + { 244 + struct dfsdm_priv *priv; 245 + const struct stm32_dfsdm_dev_data *dev_data; 246 + struct stm32_dfsdm *dfsdm; 247 + int ret; 248 + 249 + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 250 + if (!priv) 251 + return -ENOMEM; 252 + 253 + priv->pdev = pdev; 254 + 255 + dev_data = of_device_get_match_data(&pdev->dev); 256 + 257 + dfsdm = &priv->dfsdm; 258 + dfsdm->fl_list = devm_kcalloc(&pdev->dev, dev_data->num_filters, 259 + sizeof(*dfsdm->fl_list), GFP_KERNEL); 260 + if (!dfsdm->fl_list) 261 + return -ENOMEM; 262 + 263 + dfsdm->num_fls = dev_data->num_filters; 264 + dfsdm->ch_list = devm_kcalloc(&pdev->dev, dev_data->num_channels, 265 + sizeof(*dfsdm->ch_list), 266 + GFP_KERNEL); 267 + if (!dfsdm->ch_list) 268 + return -ENOMEM; 269 + dfsdm->num_chs = dev_data->num_channels; 270 + 271 + ret = stm32_dfsdm_parse_of(pdev, priv); 272 + if (ret < 0) 273 + return ret; 274 + 275 + dfsdm->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "dfsdm", 276 + dfsdm->base, 277 + &stm32h7_dfsdm_regmap_cfg); 278 + if (IS_ERR(dfsdm->regmap)) { 279 + ret = PTR_ERR(dfsdm->regmap); 280 + dev_err(&pdev->dev, "%s: Failed to allocate regmap: %d\n", 281 + __func__, ret); 282 + return ret; 283 + } 284 + 285 + platform_set_drvdata(pdev, dfsdm); 286 + 287 + return devm_of_platform_populate(&pdev->dev); 288 + } 289 + 290 + static struct platform_driver stm32_dfsdm_driver = { 291 + .probe = stm32_dfsdm_probe, 292 + .driver = { 293 + .name = "stm32-dfsdm", 294 + .of_match_table = stm32_dfsdm_of_match, 295 + }, 296 + }; 297 + 298 + module_platform_driver(stm32_dfsdm_driver); 299 + 300 + MODULE_AUTHOR("Arnaud Pouliquen <arnaud.pouliquen@st.com>"); 301 + MODULE_DESCRIPTION("STMicroelectronics STM32 dfsdm driver"); 302 + MODULE_LICENSE("GPL v2");
+310
drivers/iio/adc/stm32-dfsdm.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * This file is part of STM32 DFSDM driver 4 + * 5 + * Copyright (C) 2017, STMicroelectronics - All Rights Reserved 6 + * Author(s): Arnaud Pouliquen <arnaud.pouliquen@st.com>. 7 + */ 8 + 9 + #ifndef MDF_STM32_DFSDM__H 10 + #define MDF_STM32_DFSDM__H 11 + 12 + #include <linux/bitfield.h> 13 + 14 + /* 15 + * STM32 DFSDM - global register map 16 + * ________________________________________________________ 17 + * | Offset | Registers block | 18 + * -------------------------------------------------------- 19 + * | 0x000 | CHANNEL 0 + COMMON CHANNEL FIELDS | 20 + * -------------------------------------------------------- 21 + * | 0x020 | CHANNEL 1 | 22 + * -------------------------------------------------------- 23 + * | ... | ..... | 24 + * -------------------------------------------------------- 25 + * | 0x0E0 | CHANNEL 7 | 26 + * -------------------------------------------------------- 27 + * | 0x100 | FILTER 0 + COMMON FILTER FIELDs | 28 + * -------------------------------------------------------- 29 + * | 0x200 | FILTER 1 | 30 + * -------------------------------------------------------- 31 + * | 0x300 | FILTER 2 | 32 + * -------------------------------------------------------- 33 + * | 0x400 | FILTER 3 | 34 + * -------------------------------------------------------- 35 + */ 36 + 37 + /* 38 + * Channels register definitions 39 + */ 40 + #define DFSDM_CHCFGR1(y) ((y) * 0x20 + 0x00) 41 + #define DFSDM_CHCFGR2(y) ((y) * 0x20 + 0x04) 42 + #define DFSDM_AWSCDR(y) ((y) * 0x20 + 0x08) 43 + #define DFSDM_CHWDATR(y) ((y) * 0x20 + 0x0C) 44 + #define DFSDM_CHDATINR(y) ((y) * 0x20 + 0x10) 45 + 46 + /* CHCFGR1: Channel configuration register 1 */ 47 + #define DFSDM_CHCFGR1_SITP_MASK GENMASK(1, 0) 48 + #define DFSDM_CHCFGR1_SITP(v) FIELD_PREP(DFSDM_CHCFGR1_SITP_MASK, v) 49 + #define DFSDM_CHCFGR1_SPICKSEL_MASK GENMASK(3, 2) 50 + #define DFSDM_CHCFGR1_SPICKSEL(v) FIELD_PREP(DFSDM_CHCFGR1_SPICKSEL_MASK, v) 51 + #define DFSDM_CHCFGR1_SCDEN_MASK BIT(5) 52 + #define DFSDM_CHCFGR1_SCDEN(v) FIELD_PREP(DFSDM_CHCFGR1_SCDEN_MASK, v) 53 + #define DFSDM_CHCFGR1_CKABEN_MASK BIT(6) 54 + #define DFSDM_CHCFGR1_CKABEN(v) FIELD_PREP(DFSDM_CHCFGR1_CKABEN_MASK, v) 55 + #define DFSDM_CHCFGR1_CHEN_MASK BIT(7) 56 + #define DFSDM_CHCFGR1_CHEN(v) FIELD_PREP(DFSDM_CHCFGR1_CHEN_MASK, v) 57 + #define DFSDM_CHCFGR1_CHINSEL_MASK BIT(8) 58 + #define DFSDM_CHCFGR1_CHINSEL(v) FIELD_PREP(DFSDM_CHCFGR1_CHINSEL_MASK, v) 59 + #define DFSDM_CHCFGR1_DATMPX_MASK GENMASK(13, 12) 60 + #define DFSDM_CHCFGR1_DATMPX(v) FIELD_PREP(DFSDM_CHCFGR1_DATMPX_MASK, v) 61 + #define DFSDM_CHCFGR1_DATPACK_MASK GENMASK(15, 14) 62 + #define DFSDM_CHCFGR1_DATPACK(v) FIELD_PREP(DFSDM_CHCFGR1_DATPACK_MASK, v) 63 + #define DFSDM_CHCFGR1_CKOUTDIV_MASK GENMASK(23, 16) 64 + #define DFSDM_CHCFGR1_CKOUTDIV(v) FIELD_PREP(DFSDM_CHCFGR1_CKOUTDIV_MASK, v) 65 + #define DFSDM_CHCFGR1_CKOUTSRC_MASK BIT(30) 66 + #define DFSDM_CHCFGR1_CKOUTSRC(v) FIELD_PREP(DFSDM_CHCFGR1_CKOUTSRC_MASK, v) 67 + #define DFSDM_CHCFGR1_DFSDMEN_MASK BIT(31) 68 + #define DFSDM_CHCFGR1_DFSDMEN(v) FIELD_PREP(DFSDM_CHCFGR1_DFSDMEN_MASK, v) 69 + 70 + /* CHCFGR2: Channel configuration register 2 */ 71 + #define DFSDM_CHCFGR2_DTRBS_MASK GENMASK(7, 3) 72 + #define DFSDM_CHCFGR2_DTRBS(v) FIELD_PREP(DFSDM_CHCFGR2_DTRBS_MASK, v) 73 + #define DFSDM_CHCFGR2_OFFSET_MASK GENMASK(31, 8) 74 + #define DFSDM_CHCFGR2_OFFSET(v) FIELD_PREP(DFSDM_CHCFGR2_OFFSET_MASK, v) 75 + 76 + /* AWSCDR: Channel analog watchdog and short circuit detector */ 77 + #define DFSDM_AWSCDR_SCDT_MASK GENMASK(7, 0) 78 + #define DFSDM_AWSCDR_SCDT(v) FIELD_PREP(DFSDM_AWSCDR_SCDT_MASK, v) 79 + #define DFSDM_AWSCDR_BKSCD_MASK GENMASK(15, 12) 80 + #define DFSDM_AWSCDR_BKSCD(v) FIELD_PREP(DFSDM_AWSCDR_BKSCD_MASK, v) 81 + #define DFSDM_AWSCDR_AWFOSR_MASK GENMASK(20, 16) 82 + #define DFSDM_AWSCDR_AWFOSR(v) FIELD_PREP(DFSDM_AWSCDR_AWFOSR_MASK, v) 83 + #define DFSDM_AWSCDR_AWFORD_MASK GENMASK(23, 22) 84 + #define DFSDM_AWSCDR_AWFORD(v) FIELD_PREP(DFSDM_AWSCDR_AWFORD_MASK, v) 85 + 86 + /* 87 + * Filters register definitions 88 + */ 89 + #define DFSDM_FILTER_BASE_ADR 0x100 90 + #define DFSDM_FILTER_REG_MASK 0x7F 91 + #define DFSDM_FILTER_X_BASE_ADR(x) ((x) * 0x80 + DFSDM_FILTER_BASE_ADR) 92 + 93 + #define DFSDM_CR1(x) (DFSDM_FILTER_X_BASE_ADR(x) + 0x00) 94 + #define DFSDM_CR2(x) (DFSDM_FILTER_X_BASE_ADR(x) + 0x04) 95 + #define DFSDM_ISR(x) (DFSDM_FILTER_X_BASE_ADR(x) + 0x08) 96 + #define DFSDM_ICR(x) (DFSDM_FILTER_X_BASE_ADR(x) + 0x0C) 97 + #define DFSDM_JCHGR(x) (DFSDM_FILTER_X_BASE_ADR(x) + 0x10) 98 + #define DFSDM_FCR(x) (DFSDM_FILTER_X_BASE_ADR(x) + 0x14) 99 + #define DFSDM_JDATAR(x) (DFSDM_FILTER_X_BASE_ADR(x) + 0x18) 100 + #define DFSDM_RDATAR(x) (DFSDM_FILTER_X_BASE_ADR(x) + 0x1C) 101 + #define DFSDM_AWHTR(x) (DFSDM_FILTER_X_BASE_ADR(x) + 0x20) 102 + #define DFSDM_AWLTR(x) (DFSDM_FILTER_X_BASE_ADR(x) + 0x24) 103 + #define DFSDM_AWSR(x) (DFSDM_FILTER_X_BASE_ADR(x) + 0x28) 104 + #define DFSDM_AWCFR(x) (DFSDM_FILTER_X_BASE_ADR(x) + 0x2C) 105 + #define DFSDM_EXMAX(x) (DFSDM_FILTER_X_BASE_ADR(x) + 0x30) 106 + #define DFSDM_EXMIN(x) (DFSDM_FILTER_X_BASE_ADR(x) + 0x34) 107 + #define DFSDM_CNVTIMR(x) (DFSDM_FILTER_X_BASE_ADR(x) + 0x38) 108 + 109 + /* CR1 Control register 1 */ 110 + #define DFSDM_CR1_DFEN_MASK BIT(0) 111 + #define DFSDM_CR1_DFEN(v) FIELD_PREP(DFSDM_CR1_DFEN_MASK, v) 112 + #define DFSDM_CR1_JSWSTART_MASK BIT(1) 113 + #define DFSDM_CR1_JSWSTART(v) FIELD_PREP(DFSDM_CR1_JSWSTART_MASK, v) 114 + #define DFSDM_CR1_JSYNC_MASK BIT(3) 115 + #define DFSDM_CR1_JSYNC(v) FIELD_PREP(DFSDM_CR1_JSYNC_MASK, v) 116 + #define DFSDM_CR1_JSCAN_MASK BIT(4) 117 + #define DFSDM_CR1_JSCAN(v) FIELD_PREP(DFSDM_CR1_JSCAN_MASK, v) 118 + #define DFSDM_CR1_JDMAEN_MASK BIT(5) 119 + #define DFSDM_CR1_JDMAEN(v) FIELD_PREP(DFSDM_CR1_JDMAEN_MASK, v) 120 + #define DFSDM_CR1_JEXTSEL_MASK GENMASK(12, 8) 121 + #define DFSDM_CR1_JEXTSEL(v) FIELD_PREP(DFSDM_CR1_JEXTSEL_MASK, v) 122 + #define DFSDM_CR1_JEXTEN_MASK GENMASK(14, 13) 123 + #define DFSDM_CR1_JEXTEN(v) FIELD_PREP(DFSDM_CR1_JEXTEN_MASK, v) 124 + #define DFSDM_CR1_RSWSTART_MASK BIT(17) 125 + #define DFSDM_CR1_RSWSTART(v) FIELD_PREP(DFSDM_CR1_RSWSTART_MASK, v) 126 + #define DFSDM_CR1_RCONT_MASK BIT(18) 127 + #define DFSDM_CR1_RCONT(v) FIELD_PREP(DFSDM_CR1_RCONT_MASK, v) 128 + #define DFSDM_CR1_RSYNC_MASK BIT(19) 129 + #define DFSDM_CR1_RSYNC(v) FIELD_PREP(DFSDM_CR1_RSYNC_MASK, v) 130 + #define DFSDM_CR1_RDMAEN_MASK BIT(21) 131 + #define DFSDM_CR1_RDMAEN(v) FIELD_PREP(DFSDM_CR1_RDMAEN_MASK, v) 132 + #define DFSDM_CR1_RCH_MASK GENMASK(26, 24) 133 + #define DFSDM_CR1_RCH(v) FIELD_PREP(DFSDM_CR1_RCH_MASK, v) 134 + #define DFSDM_CR1_FAST_MASK BIT(29) 135 + #define DFSDM_CR1_FAST(v) FIELD_PREP(DFSDM_CR1_FAST_MASK, v) 136 + #define DFSDM_CR1_AWFSEL_MASK BIT(30) 137 + #define DFSDM_CR1_AWFSEL(v) FIELD_PREP(DFSDM_CR1_AWFSEL_MASK, v) 138 + 139 + /* CR2: Control register 2 */ 140 + #define DFSDM_CR2_IE_MASK GENMASK(6, 0) 141 + #define DFSDM_CR2_IE(v) FIELD_PREP(DFSDM_CR2_IE_MASK, v) 142 + #define DFSDM_CR2_JEOCIE_MASK BIT(0) 143 + #define DFSDM_CR2_JEOCIE(v) FIELD_PREP(DFSDM_CR2_JEOCIE_MASK, v) 144 + #define DFSDM_CR2_REOCIE_MASK BIT(1) 145 + #define DFSDM_CR2_REOCIE(v) FIELD_PREP(DFSDM_CR2_REOCIE_MASK, v) 146 + #define DFSDM_CR2_JOVRIE_MASK BIT(2) 147 + #define DFSDM_CR2_JOVRIE(v) FIELD_PREP(DFSDM_CR2_JOVRIE_MASK, v) 148 + #define DFSDM_CR2_ROVRIE_MASK BIT(3) 149 + #define DFSDM_CR2_ROVRIE(v) FIELD_PREP(DFSDM_CR2_ROVRIE_MASK, v) 150 + #define DFSDM_CR2_AWDIE_MASK BIT(4) 151 + #define DFSDM_CR2_AWDIE(v) FIELD_PREP(DFSDM_CR2_AWDIE_MASK, v) 152 + #define DFSDM_CR2_SCDIE_MASK BIT(5) 153 + #define DFSDM_CR2_SCDIE(v) FIELD_PREP(DFSDM_CR2_SCDIE_MASK, v) 154 + #define DFSDM_CR2_CKABIE_MASK BIT(6) 155 + #define DFSDM_CR2_CKABIE(v) FIELD_PREP(DFSDM_CR2_CKABIE_MASK, v) 156 + #define DFSDM_CR2_EXCH_MASK GENMASK(15, 8) 157 + #define DFSDM_CR2_EXCH(v) FIELD_PREP(DFSDM_CR2_EXCH_MASK, v) 158 + #define DFSDM_CR2_AWDCH_MASK GENMASK(23, 16) 159 + #define DFSDM_CR2_AWDCH(v) FIELD_PREP(DFSDM_CR2_AWDCH_MASK, v) 160 + 161 + /* ISR: Interrupt status register */ 162 + #define DFSDM_ISR_JEOCF_MASK BIT(0) 163 + #define DFSDM_ISR_JEOCF(v) FIELD_PREP(DFSDM_ISR_JEOCF_MASK, v) 164 + #define DFSDM_ISR_REOCF_MASK BIT(1) 165 + #define DFSDM_ISR_REOCF(v) FIELD_PREP(DFSDM_ISR_REOCF_MASK, v) 166 + #define DFSDM_ISR_JOVRF_MASK BIT(2) 167 + #define DFSDM_ISR_JOVRF(v) FIELD_PREP(DFSDM_ISR_JOVRF_MASK, v) 168 + #define DFSDM_ISR_ROVRF_MASK BIT(3) 169 + #define DFSDM_ISR_ROVRF(v) FIELD_PREP(DFSDM_ISR_ROVRF_MASK, v) 170 + #define DFSDM_ISR_AWDF_MASK BIT(4) 171 + #define DFSDM_ISR_AWDF(v) FIELD_PREP(DFSDM_ISR_AWDF_MASK, v) 172 + #define DFSDM_ISR_JCIP_MASK BIT(13) 173 + #define DFSDM_ISR_JCIP(v) FIELD_PREP(DFSDM_ISR_JCIP_MASK, v) 174 + #define DFSDM_ISR_RCIP_MASK BIT(14) 175 + #define DFSDM_ISR_RCIP(v) FIELD_PREP(DFSDM_ISR_RCIP, v) 176 + #define DFSDM_ISR_CKABF_MASK GENMASK(23, 16) 177 + #define DFSDM_ISR_CKABF(v) FIELD_PREP(DFSDM_ISR_CKABF_MASK, v) 178 + #define DFSDM_ISR_SCDF_MASK GENMASK(31, 24) 179 + #define DFSDM_ISR_SCDF(v) FIELD_PREP(DFSDM_ISR_SCDF_MASK, v) 180 + 181 + /* ICR: Interrupt flag clear register */ 182 + #define DFSDM_ICR_CLRJOVRF_MASK BIT(2) 183 + #define DFSDM_ICR_CLRJOVRF(v) FIELD_PREP(DFSDM_ICR_CLRJOVRF_MASK, v) 184 + #define DFSDM_ICR_CLRROVRF_MASK BIT(3) 185 + #define DFSDM_ICR_CLRROVRF(v) FIELD_PREP(DFSDM_ICR_CLRROVRF_MASK, v) 186 + #define DFSDM_ICR_CLRCKABF_MASK GENMASK(23, 16) 187 + #define DFSDM_ICR_CLRCKABF(v) FIELD_PREP(DFSDM_ICR_CLRCKABF_MASK, v) 188 + #define DFSDM_ICR_CLRCKABF_CH_MASK(y) BIT(16 + (y)) 189 + #define DFSDM_ICR_CLRCKABF_CH(v, y) \ 190 + (((v) << (16 + (y))) & DFSDM_ICR_CLRCKABF_CH_MASK(y)) 191 + #define DFSDM_ICR_CLRSCDF_MASK GENMASK(31, 24) 192 + #define DFSDM_ICR_CLRSCDF(v) FIELD_PREP(DFSDM_ICR_CLRSCDF_MASK, v) 193 + #define DFSDM_ICR_CLRSCDF_CH_MASK(y) BIT(24 + (y)) 194 + #define DFSDM_ICR_CLRSCDF_CH(v, y) \ 195 + (((v) << (24 + (y))) & DFSDM_ICR_CLRSCDF_MASK(y)) 196 + 197 + /* FCR: Filter control register */ 198 + #define DFSDM_FCR_IOSR_MASK GENMASK(7, 0) 199 + #define DFSDM_FCR_IOSR(v) FIELD_PREP(DFSDM_FCR_IOSR_MASK, v) 200 + #define DFSDM_FCR_FOSR_MASK GENMASK(25, 16) 201 + #define DFSDM_FCR_FOSR(v) FIELD_PREP(DFSDM_FCR_FOSR_MASK, v) 202 + #define DFSDM_FCR_FORD_MASK GENMASK(31, 29) 203 + #define DFSDM_FCR_FORD(v) FIELD_PREP(DFSDM_FCR_FORD_MASK, v) 204 + 205 + /* RDATAR: Filter data register for regular channel */ 206 + #define DFSDM_DATAR_CH_MASK GENMASK(2, 0) 207 + #define DFSDM_DATAR_DATA_OFFSET 8 208 + #define DFSDM_DATAR_DATA_MASK GENMASK(31, DFSDM_DATAR_DATA_OFFSET) 209 + 210 + /* AWLTR: Filter analog watchdog low threshold register */ 211 + #define DFSDM_AWLTR_BKAWL_MASK GENMASK(3, 0) 212 + #define DFSDM_AWLTR_BKAWL(v) FIELD_PREP(DFSDM_AWLTR_BKAWL_MASK, v) 213 + #define DFSDM_AWLTR_AWLT_MASK GENMASK(31, 8) 214 + #define DFSDM_AWLTR_AWLT(v) FIELD_PREP(DFSDM_AWLTR_AWLT_MASK, v) 215 + 216 + /* AWHTR: Filter analog watchdog low threshold register */ 217 + #define DFSDM_AWHTR_BKAWH_MASK GENMASK(3, 0) 218 + #define DFSDM_AWHTR_BKAWH(v) FIELD_PREP(DFSDM_AWHTR_BKAWH_MASK, v) 219 + #define DFSDM_AWHTR_AWHT_MASK GENMASK(31, 8) 220 + #define DFSDM_AWHTR_AWHT(v) FIELD_PREP(DFSDM_AWHTR_AWHT_MASK, v) 221 + 222 + /* AWSR: Filter watchdog status register */ 223 + #define DFSDM_AWSR_AWLTF_MASK GENMASK(7, 0) 224 + #define DFSDM_AWSR_AWLTF(v) FIELD_PREP(DFSDM_AWSR_AWLTF_MASK, v) 225 + #define DFSDM_AWSR_AWHTF_MASK GENMASK(15, 8) 226 + #define DFSDM_AWSR_AWHTF(v) FIELD_PREP(DFSDM_AWSR_AWHTF_MASK, v) 227 + 228 + /* AWCFR: Filter watchdog status register */ 229 + #define DFSDM_AWCFR_AWLTF_MASK GENMASK(7, 0) 230 + #define DFSDM_AWCFR_AWLTF(v) FIELD_PREP(DFSDM_AWCFR_AWLTF_MASK, v) 231 + #define DFSDM_AWCFR_AWHTF_MASK GENMASK(15, 8) 232 + #define DFSDM_AWCFR_AWHTF(v) FIELD_PREP(DFSDM_AWCFR_AWHTF_MASK, v) 233 + 234 + /* DFSDM filter order */ 235 + enum stm32_dfsdm_sinc_order { 236 + DFSDM_FASTSINC_ORDER, /* FastSinc filter type */ 237 + DFSDM_SINC1_ORDER, /* Sinc 1 filter type */ 238 + DFSDM_SINC2_ORDER, /* Sinc 2 filter type */ 239 + DFSDM_SINC3_ORDER, /* Sinc 3 filter type */ 240 + DFSDM_SINC4_ORDER, /* Sinc 4 filter type (N.A. for watchdog) */ 241 + DFSDM_SINC5_ORDER, /* Sinc 5 filter type (N.A. for watchdog) */ 242 + DFSDM_NB_SINC_ORDER, 243 + }; 244 + 245 + /** 246 + * struct stm32_dfsdm_filter - structure relative to stm32 FDSDM filter 247 + * @iosr: integrator oversampling 248 + * @fosr: filter oversampling 249 + * @ford: filter order 250 + * @res: output sample resolution 251 + * @sync_mode: filter synchronized with filter 0 252 + * @fast: filter fast mode 253 + */ 254 + struct stm32_dfsdm_filter { 255 + unsigned int iosr; 256 + unsigned int fosr; 257 + enum stm32_dfsdm_sinc_order ford; 258 + u64 res; 259 + unsigned int sync_mode; 260 + unsigned int fast; 261 + }; 262 + 263 + /** 264 + * struct stm32_dfsdm_channel - structure relative to stm32 FDSDM channel 265 + * @id: id of the channel 266 + * @type: interface type linked to stm32_dfsdm_chan_type 267 + * @src: interface type linked to stm32_dfsdm_chan_src 268 + * @alt_si: alternative serial input interface 269 + */ 270 + struct stm32_dfsdm_channel { 271 + unsigned int id; 272 + unsigned int type; 273 + unsigned int src; 274 + unsigned int alt_si; 275 + }; 276 + 277 + /** 278 + * struct stm32_dfsdm - stm32 FDSDM driver common data (for all instances) 279 + * @base: control registers base cpu addr 280 + * @phys_base: DFSDM IP register physical address 281 + * @regmap: regmap for register read/write 282 + * @fl_list: filter resources list 283 + * @num_fls: number of filter resources available 284 + * @ch_list: channel resources list 285 + * @num_chs: number of channel resources available 286 + * @spi_master_freq: SPI clock out frequency 287 + */ 288 + struct stm32_dfsdm { 289 + void __iomem *base; 290 + phys_addr_t phys_base; 291 + struct regmap *regmap; 292 + struct stm32_dfsdm_filter *fl_list; 293 + unsigned int num_fls; 294 + struct stm32_dfsdm_channel *ch_list; 295 + unsigned int num_chs; 296 + unsigned int spi_master_freq; 297 + }; 298 + 299 + /* DFSDM channel serial spi clock source */ 300 + enum stm32_dfsdm_spi_clk_src { 301 + DFSDM_CHANNEL_SPI_CLOCK_EXTERNAL, 302 + DFSDM_CHANNEL_SPI_CLOCK_INTERNAL, 303 + DFSDM_CHANNEL_SPI_CLOCK_INTERNAL_DIV2_FALLING, 304 + DFSDM_CHANNEL_SPI_CLOCK_INTERNAL_DIV2_RISING 305 + }; 306 + 307 + int stm32_dfsdm_start_dfsdm(struct stm32_dfsdm *dfsdm); 308 + int stm32_dfsdm_stop_dfsdm(struct stm32_dfsdm *dfsdm); 309 + 310 + #endif
+10
drivers/iio/buffer/Kconfig
··· 29 29 30 30 Should be selected by drivers that want to use this functionality. 31 31 32 + config IIO_BUFFER_HW_CONSUMER 33 + tristate "Industrial I/O HW buffering" 34 + help 35 + Provides a way to bonding when an IIO device has a direct connection 36 + to another device in hardware. In this case buffers for data transfers 37 + are handled by hardware. 38 + 39 + Should be selected by drivers that want to use the generic Hw consumer 40 + interface. 41 + 32 42 config IIO_KFIFO_BUF 33 43 tristate "Industrial I/O buffering based on kfifo" 34 44 help
+1
drivers/iio/buffer/Makefile
··· 7 7 obj-$(CONFIG_IIO_BUFFER_CB) += industrialio-buffer-cb.o 8 8 obj-$(CONFIG_IIO_BUFFER_DMA) += industrialio-buffer-dma.o 9 9 obj-$(CONFIG_IIO_BUFFER_DMAENGINE) += industrialio-buffer-dmaengine.o 10 + obj-$(CONFIG_IIO_BUFFER_HW_CONSUMER) += industrialio-hw-consumer.o 10 11 obj-$(CONFIG_IIO_TRIGGERED_BUFFER) += industrialio-triggered-buffer.o 11 12 obj-$(CONFIG_IIO_KFIFO_BUF) += kfifo_buf.o
+11
drivers/iio/buffer/industrialio-buffer-cb.c
··· 104 104 } 105 105 EXPORT_SYMBOL_GPL(iio_channel_get_all_cb); 106 106 107 + int iio_channel_cb_set_buffer_watermark(struct iio_cb_buffer *cb_buff, 108 + size_t watermark) 109 + { 110 + if (!watermark) 111 + return -EINVAL; 112 + cb_buff->buffer.watermark = watermark; 113 + 114 + return 0; 115 + } 116 + EXPORT_SYMBOL_GPL(iio_channel_cb_set_buffer_watermark); 117 + 107 118 int iio_channel_start_all_cb(struct iio_cb_buffer *cb_buff) 108 119 { 109 120 return iio_update_buffers(cb_buff->indio_dev, &cb_buff->buffer,
+247
drivers/iio/buffer/industrialio-hw-consumer.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright 2017 Analog Devices Inc. 4 + * Author: Lars-Peter Clausen <lars@metafoo.de> 5 + */ 6 + 7 + #include <linux/err.h> 8 + #include <linux/export.h> 9 + #include <linux/slab.h> 10 + #include <linux/module.h> 11 + 12 + #include <linux/iio/iio.h> 13 + #include <linux/iio/consumer.h> 14 + #include <linux/iio/hw-consumer.h> 15 + #include <linux/iio/buffer_impl.h> 16 + 17 + /** 18 + * struct iio_hw_consumer - IIO hw consumer block 19 + * @buffers: hardware buffers list head. 20 + * @channels: IIO provider channels. 21 + */ 22 + struct iio_hw_consumer { 23 + struct list_head buffers; 24 + struct iio_channel *channels; 25 + }; 26 + 27 + struct hw_consumer_buffer { 28 + struct list_head head; 29 + struct iio_dev *indio_dev; 30 + struct iio_buffer buffer; 31 + long scan_mask[]; 32 + }; 33 + 34 + static struct hw_consumer_buffer *iio_buffer_to_hw_consumer_buffer( 35 + struct iio_buffer *buffer) 36 + { 37 + return container_of(buffer, struct hw_consumer_buffer, buffer); 38 + } 39 + 40 + static void iio_hw_buf_release(struct iio_buffer *buffer) 41 + { 42 + struct hw_consumer_buffer *hw_buf = 43 + iio_buffer_to_hw_consumer_buffer(buffer); 44 + kfree(hw_buf); 45 + } 46 + 47 + static const struct iio_buffer_access_funcs iio_hw_buf_access = { 48 + .release = &iio_hw_buf_release, 49 + .modes = INDIO_BUFFER_HARDWARE, 50 + }; 51 + 52 + static struct hw_consumer_buffer *iio_hw_consumer_get_buffer( 53 + struct iio_hw_consumer *hwc, struct iio_dev *indio_dev) 54 + { 55 + size_t mask_size = BITS_TO_LONGS(indio_dev->masklength) * sizeof(long); 56 + struct hw_consumer_buffer *buf; 57 + 58 + list_for_each_entry(buf, &hwc->buffers, head) { 59 + if (buf->indio_dev == indio_dev) 60 + return buf; 61 + } 62 + 63 + buf = kzalloc(sizeof(*buf) + mask_size, GFP_KERNEL); 64 + if (!buf) 65 + return NULL; 66 + 67 + buf->buffer.access = &iio_hw_buf_access; 68 + buf->indio_dev = indio_dev; 69 + buf->buffer.scan_mask = buf->scan_mask; 70 + 71 + iio_buffer_init(&buf->buffer); 72 + list_add_tail(&buf->head, &hwc->buffers); 73 + 74 + return buf; 75 + } 76 + 77 + /** 78 + * iio_hw_consumer_alloc() - Allocate IIO hardware consumer 79 + * @dev: Pointer to consumer device. 80 + * 81 + * Returns a valid iio_hw_consumer on success or a ERR_PTR() on failure. 82 + */ 83 + struct iio_hw_consumer *iio_hw_consumer_alloc(struct device *dev) 84 + { 85 + struct hw_consumer_buffer *buf; 86 + struct iio_hw_consumer *hwc; 87 + struct iio_channel *chan; 88 + int ret; 89 + 90 + hwc = kzalloc(sizeof(*hwc), GFP_KERNEL); 91 + if (!hwc) 92 + return ERR_PTR(-ENOMEM); 93 + 94 + INIT_LIST_HEAD(&hwc->buffers); 95 + 96 + hwc->channels = iio_channel_get_all(dev); 97 + if (IS_ERR(hwc->channels)) { 98 + ret = PTR_ERR(hwc->channels); 99 + goto err_free_hwc; 100 + } 101 + 102 + chan = &hwc->channels[0]; 103 + while (chan->indio_dev) { 104 + buf = iio_hw_consumer_get_buffer(hwc, chan->indio_dev); 105 + if (!buf) { 106 + ret = -ENOMEM; 107 + goto err_put_buffers; 108 + } 109 + set_bit(chan->channel->scan_index, buf->buffer.scan_mask); 110 + chan++; 111 + } 112 + 113 + return hwc; 114 + 115 + err_put_buffers: 116 + list_for_each_entry(buf, &hwc->buffers, head) 117 + iio_buffer_put(&buf->buffer); 118 + iio_channel_release_all(hwc->channels); 119 + err_free_hwc: 120 + kfree(hwc); 121 + return ERR_PTR(ret); 122 + } 123 + EXPORT_SYMBOL_GPL(iio_hw_consumer_alloc); 124 + 125 + /** 126 + * iio_hw_consumer_free() - Free IIO hardware consumer 127 + * @hwc: hw consumer to free. 128 + */ 129 + void iio_hw_consumer_free(struct iio_hw_consumer *hwc) 130 + { 131 + struct hw_consumer_buffer *buf, *n; 132 + 133 + iio_channel_release_all(hwc->channels); 134 + list_for_each_entry_safe(buf, n, &hwc->buffers, head) 135 + iio_buffer_put(&buf->buffer); 136 + kfree(hwc); 137 + } 138 + EXPORT_SYMBOL_GPL(iio_hw_consumer_free); 139 + 140 + static void devm_iio_hw_consumer_release(struct device *dev, void *res) 141 + { 142 + iio_hw_consumer_free(*(struct iio_hw_consumer **)res); 143 + } 144 + 145 + static int devm_iio_hw_consumer_match(struct device *dev, void *res, void *data) 146 + { 147 + struct iio_hw_consumer **r = res; 148 + 149 + if (!r || !*r) { 150 + WARN_ON(!r || !*r); 151 + return 0; 152 + } 153 + return *r == data; 154 + } 155 + 156 + /** 157 + * devm_iio_hw_consumer_alloc - Resource-managed iio_hw_consumer_alloc() 158 + * @dev: Pointer to consumer device. 159 + * 160 + * Managed iio_hw_consumer_alloc. iio_hw_consumer allocated with this function 161 + * is automatically freed on driver detach. 162 + * 163 + * If an iio_hw_consumer allocated with this function needs to be freed 164 + * separately, devm_iio_hw_consumer_free() must be used. 165 + * 166 + * returns pointer to allocated iio_hw_consumer on success, NULL on failure. 167 + */ 168 + struct iio_hw_consumer *devm_iio_hw_consumer_alloc(struct device *dev) 169 + { 170 + struct iio_hw_consumer **ptr, *iio_hwc; 171 + 172 + ptr = devres_alloc(devm_iio_hw_consumer_release, sizeof(*ptr), 173 + GFP_KERNEL); 174 + if (!ptr) 175 + return NULL; 176 + 177 + iio_hwc = iio_hw_consumer_alloc(dev); 178 + if (IS_ERR(iio_hwc)) { 179 + devres_free(ptr); 180 + } else { 181 + *ptr = iio_hwc; 182 + devres_add(dev, ptr); 183 + } 184 + 185 + return iio_hwc; 186 + } 187 + EXPORT_SYMBOL_GPL(devm_iio_hw_consumer_alloc); 188 + 189 + /** 190 + * devm_iio_hw_consumer_free - Resource-managed iio_hw_consumer_free() 191 + * @dev: Pointer to consumer device. 192 + * @hwc: iio_hw_consumer to free. 193 + * 194 + * Free iio_hw_consumer allocated with devm_iio_hw_consumer_alloc(). 195 + */ 196 + void devm_iio_hw_consumer_free(struct device *dev, struct iio_hw_consumer *hwc) 197 + { 198 + int rc; 199 + 200 + rc = devres_release(dev, devm_iio_hw_consumer_release, 201 + devm_iio_hw_consumer_match, hwc); 202 + WARN_ON(rc); 203 + } 204 + EXPORT_SYMBOL_GPL(devm_iio_hw_consumer_free); 205 + 206 + /** 207 + * iio_hw_consumer_enable() - Enable IIO hardware consumer 208 + * @hwc: iio_hw_consumer to enable. 209 + * 210 + * Returns 0 on success. 211 + */ 212 + int iio_hw_consumer_enable(struct iio_hw_consumer *hwc) 213 + { 214 + struct hw_consumer_buffer *buf; 215 + int ret; 216 + 217 + list_for_each_entry(buf, &hwc->buffers, head) { 218 + ret = iio_update_buffers(buf->indio_dev, &buf->buffer, NULL); 219 + if (ret) 220 + goto err_disable_buffers; 221 + } 222 + 223 + return 0; 224 + 225 + err_disable_buffers: 226 + list_for_each_entry_continue_reverse(buf, &hwc->buffers, head) 227 + iio_update_buffers(buf->indio_dev, NULL, &buf->buffer); 228 + return ret; 229 + } 230 + EXPORT_SYMBOL_GPL(iio_hw_consumer_enable); 231 + 232 + /** 233 + * iio_hw_consumer_disable() - Disable IIO hardware consumer 234 + * @hwc: iio_hw_consumer to disable. 235 + */ 236 + void iio_hw_consumer_disable(struct iio_hw_consumer *hwc) 237 + { 238 + struct hw_consumer_buffer *buf; 239 + 240 + list_for_each_entry(buf, &hwc->buffers, head) 241 + iio_update_buffers(buf->indio_dev, NULL, &buf->buffer); 242 + } 243 + EXPORT_SYMBOL_GPL(iio_hw_consumer_disable); 244 + 245 + MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); 246 + MODULE_DESCRIPTION("Hardware consumer buffer the IIO framework"); 247 + MODULE_LICENSE("GPL v2");
+12 -5
drivers/iio/inkern.c
··· 664 664 } 665 665 EXPORT_SYMBOL_GPL(iio_convert_raw_to_processed); 666 666 667 - static int iio_read_channel_attribute(struct iio_channel *chan, 668 - int *val, int *val2, 669 - enum iio_chan_info_enum attribute) 667 + int iio_read_channel_attribute(struct iio_channel *chan, int *val, int *val2, 668 + enum iio_chan_info_enum attribute) 670 669 { 671 670 int ret; 672 671 ··· 681 682 682 683 return ret; 683 684 } 685 + EXPORT_SYMBOL_GPL(iio_read_channel_attribute); 684 686 685 687 int iio_read_channel_offset(struct iio_channel *chan, int *val, int *val2) 686 688 { ··· 850 850 chan->channel, val, val2, info); 851 851 } 852 852 853 - int iio_write_channel_raw(struct iio_channel *chan, int val) 853 + int iio_write_channel_attribute(struct iio_channel *chan, int val, int val2, 854 + enum iio_chan_info_enum attribute) 854 855 { 855 856 int ret; 856 857 ··· 861 860 goto err_unlock; 862 861 } 863 862 864 - ret = iio_channel_write(chan, val, 0, IIO_CHAN_INFO_RAW); 863 + ret = iio_channel_write(chan, val, val2, attribute); 865 864 err_unlock: 866 865 mutex_unlock(&chan->indio_dev->info_exist_lock); 867 866 868 867 return ret; 868 + } 869 + EXPORT_SYMBOL_GPL(iio_write_channel_attribute); 870 + 871 + int iio_write_channel_raw(struct iio_channel *chan, int val) 872 + { 873 + return iio_write_channel_attribute(chan, val, 0, IIO_CHAN_INFO_RAW); 869 874 } 870 875 EXPORT_SYMBOL_GPL(iio_write_channel_raw); 871 876
+18
include/linux/iio/adc/stm32-dfsdm-adc.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * This file discribe the STM32 DFSDM IIO driver API for audio part 4 + * 5 + * Copyright (C) 2017, STMicroelectronics - All Rights Reserved 6 + * Author(s): Arnaud Pouliquen <arnaud.pouliquen@st.com>. 7 + */ 8 + 9 + #ifndef STM32_DFSDM_ADC_H 10 + #define STM32_DFSDM_ADC_H 11 + 12 + int stm32_dfsdm_get_buff_cb(struct iio_dev *iio_dev, 13 + int (*cb)(const void *data, size_t size, 14 + void *private), 15 + void *private); 16 + int stm32_dfsdm_release_buff_cb(struct iio_dev *iio_dev); 17 + 18 + #endif
+37
include/linux/iio/consumer.h
··· 134 134 void *private), 135 135 void *private); 136 136 /** 137 + * iio_channel_cb_set_buffer_watermark() - set the buffer watermark. 138 + * @cb_buffer: The callback buffer from whom we want the channel 139 + * information. 140 + * @watermark: buffer watermark in bytes. 141 + * 142 + * This function allows to configure the buffer watermark. 143 + */ 144 + int iio_channel_cb_set_buffer_watermark(struct iio_cb_buffer *cb_buffer, 145 + size_t watermark); 146 + 147 + /** 137 148 * iio_channel_release_all_cb() - release and unregister the callback. 138 149 * @cb_buffer: The callback buffer that was allocated. 139 150 */ ··· 225 214 * do the appropriate transformation. 226 215 */ 227 216 int iio_read_channel_processed(struct iio_channel *chan, int *val); 217 + 218 + /** 219 + * iio_write_channel_attribute() - Write values to the device attribute. 220 + * @chan: The channel being queried. 221 + * @val: Value being written. 222 + * @val2: Value being written.val2 use depends on attribute type. 223 + * @attribute: info attribute to be read. 224 + * 225 + * Returns an error code or 0. 226 + */ 227 + int iio_write_channel_attribute(struct iio_channel *chan, int val, 228 + int val2, enum iio_chan_info_enum attribute); 229 + 230 + /** 231 + * iio_read_channel_attribute() - Read values from the device attribute. 232 + * @chan: The channel being queried. 233 + * @val: Value being written. 234 + * @val2: Value being written.Val2 use depends on attribute type. 235 + * @attribute: info attribute to be written. 236 + * 237 + * Returns an error code if failed. Else returns a description of what is in val 238 + * and val2, such as IIO_VAL_INT_PLUS_MICRO telling us we have a value of val 239 + * + val2/1e6 240 + */ 241 + int iio_read_channel_attribute(struct iio_channel *chan, int *val, 242 + int *val2, enum iio_chan_info_enum attribute); 228 243 229 244 /** 230 245 * iio_write_channel_raw() - write to a given channel
+21
include/linux/iio/hw-consumer.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Industrial I/O in kernel hardware consumer interface 4 + * 5 + * Copyright 2017 Analog Devices Inc. 6 + * Author: Lars-Peter Clausen <lars@metafoo.de> 7 + */ 8 + 9 + #ifndef LINUX_IIO_HW_CONSUMER_H 10 + #define LINUX_IIO_HW_CONSUMER_H 11 + 12 + struct iio_hw_consumer; 13 + 14 + struct iio_hw_consumer *iio_hw_consumer_alloc(struct device *dev); 15 + void iio_hw_consumer_free(struct iio_hw_consumer *hwc); 16 + struct iio_hw_consumer *devm_iio_hw_consumer_alloc(struct device *dev); 17 + void devm_iio_hw_consumer_free(struct device *dev, struct iio_hw_consumer *hwc); 18 + int iio_hw_consumer_enable(struct iio_hw_consumer *hwc); 19 + void iio_hw_consumer_disable(struct iio_hw_consumer *hwc); 20 + 21 + #endif
-28
include/linux/iio/iio.h
··· 20 20 * Currently assumes nano seconds. 21 21 */ 22 22 23 - enum iio_chan_info_enum { 24 - IIO_CHAN_INFO_RAW = 0, 25 - IIO_CHAN_INFO_PROCESSED, 26 - IIO_CHAN_INFO_SCALE, 27 - IIO_CHAN_INFO_OFFSET, 28 - IIO_CHAN_INFO_CALIBSCALE, 29 - IIO_CHAN_INFO_CALIBBIAS, 30 - IIO_CHAN_INFO_PEAK, 31 - IIO_CHAN_INFO_PEAK_SCALE, 32 - IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW, 33 - IIO_CHAN_INFO_AVERAGE_RAW, 34 - IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY, 35 - IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY, 36 - IIO_CHAN_INFO_SAMP_FREQ, 37 - IIO_CHAN_INFO_FREQUENCY, 38 - IIO_CHAN_INFO_PHASE, 39 - IIO_CHAN_INFO_HARDWAREGAIN, 40 - IIO_CHAN_INFO_HYSTERESIS, 41 - IIO_CHAN_INFO_INT_TIME, 42 - IIO_CHAN_INFO_ENABLE, 43 - IIO_CHAN_INFO_CALIBHEIGHT, 44 - IIO_CHAN_INFO_CALIBWEIGHT, 45 - IIO_CHAN_INFO_DEBOUNCE_COUNT, 46 - IIO_CHAN_INFO_DEBOUNCE_TIME, 47 - IIO_CHAN_INFO_CALIBEMISSIVITY, 48 - IIO_CHAN_INFO_OVERSAMPLING_RATIO, 49 - }; 50 - 51 23 enum iio_shared_by { 52 24 IIO_SEPARATE, 53 25 IIO_SHARED_BY_TYPE,
+28
include/linux/iio/types.h
··· 34 34 IIO_AVAIL_RANGE, 35 35 }; 36 36 37 + enum iio_chan_info_enum { 38 + IIO_CHAN_INFO_RAW = 0, 39 + IIO_CHAN_INFO_PROCESSED, 40 + IIO_CHAN_INFO_SCALE, 41 + IIO_CHAN_INFO_OFFSET, 42 + IIO_CHAN_INFO_CALIBSCALE, 43 + IIO_CHAN_INFO_CALIBBIAS, 44 + IIO_CHAN_INFO_PEAK, 45 + IIO_CHAN_INFO_PEAK_SCALE, 46 + IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW, 47 + IIO_CHAN_INFO_AVERAGE_RAW, 48 + IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY, 49 + IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY, 50 + IIO_CHAN_INFO_SAMP_FREQ, 51 + IIO_CHAN_INFO_FREQUENCY, 52 + IIO_CHAN_INFO_PHASE, 53 + IIO_CHAN_INFO_HARDWAREGAIN, 54 + IIO_CHAN_INFO_HYSTERESIS, 55 + IIO_CHAN_INFO_INT_TIME, 56 + IIO_CHAN_INFO_ENABLE, 57 + IIO_CHAN_INFO_CALIBHEIGHT, 58 + IIO_CHAN_INFO_CALIBWEIGHT, 59 + IIO_CHAN_INFO_DEBOUNCE_COUNT, 60 + IIO_CHAN_INFO_DEBOUNCE_TIME, 61 + IIO_CHAN_INFO_CALIBEMISSIVITY, 62 + IIO_CHAN_INFO_OVERSAMPLING_RATIO, 63 + }; 64 + 37 65 #endif /* _IIO_TYPES_H_ */
+5
sound/soc/codecs/Kconfig
··· 95 95 select SND_SOC_MAX98925 if I2C 96 96 select SND_SOC_MAX98926 if I2C 97 97 select SND_SOC_MAX98927 if I2C 98 + select SND_SOC_MAX98373 if I2C 98 99 select SND_SOC_MAX9850 if I2C 99 100 select SND_SOC_MAX9860 if I2C 100 101 select SND_SOC_MAX9768 if I2C ··· 623 622 624 623 config SND_SOC_MAX98927 625 624 tristate "Maxim Integrated MAX98927 Speaker Amplifier" 625 + depends on I2C 626 + 627 + config SND_SOC_MAX98373 628 + tristate "Maxim Integrated MAX98373 Speaker Amplifier" 626 629 depends on I2C 627 630 628 631 config SND_SOC_MAX9850
+2
sound/soc/codecs/Makefile
··· 90 90 snd-soc-max98925-objs := max98925.o 91 91 snd-soc-max98926-objs := max98926.o 92 92 snd-soc-max98927-objs := max98927.o 93 + snd-soc-max98373-objs := max98373.o 93 94 snd-soc-max9850-objs := max9850.o 94 95 snd-soc-max9860-objs := max9860.o 95 96 snd-soc-mc13783-objs := mc13783.o ··· 333 332 obj-$(CONFIG_SND_SOC_MAX98925) += snd-soc-max98925.o 334 333 obj-$(CONFIG_SND_SOC_MAX98926) += snd-soc-max98926.o 335 334 obj-$(CONFIG_SND_SOC_MAX98927) += snd-soc-max98927.o 335 + obj-$(CONFIG_SND_SOC_MAX98373) += snd-soc-max98373.o 336 336 obj-$(CONFIG_SND_SOC_MAX9850) += snd-soc-max9850.o 337 337 obj-$(CONFIG_SND_SOC_MAX9860) += snd-soc-max9860.o 338 338 obj-$(CONFIG_SND_SOC_MC13783) += snd-soc-mc13783.o
+976
sound/soc/codecs/max98373.c
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* Copyright (c) 2017, Maxim Integrated */ 3 + 4 + #include <linux/acpi.h> 5 + #include <linux/i2c.h> 6 + #include <linux/module.h> 7 + #include <linux/regmap.h> 8 + #include <linux/slab.h> 9 + #include <linux/cdev.h> 10 + #include <sound/pcm.h> 11 + #include <sound/pcm_params.h> 12 + #include <sound/soc.h> 13 + #include <linux/gpio.h> 14 + #include <linux/of_gpio.h> 15 + #include <sound/tlv.h> 16 + #include "max98373.h" 17 + 18 + static struct reg_default max98373_reg[] = { 19 + {MAX98373_R2000_SW_RESET, 0x00}, 20 + {MAX98373_R2001_INT_RAW1, 0x00}, 21 + {MAX98373_R2002_INT_RAW2, 0x00}, 22 + {MAX98373_R2003_INT_RAW3, 0x00}, 23 + {MAX98373_R2004_INT_STATE1, 0x00}, 24 + {MAX98373_R2005_INT_STATE2, 0x00}, 25 + {MAX98373_R2006_INT_STATE3, 0x00}, 26 + {MAX98373_R2007_INT_FLAG1, 0x00}, 27 + {MAX98373_R2008_INT_FLAG2, 0x00}, 28 + {MAX98373_R2009_INT_FLAG3, 0x00}, 29 + {MAX98373_R200A_INT_EN1, 0x00}, 30 + {MAX98373_R200B_INT_EN2, 0x00}, 31 + {MAX98373_R200C_INT_EN3, 0x00}, 32 + {MAX98373_R200D_INT_FLAG_CLR1, 0x00}, 33 + {MAX98373_R200E_INT_FLAG_CLR2, 0x00}, 34 + {MAX98373_R200F_INT_FLAG_CLR3, 0x00}, 35 + {MAX98373_R2010_IRQ_CTRL, 0x00}, 36 + {MAX98373_R2014_THERM_WARN_THRESH, 0x10}, 37 + {MAX98373_R2015_THERM_SHDN_THRESH, 0x27}, 38 + {MAX98373_R2016_THERM_HYSTERESIS, 0x01}, 39 + {MAX98373_R2017_THERM_FOLDBACK_SET, 0xC0}, 40 + {MAX98373_R2018_THERM_FOLDBACK_EN, 0x00}, 41 + {MAX98373_R201E_PIN_DRIVE_STRENGTH, 0x55}, 42 + {MAX98373_R2020_PCM_TX_HIZ_EN_1, 0xFE}, 43 + {MAX98373_R2021_PCM_TX_HIZ_EN_2, 0xFF}, 44 + {MAX98373_R2022_PCM_TX_SRC_1, 0x00}, 45 + {MAX98373_R2023_PCM_TX_SRC_2, 0x00}, 46 + {MAX98373_R2024_PCM_DATA_FMT_CFG, 0xC0}, 47 + {MAX98373_R2025_AUDIO_IF_MODE, 0x00}, 48 + {MAX98373_R2026_PCM_CLOCK_RATIO, 0x04}, 49 + {MAX98373_R2027_PCM_SR_SETUP_1, 0x08}, 50 + {MAX98373_R2028_PCM_SR_SETUP_2, 0x88}, 51 + {MAX98373_R2029_PCM_TO_SPK_MONO_MIX_1, 0x00}, 52 + {MAX98373_R202A_PCM_TO_SPK_MONO_MIX_2, 0x00}, 53 + {MAX98373_R202B_PCM_RX_EN, 0x00}, 54 + {MAX98373_R202C_PCM_TX_EN, 0x00}, 55 + {MAX98373_R202E_ICC_RX_CH_EN_1, 0x00}, 56 + {MAX98373_R202F_ICC_RX_CH_EN_2, 0x00}, 57 + {MAX98373_R2030_ICC_TX_HIZ_EN_1, 0xFF}, 58 + {MAX98373_R2031_ICC_TX_HIZ_EN_2, 0xFF}, 59 + {MAX98373_R2032_ICC_LINK_EN_CFG, 0x30}, 60 + {MAX98373_R2034_ICC_TX_CNTL, 0x00}, 61 + {MAX98373_R2035_ICC_TX_EN, 0x00}, 62 + {MAX98373_R2036_SOUNDWIRE_CTRL, 0x05}, 63 + {MAX98373_R203D_AMP_DIG_VOL_CTRL, 0x00}, 64 + {MAX98373_R203E_AMP_PATH_GAIN, 0x08}, 65 + {MAX98373_R203F_AMP_DSP_CFG, 0x02}, 66 + {MAX98373_R2040_TONE_GEN_CFG, 0x00}, 67 + {MAX98373_R2041_AMP_CFG, 0x03}, 68 + {MAX98373_R2042_AMP_EDGE_RATE_CFG, 0x00}, 69 + {MAX98373_R2043_AMP_EN, 0x00}, 70 + {MAX98373_R2046_IV_SENSE_ADC_DSP_CFG, 0x04}, 71 + {MAX98373_R2047_IV_SENSE_ADC_EN, 0x00}, 72 + {MAX98373_R2051_MEAS_ADC_SAMPLING_RATE, 0x00}, 73 + {MAX98373_R2052_MEAS_ADC_PVDD_FLT_CFG, 0x00}, 74 + {MAX98373_R2053_MEAS_ADC_THERM_FLT_CFG, 0x00}, 75 + {MAX98373_R2054_MEAS_ADC_PVDD_CH_READBACK, 0x00}, 76 + {MAX98373_R2055_MEAS_ADC_THERM_CH_READBACK, 0x00}, 77 + {MAX98373_R2056_MEAS_ADC_PVDD_CH_EN, 0x00}, 78 + {MAX98373_R2090_BDE_LVL_HOLD, 0x00}, 79 + {MAX98373_R2091_BDE_GAIN_ATK_REL_RATE, 0x00}, 80 + {MAX98373_R2092_BDE_CLIPPER_MODE, 0x00}, 81 + {MAX98373_R2097_BDE_L1_THRESH, 0x00}, 82 + {MAX98373_R2098_BDE_L2_THRESH, 0x00}, 83 + {MAX98373_R2099_BDE_L3_THRESH, 0x00}, 84 + {MAX98373_R209A_BDE_L4_THRESH, 0x00}, 85 + {MAX98373_R209B_BDE_THRESH_HYST, 0x00}, 86 + {MAX98373_R20A8_BDE_L1_CFG_1, 0x00}, 87 + {MAX98373_R20A9_BDE_L1_CFG_2, 0x00}, 88 + {MAX98373_R20AA_BDE_L1_CFG_3, 0x00}, 89 + {MAX98373_R20AB_BDE_L2_CFG_1, 0x00}, 90 + {MAX98373_R20AC_BDE_L2_CFG_2, 0x00}, 91 + {MAX98373_R20AD_BDE_L2_CFG_3, 0x00}, 92 + {MAX98373_R20AE_BDE_L3_CFG_1, 0x00}, 93 + {MAX98373_R20AF_BDE_L3_CFG_2, 0x00}, 94 + {MAX98373_R20B0_BDE_L3_CFG_3, 0x00}, 95 + {MAX98373_R20B1_BDE_L4_CFG_1, 0x00}, 96 + {MAX98373_R20B2_BDE_L4_CFG_2, 0x00}, 97 + {MAX98373_R20B3_BDE_L4_CFG_3, 0x00}, 98 + {MAX98373_R20B4_BDE_INFINITE_HOLD_RELEASE, 0x00}, 99 + {MAX98373_R20B5_BDE_EN, 0x00}, 100 + {MAX98373_R20B6_BDE_CUR_STATE_READBACK, 0x00}, 101 + {MAX98373_R20D1_DHT_CFG, 0x01}, 102 + {MAX98373_R20D2_DHT_ATTACK_CFG, 0x02}, 103 + {MAX98373_R20D3_DHT_RELEASE_CFG, 0x03}, 104 + {MAX98373_R20D4_DHT_EN, 0x00}, 105 + {MAX98373_R20E0_LIMITER_THRESH_CFG, 0x00}, 106 + {MAX98373_R20E1_LIMITER_ATK_REL_RATES, 0x00}, 107 + {MAX98373_R20E2_LIMITER_EN, 0x00}, 108 + {MAX98373_R20FE_DEVICE_AUTO_RESTART_CFG, 0x00}, 109 + {MAX98373_R20FF_GLOBAL_SHDN, 0x00}, 110 + {MAX98373_R21FF_REV_ID, 0x42}, 111 + }; 112 + 113 + static int max98373_dai_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) 114 + { 115 + struct snd_soc_codec *codec = codec_dai->codec; 116 + struct max98373_priv *max98373 = snd_soc_codec_get_drvdata(codec); 117 + unsigned int format = 0; 118 + unsigned int invert = 0; 119 + 120 + dev_dbg(codec->dev, "%s: fmt 0x%08X\n", __func__, fmt); 121 + 122 + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 123 + case SND_SOC_DAIFMT_NB_NF: 124 + break; 125 + case SND_SOC_DAIFMT_IB_NF: 126 + invert = MAX98373_PCM_MODE_CFG_PCM_BCLKEDGE; 127 + break; 128 + default: 129 + dev_err(codec->dev, "DAI invert mode unsupported\n"); 130 + return -EINVAL; 131 + } 132 + 133 + regmap_update_bits(max98373->regmap, 134 + MAX98373_R2026_PCM_CLOCK_RATIO, 135 + MAX98373_PCM_MODE_CFG_PCM_BCLKEDGE, 136 + invert); 137 + 138 + /* interface format */ 139 + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 140 + case SND_SOC_DAIFMT_I2S: 141 + format = MAX98373_PCM_FORMAT_I2S; 142 + break; 143 + case SND_SOC_DAIFMT_LEFT_J: 144 + format = MAX98373_PCM_FORMAT_LJ; 145 + break; 146 + case SND_SOC_DAIFMT_DSP_A: 147 + format = MAX98373_PCM_FORMAT_TDM_MODE1; 148 + break; 149 + case SND_SOC_DAIFMT_DSP_B: 150 + format = MAX98373_PCM_FORMAT_TDM_MODE0; 151 + break; 152 + default: 153 + return -EINVAL; 154 + } 155 + 156 + regmap_update_bits(max98373->regmap, 157 + MAX98373_R2024_PCM_DATA_FMT_CFG, 158 + MAX98373_PCM_MODE_CFG_FORMAT_MASK, 159 + format << MAX98373_PCM_MODE_CFG_FORMAT_SHIFT); 160 + 161 + return 0; 162 + } 163 + 164 + /* BCLKs per LRCLK */ 165 + static const int bclk_sel_table[] = { 166 + 32, 48, 64, 96, 128, 192, 256, 384, 512, 320, 167 + }; 168 + 169 + static int max98373_get_bclk_sel(int bclk) 170 + { 171 + int i; 172 + /* match BCLKs per LRCLK */ 173 + for (i = 0; i < ARRAY_SIZE(bclk_sel_table); i++) { 174 + if (bclk_sel_table[i] == bclk) 175 + return i + 2; 176 + } 177 + return 0; 178 + } 179 + 180 + static int max98373_set_clock(struct snd_soc_codec *codec, 181 + struct snd_pcm_hw_params *params) 182 + { 183 + struct max98373_priv *max98373 = snd_soc_codec_get_drvdata(codec); 184 + /* BCLK/LRCLK ratio calculation */ 185 + int blr_clk_ratio = params_channels(params) * max98373->ch_size; 186 + int value; 187 + 188 + if (!max98373->tdm_mode) { 189 + /* BCLK configuration */ 190 + value = max98373_get_bclk_sel(blr_clk_ratio); 191 + if (!value) { 192 + dev_err(codec->dev, "format unsupported %d\n", 193 + params_format(params)); 194 + return -EINVAL; 195 + } 196 + 197 + regmap_update_bits(max98373->regmap, 198 + MAX98373_R2026_PCM_CLOCK_RATIO, 199 + MAX98373_PCM_CLK_SETUP_BSEL_MASK, 200 + value); 201 + } 202 + return 0; 203 + } 204 + 205 + static int max98373_dai_hw_params(struct snd_pcm_substream *substream, 206 + struct snd_pcm_hw_params *params, 207 + struct snd_soc_dai *dai) 208 + { 209 + struct snd_soc_codec *codec = dai->codec; 210 + struct max98373_priv *max98373 = snd_soc_codec_get_drvdata(codec); 211 + unsigned int sampling_rate = 0; 212 + unsigned int chan_sz = 0; 213 + 214 + /* pcm mode configuration */ 215 + switch (snd_pcm_format_width(params_format(params))) { 216 + case 16: 217 + chan_sz = MAX98373_PCM_MODE_CFG_CHANSZ_16; 218 + break; 219 + case 24: 220 + chan_sz = MAX98373_PCM_MODE_CFG_CHANSZ_24; 221 + break; 222 + case 32: 223 + chan_sz = MAX98373_PCM_MODE_CFG_CHANSZ_32; 224 + break; 225 + default: 226 + dev_err(codec->dev, "format unsupported %d\n", 227 + params_format(params)); 228 + goto err; 229 + } 230 + 231 + max98373->ch_size = snd_pcm_format_width(params_format(params)); 232 + 233 + regmap_update_bits(max98373->regmap, 234 + MAX98373_R2024_PCM_DATA_FMT_CFG, 235 + MAX98373_PCM_MODE_CFG_CHANSZ_MASK, chan_sz); 236 + 237 + dev_dbg(codec->dev, "format supported %d", 238 + params_format(params)); 239 + 240 + /* sampling rate configuration */ 241 + switch (params_rate(params)) { 242 + case 8000: 243 + sampling_rate = MAX98373_PCM_SR_SET1_SR_8000; 244 + break; 245 + case 11025: 246 + sampling_rate = MAX98373_PCM_SR_SET1_SR_11025; 247 + break; 248 + case 12000: 249 + sampling_rate = MAX98373_PCM_SR_SET1_SR_12000; 250 + break; 251 + case 16000: 252 + sampling_rate = MAX98373_PCM_SR_SET1_SR_16000; 253 + break; 254 + case 22050: 255 + sampling_rate = MAX98373_PCM_SR_SET1_SR_22050; 256 + break; 257 + case 24000: 258 + sampling_rate = MAX98373_PCM_SR_SET1_SR_24000; 259 + break; 260 + case 32000: 261 + sampling_rate = MAX98373_PCM_SR_SET1_SR_32000; 262 + break; 263 + case 44100: 264 + sampling_rate = MAX98373_PCM_SR_SET1_SR_44100; 265 + break; 266 + case 48000: 267 + sampling_rate = MAX98373_PCM_SR_SET1_SR_48000; 268 + break; 269 + default: 270 + dev_err(codec->dev, "rate %d not supported\n", 271 + params_rate(params)); 272 + goto err; 273 + } 274 + 275 + /* set DAI_SR to correct LRCLK frequency */ 276 + regmap_update_bits(max98373->regmap, 277 + MAX98373_R2027_PCM_SR_SETUP_1, 278 + MAX98373_PCM_SR_SET1_SR_MASK, 279 + sampling_rate); 280 + regmap_update_bits(max98373->regmap, 281 + MAX98373_R2028_PCM_SR_SETUP_2, 282 + MAX98373_PCM_SR_SET2_SR_MASK, 283 + sampling_rate << MAX98373_PCM_SR_SET2_SR_SHIFT); 284 + 285 + /* set sampling rate of IV */ 286 + if (max98373->interleave_mode && 287 + sampling_rate > MAX98373_PCM_SR_SET1_SR_16000) 288 + regmap_update_bits(max98373->regmap, 289 + MAX98373_R2028_PCM_SR_SETUP_2, 290 + MAX98373_PCM_SR_SET2_IVADC_SR_MASK, 291 + sampling_rate - 3); 292 + else 293 + regmap_update_bits(max98373->regmap, 294 + MAX98373_R2028_PCM_SR_SETUP_2, 295 + MAX98373_PCM_SR_SET2_IVADC_SR_MASK, 296 + sampling_rate); 297 + 298 + return max98373_set_clock(codec, params); 299 + err: 300 + return -EINVAL; 301 + } 302 + 303 + static int max98373_dai_tdm_slot(struct snd_soc_dai *dai, 304 + unsigned int tx_mask, unsigned int rx_mask, 305 + int slots, int slot_width) 306 + { 307 + struct snd_soc_codec *codec = dai->codec; 308 + struct max98373_priv *max98373 = snd_soc_codec_get_drvdata(codec); 309 + int bsel = 0; 310 + unsigned int chan_sz = 0; 311 + unsigned int mask; 312 + int x, slot_found; 313 + 314 + if (!tx_mask && !rx_mask && !slots && !slot_width) 315 + max98373->tdm_mode = false; 316 + else 317 + max98373->tdm_mode = true; 318 + 319 + /* BCLK configuration */ 320 + bsel = max98373_get_bclk_sel(slots * slot_width); 321 + if (bsel == 0) { 322 + dev_err(codec->dev, "BCLK %d not supported\n", 323 + slots * slot_width); 324 + return -EINVAL; 325 + } 326 + 327 + regmap_update_bits(max98373->regmap, 328 + MAX98373_R2026_PCM_CLOCK_RATIO, 329 + MAX98373_PCM_CLK_SETUP_BSEL_MASK, 330 + bsel); 331 + 332 + /* Channel size configuration */ 333 + switch (slot_width) { 334 + case 16: 335 + chan_sz = MAX98373_PCM_MODE_CFG_CHANSZ_16; 336 + break; 337 + case 24: 338 + chan_sz = MAX98373_PCM_MODE_CFG_CHANSZ_24; 339 + break; 340 + case 32: 341 + chan_sz = MAX98373_PCM_MODE_CFG_CHANSZ_32; 342 + break; 343 + default: 344 + dev_err(codec->dev, "format unsupported %d\n", 345 + slot_width); 346 + return -EINVAL; 347 + } 348 + 349 + regmap_update_bits(max98373->regmap, 350 + MAX98373_R2024_PCM_DATA_FMT_CFG, 351 + MAX98373_PCM_MODE_CFG_CHANSZ_MASK, chan_sz); 352 + 353 + /* Rx slot configuration */ 354 + slot_found = 0; 355 + mask = rx_mask; 356 + for (x = 0 ; x < 16 ; x++, mask >>= 1) { 357 + if (mask & 0x1) { 358 + if (slot_found == 0) 359 + regmap_update_bits(max98373->regmap, 360 + MAX98373_R2029_PCM_TO_SPK_MONO_MIX_1, 361 + MAX98373_PCM_TO_SPK_CH0_SRC_MASK, x); 362 + else 363 + regmap_write(max98373->regmap, 364 + MAX98373_R202A_PCM_TO_SPK_MONO_MIX_2, 365 + x); 366 + slot_found++; 367 + if (slot_found > 1) 368 + break; 369 + } 370 + } 371 + 372 + /* Tx slot Hi-Z configuration */ 373 + regmap_write(max98373->regmap, 374 + MAX98373_R2020_PCM_TX_HIZ_EN_1, 375 + ~tx_mask & 0xFF); 376 + regmap_write(max98373->regmap, 377 + MAX98373_R2021_PCM_TX_HIZ_EN_2, 378 + (~tx_mask & 0xFF00) >> 8); 379 + 380 + return 0; 381 + } 382 + 383 + #define MAX98373_RATES SNDRV_PCM_RATE_8000_96000 384 + 385 + #define MAX98373_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ 386 + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) 387 + 388 + static const struct snd_soc_dai_ops max98373_dai_ops = { 389 + .set_fmt = max98373_dai_set_fmt, 390 + .hw_params = max98373_dai_hw_params, 391 + .set_tdm_slot = max98373_dai_tdm_slot, 392 + }; 393 + 394 + static int max98373_dac_event(struct snd_soc_dapm_widget *w, 395 + struct snd_kcontrol *kcontrol, int event) 396 + { 397 + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); 398 + struct max98373_priv *max98373 = snd_soc_codec_get_drvdata(codec); 399 + 400 + switch (event) { 401 + case SND_SOC_DAPM_POST_PMU: 402 + regmap_update_bits(max98373->regmap, 403 + MAX98373_R20FF_GLOBAL_SHDN, 404 + MAX98373_GLOBAL_EN_MASK, 1); 405 + break; 406 + case SND_SOC_DAPM_POST_PMD: 407 + regmap_update_bits(max98373->regmap, 408 + MAX98373_R20FF_GLOBAL_SHDN, 409 + MAX98373_GLOBAL_EN_MASK, 0); 410 + max98373->tdm_mode = 0; 411 + break; 412 + default: 413 + return 0; 414 + } 415 + return 0; 416 + } 417 + 418 + static const char * const max98373_switch_text[] = { 419 + "Left", "Right", "LeftRight"}; 420 + 421 + static const struct soc_enum dai_sel_enum = 422 + SOC_ENUM_SINGLE(MAX98373_R2029_PCM_TO_SPK_MONO_MIX_1, 423 + MAX98373_PCM_TO_SPK_MONOMIX_CFG_SHIFT, 424 + 3, max98373_switch_text); 425 + 426 + static const struct snd_kcontrol_new max98373_dai_controls = 427 + SOC_DAPM_ENUM("DAI Sel", dai_sel_enum); 428 + 429 + static const struct snd_kcontrol_new max98373_vi_control = 430 + SOC_DAPM_SINGLE("Switch", MAX98373_R202C_PCM_TX_EN, 0, 1, 0); 431 + 432 + static const struct snd_kcontrol_new max98373_spkfb_control = 433 + SOC_DAPM_SINGLE("Switch", MAX98373_R2043_AMP_EN, 1, 1, 0); 434 + 435 + static const struct snd_soc_dapm_widget max98373_dapm_widgets[] = { 436 + SND_SOC_DAPM_DAC_E("Amp Enable", "HiFi Playback", 437 + MAX98373_R202B_PCM_RX_EN, 0, 0, max98373_dac_event, 438 + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), 439 + SND_SOC_DAPM_MUX("DAI Sel Mux", SND_SOC_NOPM, 0, 0, 440 + &max98373_dai_controls), 441 + SND_SOC_DAPM_OUTPUT("BE_OUT"), 442 + SND_SOC_DAPM_AIF_OUT("Voltage Sense", "HiFi Capture", 0, 443 + MAX98373_R2047_IV_SENSE_ADC_EN, 0, 0), 444 + SND_SOC_DAPM_AIF_OUT("Current Sense", "HiFi Capture", 0, 445 + MAX98373_R2047_IV_SENSE_ADC_EN, 1, 0), 446 + SND_SOC_DAPM_AIF_OUT("Speaker FB Sense", "HiFi Capture", 0, 447 + SND_SOC_NOPM, 0, 0), 448 + SND_SOC_DAPM_SWITCH("VI Sense", SND_SOC_NOPM, 0, 0, 449 + &max98373_vi_control), 450 + SND_SOC_DAPM_SWITCH("SpkFB Sense", SND_SOC_NOPM, 0, 0, 451 + &max98373_spkfb_control), 452 + SND_SOC_DAPM_SIGGEN("VMON"), 453 + SND_SOC_DAPM_SIGGEN("IMON"), 454 + SND_SOC_DAPM_SIGGEN("FBMON"), 455 + }; 456 + 457 + static DECLARE_TLV_DB_SCALE(max98373_digital_tlv, 0, -50, 0); 458 + static const DECLARE_TLV_DB_RANGE(max98373_spk_tlv, 459 + 0, 8, TLV_DB_SCALE_ITEM(0, 50, 0), 460 + 9, 10, TLV_DB_SCALE_ITEM(500, 100, 0), 461 + ); 462 + static const DECLARE_TLV_DB_RANGE(max98373_spkgain_max_tlv, 463 + 0, 9, TLV_DB_SCALE_ITEM(800, 100, 0), 464 + ); 465 + static const DECLARE_TLV_DB_RANGE(max98373_dht_step_size_tlv, 466 + 0, 1, TLV_DB_SCALE_ITEM(25, 25, 0), 467 + 2, 4, TLV_DB_SCALE_ITEM(100, 100, 0), 468 + ); 469 + static const DECLARE_TLV_DB_RANGE(max98373_dht_spkgain_min_tlv, 470 + 0, 9, TLV_DB_SCALE_ITEM(800, 100, 0), 471 + ); 472 + static const DECLARE_TLV_DB_RANGE(max98373_dht_rotation_point_tlv, 473 + 0, 1, TLV_DB_SCALE_ITEM(-50, -50, 0), 474 + 2, 7, TLV_DB_SCALE_ITEM(-200, -100, 0), 475 + 8, 9, TLV_DB_SCALE_ITEM(-1000, -200, 0), 476 + 10, 11, TLV_DB_SCALE_ITEM(-1500, -300, 0), 477 + 12, 13, TLV_DB_SCALE_ITEM(-2000, -200, 0), 478 + 14, 15, TLV_DB_SCALE_ITEM(-2500, -500, 0), 479 + ); 480 + static const DECLARE_TLV_DB_RANGE(max98373_limiter_thresh_tlv, 481 + 0, 15, TLV_DB_SCALE_ITEM(0, -100, 0), 482 + ); 483 + 484 + static const DECLARE_TLV_DB_RANGE(max98373_bde_gain_tlv, 485 + 0, 60, TLV_DB_SCALE_ITEM(0, -25, 0), 486 + ); 487 + 488 + static bool max98373_readable_register(struct device *dev, unsigned int reg) 489 + { 490 + switch (reg) { 491 + case MAX98373_R2001_INT_RAW1 ... MAX98373_R200C_INT_EN3: 492 + case MAX98373_R2010_IRQ_CTRL: 493 + case MAX98373_R2014_THERM_WARN_THRESH 494 + ... MAX98373_R2018_THERM_FOLDBACK_EN: 495 + case MAX98373_R201E_PIN_DRIVE_STRENGTH 496 + ... MAX98373_R2036_SOUNDWIRE_CTRL: 497 + case MAX98373_R203D_AMP_DIG_VOL_CTRL ... MAX98373_R2043_AMP_EN: 498 + case MAX98373_R2046_IV_SENSE_ADC_DSP_CFG 499 + ... MAX98373_R2047_IV_SENSE_ADC_EN: 500 + case MAX98373_R2051_MEAS_ADC_SAMPLING_RATE 501 + ... MAX98373_R2056_MEAS_ADC_PVDD_CH_EN: 502 + case MAX98373_R2090_BDE_LVL_HOLD ... MAX98373_R2092_BDE_CLIPPER_MODE: 503 + case MAX98373_R2097_BDE_L1_THRESH 504 + ... MAX98373_R209B_BDE_THRESH_HYST: 505 + case MAX98373_R20A8_BDE_L1_CFG_1 ... MAX98373_R20B3_BDE_L4_CFG_3: 506 + case MAX98373_R20B5_BDE_EN ... MAX98373_R20B6_BDE_CUR_STATE_READBACK: 507 + case MAX98373_R20D1_DHT_CFG ... MAX98373_R20D4_DHT_EN: 508 + case MAX98373_R20E0_LIMITER_THRESH_CFG ... MAX98373_R20E2_LIMITER_EN: 509 + case MAX98373_R20FE_DEVICE_AUTO_RESTART_CFG 510 + ... MAX98373_R20FF_GLOBAL_SHDN: 511 + case MAX98373_R21FF_REV_ID: 512 + return true; 513 + default: 514 + return false; 515 + } 516 + }; 517 + 518 + static bool max98373_volatile_reg(struct device *dev, unsigned int reg) 519 + { 520 + switch (reg) { 521 + case MAX98373_R2000_SW_RESET ... MAX98373_R2009_INT_FLAG3: 522 + case MAX98373_R2054_MEAS_ADC_PVDD_CH_READBACK: 523 + case MAX98373_R2055_MEAS_ADC_THERM_CH_READBACK: 524 + case MAX98373_R20B6_BDE_CUR_STATE_READBACK: 525 + case MAX98373_R21FF_REV_ID: 526 + return true; 527 + default: 528 + return false; 529 + } 530 + } 531 + 532 + static const char * const max98373_output_voltage_lvl_text[] = { 533 + "5.43V", "6.09V", "6.83V", "7.67V", "8.60V", 534 + "9.65V", "10.83V", "12.15V", "13.63V", "15.29V" 535 + }; 536 + 537 + static SOC_ENUM_SINGLE_DECL(max98373_out_volt_enum, 538 + MAX98373_R203E_AMP_PATH_GAIN, 0, 539 + max98373_output_voltage_lvl_text); 540 + 541 + static const char * const max98373_dht_attack_rate_text[] = { 542 + "17.5us", "35us", "70us", "140us", 543 + "280us", "560us", "1120us", "2240us" 544 + }; 545 + 546 + static SOC_ENUM_SINGLE_DECL(max98373_dht_attack_rate_enum, 547 + MAX98373_R20D2_DHT_ATTACK_CFG, 0, 548 + max98373_dht_attack_rate_text); 549 + 550 + static const char * const max98373_dht_release_rate_text[] = { 551 + "45ms", "225ms", "450ms", "1150ms", 552 + "2250ms", "3100ms", "4500ms", "6750ms" 553 + }; 554 + 555 + static SOC_ENUM_SINGLE_DECL(max98373_dht_release_rate_enum, 556 + MAX98373_R20D3_DHT_RELEASE_CFG, 0, 557 + max98373_dht_release_rate_text); 558 + 559 + static const char * const max98373_limiter_attack_rate_text[] = { 560 + "10us", "20us", "40us", "80us", 561 + "160us", "320us", "640us", "1.28ms", 562 + "2.56ms", "5.12ms", "10.24ms", "20.48ms", 563 + "40.96ms", "81.92ms", "16.384ms", "32.768ms" 564 + }; 565 + 566 + static SOC_ENUM_SINGLE_DECL(max98373_limiter_attack_rate_enum, 567 + MAX98373_R20E1_LIMITER_ATK_REL_RATES, 4, 568 + max98373_limiter_attack_rate_text); 569 + 570 + static const char * const max98373_limiter_release_rate_text[] = { 571 + "40us", "80us", "160us", "320us", 572 + "640us", "1.28ms", "2.56ms", "5.120ms", 573 + "10.24ms", "20.48ms", "40.96ms", "81.92ms", 574 + "163.84ms", "327.68ms", "655.36ms", "1310.72ms" 575 + }; 576 + 577 + static SOC_ENUM_SINGLE_DECL(max98373_limiter_release_rate_enum, 578 + MAX98373_R20E1_LIMITER_ATK_REL_RATES, 0, 579 + max98373_limiter_release_rate_text); 580 + 581 + static const char * const max98373_ADC_samplerate_text[] = { 582 + "333kHz", "192kHz", "64kHz", "48kHz" 583 + }; 584 + 585 + static SOC_ENUM_SINGLE_DECL(max98373_adc_samplerate_enum, 586 + MAX98373_R2051_MEAS_ADC_SAMPLING_RATE, 0, 587 + max98373_ADC_samplerate_text); 588 + 589 + static const struct snd_kcontrol_new max98373_snd_controls[] = { 590 + SOC_SINGLE("Digital Vol Sel Switch", MAX98373_R203F_AMP_DSP_CFG, 591 + MAX98373_AMP_VOL_SEL_SHIFT, 1, 0), 592 + SOC_SINGLE("Volume Location Switch", MAX98373_R203F_AMP_DSP_CFG, 593 + MAX98373_AMP_VOL_SEL_SHIFT, 1, 0), 594 + SOC_SINGLE("Ramp Up Switch", MAX98373_R203F_AMP_DSP_CFG, 595 + MAX98373_AMP_DSP_CFG_RMP_UP_SHIFT, 1, 0), 596 + SOC_SINGLE("Ramp Down Switch", MAX98373_R203F_AMP_DSP_CFG, 597 + MAX98373_AMP_DSP_CFG_RMP_DN_SHIFT, 1, 0), 598 + SOC_SINGLE("CLK Monitor Switch", MAX98373_R20FE_DEVICE_AUTO_RESTART_CFG, 599 + MAX98373_CLOCK_MON_SHIFT, 1, 0), 600 + SOC_SINGLE("Dither Switch", MAX98373_R203F_AMP_DSP_CFG, 601 + MAX98373_AMP_DSP_CFG_DITH_SHIFT, 1, 0), 602 + SOC_SINGLE("DC Blocker Switch", MAX98373_R203F_AMP_DSP_CFG, 603 + MAX98373_AMP_DSP_CFG_DCBLK_SHIFT, 1, 0), 604 + SOC_SINGLE_TLV("Digital Volume", MAX98373_R203D_AMP_DIG_VOL_CTRL, 605 + 0, 0x7F, 0, max98373_digital_tlv), 606 + SOC_SINGLE_TLV("Speaker Volume", MAX98373_R203E_AMP_PATH_GAIN, 607 + MAX98373_SPK_DIGI_GAIN_SHIFT, 10, 0, max98373_spk_tlv), 608 + SOC_SINGLE_TLV("FS Max Volume", MAX98373_R203E_AMP_PATH_GAIN, 609 + MAX98373_FS_GAIN_MAX_SHIFT, 9, 0, max98373_spkgain_max_tlv), 610 + SOC_ENUM("Output Voltage", max98373_out_volt_enum), 611 + /* Dynamic Headroom Tracking */ 612 + SOC_SINGLE("DHT Switch", MAX98373_R20D4_DHT_EN, 613 + MAX98373_DHT_EN_SHIFT, 1, 0), 614 + SOC_SINGLE_TLV("DHT Min Volume", MAX98373_R20D1_DHT_CFG, 615 + MAX98373_DHT_SPK_GAIN_MIN_SHIFT, 9, 0, max98373_dht_spkgain_min_tlv), 616 + SOC_SINGLE_TLV("DHT Rot Pnt Volume", MAX98373_R20D1_DHT_CFG, 617 + MAX98373_DHT_ROT_PNT_SHIFT, 15, 0, max98373_dht_rotation_point_tlv), 618 + SOC_SINGLE_TLV("DHT Attack Step Volume", MAX98373_R20D2_DHT_ATTACK_CFG, 619 + MAX98373_DHT_ATTACK_STEP_SHIFT, 4, 0, max98373_dht_step_size_tlv), 620 + SOC_SINGLE_TLV("DHT Release Step Volume", MAX98373_R20D3_DHT_RELEASE_CFG, 621 + MAX98373_DHT_RELEASE_STEP_SHIFT, 4, 0, max98373_dht_step_size_tlv), 622 + SOC_ENUM("DHT Attack Rate", max98373_dht_attack_rate_enum), 623 + SOC_ENUM("DHT Release Rate", max98373_dht_release_rate_enum), 624 + /* ADC configuration */ 625 + SOC_SINGLE("ADC PVDD CH Switch", MAX98373_R2056_MEAS_ADC_PVDD_CH_EN, 0, 1, 0), 626 + SOC_SINGLE("ADC PVDD FLT Switch", MAX98373_R2052_MEAS_ADC_PVDD_FLT_CFG, 627 + MAX98373_FLT_EN_SHIFT, 1, 0), 628 + SOC_SINGLE("ADC TEMP FLT Switch", MAX98373_R2053_MEAS_ADC_THERM_FLT_CFG, 629 + MAX98373_FLT_EN_SHIFT, 1, 0), 630 + SOC_SINGLE("ADC PVDD", MAX98373_R2054_MEAS_ADC_PVDD_CH_READBACK, 0, 0xFF, 0), 631 + SOC_SINGLE("ADC TEMP", MAX98373_R2055_MEAS_ADC_THERM_CH_READBACK, 0, 0xFF, 0), 632 + SOC_SINGLE("ADC PVDD FLT Coeff", MAX98373_R2052_MEAS_ADC_PVDD_FLT_CFG, 633 + 0, 0x3, 0), 634 + SOC_SINGLE("ADC TEMP FLT Coeff", MAX98373_R2053_MEAS_ADC_THERM_FLT_CFG, 635 + 0, 0x3, 0), 636 + SOC_ENUM("ADC SampleRate", max98373_adc_samplerate_enum), 637 + /* Brownout Detection Engine */ 638 + SOC_SINGLE("BDE Switch", MAX98373_R20B5_BDE_EN, MAX98373_BDE_EN_SHIFT, 1, 0), 639 + SOC_SINGLE("BDE LVL4 Mute Switch", MAX98373_R20B2_BDE_L4_CFG_2, 640 + MAX98373_LVL4_MUTE_EN_SHIFT, 1, 0), 641 + SOC_SINGLE("BDE LVL4 Hold Switch", MAX98373_R20B2_BDE_L4_CFG_2, 642 + MAX98373_LVL4_HOLD_EN_SHIFT, 1, 0), 643 + SOC_SINGLE("BDE LVL1 Thresh", MAX98373_R2097_BDE_L1_THRESH, 0, 0xFF, 0), 644 + SOC_SINGLE("BDE LVL2 Thresh", MAX98373_R2098_BDE_L2_THRESH, 0, 0xFF, 0), 645 + SOC_SINGLE("BDE LVL3 Thresh", MAX98373_R2099_BDE_L3_THRESH, 0, 0xFF, 0), 646 + SOC_SINGLE("BDE LVL4 Thresh", MAX98373_R209A_BDE_L4_THRESH, 0, 0xFF, 0), 647 + SOC_SINGLE("BDE Active Level", MAX98373_R20B6_BDE_CUR_STATE_READBACK, 0, 8, 0), 648 + SOC_SINGLE("BDE Clip Mode Switch", MAX98373_R2092_BDE_CLIPPER_MODE, 0, 1, 0), 649 + SOC_SINGLE("BDE Thresh Hysteresis", MAX98373_R209B_BDE_THRESH_HYST, 0, 0xFF, 0), 650 + SOC_SINGLE("BDE Hold Time", MAX98373_R2090_BDE_LVL_HOLD, 0, 0xFF, 0), 651 + SOC_SINGLE("BDE Attack Rate", MAX98373_R2091_BDE_GAIN_ATK_REL_RATE, 4, 0xF, 0), 652 + SOC_SINGLE("BDE Release Rate", MAX98373_R2091_BDE_GAIN_ATK_REL_RATE, 0, 0xF, 0), 653 + SOC_SINGLE_TLV("BDE LVL1 Clip Thresh Volume", MAX98373_R20A9_BDE_L1_CFG_2, 654 + 0, 0x3C, 0, max98373_bde_gain_tlv), 655 + SOC_SINGLE_TLV("BDE LVL2 Clip Thresh Volume", MAX98373_R20AC_BDE_L2_CFG_2, 656 + 0, 0x3C, 0, max98373_bde_gain_tlv), 657 + SOC_SINGLE_TLV("BDE LVL3 Clip Thresh Volume", MAX98373_R20AF_BDE_L3_CFG_2, 658 + 0, 0x3C, 0, max98373_bde_gain_tlv), 659 + SOC_SINGLE_TLV("BDE LVL4 Clip Thresh Volume", MAX98373_R20B2_BDE_L4_CFG_2, 660 + 0, 0x3C, 0, max98373_bde_gain_tlv), 661 + SOC_SINGLE_TLV("BDE LVL1 Clip Reduction Volume", MAX98373_R20AA_BDE_L1_CFG_3, 662 + 0, 0x3C, 0, max98373_bde_gain_tlv), 663 + SOC_SINGLE_TLV("BDE LVL2 Clip Reduction Volume", MAX98373_R20AD_BDE_L2_CFG_3, 664 + 0, 0x3C, 0, max98373_bde_gain_tlv), 665 + SOC_SINGLE_TLV("BDE LVL3 Clip Reduction Volume", MAX98373_R20B0_BDE_L3_CFG_3, 666 + 0, 0x3C, 0, max98373_bde_gain_tlv), 667 + SOC_SINGLE_TLV("BDE LVL4 Clip Reduction Volume", MAX98373_R20B3_BDE_L4_CFG_3, 668 + 0, 0x3C, 0, max98373_bde_gain_tlv), 669 + SOC_SINGLE_TLV("BDE LVL1 Limiter Thresh Volume", MAX98373_R20A8_BDE_L1_CFG_1, 670 + 0, 0xF, 0, max98373_limiter_thresh_tlv), 671 + SOC_SINGLE_TLV("BDE LVL2 Limiter Thresh Volume", MAX98373_R20AB_BDE_L2_CFG_1, 672 + 0, 0xF, 0, max98373_limiter_thresh_tlv), 673 + SOC_SINGLE_TLV("BDE LVL3 Limiter Thresh Volume", MAX98373_R20AE_BDE_L3_CFG_1, 674 + 0, 0xF, 0, max98373_limiter_thresh_tlv), 675 + SOC_SINGLE_TLV("BDE LVL4 Limiter Thresh Volume", MAX98373_R20B1_BDE_L4_CFG_1, 676 + 0, 0xF, 0, max98373_limiter_thresh_tlv), 677 + /* Limiter */ 678 + SOC_SINGLE("Limiter Switch", MAX98373_R20E2_LIMITER_EN, 679 + MAX98373_LIMITER_EN_SHIFT, 1, 0), 680 + SOC_SINGLE("Limiter Src Switch", MAX98373_R20E0_LIMITER_THRESH_CFG, 681 + MAX98373_LIMITER_THRESH_SRC_SHIFT, 1, 0), 682 + SOC_SINGLE_TLV("Limiter Thresh Volume", MAX98373_R20E0_LIMITER_THRESH_CFG, 683 + MAX98373_LIMITER_THRESH_SHIFT, 15, 0, max98373_limiter_thresh_tlv), 684 + SOC_ENUM("Limiter Attack Rate", max98373_limiter_attack_rate_enum), 685 + SOC_ENUM("Limiter Release Rate", max98373_limiter_release_rate_enum), 686 + }; 687 + 688 + static const struct snd_soc_dapm_route max98373_audio_map[] = { 689 + /* Plabyack */ 690 + {"DAI Sel Mux", "Left", "Amp Enable"}, 691 + {"DAI Sel Mux", "Right", "Amp Enable"}, 692 + {"DAI Sel Mux", "LeftRight", "Amp Enable"}, 693 + {"BE_OUT", NULL, "DAI Sel Mux"}, 694 + /* Capture */ 695 + { "VI Sense", "Switch", "VMON" }, 696 + { "VI Sense", "Switch", "IMON" }, 697 + { "SpkFB Sense", "Switch", "FBMON" }, 698 + { "Voltage Sense", NULL, "VI Sense" }, 699 + { "Current Sense", NULL, "VI Sense" }, 700 + { "Speaker FB Sense", NULL, "SpkFB Sense" }, 701 + }; 702 + 703 + static struct snd_soc_dai_driver max98373_dai[] = { 704 + { 705 + .name = "max98373-aif1", 706 + .playback = { 707 + .stream_name = "HiFi Playback", 708 + .channels_min = 1, 709 + .channels_max = 2, 710 + .rates = MAX98373_RATES, 711 + .formats = MAX98373_FORMATS, 712 + }, 713 + .capture = { 714 + .stream_name = "HiFi Capture", 715 + .channels_min = 1, 716 + .channels_max = 2, 717 + .rates = MAX98373_RATES, 718 + .formats = MAX98373_FORMATS, 719 + }, 720 + .ops = &max98373_dai_ops, 721 + } 722 + }; 723 + 724 + static int max98373_probe(struct snd_soc_codec *codec) 725 + { 726 + struct max98373_priv *max98373 = snd_soc_codec_get_drvdata(codec); 727 + 728 + codec->control_data = max98373->regmap; 729 + 730 + /* Software Reset */ 731 + regmap_write(max98373->regmap, 732 + MAX98373_R2000_SW_RESET, MAX98373_SOFT_RESET); 733 + 734 + /* IV default slot configuration */ 735 + regmap_write(max98373->regmap, 736 + MAX98373_R2020_PCM_TX_HIZ_EN_1, 737 + 0xFF); 738 + regmap_write(max98373->regmap, 739 + MAX98373_R2021_PCM_TX_HIZ_EN_2, 740 + 0xFF); 741 + /* L/R mix configuration */ 742 + regmap_write(max98373->regmap, 743 + MAX98373_R2029_PCM_TO_SPK_MONO_MIX_1, 744 + 0x80); 745 + regmap_write(max98373->regmap, 746 + MAX98373_R202A_PCM_TO_SPK_MONO_MIX_2, 747 + 0x1); 748 + /* Set inital volume (0dB) */ 749 + regmap_write(max98373->regmap, 750 + MAX98373_R203D_AMP_DIG_VOL_CTRL, 751 + 0x00); 752 + regmap_write(max98373->regmap, 753 + MAX98373_R203E_AMP_PATH_GAIN, 754 + 0x00); 755 + /* Enable DC blocker */ 756 + regmap_write(max98373->regmap, 757 + MAX98373_R203F_AMP_DSP_CFG, 758 + 0x3); 759 + /* Enable IMON VMON DC blocker */ 760 + regmap_write(max98373->regmap, 761 + MAX98373_R2046_IV_SENSE_ADC_DSP_CFG, 762 + 0x7); 763 + /* voltage, current slot configuration */ 764 + regmap_write(max98373->regmap, 765 + MAX98373_R2022_PCM_TX_SRC_1, 766 + (max98373->i_slot << MAX98373_PCM_TX_CH_SRC_A_I_SHIFT | 767 + max98373->v_slot) & 0xFF); 768 + if (max98373->v_slot < 8) 769 + regmap_update_bits(max98373->regmap, 770 + MAX98373_R2020_PCM_TX_HIZ_EN_1, 771 + 1 << max98373->v_slot, 0); 772 + else 773 + regmap_update_bits(max98373->regmap, 774 + MAX98373_R2021_PCM_TX_HIZ_EN_2, 775 + 1 << (max98373->v_slot - 8), 0); 776 + 777 + if (max98373->i_slot < 8) 778 + regmap_update_bits(max98373->regmap, 779 + MAX98373_R2020_PCM_TX_HIZ_EN_1, 780 + 1 << max98373->i_slot, 0); 781 + else 782 + regmap_update_bits(max98373->regmap, 783 + MAX98373_R2021_PCM_TX_HIZ_EN_2, 784 + 1 << (max98373->i_slot - 8), 0); 785 + 786 + /* speaker feedback slot configuration */ 787 + regmap_write(max98373->regmap, 788 + MAX98373_R2023_PCM_TX_SRC_2, 789 + max98373->spkfb_slot & 0xFF); 790 + 791 + /* Set interleave mode */ 792 + if (max98373->interleave_mode) 793 + regmap_update_bits(max98373->regmap, 794 + MAX98373_R2024_PCM_DATA_FMT_CFG, 795 + MAX98373_PCM_TX_CH_INTERLEAVE_MASK, 796 + MAX98373_PCM_TX_CH_INTERLEAVE_MASK); 797 + 798 + /* Speaker enable */ 799 + regmap_update_bits(max98373->regmap, 800 + MAX98373_R2043_AMP_EN, 801 + MAX98373_SPK_EN_MASK, 1); 802 + 803 + return 0; 804 + } 805 + 806 + #ifdef CONFIG_PM_SLEEP 807 + static int max98373_suspend(struct device *dev) 808 + { 809 + struct max98373_priv *max98373 = dev_get_drvdata(dev); 810 + 811 + regcache_cache_only(max98373->regmap, true); 812 + regcache_mark_dirty(max98373->regmap); 813 + return 0; 814 + } 815 + static int max98373_resume(struct device *dev) 816 + { 817 + struct max98373_priv *max98373 = dev_get_drvdata(dev); 818 + 819 + regmap_write(max98373->regmap, 820 + MAX98373_R2000_SW_RESET, MAX98373_SOFT_RESET); 821 + regcache_cache_only(max98373->regmap, false); 822 + regcache_sync(max98373->regmap); 823 + return 0; 824 + } 825 + #endif 826 + 827 + static const struct dev_pm_ops max98373_pm = { 828 + SET_SYSTEM_SLEEP_PM_OPS(max98373_suspend, max98373_resume) 829 + }; 830 + 831 + static const struct snd_soc_codec_driver soc_codec_dev_max98373 = { 832 + .probe = max98373_probe, 833 + .component_driver = { 834 + .controls = max98373_snd_controls, 835 + .num_controls = ARRAY_SIZE(max98373_snd_controls), 836 + .dapm_widgets = max98373_dapm_widgets, 837 + .num_dapm_widgets = ARRAY_SIZE(max98373_dapm_widgets), 838 + .dapm_routes = max98373_audio_map, 839 + .num_dapm_routes = ARRAY_SIZE(max98373_audio_map), 840 + }, 841 + }; 842 + 843 + static const struct regmap_config max98373_regmap = { 844 + .reg_bits = 16, 845 + .val_bits = 8, 846 + .max_register = MAX98373_R21FF_REV_ID, 847 + .reg_defaults = max98373_reg, 848 + .num_reg_defaults = ARRAY_SIZE(max98373_reg), 849 + .readable_reg = max98373_readable_register, 850 + .volatile_reg = max98373_volatile_reg, 851 + .cache_type = REGCACHE_RBTREE, 852 + }; 853 + 854 + static void max98373_slot_config(struct i2c_client *i2c, 855 + struct max98373_priv *max98373) 856 + { 857 + int value; 858 + struct device *dev = &i2c->dev; 859 + 860 + if (!device_property_read_u32(dev, "maxim,vmon-slot-no", &value)) 861 + max98373->v_slot = value & 0xF; 862 + else 863 + max98373->v_slot = 0; 864 + 865 + if (!device_property_read_u32(dev, "maxim,imon-slot-no", &value)) 866 + max98373->i_slot = value & 0xF; 867 + else 868 + max98373->i_slot = 1; 869 + 870 + if (!device_property_read_u32(dev, "maxim,spkfb-slot-no", &value)) 871 + max98373->spkfb_slot = value & 0xF; 872 + else 873 + max98373->spkfb_slot = 2; 874 + } 875 + 876 + static int max98373_i2c_probe(struct i2c_client *i2c, 877 + const struct i2c_device_id *id) 878 + { 879 + 880 + int ret = 0; 881 + int reg = 0; 882 + struct max98373_priv *max98373 = NULL; 883 + 884 + max98373 = devm_kzalloc(&i2c->dev, sizeof(*max98373), GFP_KERNEL); 885 + 886 + if (!max98373) { 887 + ret = -ENOMEM; 888 + return ret; 889 + } 890 + i2c_set_clientdata(i2c, max98373); 891 + 892 + /* update interleave mode info */ 893 + if (device_property_read_bool(&i2c->dev, "maxim,interleave_mode")) 894 + max98373->interleave_mode = 1; 895 + else 896 + max98373->interleave_mode = 0; 897 + 898 + 899 + /* regmap initialization */ 900 + max98373->regmap 901 + = devm_regmap_init_i2c(i2c, &max98373_regmap); 902 + if (IS_ERR(max98373->regmap)) { 903 + ret = PTR_ERR(max98373->regmap); 904 + dev_err(&i2c->dev, 905 + "Failed to allocate regmap: %d\n", ret); 906 + return ret; 907 + } 908 + 909 + /* Check Revision ID */ 910 + ret = regmap_read(max98373->regmap, 911 + MAX98373_R21FF_REV_ID, &reg); 912 + if (ret < 0) { 913 + dev_err(&i2c->dev, 914 + "Failed to read: 0x%02X\n", MAX98373_R21FF_REV_ID); 915 + return ret; 916 + } 917 + dev_info(&i2c->dev, "MAX98373 revisionID: 0x%02X\n", reg); 918 + 919 + /* voltage/current slot configuration */ 920 + max98373_slot_config(i2c, max98373); 921 + 922 + /* codec registeration */ 923 + ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_max98373, 924 + max98373_dai, ARRAY_SIZE(max98373_dai)); 925 + if (ret < 0) 926 + dev_err(&i2c->dev, "Failed to register codec: %d\n", ret); 927 + 928 + return ret; 929 + } 930 + 931 + static int max98373_i2c_remove(struct i2c_client *client) 932 + { 933 + snd_soc_unregister_codec(&client->dev); 934 + return 0; 935 + } 936 + 937 + static const struct i2c_device_id max98373_i2c_id[] = { 938 + { "max98373", 0}, 939 + { }, 940 + }; 941 + 942 + MODULE_DEVICE_TABLE(i2c, max98373_i2c_id); 943 + 944 + #if defined(CONFIG_OF) 945 + static const struct of_device_id max98373_of_match[] = { 946 + { .compatible = "maxim,max98373", }, 947 + { } 948 + }; 949 + MODULE_DEVICE_TABLE(of, max98373_of_match); 950 + #endif 951 + 952 + #ifdef CONFIG_ACPI 953 + static const struct acpi_device_id max98373_acpi_match[] = { 954 + { "MX98373", 0 }, 955 + {}, 956 + }; 957 + MODULE_DEVICE_TABLE(acpi, max98373_acpi_match); 958 + #endif 959 + 960 + static struct i2c_driver max98373_i2c_driver = { 961 + .driver = { 962 + .name = "max98373", 963 + .of_match_table = of_match_ptr(max98373_of_match), 964 + .acpi_match_table = ACPI_PTR(max98373_acpi_match), 965 + .pm = &max98373_pm, 966 + }, 967 + .probe = max98373_i2c_probe, 968 + .remove = max98373_i2c_remove, 969 + .id_table = max98373_i2c_id, 970 + }; 971 + 972 + module_i2c_driver(max98373_i2c_driver) 973 + 974 + MODULE_DESCRIPTION("ALSA SoC MAX98373 driver"); 975 + MODULE_AUTHOR("Ryan Lee <ryans.lee@maximintegrated.com>"); 976 + MODULE_LICENSE("GPL");
+212
sound/soc/codecs/max98373.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* Copyright (c) 2017, Maxim Integrated */ 3 + #ifndef _MAX98373_H 4 + #define _MAX98373_H 5 + 6 + #define MAX98373_R2000_SW_RESET 0x2000 7 + #define MAX98373_R2001_INT_RAW1 0x2001 8 + #define MAX98373_R2002_INT_RAW2 0x2002 9 + #define MAX98373_R2003_INT_RAW3 0x2003 10 + #define MAX98373_R2004_INT_STATE1 0x2004 11 + #define MAX98373_R2005_INT_STATE2 0x2005 12 + #define MAX98373_R2006_INT_STATE3 0x2006 13 + #define MAX98373_R2007_INT_FLAG1 0x2007 14 + #define MAX98373_R2008_INT_FLAG2 0x2008 15 + #define MAX98373_R2009_INT_FLAG3 0x2009 16 + #define MAX98373_R200A_INT_EN1 0x200A 17 + #define MAX98373_R200B_INT_EN2 0x200B 18 + #define MAX98373_R200C_INT_EN3 0x200C 19 + #define MAX98373_R200D_INT_FLAG_CLR1 0x200D 20 + #define MAX98373_R200E_INT_FLAG_CLR2 0x200E 21 + #define MAX98373_R200F_INT_FLAG_CLR3 0x200F 22 + #define MAX98373_R2010_IRQ_CTRL 0x2010 23 + #define MAX98373_R2014_THERM_WARN_THRESH 0x2014 24 + #define MAX98373_R2015_THERM_SHDN_THRESH 0x2015 25 + #define MAX98373_R2016_THERM_HYSTERESIS 0x2016 26 + #define MAX98373_R2017_THERM_FOLDBACK_SET 0x2017 27 + #define MAX98373_R2018_THERM_FOLDBACK_EN 0x2018 28 + #define MAX98373_R201E_PIN_DRIVE_STRENGTH 0x201E 29 + #define MAX98373_R2020_PCM_TX_HIZ_EN_1 0x2020 30 + #define MAX98373_R2021_PCM_TX_HIZ_EN_2 0x2021 31 + #define MAX98373_R2022_PCM_TX_SRC_1 0x2022 32 + #define MAX98373_R2023_PCM_TX_SRC_2 0x2023 33 + #define MAX98373_R2024_PCM_DATA_FMT_CFG 0x2024 34 + #define MAX98373_R2025_AUDIO_IF_MODE 0x2025 35 + #define MAX98373_R2026_PCM_CLOCK_RATIO 0x2026 36 + #define MAX98373_R2027_PCM_SR_SETUP_1 0x2027 37 + #define MAX98373_R2028_PCM_SR_SETUP_2 0x2028 38 + #define MAX98373_R2029_PCM_TO_SPK_MONO_MIX_1 0x2029 39 + #define MAX98373_R202A_PCM_TO_SPK_MONO_MIX_2 0x202A 40 + #define MAX98373_R202B_PCM_RX_EN 0x202B 41 + #define MAX98373_R202C_PCM_TX_EN 0x202C 42 + #define MAX98373_R202E_ICC_RX_CH_EN_1 0x202E 43 + #define MAX98373_R202F_ICC_RX_CH_EN_2 0x202F 44 + #define MAX98373_R2030_ICC_TX_HIZ_EN_1 0x2030 45 + #define MAX98373_R2031_ICC_TX_HIZ_EN_2 0x2031 46 + #define MAX98373_R2032_ICC_LINK_EN_CFG 0x2032 47 + #define MAX98373_R2034_ICC_TX_CNTL 0x2034 48 + #define MAX98373_R2035_ICC_TX_EN 0x2035 49 + #define MAX98373_R2036_SOUNDWIRE_CTRL 0x2036 50 + #define MAX98373_R203D_AMP_DIG_VOL_CTRL 0x203D 51 + #define MAX98373_R203E_AMP_PATH_GAIN 0x203E 52 + #define MAX98373_R203F_AMP_DSP_CFG 0x203F 53 + #define MAX98373_R2040_TONE_GEN_CFG 0x2040 54 + #define MAX98373_R2041_AMP_CFG 0x2041 55 + #define MAX98373_R2042_AMP_EDGE_RATE_CFG 0x2042 56 + #define MAX98373_R2043_AMP_EN 0x2043 57 + #define MAX98373_R2046_IV_SENSE_ADC_DSP_CFG 0x2046 58 + #define MAX98373_R2047_IV_SENSE_ADC_EN 0x2047 59 + #define MAX98373_R2051_MEAS_ADC_SAMPLING_RATE 0x2051 60 + #define MAX98373_R2052_MEAS_ADC_PVDD_FLT_CFG 0x2052 61 + #define MAX98373_R2053_MEAS_ADC_THERM_FLT_CFG 0x2053 62 + #define MAX98373_R2054_MEAS_ADC_PVDD_CH_READBACK 0x2054 63 + #define MAX98373_R2055_MEAS_ADC_THERM_CH_READBACK 0x2055 64 + #define MAX98373_R2056_MEAS_ADC_PVDD_CH_EN 0x2056 65 + #define MAX98373_R2090_BDE_LVL_HOLD 0x2090 66 + #define MAX98373_R2091_BDE_GAIN_ATK_REL_RATE 0x2091 67 + #define MAX98373_R2092_BDE_CLIPPER_MODE 0x2092 68 + #define MAX98373_R2097_BDE_L1_THRESH 0x2097 69 + #define MAX98373_R2098_BDE_L2_THRESH 0x2098 70 + #define MAX98373_R2099_BDE_L3_THRESH 0x2099 71 + #define MAX98373_R209A_BDE_L4_THRESH 0x209A 72 + #define MAX98373_R209B_BDE_THRESH_HYST 0x209B 73 + #define MAX98373_R20A8_BDE_L1_CFG_1 0x20A8 74 + #define MAX98373_R20A9_BDE_L1_CFG_2 0x20A9 75 + #define MAX98373_R20AA_BDE_L1_CFG_3 0x20AA 76 + #define MAX98373_R20AB_BDE_L2_CFG_1 0x20AB 77 + #define MAX98373_R20AC_BDE_L2_CFG_2 0x20AC 78 + #define MAX98373_R20AD_BDE_L2_CFG_3 0x20AD 79 + #define MAX98373_R20AE_BDE_L3_CFG_1 0x20AE 80 + #define MAX98373_R20AF_BDE_L3_CFG_2 0x20AF 81 + #define MAX98373_R20B0_BDE_L3_CFG_3 0x20B0 82 + #define MAX98373_R20B1_BDE_L4_CFG_1 0x20B1 83 + #define MAX98373_R20B2_BDE_L4_CFG_2 0x20B2 84 + #define MAX98373_R20B3_BDE_L4_CFG_3 0x20B3 85 + #define MAX98373_R20B4_BDE_INFINITE_HOLD_RELEASE 0x20B4 86 + #define MAX98373_R20B5_BDE_EN 0x20B5 87 + #define MAX98373_R20B6_BDE_CUR_STATE_READBACK 0x20B6 88 + #define MAX98373_R20D1_DHT_CFG 0x20D1 89 + #define MAX98373_R20D2_DHT_ATTACK_CFG 0x20D2 90 + #define MAX98373_R20D3_DHT_RELEASE_CFG 0x20D3 91 + #define MAX98373_R20D4_DHT_EN 0x20D4 92 + #define MAX98373_R20E0_LIMITER_THRESH_CFG 0x20E0 93 + #define MAX98373_R20E1_LIMITER_ATK_REL_RATES 0x20E1 94 + #define MAX98373_R20E2_LIMITER_EN 0x20E2 95 + #define MAX98373_R20FE_DEVICE_AUTO_RESTART_CFG 0x20FE 96 + #define MAX98373_R20FF_GLOBAL_SHDN 0x20FF 97 + #define MAX98373_R21FF_REV_ID 0x21FF 98 + 99 + /* MAX98373_R2022_PCM_TX_SRC_1 */ 100 + #define MAX98373_PCM_TX_CH_SRC_A_V_SHIFT (0) 101 + #define MAX98373_PCM_TX_CH_SRC_A_I_SHIFT (4) 102 + 103 + /* MAX98373_R2024_PCM_DATA_FMT_CFG */ 104 + #define MAX98373_PCM_MODE_CFG_FORMAT_MASK (0x7 << 3) 105 + #define MAX98373_PCM_MODE_CFG_FORMAT_SHIFT (3) 106 + #define MAX98373_PCM_TX_CH_INTERLEAVE_MASK (0x1 << 2) 107 + #define MAX98373_PCM_FORMAT_I2S (0x0 << 0) 108 + #define MAX98373_PCM_FORMAT_LJ (0x1 << 0) 109 + #define MAX98373_PCM_FORMAT_TDM_MODE0 (0x3 << 0) 110 + #define MAX98373_PCM_FORMAT_TDM_MODE1 (0x4 << 0) 111 + #define MAX98373_PCM_FORMAT_TDM_MODE2 (0x5 << 0) 112 + #define MAX98373_PCM_MODE_CFG_CHANSZ_MASK (0x3 << 6) 113 + #define MAX98373_PCM_MODE_CFG_CHANSZ_16 (0x1 << 6) 114 + #define MAX98373_PCM_MODE_CFG_CHANSZ_24 (0x2 << 6) 115 + #define MAX98373_PCM_MODE_CFG_CHANSZ_32 (0x3 << 6) 116 + 117 + /* MAX98373_R2026_PCM_CLOCK_RATIO */ 118 + #define MAX98373_PCM_MODE_CFG_PCM_BCLKEDGE (0x1 << 4) 119 + #define MAX98373_PCM_CLK_SETUP_BSEL_MASK (0xF << 0) 120 + 121 + /* MAX98373_R2027_PCM_SR_SETUP_1 */ 122 + #define MAX98373_PCM_SR_SET1_SR_MASK (0xF << 0) 123 + #define MAX98373_PCM_SR_SET1_SR_8000 (0x0 << 0) 124 + #define MAX98373_PCM_SR_SET1_SR_11025 (0x1 << 0) 125 + #define MAX98373_PCM_SR_SET1_SR_12000 (0x2 << 0) 126 + #define MAX98373_PCM_SR_SET1_SR_16000 (0x3 << 0) 127 + #define MAX98373_PCM_SR_SET1_SR_22050 (0x4 << 0) 128 + #define MAX98373_PCM_SR_SET1_SR_24000 (0x5 << 0) 129 + #define MAX98373_PCM_SR_SET1_SR_32000 (0x6 << 0) 130 + #define MAX98373_PCM_SR_SET1_SR_44100 (0x7 << 0) 131 + #define MAX98373_PCM_SR_SET1_SR_48000 (0x8 << 0) 132 + 133 + /* MAX98373_R2028_PCM_SR_SETUP_2 */ 134 + #define MAX98373_PCM_SR_SET2_SR_MASK (0xF << 4) 135 + #define MAX98373_PCM_SR_SET2_SR_SHIFT (4) 136 + #define MAX98373_PCM_SR_SET2_IVADC_SR_MASK (0xF << 0) 137 + 138 + /* MAX98373_R2029_PCM_TO_SPK_MONO_MIX_1 */ 139 + #define MAX98373_PCM_TO_SPK_MONOMIX_CFG_MASK (0x3 << 6) 140 + #define MAX98373_PCM_TO_SPK_MONOMIX_CFG_SHIFT (6) 141 + #define MAX98373_PCM_TO_SPK_CH0_SRC_MASK (0xF << 0) 142 + 143 + /* MAX98373_R203E_AMP_PATH_GAIN */ 144 + #define MAX98373_SPK_DIGI_GAIN_MASK (0xF << 4) 145 + #define MAX98373_SPK_DIGI_GAIN_SHIFT (4) 146 + #define MAX98373_FS_GAIN_MAX_MASK (0xF << 0) 147 + #define MAX98373_FS_GAIN_MAX_SHIFT (0) 148 + 149 + /* MAX98373_R203F_AMP_DSP_CFG */ 150 + #define MAX98373_AMP_DSP_CFG_DCBLK_SHIFT (0) 151 + #define MAX98373_AMP_DSP_CFG_DITH_SHIFT (1) 152 + #define MAX98373_AMP_DSP_CFG_RMP_UP_SHIFT (2) 153 + #define MAX98373_AMP_DSP_CFG_RMP_DN_SHIFT (3) 154 + #define MAX98373_AMP_DSP_CFG_DAC_INV_SHIFT (5) 155 + #define MAX98373_AMP_VOL_SEL_SHIFT (7) 156 + 157 + /* MAX98373_R2043_AMP_EN */ 158 + #define MAX98373_SPKFB_EN_MASK (0x1 << 1) 159 + #define MAX98373_SPK_EN_MASK (0x1 << 0) 160 + #define MAX98373_SPKFB_EN_SHIFT (1) 161 + 162 + /*MAX98373_R2052_MEAS_ADC_PVDD_FLT_CFG */ 163 + #define MAX98373_FLT_EN_SHIFT (4) 164 + 165 + /* MAX98373_R20B2_BDE_L4_CFG_2 */ 166 + #define MAX98373_LVL4_MUTE_EN_SHIFT (7) 167 + #define MAX98373_LVL4_HOLD_EN_SHIFT (6) 168 + 169 + /* MAX98373_R20B5_BDE_EN */ 170 + #define MAX98373_BDE_EN_SHIFT (0) 171 + 172 + /* MAX98373_R20D1_DHT_CFG */ 173 + #define MAX98373_DHT_SPK_GAIN_MIN_SHIFT (4) 174 + #define MAX98373_DHT_ROT_PNT_SHIFT (0) 175 + 176 + /* MAX98373_R20D2_DHT_ATTACK_CFG */ 177 + #define MAX98373_DHT_ATTACK_STEP_SHIFT (3) 178 + #define MAX98373_DHT_ATTACK_RATE_SHIFT (0) 179 + 180 + /* MAX98373_R20D3_DHT_RELEASE_CFG */ 181 + #define MAX98373_DHT_RELEASE_STEP_SHIFT (3) 182 + #define MAX98373_DHT_RELEASE_RATE_SHIFT (0) 183 + 184 + /* MAX98373_R20D4_DHT_EN */ 185 + #define MAX98373_DHT_EN_SHIFT (0) 186 + 187 + /* MAX98373_R20E0_LIMITER_THRESH_CFG */ 188 + #define MAX98373_LIMITER_THRESH_SHIFT (2) 189 + #define MAX98373_LIMITER_THRESH_SRC_SHIFT (0) 190 + 191 + /* MAX98373_R20E2_LIMITER_EN */ 192 + #define MAX98373_LIMITER_EN_SHIFT (0) 193 + 194 + /* MAX98373_R20FE_DEVICE_AUTO_RESTART_CFG */ 195 + #define MAX98373_CLOCK_MON_SHIFT (0) 196 + 197 + /* MAX98373_R20FF_GLOBAL_SHDN */ 198 + #define MAX98373_GLOBAL_EN_MASK (0x1 << 0) 199 + 200 + /* MAX98373_R2000_SW_RESET */ 201 + #define MAX98373_SOFT_RESET (0x1 << 0) 202 + 203 + struct max98373_priv { 204 + struct regmap *regmap; 205 + unsigned int v_slot; 206 + unsigned int i_slot; 207 + unsigned int spkfb_slot; 208 + bool interleave_mode; 209 + unsigned int ch_size; 210 + bool tdm_mode; 211 + }; 212 + #endif
+1 -1
sound/soc/codecs/max98926.c
··· 490 490 struct max98926_priv *max98926 = snd_soc_codec_get_drvdata(codec); 491 491 492 492 max98926->codec = codec; 493 - codec->control_data = max98926->regmap; 493 + 494 494 /* Hi-Z all the slots */ 495 495 regmap_write(max98926->regmap, MAX98926_DOUT_HIZ_CFG4, 0xF0); 496 496 return 0;
-1
sound/soc/hisilicon/hi6210-i2s.c
··· 36 36 #include <linux/of_irq.h> 37 37 #include <linux/mfd/syscon.h> 38 38 #include <linux/reset-controller.h> 39 - #include <linux/clk.h> 40 39 41 40 #include "hi6210-i2s.h" 42 41