Merge branch 'asoc-5.5' into asoc-next

This commit is contained in:
Mark Brown 2019-10-16 13:58:26 +01:00
commit 94fae3e24c
No known key found for this signature in database
GPG Key ID: 24D68B725D5487D0
130 changed files with 6184 additions and 1850 deletions

View File

@ -0,0 +1,90 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/adi,adau7118.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Analog Devices ADAU7118 8 Channel PDM to I2S/TDM Converter
maintainers:
- Nuno Sá <nuno.sa@analog.com>
description: |
Analog Devices ADAU7118 8 Channel PDM to I2S/TDM Converter over I2C or HW
standalone mode.
https://www.analog.com/media/en/technical-documentation/data-sheets/ADAU7118.pdf
properties:
compatible:
enum:
- adi,adau7118
reg:
maxItems: 1
"#sound-dai-cells":
const: 0
IOVDD-supply:
description: Digital Input/Output Power Supply.
$ref: "/schemas/types.yaml#/definitions/phandle"
DVDD-supply:
description: Internal Core Digital Power Supply.
$ref: "/schemas/types.yaml#/definitions/phandle"
adi,decimation-ratio:
description: |
This property set's the decimation ratio of PDM to PCM audio data.
allOf:
- $ref: /schemas/types.yaml#/definitions/uint32
- enum: [64, 32, 16]
default: 64
adi,pdm-clk-map:
description: |
The ADAU7118 has two PDM clocks for the four Inputs. Each input must be
assigned to one of these two clocks. This property set's the mapping
between the clocks and the inputs.
allOf:
- $ref: /schemas/types.yaml#/definitions/uint32-array
- minItems: 4
maxItems: 4
items:
maximum: 1
default: [0, 0, 1, 1]
required:
- "#sound-dai-cells"
- compatible
- IOVDD-supply
- DVDD-supply
examples:
- |
i2c0 {
/* example with i2c support */
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
adau7118_codec: adau7118-codec@14 {
compatible = "adi,adau7118";
reg = <14>;
#sound-dai-cells = <0>;
status = "okay";
IOVDD-supply = <&supply>;
DVDD-supply = <&supply>;
adi,pdm-clk-map = <1 1 0 0>;
adi,decimation-ratio = <16>;
};
};
/* example with hw standalone mode */
adau7118_codec_hw: adau7118-codec-hw {
compatible = "adi,adau7118";
#sound-dai-cells = <0>;
status = "okay";
IOVDD-supply = <&supply>;
DVDD-supply = <&supply>;
};

View File

@ -0,0 +1,38 @@
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/sound/allwinner,sun8i-a23-codec-analog.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Allwinner A23 Analog Codec Device Tree Bindings
maintainers:
- Chen-Yu Tsai <wens@csie.org>
- Maxime Ripard <maxime.ripard@bootlin.com>
properties:
compatible:
enum:
# FIXME: This is documented in the PRCM binding, but needs to be
# migrated here at some point
# - allwinner,sun8i-a23-codec-analog
- allwinner,sun8i-h3-codec-analog
- allwinner,sun8i-v3s-codec-analog
reg:
maxItems: 1
required:
- compatible
- reg
additionalProperties: false
examples:
- |
codec_analog: codec-analog@1f015c0 {
compatible = "allwinner,sun8i-h3-codec-analog";
reg = <0x01f015c0 0x4>;
};
...

View File

@ -1,8 +1,9 @@
Audio Binding for Arndale boards
Required properties:
- compatible : Can be the following,
"samsung,arndale-rt5631"
- compatible : Can be one of the following:
"samsung,arndale-rt5631",
"samsung,arndale-wm1811"
- samsung,audio-cpu: The phandle of the Samsung I2S controller
- samsung,audio-codec: The phandle of the audio codec

View File

@ -0,0 +1,36 @@
fsl,mqs audio CODEC
Required properties:
- compatible : Must contain one of "fsl,imx6sx-mqs", "fsl,codec-mqs"
"fsl,imx8qm-mqs", "fsl,imx8qxp-mqs".
- clocks : A list of phandles + clock-specifiers, one for each entry in
clock-names
- clock-names : "mclk" - must required.
"core" - required if compatible is "fsl,imx8qm-mqs", it
is for register access.
- gpr : A phandle of General Purpose Registers in IOMUX Controller.
Required if compatible is "fsl,imx6sx-mqs".
Required if compatible is "fsl,imx8qm-mqs":
- power-domains: A phandle of PM domain provider node.
- reg: Offset and length of the register set for the device.
Example:
mqs: mqs {
compatible = "fsl,imx6sx-mqs";
gpr = <&gpr>;
clocks = <&clks IMX6SX_CLK_SAI1>;
clock-names = "mclk";
status = "disabled";
};
mqs: mqs@59850000 {
compatible = "fsl,imx8qm-mqs";
reg = <0x59850000 0x10000>;
clocks = <&clk IMX8QM_AUD_MQS_IPG>,
<&clk IMX8QM_AUD_MQS_HMCLK>;
clock-names = "core", "mclk";
power-domains = <&pd_mqs0>;
status = "disabled";
};

View File

@ -4,6 +4,10 @@ Required properties:
- compatible = "mediatek,mt68183-audio";
- reg: register location and size
- interrupts: should contain AFE interrupt
- resets: Must contain an entry for each entry in reset-names
See ../reset/reset.txt for details.
- reset-names: should have these reset names:
"audiosys";
- power-domains: should define the power domain
- clocks: Must contain an entry for each entry in clock-names
- clock-names: should have these clock names:
@ -20,6 +24,8 @@ Example:
compatible = "mediatek,mt8183-audio";
reg = <0 0x11220000 0 0x1000>;
interrupts = <GIC_SPI 161 IRQ_TYPE_LEVEL_LOW>;
resets = <&watchdog MT8183_TOPRGU_AUDIO_SW_RST>;
reset-names = "audiosys";
power-domains = <&scpsys MT8183_POWER_DOMAIN_AUDIO>;
clocks = <&infrasys CLK_INFRA_AUDIO>,
<&infrasys CLK_INFRA_AUDIO_26M_BCLK>,

View File

@ -2,9 +2,11 @@ MT8183 with MT6358, TS3A227 and MAX98357 CODECS
Required properties:
- compatible : "mediatek,mt8183_mt6358_ts3a227_max98357"
- mediatek,headset-codec: the phandles of ts3a227 codecs
- mediatek,platform: the phandle of MT8183 ASoC platform
Optional properties:
- mediatek,headset-codec: the phandles of ts3a227 codecs
Example:
sound {

View File

@ -268,6 +268,7 @@ Required properties:
- "renesas,rcar_sound-r8a7745" (RZ/G1E)
- "renesas,rcar_sound-r8a77470" (RZ/G1C)
- "renesas,rcar_sound-r8a774a1" (RZ/G2M)
- "renesas,rcar_sound-r8a774b1" (RZ/G2N)
- "renesas,rcar_sound-r8a774c0" (RZ/G2E)
- "renesas,rcar_sound-r8a7778" (R-Car M1A)
- "renesas,rcar_sound-r8a7779" (R-Car H1)

View File

@ -20,6 +20,14 @@ Required properties:
| 1 | 1 | 0x3b |
-------------------------------------
Optional properties:
- realtek,temperature_calib
u32. The temperature was measured while doing the calibration. Units: Celsius degree
- realtek,r0_calib
u32. This is r0 calibration data which was measured in factory mode.
Pins on the device (for linking into audio routes) for RT1011:
* SPO
@ -29,4 +37,6 @@ Example:
rt1011: codec@38 {
compatible = "realtek,rt1011";
reg = <0x38>;
realtek,temperature_calib = <25>;
realtek,r0_calib = <0x224050>;
};

View File

@ -1,17 +0,0 @@
* Allwinner Codec Analog Controls
Required properties:
- compatible: must be one of the following compatibles:
- "allwinner,sun8i-a23-codec-analog"
- "allwinner,sun8i-h3-codec-analog"
- "allwinner,sun8i-v3s-codec-analog"
Required properties if not a sub-node of the PRCM node:
- reg: must contain the registers location and length
Example:
prcm: prcm@1f01400 {
codec_analog: codec-analog {
compatible = "allwinner,sun8i-a23-codec-analog";
};
};

View File

@ -0,0 +1,34 @@
Texas Instruments TAS2562 Smart PA
The TAS2562 is a mono, digital input Class-D audio amplifier optimized for
efficiently driving high peak power into small loudspeakers.
Integrated speaker voltage and current sense provides for
real time monitoring of loudspeaker behavior.
Required properties:
- #address-cells - Should be <1>.
- #size-cells - Should be <0>.
- compatible: - Should contain "ti,tas2562".
- reg: - The i2c address. Should be 0x4c, 0x4d, 0x4e or 0x4f.
- ti,imon-slot-no:- TDM TX current sense time slot.
Optional properties:
- interrupt-parent: phandle to the interrupt controller which provides
the interrupt.
- interrupts: (GPIO) interrupt to which the chip is connected.
- shut-down: GPIO used to control the state of the device.
Examples:
tas2562@4c {
#address-cells = <1>;
#size-cells = <0>;
compatible = "ti,tas2562";
reg = <0x4c>;
interrupt-parent = <&gpio1>;
interrupts = <14>;
shut-down = <&gpio1 15 0>;
ti,imon-slot-no = <0>;
};

View File

@ -0,0 +1,37 @@
Texas Instruments TAS2770 Smart PA
The TAS2770 is a mono, digital input Class-D audio amplifier optimized for
efficiently driving high peak power into small loudspeakers.
Integrated speaker voltage and current sense provides for
real time monitoring of loudspeaker behavior.
Required properties:
- compatible: - Should contain "ti,tas2770".
- reg: - The i2c address. Should contain <0x4c>, <0x4d>,<0x4e>, or <0x4f>.
- #address-cells - Should be <1>.
- #size-cells - Should be <0>.
- ti,asi-format: - Sets TDM RX capture edge. 0->Rising; 1->Falling.
- ti,imon-slot-no:- TDM TX current sense time slot.
- ti,vmon-slot-no:- TDM TX voltage sense time slot.
Optional properties:
- interrupt-parent: the phandle to the interrupt controller which provides
the interrupt.
- interrupts: interrupt specification for data-ready.
Examples:
tas2770@4c {
compatible = "ti,tas2770";
reg = <0x4c>;
#address-cells = <1>;
#size-cells = <0>;
interrupt-parent = <&msm_gpio>;
interrupts = <97 0>;
ti,asi-format = <0>;
ti,imon-slot-no = <0>;
ti,vmon-slot-no = <2>;
};

View File

@ -1002,6 +1002,7 @@ F: drivers/media/i2c/adv7842*
ANALOG DEVICES INC ASOC CODEC DRIVERS
M: Lars-Peter Clausen <lars@metafoo.de>
M: Nuno Sá <nuno.sa@analog.com>
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
W: http://wiki.analog.com/
W: http://ez.analog.com/community/linux-device-drivers

View File

@ -83,6 +83,11 @@ void snd_dmaengine_pcm_set_config_from_dai_data(
const struct snd_dmaengine_dai_dma_data *dma_data,
struct dma_slave_config *config);
int snd_dmaengine_pcm_refine_runtime_hwparams(
struct snd_pcm_substream *substream,
struct snd_dmaengine_dai_dma_data *dma_data,
struct snd_pcm_hardware *hw,
struct dma_chan *chan);
/*
* Try to request the DMA channel using compat_request_channel or

View File

@ -10,6 +10,7 @@ struct snd_pcm_substream;
struct snd_pcm_hw_params;
struct snd_soc_pcm_runtime;
struct snd_pcm;
struct snd_soc_component;
extern int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params);
@ -23,8 +24,29 @@ extern int pxa2xx_pcm_mmap(struct snd_pcm_substream *substream,
struct vm_area_struct *vma);
extern int pxa2xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream);
extern void pxa2xx_pcm_free_dma_buffers(struct snd_pcm *pcm);
extern int pxa2xx_soc_pcm_new(struct snd_soc_pcm_runtime *rtd);
extern const struct snd_pcm_ops pxa2xx_pcm_ops;
extern void pxa2xx_soc_pcm_free(struct snd_soc_component *component,
struct snd_pcm *pcm);
extern int pxa2xx_soc_pcm_new(struct snd_soc_component *component,
struct snd_soc_pcm_runtime *rtd);
extern int pxa2xx_soc_pcm_open(struct snd_soc_component *component,
struct snd_pcm_substream *substream);
extern int pxa2xx_soc_pcm_close(struct snd_soc_component *component,
struct snd_pcm_substream *substream);
extern int pxa2xx_soc_pcm_hw_params(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params);
extern int pxa2xx_soc_pcm_hw_free(struct snd_soc_component *component,
struct snd_pcm_substream *substream);
extern int pxa2xx_soc_pcm_prepare(struct snd_soc_component *component,
struct snd_pcm_substream *substream);
extern int pxa2xx_soc_pcm_trigger(struct snd_soc_component *component,
struct snd_pcm_substream *substream, int cmd);
extern snd_pcm_uframes_t
pxa2xx_soc_pcm_pointer(struct snd_soc_component *component,
struct snd_pcm_substream *substream);
extern int pxa2xx_soc_pcm_mmap(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
struct vm_area_struct *vma);
/* AC97 */

View File

@ -8,6 +8,7 @@
#ifndef __SIMPLE_CARD_UTILS_H
#define __SIMPLE_CARD_UTILS_H
#include <linux/clk.h>
#include <sound/soc.h>
#define asoc_simple_init_hp(card, sjack, prefix) \

View File

@ -75,6 +75,7 @@ struct snd_soc_acpi_mach_params {
* all firmware/topology related fields.
*
* @id: ACPI ID (usually the codec's) used to find a matching machine driver.
* @link_mask: describes required board layout, e.g. for SoundWire.
* @drv_name: machine driver name
* @fw_filename: firmware file name. Used when SOF is not enabled.
* @board: board name
@ -90,6 +91,7 @@ struct snd_soc_acpi_mach_params {
/* Descriptor for SST ASoC machine driver */
struct snd_soc_acpi_mach {
const u8 id[ACPI_ID_LEN];
const u32 link_mask;
const char *drv_name;
const char *fw_filename;
const char *board;

View File

@ -3,10 +3,6 @@
* soc-component.h
*
* Copyright (c) 2019 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __SOC_COMPONENT_H
#define __SOC_COMPONENT_H
@ -51,8 +47,10 @@ struct snd_soc_component_driver {
unsigned int reg, unsigned int val);
/* pcm creation and destruction */
int (*pcm_new)(struct snd_soc_pcm_runtime *rtd);
void (*pcm_free)(struct snd_pcm *pcm);
int (*pcm_construct)(struct snd_soc_component *component,
struct snd_soc_pcm_runtime *rtd);
void (*pcm_destruct)(struct snd_soc_component *component,
struct snd_pcm *pcm);
/* component wide operations */
int (*set_sysclk)(struct snd_soc_component *component,
@ -74,7 +72,40 @@ struct snd_soc_component_driver {
int (*set_bias_level)(struct snd_soc_component *component,
enum snd_soc_bias_level level);
const struct snd_pcm_ops *ops;
int (*open)(struct snd_soc_component *component,
struct snd_pcm_substream *substream);
int (*close)(struct snd_soc_component *component,
struct snd_pcm_substream *substream);
int (*ioctl)(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
unsigned int cmd, void *arg);
int (*hw_params)(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params);
int (*hw_free)(struct snd_soc_component *component,
struct snd_pcm_substream *substream);
int (*prepare)(struct snd_soc_component *component,
struct snd_pcm_substream *substream);
int (*trigger)(struct snd_soc_component *component,
struct snd_pcm_substream *substream, int cmd);
snd_pcm_uframes_t (*pointer)(struct snd_soc_component *component,
struct snd_pcm_substream *substream);
int (*get_time_info)(struct snd_soc_component *component,
struct snd_pcm_substream *substream, struct timespec *system_ts,
struct timespec *audio_ts,
struct snd_pcm_audio_tstamp_config *audio_tstamp_config,
struct snd_pcm_audio_tstamp_report *audio_tstamp_report);
int (*copy_user)(struct snd_soc_component *component,
struct snd_pcm_substream *substream, int channel,
unsigned long pos, void __user *buf,
unsigned long bytes);
struct page *(*page)(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
unsigned long offset);
int (*mmap)(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
struct vm_area_struct *vma);
const struct snd_compr_ops *compr_ops;
/* probe ordering - for components with runtime dependencies */

View File

@ -1148,7 +1148,6 @@ struct snd_soc_pcm_runtime {
struct list_head component_list; /* list of connected components */
/* bit field */
unsigned int dev_registered:1;
unsigned int pop_wait:1;
unsigned int fe_compr:1; /* for Dynamic PCM */
};
@ -1391,6 +1390,11 @@ static inline void snd_soc_dapm_mutex_unlock(struct snd_soc_dapm_context *dapm)
mutex_unlock(&dapm->card->dapm_mutex);
}
/* bypass */
int snd_soc_pcm_lib_ioctl(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
unsigned int cmd, void *arg);
#include <sound/soc-component.h>
#endif

View File

@ -61,6 +61,9 @@ struct sof_dev_desc {
/* list of machines using this configuration */
struct snd_soc_acpi_mach *machines;
/* alternate list of machines using this configuration */
struct snd_soc_acpi_mach *alt_machines;
/* Platform resource indexes in BAR / ACPI resources. */
/* Must set to -1 if not used - add new items to end */
int resindex_lpe_base;

View File

@ -0,0 +1,34 @@
/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
/*
* Copyright 2019 NXP
*
* Author: Daniel Baluta <daniel.baluta@nxp.com>
*/
#ifndef __INCLUDE_SOUND_SOF_DAI_IMX_H__
#define __INCLUDE_SOUND_SOF_DAI_IMX_H__
#include <sound/sof/header.h>
/* ESAI Configuration Request - SOF_IPC_DAI_ESAI_CONFIG */
struct sof_ipc_dai_esai_params {
struct sof_ipc_hdr hdr;
/* MCLK */
uint16_t reserved1;
uint16_t mclk_id;
uint32_t mclk_direction;
uint32_t mclk_rate; /* MCLK frequency in Hz */
uint32_t fsync_rate; /* FSYNC frequency in Hz */
uint32_t bclk_rate; /* BCLK frequency in Hz */
/* TDM */
uint32_t tdm_slots;
uint32_t rx_slots;
uint32_t tx_slots;
uint16_t tdm_slot_width;
uint16_t reserved2; /* alignment */
} __packed;
#endif

View File

@ -11,6 +11,7 @@
#include <sound/sof/header.h>
#include <sound/sof/dai-intel.h>
#include <sound/sof/dai-imx.h>
/*
* DAI Configuration.
@ -73,6 +74,7 @@ struct sof_ipc_dai_config {
struct sof_ipc_dai_dmic_params dmic;
struct sof_ipc_dai_hda_params hda;
struct sof_ipc_dai_alh_params alh;
struct sof_ipc_dai_esai_params esai;
};
} __packed;

View File

@ -9,6 +9,7 @@
#ifndef __INCLUDE_SOUND_SOF_HEADER_H__
#define __INCLUDE_SOUND_SOF_HEADER_H__
#include <linux/types.h>
#include <uapi/sound/sof/abi.h>
/** \addtogroup sof_uapi uAPI

View File

@ -83,10 +83,10 @@ struct sof_ipc_stream_params {
uint16_t sample_valid_bytes;
uint16_t sample_container_bytes;
/* for notifying host period has completed - 0 means no period IRQ */
uint32_t host_period_bytes;
uint16_t no_stream_position; /**< 1 means don't send stream position */
uint32_t reserved[2];
uint16_t reserved[3];
uint16_t chmap[SOF_IPC_MAX_CHANNELS]; /**< channel map - SOF_CHMAP_ */
} __packed;

View File

@ -26,7 +26,7 @@
/* SOF ABI version major, minor and patch numbers */
#define SOF_ABI_MAJOR 3
#define SOF_ABI_MINOR 10
#define SOF_ABI_MINOR 11
#define SOF_ABI_PATCH 0
/* SOF ABI version number. Format within 32bit word is MMmmmppp */

View File

@ -111,7 +111,10 @@
/* TODO: Add SAI tokens */
/* ESAI */
#define SOF_TKN_IMX_ESAI_FIRST_TOKEN 1100
/* TODO: Add ESAI tokens */
#define SOF_TKN_IMX_ESAI_MCLK_ID 1100
/* Led control for mute switches */
#define SOF_TKN_MUTE_LED_USE 1300
#define SOF_TKN_MUTE_LED_DIRECTION 1301
#endif

View File

@ -175,7 +175,15 @@ void pxa2xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
}
EXPORT_SYMBOL(pxa2xx_pcm_free_dma_buffers);
int pxa2xx_soc_pcm_new(struct snd_soc_pcm_runtime *rtd)
void pxa2xx_soc_pcm_free(struct snd_soc_component *component,
struct snd_pcm *pcm)
{
pxa2xx_pcm_free_dma_buffers(pcm);
}
EXPORT_SYMBOL(pxa2xx_soc_pcm_free);
int pxa2xx_soc_pcm_new(struct snd_soc_component *component,
struct snd_soc_pcm_runtime *rtd)
{
struct snd_card *card = rtd->card->snd_card;
struct snd_pcm *pcm = rtd->pcm;
@ -203,18 +211,64 @@ int pxa2xx_soc_pcm_new(struct snd_soc_pcm_runtime *rtd)
}
EXPORT_SYMBOL(pxa2xx_soc_pcm_new);
const struct snd_pcm_ops pxa2xx_pcm_ops = {
.open = pxa2xx_pcm_open,
.close = pxa2xx_pcm_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = pxa2xx_pcm_hw_params,
.hw_free = pxa2xx_pcm_hw_free,
.prepare = pxa2xx_pcm_prepare,
.trigger = pxa2xx_pcm_trigger,
.pointer = pxa2xx_pcm_pointer,
.mmap = pxa2xx_pcm_mmap,
};
EXPORT_SYMBOL(pxa2xx_pcm_ops);
int pxa2xx_soc_pcm_open(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
return pxa2xx_pcm_open(substream);
}
EXPORT_SYMBOL(pxa2xx_soc_pcm_open);
int pxa2xx_soc_pcm_close(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
return pxa2xx_pcm_close(substream);
}
EXPORT_SYMBOL(pxa2xx_soc_pcm_close);
int pxa2xx_soc_pcm_hw_params(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
return pxa2xx_pcm_hw_params(substream, params);
}
EXPORT_SYMBOL(pxa2xx_soc_pcm_hw_params);
int pxa2xx_soc_pcm_hw_free(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
return pxa2xx_pcm_hw_free(substream);
}
EXPORT_SYMBOL(pxa2xx_soc_pcm_hw_free);
int pxa2xx_soc_pcm_prepare(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
return pxa2xx_pcm_prepare(substream);
}
EXPORT_SYMBOL(pxa2xx_soc_pcm_prepare);
int pxa2xx_soc_pcm_trigger(struct snd_soc_component *component,
struct snd_pcm_substream *substream, int cmd)
{
return pxa2xx_pcm_trigger(substream, cmd);
}
EXPORT_SYMBOL(pxa2xx_soc_pcm_trigger);
snd_pcm_uframes_t
pxa2xx_soc_pcm_pointer(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
return pxa2xx_pcm_pointer(substream);
}
EXPORT_SYMBOL(pxa2xx_soc_pcm_pointer);
int pxa2xx_soc_pcm_mmap(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
struct vm_area_struct *vma)
{
return pxa2xx_pcm_mmap(substream, vma);
}
EXPORT_SYMBOL(pxa2xx_soc_pcm_mmap);
MODULE_AUTHOR("Nicolas Pitre");
MODULE_DESCRIPTION("Intel PXA2xx sound library");

View File

@ -369,4 +369,87 @@ int snd_dmaengine_pcm_close_release_chan(struct snd_pcm_substream *substream)
}
EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_close_release_chan);
/**
* snd_dmaengine_pcm_refine_runtime_hwparams - Refine runtime hw params
* @substream: PCM substream
* @dma_data: DAI DMA data
* @hw: PCM hw params
* @chan: DMA channel to use for data transfers
*
* Returns 0 on success, a negative error code otherwise.
*
* This function will query DMA capability, then refine the pcm hardware
* parameters.
*/
int snd_dmaengine_pcm_refine_runtime_hwparams(
struct snd_pcm_substream *substream,
struct snd_dmaengine_dai_dma_data *dma_data,
struct snd_pcm_hardware *hw,
struct dma_chan *chan)
{
struct dma_slave_caps dma_caps;
u32 addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
snd_pcm_format_t i;
int ret = 0;
if (!hw || !chan || !dma_data)
return -EINVAL;
ret = dma_get_slave_caps(chan, &dma_caps);
if (ret == 0) {
if (dma_caps.cmd_pause && dma_caps.cmd_resume)
hw->info |= SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME;
if (dma_caps.residue_granularity <= DMA_RESIDUE_GRANULARITY_SEGMENT)
hw->info |= SNDRV_PCM_INFO_BATCH;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
addr_widths = dma_caps.dst_addr_widths;
else
addr_widths = dma_caps.src_addr_widths;
}
/*
* If SND_DMAENGINE_PCM_DAI_FLAG_PACK is set keep
* hw.formats set to 0, meaning no restrictions are in place.
* In this case it's the responsibility of the DAI driver to
* provide the supported format information.
*/
if (!(dma_data->flags & SND_DMAENGINE_PCM_DAI_FLAG_PACK))
/*
* Prepare formats mask for valid/allowed sample types. If the
* dma does not have support for the given physical word size,
* it needs to be masked out so user space can not use the
* format which produces corrupted audio.
* In case the dma driver does not implement the slave_caps the
* default assumption is that it supports 1, 2 and 4 bytes
* widths.
*/
for (i = SNDRV_PCM_FORMAT_FIRST; i <= SNDRV_PCM_FORMAT_LAST; i++) {
int bits = snd_pcm_format_physical_width(i);
/*
* Enable only samples with DMA supported physical
* widths
*/
switch (bits) {
case 8:
case 16:
case 24:
case 32:
case 64:
if (addr_widths & (1 << (bits / 8)))
hw->formats |= pcm_format_to_bits(i);
break;
default:
/* Unsupported types */
break;
}
}
return ret;
}
EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_refine_runtime_hwparams);
MODULE_LICENSE("GPL");

View File

@ -759,14 +759,12 @@ static irqreturn_t dma_irq_handler(int irq, void *arg)
return IRQ_NONE;
}
static int acp_dma_open(struct snd_pcm_substream *substream)
static int acp_dma_open(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
u16 bank;
int ret = 0;
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *prtd = substream->private_data;
struct snd_soc_component *component = snd_soc_rtdcom_lookup(prtd,
DRV_NAME);
struct audio_drv_data *intr_data = dev_get_drvdata(component->dev);
struct audio_substream_data *adata =
kzalloc(sizeof(struct audio_substream_data), GFP_KERNEL);
@ -834,7 +832,8 @@ static int acp_dma_open(struct snd_pcm_substream *substream)
return 0;
}
static int acp_dma_hw_params(struct snd_pcm_substream *substream,
static int acp_dma_hw_params(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
int status;
@ -843,8 +842,6 @@ static int acp_dma_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_runtime *runtime;
struct audio_substream_data *rtd;
struct snd_soc_pcm_runtime *prtd = substream->private_data;
struct snd_soc_component *component = snd_soc_rtdcom_lookup(prtd,
DRV_NAME);
struct audio_drv_data *adata = dev_get_drvdata(component->dev);
struct snd_soc_card *card = prtd->card;
struct acp_platform_info *pinfo = snd_soc_card_get_drvdata(card);
@ -995,7 +992,8 @@ static int acp_dma_hw_params(struct snd_pcm_substream *substream,
return status;
}
static int acp_dma_hw_free(struct snd_pcm_substream *substream)
static int acp_dma_hw_free(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
return snd_pcm_lib_free_pages(substream);
}
@ -1011,7 +1009,8 @@ static u64 acp_get_byte_count(struct audio_substream_data *rtd)
return byte_count.bytescount;
}
static snd_pcm_uframes_t acp_dma_pointer(struct snd_pcm_substream *substream)
static snd_pcm_uframes_t acp_dma_pointer(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
u32 buffersize;
u32 pos = 0;
@ -1053,13 +1052,15 @@ static snd_pcm_uframes_t acp_dma_pointer(struct snd_pcm_substream *substream)
return bytes_to_frames(runtime, pos);
}
static int acp_dma_mmap(struct snd_pcm_substream *substream,
static int acp_dma_mmap(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
struct vm_area_struct *vma)
{
return snd_pcm_lib_default_mmap(substream, vma);
}
static int acp_dma_prepare(struct snd_pcm_substream *substream)
static int acp_dma_prepare(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct audio_substream_data *rtd = runtime->private_data;
@ -1086,7 +1087,8 @@ static int acp_dma_prepare(struct snd_pcm_substream *substream)
return 0;
}
static int acp_dma_trigger(struct snd_pcm_substream *substream, int cmd)
static int acp_dma_trigger(struct snd_soc_component *component,
struct snd_pcm_substream *substream, int cmd)
{
int ret;
@ -1132,10 +1134,9 @@ static int acp_dma_trigger(struct snd_pcm_substream *substream, int cmd)
return ret;
}
static int acp_dma_new(struct snd_soc_pcm_runtime *rtd)
static int acp_dma_new(struct snd_soc_component *component,
struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd,
DRV_NAME);
struct audio_drv_data *adata = dev_get_drvdata(component->dev);
struct device *parent = component->dev->parent;
@ -1158,14 +1159,12 @@ static int acp_dma_new(struct snd_soc_pcm_runtime *rtd)
return 0;
}
static int acp_dma_close(struct snd_pcm_substream *substream)
static int acp_dma_close(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
u16 bank;
struct snd_pcm_runtime *runtime = substream->runtime;
struct audio_substream_data *rtd = runtime->private_data;
struct snd_soc_pcm_runtime *prtd = substream->private_data;
struct snd_soc_component *component = snd_soc_rtdcom_lookup(prtd,
DRV_NAME);
struct audio_drv_data *adata = dev_get_drvdata(component->dev);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
@ -1216,22 +1215,18 @@ static int acp_dma_close(struct snd_pcm_substream *substream)
return 0;
}
static const struct snd_pcm_ops acp_dma_ops = {
.open = acp_dma_open,
.close = acp_dma_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = acp_dma_hw_params,
.hw_free = acp_dma_hw_free,
.trigger = acp_dma_trigger,
.pointer = acp_dma_pointer,
.mmap = acp_dma_mmap,
.prepare = acp_dma_prepare,
};
static const struct snd_soc_component_driver acp_asoc_platform = {
.name = DRV_NAME,
.ops = &acp_dma_ops,
.pcm_new = acp_dma_new,
.name = DRV_NAME,
.open = acp_dma_open,
.close = acp_dma_close,
.ioctl = snd_soc_pcm_lib_ioctl,
.hw_params = acp_dma_hw_params,
.hw_free = acp_dma_hw_free,
.trigger = acp_dma_trigger,
.pointer = acp_dma_pointer,
.mmap = acp_dma_mmap,
.prepare = acp_dma_prepare,
.pcm_construct = acp_dma_new,
};
static int acp_audio_probe(struct platform_device *pdev)

View File

@ -275,16 +275,12 @@ static void config_acp3x_dma(struct i2s_stream_instance *rtd, int direction)
rtd->acp3x_base + mmACP_EXTERNAL_INTR_CNTL);
}
static int acp3x_dma_open(struct snd_pcm_substream *substream)
static int acp3x_dma_open(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
int ret = 0;
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *prtd = substream->private_data;
struct snd_soc_component *component = snd_soc_rtdcom_lookup(prtd,
DRV_NAME);
struct i2s_dev_data *adata = dev_get_drvdata(component->dev);
struct i2s_stream_instance *i2s_data = kzalloc(sizeof(struct i2s_stream_instance),
GFP_KERNEL);
if (!i2s_data)
@ -334,7 +330,8 @@ static u64 acp_get_byte_count(struct i2s_stream_instance *rtd, int direction)
return byte_count;
}
static int acp3x_dma_hw_params(struct snd_pcm_substream *substream,
static int acp3x_dma_hw_params(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
int status;
@ -362,7 +359,8 @@ static int acp3x_dma_hw_params(struct snd_pcm_substream *substream,
return status;
}
static snd_pcm_uframes_t acp3x_dma_pointer(struct snd_pcm_substream *substream)
static snd_pcm_uframes_t acp3x_dma_pointer(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
u32 pos = 0;
u32 buffersize = 0;
@ -379,33 +377,32 @@ static snd_pcm_uframes_t acp3x_dma_pointer(struct snd_pcm_substream *substream)
return bytes_to_frames(substream->runtime, pos);
}
static int acp3x_dma_new(struct snd_soc_pcm_runtime *rtd)
static int acp3x_dma_new(struct snd_soc_component *component,
struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd,
DRV_NAME);
struct device *parent = component->dev->parent;
snd_pcm_lib_preallocate_pages_for_all(rtd->pcm, SNDRV_DMA_TYPE_DEV,
parent, MIN_BUFFER, MAX_BUFFER);
return 0;
}
static int acp3x_dma_hw_free(struct snd_pcm_substream *substream)
static int acp3x_dma_hw_free(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
return snd_pcm_lib_free_pages(substream);
}
static int acp3x_dma_mmap(struct snd_pcm_substream *substream,
static int acp3x_dma_mmap(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
struct vm_area_struct *vma)
{
return snd_pcm_lib_default_mmap(substream, vma);
}
static int acp3x_dma_close(struct snd_pcm_substream *substream)
static int acp3x_dma_close(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *prtd = substream->private_data;
struct i2s_stream_instance *rtd = substream->runtime->private_data;
struct snd_soc_component *component = snd_soc_rtdcom_lookup(prtd,
DRV_NAME);
struct i2s_dev_data *adata = dev_get_drvdata(component->dev);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
@ -422,17 +419,6 @@ static int acp3x_dma_close(struct snd_pcm_substream *substream)
return 0;
}
static struct snd_pcm_ops acp3x_dma_ops = {
.open = acp3x_dma_open,
.close = acp3x_dma_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = acp3x_dma_hw_params,
.hw_free = acp3x_dma_hw_free,
.pointer = acp3x_dma_pointer,
.mmap = acp3x_dma_mmap,
};
static int acp3x_dai_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
{
@ -610,9 +596,15 @@ static struct snd_soc_dai_driver acp3x_i2s_dai_driver = {
};
static const struct snd_soc_component_driver acp3x_i2s_component = {
.name = DRV_NAME,
.ops = &acp3x_dma_ops,
.pcm_new = acp3x_dma_new,
.name = DRV_NAME,
.open = acp3x_dma_open,
.close = acp3x_dma_close,
.ioctl = snd_soc_pcm_lib_ioctl,
.hw_params = acp3x_dma_hw_params,
.hw_free = acp3x_dma_hw_free,
.pointer = acp3x_dma_pointer,
.mmap = acp3x_dma_mmap,
.pcm_construct = acp3x_dma_new,
};
static int acp3x_audio_probe(struct platform_device *pdev)
@ -631,7 +623,7 @@ static int acp3x_audio_probe(struct platform_device *pdev)
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(&pdev->dev, "IORESOURCE_IRQ FAILED\n");
return -ENODEV;
return -ENODEV;
}
adata = devm_kzalloc(&pdev->dev, sizeof(*adata), GFP_KERNEL);

View File

@ -56,15 +56,17 @@ static int atmel_pcm_preallocate_dma_buffer(struct snd_pcm *pcm,
return 0;
}
static int atmel_pcm_mmap(struct snd_pcm_substream *substream,
struct vm_area_struct *vma)
static int atmel_pcm_mmap(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
struct vm_area_struct *vma)
{
return remap_pfn_range(vma, vma->vm_start,
substream->dma_buffer.addr >> PAGE_SHIFT,
vma->vm_end - vma->vm_start, vma->vm_page_prot);
}
static int atmel_pcm_new(struct snd_soc_pcm_runtime *rtd)
static int atmel_pcm_new(struct snd_soc_component *component,
struct snd_soc_pcm_runtime *rtd)
{
struct snd_card *card = rtd->card->snd_card;
struct snd_pcm *pcm = rtd->pcm;
@ -93,7 +95,8 @@ static int atmel_pcm_new(struct snd_soc_pcm_runtime *rtd)
return ret;
}
static void atmel_pcm_free(struct snd_pcm *pcm)
static void atmel_pcm_free(struct snd_soc_component *component,
struct snd_pcm *pcm)
{
struct snd_pcm_substream *substream;
struct snd_dma_buffer *buf;
@ -196,8 +199,9 @@ static void atmel_pcm_dma_irq(u32 ssc_sr,
/*--------------------------------------------------------------------------*\
* PCM operations
\*--------------------------------------------------------------------------*/
static int atmel_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
static int atmel_pcm_hw_params(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct atmel_runtime_data *prtd = runtime->private_data;
@ -225,7 +229,8 @@ static int atmel_pcm_hw_params(struct snd_pcm_substream *substream,
return 0;
}
static int atmel_pcm_hw_free(struct snd_pcm_substream *substream)
static int atmel_pcm_hw_free(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct atmel_runtime_data *prtd = substream->runtime->private_data;
struct atmel_pcm_dma_params *params = prtd->params;
@ -239,7 +244,8 @@ static int atmel_pcm_hw_free(struct snd_pcm_substream *substream)
return 0;
}
static int atmel_pcm_prepare(struct snd_pcm_substream *substream)
static int atmel_pcm_prepare(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct atmel_runtime_data *prtd = substream->runtime->private_data;
struct atmel_pcm_dma_params *params = prtd->params;
@ -251,8 +257,8 @@ static int atmel_pcm_prepare(struct snd_pcm_substream *substream)
return 0;
}
static int atmel_pcm_trigger(struct snd_pcm_substream *substream,
int cmd)
static int atmel_pcm_trigger(struct snd_soc_component *component,
struct snd_pcm_substream *substream, int cmd)
{
struct snd_pcm_runtime *rtd = substream->runtime;
struct atmel_runtime_data *prtd = rtd->private_data;
@ -317,8 +323,8 @@ static int atmel_pcm_trigger(struct snd_pcm_substream *substream,
return ret;
}
static snd_pcm_uframes_t atmel_pcm_pointer(
struct snd_pcm_substream *substream)
static snd_pcm_uframes_t atmel_pcm_pointer(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct atmel_runtime_data *prtd = runtime->private_data;
@ -335,7 +341,8 @@ static snd_pcm_uframes_t atmel_pcm_pointer(
return x;
}
static int atmel_pcm_open(struct snd_pcm_substream *substream)
static int atmel_pcm_open(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct atmel_runtime_data *prtd;
@ -360,7 +367,8 @@ static int atmel_pcm_open(struct snd_pcm_substream *substream)
return ret;
}
static int atmel_pcm_close(struct snd_pcm_substream *substream)
static int atmel_pcm_close(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct atmel_runtime_data *prtd = substream->runtime->private_data;
@ -368,22 +376,18 @@ static int atmel_pcm_close(struct snd_pcm_substream *substream)
return 0;
}
static const struct snd_pcm_ops atmel_pcm_ops = {
static const struct snd_soc_component_driver atmel_soc_platform = {
.open = atmel_pcm_open,
.close = atmel_pcm_close,
.ioctl = snd_pcm_lib_ioctl,
.ioctl = snd_soc_pcm_lib_ioctl,
.hw_params = atmel_pcm_hw_params,
.hw_free = atmel_pcm_hw_free,
.prepare = atmel_pcm_prepare,
.trigger = atmel_pcm_trigger,
.pointer = atmel_pcm_pointer,
.mmap = atmel_pcm_mmap,
};
static struct snd_soc_component_driver atmel_soc_platform = {
.ops = &atmel_pcm_ops,
.pcm_new = atmel_pcm_new,
.pcm_free = atmel_pcm_free,
.pcm_construct = atmel_pcm_new,
.pcm_destruct = atmel_pcm_free,
};
int atmel_pcm_pdc_platform_register(struct device *dev)

View File

@ -182,15 +182,15 @@ static int au1x_pcm_dbdma_realloc(struct au1xpsc_audio_dmadata *pcd,
return 0;
}
static inline struct au1xpsc_audio_dmadata *to_dmadata(struct snd_pcm_substream *ss)
static inline struct au1xpsc_audio_dmadata *to_dmadata(struct snd_pcm_substream *ss,
struct snd_soc_component *component)
{
struct snd_soc_pcm_runtime *rtd = ss->private_data;
struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
struct au1xpsc_audio_dmadata *pcd = snd_soc_component_get_drvdata(component);
return &pcd[ss->stream];
}
static int au1xpsc_pcm_hw_params(struct snd_pcm_substream *substream,
static int au1xpsc_pcm_hw_params(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_pcm_runtime *runtime = substream->runtime;
@ -202,7 +202,7 @@ static int au1xpsc_pcm_hw_params(struct snd_pcm_substream *substream,
goto out;
stype = substream->stream;
pcd = to_dmadata(substream);
pcd = to_dmadata(substream, component);
DBG("runtime->dma_area = 0x%08lx dma_addr_t = 0x%08lx dma_size = %zu "
"runtime->min_align %lu\n",
@ -232,15 +232,17 @@ static int au1xpsc_pcm_hw_params(struct snd_pcm_substream *substream,
return ret;
}
static int au1xpsc_pcm_hw_free(struct snd_pcm_substream *substream)
static int au1xpsc_pcm_hw_free(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
snd_pcm_lib_free_pages(substream);
return 0;
}
static int au1xpsc_pcm_prepare(struct snd_pcm_substream *substream)
static int au1xpsc_pcm_prepare(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct au1xpsc_audio_dmadata *pcd = to_dmadata(substream);
struct au1xpsc_audio_dmadata *pcd = to_dmadata(substream, component);
au1xxx_dbdma_reset(pcd->ddma_chan);
@ -255,9 +257,10 @@ static int au1xpsc_pcm_prepare(struct snd_pcm_substream *substream)
return 0;
}
static int au1xpsc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
static int au1xpsc_pcm_trigger(struct snd_soc_component *component,
struct snd_pcm_substream *substream, int cmd)
{
u32 c = to_dmadata(substream)->ddma_chan;
u32 c = to_dmadata(substream, component)->ddma_chan;
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
@ -275,14 +278,17 @@ static int au1xpsc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
}
static snd_pcm_uframes_t
au1xpsc_pcm_pointer(struct snd_pcm_substream *substream)
au1xpsc_pcm_pointer(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
return bytes_to_frames(substream->runtime, to_dmadata(substream)->pos);
return bytes_to_frames(substream->runtime,
to_dmadata(substream, component)->pos);
}
static int au1xpsc_pcm_open(struct snd_pcm_substream *substream)
static int au1xpsc_pcm_open(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct au1xpsc_audio_dmadata *pcd = to_dmadata(substream);
struct au1xpsc_audio_dmadata *pcd = to_dmadata(substream, component);
struct snd_soc_pcm_runtime *rtd = substream->private_data;
int stype = substream->stream, *dmaids;
@ -296,24 +302,15 @@ static int au1xpsc_pcm_open(struct snd_pcm_substream *substream)
return 0;
}
static int au1xpsc_pcm_close(struct snd_pcm_substream *substream)
static int au1xpsc_pcm_close(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
au1x_pcm_dbdma_free(to_dmadata(substream));
au1x_pcm_dbdma_free(to_dmadata(substream, component));
return 0;
}
static const struct snd_pcm_ops au1xpsc_pcm_ops = {
.open = au1xpsc_pcm_open,
.close = au1xpsc_pcm_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = au1xpsc_pcm_hw_params,
.hw_free = au1xpsc_pcm_hw_free,
.prepare = au1xpsc_pcm_prepare,
.trigger = au1xpsc_pcm_trigger,
.pointer = au1xpsc_pcm_pointer,
};
static int au1xpsc_pcm_new(struct snd_soc_pcm_runtime *rtd)
static int au1xpsc_pcm_new(struct snd_soc_component *component,
struct snd_soc_pcm_runtime *rtd)
{
struct snd_card *card = rtd->card->snd_card;
struct snd_pcm *pcm = rtd->pcm;
@ -327,8 +324,15 @@ static int au1xpsc_pcm_new(struct snd_soc_pcm_runtime *rtd)
/* au1xpsc audio platform */
static struct snd_soc_component_driver au1xpsc_soc_component = {
.name = DRV_NAME,
.ops = &au1xpsc_pcm_ops,
.pcm_new = au1xpsc_pcm_new,
.open = au1xpsc_pcm_open,
.close = au1xpsc_pcm_close,
.ioctl = snd_soc_pcm_lib_ioctl,
.hw_params = au1xpsc_pcm_hw_params,
.hw_free = au1xpsc_pcm_hw_free,
.prepare = au1xpsc_pcm_prepare,
.trigger = au1xpsc_pcm_trigger,
.pointer = au1xpsc_pcm_pointer,
.pcm_construct = au1xpsc_pcm_new,
};
static int au1xpsc_pcm_drvprobe(struct platform_device *pdev)

View File

@ -174,22 +174,23 @@ static const struct snd_pcm_hardware alchemy_pcm_hardware = {
.fifo_size = 16,
};
static inline struct alchemy_pcm_ctx *ss_to_ctx(struct snd_pcm_substream *ss)
static inline struct alchemy_pcm_ctx *ss_to_ctx(struct snd_pcm_substream *ss,
struct snd_soc_component *component)
{
struct snd_soc_pcm_runtime *rtd = ss->private_data;
struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
return snd_soc_component_get_drvdata(component);
}
static inline struct audio_stream *ss_to_as(struct snd_pcm_substream *ss)
static inline struct audio_stream *ss_to_as(struct snd_pcm_substream *ss,
struct snd_soc_component *component)
{
struct alchemy_pcm_ctx *ctx = ss_to_ctx(ss);
struct alchemy_pcm_ctx *ctx = ss_to_ctx(ss, component);
return &(ctx->stream[ss->stream]);
}
static int alchemy_pcm_open(struct snd_pcm_substream *substream)
static int alchemy_pcm_open(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct alchemy_pcm_ctx *ctx = ss_to_ctx(substream);
struct alchemy_pcm_ctx *ctx = ss_to_ctx(substream, component);
struct snd_soc_pcm_runtime *rtd = substream->private_data;
int *dmaids, s = substream->stream;
char *name;
@ -213,9 +214,10 @@ static int alchemy_pcm_open(struct snd_pcm_substream *substream)
return 0;
}
static int alchemy_pcm_close(struct snd_pcm_substream *substream)
static int alchemy_pcm_close(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct alchemy_pcm_ctx *ctx = ss_to_ctx(substream);
struct alchemy_pcm_ctx *ctx = ss_to_ctx(substream, component);
int stype = substream->stream;
ctx->stream[stype].substream = NULL;
@ -224,10 +226,11 @@ static int alchemy_pcm_close(struct snd_pcm_substream *substream)
return 0;
}
static int alchemy_pcm_hw_params(struct snd_pcm_substream *substream,
static int alchemy_pcm_hw_params(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *hw_params)
{
struct audio_stream *stream = ss_to_as(substream);
struct audio_stream *stream = ss_to_as(substream, component);
int err;
err = snd_pcm_lib_malloc_pages(substream,
@ -243,16 +246,18 @@ static int alchemy_pcm_hw_params(struct snd_pcm_substream *substream,
return err;
}
static int alchemy_pcm_hw_free(struct snd_pcm_substream *substream)
static int alchemy_pcm_hw_free(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct audio_stream *stream = ss_to_as(substream);
struct audio_stream *stream = ss_to_as(substream, component);
au1000_release_dma_link(stream);
return snd_pcm_lib_free_pages(substream);
}
static int alchemy_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
static int alchemy_pcm_trigger(struct snd_soc_component *component,
struct snd_pcm_substream *substream, int cmd)
{
struct audio_stream *stream = ss_to_as(substream);
struct audio_stream *stream = ss_to_as(substream, component);
int err = 0;
switch (cmd) {
@ -269,9 +274,10 @@ static int alchemy_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
return err;
}
static snd_pcm_uframes_t alchemy_pcm_pointer(struct snd_pcm_substream *ss)
static snd_pcm_uframes_t alchemy_pcm_pointer(struct snd_soc_component *component,
struct snd_pcm_substream *ss)
{
struct audio_stream *stream = ss_to_as(ss);
struct audio_stream *stream = ss_to_as(ss, component);
long location;
location = get_dma_residue(stream->dma);
@ -281,17 +287,8 @@ static snd_pcm_uframes_t alchemy_pcm_pointer(struct snd_pcm_substream *ss)
return bytes_to_frames(ss->runtime, location);
}
static const struct snd_pcm_ops alchemy_pcm_ops = {
.open = alchemy_pcm_open,
.close = alchemy_pcm_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = alchemy_pcm_hw_params,
.hw_free = alchemy_pcm_hw_free,
.trigger = alchemy_pcm_trigger,
.pointer = alchemy_pcm_pointer,
};
static int alchemy_pcm_new(struct snd_soc_pcm_runtime *rtd)
static int alchemy_pcm_new(struct snd_soc_component *component,
struct snd_soc_pcm_runtime *rtd)
{
struct snd_pcm *pcm = rtd->pcm;
@ -303,8 +300,14 @@ static int alchemy_pcm_new(struct snd_soc_pcm_runtime *rtd)
static struct snd_soc_component_driver alchemy_pcm_soc_component = {
.name = DRV_NAME,
.ops = &alchemy_pcm_ops,
.pcm_new = alchemy_pcm_new,
.open = alchemy_pcm_open,
.close = alchemy_pcm_close,
.ioctl = snd_soc_pcm_lib_ioctl,
.hw_params = alchemy_pcm_hw_params,
.hw_free = alchemy_pcm_hw_free,
.trigger = alchemy_pcm_trigger,
.pointer = alchemy_pcm_pointer,
.pcm_construct = alchemy_pcm_new,
};
static int alchemy_pcm_drvprobe(struct platform_device *pdev)

View File

@ -376,7 +376,8 @@ static void disable_intr(struct snd_pcm_substream *substream)
}
static int cygnus_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
static int cygnus_pcm_trigger(struct snd_soc_component *component,
struct snd_pcm_substream *substream, int cmd)
{
int ret = 0;
@ -577,7 +578,8 @@ static irqreturn_t cygnus_dma_irq(int irq, void *data)
return IRQ_HANDLED;
}
static int cygnus_pcm_open(struct snd_pcm_substream *substream)
static int cygnus_pcm_open(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_pcm_runtime *runtime = substream->runtime;
@ -613,7 +615,8 @@ static int cygnus_pcm_open(struct snd_pcm_substream *substream)
return 0;
}
static int cygnus_pcm_close(struct snd_pcm_substream *substream)
static int cygnus_pcm_close(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct cygnus_aio_port *aio;
@ -633,8 +636,9 @@ static int cygnus_pcm_close(struct snd_pcm_substream *substream)
return 0;
}
static int cygnus_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
static int cygnus_pcm_hw_params(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_pcm_runtime *runtime = substream->runtime;
@ -649,7 +653,8 @@ static int cygnus_pcm_hw_params(struct snd_pcm_substream *substream,
return 0;
}
static int cygnus_pcm_hw_free(struct snd_pcm_substream *substream)
static int cygnus_pcm_hw_free(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct cygnus_aio_port *aio;
@ -661,7 +666,8 @@ static int cygnus_pcm_hw_free(struct snd_pcm_substream *substream)
return 0;
}
static int cygnus_pcm_prepare(struct snd_pcm_substream *substream)
static int cygnus_pcm_prepare(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_pcm_runtime *runtime = substream->runtime;
@ -694,7 +700,8 @@ static int cygnus_pcm_prepare(struct snd_pcm_substream *substream)
return 0;
}
static snd_pcm_uframes_t cygnus_pcm_pointer(struct snd_pcm_substream *substream)
static snd_pcm_uframes_t cygnus_pcm_pointer(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct cygnus_aio_port *aio;
unsigned int res = 0, cur = 0, base = 0;
@ -750,19 +757,8 @@ static int cygnus_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
return 0;
}
static const struct snd_pcm_ops cygnus_pcm_ops = {
.open = cygnus_pcm_open,
.close = cygnus_pcm_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = cygnus_pcm_hw_params,
.hw_free = cygnus_pcm_hw_free,
.prepare = cygnus_pcm_prepare,
.trigger = cygnus_pcm_trigger,
.pointer = cygnus_pcm_pointer,
};
static void cygnus_dma_free_dma_buffers(struct snd_pcm *pcm)
static void cygnus_dma_free_dma_buffers(struct snd_soc_component *component,
struct snd_pcm *pcm)
{
struct snd_pcm_substream *substream;
struct snd_dma_buffer *buf;
@ -788,7 +784,8 @@ static void cygnus_dma_free_dma_buffers(struct snd_pcm *pcm)
}
}
static int cygnus_dma_new(struct snd_soc_pcm_runtime *rtd)
static int cygnus_dma_new(struct snd_soc_component *component,
struct snd_soc_pcm_runtime *rtd)
{
struct snd_card *card = rtd->card->snd_card;
struct snd_pcm *pcm = rtd->pcm;
@ -810,7 +807,7 @@ static int cygnus_dma_new(struct snd_soc_pcm_runtime *rtd)
ret = cygnus_pcm_preallocate_dma_buffer(pcm,
SNDRV_PCM_STREAM_CAPTURE);
if (ret) {
cygnus_dma_free_dma_buffers(pcm);
cygnus_dma_free_dma_buffers(component, pcm);
return ret;
}
}
@ -819,9 +816,16 @@ static int cygnus_dma_new(struct snd_soc_pcm_runtime *rtd)
}
static struct snd_soc_component_driver cygnus_soc_platform = {
.ops = &cygnus_pcm_ops,
.pcm_new = cygnus_dma_new,
.pcm_free = cygnus_dma_free_dma_buffers,
.open = cygnus_pcm_open,
.close = cygnus_pcm_close,
.ioctl = snd_soc_pcm_lib_ioctl,
.hw_params = cygnus_pcm_hw_params,
.hw_free = cygnus_pcm_hw_free,
.prepare = cygnus_pcm_prepare,
.trigger = cygnus_pcm_trigger,
.pointer = cygnus_pcm_pointer,
.pcm_construct = cygnus_dma_new,
.pcm_destruct = cygnus_dma_free_dma_buffers,
};
int cygnus_soc_platform_register(struct device *dev,

View File

@ -34,6 +34,8 @@ config SND_SOC_ALL_CODECS
select SND_SOC_ADAU1977_I2C if I2C
select SND_SOC_ADAU1701 if I2C
select SND_SOC_ADAU7002
select SND_SOC_ADAU7118_I2C if I2C
select SND_SOC_ADAU7118_HW
select SND_SOC_ADS117X
select SND_SOC_AK4104 if SPI_MASTER
select SND_SOC_AK4118 if I2C
@ -179,6 +181,8 @@ config SND_SOC_ALL_CODECS
select SND_SOC_STAC9766 if SND_SOC_AC97_BUS
select SND_SOC_STI_SAS
select SND_SOC_TAS2552 if I2C
select SND_SOC_TAS2562 if I2C
select SND_SOC_TAS2770 if I2C
select SND_SOC_TAS5086 if I2C
select SND_SOC_TAS571X if I2C
select SND_SOC_TAS5720 if I2C
@ -395,6 +399,33 @@ config SND_SOC_ADAU1977_I2C
config SND_SOC_ADAU7002
tristate "Analog Devices ADAU7002 Stereo PDM-to-I2S/TDM Converter"
config SND_SOC_ADAU7118
tristate
config SND_SOC_ADAU7118_HW
tristate "Analog Devices ADAU7118 8 Channel PDM-to-I2S/TDM Converter - HW Mode"
select SND_SOC_ADAU7118
help
Enable support for the Analog Devices ADAU7118 8 Channel PDM-to-I2S/TDM
Converter. In this mode, the device works in standalone mode which
means that there is no bus to comunicate with it. Stereo mode is not
supported in this mode.
To compile this driver as a module, choose M here: the module
will be called snd-soc-adau7118-hw.
config SND_SOC_ADAU7118_I2C
tristate "Analog Devices ADAU7118 8 Channel PDM-to-I2S/TDM Converter - I2C"
depends on I2C
select SND_SOC_ADAU7118
select REGMAP_I2C
help
Enable support for the Analog Devices ADAU7118 8 Channel PDM-to-I2S/TDM
Converter over I2C. This gives full support over the device.
To compile this driver as a module, choose M here: the module
will be called snd-soc-adau7118-i2c.
config SND_SOC_ADAV80X
tristate
@ -1104,6 +1135,14 @@ config SND_SOC_TAS2552
tristate "Texas Instruments TAS2552 Mono Audio amplifier"
depends on I2C
config SND_SOC_TAS2562
tristate "Texas Instruments TAS2562 Mono Audio amplifier"
depends on I2C
config SND_SOC_TAS2770
tristate "Texas Instruments TAS2770 speaker amplifier"
depends on I2C
config SND_SOC_TAS5086
tristate "Texas Instruments TAS5086 speaker amplifier"
depends on I2C

View File

@ -22,6 +22,9 @@ snd-soc-adau1977-objs := adau1977.o
snd-soc-adau1977-spi-objs := adau1977-spi.o
snd-soc-adau1977-i2c-objs := adau1977-i2c.o
snd-soc-adau7002-objs := adau7002.o
snd-soc-adau7118-objs := adau7118.o
snd-soc-adau7118-i2c-objs := adau7118-i2c.o
snd-soc-adau7118-hw-objs := adau7118-hw.o
snd-soc-adav80x-objs := adav80x.o
snd-soc-adav801-objs := adav801.o
snd-soc-adav803-objs := adav803.o
@ -196,6 +199,7 @@ snd-soc-tas571x-objs := tas571x.o
snd-soc-tas5720-objs := tas5720.o
snd-soc-tas6424-objs := tas6424.o
snd-soc-tda7419-objs := tda7419.o
snd-soc-tas2770-objs := tas2770.o
snd-soc-tfa9879-objs := tfa9879.o
snd-soc-tlv320aic23-objs := tlv320aic23.o
snd-soc-tlv320aic23-i2c-objs := tlv320aic23-i2c.o
@ -280,6 +284,7 @@ snd-soc-max98504-objs := max98504.o
snd-soc-simple-amplifier-objs := simple-amplifier.o
snd-soc-tpa6130a2-objs := tpa6130a2.o
snd-soc-tas2552-objs := tas2552.o
snd-soc-tas2562-objs := tas2562.o
obj-$(CONFIG_SND_SOC_88PM860X) += snd-soc-88pm860x.o
obj-$(CONFIG_SND_SOC_AB8500_CODEC) += snd-soc-ab8500-codec.o
@ -304,6 +309,9 @@ obj-$(CONFIG_SND_SOC_ADAU1977) += snd-soc-adau1977.o
obj-$(CONFIG_SND_SOC_ADAU1977_SPI) += snd-soc-adau1977-spi.o
obj-$(CONFIG_SND_SOC_ADAU1977_I2C) += snd-soc-adau1977-i2c.o
obj-$(CONFIG_SND_SOC_ADAU7002) += snd-soc-adau7002.o
obj-$(CONFIG_SND_SOC_ADAU7118) += snd-soc-adau7118.o
obj-$(CONFIG_SND_SOC_ADAU7118_I2C) += snd-soc-adau7118-i2c.o
obj-$(CONFIG_SND_SOC_ADAU7118_HW) += snd-soc-adau7118-hw.o
obj-$(CONFIG_SND_SOC_ADAV80X) += snd-soc-adav80x.o
obj-$(CONFIG_SND_SOC_ADAV801) += snd-soc-adav801.o
obj-$(CONFIG_SND_SOC_ADAV803) += snd-soc-adav803.o
@ -474,11 +482,13 @@ obj-$(CONFIG_SND_SOC_STA529) += snd-soc-sta529.o
obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o
obj-$(CONFIG_SND_SOC_STI_SAS) += snd-soc-sti-sas.o
obj-$(CONFIG_SND_SOC_TAS2552) += snd-soc-tas2552.o
obj-$(CONFIG_SND_SOC_TAS2562) += snd-soc-tas2562.o
obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc-tas5086.o
obj-$(CONFIG_SND_SOC_TAS571X) += snd-soc-tas571x.o
obj-$(CONFIG_SND_SOC_TAS5720) += snd-soc-tas5720.o
obj-$(CONFIG_SND_SOC_TAS6424) += snd-soc-tas6424.o
obj-$(CONFIG_SND_SOC_TDA7419) += snd-soc-tda7419.o
obj-$(CONFIG_SND_SOC_TAS2770) += snd-soc-tas2770.o
obj-$(CONFIG_SND_SOC_TFA9879) += snd-soc-tfa9879.o
obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o
obj-$(CONFIG_SND_SOC_TLV320AIC23_I2C) += snd-soc-tlv320aic23-i2c.o

View File

@ -28,6 +28,10 @@
#define ADAU1761_REC_MIXER_RIGHT1 0x400d
#define ADAU1761_LEFT_DIFF_INPUT_VOL 0x400e
#define ADAU1761_RIGHT_DIFF_INPUT_VOL 0x400f
#define ADAU1761_ALC_CTRL0 0x4011
#define ADAU1761_ALC_CTRL1 0x4012
#define ADAU1761_ALC_CTRL2 0x4013
#define ADAU1761_ALC_CTRL3 0x4014
#define ADAU1761_PLAY_LR_MIXER_LEFT 0x4020
#define ADAU1761_PLAY_MIXER_LEFT0 0x401c
#define ADAU1761_PLAY_MIXER_LEFT1 0x401d
@ -71,6 +75,10 @@ static const struct reg_default adau1761_reg_defaults[] = {
{ ADAU1761_REC_MIXER_RIGHT0, 0x00 },
{ ADAU1761_REC_MIXER_RIGHT1, 0x00 },
{ ADAU1761_LEFT_DIFF_INPUT_VOL, 0x00 },
{ ADAU1761_ALC_CTRL0, 0x00 },
{ ADAU1761_ALC_CTRL1, 0x00 },
{ ADAU1761_ALC_CTRL2, 0x00 },
{ ADAU1761_ALC_CTRL3, 0x00 },
{ ADAU1761_RIGHT_DIFF_INPUT_VOL, 0x00 },
{ ADAU1761_PLAY_LR_MIXER_LEFT, 0x00 },
{ ADAU1761_PLAY_MIXER_LEFT0, 0x00 },
@ -121,6 +129,10 @@ static const DECLARE_TLV_DB_SCALE(adau1761_sidetone_tlv, -1800, 300, 1);
static const DECLARE_TLV_DB_SCALE(adau1761_boost_tlv, -600, 600, 1);
static const DECLARE_TLV_DB_SCALE(adau1761_pga_boost_tlv, -2000, 2000, 1);
static const DECLARE_TLV_DB_SCALE(adau1761_alc_max_gain_tlv, -1200, 600, 0);
static const DECLARE_TLV_DB_SCALE(adau1761_alc_target_tlv, -2850, 150, 0);
static const DECLARE_TLV_DB_SCALE(adau1761_alc_ng_threshold_tlv, -7650, 150, 0);
static const unsigned int adau1761_bias_select_values[] = {
0, 2, 3,
};
@ -147,6 +159,103 @@ static SOC_VALUE_ENUM_SINGLE_DECL(adau1761_capture_bias_enum,
ADAU17X1_REC_POWER_MGMT, 1, 0x3, adau1761_bias_select_text,
adau1761_bias_select_values);
static const unsigned int adau1761_pga_slew_time_values[] = {
3, 0, 1, 2,
};
static const char * const adau1761_pga_slew_time_text[] = {
"Off",
"24 ms",
"48 ms",
"96 ms",
};
static const char * const adau1761_alc_function_text[] = {
"Off",
"Right",
"Left",
"Stereo",
"DSP control",
};
static const char * const adau1761_alc_hold_time_text[] = {
"2.67 ms",
"5.34 ms",
"10.68 ms",
"21.36 ms",
"42.72 ms",
"85.44 ms",
"170.88 ms",
"341.76 ms",
"683.52 ms",
"1367 ms",
"2734.1 ms",
"5468.2 ms",
"10936 ms",
"21873 ms",
"43745 ms",
"87491 ms",
};
static const char * const adau1761_alc_attack_time_text[] = {
"6 ms",
"12 ms",
"24 ms",
"48 ms",
"96 ms",
"192 ms",
"384 ms",
"768 ms",
"1540 ms",
"3070 ms",
"6140 ms",
"12290 ms",
"24580 ms",
"49150 ms",
"98300 ms",
"196610 ms",
};
static const char * const adau1761_alc_decay_time_text[] = {
"24 ms",
"48 ms",
"96 ms",
"192 ms",
"384 ms",
"768 ms",
"15400 ms",
"30700 ms",
"61400 ms",
"12290 ms",
"24580 ms",
"49150 ms",
"98300 ms",
"196610 ms",
"393220 ms",
"786430 ms",
};
static const char * const adau1761_alc_ng_type_text[] = {
"Hold",
"Mute",
"Fade",
"Fade + Mute",
};
static SOC_VALUE_ENUM_SINGLE_DECL(adau1761_pga_slew_time_enum,
ADAU1761_ALC_CTRL0, 6, 0x3, adau1761_pga_slew_time_text,
adau1761_pga_slew_time_values);
static SOC_ENUM_SINGLE_DECL(adau1761_alc_function_enum,
ADAU1761_ALC_CTRL0, 0, adau1761_alc_function_text);
static SOC_ENUM_SINGLE_DECL(adau1761_alc_hold_time_enum,
ADAU1761_ALC_CTRL1, 4, adau1761_alc_hold_time_text);
static SOC_ENUM_SINGLE_DECL(adau1761_alc_attack_time_enum,
ADAU1761_ALC_CTRL2, 4, adau1761_alc_attack_time_text);
static SOC_ENUM_SINGLE_DECL(adau1761_alc_decay_time_enum,
ADAU1761_ALC_CTRL2, 0, adau1761_alc_decay_time_text);
static SOC_ENUM_SINGLE_DECL(adau1761_alc_ng_type_enum,
ADAU1761_ALC_CTRL3, 6, adau1761_alc_ng_type_text);
static const struct snd_kcontrol_new adau1761_jack_detect_controls[] = {
SOC_SINGLE("Speaker Auto-mute Switch", ADAU1761_DIGMIC_JACKDETECT,
4, 1, 0),
@ -161,6 +270,22 @@ static const struct snd_kcontrol_new adau1761_differential_mode_controls[] = {
SOC_DOUBLE_R_TLV("PGA Boost Capture Volume", ADAU1761_REC_MIXER_LEFT1,
ADAU1761_REC_MIXER_RIGHT1, 3, 2, 0, adau1761_pga_boost_tlv),
SOC_ENUM("PGA Capture Slew Time", adau1761_pga_slew_time_enum),
SOC_SINGLE_TLV("ALC Capture Max Gain Volume", ADAU1761_ALC_CTRL0,
3, 7, 0, adau1761_alc_max_gain_tlv),
SOC_ENUM("ALC Capture Function", adau1761_alc_function_enum),
SOC_ENUM("ALC Capture Hold Time", adau1761_alc_hold_time_enum),
SOC_SINGLE_TLV("ALC Capture Target Volume", ADAU1761_ALC_CTRL1,
0, 15, 0, adau1761_alc_target_tlv),
SOC_ENUM("ALC Capture Attack Time", adau1761_alc_decay_time_enum),
SOC_ENUM("ALC Capture Decay Time", adau1761_alc_attack_time_enum),
SOC_ENUM("ALC Capture Noise Gate Type", adau1761_alc_ng_type_enum),
SOC_SINGLE("ALC Capture Noise Gate Switch",
ADAU1761_ALC_CTRL3, 5, 1, 0),
SOC_SINGLE_TLV("ALC Capture Noise Gate Threshold Volume",
ADAU1761_ALC_CTRL3, 0, 31, 0, adau1761_alc_ng_threshold_tlv),
};
static const struct snd_kcontrol_new adau1761_single_mode_controls[] = {
@ -632,6 +757,10 @@ static bool adau1761_readable_register(struct device *dev, unsigned int reg)
case ADAU1761_DEJITTER:
case ADAU1761_CLK_ENABLE0:
case ADAU1761_CLK_ENABLE1:
case ADAU1761_ALC_CTRL0:
case ADAU1761_ALC_CTRL1:
case ADAU1761_ALC_CTRL2:
case ADAU1761_ALC_CTRL3:
return true;
default:
break;

View File

@ -0,0 +1,43 @@
// SPDX-License-Identifier: GPL-2.0
//
// Analog Devices ADAU7118 8 channel PDM-to-I2S/TDM Converter Standalone Hw
// driver
//
// Copyright 2019 Analog Devices Inc.
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/platform_device.h>
#include "adau7118.h"
static int adau7118_probe_hw(struct platform_device *pdev)
{
return adau7118_probe(&pdev->dev, NULL, true);
}
static const struct of_device_id adau7118_of_match[] = {
{ .compatible = "adi,adau7118" },
{}
};
MODULE_DEVICE_TABLE(of, adau7118_of_match);
static const struct platform_device_id adau7118_id[] = {
{ .name = "adau7118" },
{ }
};
MODULE_DEVICE_TABLE(platform, adau7118_id);
static struct platform_driver adau7118_driver_hw = {
.driver = {
.name = "adau7118",
.of_match_table = adau7118_of_match,
},
.probe = adau7118_probe_hw,
.id_table = adau7118_id,
};
module_platform_driver(adau7118_driver_hw);
MODULE_AUTHOR("Nuno Sa <nuno.sa@analog.com>");
MODULE_DESCRIPTION("ADAU7118 8 channel PDM-to-I2S/TDM Converter driver for standalone hw mode");
MODULE_LICENSE("GPL");

View File

@ -0,0 +1,82 @@
// SPDX-License-Identifier: GPL-2.0
//
// Analog Devices ADAU7118 8 channel PDM-to-I2S/TDM Converter driver over I2C
//
// Copyright 2019 Analog Devices Inc.
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include "adau7118.h"
static const struct reg_default adau7118_reg_defaults[] = {
{ ADAU7118_REG_VENDOR_ID, 0x41 },
{ ADAU7118_REG_DEVICE_ID1, 0x71 },
{ ADAU7118_REG_DEVICE_ID2, 0x18 },
{ ADAU7118_REG_REVISION_ID, 0x00 },
{ ADAU7118_REG_ENABLES, 0x3F },
{ ADAU7118_REG_DEC_RATIO_CLK_MAP, 0xC0 },
{ ADAU7118_REG_HPF_CONTROL, 0xD0 },
{ ADAU7118_REG_SPT_CTRL1, 0x41 },
{ ADAU7118_REG_SPT_CTRL2, 0x00 },
{ ADAU7118_REG_SPT_CX(0), 0x01 },
{ ADAU7118_REG_SPT_CX(1), 0x11 },
{ ADAU7118_REG_SPT_CX(2), 0x21 },
{ ADAU7118_REG_SPT_CX(3), 0x31 },
{ ADAU7118_REG_SPT_CX(4), 0x41 },
{ ADAU7118_REG_SPT_CX(5), 0x51 },
{ ADAU7118_REG_SPT_CX(6), 0x61 },
{ ADAU7118_REG_SPT_CX(7), 0x71 },
{ ADAU7118_REG_DRIVE_STRENGTH, 0x2a },
{ ADAU7118_REG_RESET, 0x00 },
};
static const struct regmap_config adau7118_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.reg_defaults = adau7118_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(adau7118_reg_defaults),
.cache_type = REGCACHE_RBTREE,
.max_register = ADAU7118_REG_RESET,
};
static int adau7118_probe_i2c(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct regmap *map;
map = devm_regmap_init_i2c(i2c, &adau7118_regmap_config);
if (IS_ERR(map)) {
dev_err(&i2c->dev, "Failed to init regmap %ld\n", PTR_ERR(map));
return PTR_ERR(map);
}
return adau7118_probe(&i2c->dev, map, false);
}
static const struct of_device_id adau7118_of_match[] = {
{ .compatible = "adi,adau7118" },
{}
};
MODULE_DEVICE_TABLE(of, adau7118_of_match);
static const struct i2c_device_id adau7118_id[] = {
{"adau7118", 0},
{}
};
MODULE_DEVICE_TABLE(i2c, adau7118_id);
static struct i2c_driver adau7118_driver = {
.driver = {
.name = "adau7118",
.of_match_table = adau7118_of_match,
},
.probe = adau7118_probe_i2c,
.id_table = adau7118_id,
};
module_i2c_driver(adau7118_driver);
MODULE_AUTHOR("Nuno Sa <nuno.sa@analog.com>");
MODULE_DESCRIPTION("ADAU7118 8 channel PDM-to-I2S/TDM Converter driver over I2C");
MODULE_LICENSE("GPL");

586
sound/soc/codecs/adau7118.c Normal file
View File

@ -0,0 +1,586 @@
// SPDX-License-Identifier: GPL-2.0
//
// Analog Devices ADAU7118 8 channel PDM-to-I2S/TDM Converter driver
//
// Copyright 2019 Analog Devices Inc.
#include <linux/bitfield.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include "adau7118.h"
#define ADAU7118_DEC_RATIO_MASK GENMASK(1, 0)
#define ADAU7118_DEC_RATIO(x) FIELD_PREP(ADAU7118_DEC_RATIO_MASK, x)
#define ADAU7118_CLK_MAP_MASK GENMASK(7, 4)
#define ADAU7118_SLOT_WIDTH_MASK GENMASK(5, 4)
#define ADAU7118_SLOT_WIDTH(x) FIELD_PREP(ADAU7118_SLOT_WIDTH_MASK, x)
#define ADAU7118_TRISTATE_MASK BIT(6)
#define ADAU7118_TRISTATE(x) FIELD_PREP(ADAU7118_TRISTATE_MASK, x)
#define ADAU7118_DATA_FMT_MASK GENMASK(3, 1)
#define ADAU7118_DATA_FMT(x) FIELD_PREP(ADAU7118_DATA_FMT_MASK, x)
#define ADAU7118_SAI_MODE_MASK BIT(0)
#define ADAU7118_SAI_MODE(x) FIELD_PREP(ADAU7118_SAI_MODE_MASK, x)
#define ADAU7118_LRCLK_BCLK_POL_MASK GENMASK(1, 0)
#define ADAU7118_LRCLK_BCLK_POL(x) \
FIELD_PREP(ADAU7118_LRCLK_BCLK_POL_MASK, x)
#define ADAU7118_SPT_SLOT_MASK GENMASK(7, 4)
#define ADAU7118_SPT_SLOT(x) FIELD_PREP(ADAU7118_SPT_SLOT_MASK, x)
#define ADAU7118_FULL_SOFT_R_MASK BIT(1)
#define ADAU7118_FULL_SOFT_R(x) FIELD_PREP(ADAU7118_FULL_SOFT_R_MASK, x)
struct adau7118_data {
struct regmap *map;
struct device *dev;
struct regulator *iovdd;
struct regulator *dvdd;
u32 slot_width;
u32 slots;
bool hw_mode;
bool right_j;
};
/* Input Enable */
static const struct snd_kcontrol_new adau7118_dapm_pdm_control[4] = {
SOC_DAPM_SINGLE("Capture Switch", ADAU7118_REG_ENABLES, 0, 1, 0),
SOC_DAPM_SINGLE("Capture Switch", ADAU7118_REG_ENABLES, 1, 1, 0),
SOC_DAPM_SINGLE("Capture Switch", ADAU7118_REG_ENABLES, 2, 1, 0),
SOC_DAPM_SINGLE("Capture Switch", ADAU7118_REG_ENABLES, 3, 1, 0),
};
static const struct snd_soc_dapm_widget adau7118_widgets_sw[] = {
/* Input Enable Switches */
SND_SOC_DAPM_SWITCH("PDM0", SND_SOC_NOPM, 0, 0,
&adau7118_dapm_pdm_control[0]),
SND_SOC_DAPM_SWITCH("PDM1", SND_SOC_NOPM, 0, 0,
&adau7118_dapm_pdm_control[1]),
SND_SOC_DAPM_SWITCH("PDM2", SND_SOC_NOPM, 0, 0,
&adau7118_dapm_pdm_control[2]),
SND_SOC_DAPM_SWITCH("PDM3", SND_SOC_NOPM, 0, 0,
&adau7118_dapm_pdm_control[3]),
/* PDM Clocks */
SND_SOC_DAPM_SUPPLY("PDM_CLK0", ADAU7118_REG_ENABLES, 4, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("PDM_CLK1", ADAU7118_REG_ENABLES, 5, 0, NULL, 0),
/* Output channels */
SND_SOC_DAPM_AIF_OUT("AIF1TX1", "Capture", 0, ADAU7118_REG_SPT_CX(0),
0, 0),
SND_SOC_DAPM_AIF_OUT("AIF1TX2", "Capture", 0, ADAU7118_REG_SPT_CX(1),
0, 0),
SND_SOC_DAPM_AIF_OUT("AIF1TX3", "Capture", 0, ADAU7118_REG_SPT_CX(2),
0, 0),
SND_SOC_DAPM_AIF_OUT("AIF1TX4", "Capture", 0, ADAU7118_REG_SPT_CX(3),
0, 0),
SND_SOC_DAPM_AIF_OUT("AIF1TX5", "Capture", 0, ADAU7118_REG_SPT_CX(4),
0, 0),
SND_SOC_DAPM_AIF_OUT("AIF1TX6", "Capture", 0, ADAU7118_REG_SPT_CX(5),
0, 0),
SND_SOC_DAPM_AIF_OUT("AIF1TX7", "Capture", 0, ADAU7118_REG_SPT_CX(6),
0, 0),
SND_SOC_DAPM_AIF_OUT("AIF1TX8", "Capture", 0, ADAU7118_REG_SPT_CX(7),
0, 0),
};
static const struct snd_soc_dapm_route adau7118_routes_sw[] = {
{ "PDM0", "Capture Switch", "PDM_DAT0" },
{ "PDM1", "Capture Switch", "PDM_DAT1" },
{ "PDM2", "Capture Switch", "PDM_DAT2" },
{ "PDM3", "Capture Switch", "PDM_DAT3" },
{ "AIF1TX1", NULL, "PDM0" },
{ "AIF1TX2", NULL, "PDM0" },
{ "AIF1TX3", NULL, "PDM1" },
{ "AIF1TX4", NULL, "PDM1" },
{ "AIF1TX5", NULL, "PDM2" },
{ "AIF1TX6", NULL, "PDM2" },
{ "AIF1TX7", NULL, "PDM3" },
{ "AIF1TX8", NULL, "PDM3" },
{ "Capture", NULL, "PDM_CLK0" },
{ "Capture", NULL, "PDM_CLK1" },
};
static const struct snd_soc_dapm_widget adau7118_widgets_hw[] = {
SND_SOC_DAPM_AIF_OUT("AIF1TX", "Capture", 0, SND_SOC_NOPM, 0, 0),
};
static const struct snd_soc_dapm_route adau7118_routes_hw[] = {
{ "AIF1TX", NULL, "PDM_DAT0" },
{ "AIF1TX", NULL, "PDM_DAT1" },
{ "AIF1TX", NULL, "PDM_DAT2" },
{ "AIF1TX", NULL, "PDM_DAT3" },
};
static const struct snd_soc_dapm_widget adau7118_widgets[] = {
SND_SOC_DAPM_INPUT("PDM_DAT0"),
SND_SOC_DAPM_INPUT("PDM_DAT1"),
SND_SOC_DAPM_INPUT("PDM_DAT2"),
SND_SOC_DAPM_INPUT("PDM_DAT3"),
};
static int adau7118_set_channel_map(struct snd_soc_dai *dai,
unsigned int tx_num, unsigned int *tx_slot,
unsigned int rx_num, unsigned int *rx_slot)
{
struct adau7118_data *st =
snd_soc_component_get_drvdata(dai->component);
int chan, ret;
dev_dbg(st->dev, "Set channel map, %d", tx_num);
for (chan = 0; chan < tx_num; chan++) {
ret = snd_soc_component_update_bits(dai->component,
ADAU7118_REG_SPT_CX(chan),
ADAU7118_SPT_SLOT_MASK,
ADAU7118_SPT_SLOT(tx_slot[chan]));
if (ret < 0)
return ret;
}
return 0;
}
static int adau7118_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
{
struct adau7118_data *st =
snd_soc_component_get_drvdata(dai->component);
int ret = 0;
u32 regval;
dev_dbg(st->dev, "Set format, fmt:%d\n", fmt);
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_I2S:
ret = snd_soc_component_update_bits(dai->component,
ADAU7118_REG_SPT_CTRL1,
ADAU7118_DATA_FMT_MASK,
ADAU7118_DATA_FMT(0));
break;
case SND_SOC_DAIFMT_LEFT_J:
ret = snd_soc_component_update_bits(dai->component,
ADAU7118_REG_SPT_CTRL1,
ADAU7118_DATA_FMT_MASK,
ADAU7118_DATA_FMT(1));
break;
case SND_SOC_DAIFMT_RIGHT_J:
st->right_j = true;
break;
default:
dev_err(st->dev, "Invalid format %d",
fmt & SND_SOC_DAIFMT_FORMAT_MASK);
return -EINVAL;
}
if (ret < 0)
return ret;
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
case SND_SOC_DAIFMT_NB_NF:
regval = ADAU7118_LRCLK_BCLK_POL(0);
break;
case SND_SOC_DAIFMT_NB_IF:
regval = ADAU7118_LRCLK_BCLK_POL(2);
break;
case SND_SOC_DAIFMT_IB_NF:
regval = ADAU7118_LRCLK_BCLK_POL(1);
break;
case SND_SOC_DAIFMT_IB_IF:
regval = ADAU7118_LRCLK_BCLK_POL(3);
break;
default:
dev_err(st->dev, "Invalid Inv mask %d",
fmt & SND_SOC_DAIFMT_INV_MASK);
return -EINVAL;
}
ret = snd_soc_component_update_bits(dai->component,
ADAU7118_REG_SPT_CTRL2,
ADAU7118_LRCLK_BCLK_POL_MASK,
regval);
if (ret < 0)
return ret;
return 0;
}
static int adau7118_set_tristate(struct snd_soc_dai *dai, int tristate)
{
struct adau7118_data *st =
snd_soc_component_get_drvdata(dai->component);
int ret;
dev_dbg(st->dev, "Set tristate, %d\n", tristate);
ret = snd_soc_component_update_bits(dai->component,
ADAU7118_REG_SPT_CTRL1,
ADAU7118_TRISTATE_MASK,
ADAU7118_TRISTATE(tristate));
if (ret < 0)
return ret;
return 0;
}
static int adau7118_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
unsigned int rx_mask, int slots,
int slot_width)
{
struct adau7118_data *st =
snd_soc_component_get_drvdata(dai->component);
int ret = 0;
u32 regval;
dev_dbg(st->dev, "Set tdm, slots:%d width:%d\n", slots, slot_width);
switch (slot_width) {
case 32:
regval = ADAU7118_SLOT_WIDTH(0);
break;
case 24:
regval = ADAU7118_SLOT_WIDTH(2);
break;
case 16:
regval = ADAU7118_SLOT_WIDTH(1);
break;
default:
dev_err(st->dev, "Invalid slot width:%d\n", slot_width);
return -EINVAL;
}
ret = snd_soc_component_update_bits(dai->component,
ADAU7118_REG_SPT_CTRL1,
ADAU7118_SLOT_WIDTH_MASK, regval);
if (ret < 0)
return ret;
st->slot_width = slot_width;
st->slots = slots;
return 0;
}
static int adau7118_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
struct adau7118_data *st =
snd_soc_component_get_drvdata(dai->component);
u32 data_width = params_width(params), slots_width;
int ret;
u32 regval;
if (!st->slots) {
/* set stereo mode */
ret = snd_soc_component_update_bits(dai->component,
ADAU7118_REG_SPT_CTRL1,
ADAU7118_SAI_MODE_MASK,
ADAU7118_SAI_MODE(0));
if (ret < 0)
return ret;
slots_width = 32;
} else {
slots_width = st->slot_width;
}
if (data_width > slots_width) {
dev_err(st->dev, "Invalid data_width:%d, slots_width:%d",
data_width, slots_width);
return -EINVAL;
}
if (st->right_j) {
switch (slots_width - data_width) {
case 8:
/* delay bclck by 8 */
regval = ADAU7118_DATA_FMT(2);
break;
case 12:
/* delay bclck by 12 */
regval = ADAU7118_DATA_FMT(3);
break;
case 16:
/* delay bclck by 16 */
regval = ADAU7118_DATA_FMT(4);
break;
default:
dev_err(st->dev,
"Cannot set right_j setting, slot_w:%d, data_w:%d\n",
slots_width, data_width);
return -EINVAL;
}
ret = snd_soc_component_update_bits(dai->component,
ADAU7118_REG_SPT_CTRL1,
ADAU7118_DATA_FMT_MASK,
regval);
if (ret < 0)
return ret;
}
return 0;
}
static int adau7118_set_bias_level(struct snd_soc_component *component,
enum snd_soc_bias_level level)
{
struct adau7118_data *st = snd_soc_component_get_drvdata(component);
int ret = 0;
dev_dbg(st->dev, "Set bias level %d\n", level);
switch (level) {
case SND_SOC_BIAS_ON:
case SND_SOC_BIAS_PREPARE:
break;
case SND_SOC_BIAS_STANDBY:
if (snd_soc_component_get_bias_level(component) ==
SND_SOC_BIAS_OFF) {
/* power on */
ret = regulator_enable(st->iovdd);
if (ret)
return ret;
/* there's no timing constraints before enabling dvdd */
ret = regulator_enable(st->dvdd);
if (ret) {
regulator_disable(st->iovdd);
return ret;
}
if (st->hw_mode)
return 0;
regcache_cache_only(st->map, false);
/* sync cache */
ret = snd_soc_component_cache_sync(component);
}
break;
case SND_SOC_BIAS_OFF:
/* power off */
ret = regulator_disable(st->dvdd);
if (ret)
return ret;
ret = regulator_disable(st->iovdd);
if (ret)
return ret;
if (st->hw_mode)
return 0;
/* cache only */
regcache_mark_dirty(st->map);
regcache_cache_only(st->map, true);
break;
}
return ret;
}
static int adau7118_component_probe(struct snd_soc_component *component)
{
struct adau7118_data *st = snd_soc_component_get_drvdata(component);
struct snd_soc_dapm_context *dapm =
snd_soc_component_get_dapm(component);
int ret = 0;
if (st->hw_mode) {
ret = snd_soc_dapm_new_controls(dapm, adau7118_widgets_hw,
ARRAY_SIZE(adau7118_widgets_hw));
if (ret)
return ret;
ret = snd_soc_dapm_add_routes(dapm, adau7118_routes_hw,
ARRAY_SIZE(adau7118_routes_hw));
} else {
snd_soc_component_init_regmap(component, st->map);
ret = snd_soc_dapm_new_controls(dapm, adau7118_widgets_sw,
ARRAY_SIZE(adau7118_widgets_sw));
if (ret)
return ret;
ret = snd_soc_dapm_add_routes(dapm, adau7118_routes_sw,
ARRAY_SIZE(adau7118_routes_sw));
}
return ret;
}
static const struct snd_soc_dai_ops adau7118_ops = {
.hw_params = adau7118_hw_params,
.set_channel_map = adau7118_set_channel_map,
.set_fmt = adau7118_set_fmt,
.set_tdm_slot = adau7118_set_tdm_slot,
.set_tristate = adau7118_set_tristate,
};
static struct snd_soc_dai_driver adau7118_dai = {
.name = "adau7118-hifi-capture",
.capture = {
.stream_name = "Capture",
.channels_min = 1,
.channels_max = 8,
.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |
SNDRV_PCM_FMTBIT_S20_LE | SNDRV_PCM_FMTBIT_S24_LE |
SNDRV_PCM_FMTBIT_S24_3LE,
.rates = SNDRV_PCM_RATE_CONTINUOUS,
.rate_min = 4000,
.rate_max = 192000,
.sig_bits = 24,
},
};
static const struct snd_soc_component_driver adau7118_component_driver = {
.probe = adau7118_component_probe,
.set_bias_level = adau7118_set_bias_level,
.dapm_widgets = adau7118_widgets,
.num_dapm_widgets = ARRAY_SIZE(adau7118_widgets),
.use_pmdown_time = 1,
.endianness = 1,
.non_legacy_dai_naming = 1,
};
static void adau7118_regulator_disable(void *data)
{
struct adau7118_data *st = data;
int ret;
/*
* If we fail to disable DVDD, don't bother in trying IOVDD. We
* actually don't want to be left in the situation where DVDD
* is enabled and IOVDD is disabled.
*/
ret = regulator_disable(st->dvdd);
if (ret)
return;
regulator_disable(st->iovdd);
}
static int adau7118_regulator_setup(struct adau7118_data *st)
{
st->iovdd = devm_regulator_get(st->dev, "IOVDD");
if (IS_ERR(st->iovdd)) {
dev_err(st->dev, "Could not get iovdd: %ld\n",
PTR_ERR(st->iovdd));
return PTR_ERR(st->iovdd);
}
st->dvdd = devm_regulator_get(st->dev, "DVDD");
if (IS_ERR(st->dvdd)) {
dev_err(st->dev, "Could not get dvdd: %ld\n",
PTR_ERR(st->dvdd));
return PTR_ERR(st->dvdd);
}
/* just assume the device is in reset */
if (!st->hw_mode) {
regcache_mark_dirty(st->map);
regcache_cache_only(st->map, true);
}
return devm_add_action_or_reset(st->dev, adau7118_regulator_disable,
st);
}
static int adau7118_parset_dt(const struct adau7118_data *st)
{
int ret;
u32 dec_ratio = 0;
/* 4 inputs */
u32 clk_map[4], regval;
if (st->hw_mode)
return 0;
ret = device_property_read_u32(st->dev, "adi,decimation-ratio",
&dec_ratio);
if (!ret) {
switch (dec_ratio) {
case 64:
regval = ADAU7118_DEC_RATIO(0);
break;
case 32:
regval = ADAU7118_DEC_RATIO(1);
break;
case 16:
regval = ADAU7118_DEC_RATIO(2);
break;
default:
dev_err(st->dev, "Invalid dec ratio: %u", dec_ratio);
return -EINVAL;
}
ret = regmap_update_bits(st->map,
ADAU7118_REG_DEC_RATIO_CLK_MAP,
ADAU7118_DEC_RATIO_MASK, regval);
if (ret)
return ret;
}
ret = device_property_read_u32_array(st->dev, "adi,pdm-clk-map",
clk_map, ARRAY_SIZE(clk_map));
if (!ret) {
int pdm;
u32 _clk_map = 0;
for (pdm = 0; pdm < ARRAY_SIZE(clk_map); pdm++)
_clk_map |= (clk_map[pdm] << (pdm + 4));
ret = regmap_update_bits(st->map,
ADAU7118_REG_DEC_RATIO_CLK_MAP,
ADAU7118_CLK_MAP_MASK, _clk_map);
if (ret)
return ret;
}
return 0;
}
int adau7118_probe(struct device *dev, struct regmap *map, bool hw_mode)
{
struct adau7118_data *st;
int ret;
st = devm_kzalloc(dev, sizeof(*st), GFP_KERNEL);
if (!st)
return -ENOMEM;
st->dev = dev;
st->hw_mode = hw_mode;
dev_set_drvdata(dev, st);
if (!hw_mode) {
st->map = map;
adau7118_dai.ops = &adau7118_ops;
/*
* Perform a full soft reset. This will set all register's
* with their reset values.
*/
ret = regmap_update_bits(map, ADAU7118_REG_RESET,
ADAU7118_FULL_SOFT_R_MASK,
ADAU7118_FULL_SOFT_R(1));
if (ret)
return ret;
}
ret = adau7118_parset_dt(st);
if (ret)
return ret;
ret = adau7118_regulator_setup(st);
if (ret)
return ret;
return devm_snd_soc_register_component(dev,
&adau7118_component_driver,
&adau7118_dai, 1);
}
EXPORT_SYMBOL_GPL(adau7118_probe);
MODULE_AUTHOR("Nuno Sa <nuno.sa@analog.com>");
MODULE_DESCRIPTION("ADAU7118 8 channel PDM-to-I2S/TDM Converter driver");
MODULE_LICENSE("GPL");

View File

@ -0,0 +1,24 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _LINUX_ADAU7118_H
#define _LINUX_ADAU7118_H
struct regmap;
struct device;
/* register map */
#define ADAU7118_REG_VENDOR_ID 0x00
#define ADAU7118_REG_DEVICE_ID1 0x01
#define ADAU7118_REG_DEVICE_ID2 0x02
#define ADAU7118_REG_REVISION_ID 0x03
#define ADAU7118_REG_ENABLES 0x04
#define ADAU7118_REG_DEC_RATIO_CLK_MAP 0x05
#define ADAU7118_REG_HPF_CONTROL 0x06
#define ADAU7118_REG_SPT_CTRL1 0x07
#define ADAU7118_REG_SPT_CTRL2 0x08
#define ADAU7118_REG_SPT_CX(num) (0x09 + (num))
#define ADAU7118_REG_DRIVE_STRENGTH 0x11
#define ADAU7118_REG_RESET 0x12
int adau7118_probe(struct device *dev, struct regmap *map, bool hw_mode);
#endif

View File

@ -27,6 +27,7 @@
#define MADERA_FLL_SRC_NONE -1
#define MADERA_FLL_SRC_MCLK1 0
#define MADERA_FLL_SRC_MCLK2 1
#define MADERA_FLL_SRC_MCLK3 2
#define MADERA_FLL_SRC_SLIMCLK 3
#define MADERA_FLL_SRC_FLL1 4
#define MADERA_FLL_SRC_FLL2 5
@ -51,6 +52,7 @@
#define MADERA_CLK_SRC_MCLK1 0x0
#define MADERA_CLK_SRC_MCLK2 0x1
#define MADERA_CLK_SRC_MCLK3 0x2
#define MADERA_CLK_SRC_FLL1 0x4
#define MADERA_CLK_SRC_FLL2 0x5
#define MADERA_CLK_SRC_FLL3 0x6

View File

@ -62,6 +62,7 @@ struct pcm3168a_priv {
unsigned long sysclk;
struct pcm3168a_io_params io_params[2];
struct snd_soc_dai_driver dai_drv[2];
};
static const char *const pcm3168a_roll_off[] = { "Sharp", "Slow" };
@ -314,6 +315,34 @@ static int pcm3168a_set_dai_sysclk(struct snd_soc_dai *dai,
return 0;
}
static void pcm3168a_update_fixup_pcm_stream(struct snd_soc_dai *dai)
{
struct snd_soc_component *component = dai->component;
struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(component);
u64 formats = SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_LE;
unsigned int channel_max = dai->id == PCM3168A_DAI_DAC ? 8 : 6;
if (pcm3168a->io_params[dai->id].fmt == PCM3168A_FMT_RIGHT_J) {
/* S16_LE is only supported in RIGHT_J mode */
formats |= SNDRV_PCM_FMTBIT_S16_LE;
/*
* If multi DIN/DOUT is not selected, RIGHT_J can only support
* two channels (no TDM support)
*/
if (pcm3168a->io_params[dai->id].tdm_slots != 2)
channel_max = 2;
}
if (dai->id == PCM3168A_DAI_DAC) {
dai->driver->playback.channels_max = channel_max;
dai->driver->playback.formats = formats;
} else {
dai->driver->capture.channels_max = channel_max;
dai->driver->capture.formats = formats;
}
}
static int pcm3168a_set_dai_fmt(struct snd_soc_dai *dai, unsigned int format)
{
struct snd_soc_component *component = dai->component;
@ -376,6 +405,8 @@ static int pcm3168a_set_dai_fmt(struct snd_soc_dai *dai, unsigned int format)
regmap_update_bits(pcm3168a->regmap, reg, mask, fmt << shift);
pcm3168a_update_fixup_pcm_stream(dai);
return 0;
}
@ -409,6 +440,8 @@ static int pcm3168a_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
else
io_params->tdm_mask = rx_mask;
pcm3168a_update_fixup_pcm_stream(dai);
return 0;
}
@ -530,63 +563,7 @@ static int pcm3168a_hw_params(struct snd_pcm_substream *substream,
return 0;
}
static int pcm3168a_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_component *component = dai->component;
struct pcm3168a_priv *pcm3168a = snd_soc_component_get_drvdata(component);
unsigned int sample_min;
unsigned int channel_max;
unsigned int channel_maxs[] = {
8, /* DAC */
6 /* ADC */
};
/*
* Available Data Bits
*
* RIGHT_J : 24 / 16
* LEFT_J : 24
* I2S : 24
*
* TDM available
*
* I2S
* LEFT_J
*/
switch (pcm3168a->io_params[dai->id].fmt) {
case PCM3168A_FMT_RIGHT_J:
sample_min = 16;
channel_max = 2;
break;
case PCM3168A_FMT_LEFT_J:
case PCM3168A_FMT_I2S:
case PCM3168A_FMT_DSP_A:
case PCM3168A_FMT_DSP_B:
sample_min = 24;
channel_max = channel_maxs[dai->id];
break;
default:
sample_min = 24;
channel_max = 2;
}
snd_pcm_hw_constraint_minmax(substream->runtime,
SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
sample_min, 32);
/* Allow all channels in multi DIN/DOUT mode */
if (pcm3168a->io_params[dai->id].tdm_slots == 2)
channel_max = channel_maxs[dai->id];
snd_pcm_hw_constraint_minmax(substream->runtime,
SNDRV_PCM_HW_PARAM_CHANNELS,
2, channel_max);
return 0;
}
static const struct snd_soc_dai_ops pcm3168a_dai_ops = {
.startup = pcm3168a_startup,
.set_fmt = pcm3168a_set_dai_fmt,
.set_sysclk = pcm3168a_set_dai_sysclk,
.hw_params = pcm3168a_hw_params,
@ -776,8 +753,10 @@ int pcm3168a_probe(struct device *dev, struct regmap *regmap)
pm_runtime_enable(dev);
pm_runtime_idle(dev);
ret = devm_snd_soc_register_component(dev, &pcm3168a_driver, pcm3168a_dais,
ARRAY_SIZE(pcm3168a_dais));
memcpy(pcm3168a->dai_drv, pcm3168a_dais, sizeof(pcm3168a->dai_drv));
ret = devm_snd_soc_register_component(dev, &pcm3168a_driver,
pcm3168a->dai_drv,
ARRAY_SIZE(pcm3168a->dai_drv));
if (ret) {
dev_err(dev, "failed to register component: %d\n", ret);
goto err_regulator;

View File

@ -1805,8 +1805,8 @@ static int rt1011_set_tdm_slot(struct snd_soc_dai *dai,
struct snd_soc_component *component = dai->component;
struct snd_soc_dapm_context *dapm =
snd_soc_component_get_dapm(component);
unsigned int val = 0, tdm_en = 0;
int ret = 0;
unsigned int val = 0, tdm_en = 0, rx_slotnum, tx_slotnum;
int ret = 0, first_bit, last_bit;
snd_soc_dapm_mutex_lock(dapm);
if (rx_mask || tx_mask)
@ -1829,6 +1829,7 @@ static int rt1011_set_tdm_slot(struct snd_soc_dai *dai,
break;
default:
ret = -EINVAL;
goto _set_tdm_err_;
}
switch (slot_width) {
@ -1848,6 +1849,135 @@ static int rt1011_set_tdm_slot(struct snd_soc_dai *dai,
break;
default:
ret = -EINVAL;
goto _set_tdm_err_;
}
/* Rx slot configuration */
rx_slotnum = hweight_long(rx_mask);
first_bit = find_next_bit((unsigned long *)&rx_mask, 32, 0);
if (rx_slotnum > 1 || rx_slotnum == 0) {
ret = -EINVAL;
dev_dbg(component->dev, "too many rx slots or zero slot\n");
goto _set_tdm_err_;
}
switch (first_bit) {
case 0:
case 2:
case 4:
case 6:
snd_soc_component_update_bits(component,
RT1011_CROSS_BQ_SET_1, RT1011_MONO_LR_SEL_MASK,
RT1011_MONO_L_CHANNEL);
snd_soc_component_update_bits(component,
RT1011_TDM1_SET_4,
RT1011_TDM_I2S_TX_L_DAC1_1_MASK |
RT1011_TDM_I2S_TX_R_DAC1_1_MASK,
(first_bit << RT1011_TDM_I2S_TX_L_DAC1_1_SFT) |
((first_bit+1) << RT1011_TDM_I2S_TX_R_DAC1_1_SFT));
break;
case 1:
case 3:
case 5:
case 7:
snd_soc_component_update_bits(component,
RT1011_CROSS_BQ_SET_1, RT1011_MONO_LR_SEL_MASK,
RT1011_MONO_R_CHANNEL);
snd_soc_component_update_bits(component,
RT1011_TDM1_SET_4,
RT1011_TDM_I2S_TX_L_DAC1_1_MASK |
RT1011_TDM_I2S_TX_R_DAC1_1_MASK,
((first_bit-1) << RT1011_TDM_I2S_TX_L_DAC1_1_SFT) |
(first_bit << RT1011_TDM_I2S_TX_R_DAC1_1_SFT));
break;
default:
ret = -EINVAL;
goto _set_tdm_err_;
}
/* Tx slot configuration */
tx_slotnum = hweight_long(tx_mask);
first_bit = find_next_bit((unsigned long *)&tx_mask, 32, 0);
last_bit = find_last_bit((unsigned long *)&tx_mask, 32);
if (tx_slotnum > 2 || (last_bit-first_bit) > 1) {
ret = -EINVAL;
dev_dbg(component->dev, "too many tx slots or tx slot location error\n");
goto _set_tdm_err_;
}
if (tx_slotnum == 1) {
snd_soc_component_update_bits(component, RT1011_TDM1_SET_2,
RT1011_TDM_I2S_DOCK_ADCDAT_LEN_1_MASK |
RT1011_TDM_ADCDAT1_DATA_LOCATION, first_bit);
switch (first_bit) {
case 1:
snd_soc_component_update_bits(component,
RT1011_TDM1_SET_3,
RT1011_TDM_I2S_RX_ADC1_1_MASK,
RT1011_TDM_I2S_RX_ADC1_1_LL);
break;
case 3:
snd_soc_component_update_bits(component,
RT1011_TDM1_SET_3,
RT1011_TDM_I2S_RX_ADC2_1_MASK,
RT1011_TDM_I2S_RX_ADC2_1_LL);
break;
case 5:
snd_soc_component_update_bits(component,
RT1011_TDM1_SET_3,
RT1011_TDM_I2S_RX_ADC3_1_MASK,
RT1011_TDM_I2S_RX_ADC3_1_LL);
break;
case 7:
snd_soc_component_update_bits(component,
RT1011_TDM1_SET_3,
RT1011_TDM_I2S_RX_ADC4_1_MASK,
RT1011_TDM_I2S_RX_ADC4_1_LL);
break;
case 0:
snd_soc_component_update_bits(component,
RT1011_TDM1_SET_3,
RT1011_TDM_I2S_RX_ADC1_1_MASK, 0);
break;
case 2:
snd_soc_component_update_bits(component,
RT1011_TDM1_SET_3,
RT1011_TDM_I2S_RX_ADC2_1_MASK, 0);
break;
case 4:
snd_soc_component_update_bits(component,
RT1011_TDM1_SET_3,
RT1011_TDM_I2S_RX_ADC3_1_MASK, 0);
break;
case 6:
snd_soc_component_update_bits(component,
RT1011_TDM1_SET_3,
RT1011_TDM_I2S_RX_ADC4_1_MASK, 0);
break;
default:
ret = -EINVAL;
dev_dbg(component->dev,
"tx slot location error\n");
goto _set_tdm_err_;
}
} else if (tx_slotnum == 2) {
switch (first_bit) {
case 0:
case 2:
case 4:
case 6:
snd_soc_component_update_bits(component,
RT1011_TDM1_SET_2,
RT1011_TDM_I2S_DOCK_ADCDAT_LEN_1_MASK |
RT1011_TDM_ADCDAT1_DATA_LOCATION,
RT1011_TDM_I2S_DOCK_ADCDAT_2CH | first_bit);
break;
default:
ret = -EINVAL;
dev_dbg(component->dev,
"tx slot location should be paired and start from slot0/2/4/6\n");
goto _set_tdm_err_;
}
}
snd_soc_component_update_bits(component, RT1011_TDM1_SET_1,
@ -1860,10 +1990,12 @@ static int rt1011_set_tdm_slot(struct snd_soc_dai *dai,
RT1011_TDM_I2S_DOCK_EN_1_MASK, tdm_en);
snd_soc_component_update_bits(component, RT1011_TDM2_SET_2,
RT1011_TDM_I2S_DOCK_EN_2_MASK, tdm_en);
snd_soc_component_update_bits(component, RT1011_TDM_TOTAL_SET,
RT1011_ADCDAT1_PIN_CONFIG | RT1011_ADCDAT2_PIN_CONFIG,
RT1011_ADCDAT1_OUTPUT | RT1011_ADCDAT2_OUTPUT);
if (tx_slotnum)
snd_soc_component_update_bits(component, RT1011_TDM_TOTAL_SET,
RT1011_ADCDAT1_PIN_CONFIG | RT1011_ADCDAT2_PIN_CONFIG,
RT1011_ADCDAT1_OUTPUT | RT1011_ADCDAT2_OUTPUT);
_set_tdm_err_:
snd_soc_dapm_mutex_unlock(dapm);
return ret;
}
@ -2196,8 +2328,12 @@ static void rt1011_calibration_work(struct work_struct *work)
struct rt1011_priv *rt1011 =
container_of(work, struct rt1011_priv, cali_work);
struct snd_soc_component *component = rt1011->component;
unsigned int r0_integer, r0_factor, format;
rt1011_calibrate(rt1011, 1);
if (rt1011->r0_calib)
rt1011_calibrate(rt1011, 0);
else
rt1011_calibrate(rt1011, 1);
/*
* This flag should reset after booting.
@ -2208,6 +2344,39 @@ static void rt1011_calibration_work(struct work_struct *work)
/* initial */
rt1011_reg_init(component);
/* Apply temperature and calibration data from device property */
if (rt1011->temperature_calib) {
snd_soc_component_update_bits(component,
RT1011_STP_INITIAL_RESISTANCE_TEMP, 0x3ff,
(rt1011->temperature_calib << 2));
}
if (rt1011->r0_calib) {
rt1011->r0_reg = rt1011->r0_calib;
format = 2147483648U; /* 2^24 * 128 */
r0_integer = format / rt1011->r0_reg / 128;
r0_factor = ((format / rt1011->r0_reg * 100) / 128)
- (r0_integer * 100);
dev_info(component->dev, "DP r0 resistance about %d.%02d ohm, reg=0x%X\n",
r0_integer, r0_factor, rt1011->r0_reg);
rt1011_r0_load(rt1011);
}
}
static int rt1011_parse_dp(struct rt1011_priv *rt1011, struct device *dev)
{
device_property_read_u32(dev, "realtek,temperature_calib",
&rt1011->temperature_calib);
device_property_read_u32(dev, "realtek,r0_calib",
&rt1011->r0_calib);
dev_dbg(dev, "%s: r0_calib: 0x%x, temperture_calib: 0x%x",
__func__, rt1011->r0_calib, rt1011->temperature_calib);
return 0;
}
static int rt1011_i2c_probe(struct i2c_client *i2c,
@ -2224,6 +2393,8 @@ static int rt1011_i2c_probe(struct i2c_client *i2c,
i2c_set_clientdata(i2c, rt1011);
rt1011_parse_dp(rt1011, &i2c->dev);
rt1011->regmap = devm_regmap_init_i2c(i2c, &rt1011_regmap);
if (IS_ERR(rt1011->regmap)) {
ret = PTR_ERR(rt1011->regmap);

View File

@ -460,6 +460,23 @@
#define RT1011_TDM_I2S_DOCK_EN_1_MASK (0x1 << 3)
#define RT1011_TDM_I2S_DOCK_EN_1_SFT 3
#define RT1011_TDM_I2S_DOCK_EN_1 (0x1 << 3)
#define RT1011_TDM_ADCDAT1_DATA_LOCATION (0x7 << 0)
/* TDM1 Setting-3 (0x0118) */
#define RT1011_TDM_I2S_RX_ADC1_1_MASK (0x3 << 6)
#define RT1011_TDM_I2S_RX_ADC2_1_MASK (0x3 << 4)
#define RT1011_TDM_I2S_RX_ADC3_1_MASK (0x3 << 2)
#define RT1011_TDM_I2S_RX_ADC4_1_MASK (0x3 << 0)
#define RT1011_TDM_I2S_RX_ADC1_1_LL (0x2 << 6)
#define RT1011_TDM_I2S_RX_ADC2_1_LL (0x2 << 4)
#define RT1011_TDM_I2S_RX_ADC3_1_LL (0x2 << 2)
#define RT1011_TDM_I2S_RX_ADC4_1_LL (0x2 << 0)
/* TDM1 Setting-4 (0x011a) */
#define RT1011_TDM_I2S_TX_L_DAC1_1_MASK (0x7 << 12)
#define RT1011_TDM_I2S_TX_R_DAC1_1_MASK (0x7 << 8)
#define RT1011_TDM_I2S_TX_L_DAC1_1_SFT 12
#define RT1011_TDM_I2S_TX_R_DAC1_1_SFT 8
/* TDM2 Setting-2 (0x0120) */
#define RT1011_TDM_I2S_DOCK_ADCDAT_LEN_2_MASK (0x7 << 13)
@ -585,6 +602,12 @@
#define RT1011_STP_T0_EN_BIT 6
#define RT1011_STP_T0_EN (0x1 << 6)
/* Cross Biquad Setting-1 (0x0702) */
#define RT1011_MONO_LR_SEL_MASK (0x3 << 5)
#define RT1011_MONO_L_CHANNEL (0x0 << 5)
#define RT1011_MONO_R_CHANNEL (0x1 << 5)
#define RT1011_MONO_LR_MIX_CHANNEL (0x2 << 5)
/* ClassD Internal Setting-1 (0x1300) */
#define RT1011_DRIVER_READY_SPK (0x1 << 12)
#define RT1011_DRIVER_READY_SPK_BIT 12
@ -667,6 +690,7 @@ struct rt1011_priv {
int bq_drc_set;
unsigned int r0_reg, cali_done;
unsigned int r0_calib, temperature_calib;
int recv_spk_mode;
};

View File

@ -201,18 +201,18 @@ static irqreturn_t rt5514_spi_irq(int irq, void *data)
}
/* PCM for streaming audio from the DSP buffer */
static int rt5514_spi_pcm_open(struct snd_pcm_substream *substream)
static int rt5514_spi_pcm_open(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
snd_soc_set_runtime_hwparams(substream, &rt5514_spi_pcm_hardware);
return 0;
}
static int rt5514_spi_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *hw_params)
static int rt5514_spi_hw_params(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *hw_params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
struct rt5514_dsp *rt5514_dsp =
snd_soc_component_get_drvdata(component);
int ret;
@ -234,10 +234,9 @@ static int rt5514_spi_hw_params(struct snd_pcm_substream *substream,
return ret;
}
static int rt5514_spi_hw_free(struct snd_pcm_substream *substream)
static int rt5514_spi_hw_free(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
struct rt5514_dsp *rt5514_dsp =
snd_soc_component_get_drvdata(component);
@ -251,24 +250,22 @@ static int rt5514_spi_hw_free(struct snd_pcm_substream *substream)
}
static snd_pcm_uframes_t rt5514_spi_pcm_pointer(
struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
struct rt5514_dsp *rt5514_dsp =
snd_soc_component_get_drvdata(component);
return bytes_to_frames(runtime, rt5514_dsp->dma_offset);
}
static const struct snd_pcm_ops rt5514_spi_pcm_ops = {
.open = rt5514_spi_pcm_open,
.hw_params = rt5514_spi_hw_params,
.hw_free = rt5514_spi_hw_free,
.pointer = rt5514_spi_pcm_pointer,
.page = snd_pcm_lib_get_vmalloc_page,
};
static struct page *rt5514_spi_pcm_page(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
unsigned long offset)
{
return snd_pcm_lib_get_vmalloc_page(substream, offset);
}
static int rt5514_spi_pcm_probe(struct snd_soc_component *component)
{
@ -302,9 +299,13 @@ static int rt5514_spi_pcm_probe(struct snd_soc_component *component)
}
static const struct snd_soc_component_driver rt5514_spi_component = {
.name = DRV_NAME,
.probe = rt5514_spi_pcm_probe,
.ops = &rt5514_spi_pcm_ops,
.name = DRV_NAME,
.probe = rt5514_spi_pcm_probe,
.open = rt5514_spi_pcm_open,
.hw_params = rt5514_spi_hw_params,
.hw_free = rt5514_spi_hw_free,
.pointer = rt5514_spi_pcm_pointer,
.page = rt5514_spi_pcm_page,
};
/**

View File

@ -3644,7 +3644,7 @@ static int rt5663_i2c_probe(struct i2c_client *i2c,
regmap_update_bits(rt5663->regmap, RT5663_PWR_ANLG_1,
RT5663_LDO1_DVO_MASK | RT5663_AMP_HP_MASK,
RT5663_LDO1_DVO_0_9V | RT5663_AMP_HP_3X);
break;
break;
case CODEC_VER_0:
regmap_update_bits(rt5663->regmap, RT5663_DIG_MISC,
RT5663_DIG_GATE_CTRL_MASK, RT5663_DIG_GATE_CTRL_EN);
@ -3663,7 +3663,7 @@ static int rt5663_i2c_probe(struct i2c_client *i2c,
regmap_update_bits(rt5663->regmap, RT5663_TDM_2,
RT5663_DATA_SWAP_ADCDAT1_MASK,
RT5663_DATA_SWAP_ADCDAT1_LL);
break;
break;
default:
dev_err(&i2c->dev, "%s:Unknown codec type\n", __func__);
}

590
sound/soc/codecs/tas2562.c Normal file
View File

@ -0,0 +1,590 @@
// SPDX-License-Identifier: GPL-2.0
//
// Driver for the Texas Instruments TAS2562 CODEC
// Copyright (C) 2019 Texas Instruments Inc.
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/device.h>
#include <linux/i2c.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/gpio/consumer.h>
#include <linux/regulator/consumer.h>
#include <linux/delay.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/soc-dapm.h>
#include <sound/tlv.h>
#include "tas2562.h"
#define TAS2562_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE |\
SNDRV_PCM_FORMAT_S32_LE)
struct tas2562_data {
struct snd_soc_component *component;
struct gpio_desc *sdz_gpio;
struct regmap *regmap;
struct device *dev;
struct i2c_client *client;
int v_sense_slot;
int i_sense_slot;
};
static int tas2562_set_bias_level(struct snd_soc_component *component,
enum snd_soc_bias_level level)
{
struct tas2562_data *tas2562 =
snd_soc_component_get_drvdata(component);
switch (level) {
case SND_SOC_BIAS_ON:
snd_soc_component_update_bits(component,
TAS2562_PWR_CTRL,
TAS2562_MODE_MASK, TAS2562_ACTIVE);
break;
case SND_SOC_BIAS_STANDBY:
case SND_SOC_BIAS_PREPARE:
snd_soc_component_update_bits(component,
TAS2562_PWR_CTRL,
TAS2562_MODE_MASK, TAS2562_MUTE);
break;
case SND_SOC_BIAS_OFF:
snd_soc_component_update_bits(component,
TAS2562_PWR_CTRL,
TAS2562_MODE_MASK, TAS2562_SHUTDOWN);
break;
default:
dev_err(tas2562->dev,
"wrong power level setting %d\n", level);
return -EINVAL;
}
return 0;
}
static int tas2562_set_samplerate(struct tas2562_data *tas2562, int samplerate)
{
int samp_rate;
int ramp_rate;
switch (samplerate) {
case 7350:
ramp_rate = TAS2562_TDM_CFG0_RAMPRATE_44_1;
samp_rate = TAS2562_TDM_CFG0_SAMPRATE_7305_8KHZ;
break;
case 8000:
ramp_rate = 0;
samp_rate = TAS2562_TDM_CFG0_SAMPRATE_7305_8KHZ;
break;
case 14700:
ramp_rate = TAS2562_TDM_CFG0_RAMPRATE_44_1;
samp_rate = TAS2562_TDM_CFG0_SAMPRATE_14_7_16KHZ;
break;
case 16000:
ramp_rate = 0;
samp_rate = TAS2562_TDM_CFG0_SAMPRATE_14_7_16KHZ;
break;
case 22050:
ramp_rate = TAS2562_TDM_CFG0_RAMPRATE_44_1;
samp_rate = TAS2562_TDM_CFG0_SAMPRATE_22_05_24KHZ;
break;
case 24000:
ramp_rate = 0;
samp_rate = TAS2562_TDM_CFG0_SAMPRATE_22_05_24KHZ;
break;
case 29400:
ramp_rate = TAS2562_TDM_CFG0_RAMPRATE_44_1;
samp_rate = TAS2562_TDM_CFG0_SAMPRATE_29_4_32KHZ;
break;
case 32000:
ramp_rate = 0;
samp_rate = TAS2562_TDM_CFG0_SAMPRATE_29_4_32KHZ;
break;
case 44100:
ramp_rate = TAS2562_TDM_CFG0_RAMPRATE_44_1;
samp_rate = TAS2562_TDM_CFG0_SAMPRATE_44_1_48KHZ;
break;
case 48000:
ramp_rate = 0;
samp_rate = TAS2562_TDM_CFG0_SAMPRATE_44_1_48KHZ;
break;
case 88200:
ramp_rate = TAS2562_TDM_CFG0_RAMPRATE_44_1;
samp_rate = TAS2562_TDM_CFG0_SAMPRATE_88_2_96KHZ;
break;
case 96000:
ramp_rate = 0;
samp_rate = TAS2562_TDM_CFG0_SAMPRATE_88_2_96KHZ;
break;
case 176400:
ramp_rate = TAS2562_TDM_CFG0_RAMPRATE_44_1;
samp_rate = TAS2562_TDM_CFG0_SAMPRATE_176_4_192KHZ;
break;
case 192000:
ramp_rate = 0;
samp_rate = TAS2562_TDM_CFG0_SAMPRATE_176_4_192KHZ;
break;
default:
dev_info(tas2562->dev, "%s, unsupported sample rate, %d\n",
__func__, samplerate);
return -EINVAL;
}
snd_soc_component_update_bits(tas2562->component, TAS2562_TDM_CFG0,
TAS2562_TDM_CFG0_RAMPRATE_MASK, ramp_rate);
snd_soc_component_update_bits(tas2562->component, TAS2562_TDM_CFG0,
TAS2562_TDM_CFG0_SAMPRATE_MASK, samp_rate);
return 0;
}
static int tas2562_set_dai_tdm_slot(struct snd_soc_dai *dai,
unsigned int tx_mask, unsigned int rx_mask,
int slots, int slot_width)
{
struct snd_soc_component *component = dai->component;
struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component);
int ret = 0;
switch (slot_width) {
case 16:
ret = snd_soc_component_update_bits(component,
TAS2562_TDM_CFG2,
TAS2562_TDM_CFG2_RXLEN_MASK,
TAS2562_TDM_CFG2_RXLEN_16B);
break;
case 24:
ret = snd_soc_component_update_bits(component,
TAS2562_TDM_CFG2,
TAS2562_TDM_CFG2_RXLEN_MASK,
TAS2562_TDM_CFG2_RXLEN_24B);
break;
case 32:
ret = snd_soc_component_update_bits(component,
TAS2562_TDM_CFG2,
TAS2562_TDM_CFG2_RXLEN_MASK,
TAS2562_TDM_CFG2_RXLEN_32B);
break;
case 0:
/* Do not change slot width */
break;
default:
dev_err(tas2562->dev, "slot width not supported");
ret = -EINVAL;
}
if (ret < 0)
return ret;
return 0;
}
static int tas2562_set_bitwidth(struct tas2562_data *tas2562, int bitwidth)
{
int ret;
switch (bitwidth) {
case SNDRV_PCM_FORMAT_S16_LE:
snd_soc_component_update_bits(tas2562->component,
TAS2562_TDM_CFG2,
TAS2562_TDM_CFG2_RXWLEN_MASK,
TAS2562_TDM_CFG2_RXWLEN_16B);
tas2562->v_sense_slot = tas2562->i_sense_slot + 2;
break;
case SNDRV_PCM_FORMAT_S24_LE:
snd_soc_component_update_bits(tas2562->component,
TAS2562_TDM_CFG2,
TAS2562_TDM_CFG2_RXWLEN_MASK,
TAS2562_TDM_CFG2_RXWLEN_24B);
tas2562->v_sense_slot = tas2562->i_sense_slot + 4;
break;
case SNDRV_PCM_FORMAT_S32_LE:
snd_soc_component_update_bits(tas2562->component,
TAS2562_TDM_CFG2,
TAS2562_TDM_CFG2_RXWLEN_MASK,
TAS2562_TDM_CFG2_RXWLEN_32B);
tas2562->v_sense_slot = tas2562->i_sense_slot + 4;
break;
default:
dev_info(tas2562->dev, "Not supported params format\n");
}
ret = snd_soc_component_update_bits(tas2562->component,
TAS2562_TDM_CFG5,
TAS2562_TDM_CFG5_VSNS_EN | TAS2562_TDM_CFG5_VSNS_SLOT_MASK,
TAS2562_TDM_CFG5_VSNS_EN | tas2562->v_sense_slot);
if (ret < 0)
return ret;
ret = snd_soc_component_update_bits(tas2562->component,
TAS2562_TDM_CFG6,
TAS2562_TDM_CFG6_ISNS_EN | TAS2562_TDM_CFG6_ISNS_SLOT_MASK,
TAS2562_TDM_CFG6_ISNS_EN | tas2562->i_sense_slot);
if (ret < 0)
return ret;
return 0;
}
static int tas2562_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
struct snd_soc_component *component = dai->component;
struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component);
int ret;
ret = tas2562_set_bitwidth(tas2562, params_format(params));
if (ret) {
dev_err(tas2562->dev, "set bitwidth failed, %d\n", ret);
return ret;
}
ret = tas2562_set_samplerate(tas2562, params_rate(params));
if (ret)
dev_err(tas2562->dev, "set bitwidth failed, %d\n", ret);
return ret;
}
static int tas2562_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
{
struct snd_soc_component *component = dai->component;
struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component);
u8 tdm_rx_start_slot = 0, asi_cfg_1 = 0;
int ret;
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
case SND_SOC_DAIFMT_NB_NF:
asi_cfg_1 = 0;
break;
case SND_SOC_DAIFMT_IB_NF:
asi_cfg_1 |= TAS2562_TDM_CFG1_RX_FALLING;
break;
default:
dev_err(tas2562->dev, "ASI format Inverse is not found\n");
return -EINVAL;
}
ret = snd_soc_component_update_bits(component, TAS2562_TDM_CFG1,
TAS2562_TDM_CFG1_RX_EDGE_MASK,
asi_cfg_1);
if (ret < 0) {
dev_err(tas2562->dev, "Failed to set RX edge\n");
return ret;
}
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case (SND_SOC_DAIFMT_I2S):
case (SND_SOC_DAIFMT_DSP_A):
case (SND_SOC_DAIFMT_DSP_B):
tdm_rx_start_slot = BIT(1);
break;
case (SND_SOC_DAIFMT_LEFT_J):
tdm_rx_start_slot = 0;
break;
default:
dev_err(tas2562->dev, "DAI Format is not found, fmt=0x%x\n",
fmt);
ret = -EINVAL;
break;
}
ret = snd_soc_component_update_bits(component, TAS2562_TDM_CFG1,
TAS2562_TDM_CFG1_RX_OFFSET_MASK,
tdm_rx_start_slot);
if (ret < 0)
return ret;
return 0;
}
static int tas2562_mute(struct snd_soc_dai *dai, int mute)
{
struct snd_soc_component *component = dai->component;
return snd_soc_component_update_bits(component, TAS2562_PWR_CTRL,
TAS2562_MODE_MASK,
mute ? TAS2562_MUTE : 0);
}
static int tas2562_codec_probe(struct snd_soc_component *component)
{
struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component);
int ret;
tas2562->component = component;
if (tas2562->sdz_gpio)
gpiod_set_value_cansleep(tas2562->sdz_gpio, 1);
ret = snd_soc_component_update_bits(component, TAS2562_PWR_CTRL,
TAS2562_MODE_MASK, TAS2562_MUTE);
if (ret < 0)
return ret;
return 0;
}
#ifdef CONFIG_PM
static int tas2562_suspend(struct snd_soc_component *component)
{
struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component);
regcache_cache_only(tas2562->regmap, true);
regcache_mark_dirty(tas2562->regmap);
if (tas2562->sdz_gpio)
gpiod_set_value_cansleep(tas2562->sdz_gpio, 0);
return 0;
}
static int tas2562_resume(struct snd_soc_component *component)
{
struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component);
if (tas2562->sdz_gpio)
gpiod_set_value_cansleep(tas2562->sdz_gpio, 1);
regcache_cache_only(tas2562->regmap, false);
return regcache_sync(tas2562->regmap);
}
#else
#define tas2562_suspend NULL
#define tas2562_resume NULL
#endif
static const char * const tas2562_ASI1_src[] = {
"I2C offset", "Left", "Right", "LeftRightDiv2",
};
static SOC_ENUM_SINGLE_DECL(tas2562_ASI1_src_enum, TAS2562_TDM_CFG2, 4,
tas2562_ASI1_src);
static const struct snd_kcontrol_new tas2562_asi1_mux =
SOC_DAPM_ENUM("ASI1 Source", tas2562_ASI1_src_enum);
static int tas2562_dac_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_component *component =
snd_soc_dapm_to_component(w->dapm);
struct tas2562_data *tas2562 = snd_soc_component_get_drvdata(component);
switch (event) {
case SND_SOC_DAPM_POST_PMU:
dev_info(tas2562->dev, "SND_SOC_DAPM_POST_PMU\n");
break;
case SND_SOC_DAPM_PRE_PMD:
dev_info(tas2562->dev, "SND_SOC_DAPM_PRE_PMD\n");
break;
default:
break;
}
return 0;
}
static DECLARE_TLV_DB_SCALE(tas2562_dac_tlv, 850, 50, 0);
static const struct snd_kcontrol_new isense_switch =
SOC_DAPM_SINGLE("Switch", TAS2562_PWR_CTRL, TAS2562_ISENSE_POWER_EN,
1, 1);
static const struct snd_kcontrol_new vsense_switch =
SOC_DAPM_SINGLE("Switch", TAS2562_PWR_CTRL, TAS2562_VSENSE_POWER_EN,
1, 1);
static const struct snd_kcontrol_new tas2562_snd_controls[] = {
SOC_SINGLE_TLV("Amp Gain Volume", TAS2562_PB_CFG1, 0, 0x1c, 0,
tas2562_dac_tlv),
};
static const struct snd_soc_dapm_widget tas2562_dapm_widgets[] = {
SND_SOC_DAPM_AIF_IN("ASI1", "ASI1 Playback", 0, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_MUX("ASI1 Sel", SND_SOC_NOPM, 0, 0, &tas2562_asi1_mux),
SND_SOC_DAPM_AIF_IN("DAC IN", "Playback", 0, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0, tas2562_dac_event,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
SND_SOC_DAPM_SWITCH("ISENSE", TAS2562_PWR_CTRL, 3, 1, &isense_switch),
SND_SOC_DAPM_SWITCH("VSENSE", TAS2562_PWR_CTRL, 2, 1, &vsense_switch),
SND_SOC_DAPM_SIGGEN("VMON"),
SND_SOC_DAPM_SIGGEN("IMON"),
SND_SOC_DAPM_OUTPUT("OUT"),
};
static const struct snd_soc_dapm_route tas2562_audio_map[] = {
{"ASI1 Sel", "I2C offset", "ASI1"},
{"ASI1 Sel", "Left", "ASI1"},
{"ASI1 Sel", "Right", "ASI1"},
{"ASI1 Sel", "LeftRightDiv2", "ASI1"},
{ "DAC", NULL, "DAC IN" },
{ "OUT", NULL, "DAC" },
{"ISENSE", "Switch", "IMON"},
{"VSENSE", "Switch", "VMON"},
};
static const struct snd_soc_component_driver soc_component_dev_tas2562 = {
.probe = tas2562_codec_probe,
.suspend = tas2562_suspend,
.resume = tas2562_resume,
.set_bias_level = tas2562_set_bias_level,
.controls = tas2562_snd_controls,
.num_controls = ARRAY_SIZE(tas2562_snd_controls),
.dapm_widgets = tas2562_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(tas2562_dapm_widgets),
.dapm_routes = tas2562_audio_map,
.num_dapm_routes = ARRAY_SIZE(tas2562_audio_map),
.idle_bias_on = 1,
.use_pmdown_time = 1,
.endianness = 1,
.non_legacy_dai_naming = 1,
};
static const struct snd_soc_dai_ops tas2562_speaker_dai_ops = {
.hw_params = tas2562_hw_params,
.set_fmt = tas2562_set_dai_fmt,
.set_tdm_slot = tas2562_set_dai_tdm_slot,
.digital_mute = tas2562_mute,
};
static struct snd_soc_dai_driver tas2562_dai[] = {
{
.name = "tas2562-amplifier",
.id = 0,
.playback = {
.stream_name = "ASI1 Playback",
.channels_min = 2,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_8000_192000,
.formats = TAS2562_FORMATS,
},
.ops = &tas2562_speaker_dai_ops,
},
};
static const struct regmap_range_cfg tas2562_ranges[] = {
{
.range_min = 0,
.range_max = 5 * 128,
.selector_reg = TAS2562_PAGE_CTRL,
.selector_mask = 0xff,
.selector_shift = 0,
.window_start = 0,
.window_len = 128,
},
};
static const struct reg_default tas2562_reg_defaults[] = {
{ TAS2562_PAGE_CTRL, 0x00 },
{ TAS2562_SW_RESET, 0x00 },
{ TAS2562_PWR_CTRL, 0x0e },
{ TAS2562_PB_CFG1, 0x20 },
{ TAS2562_TDM_CFG0, 0x09 },
{ TAS2562_TDM_CFG1, 0x02 },
};
static const struct regmap_config tas2562_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = 5 * 128,
.cache_type = REGCACHE_RBTREE,
.reg_defaults = tas2562_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(tas2562_reg_defaults),
.ranges = tas2562_ranges,
.num_ranges = ARRAY_SIZE(tas2562_ranges),
};
static int tas2562_parse_dt(struct tas2562_data *tas2562)
{
struct device *dev = tas2562->dev;
int ret = 0;
tas2562->sdz_gpio = devm_gpiod_get_optional(dev, "shut-down-gpio",
GPIOD_OUT_HIGH);
if (IS_ERR(tas2562->sdz_gpio)) {
if (PTR_ERR(tas2562->sdz_gpio) == -EPROBE_DEFER) {
tas2562->sdz_gpio = NULL;
return -EPROBE_DEFER;
}
}
ret = fwnode_property_read_u32(dev->fwnode, "ti,imon-slot-no",
&tas2562->i_sense_slot);
if (ret)
dev_err(dev, "Looking up %s property failed %d\n",
"ti,imon-slot-no", ret);
return ret;
}
static int tas2562_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct device *dev = &client->dev;
struct tas2562_data *data;
int ret;
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
data->client = client;
data->dev = &client->dev;
tas2562_parse_dt(data);
data->regmap = devm_regmap_init_i2c(client, &tas2562_regmap_config);
if (IS_ERR(data->regmap)) {
ret = PTR_ERR(data->regmap);
dev_err(dev, "failed to allocate register map: %d\n", ret);
return ret;
}
dev_set_drvdata(&client->dev, data);
return devm_snd_soc_register_component(dev, &soc_component_dev_tas2562,
tas2562_dai,
ARRAY_SIZE(tas2562_dai));
}
static const struct i2c_device_id tas2562_id[] = {
{ "tas2562", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, tas2562_id);
static const struct of_device_id tas2562_of_match[] = {
{ .compatible = "ti,tas2562", },
{ },
};
MODULE_DEVICE_TABLE(of, tas2562_of_match);
static struct i2c_driver tas2562_i2c_driver = {
.driver = {
.name = "tas2562",
.of_match_table = of_match_ptr(tas2562_of_match),
},
.probe = tas2562_probe,
.id_table = tas2562_id,
};
module_i2c_driver(tas2562_i2c_driver);
MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>");
MODULE_DESCRIPTION("TAS2562 Audio amplifier driver");
MODULE_LICENSE("GPL");

View File

@ -0,0 +1,85 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* tas2562.h - ALSA SoC Texas Instruments TAS2562 Mono Audio Amplifier
*
* Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com
*
* Author: Dan Murphy <dmurphy@ti.com>
*/
#ifndef __TAS2562_H__
#define __TAS2562_H__
#define TAS2562_PAGE_CTRL 0x00
#define TAS2562_REG(page, reg) ((page * 128) + reg)
#define TAS2562_SW_RESET TAS2562_REG(0, 0x01)
#define TAS2562_PWR_CTRL TAS2562_REG(0, 0x02)
#define TAS2562_PB_CFG1 TAS2562_REG(0, 0x03)
#define TAS2562_MISC_CFG1 TAS2562_REG(0, 0x04)
#define TAS2562_MISC_CFG2 TAS2562_REG(0, 0x05)
#define TAS2562_TDM_CFG0 TAS2562_REG(0, 0x06)
#define TAS2562_TDM_CFG1 TAS2562_REG(0, 0x07)
#define TAS2562_TDM_CFG2 TAS2562_REG(0, 0x08)
#define TAS2562_TDM_CFG3 TAS2562_REG(0, 0x09)
#define TAS2562_TDM_CFG4 TAS2562_REG(0, 0x0a)
#define TAS2562_TDM_CFG5 TAS2562_REG(0, 0x0b)
#define TAS2562_TDM_CFG6 TAS2562_REG(0, 0x0c)
#define TAS2562_TDM_CFG7 TAS2562_REG(0, 0x0d)
#define TAS2562_TDM_CFG8 TAS2562_REG(0, 0x0e)
#define TAS2562_TDM_CFG9 TAS2562_REG(0, 0x0f)
#define TAS2562_TDM_CFG10 TAS2562_REG(0, 0x10)
#define TAS2562_TDM_DET TAS2562_REG(0, 0x11)
#define TAS2562_REV_ID TAS2562_REG(0, 0x7d)
/* Page 2 */
#define TAS2562_DVC_CFG1 TAS2562_REG(2, 0x01)
#define TAS2562_DVC_CFG2 TAS2562_REG(2, 0x02)
#define TAS2562_RESET BIT(0)
#define TAS2562_MODE_MASK 0x3
#define TAS2562_ACTIVE 0x0
#define TAS2562_MUTE 0x1
#define TAS2562_SHUTDOWN 0x2
#define TAS2562_TDM_CFG1_RX_EDGE_MASK BIT(0)
#define TAS2562_TDM_CFG1_RX_FALLING 1
#define TAS2562_TDM_CFG1_RX_OFFSET_MASK GENMASK(4, 0)
#define TAS2562_TDM_CFG0_RAMPRATE_MASK BIT(5)
#define TAS2562_TDM_CFG0_RAMPRATE_44_1 BIT(5)
#define TAS2562_TDM_CFG0_SAMPRATE_MASK GENMASK(3, 1)
#define TAS2562_TDM_CFG0_SAMPRATE_7305_8KHZ 0x0
#define TAS2562_TDM_CFG0_SAMPRATE_14_7_16KHZ 0x1
#define TAS2562_TDM_CFG0_SAMPRATE_22_05_24KHZ 0x2
#define TAS2562_TDM_CFG0_SAMPRATE_29_4_32KHZ 0x3
#define TAS2562_TDM_CFG0_SAMPRATE_44_1_48KHZ 0x4
#define TAS2562_TDM_CFG0_SAMPRATE_88_2_96KHZ 0x5
#define TAS2562_TDM_CFG0_SAMPRATE_176_4_192KHZ 0x6
#define TAS2562_TDM_CFG2_RIGHT_JUSTIFY BIT(6)
#define TAS2562_TDM_CFG2_RXLEN_MASK GENMASK(0, 1)
#define TAS2562_TDM_CFG2_RXLEN_16B 0x0
#define TAS2562_TDM_CFG2_RXLEN_24B BIT(0)
#define TAS2562_TDM_CFG2_RXLEN_32B BIT(1)
#define TAS2562_TDM_CFG2_RXWLEN_MASK GENMASK(3, 2)
#define TAS2562_TDM_CFG2_RXWLEN_16B 0x0
#define TAS2562_TDM_CFG2_RXWLEN_20B BIT(2)
#define TAS2562_TDM_CFG2_RXWLEN_24B BIT(3)
#define TAS2562_TDM_CFG2_RXWLEN_32B (BIT(2) | BIT(3))
#define TAS2562_VSENSE_POWER_EN BIT(2)
#define TAS2562_ISENSE_POWER_EN BIT(3)
#define TAS2562_TDM_CFG5_VSNS_EN BIT(6)
#define TAS2562_TDM_CFG5_VSNS_SLOT_MASK GENMASK(5, 0)
#define TAS2562_TDM_CFG6_ISNS_EN BIT(6)
#define TAS2562_TDM_CFG6_ISNS_SLOT_MASK GENMASK(5, 0)
#endif /* __TAS2562_H__ */

819
sound/soc/codecs/tas2770.c Normal file
View File

@ -0,0 +1,819 @@
// SPDX-License-Identifier: GPL-2.0
//
// ALSA SoC Texas Instruments TAS2770 20-W Digital Input Mono Class-D
// Audio Amplifier with Speaker I/V Sense
//
// Copyright (C) 2016-2017 Texas Instruments Incorporated - http://www.ti.com/
// Author: Tracy Yi <tracy-yi@ti.com>
// Frank Shi <shifu0704@thundersoft.com>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/err.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h>
#include <linux/firmware.h>
#include <linux/regmap.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/slab.h>
#include <sound/soc.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/initval.h>
#include <sound/tlv.h>
#include "tas2770.h"
#define TAS2770_MDELAY 0xFFFFFFFE
static void tas2770_reset(struct tas2770_priv *tas2770)
{
if (tas2770->reset_gpio) {
gpiod_set_value_cansleep(tas2770->reset_gpio, 0);
msleep(20);
gpiod_set_value_cansleep(tas2770->reset_gpio, 1);
}
snd_soc_component_write(tas2770->component, TAS2770_SW_RST,
TAS2770_RST);
}
static int tas2770_set_bias_level(struct snd_soc_component *component,
enum snd_soc_bias_level level)
{
struct tas2770_priv *tas2770 =
snd_soc_component_get_drvdata(component);
switch (level) {
case SND_SOC_BIAS_ON:
snd_soc_component_update_bits(component,
TAS2770_PWR_CTRL,
TAS2770_PWR_CTRL_MASK,
TAS2770_PWR_CTRL_ACTIVE);
break;
case SND_SOC_BIAS_OFF:
snd_soc_component_update_bits(component,
TAS2770_PWR_CTRL,
TAS2770_PWR_CTRL_MASK,
TAS2770_PWR_CTRL_SHUTDOWN);
break;
default:
dev_err(tas2770->dev,
"wrong power level setting %d\n", level);
return -EINVAL;
}
return 0;
}
#ifdef CONFIG_PM
static int tas2770_codec_suspend(struct snd_soc_component *component)
{
int ret;
ret = snd_soc_component_update_bits(component,
TAS2770_PWR_CTRL,
TAS2770_PWR_CTRL_MASK,
TAS2770_PWR_CTRL_SHUTDOWN);
if (ret < 0)
return ret;
return 0;
}
static int tas2770_codec_resume(struct snd_soc_component *component)
{
int ret;
ret = snd_soc_component_update_bits(component,
TAS2770_PWR_CTRL,
TAS2770_PWR_CTRL_MASK,
TAS2770_PWR_CTRL_ACTIVE);
if (ret < 0)
return ret;
return 0;
}
#else
#define tas2770_codec_suspend NULL
#define tas2770_codec_resume NULL
#endif
static const char * const tas2770_ASI1_src[] = {
"I2C offset", "Left", "Right", "LeftRightDiv2",
};
static SOC_ENUM_SINGLE_DECL(
tas2770_ASI1_src_enum, TAS2770_TDM_CFG_REG2,
4, tas2770_ASI1_src);
static const struct snd_kcontrol_new tas2770_asi1_mux =
SOC_DAPM_ENUM("ASI1 Source", tas2770_ASI1_src_enum);
static int tas2770_dac_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_component *component =
snd_soc_dapm_to_component(w->dapm);
struct tas2770_priv *tas2770 =
snd_soc_component_get_drvdata(component);
int ret;
switch (event) {
case SND_SOC_DAPM_POST_PMU:
ret = snd_soc_component_update_bits(component,
TAS2770_PWR_CTRL,
TAS2770_PWR_CTRL_MASK,
TAS2770_PWR_CTRL_MUTE);
if (ret)
goto end;
break;
case SND_SOC_DAPM_PRE_PMD:
ret = snd_soc_component_update_bits(component,
TAS2770_PWR_CTRL,
TAS2770_PWR_CTRL_MASK,
TAS2770_PWR_CTRL_SHUTDOWN);
if (ret)
goto end;
break;
default:
dev_err(tas2770->dev, "Not supported evevt\n");
return -EINVAL;
}
end:
if (ret < 0)
return ret;
return 0;
}
static const struct snd_kcontrol_new isense_switch =
SOC_DAPM_SINGLE("Switch", TAS2770_PWR_CTRL, 3, 1, 1);
static const struct snd_kcontrol_new vsense_switch =
SOC_DAPM_SINGLE("Switch", TAS2770_PWR_CTRL, 2, 1, 1);
static const struct snd_soc_dapm_widget tas2770_dapm_widgets[] = {
SND_SOC_DAPM_AIF_IN("ASI1", "ASI1 Playback", 0, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_MUX("ASI1 Sel", SND_SOC_NOPM, 0, 0,
&tas2770_asi1_mux),
SND_SOC_DAPM_SWITCH("ISENSE", TAS2770_PWR_CTRL, 3, 1,
&isense_switch),
SND_SOC_DAPM_SWITCH("VSENSE", TAS2770_PWR_CTRL, 2, 1,
&vsense_switch),
SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0, tas2770_dac_event,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
SND_SOC_DAPM_OUTPUT("OUT"),
SND_SOC_DAPM_SIGGEN("VMON"),
SND_SOC_DAPM_SIGGEN("IMON")
};
static const struct snd_soc_dapm_route tas2770_audio_map[] = {
{"ASI1 Sel", "I2C offset", "ASI1"},
{"ASI1 Sel", "Left", "ASI1"},
{"ASI1 Sel", "Right", "ASI1"},
{"ASI1 Sel", "LeftRightDiv2", "ASI1"},
{"DAC", NULL, "ASI1 Sel"},
{"OUT", NULL, "DAC"},
{"ISENSE", "Switch", "IMON"},
{"VSENSE", "Switch", "VMON"},
};
static int tas2770_mute(struct snd_soc_dai *dai, int mute)
{
struct snd_soc_component *component = dai->component;
int ret;
if (mute)
ret = snd_soc_component_update_bits(component,
TAS2770_PWR_CTRL,
TAS2770_PWR_CTRL_MASK,
TAS2770_PWR_CTRL_MUTE);
else
ret = snd_soc_component_update_bits(component,
TAS2770_PWR_CTRL,
TAS2770_PWR_CTRL_MASK,
TAS2770_PWR_CTRL_ACTIVE);
if (ret < 0)
return ret;
return 0;
}
static int tas2770_set_bitwidth(struct tas2770_priv *tas2770, int bitwidth)
{
int ret;
struct snd_soc_component *component = tas2770->component;
switch (bitwidth) {
case SNDRV_PCM_FORMAT_S16_LE:
ret = snd_soc_component_update_bits(component,
TAS2770_TDM_CFG_REG2,
TAS2770_TDM_CFG_REG2_RXW_MASK,
TAS2770_TDM_CFG_REG2_RXW_16BITS);
tas2770->v_sense_slot = tas2770->i_sense_slot + 2;
break;
case SNDRV_PCM_FORMAT_S24_LE:
ret = snd_soc_component_update_bits(component,
TAS2770_TDM_CFG_REG2,
TAS2770_TDM_CFG_REG2_RXW_MASK,
TAS2770_TDM_CFG_REG2_RXW_24BITS);
tas2770->v_sense_slot = tas2770->i_sense_slot + 4;
break;
case SNDRV_PCM_FORMAT_S32_LE:
ret = snd_soc_component_update_bits(component,
TAS2770_TDM_CFG_REG2,
TAS2770_TDM_CFG_REG2_RXW_MASK,
TAS2770_TDM_CFG_REG2_RXW_32BITS);
tas2770->v_sense_slot = tas2770->i_sense_slot + 4;
break;
default:
return -EINVAL;
}
tas2770->channel_size = bitwidth;
ret = snd_soc_component_update_bits(component,
TAS2770_TDM_CFG_REG5,
TAS2770_TDM_CFG_REG5_VSNS_MASK |
TAS2770_TDM_CFG_REG5_50_MASK,
TAS2770_TDM_CFG_REG5_VSNS_ENABLE |
tas2770->v_sense_slot);
if (ret)
goto end;
ret = snd_soc_component_update_bits(component,
TAS2770_TDM_CFG_REG6,
TAS2770_TDM_CFG_REG6_ISNS_MASK |
TAS2770_TDM_CFG_REG6_50_MASK,
TAS2770_TDM_CFG_REG6_ISNS_ENABLE |
tas2770->i_sense_slot);
end:
if (ret < 0)
return ret;
return 0;
}
static int tas2770_set_samplerate(struct tas2770_priv *tas2770, int samplerate)
{
int ret;
struct snd_soc_component *component = tas2770->component;
switch (samplerate) {
case 48000:
ret = snd_soc_component_update_bits(component,
TAS2770_TDM_CFG_REG0,
TAS2770_TDM_CFG_REG0_SMP_MASK,
TAS2770_TDM_CFG_REG0_SMP_48KHZ);
if (ret)
goto end;
ret = snd_soc_component_update_bits(component,
TAS2770_TDM_CFG_REG0,
TAS2770_TDM_CFG_REG0_31_MASK,
TAS2770_TDM_CFG_REG0_31_44_1_48KHZ);
if (ret)
goto end;
break;
case 44100:
ret = snd_soc_component_update_bits(component,
TAS2770_TDM_CFG_REG0,
TAS2770_TDM_CFG_REG0_SMP_MASK,
TAS2770_TDM_CFG_REG0_SMP_44_1KHZ);
if (ret)
goto end;
ret = snd_soc_component_update_bits(component,
TAS2770_TDM_CFG_REG0,
TAS2770_TDM_CFG_REG0_31_MASK,
TAS2770_TDM_CFG_REG0_31_44_1_48KHZ);
if (ret)
goto end;
break;
case 96000:
ret = snd_soc_component_update_bits(component,
TAS2770_TDM_CFG_REG0,
TAS2770_TDM_CFG_REG0_SMP_MASK,
TAS2770_TDM_CFG_REG0_SMP_48KHZ);
if (ret)
goto end;
ret = snd_soc_component_update_bits(component,
TAS2770_TDM_CFG_REG0,
TAS2770_TDM_CFG_REG0_31_MASK,
TAS2770_TDM_CFG_REG0_31_88_2_96KHZ);
break;
case 88200:
ret = snd_soc_component_update_bits(component,
TAS2770_TDM_CFG_REG0,
TAS2770_TDM_CFG_REG0_SMP_MASK,
TAS2770_TDM_CFG_REG0_SMP_44_1KHZ);
if (ret)
goto end;
ret = snd_soc_component_update_bits(component,
TAS2770_TDM_CFG_REG0,
TAS2770_TDM_CFG_REG0_31_MASK,
TAS2770_TDM_CFG_REG0_31_88_2_96KHZ);
break;
case 19200:
ret = snd_soc_component_update_bits(component,
TAS2770_TDM_CFG_REG0,
TAS2770_TDM_CFG_REG0_SMP_MASK,
TAS2770_TDM_CFG_REG0_SMP_48KHZ);
if (ret)
goto end;
ret = snd_soc_component_update_bits(component,
TAS2770_TDM_CFG_REG0,
TAS2770_TDM_CFG_REG0_31_MASK,
TAS2770_TDM_CFG_REG0_31_176_4_192KHZ);
if (ret)
goto end;
break;
case 17640:
ret = snd_soc_component_update_bits(component,
TAS2770_TDM_CFG_REG0,
TAS2770_TDM_CFG_REG0_SMP_MASK,
TAS2770_TDM_CFG_REG0_SMP_44_1KHZ);
if (ret)
goto end;
ret = snd_soc_component_update_bits(component,
TAS2770_TDM_CFG_REG0,
TAS2770_TDM_CFG_REG0_31_MASK,
TAS2770_TDM_CFG_REG0_31_176_4_192KHZ);
break;
default:
ret = -EINVAL;
}
end:
if (ret < 0)
return ret;
tas2770->sampling_rate = samplerate;
return 0;
}
static int tas2770_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
struct snd_soc_component *component = dai->component;
struct tas2770_priv *tas2770 =
snd_soc_component_get_drvdata(component);
int ret;
ret = tas2770_set_bitwidth(tas2770, params_format(params));
if (ret < 0)
goto end;
ret = tas2770_set_samplerate(tas2770, params_rate(params));
end:
return ret;
}
static int tas2770_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
{
u8 tdm_rx_start_slot = 0, asi_cfg_1 = 0;
int ret;
struct snd_soc_component *component = dai->component;
struct tas2770_priv *tas2770 =
snd_soc_component_get_drvdata(component);
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBS_CFS:
break;
default:
dev_err(tas2770->dev, "ASI format master is not found\n");
return -EINVAL;
}
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
case SND_SOC_DAIFMT_NB_NF:
asi_cfg_1 |= TAS2770_TDM_CFG_REG1_RX_RSING;
break;
case SND_SOC_DAIFMT_IB_NF:
asi_cfg_1 |= TAS2770_TDM_CFG_REG1_RX_FALING;
break;
default:
dev_err(tas2770->dev, "ASI format Inverse is not found\n");
return -EINVAL;
}
ret = snd_soc_component_update_bits(component, TAS2770_TDM_CFG_REG1,
TAS2770_TDM_CFG_REG1_RX_MASK,
asi_cfg_1);
if (ret < 0)
return ret;
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_I2S:
tdm_rx_start_slot = 1;
break;
case SND_SOC_DAIFMT_DSP_A:
tdm_rx_start_slot = 0;
break;
case SND_SOC_DAIFMT_DSP_B:
tdm_rx_start_slot = 1;
break;
case SND_SOC_DAIFMT_LEFT_J:
tdm_rx_start_slot = 0;
break;
default:
dev_err(tas2770->dev,
"DAI Format is not found, fmt=0x%x\n", fmt);
return -EINVAL;
}
ret = snd_soc_component_update_bits(component, TAS2770_TDM_CFG_REG1,
TAS2770_TDM_CFG_REG1_MASK,
(tdm_rx_start_slot << TAS2770_TDM_CFG_REG1_51_SHIFT));
if (ret < 0)
return ret;
tas2770->asi_format = fmt;
return 0;
}
static int tas2770_set_dai_tdm_slot(struct snd_soc_dai *dai,
unsigned int tx_mask,
unsigned int rx_mask,
int slots, int slot_width)
{
struct snd_soc_component *component = dai->component;
struct tas2770_priv *tas2770 =
snd_soc_component_get_drvdata(component);
int left_slot, right_slot;
int ret;
if (tx_mask == 0 || rx_mask != 0)
return -EINVAL;
if (slots == 1) {
if (tx_mask != 1)
return -EINVAL;
left_slot = 0;
right_slot = 0;
} else {
left_slot = __ffs(tx_mask);
tx_mask &= ~(1 << left_slot);
if (tx_mask == 0) {
right_slot = left_slot;
} else {
right_slot = __ffs(tx_mask);
tx_mask &= ~(1 << right_slot);
}
}
if (tx_mask != 0 || left_slot >= slots || right_slot >= slots)
return -EINVAL;
ret = snd_soc_component_update_bits(component, TAS2770_TDM_CFG_REG3,
TAS2770_TDM_CFG_REG3_30_MASK,
(left_slot << TAS2770_TDM_CFG_REG3_30_SHIFT));
if (ret < 0)
return ret;
ret = snd_soc_component_update_bits(component, TAS2770_TDM_CFG_REG3,
TAS2770_TDM_CFG_REG3_RXS_MASK,
(right_slot << TAS2770_TDM_CFG_REG3_RXS_SHIFT));
if (ret < 0)
return ret;
switch (slot_width) {
case 16:
ret = snd_soc_component_update_bits(component,
TAS2770_TDM_CFG_REG2,
TAS2770_TDM_CFG_REG2_RXS_MASK,
TAS2770_TDM_CFG_REG2_RXS_16BITS);
break;
case 24:
ret = snd_soc_component_update_bits(component,
TAS2770_TDM_CFG_REG2,
TAS2770_TDM_CFG_REG2_RXS_MASK,
TAS2770_TDM_CFG_REG2_RXS_24BITS);
break;
case 32:
ret = snd_soc_component_update_bits(component,
TAS2770_TDM_CFG_REG2,
TAS2770_TDM_CFG_REG2_RXS_MASK,
TAS2770_TDM_CFG_REG2_RXS_32BITS);
break;
case 0:
/* Do not change slot width */
ret = 0;
break;
default:
ret = -EINVAL;
}
if (ret < 0)
return ret;
tas2770->slot_width = slot_width;
return 0;
}
static struct snd_soc_dai_ops tas2770_dai_ops = {
.digital_mute = tas2770_mute,
.hw_params = tas2770_hw_params,
.set_fmt = tas2770_set_fmt,
.set_tdm_slot = tas2770_set_dai_tdm_slot,
};
#define TAS2770_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
#define TAS2770_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\
SNDRV_PCM_RATE_96000 |\
SNDRV_PCM_RATE_192000\
)
static struct snd_soc_dai_driver tas2770_dai_driver[] = {
{
.name = "tas2770 ASI1",
.id = 0,
.playback = {
.stream_name = "ASI1 Playback",
.channels_min = 2,
.channels_max = 2,
.rates = TAS2770_RATES,
.formats = TAS2770_FORMATS,
},
.capture = {
.stream_name = "ASI1 Capture",
.channels_min = 0,
.channels_max = 2,
.rates = TAS2770_RATES,
.formats = TAS2770_FORMATS,
},
.ops = &tas2770_dai_ops,
.symmetric_rates = 1,
},
};
static int tas2770_codec_probe(struct snd_soc_component *component)
{
struct tas2770_priv *tas2770 =
snd_soc_component_get_drvdata(component);
tas2770->component = component;
return 0;
}
static DECLARE_TLV_DB_SCALE(tas2770_digital_tlv, 1100, 50, 0);
static DECLARE_TLV_DB_SCALE(tas2770_playback_volume, -12750, 50, 0);
static const struct snd_kcontrol_new tas2770_snd_controls[] = {
SOC_SINGLE_TLV("Speaker Playback Volume", TAS2770_PLAY_CFG_REG2,
0, TAS2770_PLAY_CFG_REG2_VMAX, 1,
tas2770_playback_volume),
SOC_SINGLE_TLV("Amp Gain Volume", TAS2770_PLAY_CFG_REG0,
0, 0x14, 0,
tas2770_digital_tlv),
};
static const struct snd_soc_component_driver soc_component_driver_tas2770 = {
.probe = tas2770_codec_probe,
.suspend = tas2770_codec_suspend,
.resume = tas2770_codec_resume,
.set_bias_level = tas2770_set_bias_level,
.controls = tas2770_snd_controls,
.num_controls = ARRAY_SIZE(tas2770_snd_controls),
.dapm_widgets = tas2770_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(tas2770_dapm_widgets),
.dapm_routes = tas2770_audio_map,
.num_dapm_routes = ARRAY_SIZE(tas2770_audio_map),
.idle_bias_on = 1,
.endianness = 1,
.non_legacy_dai_naming = 1,
};
static int tas2770_register_codec(struct tas2770_priv *tas2770)
{
return devm_snd_soc_register_component(tas2770->dev,
&soc_component_driver_tas2770,
tas2770_dai_driver, ARRAY_SIZE(tas2770_dai_driver));
}
static const struct reg_default tas2770_reg_defaults[] = {
{ TAS2770_PAGE, 0x00 },
{ TAS2770_SW_RST, 0x00 },
{ TAS2770_PWR_CTRL, 0x0e },
{ TAS2770_PLAY_CFG_REG0, 0x10 },
{ TAS2770_PLAY_CFG_REG1, 0x01 },
{ TAS2770_PLAY_CFG_REG2, 0x00 },
{ TAS2770_MSC_CFG_REG0, 0x07 },
{ TAS2770_TDM_CFG_REG1, 0x02 },
{ TAS2770_TDM_CFG_REG2, 0x0a },
{ TAS2770_TDM_CFG_REG3, 0x10 },
{ TAS2770_INT_MASK_REG0, 0xfc },
{ TAS2770_INT_MASK_REG1, 0xb1 },
{ TAS2770_INT_CFG, 0x05 },
{ TAS2770_MISC_IRQ, 0x81 },
{ TAS2770_CLK_CGF, 0x0c },
};
static bool tas2770_volatile(struct device *dev, unsigned int reg)
{
switch (reg) {
case TAS2770_PAGE: /* regmap implementation requires this */
case TAS2770_SW_RST: /* always clears after write */
case TAS2770_BO_PRV_REG0:/* has a self clearing bit */
case TAS2770_LVE_INT_REG0:
case TAS2770_LVE_INT_REG1:
case TAS2770_LAT_INT_REG0:/* Sticky interrupt flags */
case TAS2770_LAT_INT_REG1:/* Sticky interrupt flags */
case TAS2770_VBAT_MSB:
case TAS2770_VBAT_LSB:
case TAS2770_TEMP_MSB:
case TAS2770_TEMP_LSB:
return true;
}
return false;
}
static bool tas2770_writeable(struct device *dev, unsigned int reg)
{
switch (reg) {
case TAS2770_LVE_INT_REG0:
case TAS2770_LVE_INT_REG1:
case TAS2770_LAT_INT_REG0:
case TAS2770_LAT_INT_REG1:
case TAS2770_VBAT_MSB:
case TAS2770_VBAT_LSB:
case TAS2770_TEMP_MSB:
case TAS2770_TEMP_LSB:
case TAS2770_TDM_CLK_DETC:
case TAS2770_REV_AND_GPID:
return false;
}
return true;
}
static const struct regmap_range_cfg tas2770_regmap_ranges[] = {
{
.range_min = 0,
.range_max = 1 * 128,
.selector_reg = TAS2770_PAGE,
.selector_mask = 0xff,
.selector_shift = 0,
.window_start = 0,
.window_len = 128,
},
};
static const struct regmap_config tas2770_i2c_regmap = {
.reg_bits = 8,
.val_bits = 8,
.writeable_reg = tas2770_writeable,
.volatile_reg = tas2770_volatile,
.reg_defaults = tas2770_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(tas2770_reg_defaults),
.cache_type = REGCACHE_RBTREE,
.ranges = tas2770_regmap_ranges,
.num_ranges = ARRAY_SIZE(tas2770_regmap_ranges),
.max_register = 1 * 128,
};
static int tas2770_parse_dt(struct device *dev, struct tas2770_priv *tas2770)
{
int rc = 0;
rc = fwnode_property_read_u32(dev->fwnode, "ti,asi-format",
&tas2770->asi_format);
if (rc) {
dev_err(tas2770->dev, "Looking up %s property failed %d\n",
"ti,asi-format", rc);
goto end;
}
rc = fwnode_property_read_u32(dev->fwnode, "ti,imon-slot-no",
&tas2770->i_sense_slot);
if (rc) {
dev_err(tas2770->dev, "Looking up %s property failed %d\n",
"ti,imon-slot-no", rc);
goto end;
}
rc = fwnode_property_read_u32(dev->fwnode, "ti,vmon-slot-no",
&tas2770->v_sense_slot);
if (rc) {
dev_err(tas2770->dev, "Looking up %s property failed %d\n",
"ti,vmon-slot-no", rc);
goto end;
}
end:
return rc;
}
static int tas2770_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct tas2770_priv *tas2770;
int result;
tas2770 = devm_kzalloc(&client->dev,
sizeof(struct tas2770_priv), GFP_KERNEL);
if (!tas2770)
return -ENOMEM;
tas2770->dev = &client->dev;
i2c_set_clientdata(client, tas2770);
dev_set_drvdata(&client->dev, tas2770);
tas2770->power_state = TAS2770_POWER_SHUTDOWN;
tas2770->regmap = devm_regmap_init_i2c(client, &tas2770_i2c_regmap);
if (IS_ERR(tas2770->regmap)) {
result = PTR_ERR(tas2770->regmap);
dev_err(&client->dev, "Failed to allocate register map: %d\n",
result);
goto end;
}
if (client->dev.of_node) {
result = tas2770_parse_dt(&client->dev, tas2770);
if (result) {
dev_err(tas2770->dev, "%s: Failed to parse devicetree\n",
__func__);
goto end;
}
}
tas2770->reset_gpio = devm_gpiod_get_optional(tas2770->dev,
"reset-gpio",
GPIOD_OUT_HIGH);
if (IS_ERR(tas2770->reset_gpio)) {
if (PTR_ERR(tas2770->reset_gpio) == -EPROBE_DEFER) {
tas2770->reset_gpio = NULL;
return -EPROBE_DEFER;
}
}
tas2770->channel_size = 0;
tas2770->slot_width = 0;
tas2770_reset(tas2770);
result = tas2770_register_codec(tas2770);
if (result)
dev_err(tas2770->dev, "Register codec failed.\n");
end:
return result;
}
static int tas2770_i2c_remove(struct i2c_client *client)
{
pm_runtime_disable(&client->dev);
return 0;
}
static const struct i2c_device_id tas2770_i2c_id[] = {
{ "tas2770", 0},
{ }
};
MODULE_DEVICE_TABLE(i2c, tas2770_i2c_id);
#if defined(CONFIG_OF)
static const struct of_device_id tas2770_of_match[] = {
{ .compatible = "ti,tas2770" },
{},
};
MODULE_DEVICE_TABLE(of, tas2770_of_match);
#endif
static struct i2c_driver tas2770_i2c_driver = {
.driver = {
.name = "tas2770",
.of_match_table = of_match_ptr(tas2770_of_match),
},
.probe = tas2770_i2c_probe,
.remove = tas2770_i2c_remove,
.id_table = tas2770_i2c_id,
};
module_i2c_driver(tas2770_i2c_driver);
MODULE_AUTHOR("Shi Fu <shifu0704@thundersoft.com>");
MODULE_DESCRIPTION("TAS2770 I2C Smart Amplifier driver");
MODULE_LICENSE("GPL v2");

143
sound/soc/codecs/tas2770.h Normal file
View File

@ -0,0 +1,143 @@
/* SPDX-License-Identifier: GPL-2.0
*
* ALSA SoC TAS2770 codec driver
*
* Copyright (C) 2016-2017 Texas Instruments Incorporated - http://www.ti.com/
*/
#ifndef __TAS2770__
#define __TAS2770__
/* Book Control Register (available in page0 of each book) */
#define TAS2770_BOOKCTL_PAGE 0
#define TAS2770_BOOKCTL_REG 127
#define TAS2770_REG(page, reg) ((page * 128) + reg)
/* Page */
#define TAS2770_PAGE TAS2770_REG(0X0, 0x00)
#define TAS2770_PAGE_PAGE_MASK 255
/* Software Reset */
#define TAS2770_SW_RST TAS2770_REG(0X0, 0x01)
#define TAS2770_RST BIT(0)
/* Power Control */
#define TAS2770_PWR_CTRL TAS2770_REG(0X0, 0x02)
#define TAS2770_PWR_CTRL_MASK 0x3
#define TAS2770_PWR_CTRL_ACTIVE 0x0
#define TAS2770_PWR_CTRL_MUTE BIT(0)
#define TAS2770_PWR_CTRL_SHUTDOWN 0x2
/* Playback Configuration Reg0 */
#define TAS2770_PLAY_CFG_REG0 TAS2770_REG(0X0, 0x03)
/* Playback Configuration Reg1 */
#define TAS2770_PLAY_CFG_REG1 TAS2770_REG(0X0, 0x04)
/* Playback Configuration Reg2 */
#define TAS2770_PLAY_CFG_REG2 TAS2770_REG(0X0, 0x05)
#define TAS2770_PLAY_CFG_REG2_VMAX 0xc9
/* Misc Configuration Reg0 */
#define TAS2770_MSC_CFG_REG0 TAS2770_REG(0X0, 0x07)
/* TDM Configuration Reg0 */
#define TAS2770_TDM_CFG_REG0 TAS2770_REG(0X0, 0x0A)
#define TAS2770_TDM_CFG_REG0_SMP_MASK BIT(5)
#define TAS2770_TDM_CFG_REG0_SMP_48KHZ 0x0
#define TAS2770_TDM_CFG_REG0_SMP_44_1KHZ BIT(5)
#define TAS2770_TDM_CFG_REG0_31_MASK 0xe
#define TAS2770_TDM_CFG_REG0_31_44_1_48KHZ 0x6
#define TAS2770_TDM_CFG_REG0_31_88_2_96KHZ 0x8
#define TAS2770_TDM_CFG_REG0_31_176_4_192KHZ 0xa
/* TDM Configuration Reg1 */
#define TAS2770_TDM_CFG_REG1 TAS2770_REG(0X0, 0x0B)
#define TAS2770_TDM_CFG_REG1_MASK 0x3e
#define TAS2770_TDM_CFG_REG1_51_SHIFT 1
#define TAS2770_TDM_CFG_REG1_RX_MASK BIT(0)
#define TAS2770_TDM_CFG_REG1_RX_RSING 0x0
#define TAS2770_TDM_CFG_REG1_RX_FALING BIT(0)
/* TDM Configuration Reg2 */
#define TAS2770_TDM_CFG_REG2 TAS2770_REG(0X0, 0x0C)
#define TAS2770_TDM_CFG_REG2_RXW_MASK 0xc
#define TAS2770_TDM_CFG_REG2_RXW_16BITS 0x0
#define TAS2770_TDM_CFG_REG2_RXW_24BITS 0x8
#define TAS2770_TDM_CFG_REG2_RXW_32BITS 0xc
#define TAS2770_TDM_CFG_REG2_RXS_MASK 0x3
#define TAS2770_TDM_CFG_REG2_RXS_16BITS 0x0
#define TAS2770_TDM_CFG_REG2_RXS_24BITS BIT(0)
#define TAS2770_TDM_CFG_REG2_RXS_32BITS 0x2
/* TDM Configuration Reg3 */
#define TAS2770_TDM_CFG_REG3 TAS2770_REG(0X0, 0x0D)
#define TAS2770_TDM_CFG_REG3_RXS_MASK 0xf0
#define TAS2770_TDM_CFG_REG3_RXS_SHIFT 0x4
#define TAS2770_TDM_CFG_REG3_30_MASK 0xf
#define TAS2770_TDM_CFG_REG3_30_SHIFT 0
/* TDM Configuration Reg5 */
#define TAS2770_TDM_CFG_REG5 TAS2770_REG(0X0, 0x0F)
#define TAS2770_TDM_CFG_REG5_VSNS_MASK BIT(6)
#define TAS2770_TDM_CFG_REG5_VSNS_ENABLE BIT(6)
#define TAS2770_TDM_CFG_REG5_50_MASK 0x3f
/* TDM Configuration Reg6 */
#define TAS2770_TDM_CFG_REG6 TAS2770_REG(0X0, 0x10)
#define TAS2770_TDM_CFG_REG6_ISNS_MASK BIT(6)
#define TAS2770_TDM_CFG_REG6_ISNS_ENABLE BIT(6)
#define TAS2770_TDM_CFG_REG6_50_MASK 0x3f
/* Brown Out Prevention Reg0 */
#define TAS2770_BO_PRV_REG0 TAS2770_REG(0X0, 0x1B)
/* Interrupt MASK Reg0 */
#define TAS2770_INT_MASK_REG0 TAS2770_REG(0X0, 0x20)
#define TAS2770_INT_REG0_DEFAULT 0xfc
#define TAS2770_INT_MASK_REG0_DISABLE 0xff
/* Interrupt MASK Reg1 */
#define TAS2770_INT_MASK_REG1 TAS2770_REG(0X0, 0x21)
#define TAS2770_INT_REG1_DEFAULT 0xb1
#define TAS2770_INT_MASK_REG1_DISABLE 0xff
/* Live-Interrupt Reg0 */
#define TAS2770_LVE_INT_REG0 TAS2770_REG(0X0, 0x22)
/* Live-Interrupt Reg1 */
#define TAS2770_LVE_INT_REG1 TAS2770_REG(0X0, 0x23)
/* Latched-Interrupt Reg0 */
#define TAS2770_LAT_INT_REG0 TAS2770_REG(0X0, 0x24)
#define TAS2770_LAT_INT_REG0_OCE_FLG BIT(1)
#define TAS2770_LAT_INT_REG0_OTE_FLG BIT(0)
/* Latched-Interrupt Reg1 */
#define TAS2770_LAT_INT_REG1 TAS2770_REG(0X0, 0x25)
#define TAS2770_LAT_INT_REG1_VBA_TOV BIT(3)
#define TAS2770_LAT_INT_REG1_VBA_TUV BIT(2)
#define TAS2770_LAT_INT_REG1_BOUT_FLG BIT(1)
/* VBAT MSB */
#define TAS2770_VBAT_MSB TAS2770_REG(0X0, 0x27)
/* VBAT LSB */
#define TAS2770_VBAT_LSB TAS2770_REG(0X0, 0x28)
/* TEMP MSB */
#define TAS2770_TEMP_MSB TAS2770_REG(0X0, 0x29)
/* TEMP LSB */
#define TAS2770_TEMP_LSB TAS2770_REG(0X0, 0x2A)
/* Interrupt Configuration */
#define TAS2770_INT_CFG TAS2770_REG(0X0, 0x30)
/* Misc IRQ */
#define TAS2770_MISC_IRQ TAS2770_REG(0X0, 0x32)
/* Clock Configuration */
#define TAS2770_CLK_CGF TAS2770_REG(0X0, 0x3C)
/* TDM Clock detection monitor */
#define TAS2770_TDM_CLK_DETC TAS2770_REG(0X0, 0x77)
/* Revision and PG ID */
#define TAS2770_REV_AND_GPID TAS2770_REG(0X0, 0x7D)
#define TAS2770_POWER_ACTIVE 0
#define TAS2770_POWER_MUTE 1
#define TAS2770_POWER_SHUTDOWN 2
#define ERROR_OVER_CURRENT 0x0000001
#define ERROR_DIE_OVERTEMP 0x0000002
#define ERROR_OVER_VOLTAGE 0x0000004
#define ERROR_UNDER_VOLTAGE 0x0000008
#define ERROR_BROWNOUT 0x0000010
#define ERROR_CLASSD_PWR 0x0000020
struct tas2770_priv {
struct device *dev;
struct regmap *regmap;
struct snd_soc_component *component;
int power_state;
int asi_format;
struct gpio_desc *reset_gpio;
int sampling_rate;
int channel_size;
int slot_width;
int v_sense_slot;
int i_sense_slot;
};
#endif /* __TAS2770__ */

View File

@ -2837,11 +2837,11 @@ static int wcd9335_codec_enable_dec(struct snd_soc_dapm_widget *w,
TX_HPF_CUT_OFF_FREQ_MASK) >> 5;
snd_soc_component_update_bits(comp, tx_vol_ctl_reg, 0x10, 0x10);
snd_soc_component_update_bits(comp, dec_cfg_reg, 0x08, 0x00);
if (hpf_coff_freq != CF_MIN_3DB_150HZ) {
snd_soc_component_update_bits(comp, dec_cfg_reg,
TX_HPF_CUT_OFF_FREQ_MASK,
hpf_coff_freq << 5);
}
if (hpf_coff_freq != CF_MIN_3DB_150HZ) {
snd_soc_component_update_bits(comp, dec_cfg_reg,
TX_HPF_CUT_OFF_FREQ_MASK,
hpf_coff_freq << 5);
}
break;
case SND_SOC_DAPM_POST_PMD:
snd_soc_component_update_bits(comp, tx_vol_ctl_reg, 0x10, 0x00);

View File

@ -25,6 +25,8 @@
#include <linux/mfd/wm8994/pdata.h>
#include <linux/mfd/wm8994/gpio.h>
#include <asm/unaligned.h>
#include "wm8994.h"
#define WM_FW_BLOCK_INFO 0xff
@ -58,18 +60,15 @@ static int wm8958_dsp2_fw(struct snd_soc_component *component, const char *name,
}
if (memcmp(fw->data, "WMFW", 4) != 0) {
memcpy(&data32, fw->data, sizeof(data32));
data32 = be32_to_cpu(data32);
data32 = get_unaligned_be32(fw->data);
dev_err(component->dev, "%s: firmware has bad file magic %08x\n",
name, data32);
goto err;
}
memcpy(&data32, fw->data + 4, sizeof(data32));
len = be32_to_cpu(data32);
len = get_unaligned_be32(fw->data + 4);
data32 = get_unaligned_be32(fw->data + 8);
memcpy(&data32, fw->data + 8, sizeof(data32));
data32 = be32_to_cpu(data32);
if ((data32 >> 24) & 0xff) {
dev_err(component->dev, "%s: unsupported firmware version %d\n",
name, (data32 >> 24) & 0xff);
@ -87,9 +86,8 @@ static int wm8958_dsp2_fw(struct snd_soc_component *component, const char *name,
}
if (check) {
memcpy(&data64, fw->data + 24, sizeof(u64));
dev_info(component->dev, "%s timestamp %llx\n",
name, be64_to_cpu(data64));
data64 = get_unaligned_be64(fw->data + 24);
dev_info(component->dev, "%s timestamp %llx\n", name, data64);
} else {
snd_soc_component_write(component, 0x102, 0x2);
snd_soc_component_write(component, 0x900, 0x2);
@ -104,8 +102,7 @@ static int wm8958_dsp2_fw(struct snd_soc_component *component, const char *name,
goto err;
}
memcpy(&data32, data + 4, sizeof(data32));
block_len = be32_to_cpu(data32);
block_len = get_unaligned_be32(data + 4);
if (block_len + 8 > len) {
dev_err(component->dev, "%zd byte block longer than file\n",
block_len);
@ -116,8 +113,7 @@ static int wm8958_dsp2_fw(struct snd_soc_component *component, const char *name,
goto err;
}
memcpy(&data32, data, sizeof(data32));
data32 = be32_to_cpu(data32);
data32 = get_unaligned_be32(data);
switch ((data32 >> 24) & 0xff) {
case WM_FW_BLOCK_INFO:

View File

@ -167,12 +167,12 @@ static int configure_aif_clock(struct snd_soc_component *component, int aif)
switch (wm8994->sysclk[aif]) {
case WM8994_SYSCLK_MCLK1:
rate = wm8994->mclk[0];
rate = wm8994->mclk_rate[0];
break;
case WM8994_SYSCLK_MCLK2:
reg1 |= 0x8;
rate = wm8994->mclk[1];
rate = wm8994->mclk_rate[1];
break;
case WM8994_SYSCLK_FLL1:
@ -1038,6 +1038,45 @@ static bool wm8994_check_class_w_digital(struct snd_soc_component *component)
return true;
}
static int aif_mclk_set(struct snd_soc_component *component, int aif, bool enable)
{
struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
unsigned int offset, val, clk_idx;
int ret;
if (aif)
offset = 4;
else
offset = 0;
val = snd_soc_component_read32(component, WM8994_AIF1_CLOCKING_1 + offset);
val &= WM8994_AIF1CLK_SRC_MASK;
switch (val) {
case 0:
clk_idx = WM8994_MCLK1;
break;
case 1:
clk_idx = WM8994_MCLK2;
break;
default:
return 0;
}
if (enable) {
ret = clk_prepare_enable(wm8994->mclk[clk_idx].clk);
if (ret < 0) {
dev_err(component->dev, "Failed to enable MCLK%d\n",
clk_idx);
return ret;
}
} else {
clk_disable_unprepare(wm8994->mclk[clk_idx].clk);
}
return 0;
}
static int aif1clk_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
@ -1045,7 +1084,7 @@ static int aif1clk_ev(struct snd_soc_dapm_widget *w,
struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
struct wm8994 *control = wm8994->wm8994;
int mask = WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC1R_ENA;
int i;
int ret, i;
int dac;
int adc;
int val;
@ -1061,6 +1100,10 @@ static int aif1clk_ev(struct snd_soc_dapm_widget *w,
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
ret = aif_mclk_set(component, 0, true);
if (ret < 0)
return ret;
/* Don't enable timeslot 2 if not in use */
if (wm8994->channels[0] <= 2)
mask &= ~(WM8994_AIF1DAC2L_ENA | WM8994_AIF1DAC2R_ENA);
@ -1133,6 +1176,12 @@ static int aif1clk_ev(struct snd_soc_dapm_widget *w,
break;
}
switch (event) {
case SND_SOC_DAPM_POST_PMD:
aif_mclk_set(component, 0, false);
break;
}
return 0;
}
@ -1140,13 +1189,17 @@ static int aif2clk_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
int i;
int ret, i;
int dac;
int adc;
int val;
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
ret = aif_mclk_set(component, 1, true);
if (ret < 0)
return ret;
val = snd_soc_component_read32(component, WM8994_AIF2_CONTROL_1);
if ((val & WM8994_AIF2ADCL_SRC) &&
(val & WM8994_AIF2ADCR_SRC))
@ -1218,6 +1271,12 @@ static int aif2clk_ev(struct snd_soc_dapm_widget *w,
break;
}
switch (event) {
case SND_SOC_DAPM_POST_PMD:
aif_mclk_set(component, 1, false);
break;
}
return 0;
}
@ -1623,10 +1682,10 @@ SND_SOC_DAPM_POST("Late Disable PGA", late_disable_ev)
static const struct snd_soc_dapm_widget wm8994_lateclk_widgets[] = {
SND_SOC_DAPM_SUPPLY("AIF1CLK", WM8994_AIF1_CLOCKING_1, 0, 0, aif1clk_ev,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
SND_SOC_DAPM_PRE_PMD),
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_SUPPLY("AIF2CLK", WM8994_AIF2_CLOCKING_1, 0, 0, aif2clk_ev,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
SND_SOC_DAPM_PRE_PMD),
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_PGA("Direct Voice", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("SPKL", WM8994_POWER_MANAGEMENT_3, 8, 0,
left_speaker_mixer, ARRAY_SIZE(left_speaker_mixer)),
@ -2141,6 +2200,7 @@ static int _wm8994_set_fll(struct snd_soc_component *component, int id, int src,
u16 reg, clk1, aif_reg, aif_src;
unsigned long timeout;
bool was_enabled;
struct clk *mclk;
switch (id) {
case WM8994_FLL1:
@ -2216,6 +2276,27 @@ static int _wm8994_set_fll(struct snd_soc_component *component, int id, int src,
snd_soc_component_update_bits(component, WM8994_FLL1_CONTROL_1 + reg_offset,
WM8994_FLL1_ENA, 0);
/* Disable MCLK if needed before we possibly change to new clock parent */
if (was_enabled) {
reg = snd_soc_component_read32(component, WM8994_FLL1_CONTROL_5
+ reg_offset);
reg = ((reg & WM8994_FLL1_REFCLK_SRC_MASK)
>> WM8994_FLL1_REFCLK_SRC_SHIFT) + 1;
switch (reg) {
case WM8994_FLL_SRC_MCLK1:
mclk = wm8994->mclk[WM8994_MCLK1].clk;
break;
case WM8994_FLL_SRC_MCLK2:
mclk = wm8994->mclk[WM8994_MCLK2].clk;
break;
default:
mclk = NULL;
}
clk_disable_unprepare(mclk);
}
if (wm8994->fll_byp && src == WM8994_FLL_SRC_BCLK &&
freq_in == freq_out && freq_out) {
dev_dbg(component->dev, "Bypassing FLL%d\n", id + 1);
@ -2260,10 +2341,29 @@ static int _wm8994_set_fll(struct snd_soc_component *component, int id, int src,
/* Clear any pending completion from a previous failure */
try_wait_for_completion(&wm8994->fll_locked[id]);
switch (src) {
case WM8994_FLL_SRC_MCLK1:
mclk = wm8994->mclk[WM8994_MCLK1].clk;
break;
case WM8994_FLL_SRC_MCLK2:
mclk = wm8994->mclk[WM8994_MCLK2].clk;
break;
default:
mclk = NULL;
}
/* Enable (with fractional mode if required) */
if (freq_out) {
ret = clk_prepare_enable(mclk);
if (ret < 0) {
dev_err(component->dev, "Failed to enable MCLK for FLL%d\n",
id + 1);
return ret;
}
/* Enable VMID if we need it */
if (!was_enabled) {
active_reference(component);
switch (control->type) {
@ -2372,12 +2472,29 @@ static int wm8994_set_fll(struct snd_soc_dai *dai, int id, int src,
return _wm8994_set_fll(dai->component, id, src, freq_in, freq_out);
}
static int wm8994_set_mclk_rate(struct wm8994_priv *wm8994, unsigned int id,
unsigned int *freq)
{
int ret;
if (!wm8994->mclk[id].clk || *freq == wm8994->mclk_rate[id])
return 0;
ret = clk_set_rate(wm8994->mclk[id].clk, *freq);
if (ret < 0)
return ret;
*freq = clk_get_rate(wm8994->mclk[id].clk);
return 0;
}
static int wm8994_set_dai_sysclk(struct snd_soc_dai *dai,
int clk_id, unsigned int freq, int dir)
{
struct snd_soc_component *component = dai->component;
struct wm8994_priv *wm8994 = snd_soc_component_get_drvdata(component);
int i;
int ret, i;
switch (dai->id) {
case 1:
@ -2392,7 +2509,12 @@ static int wm8994_set_dai_sysclk(struct snd_soc_dai *dai,
switch (clk_id) {
case WM8994_SYSCLK_MCLK1:
wm8994->sysclk[dai->id - 1] = WM8994_SYSCLK_MCLK1;
wm8994->mclk[0] = freq;
ret = wm8994_set_mclk_rate(wm8994, dai->id - 1, &freq);
if (ret < 0)
return ret;
wm8994->mclk_rate[0] = freq;
dev_dbg(dai->dev, "AIF%d using MCLK1 at %uHz\n",
dai->id, freq);
break;
@ -2400,7 +2522,12 @@ static int wm8994_set_dai_sysclk(struct snd_soc_dai *dai,
case WM8994_SYSCLK_MCLK2:
/* TODO: Set GPIO AF */
wm8994->sysclk[dai->id - 1] = WM8994_SYSCLK_MCLK2;
wm8994->mclk[1] = freq;
ret = wm8994_set_mclk_rate(wm8994, dai->id - 1, &freq);
if (ret < 0)
return ret;
wm8994->mclk_rate[1] = freq;
dev_dbg(dai->dev, "AIF%d using MCLK2 at %uHz\n",
dai->id, freq);
break;
@ -4456,6 +4583,7 @@ static const struct snd_soc_component_driver soc_component_dev_wm8994 = {
static int wm8994_probe(struct platform_device *pdev)
{
struct wm8994_priv *wm8994;
int ret;
wm8994 = devm_kzalloc(&pdev->dev, sizeof(struct wm8994_priv),
GFP_KERNEL);
@ -4467,6 +4595,16 @@ static int wm8994_probe(struct platform_device *pdev)
wm8994->wm8994 = dev_get_drvdata(pdev->dev.parent);
wm8994->mclk[WM8994_MCLK1].id = "MCLK1";
wm8994->mclk[WM8994_MCLK2].id = "MCLK2";
ret = devm_clk_bulk_get_optional(pdev->dev.parent, ARRAY_SIZE(wm8994->mclk),
wm8994->mclk);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to get clocks: %d\n", ret);
return ret;
}
pm_runtime_enable(&pdev->dev);
pm_runtime_idle(&pdev->dev);

View File

@ -6,6 +6,7 @@
#ifndef _WM8994_H
#define _WM8994_H
#include <linux/clk.h>
#include <sound/soc.h>
#include <linux/firmware.h>
#include <linux/completion.h>
@ -14,6 +15,12 @@
#include "wm_hubs.h"
enum {
WM8994_MCLK1,
WM8994_MCLK2,
WM8994_NUM_MCLK
};
/* Sources for AIF1/2 SYSCLK - use with set_dai_sysclk() */
#define WM8994_SYSCLK_MCLK1 1
#define WM8994_SYSCLK_MCLK2 2
@ -73,9 +80,10 @@ struct wm8994;
struct wm8994_priv {
struct wm_hubs_data hubs;
struct wm8994 *wm8994;
struct clk_bulk_data mclk[WM8994_NUM_MCLK];
int sysclk[2];
int sysclk_rate[2];
int mclk[2];
int mclk_rate[2];
int aifclk[2];
int aifdiv[2];
int channels[2];

View File

@ -135,7 +135,8 @@ void dw_pcm_pop_rx(struct dw_i2s_dev *dev)
dw_pcm_transfer(dev, false);
}
static int dw_pcm_open(struct snd_pcm_substream *substream)
static int dw_pcm_open(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
@ -148,14 +149,16 @@ static int dw_pcm_open(struct snd_pcm_substream *substream)
return 0;
}
static int dw_pcm_close(struct snd_pcm_substream *substream)
static int dw_pcm_close(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
synchronize_rcu();
return 0;
}
static int dw_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *hw_params)
static int dw_pcm_hw_params(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *hw_params)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct dw_i2s_dev *dev = runtime->private_data;
@ -192,12 +195,14 @@ static int dw_pcm_hw_params(struct snd_pcm_substream *substream,
return 0;
}
static int dw_pcm_hw_free(struct snd_pcm_substream *substream)
static int dw_pcm_hw_free(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
return snd_pcm_lib_free_pages(substream);
}
static int dw_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
static int dw_pcm_trigger(struct snd_soc_component *component,
struct snd_pcm_substream *substream, int cmd)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct dw_i2s_dev *dev = runtime->private_data;
@ -231,7 +236,8 @@ static int dw_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
return ret;
}
static snd_pcm_uframes_t dw_pcm_pointer(struct snd_pcm_substream *substream)
static snd_pcm_uframes_t dw_pcm_pointer(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct dw_i2s_dev *dev = runtime->private_data;
@ -245,7 +251,8 @@ static snd_pcm_uframes_t dw_pcm_pointer(struct snd_pcm_substream *substream)
return pos < runtime->buffer_size ? pos : 0;
}
static int dw_pcm_new(struct snd_soc_pcm_runtime *rtd)
static int dw_pcm_new(struct snd_soc_component *component,
struct snd_soc_pcm_runtime *rtd)
{
size_t size = dw_pcm_hardware.buffer_bytes_max;
@ -255,25 +262,22 @@ static int dw_pcm_new(struct snd_soc_pcm_runtime *rtd)
return 0;
}
static void dw_pcm_free(struct snd_pcm *pcm)
static void dw_pcm_free(struct snd_soc_component *component,
struct snd_pcm *pcm)
{
snd_pcm_lib_preallocate_free_for_all(pcm);
}
static const struct snd_pcm_ops dw_pcm_ops = {
.open = dw_pcm_open,
.close = dw_pcm_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = dw_pcm_hw_params,
.hw_free = dw_pcm_hw_free,
.trigger = dw_pcm_trigger,
.pointer = dw_pcm_pointer,
};
static const struct snd_soc_component_driver dw_pcm_component = {
.pcm_new = dw_pcm_new,
.pcm_free = dw_pcm_free,
.ops = &dw_pcm_ops,
.open = dw_pcm_open,
.close = dw_pcm_close,
.ioctl = snd_soc_pcm_lib_ioctl,
.hw_params = dw_pcm_hw_params,
.hw_free = dw_pcm_hw_free,
.trigger = dw_pcm_trigger,
.pointer = dw_pcm_pointer,
.pcm_construct = dw_pcm_new,
.pcm_destruct = dw_pcm_free,
};
int dw_pcm_register(struct platform_device *pdev)

View File

@ -25,6 +25,16 @@ config SND_SOC_FSL_SAI
This option is only useful for out-of-tree drivers since
in-tree drivers select it automatically.
config SND_SOC_FSL_MQS
tristate "Medium Quality Sound (MQS) module support"
depends on SND_SOC_FSL_SAI
select REGMAP_MMIO
help
Say Y if you want to add Medium Quality Sound (MQS)
support for the Freescale CPUs.
This option is only useful for out-of-tree drivers since
in-tree drivers select it automatically.
config SND_SOC_FSL_AUDMIX
tristate "Audio Mixer (AUDMIX) module support"
select REGMAP_MMIO

View File

@ -23,6 +23,7 @@ snd-soc-fsl-esai-objs := fsl_esai.o
snd-soc-fsl-micfil-objs := fsl_micfil.o
snd-soc-fsl-utils-objs := fsl_utils.o
snd-soc-fsl-dma-objs := fsl_dma.o
snd-soc-fsl-mqs-objs := fsl_mqs.o
obj-$(CONFIG_SND_SOC_FSL_AUDMIX) += snd-soc-fsl-audmix.o
obj-$(CONFIG_SND_SOC_FSL_ASOC_CARD) += snd-soc-fsl-asoc-card.o
@ -33,6 +34,7 @@ obj-$(CONFIG_SND_SOC_FSL_SPDIF) += snd-soc-fsl-spdif.o
obj-$(CONFIG_SND_SOC_FSL_ESAI) += snd-soc-fsl-esai.o
obj-$(CONFIG_SND_SOC_FSL_MICFIL) += snd-soc-fsl-micfil.o
obj-$(CONFIG_SND_SOC_FSL_UTILS) += snd-soc-fsl-utils.o
obj-$(CONFIG_SND_SOC_FSL_MQS) += snd-soc-fsl-mqs.o
obj-$(CONFIG_SND_SOC_POWERPC_DMA) += snd-soc-fsl-dma.o
# MPC5200 Platform Support

View File

@ -115,7 +115,7 @@ static void fsl_asrc_sel_proc(int inrate, int outrate,
* within range [ANCA, ANCA+ANCB-1], depends on the channels of pair A
* while pair A and pair C are comparatively independent.
*/
static int fsl_asrc_request_pair(int channels, struct fsl_asrc_pair *pair)
int fsl_asrc_request_pair(int channels, struct fsl_asrc_pair *pair)
{
enum asrc_pair_index index = ASRC_INVALID_PAIR;
struct fsl_asrc *asrc_priv = pair->asrc_priv;
@ -158,7 +158,7 @@ static int fsl_asrc_request_pair(int channels, struct fsl_asrc_pair *pair)
*
* It clears the resource from asrc_priv and releases the occupied channels.
*/
static void fsl_asrc_release_pair(struct fsl_asrc_pair *pair)
void fsl_asrc_release_pair(struct fsl_asrc_pair *pair)
{
struct fsl_asrc *asrc_priv = pair->asrc_priv;
enum asrc_pair_index index = pair->index;
@ -265,6 +265,8 @@ static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair)
struct asrc_config *config = pair->config;
struct fsl_asrc *asrc_priv = pair->asrc_priv;
enum asrc_pair_index index = pair->index;
enum asrc_word_width input_word_width;
enum asrc_word_width output_word_width;
u32 inrate, outrate, indiv, outdiv;
u32 clk_index[2], div[2];
int in, out, channels;
@ -283,9 +285,32 @@ static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair)
return -EINVAL;
}
/* Validate output width */
if (config->output_word_width == ASRC_WIDTH_8_BIT) {
pair_err("does not support 8bit width output\n");
switch (snd_pcm_format_width(config->input_format)) {
case 8:
input_word_width = ASRC_WIDTH_8_BIT;
break;
case 16:
input_word_width = ASRC_WIDTH_16_BIT;
break;
case 24:
input_word_width = ASRC_WIDTH_24_BIT;
break;
default:
pair_err("does not support this input format, %d\n",
config->input_format);
return -EINVAL;
}
switch (snd_pcm_format_width(config->output_format)) {
case 16:
output_word_width = ASRC_WIDTH_16_BIT;
break;
case 24:
output_word_width = ASRC_WIDTH_24_BIT;
break;
default:
pair_err("does not support this output format, %d\n",
config->output_format);
return -EINVAL;
}
@ -383,8 +408,8 @@ static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair)
/* Implement word_width configurations */
regmap_update_bits(asrc_priv->regmap, REG_ASRMCR1(index),
ASRMCR1i_OW16_MASK | ASRMCR1i_IWD_MASK,
ASRMCR1i_OW16(config->output_word_width) |
ASRMCR1i_IWD(config->input_word_width));
ASRMCR1i_OW16(output_word_width) |
ASRMCR1i_IWD(input_word_width));
/* Enable BUFFER STALL */
regmap_update_bits(asrc_priv->regmap, REG_ASRMCR(index),
@ -497,13 +522,13 @@ static int fsl_asrc_dai_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct fsl_asrc *asrc_priv = snd_soc_dai_get_drvdata(dai);
int width = params_width(params);
struct snd_pcm_runtime *runtime = substream->runtime;
struct fsl_asrc_pair *pair = runtime->private_data;
unsigned int channels = params_channels(params);
unsigned int rate = params_rate(params);
struct asrc_config config;
int word_width, ret;
snd_pcm_format_t format;
int ret;
ret = fsl_asrc_request_pair(channels, pair);
if (ret) {
@ -513,15 +538,10 @@ static int fsl_asrc_dai_hw_params(struct snd_pcm_substream *substream,
pair->config = &config;
if (width == 16)
width = ASRC_WIDTH_16_BIT;
else
width = ASRC_WIDTH_24_BIT;
if (asrc_priv->asrc_width == 16)
word_width = ASRC_WIDTH_16_BIT;
format = SNDRV_PCM_FORMAT_S16_LE;
else
word_width = ASRC_WIDTH_24_BIT;
format = SNDRV_PCM_FORMAT_S24_LE;
config.pair = pair->index;
config.channel_num = channels;
@ -529,13 +549,13 @@ static int fsl_asrc_dai_hw_params(struct snd_pcm_substream *substream,
config.outclk = OUTCLK_ASRCK1_CLK;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
config.input_word_width = width;
config.output_word_width = word_width;
config.input_format = params_format(params);
config.output_format = format;
config.input_sample_rate = rate;
config.output_sample_rate = asrc_priv->asrc_rate;
} else {
config.input_word_width = word_width;
config.output_word_width = width;
config.input_format = format;
config.output_format = params_format(params);
config.input_sample_rate = asrc_priv->asrc_rate;
config.output_sample_rate = rate;
}
@ -604,7 +624,7 @@ static int fsl_asrc_dai_probe(struct snd_soc_dai *dai)
#define FSL_ASRC_FORMATS (SNDRV_PCM_FMTBIT_S24_LE | \
SNDRV_PCM_FMTBIT_S16_LE | \
SNDRV_PCM_FMTBIT_S20_3LE)
SNDRV_PCM_FMTBIT_S24_3LE)
static struct snd_soc_dai_driver fsl_asrc_dai = {
.probe = fsl_asrc_dai_probe,
@ -615,7 +635,8 @@ static struct snd_soc_dai_driver fsl_asrc_dai = {
.rate_min = 5512,
.rate_max = 192000,
.rates = SNDRV_PCM_RATE_KNOT,
.formats = FSL_ASRC_FORMATS,
.formats = FSL_ASRC_FORMATS |
SNDRV_PCM_FMTBIT_S8,
},
.capture = {
.stream_name = "ASRC-Capture",

View File

@ -342,8 +342,8 @@ struct asrc_config {
unsigned int dma_buffer_size;
unsigned int input_sample_rate;
unsigned int output_sample_rate;
enum asrc_word_width input_word_width;
enum asrc_word_width output_word_width;
snd_pcm_format_t input_format;
snd_pcm_format_t output_format;
enum asrc_inclk inclk;
enum asrc_outclk outclk;
};
@ -462,4 +462,7 @@ struct fsl_asrc {
#define DRV_NAME "fsl-asrc-dai"
extern struct snd_soc_component_driver fsl_asrc_component;
struct dma_chan *fsl_asrc_get_dma_channel(struct fsl_asrc_pair *pair, bool dir);
int fsl_asrc_request_pair(int channels, struct fsl_asrc_pair *pair);
void fsl_asrc_release_pair(struct fsl_asrc_pair *pair);
#endif /* _FSL_ASRC_H */

View File

@ -16,13 +16,11 @@
#define FSL_ASRC_DMABUF_SIZE (256 * 1024)
static const struct snd_pcm_hardware snd_imx_hardware = {
static struct snd_pcm_hardware snd_imx_hardware = {
.info = SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID |
SNDRV_PCM_INFO_PAUSE |
SNDRV_PCM_INFO_RESUME,
SNDRV_PCM_INFO_MMAP_VALID,
.buffer_bytes_max = FSL_ASRC_DMABUF_SIZE,
.period_bytes_min = 128,
.period_bytes_max = 65535, /* Limited by SDMA engine */
@ -54,13 +52,12 @@ static void fsl_asrc_dma_complete(void *arg)
snd_pcm_period_elapsed(substream);
}
static int fsl_asrc_dma_prepare_and_submit(struct snd_pcm_substream *substream)
static int fsl_asrc_dma_prepare_and_submit(struct snd_pcm_substream *substream,
struct snd_soc_component *component)
{
u8 dir = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? OUT : IN;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_pcm_runtime *runtime = substream->runtime;
struct fsl_asrc_pair *pair = runtime->private_data;
struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
struct device *dev = component->dev;
unsigned long flags = DMA_CTRL_ACK;
@ -97,7 +94,8 @@ static int fsl_asrc_dma_prepare_and_submit(struct snd_pcm_substream *substream)
return 0;
}
static int fsl_asrc_dma_trigger(struct snd_pcm_substream *substream, int cmd)
static int fsl_asrc_dma_trigger(struct snd_soc_component *component,
struct snd_pcm_substream *substream, int cmd)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct fsl_asrc_pair *pair = runtime->private_data;
@ -107,7 +105,7 @@ static int fsl_asrc_dma_trigger(struct snd_pcm_substream *substream, int cmd)
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
ret = fsl_asrc_dma_prepare_and_submit(substream);
ret = fsl_asrc_dma_prepare_and_submit(substream, component);
if (ret)
return ret;
dma_async_issue_pending(pair->dma_chan[IN]);
@ -126,7 +124,8 @@ static int fsl_asrc_dma_trigger(struct snd_pcm_substream *substream, int cmd)
return 0;
}
static int fsl_asrc_dma_hw_params(struct snd_pcm_substream *substream,
static int fsl_asrc_dma_hw_params(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
enum dma_slave_buswidth buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES;
@ -134,7 +133,6 @@ static int fsl_asrc_dma_hw_params(struct snd_pcm_substream *substream,
bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
struct snd_dmaengine_dai_dma_data *dma_params_fe = NULL;
struct snd_dmaengine_dai_dma_data *dma_params_be = NULL;
struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
struct snd_pcm_runtime *runtime = substream->runtime;
struct fsl_asrc_pair *pair = runtime->private_data;
struct fsl_asrc *asrc_priv = pair->asrc_priv;
@ -249,7 +247,8 @@ static int fsl_asrc_dma_hw_params(struct snd_pcm_substream *substream,
return 0;
}
static int fsl_asrc_dma_hw_free(struct snd_pcm_substream *substream)
static int fsl_asrc_dma_hw_free(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct fsl_asrc_pair *pair = runtime->private_data;
@ -268,14 +267,27 @@ static int fsl_asrc_dma_hw_free(struct snd_pcm_substream *substream)
return 0;
}
static int fsl_asrc_dma_startup(struct snd_pcm_substream *substream)
static int fsl_asrc_dma_startup(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
struct snd_dmaengine_dai_dma_data *dma_data;
struct device *dev = component->dev;
struct fsl_asrc *asrc_priv = dev_get_drvdata(dev);
struct fsl_asrc_pair *pair;
struct dma_chan *tmp_chan = NULL;
u8 dir = tx ? OUT : IN;
bool release_pair = true;
int ret = 0;
ret = snd_pcm_hw_constraint_integer(substream->runtime,
SNDRV_PCM_HW_PARAM_PERIODS);
if (ret < 0) {
dev_err(dev, "failed to set pcm hw params periods\n");
return ret;
}
pair = kzalloc(sizeof(struct fsl_asrc_pair), GFP_KERNEL);
if (!pair)
@ -285,14 +297,54 @@ static int fsl_asrc_dma_startup(struct snd_pcm_substream *substream)
runtime->private_data = pair;
snd_pcm_hw_constraint_integer(substream->runtime,
SNDRV_PCM_HW_PARAM_PERIODS);
/* Request a dummy pair, which will be released later.
* Request pair function needs channel num as input, for this
* dummy pair, we just request "1" channel temporarily.
*/
ret = fsl_asrc_request_pair(1, pair);
if (ret < 0) {
dev_err(dev, "failed to request asrc pair\n");
goto req_pair_err;
}
/* Request a dummy dma channel, which will be released later. */
tmp_chan = fsl_asrc_get_dma_channel(pair, dir);
if (!tmp_chan) {
dev_err(dev, "failed to get dma channel\n");
ret = -EINVAL;
goto dma_chan_err;
}
dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
/* Refine the snd_imx_hardware according to caps of DMA. */
ret = snd_dmaengine_pcm_refine_runtime_hwparams(substream,
dma_data,
&snd_imx_hardware,
tmp_chan);
if (ret < 0) {
dev_err(dev, "failed to refine runtime hwparams\n");
goto out;
}
release_pair = false;
snd_soc_set_runtime_hwparams(substream, &snd_imx_hardware);
return 0;
out:
dma_release_channel(tmp_chan);
dma_chan_err:
fsl_asrc_release_pair(pair);
req_pair_err:
if (release_pair)
kfree(pair);
return ret;
}
static int fsl_asrc_dma_shutdown(struct snd_pcm_substream *substream)
static int fsl_asrc_dma_shutdown(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct fsl_asrc_pair *pair = runtime->private_data;
@ -311,7 +363,9 @@ static int fsl_asrc_dma_shutdown(struct snd_pcm_substream *substream)
return 0;
}
static snd_pcm_uframes_t fsl_asrc_dma_pcm_pointer(struct snd_pcm_substream *substream)
static snd_pcm_uframes_t
fsl_asrc_dma_pcm_pointer(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct fsl_asrc_pair *pair = runtime->private_data;
@ -319,17 +373,8 @@ static snd_pcm_uframes_t fsl_asrc_dma_pcm_pointer(struct snd_pcm_substream *subs
return bytes_to_frames(substream->runtime, pair->pos);
}
static const struct snd_pcm_ops fsl_asrc_dma_pcm_ops = {
.ioctl = snd_pcm_lib_ioctl,
.hw_params = fsl_asrc_dma_hw_params,
.hw_free = fsl_asrc_dma_hw_free,
.trigger = fsl_asrc_dma_trigger,
.open = fsl_asrc_dma_startup,
.close = fsl_asrc_dma_shutdown,
.pointer = fsl_asrc_dma_pcm_pointer,
};
static int fsl_asrc_dma_pcm_new(struct snd_soc_pcm_runtime *rtd)
static int fsl_asrc_dma_pcm_new(struct snd_soc_component *component,
struct snd_soc_pcm_runtime *rtd)
{
struct snd_card *card = rtd->card->snd_card;
struct snd_pcm_substream *substream;
@ -364,7 +409,8 @@ static int fsl_asrc_dma_pcm_new(struct snd_soc_pcm_runtime *rtd)
return ret;
}
static void fsl_asrc_dma_pcm_free(struct snd_pcm *pcm)
static void fsl_asrc_dma_pcm_free(struct snd_soc_component *component,
struct snd_pcm *pcm)
{
struct snd_pcm_substream *substream;
int i;
@ -382,8 +428,14 @@ static void fsl_asrc_dma_pcm_free(struct snd_pcm *pcm)
struct snd_soc_component_driver fsl_asrc_component = {
.name = DRV_NAME,
.ops = &fsl_asrc_dma_pcm_ops,
.pcm_new = fsl_asrc_dma_pcm_new,
.pcm_free = fsl_asrc_dma_pcm_free,
.ioctl = snd_soc_pcm_lib_ioctl,
.hw_params = fsl_asrc_dma_hw_params,
.hw_free = fsl_asrc_dma_hw_free,
.trigger = fsl_asrc_dma_trigger,
.open = fsl_asrc_dma_startup,
.close = fsl_asrc_dma_shutdown,
.pointer = fsl_asrc_dma_pcm_pointer,
.pcm_construct = fsl_asrc_dma_pcm_new,
.pcm_destruct = fsl_asrc_dma_pcm_free,
};
EXPORT_SYMBOL_GPL(fsl_asrc_component);

View File

@ -201,8 +201,7 @@ static irqreturn_t fsl_dma_isr(int irq, void *dev_id)
struct fsl_dma_private *dma_private = dev_id;
struct snd_pcm_substream *substream = dma_private->substream;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
struct device *dev = component->dev;
struct device *dev = rtd->dev;
struct ccsr_dma_channel __iomem *dma_channel = dma_private->dma_channel;
irqreturn_t ret = IRQ_NONE;
u32 sr, sr2 = 0;
@ -280,7 +279,8 @@ static irqreturn_t fsl_dma_isr(int irq, void *dev_id)
* Regardless of where the memory is actually allocated, since the device can
* technically DMA to any 36-bit address, we do need to set the DMA mask to 36.
*/
static int fsl_dma_new(struct snd_soc_pcm_runtime *rtd)
static int fsl_dma_new(struct snd_soc_component *component,
struct snd_soc_pcm_runtime *rtd)
{
struct snd_card *card = rtd->card->snd_card;
struct snd_pcm *pcm = rtd->pcm;
@ -380,11 +380,10 @@ static int fsl_dma_new(struct snd_soc_pcm_runtime *rtd)
* buffer, which is what ALSA expects. We're just dividing it into
* contiguous parts, and creating a link descriptor for each one.
*/
static int fsl_dma_open(struct snd_pcm_substream *substream)
static int fsl_dma_open(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
struct device *dev = component->dev;
struct dma_object *dma =
container_of(component->driver, struct dma_object, dai);
@ -533,13 +532,12 @@ static int fsl_dma_open(struct snd_pcm_substream *substream)
* and 8 bytes at a time). So we do not support packed 24-bit samples.
* 24-bit data must be padded to 32 bits.
*/
static int fsl_dma_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *hw_params)
static int fsl_dma_hw_params(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *hw_params)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct fsl_dma_private *dma_private = runtime->private_data;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
struct device *dev = component->dev;
/* Number of bits per sample */
@ -698,12 +696,11 @@ static int fsl_dma_hw_params(struct snd_pcm_substream *substream,
* The base address of the buffer is stored in the source_addr field of the
* first link descriptor.
*/
static snd_pcm_uframes_t fsl_dma_pointer(struct snd_pcm_substream *substream)
static snd_pcm_uframes_t fsl_dma_pointer(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct fsl_dma_private *dma_private = runtime->private_data;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
struct device *dev = component->dev;
struct ccsr_dma_channel __iomem *dma_channel = dma_private->dma_channel;
dma_addr_t position;
@ -763,7 +760,8 @@ static snd_pcm_uframes_t fsl_dma_pointer(struct snd_pcm_substream *substream)
*
* This function can be called multiple times.
*/
static int fsl_dma_hw_free(struct snd_pcm_substream *substream)
static int fsl_dma_hw_free(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct fsl_dma_private *dma_private = runtime->private_data;
@ -796,12 +794,11 @@ static int fsl_dma_hw_free(struct snd_pcm_substream *substream)
/**
* fsl_dma_close: close the stream.
*/
static int fsl_dma_close(struct snd_pcm_substream *substream)
static int fsl_dma_close(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct fsl_dma_private *dma_private = runtime->private_data;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
struct device *dev = component->dev;
struct dma_object *dma =
container_of(component->driver, struct dma_object, dai);
@ -824,7 +821,8 @@ static int fsl_dma_close(struct snd_pcm_substream *substream)
/*
* Remove this PCM driver.
*/
static void fsl_dma_free_dma_buffers(struct snd_pcm *pcm)
static void fsl_dma_free_dma_buffers(struct snd_soc_component *component,
struct snd_pcm *pcm)
{
struct snd_pcm_substream *substream;
unsigned int i;
@ -872,15 +870,6 @@ static struct device_node *find_ssi_node(struct device_node *dma_channel_np)
return NULL;
}
static const struct snd_pcm_ops fsl_dma_ops = {
.open = fsl_dma_open,
.close = fsl_dma_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = fsl_dma_hw_params,
.hw_free = fsl_dma_hw_free,
.pointer = fsl_dma_pointer,
};
static int fsl_soc_dma_probe(struct platform_device *pdev)
{
struct dma_object *dma;
@ -913,8 +902,14 @@ static int fsl_soc_dma_probe(struct platform_device *pdev)
dma->dai.name = DRV_NAME;
dma->dai.ops = &fsl_dma_ops;
dma->dai.pcm_new = fsl_dma_new;
dma->dai.pcm_free = fsl_dma_free_dma_buffers;
dma->dai.open = fsl_dma_open;
dma->dai.close = fsl_dma_close;
dma->dai.ioctl = snd_soc_pcm_lib_ioctl;
dma->dai.hw_params = fsl_dma_hw_params;
dma->dai.hw_free = fsl_dma_hw_free;
dma->dai.pointer = fsl_dma_pointer;
dma->dai.pcm_construct = fsl_dma_new;
dma->dai.pcm_destruct = fsl_dma_free_dma_buffers;
/* Store the SSI-specific information that we need */
dma->ssi_stx_phys = res.start + REG_SSI_STX0;

335
sound/soc/fsl/fsl_mqs.c Normal file
View File

@ -0,0 +1,335 @@
// SPDX-License-Identifier: GPL-2.0
//
// ALSA SoC IMX MQS driver
//
// Copyright (C) 2014-2015 Freescale Semiconductor, Inc.
// Copyright 2019 NXP
#include <linux/clk.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/mfd/syscon.h>
#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
#include <linux/pm_runtime.h>
#include <linux/of.h>
#include <linux/pm.h>
#include <linux/slab.h>
#include <sound/soc.h>
#include <sound/pcm.h>
#include <sound/initval.h>
#define REG_MQS_CTRL 0x00
#define MQS_EN_MASK (0x1 << 28)
#define MQS_EN_SHIFT (28)
#define MQS_SW_RST_MASK (0x1 << 24)
#define MQS_SW_RST_SHIFT (24)
#define MQS_OVERSAMPLE_MASK (0x1 << 20)
#define MQS_OVERSAMPLE_SHIFT (20)
#define MQS_CLK_DIV_MASK (0xFF << 0)
#define MQS_CLK_DIV_SHIFT (0)
/* codec private data */
struct fsl_mqs {
struct regmap *regmap;
struct clk *mclk;
struct clk *ipg;
unsigned int reg_iomuxc_gpr2;
unsigned int reg_mqs_ctrl;
bool use_gpr;
};
#define FSL_MQS_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
#define FSL_MQS_FORMATS SNDRV_PCM_FMTBIT_S16_LE
static int fsl_mqs_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
struct snd_soc_component *component = dai->component;
struct fsl_mqs *mqs_priv = snd_soc_component_get_drvdata(component);
unsigned long mclk_rate;
int div, res;
int lrclk;
mclk_rate = clk_get_rate(mqs_priv->mclk);
lrclk = params_rate(params);
/*
* mclk_rate / (oversample(32,64) * FS * 2 * divider ) = repeat_rate;
* if repeat_rate is 8, mqs can achieve better quality.
* oversample rate is fix to 32 currently.
*/
div = mclk_rate / (32 * lrclk * 2 * 8);
res = mclk_rate % (32 * lrclk * 2 * 8);
if (res == 0 && div > 0 && div <= 256) {
if (mqs_priv->use_gpr) {
regmap_update_bits(mqs_priv->regmap, IOMUXC_GPR2,
IMX6SX_GPR2_MQS_CLK_DIV_MASK,
(div - 1) << IMX6SX_GPR2_MQS_CLK_DIV_SHIFT);
regmap_update_bits(mqs_priv->regmap, IOMUXC_GPR2,
IMX6SX_GPR2_MQS_OVERSAMPLE_MASK, 0);
} else {
regmap_update_bits(mqs_priv->regmap, REG_MQS_CTRL,
MQS_CLK_DIV_MASK,
(div - 1) << MQS_CLK_DIV_SHIFT);
regmap_update_bits(mqs_priv->regmap, REG_MQS_CTRL,
MQS_OVERSAMPLE_MASK, 0);
}
} else {
dev_err(component->dev, "can't get proper divider\n");
}
return 0;
}
static int fsl_mqs_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
{
/* Only LEFT_J & SLAVE mode is supported. */
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_LEFT_J:
break;
default:
return -EINVAL;
}
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
case SND_SOC_DAIFMT_NB_NF:
break;
default:
return -EINVAL;
}
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBS_CFS:
break;
default:
return -EINVAL;
}
return 0;
}
static int fsl_mqs_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_component *component = dai->component;
struct fsl_mqs *mqs_priv = snd_soc_component_get_drvdata(component);
if (mqs_priv->use_gpr)
regmap_update_bits(mqs_priv->regmap, IOMUXC_GPR2,
IMX6SX_GPR2_MQS_EN_MASK,
1 << IMX6SX_GPR2_MQS_EN_SHIFT);
else
regmap_update_bits(mqs_priv->regmap, REG_MQS_CTRL,
MQS_EN_MASK,
1 << MQS_EN_SHIFT);
return 0;
}
static void fsl_mqs_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_component *component = dai->component;
struct fsl_mqs *mqs_priv = snd_soc_component_get_drvdata(component);
if (mqs_priv->use_gpr)
regmap_update_bits(mqs_priv->regmap, IOMUXC_GPR2,
IMX6SX_GPR2_MQS_EN_MASK, 0);
else
regmap_update_bits(mqs_priv->regmap, REG_MQS_CTRL,
MQS_EN_MASK, 0);
}
static const struct snd_soc_component_driver soc_codec_fsl_mqs = {
.idle_bias_on = 1,
.non_legacy_dai_naming = 1,
};
static const struct snd_soc_dai_ops fsl_mqs_dai_ops = {
.startup = fsl_mqs_startup,
.shutdown = fsl_mqs_shutdown,
.hw_params = fsl_mqs_hw_params,
.set_fmt = fsl_mqs_set_dai_fmt,
};
static struct snd_soc_dai_driver fsl_mqs_dai = {
.name = "fsl-mqs-dai",
.playback = {
.stream_name = "Playback",
.channels_min = 2,
.channels_max = 2,
.rates = FSL_MQS_RATES,
.formats = FSL_MQS_FORMATS,
},
.ops = &fsl_mqs_dai_ops,
};
static const struct regmap_config fsl_mqs_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
.max_register = REG_MQS_CTRL,
.cache_type = REGCACHE_NONE,
};
static int fsl_mqs_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct device_node *gpr_np = NULL;
struct fsl_mqs *mqs_priv;
void __iomem *regs;
int ret;
mqs_priv = devm_kzalloc(&pdev->dev, sizeof(*mqs_priv), GFP_KERNEL);
if (!mqs_priv)
return -ENOMEM;
/* On i.MX6sx the MQS control register is in GPR domain
* But in i.MX8QM/i.MX8QXP the control register is moved
* to its own domain.
*/
if (of_device_is_compatible(np, "fsl,imx8qm-mqs"))
mqs_priv->use_gpr = false;
else
mqs_priv->use_gpr = true;
if (mqs_priv->use_gpr) {
gpr_np = of_parse_phandle(np, "gpr", 0);
if (!gpr_np) {
dev_err(&pdev->dev, "failed to get gpr node by phandle\n");
return -EINVAL;
}
mqs_priv->regmap = syscon_node_to_regmap(gpr_np);
if (IS_ERR(mqs_priv->regmap)) {
dev_err(&pdev->dev, "failed to get gpr regmap\n");
ret = PTR_ERR(mqs_priv->regmap);
goto err_free_gpr_np;
}
} else {
regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(regs))
return PTR_ERR(regs);
mqs_priv->regmap = devm_regmap_init_mmio_clk(&pdev->dev,
"core",
regs,
&fsl_mqs_regmap_config);
if (IS_ERR(mqs_priv->regmap)) {
dev_err(&pdev->dev, "failed to init regmap: %ld\n",
PTR_ERR(mqs_priv->regmap));
return PTR_ERR(mqs_priv->regmap);
}
mqs_priv->ipg = devm_clk_get(&pdev->dev, "core");
if (IS_ERR(mqs_priv->ipg)) {
dev_err(&pdev->dev, "failed to get the clock: %ld\n",
PTR_ERR(mqs_priv->ipg));
return PTR_ERR(mqs_priv->ipg);
}
}
mqs_priv->mclk = devm_clk_get(&pdev->dev, "mclk");
if (IS_ERR(mqs_priv->mclk)) {
dev_err(&pdev->dev, "failed to get the clock: %ld\n",
PTR_ERR(mqs_priv->mclk));
ret = PTR_ERR(mqs_priv->mclk);
goto err_free_gpr_np;
}
dev_set_drvdata(&pdev->dev, mqs_priv);
pm_runtime_enable(&pdev->dev);
ret = devm_snd_soc_register_component(&pdev->dev, &soc_codec_fsl_mqs,
&fsl_mqs_dai, 1);
if (ret)
goto err_free_gpr_np;
return 0;
err_free_gpr_np:
of_node_put(gpr_np);
return ret;
}
static int fsl_mqs_remove(struct platform_device *pdev)
{
pm_runtime_disable(&pdev->dev);
return 0;
}
#ifdef CONFIG_PM
static int fsl_mqs_runtime_resume(struct device *dev)
{
struct fsl_mqs *mqs_priv = dev_get_drvdata(dev);
if (mqs_priv->ipg)
clk_prepare_enable(mqs_priv->ipg);
if (mqs_priv->mclk)
clk_prepare_enable(mqs_priv->mclk);
if (mqs_priv->use_gpr)
regmap_write(mqs_priv->regmap, IOMUXC_GPR2,
mqs_priv->reg_iomuxc_gpr2);
else
regmap_write(mqs_priv->regmap, REG_MQS_CTRL,
mqs_priv->reg_mqs_ctrl);
return 0;
}
static int fsl_mqs_runtime_suspend(struct device *dev)
{
struct fsl_mqs *mqs_priv = dev_get_drvdata(dev);
if (mqs_priv->use_gpr)
regmap_read(mqs_priv->regmap, IOMUXC_GPR2,
&mqs_priv->reg_iomuxc_gpr2);
else
regmap_read(mqs_priv->regmap, REG_MQS_CTRL,
&mqs_priv->reg_mqs_ctrl);
if (mqs_priv->mclk)
clk_disable_unprepare(mqs_priv->mclk);
if (mqs_priv->ipg)
clk_disable_unprepare(mqs_priv->ipg);
return 0;
}
#endif
static const struct dev_pm_ops fsl_mqs_pm_ops = {
SET_RUNTIME_PM_OPS(fsl_mqs_runtime_suspend,
fsl_mqs_runtime_resume,
NULL)
SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
pm_runtime_force_resume)
};
static const struct of_device_id fsl_mqs_dt_ids[] = {
{ .compatible = "fsl,imx8qm-mqs", },
{ .compatible = "fsl,imx6sx-mqs", },
{}
};
MODULE_DEVICE_TABLE(of, fsl_mqs_dt_ids);
static struct platform_driver fsl_mqs_driver = {
.probe = fsl_mqs_probe,
.remove = fsl_mqs_remove,
.driver = {
.name = "fsl-mqs",
.of_match_table = fsl_mqs_dt_ids,
.pm = &fsl_mqs_pm_ops,
},
};
module_platform_driver(fsl_mqs_driver);
MODULE_AUTHOR("Shengjiu Wang <Shengjiu.Wang@nxp.com>");
MODULE_DESCRIPTION("MQS codec driver");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform: fsl-mqs");

View File

@ -69,8 +69,9 @@ static struct fiq_handler fh = {
.name = DRV_NAME,
};
static int snd_imx_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
static int snd_imx_pcm_hw_params(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct imx_pcm_runtime_data *iprtd = runtime->private_data;
@ -85,7 +86,8 @@ static int snd_imx_pcm_hw_params(struct snd_pcm_substream *substream,
return 0;
}
static int snd_imx_pcm_prepare(struct snd_pcm_substream *substream)
static int snd_imx_pcm_prepare(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct imx_pcm_runtime_data *iprtd = runtime->private_data;
@ -104,7 +106,8 @@ static int snd_imx_pcm_prepare(struct snd_pcm_substream *substream)
static int imx_pcm_fiq;
static int snd_imx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
static int snd_imx_pcm_trigger(struct snd_soc_component *component,
struct snd_pcm_substream *substream, int cmd)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct imx_pcm_runtime_data *iprtd = runtime->private_data;
@ -141,7 +144,9 @@ static int snd_imx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
return 0;
}
static snd_pcm_uframes_t snd_imx_pcm_pointer(struct snd_pcm_substream *substream)
static snd_pcm_uframes_t
snd_imx_pcm_pointer(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct imx_pcm_runtime_data *iprtd = runtime->private_data;
@ -165,7 +170,8 @@ static const struct snd_pcm_hardware snd_imx_hardware = {
.fifo_size = 0,
};
static int snd_imx_open(struct snd_pcm_substream *substream)
static int snd_imx_open(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct imx_pcm_runtime_data *iprtd;
@ -194,7 +200,8 @@ static int snd_imx_open(struct snd_pcm_substream *substream)
return 0;
}
static int snd_imx_close(struct snd_pcm_substream *substream)
static int snd_imx_close(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct imx_pcm_runtime_data *iprtd = runtime->private_data;
@ -206,8 +213,9 @@ static int snd_imx_close(struct snd_pcm_substream *substream)
return 0;
}
static int snd_imx_pcm_mmap(struct snd_pcm_substream *substream,
struct vm_area_struct *vma)
static int snd_imx_pcm_mmap(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
struct vm_area_struct *vma)
{
struct snd_pcm_runtime *runtime = substream->runtime;
int ret;
@ -222,17 +230,6 @@ static int snd_imx_pcm_mmap(struct snd_pcm_substream *substream,
return ret;
}
static const struct snd_pcm_ops imx_pcm_ops = {
.open = snd_imx_open,
.close = snd_imx_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = snd_imx_pcm_hw_params,
.prepare = snd_imx_pcm_prepare,
.trigger = snd_imx_pcm_trigger,
.pointer = snd_imx_pcm_pointer,
.mmap = snd_imx_pcm_mmap,
};
static int imx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
{
struct snd_pcm_substream *substream = pcm->streams[stream].substream;
@ -279,7 +276,8 @@ static int imx_pcm_new(struct snd_soc_pcm_runtime *rtd)
static int ssi_irq;
static int imx_pcm_fiq_new(struct snd_soc_pcm_runtime *rtd)
static int snd_imx_pcm_new(struct snd_soc_component *component,
struct snd_soc_pcm_runtime *rtd)
{
struct snd_pcm *pcm = rtd->pcm;
struct snd_pcm_substream *substream;
@ -329,7 +327,8 @@ static void imx_pcm_free(struct snd_pcm *pcm)
}
}
static void imx_pcm_fiq_free(struct snd_pcm *pcm)
static void snd_imx_pcm_free(struct snd_soc_component *component,
struct snd_pcm *pcm)
{
mxc_set_irq_fiq(ssi_irq, 0);
release_fiq(&fh);
@ -337,9 +336,16 @@ static void imx_pcm_fiq_free(struct snd_pcm *pcm)
}
static const struct snd_soc_component_driver imx_soc_component_fiq = {
.ops = &imx_pcm_ops,
.pcm_new = imx_pcm_fiq_new,
.pcm_free = imx_pcm_fiq_free,
.open = snd_imx_open,
.close = snd_imx_close,
.ioctl = snd_soc_pcm_lib_ioctl,
.hw_params = snd_imx_pcm_hw_params,
.prepare = snd_imx_pcm_prepare,
.trigger = snd_imx_pcm_trigger,
.pointer = snd_imx_pcm_pointer,
.mmap = snd_imx_pcm_mmap,
.pcm_construct = snd_imx_pcm_new,
.pcm_destruct = snd_imx_pcm_free,
};
int imx_pcm_fiq_init(struct platform_device *pdev,

View File

@ -98,7 +98,8 @@ static irqreturn_t psc_dma_bcom_irq(int irq, void *_psc_dma_stream)
return IRQ_HANDLED;
}
static int psc_dma_hw_free(struct snd_pcm_substream *substream)
static int psc_dma_hw_free(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
snd_pcm_set_runtime_buffer(substream, NULL);
return 0;
@ -110,7 +111,8 @@ static int psc_dma_hw_free(struct snd_pcm_substream *substream)
* This function is called by ALSA to start, stop, pause, and resume the DMA
* transfer of data.
*/
static int psc_dma_trigger(struct snd_pcm_substream *substream, int cmd)
static int psc_dma_trigger(struct snd_soc_component *component,
struct snd_pcm_substream *substream, int cmd)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(rtd->cpu_dai);
@ -210,7 +212,8 @@ static const struct snd_pcm_hardware psc_dma_hardware = {
.fifo_size = 512,
};
static int psc_dma_open(struct snd_pcm_substream *substream)
static int psc_dma_open(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
@ -238,7 +241,8 @@ static int psc_dma_open(struct snd_pcm_substream *substream)
return 0;
}
static int psc_dma_close(struct snd_pcm_substream *substream)
static int psc_dma_close(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(rtd->cpu_dai);
@ -263,7 +267,8 @@ static int psc_dma_close(struct snd_pcm_substream *substream)
}
static snd_pcm_uframes_t
psc_dma_pointer(struct snd_pcm_substream *substream)
psc_dma_pointer(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(rtd->cpu_dai);
@ -280,29 +285,19 @@ psc_dma_pointer(struct snd_pcm_substream *substream)
return bytes_to_frames(substream->runtime, count);
}
static int
psc_dma_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
static int psc_dma_hw_params(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
return 0;
}
static const struct snd_pcm_ops psc_dma_ops = {
.open = psc_dma_open,
.close = psc_dma_close,
.hw_free = psc_dma_hw_free,
.ioctl = snd_pcm_lib_ioctl,
.pointer = psc_dma_pointer,
.trigger = psc_dma_trigger,
.hw_params = psc_dma_hw_params,
};
static int psc_dma_new(struct snd_soc_pcm_runtime *rtd)
static int psc_dma_new(struct snd_soc_component *component,
struct snd_soc_pcm_runtime *rtd)
{
struct snd_card *card = rtd->card->snd_card;
struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
struct snd_soc_dai *dai = rtd->cpu_dai;
struct snd_pcm *pcm = rtd->pcm;
size_t size = psc_dma_hardware.buffer_bytes_max;
@ -341,10 +336,10 @@ static int psc_dma_new(struct snd_soc_pcm_runtime *rtd)
return -ENOMEM;
}
static void psc_dma_free(struct snd_pcm *pcm)
static void psc_dma_free(struct snd_soc_component *component,
struct snd_pcm *pcm)
{
struct snd_soc_pcm_runtime *rtd = pcm->private_data;
struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
struct snd_pcm_substream *substream;
int stream;
@ -362,9 +357,15 @@ static void psc_dma_free(struct snd_pcm *pcm)
static const struct snd_soc_component_driver mpc5200_audio_dma_component = {
.name = DRV_NAME,
.ops = &psc_dma_ops,
.pcm_new = &psc_dma_new,
.pcm_free = &psc_dma_free,
.open = psc_dma_open,
.close = psc_dma_close,
.hw_free = psc_dma_hw_free,
.ioctl = snd_soc_pcm_lib_ioctl,
.pointer = psc_dma_pointer,
.trigger = psc_dma_trigger,
.hw_params = psc_dma_hw_params,
.pcm_construct = psc_dma_new,
.pcm_destruct = psc_dma_free,
};
int mpc5200_audio_dma_create(struct platform_device *op)

View File

@ -232,7 +232,7 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv,
if (li->cpu) {
int is_single_links = 0;
/* BE is dummy */
/* Codec is dummy */
codecs->of_node = NULL;
codecs->dai_name = "snd-soc-dummy-dai";
codecs->name = "snd-soc-dummy";
@ -263,7 +263,7 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv,
} else {
struct snd_soc_codec_conf *cconf;
/* FE is dummy */
/* CPU is dummy */
cpus->of_node = NULL;
cpus->dai_name = "snd-soc-dummy-dai";
cpus->name = "snd-soc-dummy";

View File

@ -149,7 +149,7 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv,
if (li->cpu) {
int is_single_links = 0;
/* BE is dummy */
/* Codec is dummy */
codecs->of_node = NULL;
codecs->dai_name = "snd-soc-dummy-dai";
codecs->name = "snd-soc-dummy";
@ -179,7 +179,7 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv,
} else {
struct snd_soc_codec_conf *cconf;
/* FE is dummy */
/* CPU is dummy */
cpus->of_node = NULL;
cpus->dai_name = "snd-soc-dummy-dai";
cpus->name = "snd-soc-dummy";

View File

@ -586,7 +586,8 @@ static struct snd_soc_dai_driver sst_platform_dai[] = {
},
};
static int sst_platform_open(struct snd_pcm_substream *substream)
static int sst_soc_open(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime;
@ -598,15 +599,15 @@ static int sst_platform_open(struct snd_pcm_substream *substream)
return 0;
}
static int sst_platform_pcm_trigger(struct snd_pcm_substream *substream,
int cmd)
static int sst_soc_trigger(struct snd_soc_component *component,
struct snd_pcm_substream *substream, int cmd)
{
int ret_val = 0, str_id;
struct sst_runtime_stream *stream;
int status;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
dev_dbg(rtd->dev, "sst_platform_pcm_trigger called\n");
dev_dbg(rtd->dev, "%s called\n", __func__);
if (substream->pcm->internal)
return 0;
stream = substream->runtime->private_data;
@ -646,8 +647,8 @@ static int sst_platform_pcm_trigger(struct snd_pcm_substream *substream,
}
static snd_pcm_uframes_t sst_platform_pcm_pointer
(struct snd_pcm_substream *substream)
static snd_pcm_uframes_t sst_soc_pointer(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct sst_runtime_stream *stream;
int ret_val, status;
@ -668,14 +669,8 @@ static snd_pcm_uframes_t sst_platform_pcm_pointer
return str_info->buffer_ptr;
}
static const struct snd_pcm_ops sst_platform_ops = {
.open = sst_platform_open,
.ioctl = snd_pcm_lib_ioctl,
.trigger = sst_platform_pcm_trigger,
.pointer = sst_platform_pcm_pointer,
};
static int sst_pcm_new(struct snd_soc_pcm_runtime *rtd)
static int sst_soc_pcm_new(struct snd_soc_component *component,
struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_dai *dai = rtd->cpu_dai;
struct snd_pcm *pcm = rtd->pcm;
@ -709,9 +704,12 @@ static const struct snd_soc_component_driver sst_soc_platform_drv = {
.name = DRV_NAME,
.probe = sst_soc_probe,
.remove = sst_soc_remove,
.ops = &sst_platform_ops,
.open = sst_soc_open,
.ioctl = snd_soc_pcm_lib_ioctl,
.trigger = sst_soc_trigger,
.pointer = sst_soc_pointer,
.compr_ops = &sst_platform_compr_ops,
.pcm_new = sst_pcm_new,
.pcm_construct = sst_soc_pcm_new,
};
static int sst_platform_probe(struct platform_device *pdev)

View File

@ -58,11 +58,11 @@ struct sst_byt_priv_data {
};
/* this may get called several times by oss emulation */
static int sst_byt_pcm_hw_params(struct snd_pcm_substream *substream,
static int sst_byt_pcm_hw_params(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
struct sst_byt_priv_data *pdata = snd_soc_component_get_drvdata(component);
struct sst_byt_pcm_data *pcm_data = &pdata->pcm[substream->stream];
struct sst_byt *byt = pdata->byt;
@ -121,7 +121,8 @@ static int sst_byt_pcm_hw_params(struct snd_pcm_substream *substream,
return 0;
}
static int sst_byt_pcm_hw_free(struct snd_pcm_substream *substream)
static int sst_byt_pcm_hw_free(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
@ -164,10 +165,10 @@ static void sst_byt_pcm_work(struct work_struct *work)
sst_byt_pcm_restore_stream_context(pcm_data->substream);
}
static int sst_byt_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
static int sst_byt_pcm_trigger(struct snd_soc_component *component,
struct snd_pcm_substream *substream, int cmd)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
struct sst_byt_priv_data *pdata = snd_soc_component_get_drvdata(component);
struct sst_byt_pcm_data *pcm_data = &pdata->pcm[substream->stream];
struct sst_byt *byt = pdata->byt;
@ -228,11 +229,11 @@ static u32 byt_notify_pointer(struct sst_byt_stream *stream, void *data)
return pos;
}
static snd_pcm_uframes_t sst_byt_pcm_pointer(struct snd_pcm_substream *substream)
static snd_pcm_uframes_t sst_byt_pcm_pointer(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
struct sst_byt_priv_data *pdata = snd_soc_component_get_drvdata(component);
struct sst_byt_pcm_data *pcm_data = &pdata->pcm[substream->stream];
@ -241,10 +242,10 @@ static snd_pcm_uframes_t sst_byt_pcm_pointer(struct snd_pcm_substream *substream
return bytes_to_frames(runtime, pcm_data->hw_ptr);
}
static int sst_byt_pcm_open(struct snd_pcm_substream *substream)
static int sst_byt_pcm_open(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
struct sst_byt_priv_data *pdata = snd_soc_component_get_drvdata(component);
struct sst_byt_pcm_data *pcm_data = &pdata->pcm[substream->stream];
struct sst_byt *byt = pdata->byt;
@ -269,10 +270,10 @@ static int sst_byt_pcm_open(struct snd_pcm_substream *substream)
return 0;
}
static int sst_byt_pcm_close(struct snd_pcm_substream *substream)
static int sst_byt_pcm_close(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
struct sst_byt_priv_data *pdata = snd_soc_component_get_drvdata(component);
struct sst_byt_pcm_data *pcm_data = &pdata->pcm[substream->stream];
struct sst_byt *byt = pdata->byt;
@ -294,7 +295,8 @@ static int sst_byt_pcm_close(struct snd_pcm_substream *substream)
return ret;
}
static int sst_byt_pcm_mmap(struct snd_pcm_substream *substream,
static int sst_byt_pcm_mmap(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
struct vm_area_struct *vma)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
@ -303,22 +305,11 @@ static int sst_byt_pcm_mmap(struct snd_pcm_substream *substream,
return snd_pcm_lib_default_mmap(substream, vma);
}
static const struct snd_pcm_ops sst_byt_pcm_ops = {
.open = sst_byt_pcm_open,
.close = sst_byt_pcm_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = sst_byt_pcm_hw_params,
.hw_free = sst_byt_pcm_hw_free,
.trigger = sst_byt_pcm_trigger,
.pointer = sst_byt_pcm_pointer,
.mmap = sst_byt_pcm_mmap,
};
static int sst_byt_pcm_new(struct snd_soc_pcm_runtime *rtd)
static int sst_byt_pcm_new(struct snd_soc_component *component,
struct snd_soc_pcm_runtime *rtd)
{
struct snd_pcm *pcm = rtd->pcm;
size_t size;
struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
struct sst_pdata *pdata = dev_get_platdata(component->dev);
if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream ||
@ -380,8 +371,15 @@ static int sst_byt_pcm_probe(struct snd_soc_component *component)
static const struct snd_soc_component_driver byt_dai_component = {
.name = DRV_NAME,
.probe = sst_byt_pcm_probe,
.ops = &sst_byt_pcm_ops,
.pcm_new = sst_byt_pcm_new,
.open = sst_byt_pcm_open,
.close = sst_byt_pcm_close,
.ioctl = snd_soc_pcm_lib_ioctl,
.hw_params = sst_byt_pcm_hw_params,
.hw_free = sst_byt_pcm_hw_free,
.trigger = sst_byt_pcm_trigger,
.pointer = sst_byt_pcm_pointer,
.mmap = sst_byt_pcm_mmap,
.pcm_construct = sst_byt_pcm_new,
};
#ifdef CONFIG_PM

View File

@ -320,6 +320,7 @@ config SND_SOC_INTEL_KBL_RT5663_RT5514_MAX98927_MACH
select SND_SOC_RT5514_SPI
select SND_SOC_MAX98927
select SND_SOC_HDAC_HDMI
select SND_SOC_INTEL_SKYLAKE_SSP_CLK
help
This adds support for ASoC Onboard Codec I2S machine driver. This will
create an alsa sound card for RT5663 + RT5514 + MAX98927.

View File

@ -48,6 +48,7 @@ struct cht_mc_private {
#define CHT_RT5645_SSP2_AIF2 BIT(16) /* default is using AIF1 */
#define CHT_RT5645_SSP0_AIF1 BIT(17)
#define CHT_RT5645_SSP0_AIF2 BIT(18)
#define CHT_RT5645_PMC_PLT_CLK_0 BIT(19)
static unsigned long cht_rt5645_quirk = 0;
@ -59,6 +60,8 @@ static void log_quirks(struct device *dev)
dev_info(dev, "quirk SSP0_AIF1 enabled");
if (cht_rt5645_quirk & CHT_RT5645_SSP0_AIF2)
dev_info(dev, "quirk SSP0_AIF2 enabled");
if (cht_rt5645_quirk & CHT_RT5645_PMC_PLT_CLK_0)
dev_info(dev, "quirk PMC_PLT_CLK_0 enabled");
}
static int platform_clock_control(struct snd_soc_dapm_widget *w,
@ -226,15 +229,21 @@ static int cht_aif1_hw_params(struct snd_pcm_substream *substream,
return 0;
}
/* uncomment when we have a real quirk
static int cht_rt5645_quirk_cb(const struct dmi_system_id *id)
{
cht_rt5645_quirk = (unsigned long)id->driver_data;
return 1;
}
*/
static const struct dmi_system_id cht_rt5645_quirk_table[] = {
{
/* Strago family Chromebooks */
.callback = cht_rt5645_quirk_cb,
.matches = {
DMI_MATCH(DMI_PRODUCT_FAMILY, "Intel_Strago"),
},
.driver_data = (void *)CHT_RT5645_PMC_PLT_CLK_0,
},
{
},
};
@ -526,6 +535,7 @@ static int snd_cht_mc_probe(struct platform_device *pdev)
int dai_index = 0;
int ret_val = 0;
int i;
const char *mclk_name;
drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
if (!drv)
@ -662,11 +672,15 @@ static int snd_cht_mc_probe(struct platform_device *pdev)
if (ret_val)
return ret_val;
drv->mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3");
if (cht_rt5645_quirk & CHT_RT5645_PMC_PLT_CLK_0)
mclk_name = "pmc_plt_clk_0";
else
mclk_name = "pmc_plt_clk_3";
drv->mclk = devm_clk_get(&pdev->dev, mclk_name);
if (IS_ERR(drv->mclk)) {
dev_err(&pdev->dev,
"Failed to get MCLK from pmc_plt_clk_3: %ld\n",
PTR_ERR(drv->mclk));
dev_err(&pdev->dev, "Failed to get MCLK from %s: %ld\n",
mclk_name, PTR_ERR(drv->mclk));
return PTR_ERR(drv->mclk);
}

View File

@ -22,6 +22,9 @@
#include "../../codecs/rt5514.h"
#include "../../codecs/rt5663.h"
#include "../../codecs/hdac_hdmi.h"
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/clkdev.h>
#define KBL_REALTEK_CODEC_DAI "rt5663-aif"
#define KBL_REALTEK_DMIC_CODEC_DAI "rt5514-aif1"
@ -50,6 +53,8 @@ struct kbl_codec_private {
struct snd_soc_jack kabylake_headset;
struct list_head hdmi_pcm_list;
struct snd_soc_jack kabylake_hdmi[2];
struct clk *mclk;
struct clk *sclk;
};
enum {
@ -71,6 +76,61 @@ static const struct snd_kcontrol_new kabylake_controls[] = {
SOC_DAPM_PIN_SWITCH("DMIC"),
};
static int platform_clock_control(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *k, int event)
{
struct snd_soc_dapm_context *dapm = w->dapm;
struct snd_soc_card *card = dapm->card;
struct kbl_codec_private *priv = snd_soc_card_get_drvdata(card);
int ret = 0;
/*
* MCLK/SCLK need to be ON early for a successful synchronization of
* codec internal clock. And the clocks are turned off during
* POST_PMD after the stream is stopped.
*/
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
/* Enable MCLK */
ret = clk_set_rate(priv->mclk, 24000000);
if (ret < 0) {
dev_err(card->dev, "Can't set rate for mclk, err: %d\n",
ret);
return ret;
}
ret = clk_prepare_enable(priv->mclk);
if (ret < 0) {
dev_err(card->dev, "Can't enable mclk, err: %d\n", ret);
return ret;
}
/* Enable SCLK */
ret = clk_set_rate(priv->sclk, 3072000);
if (ret < 0) {
dev_err(card->dev, "Can't set rate for sclk, err: %d\n",
ret);
clk_disable_unprepare(priv->mclk);
return ret;
}
ret = clk_prepare_enable(priv->sclk);
if (ret < 0) {
dev_err(card->dev, "Can't enable sclk, err: %d\n", ret);
clk_disable_unprepare(priv->mclk);
}
break;
case SND_SOC_DAPM_POST_PMD:
clk_disable_unprepare(priv->mclk);
clk_disable_unprepare(priv->sclk);
break;
default:
return 0;
}
return 0;
}
static const struct snd_soc_dapm_widget kabylake_widgets[] = {
SND_SOC_DAPM_HP("Headphone Jack", NULL),
SND_SOC_DAPM_MIC("Headset Mic", NULL),
@ -79,11 +139,15 @@ static const struct snd_soc_dapm_widget kabylake_widgets[] = {
SND_SOC_DAPM_MIC("DMIC", NULL),
SND_SOC_DAPM_SPK("HDMI1", NULL),
SND_SOC_DAPM_SPK("HDMI2", NULL),
SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
platform_clock_control, SND_SOC_DAPM_PRE_PMU |
SND_SOC_DAPM_POST_PMD),
};
static const struct snd_soc_dapm_route kabylake_map[] = {
/* Headphones */
{ "Headphone Jack", NULL, "Platform Clock" },
{ "Headphone Jack", NULL, "HPOL" },
{ "Headphone Jack", NULL, "HPOR" },
@ -92,6 +156,7 @@ static const struct snd_soc_dapm_route kabylake_map[] = {
{ "Right Spk", NULL, "Right BE_OUT" },
/* other jacks */
{ "Headset Mic", NULL, "Platform Clock" },
{ "IN1P", NULL, "Headset Mic" },
{ "IN1N", NULL, "Headset Mic" },
@ -643,6 +708,7 @@ static int kabylake_audio_probe(struct platform_device *pdev)
{
struct kbl_codec_private *ctx;
struct snd_soc_acpi_mach *mach;
int ret = 0;
ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
if (!ctx)
@ -658,6 +724,34 @@ static int kabylake_audio_probe(struct platform_device *pdev)
dmic_constraints = mach->mach_params.dmic_num == 2 ?
&constraints_dmic_2ch : &constraints_dmic_channels;
ctx->mclk = devm_clk_get(&pdev->dev, "ssp1_mclk");
if (IS_ERR(ctx->mclk)) {
ret = PTR_ERR(ctx->mclk);
if (ret == -ENOENT) {
dev_info(&pdev->dev,
"Failed to get ssp1_mclk, defer probe\n");
return -EPROBE_DEFER;
}
dev_err(&pdev->dev, "Failed to get ssp1_mclk with err:%d\n",
ret);
return ret;
}
ctx->sclk = devm_clk_get(&pdev->dev, "ssp1_sclk");
if (IS_ERR(ctx->sclk)) {
ret = PTR_ERR(ctx->sclk);
if (ret == -ENOENT) {
dev_info(&pdev->dev,
"Failed to get ssp1_sclk, defer probe\n");
return -EPROBE_DEFER;
}
dev_err(&pdev->dev, "Failed to get ssp1_sclk with err:%d\n",
ret);
return ret;
}
return devm_snd_soc_register_card(&pdev->dev, &kabylake_audio_card);
}

View File

@ -458,12 +458,12 @@ static int create_adsp_page_table(struct snd_pcm_substream *substream,
}
/* this may get called several times by oss emulation */
static int hsw_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
static int hsw_pcm_hw_params(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
struct hsw_priv_data *pdata = snd_soc_component_get_drvdata(component);
struct hsw_pcm_data *pcm_data;
struct sst_hsw *hsw = pdata->hsw;
@ -656,16 +656,17 @@ static int hsw_pcm_hw_params(struct snd_pcm_substream *substream,
return 0;
}
static int hsw_pcm_hw_free(struct snd_pcm_substream *substream)
static int hsw_pcm_hw_free(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
snd_pcm_lib_free_pages(substream);
return 0;
}
static int hsw_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
static int hsw_pcm_trigger(struct snd_soc_component *component,
struct snd_pcm_substream *substream, int cmd)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
struct hsw_priv_data *pdata = snd_soc_component_get_drvdata(component);
struct hsw_pcm_data *pcm_data;
struct sst_hsw_stream *sst_stream;
@ -770,11 +771,11 @@ static u32 hsw_notify_pointer(struct sst_hsw_stream *stream, void *data)
return pos;
}
static snd_pcm_uframes_t hsw_pcm_pointer(struct snd_pcm_substream *substream)
static snd_pcm_uframes_t hsw_pcm_pointer(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
struct hsw_priv_data *pdata = snd_soc_component_get_drvdata(component);
struct hsw_pcm_data *pcm_data;
struct sst_hsw *hsw = pdata->hsw;
@ -795,10 +796,21 @@ static snd_pcm_uframes_t hsw_pcm_pointer(struct snd_pcm_substream *substream)
return offset;
}
static int hsw_pcm_open(struct snd_pcm_substream *substream)
#ifdef CONFIG_SND_DMA_SGBUF
static struct page *hsw_pcm_page(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
unsigned long offset)
{
return snd_pcm_sgbuf_ops_page(substream, offset);
}
#else
#define hsw_pcm_page NULL
#endif /* CONFIG_SND_DMA_SGBUF */
static int hsw_pcm_open(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
struct hsw_priv_data *pdata = snd_soc_component_get_drvdata(component);
struct hsw_pcm_data *pcm_data;
struct sst_hsw *hsw = pdata->hsw;
@ -828,10 +840,10 @@ static int hsw_pcm_open(struct snd_pcm_substream *substream)
return 0;
}
static int hsw_pcm_close(struct snd_pcm_substream *substream)
static int hsw_pcm_close(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
struct hsw_priv_data *pdata = snd_soc_component_get_drvdata(component);
struct hsw_pcm_data *pcm_data;
struct sst_hsw *hsw = pdata->hsw;
@ -862,17 +874,6 @@ static int hsw_pcm_close(struct snd_pcm_substream *substream)
return ret;
}
static const struct snd_pcm_ops hsw_pcm_ops = {
.open = hsw_pcm_open,
.close = hsw_pcm_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = hsw_pcm_hw_params,
.hw_free = hsw_pcm_hw_free,
.trigger = hsw_pcm_trigger,
.pointer = hsw_pcm_pointer,
.page = snd_pcm_sgbuf_ops_page,
};
static int hsw_pcm_create_modules(struct hsw_priv_data *pdata)
{
struct sst_hsw *hsw = pdata->hsw;
@ -930,10 +931,10 @@ static void hsw_pcm_free_modules(struct hsw_priv_data *pdata)
}
}
static int hsw_pcm_new(struct snd_soc_pcm_runtime *rtd)
static int hsw_pcm_new(struct snd_soc_component *component,
struct snd_soc_pcm_runtime *rtd)
{
struct snd_pcm *pcm = rtd->pcm;
struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
struct sst_pdata *pdata = dev_get_platdata(component->dev);
struct hsw_priv_data *priv_data = dev_get_drvdata(component->dev);
struct device *dev = pdata->dma_dev;
@ -1121,8 +1122,15 @@ static const struct snd_soc_component_driver hsw_dai_component = {
.name = DRV_NAME,
.probe = hsw_pcm_probe,
.remove = hsw_pcm_remove,
.ops = &hsw_pcm_ops,
.pcm_new = hsw_pcm_new,
.open = hsw_pcm_open,
.close = hsw_pcm_close,
.hw_params = hsw_pcm_hw_params,
.hw_free = hsw_pcm_hw_free,
.trigger = hsw_pcm_trigger,
.pointer = hsw_pcm_pointer,
.page = hsw_pcm_page,
.ioctl = snd_soc_pcm_lib_ioctl,
.pcm_construct = hsw_pcm_new,
.controls = hsw_volume_controls,
.num_controls = ARRAY_SIZE(hsw_volume_controls),
.dapm_widgets = widgets,

View File

@ -1081,7 +1081,8 @@ int skl_dai_load(struct snd_soc_component *cmp, int index,
return 0;
}
static int skl_platform_open(struct snd_pcm_substream *substream)
static int skl_platform_soc_open(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai_link *dai_link = rtd->dai_link;
@ -1167,8 +1168,9 @@ static int skl_coupled_trigger(struct snd_pcm_substream *substream,
return 0;
}
static int skl_platform_pcm_trigger(struct snd_pcm_substream *substream,
int cmd)
static int skl_platform_soc_trigger(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
int cmd)
{
struct hdac_bus *bus = get_bus_ctx(substream);
@ -1178,8 +1180,9 @@ static int skl_platform_pcm_trigger(struct snd_pcm_substream *substream,
return 0;
}
static snd_pcm_uframes_t skl_platform_pcm_pointer
(struct snd_pcm_substream *substream)
static snd_pcm_uframes_t skl_platform_soc_pointer(
struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct hdac_ext_stream *hstream = get_hdac_ext_stream(substream);
struct hdac_bus *bus = get_bus_ctx(substream);
@ -1225,6 +1228,24 @@ static snd_pcm_uframes_t skl_platform_pcm_pointer
return bytes_to_frames(substream->runtime, pos);
}
static int skl_platform_soc_mmap(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
struct vm_area_struct *area)
{
return snd_pcm_lib_default_mmap(substream, area);
}
#ifdef CONFIG_SND_DMA_SGBUF
static struct page *skl_platform_soc_page(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
unsigned long offset)
{
return snd_pcm_sgbuf_ops_page(substream, offset);
}
#else
#define skl_platform_soc_page NULL
#endif /* CONFIG_SND_DMA_SGBUF */
static u64 skl_adjust_codec_delay(struct snd_pcm_substream *substream,
u64 nsec)
{
@ -1245,7 +1266,9 @@ static u64 skl_adjust_codec_delay(struct snd_pcm_substream *substream,
return (nsec > codec_nsecs) ? nsec - codec_nsecs : 0;
}
static int skl_get_time_info(struct snd_pcm_substream *substream,
static int skl_platform_soc_get_time_info(
struct snd_soc_component *component,
struct snd_pcm_substream *substream,
struct timespec *system_ts, struct timespec *audio_ts,
struct snd_pcm_audio_tstamp_config *audio_tstamp_config,
struct snd_pcm_audio_tstamp_report *audio_tstamp_report)
@ -1277,24 +1300,16 @@ static int skl_get_time_info(struct snd_pcm_substream *substream,
return 0;
}
static const struct snd_pcm_ops skl_platform_ops = {
.open = skl_platform_open,
.ioctl = snd_pcm_lib_ioctl,
.trigger = skl_platform_pcm_trigger,
.pointer = skl_platform_pcm_pointer,
.get_time_info = skl_get_time_info,
.mmap = snd_pcm_lib_default_mmap,
.page = snd_pcm_sgbuf_ops_page,
};
static void skl_pcm_free(struct snd_pcm *pcm)
static void skl_platform_soc_free(struct snd_soc_component *component,
struct snd_pcm *pcm)
{
snd_pcm_lib_preallocate_free_for_all(pcm);
}
#define MAX_PREALLOC_SIZE (32 * 1024 * 1024)
static int skl_pcm_new(struct snd_soc_pcm_runtime *rtd)
static int skl_platform_soc_new(struct snd_soc_component *component,
struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_dai *dai = rtd->cpu_dai;
struct hdac_bus *bus = dev_get_drvdata(dai->dev);
@ -1458,7 +1473,7 @@ static int skl_platform_soc_probe(struct snd_soc_component *component)
return 0;
}
static void skl_pcm_remove(struct snd_soc_component *component)
static void skl_platform_soc_remove(struct snd_soc_component *component)
{
struct hdac_bus *bus = dev_get_drvdata(component->dev);
struct skl_dev *skl = bus_to_skl(bus);
@ -1471,10 +1486,16 @@ static void skl_pcm_remove(struct snd_soc_component *component)
static const struct snd_soc_component_driver skl_component = {
.name = "pcm",
.probe = skl_platform_soc_probe,
.remove = skl_pcm_remove,
.ops = &skl_platform_ops,
.pcm_new = skl_pcm_new,
.pcm_free = skl_pcm_free,
.remove = skl_platform_soc_remove,
.open = skl_platform_soc_open,
.ioctl = snd_soc_pcm_lib_ioctl,
.trigger = skl_platform_soc_trigger,
.pointer = skl_platform_soc_pointer,
.get_time_info = skl_platform_soc_get_time_info,
.mmap = skl_platform_soc_mmap,
.page = skl_platform_soc_page,
.pcm_construct = skl_platform_soc_new,
.pcm_destruct = skl_platform_soc_free,
.module_get_upon_open = 1, /* increment refcount when a pcm is opened */
};

View File

@ -497,15 +497,13 @@ static int jz4740_i2s_dev_probe(struct platform_device *pdev)
struct jz4740_i2s *i2s;
struct resource *mem;
int ret;
const struct of_device_id *match;
i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL);
if (!i2s)
return -ENOMEM;
match = of_match_device(jz4740_of_matches, &pdev->dev);
if (match)
i2s->version = (enum jz47xx_i2s_version)match->data;
i2s->version =
(enum jz47xx_i2s_version)of_device_get_match_data(&pdev->dev);
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
i2s->base = devm_ioremap_resource(&pdev->dev, mem);

View File

@ -98,7 +98,8 @@ kirkwood_dma_conf_mbus_windows(void __iomem *base, int win,
}
}
static int kirkwood_dma_open(struct snd_pcm_substream *substream)
static int kirkwood_dma_open(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
int err;
struct snd_pcm_runtime *runtime = substream->runtime;
@ -160,7 +161,8 @@ static int kirkwood_dma_open(struct snd_pcm_substream *substream)
return 0;
}
static int kirkwood_dma_close(struct snd_pcm_substream *substream)
static int kirkwood_dma_close(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct kirkwood_dma_data *priv = kirkwood_priv(substream);
@ -180,8 +182,9 @@ static int kirkwood_dma_close(struct snd_pcm_substream *substream)
return 0;
}
static int kirkwood_dma_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
static int kirkwood_dma_hw_params(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_pcm_runtime *runtime = substream->runtime;
@ -191,13 +194,15 @@ static int kirkwood_dma_hw_params(struct snd_pcm_substream *substream,
return 0;
}
static int kirkwood_dma_hw_free(struct snd_pcm_substream *substream)
static int kirkwood_dma_hw_free(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
snd_pcm_set_runtime_buffer(substream, NULL);
return 0;
}
static int kirkwood_dma_prepare(struct snd_pcm_substream *substream)
static int kirkwood_dma_prepare(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct kirkwood_dma_data *priv = kirkwood_priv(substream);
@ -222,8 +227,9 @@ static int kirkwood_dma_prepare(struct snd_pcm_substream *substream)
return 0;
}
static snd_pcm_uframes_t kirkwood_dma_pointer(struct snd_pcm_substream
*substream)
static snd_pcm_uframes_t kirkwood_dma_pointer(
struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct kirkwood_dma_data *priv = kirkwood_priv(substream);
snd_pcm_uframes_t count;
@ -238,16 +244,6 @@ static snd_pcm_uframes_t kirkwood_dma_pointer(struct snd_pcm_substream
return count;
}
static const struct snd_pcm_ops kirkwood_dma_ops = {
.open = kirkwood_dma_open,
.close = kirkwood_dma_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = kirkwood_dma_hw_params,
.hw_free = kirkwood_dma_hw_free,
.prepare = kirkwood_dma_prepare,
.pointer = kirkwood_dma_pointer,
};
static int kirkwood_dma_preallocate_dma_buffer(struct snd_pcm *pcm,
int stream)
{
@ -267,7 +263,8 @@ static int kirkwood_dma_preallocate_dma_buffer(struct snd_pcm *pcm,
return 0;
}
static int kirkwood_dma_new(struct snd_soc_pcm_runtime *rtd)
static int kirkwood_dma_new(struct snd_soc_component *component,
struct snd_soc_pcm_runtime *rtd)
{
struct snd_card *card = rtd->card->snd_card;
struct snd_pcm *pcm = rtd->pcm;
@ -294,7 +291,8 @@ static int kirkwood_dma_new(struct snd_soc_pcm_runtime *rtd)
return 0;
}
static void kirkwood_dma_free_dma_buffers(struct snd_pcm *pcm)
static void kirkwood_dma_free_dma_buffers(struct snd_soc_component *component,
struct snd_pcm *pcm)
{
struct snd_pcm_substream *substream;
struct snd_dma_buffer *buf;
@ -316,7 +314,13 @@ static void kirkwood_dma_free_dma_buffers(struct snd_pcm *pcm)
const struct snd_soc_component_driver kirkwood_soc_component = {
.name = DRV_NAME,
.ops = &kirkwood_dma_ops,
.pcm_new = kirkwood_dma_new,
.pcm_free = kirkwood_dma_free_dma_buffers,
.open = kirkwood_dma_open,
.close = kirkwood_dma_close,
.ioctl = snd_soc_pcm_lib_ioctl,
.hw_params = kirkwood_dma_hw_params,
.hw_free = kirkwood_dma_hw_free,
.prepare = kirkwood_dma_prepare,
.pointer = kirkwood_dma_pointer,
.pcm_construct = kirkwood_dma_new,
.pcm_destruct = kirkwood_dma_free_dma_buffers,
};

View File

@ -77,11 +77,10 @@ int mtk_afe_add_sub_dai_control(struct snd_soc_component *component)
}
EXPORT_SYMBOL_GPL(mtk_afe_add_sub_dai_control);
static snd_pcm_uframes_t mtk_afe_pcm_pointer
(struct snd_pcm_substream *substream)
snd_pcm_uframes_t mtk_afe_pcm_pointer(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
struct mtk_base_afe_memif *memif = &afe->memif[rtd->cpu_dai->id];
const struct mtk_base_memif_data *memif_data = memif->data;
@ -111,18 +110,13 @@ static snd_pcm_uframes_t mtk_afe_pcm_pointer
POINTER_RETURN_FRAMES:
return bytes_to_frames(substream->runtime, pcm_ptr_bytes);
}
EXPORT_SYMBOL_GPL(mtk_afe_pcm_pointer);
const struct snd_pcm_ops mtk_afe_pcm_ops = {
.ioctl = snd_pcm_lib_ioctl,
.pointer = mtk_afe_pcm_pointer,
};
EXPORT_SYMBOL_GPL(mtk_afe_pcm_ops);
int mtk_afe_pcm_new(struct snd_soc_pcm_runtime *rtd)
int mtk_afe_pcm_new(struct snd_soc_component *component,
struct snd_soc_pcm_runtime *rtd)
{
size_t size;
struct snd_pcm *pcm = rtd->pcm;
struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
size = afe->mtk_afe_hardware->buffer_bytes_max;
@ -132,17 +126,19 @@ int mtk_afe_pcm_new(struct snd_soc_pcm_runtime *rtd)
}
EXPORT_SYMBOL_GPL(mtk_afe_pcm_new);
void mtk_afe_pcm_free(struct snd_pcm *pcm)
void mtk_afe_pcm_free(struct snd_soc_component *component,
struct snd_pcm *pcm)
{
snd_pcm_lib_preallocate_free_for_all(pcm);
}
EXPORT_SYMBOL_GPL(mtk_afe_pcm_free);
const struct snd_soc_component_driver mtk_afe_pcm_platform = {
.name = AFE_PCM_NAME,
.ops = &mtk_afe_pcm_ops,
.pcm_new = mtk_afe_pcm_new,
.pcm_free = mtk_afe_pcm_free,
.name = AFE_PCM_NAME,
.ioctl = snd_soc_pcm_lib_ioctl,
.pointer = mtk_afe_pcm_pointer,
.pcm_construct = mtk_afe_pcm_new,
.pcm_destruct = mtk_afe_pcm_free,
};
EXPORT_SYMBOL_GPL(mtk_afe_pcm_platform);

View File

@ -10,7 +10,6 @@
#define _MTK_AFE_PLATFORM_DRIVER_H_
#define AFE_PCM_NAME "mtk-afe-pcm"
extern const struct snd_pcm_ops mtk_afe_pcm_ops;
extern const struct snd_soc_component_driver mtk_afe_pcm_platform;
struct mtk_base_afe;
@ -18,9 +17,12 @@ struct snd_pcm;
struct snd_soc_component;
struct snd_soc_pcm_runtime;
int mtk_afe_pcm_new(struct snd_soc_pcm_runtime *rtd);
void mtk_afe_pcm_free(struct snd_pcm *pcm);
snd_pcm_uframes_t mtk_afe_pcm_pointer(struct snd_soc_component *component,
struct snd_pcm_substream *substream);
int mtk_afe_pcm_new(struct snd_soc_component *component,
struct snd_soc_pcm_runtime *rtd);
void mtk_afe_pcm_free(struct snd_soc_component *component,
struct snd_pcm *pcm);
int mtk_afe_combine_sub_dai(struct mtk_base_afe *afe);
int mtk_afe_add_sub_dai_control(struct snd_soc_component *component);

View File

@ -875,11 +875,9 @@ static const struct snd_pcm_hardware mtk_btcvsd_hardware = {
.fifo_size = 0,
};
static int mtk_pcm_btcvsd_open(struct snd_pcm_substream *substream)
static int mtk_pcm_btcvsd_open(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_component *component =
snd_soc_rtdcom_lookup(rtd, BTCVSD_SND_NAME);
struct mtk_btcvsd_snd *bt = snd_soc_component_get_drvdata(component);
int ret;
@ -899,11 +897,9 @@ static int mtk_pcm_btcvsd_open(struct snd_pcm_substream *substream)
return ret;
}
static int mtk_pcm_btcvsd_close(struct snd_pcm_substream *substream)
static int mtk_pcm_btcvsd_close(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_component *component =
snd_soc_rtdcom_lookup(rtd, BTCVSD_SND_NAME);
struct mtk_btcvsd_snd *bt = snd_soc_component_get_drvdata(component);
struct mtk_btcvsd_snd_stream *bt_stream = get_bt_stream(bt, substream);
@ -914,12 +910,10 @@ static int mtk_pcm_btcvsd_close(struct snd_pcm_substream *substream)
return 0;
}
static int mtk_pcm_btcvsd_hw_params(struct snd_pcm_substream *substream,
static int mtk_pcm_btcvsd_hw_params(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *hw_params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_component *component =
snd_soc_rtdcom_lookup(rtd, BTCVSD_SND_NAME);
struct mtk_btcvsd_snd *bt = snd_soc_component_get_drvdata(component);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
@ -934,11 +928,9 @@ static int mtk_pcm_btcvsd_hw_params(struct snd_pcm_substream *substream,
return 0;
}
static int mtk_pcm_btcvsd_hw_free(struct snd_pcm_substream *substream)
static int mtk_pcm_btcvsd_hw_free(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_component *component =
snd_soc_rtdcom_lookup(rtd, BTCVSD_SND_NAME);
struct mtk_btcvsd_snd *bt = snd_soc_component_get_drvdata(component);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
@ -947,11 +939,9 @@ static int mtk_pcm_btcvsd_hw_free(struct snd_pcm_substream *substream)
return 0;
}
static int mtk_pcm_btcvsd_prepare(struct snd_pcm_substream *substream)
static int mtk_pcm_btcvsd_prepare(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_component *component =
snd_soc_rtdcom_lookup(rtd, BTCVSD_SND_NAME);
struct mtk_btcvsd_snd *bt = snd_soc_component_get_drvdata(component);
struct mtk_btcvsd_snd_stream *bt_stream = get_bt_stream(bt, substream);
@ -961,11 +951,9 @@ static int mtk_pcm_btcvsd_prepare(struct snd_pcm_substream *substream)
return 0;
}
static int mtk_pcm_btcvsd_trigger(struct snd_pcm_substream *substream, int cmd)
static int mtk_pcm_btcvsd_trigger(struct snd_soc_component *component,
struct snd_pcm_substream *substream, int cmd)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_component *component =
snd_soc_rtdcom_lookup(rtd, BTCVSD_SND_NAME);
struct mtk_btcvsd_snd *bt = snd_soc_component_get_drvdata(component);
struct mtk_btcvsd_snd_stream *bt_stream = get_bt_stream(bt, substream);
int stream = substream->stream;
@ -993,12 +981,10 @@ static int mtk_pcm_btcvsd_trigger(struct snd_pcm_substream *substream, int cmd)
}
}
static snd_pcm_uframes_t mtk_pcm_btcvsd_pointer
(struct snd_pcm_substream *substream)
static snd_pcm_uframes_t mtk_pcm_btcvsd_pointer(
struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_component *component =
snd_soc_rtdcom_lookup(rtd, BTCVSD_SND_NAME);
struct mtk_btcvsd_snd *bt = snd_soc_component_get_drvdata(component);
struct mtk_btcvsd_snd_stream *bt_stream;
snd_pcm_uframes_t frame = 0;
@ -1044,13 +1030,11 @@ static snd_pcm_uframes_t mtk_pcm_btcvsd_pointer
return frame;
}
static int mtk_pcm_btcvsd_copy(struct snd_pcm_substream *substream,
static int mtk_pcm_btcvsd_copy(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
int channel, unsigned long pos,
void __user *buf, unsigned long count)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_component *component =
snd_soc_rtdcom_lookup(rtd, BTCVSD_SND_NAME);
struct mtk_btcvsd_snd *bt = snd_soc_component_get_drvdata(component);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
@ -1061,18 +1045,6 @@ static int mtk_pcm_btcvsd_copy(struct snd_pcm_substream *substream,
return 0;
}
static struct snd_pcm_ops mtk_btcvsd_ops = {
.open = mtk_pcm_btcvsd_open,
.close = mtk_pcm_btcvsd_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = mtk_pcm_btcvsd_hw_params,
.hw_free = mtk_pcm_btcvsd_hw_free,
.prepare = mtk_pcm_btcvsd_prepare,
.trigger = mtk_pcm_btcvsd_trigger,
.pointer = mtk_pcm_btcvsd_pointer,
.copy_user = mtk_pcm_btcvsd_copy,
};
/* kcontrol */
static const char *const btsco_band_str[] = {"NB", "WB"};
@ -1295,9 +1267,17 @@ static int mtk_btcvsd_snd_component_probe(struct snd_soc_component *component)
}
static const struct snd_soc_component_driver mtk_btcvsd_snd_platform = {
.name = BTCVSD_SND_NAME,
.ops = &mtk_btcvsd_ops,
.probe = mtk_btcvsd_snd_component_probe,
.name = BTCVSD_SND_NAME,
.probe = mtk_btcvsd_snd_component_probe,
.open = mtk_pcm_btcvsd_open,
.close = mtk_pcm_btcvsd_close,
.ioctl = snd_soc_pcm_lib_ioctl,
.hw_params = mtk_pcm_btcvsd_hw_params,
.hw_free = mtk_pcm_btcvsd_hw_free,
.prepare = mtk_pcm_btcvsd_prepare,
.trigger = mtk_pcm_btcvsd_trigger,
.pointer = mtk_pcm_btcvsd_pointer,
.copy_user = mtk_pcm_btcvsd_copy,
};
static int mtk_btcvsd_snd_probe(struct platform_device *pdev)

View File

@ -710,11 +710,12 @@ static int mt6797_afe_component_probe(struct snd_soc_component *component)
}
static const struct snd_soc_component_driver mt6797_afe_component = {
.name = AFE_PCM_NAME,
.ops = &mtk_afe_pcm_ops,
.pcm_new = mtk_afe_pcm_new,
.pcm_free = mtk_afe_pcm_free,
.probe = mt6797_afe_component_probe,
.name = AFE_PCM_NAME,
.probe = mt6797_afe_component_probe,
.ioctl = snd_soc_pcm_lib_ioctl,
.pointer = mtk_afe_pcm_pointer,
.pcm_construct = mtk_afe_pcm_new,
.pcm_destruct = mtk_afe_pcm_free,
};
static int mt6797_dai_memif_register(struct mtk_base_afe *afe)

View File

@ -11,6 +11,7 @@
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/pm_runtime.h>
#include <linux/reset.h>
#include "mt8183-afe-common.h"
#include "mt8183-afe-clk.h"
@ -1047,11 +1048,12 @@ static int mt8183_afe_component_probe(struct snd_soc_component *component)
}
static const struct snd_soc_component_driver mt8183_afe_component = {
.name = AFE_PCM_NAME,
.ops = &mtk_afe_pcm_ops,
.pcm_new = mtk_afe_pcm_new,
.pcm_free = mtk_afe_pcm_free,
.probe = mt8183_afe_component_probe,
.name = AFE_PCM_NAME,
.probe = mt8183_afe_component_probe,
.ioctl = snd_soc_pcm_lib_ioctl,
.pointer = mtk_afe_pcm_pointer,
.pcm_construct = mtk_afe_pcm_new,
.pcm_destruct = mtk_afe_pcm_free,
};
static int mt8183_dai_memif_register(struct mtk_base_afe *afe)
@ -1089,6 +1091,7 @@ static int mt8183_afe_pcm_dev_probe(struct platform_device *pdev)
struct mtk_base_afe *afe;
struct mt8183_afe_private *afe_priv;
struct device *dev;
struct reset_control *rstc;
int i, irq_id, ret;
afe = devm_kzalloc(&pdev->dev, sizeof(*afe), GFP_KERNEL);
@ -1126,6 +1129,19 @@ static int mt8183_afe_pcm_dev_probe(struct platform_device *pdev)
return ret;
}
rstc = devm_reset_control_get(dev, "audiosys");
if (IS_ERR(rstc)) {
ret = PTR_ERR(rstc);
dev_err(dev, "could not get audiosys reset:%d\n", ret);
return ret;
}
ret = reset_control_reset(rstc);
if (ret) {
dev_err(dev, "failed to trigger audio reset:%d\n", ret);
return ret;
}
/* enable clock for regcache get default value from hw */
afe_priv->pm_runtime_bypass_reg_ctl = true;
pm_runtime_get_sync(&pdev->dev);

View File

@ -70,7 +70,8 @@ static void __dma_enable(struct axg_fifo *fifo, bool enable)
enable ? CTRL0_DMA_EN : 0);
}
static int axg_fifo_pcm_trigger(struct snd_pcm_substream *ss, int cmd)
int axg_fifo_pcm_trigger(struct snd_soc_component *component,
struct snd_pcm_substream *ss, int cmd)
{
struct axg_fifo *fifo = axg_fifo_data(ss);
@ -91,8 +92,10 @@ static int axg_fifo_pcm_trigger(struct snd_pcm_substream *ss, int cmd)
return 0;
}
EXPORT_SYMBOL_GPL(axg_fifo_pcm_trigger);
static snd_pcm_uframes_t axg_fifo_pcm_pointer(struct snd_pcm_substream *ss)
snd_pcm_uframes_t axg_fifo_pcm_pointer(struct snd_soc_component *component,
struct snd_pcm_substream *ss)
{
struct axg_fifo *fifo = axg_fifo_data(ss);
struct snd_pcm_runtime *runtime = ss->runtime;
@ -102,9 +105,11 @@ static snd_pcm_uframes_t axg_fifo_pcm_pointer(struct snd_pcm_substream *ss)
return bytes_to_frames(runtime, addr - (unsigned int)runtime->dma_addr);
}
EXPORT_SYMBOL_GPL(axg_fifo_pcm_pointer);
static int axg_fifo_pcm_hw_params(struct snd_pcm_substream *ss,
struct snd_pcm_hw_params *params)
int axg_fifo_pcm_hw_params(struct snd_soc_component *component,
struct snd_pcm_substream *ss,
struct snd_pcm_hw_params *params)
{
struct snd_pcm_runtime *runtime = ss->runtime;
struct axg_fifo *fifo = axg_fifo_data(ss);
@ -132,15 +137,17 @@ static int axg_fifo_pcm_hw_params(struct snd_pcm_substream *ss,
return 0;
}
EXPORT_SYMBOL_GPL(axg_fifo_pcm_hw_params);
static int g12a_fifo_pcm_hw_params(struct snd_pcm_substream *ss,
struct snd_pcm_hw_params *params)
int g12a_fifo_pcm_hw_params(struct snd_soc_component *component,
struct snd_pcm_substream *ss,
struct snd_pcm_hw_params *params)
{
struct axg_fifo *fifo = axg_fifo_data(ss);
struct snd_pcm_runtime *runtime = ss->runtime;
int ret;
ret = axg_fifo_pcm_hw_params(ss, params);
ret = axg_fifo_pcm_hw_params(component, ss, params);
if (ret)
return ret;
@ -149,8 +156,10 @@ static int g12a_fifo_pcm_hw_params(struct snd_pcm_substream *ss,
return 0;
}
EXPORT_SYMBOL_GPL(g12a_fifo_pcm_hw_params);
static int axg_fifo_pcm_hw_free(struct snd_pcm_substream *ss)
int axg_fifo_pcm_hw_free(struct snd_soc_component *component,
struct snd_pcm_substream *ss)
{
struct axg_fifo *fifo = axg_fifo_data(ss);
@ -160,6 +169,7 @@ static int axg_fifo_pcm_hw_free(struct snd_pcm_substream *ss)
return snd_pcm_lib_free_pages(ss);
}
EXPORT_SYMBOL_GPL(axg_fifo_pcm_hw_free);
static void axg_fifo_ack_irq(struct axg_fifo *fifo, u8 mask)
{
@ -194,7 +204,8 @@ static irqreturn_t axg_fifo_pcm_irq_block(int irq, void *dev_id)
return IRQ_RETVAL(status);
}
static int axg_fifo_pcm_open(struct snd_pcm_substream *ss)
int axg_fifo_pcm_open(struct snd_soc_component *component,
struct snd_pcm_substream *ss)
{
struct axg_fifo *fifo = axg_fifo_data(ss);
struct device *dev = axg_fifo_dev(ss);
@ -250,8 +261,10 @@ static int axg_fifo_pcm_open(struct snd_pcm_substream *ss)
return ret;
}
EXPORT_SYMBOL_GPL(axg_fifo_pcm_open);
static int axg_fifo_pcm_close(struct snd_pcm_substream *ss)
int axg_fifo_pcm_close(struct snd_soc_component *component,
struct snd_pcm_substream *ss)
{
struct axg_fifo *fifo = axg_fifo_data(ss);
int ret;
@ -267,28 +280,7 @@ static int axg_fifo_pcm_close(struct snd_pcm_substream *ss)
return ret;
}
const struct snd_pcm_ops axg_fifo_pcm_ops = {
.open = axg_fifo_pcm_open,
.close = axg_fifo_pcm_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = axg_fifo_pcm_hw_params,
.hw_free = axg_fifo_pcm_hw_free,
.pointer = axg_fifo_pcm_pointer,
.trigger = axg_fifo_pcm_trigger,
};
EXPORT_SYMBOL_GPL(axg_fifo_pcm_ops);
const struct snd_pcm_ops g12a_fifo_pcm_ops = {
.open = axg_fifo_pcm_open,
.close = axg_fifo_pcm_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = g12a_fifo_pcm_hw_params,
.hw_free = axg_fifo_pcm_hw_free,
.pointer = axg_fifo_pcm_pointer,
.trigger = axg_fifo_pcm_trigger,
};
EXPORT_SYMBOL_GPL(g12a_fifo_pcm_ops);
EXPORT_SYMBOL_GPL(axg_fifo_pcm_close);
int axg_fifo_pcm_new(struct snd_soc_pcm_runtime *rtd, unsigned int type)
{

View File

@ -15,7 +15,7 @@ struct reset_control;
struct snd_soc_component_driver;
struct snd_soc_dai;
struct snd_soc_dai_driver;
struct snd_pcm_ops;
struct snd_soc_pcm_runtime;
#define AXG_FIFO_CH_MAX 128
@ -75,8 +75,22 @@ struct axg_fifo_match_data {
struct snd_soc_dai_driver *dai_drv;
};
extern const struct snd_pcm_ops axg_fifo_pcm_ops;
extern const struct snd_pcm_ops g12a_fifo_pcm_ops;
int axg_fifo_pcm_open(struct snd_soc_component *component,
struct snd_pcm_substream *ss);
int axg_fifo_pcm_close(struct snd_soc_component *component,
struct snd_pcm_substream *ss);
int axg_fifo_pcm_hw_params(struct snd_soc_component *component,
struct snd_pcm_substream *ss,
struct snd_pcm_hw_params *params);
int g12a_fifo_pcm_hw_params(struct snd_soc_component *component,
struct snd_pcm_substream *ss,
struct snd_pcm_hw_params *params);
int axg_fifo_pcm_hw_free(struct snd_soc_component *component,
struct snd_pcm_substream *ss);
snd_pcm_uframes_t axg_fifo_pcm_pointer(struct snd_soc_component *component,
struct snd_pcm_substream *ss);
int axg_fifo_pcm_trigger(struct snd_soc_component *component,
struct snd_pcm_substream *ss, int cmd);
int axg_fifo_pcm_new(struct snd_soc_pcm_runtime *rtd, unsigned int type);
int axg_fifo_probe(struct platform_device *pdev);

View File

@ -149,7 +149,13 @@ static const struct snd_soc_component_driver axg_frddr_component_drv = {
.num_dapm_widgets = ARRAY_SIZE(axg_frddr_dapm_widgets),
.dapm_routes = axg_frddr_dapm_routes,
.num_dapm_routes = ARRAY_SIZE(axg_frddr_dapm_routes),
.ops = &axg_fifo_pcm_ops
.open = axg_fifo_pcm_open,
.close = axg_fifo_pcm_close,
.ioctl = snd_soc_pcm_lib_ioctl,
.hw_params = axg_fifo_pcm_hw_params,
.hw_free = axg_fifo_pcm_hw_free,
.pointer = axg_fifo_pcm_pointer,
.trigger = axg_fifo_pcm_trigger,
};
static const struct axg_fifo_match_data axg_frddr_match_data = {
@ -267,7 +273,13 @@ static const struct snd_soc_component_driver g12a_frddr_component_drv = {
.num_dapm_widgets = ARRAY_SIZE(g12a_frddr_dapm_widgets),
.dapm_routes = g12a_frddr_dapm_routes,
.num_dapm_routes = ARRAY_SIZE(g12a_frddr_dapm_routes),
.ops = &g12a_fifo_pcm_ops
.open = axg_fifo_pcm_open,
.close = axg_fifo_pcm_close,
.ioctl = snd_soc_pcm_lib_ioctl,
.hw_params = g12a_fifo_pcm_hw_params,
.hw_free = axg_fifo_pcm_hw_free,
.pointer = axg_fifo_pcm_pointer,
.trigger = axg_fifo_pcm_trigger,
};
static const struct axg_fifo_match_data g12a_frddr_match_data = {
@ -331,7 +343,13 @@ static const struct snd_soc_component_driver sm1_frddr_component_drv = {
.num_dapm_widgets = ARRAY_SIZE(sm1_frddr_dapm_widgets),
.dapm_routes = g12a_frddr_dapm_routes,
.num_dapm_routes = ARRAY_SIZE(g12a_frddr_dapm_routes),
.ops = &g12a_fifo_pcm_ops
.open = axg_fifo_pcm_open,
.close = axg_fifo_pcm_close,
.ioctl = snd_soc_pcm_lib_ioctl,
.hw_params = g12a_fifo_pcm_hw_params,
.hw_free = axg_fifo_pcm_hw_free,
.pointer = axg_fifo_pcm_pointer,
.trigger = axg_fifo_pcm_trigger,
};
static const struct axg_fifo_match_data sm1_frddr_match_data = {

View File

@ -181,7 +181,13 @@ static const struct snd_soc_component_driver axg_toddr_component_drv = {
.num_dapm_widgets = ARRAY_SIZE(axg_toddr_dapm_widgets),
.dapm_routes = axg_toddr_dapm_routes,
.num_dapm_routes = ARRAY_SIZE(axg_toddr_dapm_routes),
.ops = &axg_fifo_pcm_ops
.open = axg_fifo_pcm_open,
.close = axg_fifo_pcm_close,
.ioctl = snd_soc_pcm_lib_ioctl,
.hw_params = axg_fifo_pcm_hw_params,
.hw_free = axg_fifo_pcm_hw_free,
.pointer = axg_fifo_pcm_pointer,
.trigger = axg_fifo_pcm_trigger,
};
static const struct axg_fifo_match_data axg_toddr_match_data = {
@ -214,7 +220,13 @@ static const struct snd_soc_component_driver g12a_toddr_component_drv = {
.num_dapm_widgets = ARRAY_SIZE(axg_toddr_dapm_widgets),
.dapm_routes = axg_toddr_dapm_routes,
.num_dapm_routes = ARRAY_SIZE(axg_toddr_dapm_routes),
.ops = &g12a_fifo_pcm_ops
.open = axg_fifo_pcm_open,
.close = axg_fifo_pcm_close,
.ioctl = snd_soc_pcm_lib_ioctl,
.hw_params = g12a_fifo_pcm_hw_params,
.hw_free = axg_fifo_pcm_hw_free,
.pointer = axg_fifo_pcm_pointer,
.trigger = axg_fifo_pcm_trigger,
};
static const struct axg_fifo_match_data g12a_toddr_match_data = {
@ -278,7 +290,13 @@ static const struct snd_soc_component_driver sm1_toddr_component_drv = {
.num_dapm_widgets = ARRAY_SIZE(sm1_toddr_dapm_widgets),
.dapm_routes = sm1_toddr_dapm_routes,
.num_dapm_routes = ARRAY_SIZE(sm1_toddr_dapm_routes),
.ops = &g12a_fifo_pcm_ops
.open = axg_fifo_pcm_open,
.close = axg_fifo_pcm_close,
.ioctl = snd_soc_pcm_lib_ioctl,
.hw_params = g12a_fifo_pcm_hw_params,
.hw_free = axg_fifo_pcm_hw_free,
.pointer = axg_fifo_pcm_pointer,
.trigger = axg_fifo_pcm_trigger,
};
static const struct axg_fifo_match_data sm1_toddr_match_data = {

View File

@ -55,8 +55,9 @@ static struct snd_pcm_hardware mmp_pcm_hardware[] = {
},
};
static int mmp_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
static int mmp_pcm_hw_params(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct dma_chan *chan = snd_dmaengine_pcm_get_chan(substream);
struct dma_slave_config slave_config;
@ -77,6 +78,18 @@ static int mmp_pcm_hw_params(struct snd_pcm_substream *substream,
return 0;
}
static int mmp_pcm_trigger(struct snd_soc_component *component,
struct snd_pcm_substream *substream, int cmd)
{
return snd_dmaengine_pcm_trigger(substream, cmd);
}
static snd_pcm_uframes_t mmp_pcm_pointer(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
return snd_dmaengine_pcm_pointer(substream);
}
static bool filter(struct dma_chan *chan, void *param)
{
struct mmp_dma_data *dma_data = param;
@ -94,10 +107,10 @@ static bool filter(struct dma_chan *chan, void *param)
return found;
}
static int mmp_pcm_open(struct snd_pcm_substream *substream)
static int mmp_pcm_open(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
struct platform_device *pdev = to_platform_device(component->dev);
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
struct mmp_dma_data dma_data;
@ -117,8 +130,15 @@ static int mmp_pcm_open(struct snd_pcm_substream *substream)
&dma_data);
}
static int mmp_pcm_mmap(struct snd_pcm_substream *substream,
struct vm_area_struct *vma)
static int mmp_pcm_close(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
return snd_dmaengine_pcm_close_release_chan(substream);
}
static int mmp_pcm_mmap(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
struct vm_area_struct *vma)
{
struct snd_pcm_runtime *runtime = substream->runtime;
unsigned long off = vma->vm_pgoff;
@ -129,17 +149,8 @@ static int mmp_pcm_mmap(struct snd_pcm_substream *substream,
vma->vm_end - vma->vm_start, vma->vm_page_prot);
}
static const struct snd_pcm_ops mmp_pcm_ops = {
.open = mmp_pcm_open,
.close = snd_dmaengine_pcm_close_release_chan,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = mmp_pcm_hw_params,
.trigger = snd_dmaengine_pcm_trigger,
.pointer = snd_dmaengine_pcm_pointer,
.mmap = mmp_pcm_mmap,
};
static void mmp_pcm_free_dma_buffers(struct snd_pcm *pcm)
static void mmp_pcm_free_dma_buffers(struct snd_soc_component *component,
struct snd_pcm *pcm)
{
struct snd_pcm_substream *substream;
struct snd_dma_buffer *buf;
@ -188,7 +199,8 @@ static int mmp_pcm_preallocate_dma_buffer(struct snd_pcm_substream *substream,
return 0;
}
static int mmp_pcm_new(struct snd_soc_pcm_runtime *rtd)
static int mmp_pcm_new(struct snd_soc_component *component,
struct snd_soc_pcm_runtime *rtd)
{
struct snd_pcm_substream *substream;
struct snd_pcm *pcm = rtd->pcm;
@ -205,15 +217,21 @@ static int mmp_pcm_new(struct snd_soc_pcm_runtime *rtd)
return 0;
err:
mmp_pcm_free_dma_buffers(pcm);
mmp_pcm_free_dma_buffers(component, pcm);
return ret;
}
static const struct snd_soc_component_driver mmp_soc_component = {
.name = DRV_NAME,
.ops = &mmp_pcm_ops,
.pcm_new = mmp_pcm_new,
.pcm_free = mmp_pcm_free_dma_buffers,
.open = mmp_pcm_open,
.close = mmp_pcm_close,
.ioctl = snd_soc_pcm_lib_ioctl,
.hw_params = mmp_pcm_hw_params,
.trigger = mmp_pcm_trigger,
.pointer = mmp_pcm_pointer,
.mmap = mmp_pcm_mmap,
.pcm_construct = mmp_pcm_new,
.pcm_destruct = mmp_pcm_free_dma_buffers,
};
static int mmp_pcm_probe(struct platform_device *pdev)

View File

@ -869,9 +869,17 @@ static struct snd_soc_dai_driver pxa_ssp_dai = {
static const struct snd_soc_component_driver pxa_ssp_component = {
.name = "pxa-ssp",
.ops = &pxa2xx_pcm_ops,
.pcm_new = pxa2xx_soc_pcm_new,
.pcm_free = pxa2xx_pcm_free_dma_buffers,
.pcm_construct = pxa2xx_soc_pcm_new,
.pcm_destruct = pxa2xx_soc_pcm_free,
.open = pxa2xx_soc_pcm_open,
.close = pxa2xx_soc_pcm_close,
.ioctl = snd_soc_pcm_lib_ioctl,
.hw_params = pxa2xx_soc_pcm_hw_params,
.hw_free = pxa2xx_soc_pcm_hw_free,
.prepare = pxa2xx_soc_pcm_prepare,
.trigger = pxa2xx_soc_pcm_trigger,
.pointer = pxa2xx_soc_pcm_pointer,
.mmap = pxa2xx_soc_pcm_mmap,
};
#ifdef CONFIG_OF

View File

@ -204,9 +204,17 @@ static struct snd_soc_dai_driver pxa_ac97_dai_driver[] = {
static const struct snd_soc_component_driver pxa_ac97_component = {
.name = "pxa-ac97",
.ops = &pxa2xx_pcm_ops,
.pcm_new = pxa2xx_soc_pcm_new,
.pcm_free = pxa2xx_pcm_free_dma_buffers,
.pcm_construct = pxa2xx_soc_pcm_new,
.pcm_destruct = pxa2xx_soc_pcm_free,
.open = pxa2xx_soc_pcm_open,
.close = pxa2xx_soc_pcm_close,
.ioctl = snd_soc_pcm_lib_ioctl,
.hw_params = pxa2xx_soc_pcm_hw_params,
.hw_free = pxa2xx_soc_pcm_hw_free,
.prepare = pxa2xx_soc_pcm_prepare,
.trigger = pxa2xx_soc_pcm_trigger,
.pointer = pxa2xx_soc_pcm_pointer,
.mmap = pxa2xx_soc_pcm_mmap,
};
#ifdef CONFIG_OF

View File

@ -360,9 +360,17 @@ static struct snd_soc_dai_driver pxa_i2s_dai = {
static const struct snd_soc_component_driver pxa_i2s_component = {
.name = "pxa-i2s",
.ops = &pxa2xx_pcm_ops,
.pcm_new = pxa2xx_soc_pcm_new,
.pcm_free = pxa2xx_pcm_free_dma_buffers,
.pcm_construct = pxa2xx_soc_pcm_new,
.pcm_destruct = pxa2xx_soc_pcm_free,
.open = pxa2xx_soc_pcm_open,
.close = pxa2xx_soc_pcm_close,
.ioctl = snd_soc_pcm_lib_ioctl,
.hw_params = pxa2xx_soc_pcm_hw_params,
.hw_free = pxa2xx_soc_pcm_hw_free,
.prepare = pxa2xx_soc_pcm_prepare,
.trigger = pxa2xx_soc_pcm_trigger,
.pointer = pxa2xx_soc_pcm_pointer,
.mmap = pxa2xx_soc_pcm_mmap,
};
static int pxa2xx_i2s_drv_probe(struct platform_device *pdev)

View File

@ -18,9 +18,17 @@
#include <sound/dmaengine_pcm.h>
static const struct snd_soc_component_driver pxa2xx_soc_platform = {
.ops = &pxa2xx_pcm_ops,
.pcm_new = pxa2xx_soc_pcm_new,
.pcm_free = pxa2xx_pcm_free_dma_buffers,
.pcm_construct = pxa2xx_soc_pcm_new,
.pcm_destruct = pxa2xx_soc_pcm_free,
.open = pxa2xx_soc_pcm_open,
.close = pxa2xx_soc_pcm_close,
.ioctl = snd_soc_pcm_lib_ioctl,
.hw_params = pxa2xx_soc_pcm_hw_params,
.hw_free = pxa2xx_soc_pcm_hw_free,
.prepare = pxa2xx_soc_pcm_prepare,
.trigger = pxa2xx_soc_pcm_trigger,
.pointer = pxa2xx_soc_pcm_pointer,
.mmap = pxa2xx_soc_pcm_mmap,
};
static int pxa2xx_soc_platform_probe(struct platform_device *pdev)

View File

@ -50,12 +50,12 @@ static const struct snd_pcm_hardware lpass_platform_pcm_hardware = {
.fifo_size = 0,
};
static int lpass_platform_pcmops_open(struct snd_pcm_substream *substream)
static int lpass_platform_pcmops_open(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
struct snd_soc_dai *cpu_dai = soc_runtime->cpu_dai;
struct snd_soc_component *component = snd_soc_rtdcom_lookup(soc_runtime, DRV_NAME);
struct lpass_data *drvdata = snd_soc_component_get_drvdata(component);
struct lpass_variant *v = drvdata->variant;
int ret, dma_ch, dir = substream->stream;
@ -105,11 +105,10 @@ static int lpass_platform_pcmops_open(struct snd_pcm_substream *substream)
return 0;
}
static int lpass_platform_pcmops_close(struct snd_pcm_substream *substream)
static int lpass_platform_pcmops_close(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
struct snd_soc_component *component = snd_soc_rtdcom_lookup(soc_runtime, DRV_NAME);
struct lpass_data *drvdata = snd_soc_component_get_drvdata(component);
struct lpass_variant *v = drvdata->variant;
struct lpass_pcm_data *data;
@ -122,11 +121,11 @@ static int lpass_platform_pcmops_close(struct snd_pcm_substream *substream)
return 0;
}
static int lpass_platform_pcmops_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
static int lpass_platform_pcmops_hw_params(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
struct snd_soc_component *component = snd_soc_rtdcom_lookup(soc_runtime, DRV_NAME);
struct lpass_data *drvdata = snd_soc_component_get_drvdata(component);
struct snd_pcm_runtime *rt = substream->runtime;
struct lpass_pcm_data *pcm_data = rt->private_data;
@ -216,10 +215,10 @@ static int lpass_platform_pcmops_hw_params(struct snd_pcm_substream *substream,
return 0;
}
static int lpass_platform_pcmops_hw_free(struct snd_pcm_substream *substream)
static int lpass_platform_pcmops_hw_free(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
struct snd_soc_component *component = snd_soc_rtdcom_lookup(soc_runtime, DRV_NAME);
struct lpass_data *drvdata = snd_soc_component_get_drvdata(component);
struct snd_pcm_runtime *rt = substream->runtime;
struct lpass_pcm_data *pcm_data = rt->private_data;
@ -236,11 +235,11 @@ static int lpass_platform_pcmops_hw_free(struct snd_pcm_substream *substream)
return ret;
}
static int lpass_platform_pcmops_prepare(struct snd_pcm_substream *substream)
static int lpass_platform_pcmops_prepare(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
struct snd_soc_component *component = snd_soc_rtdcom_lookup(soc_runtime, DRV_NAME);
struct lpass_data *drvdata = snd_soc_component_get_drvdata(component);
struct snd_pcm_runtime *rt = substream->runtime;
struct lpass_pcm_data *pcm_data = rt->private_data;
@ -288,11 +287,11 @@ static int lpass_platform_pcmops_prepare(struct snd_pcm_substream *substream)
return 0;
}
static int lpass_platform_pcmops_trigger(struct snd_pcm_substream *substream,
int cmd)
static int lpass_platform_pcmops_trigger(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
int cmd)
{
struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
struct snd_soc_component *component = snd_soc_rtdcom_lookup(soc_runtime, DRV_NAME);
struct lpass_data *drvdata = snd_soc_component_get_drvdata(component);
struct snd_pcm_runtime *rt = substream->runtime;
struct lpass_pcm_data *pcm_data = rt->private_data;
@ -363,10 +362,10 @@ static int lpass_platform_pcmops_trigger(struct snd_pcm_substream *substream,
}
static snd_pcm_uframes_t lpass_platform_pcmops_pointer(
struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
struct snd_soc_component *component = snd_soc_rtdcom_lookup(soc_runtime, DRV_NAME);
struct lpass_data *drvdata = snd_soc_component_get_drvdata(component);
struct snd_pcm_runtime *rt = substream->runtime;
struct lpass_pcm_data *pcm_data = rt->private_data;
@ -395,8 +394,9 @@ static snd_pcm_uframes_t lpass_platform_pcmops_pointer(
return bytes_to_frames(substream->runtime, curr_addr - base_addr);
}
static int lpass_platform_pcmops_mmap(struct snd_pcm_substream *substream,
struct vm_area_struct *vma)
static int lpass_platform_pcmops_mmap(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
struct vm_area_struct *vma)
{
struct snd_pcm_runtime *runtime = substream->runtime;
@ -405,18 +405,6 @@ static int lpass_platform_pcmops_mmap(struct snd_pcm_substream *substream,
runtime->dma_bytes);
}
static const struct snd_pcm_ops lpass_platform_pcm_ops = {
.open = lpass_platform_pcmops_open,
.close = lpass_platform_pcmops_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = lpass_platform_pcmops_hw_params,
.hw_free = lpass_platform_pcmops_hw_free,
.prepare = lpass_platform_pcmops_prepare,
.trigger = lpass_platform_pcmops_trigger,
.pointer = lpass_platform_pcmops_pointer,
.mmap = lpass_platform_pcmops_mmap,
};
static irqreturn_t lpass_dma_interrupt_handler(
struct snd_pcm_substream *substream,
struct lpass_data *drvdata,
@ -499,11 +487,11 @@ static irqreturn_t lpass_platform_lpaif_irq(int irq, void *data)
return IRQ_HANDLED;
}
static int lpass_platform_pcm_new(struct snd_soc_pcm_runtime *soc_runtime)
static int lpass_platform_pcm_new(struct snd_soc_component *component,
struct snd_soc_pcm_runtime *soc_runtime)
{
struct snd_pcm *pcm = soc_runtime->pcm;
struct snd_pcm_substream *psubstream, *csubstream;
struct snd_soc_component *component = snd_soc_rtdcom_lookup(soc_runtime, DRV_NAME);
int ret = -EINVAL;
size_t size = lpass_platform_pcm_hardware.buffer_bytes_max;
@ -535,7 +523,8 @@ static int lpass_platform_pcm_new(struct snd_soc_pcm_runtime *soc_runtime)
return 0;
}
static void lpass_platform_pcm_free(struct snd_pcm *pcm)
static void lpass_platform_pcm_free(struct snd_soc_component *component,
struct snd_pcm *pcm)
{
struct snd_pcm_substream *substream;
int i;
@ -552,9 +541,18 @@ static void lpass_platform_pcm_free(struct snd_pcm *pcm)
static const struct snd_soc_component_driver lpass_component_driver = {
.name = DRV_NAME,
.pcm_new = lpass_platform_pcm_new,
.pcm_free = lpass_platform_pcm_free,
.ops = &lpass_platform_pcm_ops,
.open = lpass_platform_pcmops_open,
.close = lpass_platform_pcmops_close,
.ioctl = snd_soc_pcm_lib_ioctl,
.hw_params = lpass_platform_pcmops_hw_params,
.hw_free = lpass_platform_pcmops_hw_free,
.prepare = lpass_platform_pcmops_prepare,
.trigger = lpass_platform_pcmops_trigger,
.pointer = lpass_platform_pcmops_pointer,
.mmap = lpass_platform_pcmops_mmap,
.pcm_construct = lpass_platform_pcm_new,
.pcm_destruct = lpass_platform_pcm_free,
};
int asoc_qcom_lpass_platform_register(struct platform_device *pdev)

View File

@ -206,16 +206,16 @@ static void event_handler(uint32_t opcode, uint32_t token,
}
}
static int q6asm_dai_prepare(struct snd_pcm_substream *substream)
static int q6asm_dai_prepare(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
struct q6asm_dai_rtd *prtd = runtime->private_data;
struct snd_soc_component *c = snd_soc_rtdcom_lookup(soc_prtd, DRV_NAME);
struct q6asm_dai_data *pdata;
int ret, i;
pdata = snd_soc_component_get_drvdata(c);
pdata = snd_soc_component_get_drvdata(component);
if (!pdata)
return -EINVAL;
@ -294,7 +294,8 @@ static int q6asm_dai_prepare(struct snd_pcm_substream *substream)
return 0;
}
static int q6asm_dai_trigger(struct snd_pcm_substream *substream, int cmd)
static int q6asm_dai_trigger(struct snd_soc_component *component,
struct snd_pcm_substream *substream, int cmd)
{
int ret = 0;
struct snd_pcm_runtime *runtime = substream->runtime;
@ -322,21 +323,21 @@ static int q6asm_dai_trigger(struct snd_pcm_substream *substream, int cmd)
return ret;
}
static int q6asm_dai_open(struct snd_pcm_substream *substream)
static int q6asm_dai_open(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
struct snd_soc_dai *cpu_dai = soc_prtd->cpu_dai;
struct snd_soc_component *c = snd_soc_rtdcom_lookup(soc_prtd, DRV_NAME);
struct q6asm_dai_rtd *prtd;
struct q6asm_dai_data *pdata;
struct device *dev = c->dev;
struct device *dev = component->dev;
int ret = 0;
int stream_id;
stream_id = cpu_dai->driver->id;
pdata = snd_soc_component_get_drvdata(c);
pdata = snd_soc_component_get_drvdata(component);
if (!pdata) {
pr_err("Drv data not found ..\n");
return -EINVAL;
@ -414,7 +415,8 @@ static int q6asm_dai_open(struct snd_pcm_substream *substream)
return 0;
}
static int q6asm_dai_close(struct snd_pcm_substream *substream)
static int q6asm_dai_close(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
@ -435,7 +437,8 @@ static int q6asm_dai_close(struct snd_pcm_substream *substream)
return 0;
}
static snd_pcm_uframes_t q6asm_dai_pointer(struct snd_pcm_substream *substream)
static snd_pcm_uframes_t q6asm_dai_pointer(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
@ -447,22 +450,21 @@ static snd_pcm_uframes_t q6asm_dai_pointer(struct snd_pcm_substream *substream)
return bytes_to_frames(runtime, (prtd->pcm_irq_pos));
}
static int q6asm_dai_mmap(struct snd_pcm_substream *substream,
struct vm_area_struct *vma)
static int q6asm_dai_mmap(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
struct vm_area_struct *vma)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
struct snd_soc_component *c = snd_soc_rtdcom_lookup(soc_prtd, DRV_NAME);
struct device *dev = c->dev;
struct device *dev = component->dev;
return dma_mmap_coherent(dev, vma,
runtime->dma_area, runtime->dma_addr,
runtime->dma_bytes);
}
static int q6asm_dai_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
static int q6asm_dai_hw_params(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct q6asm_dai_rtd *prtd = runtime->private_data;
@ -482,17 +484,6 @@ static int q6asm_dai_hw_params(struct snd_pcm_substream *substream,
return 0;
}
static struct snd_pcm_ops q6asm_dai_ops = {
.open = q6asm_dai_open,
.hw_params = q6asm_dai_hw_params,
.close = q6asm_dai_close,
.ioctl = snd_pcm_lib_ioctl,
.prepare = q6asm_dai_prepare,
.trigger = q6asm_dai_trigger,
.pointer = q6asm_dai_pointer,
.mmap = q6asm_dai_mmap,
};
static void compress_event_handler(uint32_t opcode, uint32_t token,
uint32_t *payload, void *priv)
{
@ -800,15 +791,15 @@ static struct snd_compr_ops q6asm_dai_compr_ops = {
.ack = q6asm_dai_compr_ack,
};
static int q6asm_dai_pcm_new(struct snd_soc_pcm_runtime *rtd)
static int q6asm_dai_pcm_new(struct snd_soc_component *component,
struct snd_soc_pcm_runtime *rtd)
{
struct snd_pcm_substream *psubstream, *csubstream;
struct snd_soc_component *c = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
struct snd_pcm *pcm = rtd->pcm;
struct device *dev;
int size, ret;
dev = c->dev;
dev = component->dev;
size = q6asm_dai_hardware_playback.buffer_bytes_max;
psubstream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
if (psubstream) {
@ -835,7 +826,8 @@ static int q6asm_dai_pcm_new(struct snd_soc_pcm_runtime *rtd)
return 0;
}
static void q6asm_dai_pcm_free(struct snd_pcm *pcm)
static void q6asm_dai_pcm_free(struct snd_soc_component *component,
struct snd_pcm *pcm)
{
struct snd_pcm_substream *substream;
int i;
@ -852,9 +844,16 @@ static void q6asm_dai_pcm_free(struct snd_pcm *pcm)
static const struct snd_soc_component_driver q6asm_fe_dai_component = {
.name = DRV_NAME,
.ops = &q6asm_dai_ops,
.pcm_new = q6asm_dai_pcm_new,
.pcm_free = q6asm_dai_pcm_free,
.open = q6asm_dai_open,
.hw_params = q6asm_dai_hw_params,
.close = q6asm_dai_close,
.ioctl = snd_soc_pcm_lib_ioctl,
.prepare = q6asm_dai_prepare,
.trigger = q6asm_dai_trigger,
.pointer = q6asm_dai_pointer,
.mmap = q6asm_dai_mmap,
.pcm_construct = q6asm_dai_pcm_new,
.pcm_destruct = q6asm_dai_pcm_free,
.compr_ops = &q6asm_dai_compr_ops,
};

View File

@ -939,12 +939,12 @@ static const struct snd_soc_dapm_route intercon[] = {
};
static int routing_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
static int routing_hw_params(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_component *c = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
struct msm_routing_data *data = dev_get_drvdata(c->dev);
struct msm_routing_data *data = dev_get_drvdata(component->dev);
unsigned int be_id = rtd->cpu_dai->id;
struct session_data *session;
int path_type;
@ -980,10 +980,6 @@ static int routing_hw_params(struct snd_pcm_substream *substream,
return 0;
}
static struct snd_pcm_ops q6pcm_routing_ops = {
.hw_params = routing_hw_params,
};
static int msm_routing_probe(struct snd_soc_component *c)
{
int i;
@ -997,9 +993,9 @@ static int msm_routing_probe(struct snd_soc_component *c)
}
static const struct snd_soc_component_driver msm_soc_routing_component = {
.ops = &q6pcm_routing_ops,
.probe = msm_routing_probe,
.name = DRV_NAME,
.hw_params = routing_hw_params,
.dapm_widgets = msm_qdsp6_widgets,
.num_dapm_widgets = ARRAY_SIZE(msm_qdsp6_widgets),
.dapm_routes = intercon,

View File

@ -194,11 +194,13 @@ config SND_SOC_ODROID
help
Say Y here to enable audio support for the Odroid XU3/XU4.
config SND_SOC_ARNDALE_RT5631_ALC5631
tristate "Audio support for RT5631(ALC5631) on Arndale Board"
depends on I2C
select SND_SAMSUNG_I2S
select SND_SOC_RT5631
config SND_SOC_ARNDALE
tristate "Audio support for Arndale Board"
depends on I2C
select SND_SAMSUNG_I2S
select SND_SOC_RT5631
select MFD_WM8994
select SND_SOC_WM8994
config SND_SOC_SAMSUNG_TM2_WM5110
tristate "SoC I2S Audio support for WM5110 on TM2 board"

View File

@ -39,7 +39,7 @@ snd-soc-lowland-objs := lowland.o
snd-soc-littlemill-objs := littlemill.o
snd-soc-bells-objs := bells.o
snd-soc-odroid-objs := odroid.o
snd-soc-arndale-rt5631-objs := arndale_rt5631.o
snd-soc-arndale-objs := arndale.o
snd-soc-tm2-wm5110-objs := tm2_wm5110.o
obj-$(CONFIG_SND_SOC_SAMSUNG_JIVE_WM8750) += snd-soc-jive-wm8750.o
@ -62,5 +62,5 @@ obj-$(CONFIG_SND_SOC_LOWLAND) += snd-soc-lowland.o
obj-$(CONFIG_SND_SOC_LITTLEMILL) += snd-soc-littlemill.o
obj-$(CONFIG_SND_SOC_BELLS) += snd-soc-bells.o
obj-$(CONFIG_SND_SOC_ODROID) += snd-soc-odroid.o
obj-$(CONFIG_SND_SOC_ARNDALE_RT5631_ALC5631) += snd-soc-arndale-rt5631.o
obj-$(CONFIG_SND_SOC_ARNDALE) += snd-soc-arndale.o
obj-$(CONFIG_SND_SOC_SAMSUNG_TM2_WM5110) += snd-soc-tm2-wm5110.o

217
sound/soc/samsung/arndale.c Normal file
View File

@ -0,0 +1,217 @@
// SPDX-License-Identifier: GPL-2.0+
//
// Copyright (c) 2014, Insignal Co., Ltd.
//
// Author: Claude <claude@insginal.co.kr>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <sound/soc.h>
#include <sound/soc-dapm.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include "../codecs/wm8994.h"
#include "i2s.h"
static int arndale_rt5631_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
struct snd_soc_dai *codec_dai = rtd->codec_dai;
int rfs, ret;
unsigned long rclk;
rfs = 256;
rclk = params_rate(params) * rfs;
ret = snd_soc_dai_set_sysclk(cpu_dai, SAMSUNG_I2S_CDCLK,
0, SND_SOC_CLOCK_OUT);
if (ret < 0)
return ret;
ret = snd_soc_dai_set_sysclk(cpu_dai, SAMSUNG_I2S_RCLKSRC_0,
0, SND_SOC_CLOCK_OUT);
if (ret < 0)
return ret;
ret = snd_soc_dai_set_sysclk(codec_dai, 0, rclk, SND_SOC_CLOCK_OUT);
if (ret < 0)
return ret;
return 0;
}
static struct snd_soc_ops arndale_rt5631_ops = {
.hw_params = arndale_rt5631_hw_params,
};
static int arndale_wm1811_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *codec_dai = rtd->codec_dai;
unsigned int rfs, rclk;
/* Ensure AIF1CLK is >= 3 MHz for optimal performance */
if (params_width(params) == 24)
rfs = 384;
else if (params_rate(params) == 8000 || params_rate(params) == 11025)
rfs = 512;
else
rfs = 256;
rclk = params_rate(params) * rfs;
/*
* We add 1 to the frequency value to ensure proper EPLL setting
* for each audio sampling rate (see epll_24mhz_tbl in drivers/clk/
* samsung/clk-exynos5250.c for list of available EPLL rates).
* The CODEC uses clk API and the value will be rounded hence the MCLK1
* clock's frequency will still be exact multiple of the sample rate.
*/
return snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_MCLK1,
rclk + 1, SND_SOC_CLOCK_IN);
}
static struct snd_soc_ops arndale_wm1811_ops = {
.hw_params = arndale_wm1811_hw_params,
};
SND_SOC_DAILINK_DEFS(rt5631_hifi,
DAILINK_COMP_ARRAY(COMP_EMPTY()),
DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "rt5631-aif1")),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
static struct snd_soc_dai_link arndale_rt5631_dai[] = {
{
.name = "RT5631 HiFi",
.stream_name = "Primary",
.dai_fmt = SND_SOC_DAIFMT_I2S
| SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBS_CFS,
.ops = &arndale_rt5631_ops,
SND_SOC_DAILINK_REG(rt5631_hifi),
},
};
SND_SOC_DAILINK_DEFS(wm1811_hifi,
DAILINK_COMP_ARRAY(COMP_EMPTY()),
DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm8994-aif1")),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
static struct snd_soc_dai_link arndale_wm1811_dai[] = {
{
.name = "WM1811 HiFi",
.stream_name = "Primary",
.dai_fmt = SND_SOC_DAIFMT_I2S
| SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBM_CFM,
.ops = &arndale_wm1811_ops,
SND_SOC_DAILINK_REG(wm1811_hifi),
},
};
static struct snd_soc_card arndale_rt5631 = {
.name = "Arndale RT5631",
.owner = THIS_MODULE,
.dai_link = arndale_rt5631_dai,
.num_links = ARRAY_SIZE(arndale_rt5631_dai),
};
static struct snd_soc_card arndale_wm1811 = {
.name = "Arndale WM1811",
.owner = THIS_MODULE,
.dai_link = arndale_wm1811_dai,
.num_links = ARRAY_SIZE(arndale_wm1811_dai),
};
static void arndale_put_of_nodes(struct snd_soc_card *card)
{
struct snd_soc_dai_link *dai_link;
int i;
for_each_card_prelinks(card, i, dai_link) {
of_node_put(dai_link->cpus->of_node);
of_node_put(dai_link->codecs->of_node);
}
}
static int arndale_audio_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct snd_soc_card *card;
struct snd_soc_dai_link *dai_link;
int ret;
card = (struct snd_soc_card *)of_device_get_match_data(&pdev->dev);
card->dev = &pdev->dev;
dai_link = card->dai_link;
dai_link->cpus->of_node = of_parse_phandle(np, "samsung,audio-cpu", 0);
if (!dai_link->cpus->of_node) {
dev_err(&pdev->dev,
"Property 'samsung,audio-cpu' missing or invalid\n");
return -EINVAL;
}
if (!dai_link->platforms->name)
dai_link->platforms->of_node = dai_link->cpus->of_node;
dai_link->codecs->of_node = of_parse_phandle(np, "samsung,audio-codec", 0);
if (!dai_link->codecs->of_node) {
dev_err(&pdev->dev,
"Property 'samsung,audio-codec' missing or invalid\n");
ret = -EINVAL;
goto err_put_of_nodes;
}
ret = devm_snd_soc_register_card(card->dev, card);
if (ret) {
dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret);
goto err_put_of_nodes;
}
return 0;
err_put_of_nodes:
arndale_put_of_nodes(card);
return ret;
}
static int arndale_audio_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
arndale_put_of_nodes(card);
return 0;
}
static const struct of_device_id arndale_audio_of_match[] = {
{ .compatible = "samsung,arndale-rt5631", .data = &arndale_rt5631 },
{ .compatible = "samsung,arndale-alc5631", .data = &arndale_rt5631 },
{ .compatible = "samsung,arndale-wm1811", .data = &arndale_wm1811 },
{},
};
MODULE_DEVICE_TABLE(of, arndale_audio_of_match);
static struct platform_driver arndale_audio_driver = {
.driver = {
.name = "arndale-audio",
.pm = &snd_soc_pm_ops,
.of_match_table = arndale_audio_of_match,
},
.probe = arndale_audio_probe,
.remove = arndale_audio_remove,
};
module_platform_driver(arndale_audio_driver);
MODULE_AUTHOR("Claude <claude@insignal.co.kr>");
MODULE_DESCRIPTION("ALSA SoC Driver for Arndale Board");
MODULE_LICENSE("GPL");

View File

@ -1,164 +0,0 @@
// SPDX-License-Identifier: GPL-2.0+
//
// Copyright (c) 2014, Insignal Co., Ltd.
//
// Author: Claude <claude@insginal.co.kr>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <sound/soc.h>
#include <sound/soc-dapm.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include "i2s.h"
static int arndale_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
struct snd_soc_dai *codec_dai = rtd->codec_dai;
int rfs, ret;
unsigned long rclk;
rfs = 256;
rclk = params_rate(params) * rfs;
ret = snd_soc_dai_set_sysclk(cpu_dai, SAMSUNG_I2S_CDCLK,
0, SND_SOC_CLOCK_OUT);
if (ret < 0)
return ret;
ret = snd_soc_dai_set_sysclk(cpu_dai, SAMSUNG_I2S_RCLKSRC_0,
0, SND_SOC_CLOCK_OUT);
if (ret < 0)
return ret;
ret = snd_soc_dai_set_sysclk(codec_dai, 0, rclk, SND_SOC_CLOCK_OUT);
if (ret < 0)
return ret;
return 0;
}
static struct snd_soc_ops arndale_ops = {
.hw_params = arndale_hw_params,
};
SND_SOC_DAILINK_DEFS(rt5631_hifi,
DAILINK_COMP_ARRAY(COMP_EMPTY()),
DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "rt5631-hifi")),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
static struct snd_soc_dai_link arndale_rt5631_dai[] = {
{
.name = "RT5631 HiFi",
.stream_name = "Primary",
.dai_fmt = SND_SOC_DAIFMT_I2S
| SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBS_CFS,
.ops = &arndale_ops,
SND_SOC_DAILINK_REG(rt5631_hifi),
},
};
static struct snd_soc_card arndale_rt5631 = {
.name = "Arndale RT5631",
.owner = THIS_MODULE,
.dai_link = arndale_rt5631_dai,
.num_links = ARRAY_SIZE(arndale_rt5631_dai),
};
static void arndale_put_of_nodes(struct snd_soc_card *card)
{
struct snd_soc_dai_link *dai_link;
int i;
for_each_card_prelinks(card, i, dai_link) {
of_node_put(dai_link->cpus->of_node);
of_node_put(dai_link->codecs->of_node);
}
}
static int arndale_audio_probe(struct platform_device *pdev)
{
int n, ret;
struct device_node *np = pdev->dev.of_node;
struct snd_soc_card *card = &arndale_rt5631;
card->dev = &pdev->dev;
for (n = 0; np && n < ARRAY_SIZE(arndale_rt5631_dai); n++) {
if (!arndale_rt5631_dai[n].cpus->dai_name) {
arndale_rt5631_dai[n].cpus->of_node = of_parse_phandle(np,
"samsung,audio-cpu", n);
if (!arndale_rt5631_dai[n].cpus->of_node) {
dev_err(&pdev->dev,
"Property 'samsung,audio-cpu' missing or invalid\n");
return -EINVAL;
}
}
if (!arndale_rt5631_dai[n].platforms->name)
arndale_rt5631_dai[n].platforms->of_node =
arndale_rt5631_dai[n].cpus->of_node;
arndale_rt5631_dai[n].codecs->name = NULL;
arndale_rt5631_dai[n].codecs->of_node = of_parse_phandle(np,
"samsung,audio-codec", n);
if (!arndale_rt5631_dai[0].codecs->of_node) {
dev_err(&pdev->dev,
"Property 'samsung,audio-codec' missing or invalid\n");
ret = -EINVAL;
goto err_put_of_nodes;
}
}
ret = devm_snd_soc_register_card(card->dev, card);
if (ret) {
dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", ret);
goto err_put_of_nodes;
}
return 0;
err_put_of_nodes:
arndale_put_of_nodes(card);
return ret;
}
static int arndale_audio_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
arndale_put_of_nodes(card);
return 0;
}
static const struct of_device_id samsung_arndale_rt5631_of_match[] __maybe_unused = {
{ .compatible = "samsung,arndale-rt5631", },
{ .compatible = "samsung,arndale-alc5631", },
{},
};
MODULE_DEVICE_TABLE(of, samsung_arndale_rt5631_of_match);
static struct platform_driver arndale_audio_driver = {
.driver = {
.name = "arndale-audio",
.pm = &snd_soc_pm_ops,
.of_match_table = of_match_ptr(samsung_arndale_rt5631_of_match),
},
.probe = arndale_audio_probe,
.remove = arndale_audio_remove,
};
module_platform_driver(arndale_audio_driver);
MODULE_AUTHOR("Claude <claude@insignal.co.kr>");
MODULE_DESCRIPTION("ALSA SoC Driver for Arndale Board");
MODULE_LICENSE("GPL");

View File

@ -137,8 +137,9 @@ static void idma_done(void *id, int bytes_xfer)
snd_pcm_period_elapsed(substream);
}
static int idma_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
static int idma_hw_params(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct idma_ctrl *prtd = substream->runtime->private_data;
@ -163,14 +164,16 @@ static int idma_hw_params(struct snd_pcm_substream *substream,
return 0;
}
static int idma_hw_free(struct snd_pcm_substream *substream)
static int idma_hw_free(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
snd_pcm_set_runtime_buffer(substream, NULL);
return 0;
}
static int idma_prepare(struct snd_pcm_substream *substream)
static int idma_prepare(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct idma_ctrl *prtd = substream->runtime->private_data;
@ -183,7 +186,8 @@ static int idma_prepare(struct snd_pcm_substream *substream)
return 0;
}
static int idma_trigger(struct snd_pcm_substream *substream, int cmd)
static int idma_trigger(struct snd_soc_component *component,
struct snd_pcm_substream *substream, int cmd)
{
struct idma_ctrl *prtd = substream->runtime->private_data;
int ret = 0;
@ -216,7 +220,8 @@ static int idma_trigger(struct snd_pcm_substream *substream, int cmd)
}
static snd_pcm_uframes_t
idma_pointer(struct snd_pcm_substream *substream)
idma_pointer(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct idma_ctrl *prtd = runtime->private_data;
@ -233,7 +238,8 @@ static snd_pcm_uframes_t
return bytes_to_frames(substream->runtime, res);
}
static int idma_mmap(struct snd_pcm_substream *substream,
static int idma_mmap(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
struct vm_area_struct *vma)
{
struct snd_pcm_runtime *runtime = substream->runtime;
@ -278,7 +284,8 @@ static irqreturn_t iis_irq(int irqno, void *dev_id)
return IRQ_HANDLED;
}
static int idma_open(struct snd_pcm_substream *substream)
static int idma_open(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct idma_ctrl *prtd;
@ -304,7 +311,8 @@ static int idma_open(struct snd_pcm_substream *substream)
return 0;
}
static int idma_close(struct snd_pcm_substream *substream)
static int idma_close(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct idma_ctrl *prtd = runtime->private_data;
@ -319,19 +327,8 @@ static int idma_close(struct snd_pcm_substream *substream)
return 0;
}
static const struct snd_pcm_ops idma_ops = {
.open = idma_open,
.close = idma_close,
.ioctl = snd_pcm_lib_ioctl,
.trigger = idma_trigger,
.pointer = idma_pointer,
.mmap = idma_mmap,
.hw_params = idma_hw_params,
.hw_free = idma_hw_free,
.prepare = idma_prepare,
};
static void idma_free(struct snd_pcm *pcm)
static void idma_free(struct snd_soc_component *component,
struct snd_pcm *pcm)
{
struct snd_pcm_substream *substream;
struct snd_dma_buffer *buf;
@ -367,7 +364,8 @@ static int preallocate_idma_buffer(struct snd_pcm *pcm, int stream)
return 0;
}
static int idma_new(struct snd_soc_pcm_runtime *rtd)
static int idma_new(struct snd_soc_component *component,
struct snd_soc_pcm_runtime *rtd)
{
struct snd_card *card = rtd->card->snd_card;
struct snd_pcm *pcm = rtd->pcm;
@ -394,9 +392,17 @@ void idma_reg_addr_init(void __iomem *regs, dma_addr_t addr)
EXPORT_SYMBOL_GPL(idma_reg_addr_init);
static const struct snd_soc_component_driver asoc_idma_platform = {
.ops = &idma_ops,
.pcm_new = idma_new,
.pcm_free = idma_free,
.open = idma_open,
.close = idma_close,
.ioctl = snd_soc_pcm_lib_ioctl,
.trigger = idma_trigger,
.pointer = idma_pointer,
.mmap = idma_mmap,
.hw_params = idma_hw_params,
.hw_free = idma_hw_free,
.prepare = idma_prepare,
.pcm_construct = idma_new,
.pcm_destruct = idma_free,
};
static int asoc_idma_platform_probe(struct platform_device *pdev)

View File

@ -115,7 +115,8 @@ static void camelot_rxdma(void *data)
snd_pcm_period_elapsed(cam->rx_ss);
}
static int camelot_pcm_open(struct snd_pcm_substream *substream)
static int camelot_pcm_open(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct camelot_pcm *cam = &cam_pcm_data[rtd->cpu_dai->id];
@ -148,7 +149,8 @@ static int camelot_pcm_open(struct snd_pcm_substream *substream)
return 0;
}
static int camelot_pcm_close(struct snd_pcm_substream *substream)
static int camelot_pcm_close(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct camelot_pcm *cam = &cam_pcm_data[rtd->cpu_dai->id];
@ -168,7 +170,8 @@ static int camelot_pcm_close(struct snd_pcm_substream *substream)
return 0;
}
static int camelot_hw_params(struct snd_pcm_substream *substream,
static int camelot_hw_params(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *hw_params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
@ -191,12 +194,14 @@ static int camelot_hw_params(struct snd_pcm_substream *substream,
return 0;
}
static int camelot_hw_free(struct snd_pcm_substream *substream)
static int camelot_hw_free(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
return snd_pcm_lib_free_pages(substream);
}
static int camelot_prepare(struct snd_pcm_substream *substream)
static int camelot_prepare(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
@ -244,7 +249,8 @@ static inline void dmabrg_rec_dma_stop(struct camelot_pcm *cam)
BRGREG(BRGACR) = acr | ACR_RDS;
}
static int camelot_trigger(struct snd_pcm_substream *substream, int cmd)
static int camelot_trigger(struct snd_soc_component *component,
struct snd_pcm_substream *substream, int cmd)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct camelot_pcm *cam = &cam_pcm_data[rtd->cpu_dai->id];
@ -270,7 +276,8 @@ static int camelot_trigger(struct snd_pcm_substream *substream, int cmd)
return 0;
}
static snd_pcm_uframes_t camelot_pos(struct snd_pcm_substream *substream)
static snd_pcm_uframes_t camelot_pos(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
@ -292,18 +299,8 @@ static snd_pcm_uframes_t camelot_pos(struct snd_pcm_substream *substream)
return bytes_to_frames(runtime, pos);
}
static const struct snd_pcm_ops camelot_pcm_ops = {
.open = camelot_pcm_open,
.close = camelot_pcm_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = camelot_hw_params,
.hw_free = camelot_hw_free,
.prepare = camelot_prepare,
.trigger = camelot_trigger,
.pointer = camelot_pos,
};
static int camelot_pcm_new(struct snd_soc_pcm_runtime *rtd)
static int camelot_pcm_new(struct snd_soc_component *component,
struct snd_soc_pcm_runtime *rtd)
{
struct snd_pcm *pcm = rtd->pcm;
@ -319,8 +316,15 @@ static int camelot_pcm_new(struct snd_soc_pcm_runtime *rtd)
}
static const struct snd_soc_component_driver sh7760_soc_component = {
.ops = &camelot_pcm_ops,
.pcm_new = camelot_pcm_new,
.open = camelot_pcm_open,
.close = camelot_pcm_close,
.ioctl = snd_soc_pcm_lib_ioctl,
.hw_params = camelot_hw_params,
.hw_free = camelot_hw_free,
.prepare = camelot_prepare,
.trigger = camelot_trigger,
.pointer = camelot_pos,
.pcm_construct = camelot_pcm_new,
};
static int sh7760_soc_platform_probe(struct platform_device *pdev)

View File

@ -1718,7 +1718,8 @@ static const struct snd_pcm_hardware fsi_pcm_hardware = {
.fifo_size = 256,
};
static int fsi_pcm_open(struct snd_pcm_substream *substream)
static int fsi_pcm_open(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
int ret = 0;
@ -1731,19 +1732,22 @@ static int fsi_pcm_open(struct snd_pcm_substream *substream)
return ret;
}
static int fsi_hw_params(struct snd_pcm_substream *substream,
static int fsi_hw_params(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *hw_params)
{
return snd_pcm_lib_malloc_pages(substream,
params_buffer_bytes(hw_params));
}
static int fsi_hw_free(struct snd_pcm_substream *substream)
static int fsi_hw_free(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
return snd_pcm_lib_free_pages(substream);
}
static snd_pcm_uframes_t fsi_pointer(struct snd_pcm_substream *substream)
static snd_pcm_uframes_t fsi_pointer(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct fsi_priv *fsi = fsi_get_priv(substream);
struct fsi_stream *io = fsi_stream_get(fsi, substream);
@ -1751,14 +1755,6 @@ static snd_pcm_uframes_t fsi_pointer(struct snd_pcm_substream *substream)
return fsi_sample2frame(fsi, io->buff_sample_pos);
}
static const struct snd_pcm_ops fsi_pcm_ops = {
.open = fsi_pcm_open,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = fsi_hw_params,
.hw_free = fsi_hw_free,
.pointer = fsi_pointer,
};
/*
* snd_soc_component
*/
@ -1766,7 +1762,8 @@ static const struct snd_pcm_ops fsi_pcm_ops = {
#define PREALLOC_BUFFER (32 * 1024)
#define PREALLOC_BUFFER_MAX (32 * 1024)
static int fsi_pcm_new(struct snd_soc_pcm_runtime *rtd)
static int fsi_pcm_new(struct snd_soc_component *component,
struct snd_soc_pcm_runtime *rtd)
{
snd_pcm_lib_preallocate_pages_for_all(
rtd->pcm,
@ -1817,8 +1814,12 @@ static struct snd_soc_dai_driver fsi_soc_dai[] = {
static const struct snd_soc_component_driver fsi_soc_component = {
.name = "fsi",
.ops = &fsi_pcm_ops,
.pcm_new = fsi_pcm_new,
.open = fsi_pcm_open,
.ioctl = snd_soc_pcm_lib_ioctl,
.hw_params = fsi_hw_params,
.hw_free = fsi_hw_free,
.pointer = fsi_pointer,
.pcm_construct = fsi_pcm_new,
};
/*

View File

@ -1373,8 +1373,9 @@ static int rsnd_dai_probe(struct rsnd_priv *priv)
/*
* pcm ops
*/
static int rsnd_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *hw_params)
static int rsnd_hw_params(struct snd_soc_component *component,
struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *hw_params)
{
struct snd_soc_dai *dai = rsnd_substream_to_dai(substream);
struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
@ -1421,7 +1422,8 @@ static int rsnd_hw_params(struct snd_pcm_substream *substream,
params_buffer_bytes(hw_params));
}
static int rsnd_hw_free(struct snd_pcm_substream *substream)
static int rsnd_hw_free(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_soc_dai *dai = rsnd_substream_to_dai(substream);
struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
@ -1435,7 +1437,8 @@ static int rsnd_hw_free(struct snd_pcm_substream *substream)
return snd_pcm_lib_free_pages(substream);
}
static snd_pcm_uframes_t rsnd_pointer(struct snd_pcm_substream *substream)
static snd_pcm_uframes_t rsnd_pointer(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
struct snd_soc_dai *dai = rsnd_substream_to_dai(substream);
struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
@ -1447,13 +1450,6 @@ static snd_pcm_uframes_t rsnd_pointer(struct snd_pcm_substream *substream)
return pointer;
}
static const struct snd_pcm_ops rsnd_pcm_ops = {
.ioctl = snd_pcm_lib_ioctl,
.hw_params = rsnd_hw_params,
.hw_free = rsnd_hw_free,
.pointer = rsnd_pointer,
};
/*
* snd_kcontrol
*/
@ -1647,8 +1643,11 @@ int rsnd_kctrl_new(struct rsnd_mod *mod,
* snd_soc_component
*/
static const struct snd_soc_component_driver rsnd_soc_component = {
.ops = &rsnd_pcm_ops,
.name = "rsnd",
.ioctl = snd_soc_pcm_lib_ioctl,
.hw_params = rsnd_hw_params,
.hw_free = rsnd_hw_free,
.pointer = rsnd_pointer,
};
static int rsnd_rdai_continuance_probe(struct rsnd_priv *priv,

Some files were not shown because too many files have changed in this diff Show More