* [PATCH v2 0/4] ASoC: ti: davinci-mcasp: Add asynchronous mode support for McASP
@ 2026-02-03 0:36 Sen Wang
2026-02-03 0:37 ` [PATCH v2 1/4] ASoC: dt-bindings: davinci-mcasp: Add properties for asynchronous mode Sen Wang
` (6 more replies)
0 siblings, 7 replies; 8+ messages in thread
From: Sen Wang @ 2026-02-03 0:36 UTC (permalink / raw)
To: peter.ujfalusi, broonie, lgirdwood, perex, tiwai, robh, krzk+dt,
conor+dt
Cc: linux-sound, devicetree, linux-kernel, Sen Wang
This series adds asynchronous mode support to the McASP driver, which
enables independent configuration of bitclocks, frame sync, and audio
configurations between tx(playback) and rx(record). And achieves
simultaneous playback & record using different audio configurations.
It also adds two clean up patches to the McASP driver that disambiguate
and simplifies the logic which avoids the async enhancement from being
too convoluted to review and analyze.
The implementation is based on vendor documentation and patches tested in
both SK-AM62P-LP (sync mode, McASP slave) and AM62D-EVM
(async mode, McASP master, rx & tx has different TDM configs).
Testing verifies async mode functionality while maintaining backward
compatibility with the default sync mode.
Bootlog and Async mode tests on AM62D-EVM: [0]
[0]: https://gist.github.com/SenWang125/f31f9172b186d414695e37c8b9ef127d
Signed-off-by: Sen Wang <sen@ti.com>
Changes in v2:
- Corrected patch 1 subject title
- Retained original order of operation in patch 3
- Corrected code comments to use inclusive terminology in patch 4
Sen Wang (4):
ASoC: dt-bindings: davinci-mcasp: Add properties for asynchronous mode
ASoC: ti: davinci-mcasp: Disambiguate mcasp_is_synchronous function
ASoC: ti: davinci-mcasp: Streamline pdir behavior across rx & tx streams
ASoC: ti: davinci-mcasp: Add asynchronous mode support
.../bindings/sound/davinci-mcasp-audio.yaml | 71 ++-
include/linux/platform_data/davinci_asp.h | 3 +-
sound/soc/ti/davinci-mcasp.c | 510 ++++++++++++++----
sound/soc/ti/davinci-mcasp.h | 10 +
4 files changed, 481 insertions(+), 113 deletions(-)
base-commit: dbf8fe85a16a33d6b6bd01f2bc606fc017771465
--
2.43.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v2 1/4] ASoC: dt-bindings: davinci-mcasp: Add properties for asynchronous mode
2026-02-03 0:36 [PATCH v2 0/4] ASoC: ti: davinci-mcasp: Add asynchronous mode support for McASP Sen Wang
@ 2026-02-03 0:37 ` Sen Wang
2026-02-03 0:37 ` [PATCH v2 2/4] ASoC: ti: davinci-mcasp: Disambiguate mcasp_is_synchronous function Sen Wang
` (5 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Sen Wang @ 2026-02-03 0:37 UTC (permalink / raw)
To: peter.ujfalusi, broonie, lgirdwood, perex, tiwai, robh, krzk+dt,
conor+dt
Cc: linux-sound, devicetree, linux-kernel, Sen Wang
McASP supports the independent configuration of TX & RX clk and frame
sync registers. By default, the driver is configured in synchronous mode
where RX clock generator is disabled and it uses transmit clock signals as
bit clock and frame sync. Therefore add optional properties needed for
asynchronous mode.
Add ti,async-mode boolean binding to provide a way to decouple the default
behavior and allows for independent TX & RX clocking.
Add tdm-slots-rx uint32 binding to provide an alternative hardware
specifier stating the number of RX serializers.
The existing property tdm-slots will still dictate number of
TX serializers, and RX if tdm-slots-rx isn't given for backwards
compatibility.
Add auxclk-fs-ratio-rx which allows to specify the ratio just for RX.
The driver can be supplied with two different ratios
(auxclk-fs-ratio and auxclk-fs-ratio-rx in tandem) and achieve two
different sampling rates for tx & rx.
Signed-off-by: Sen Wang <sen@ti.com>
---
v2:
- Corrected patch subject title
.../bindings/sound/davinci-mcasp-audio.yaml | 71 +++++++++++++++++--
1 file changed, 66 insertions(+), 5 deletions(-)
diff --git a/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.yaml b/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.yaml
index beef193aaaeb..87559d0d079a 100644
--- a/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.yaml
+++ b/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.yaml
@@ -40,11 +40,33 @@ properties:
tdm-slots:
$ref: /schemas/types.yaml#/definitions/uint32
description:
- number of channels over one serializer
- the property is ignored in DIT mode
+ Number of channels over one serializer. This property
+ specifies the TX playback TDM slot count, along with default RX slot count
+ if tdm-slots-rx is not specified.
+ The property is ignored in DIT mode.
minimum: 2
maximum: 32
+ tdm-slots-rx:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description:
+ Number of RX capture channels over one serializer. If specified,
+ allows independent RX TDM slot count separate from TX. Requires
+ ti,async-mode to be enabled for independent TX/RX clock rates.
+ The property is ignored in DIT mode.
+ minimum: 2
+ maximum: 32
+
+ ti,async-mode:
+ description:
+ Specify to allow independent TX & RX clocking,
+ to enable audio playback & record with different sampling rate,
+ and different number of bits per frame.
+ if property is omitted, TX and RX will share same bit clock and frame clock signals,
+ thus RX need to use same bits per frame and sampling rate as TX in synchronous mode.
+ the property is ignored in DIT mode (as DIT is TX-only)
+ type: boolean
+
serial-dir:
description:
A list of serializer configuration
@@ -125,7 +147,21 @@ properties:
auxclk-fs-ratio:
$ref: /schemas/types.yaml#/definitions/uint32
- description: ratio of AUCLK and FS rate if applicable
+ description:
+ Ratio of AUCLK and FS rate if applicable. This property specifies
+ the TX ratio, along with default RX ratio if auxclk-fs-ratio-rx
+ is not specified.
+ When not specified, the inputted system clock frequency via set_sysclk
+ callback by the machine driver is used for divider calculation.
+
+ auxclk-fs-ratio-rx:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description:
+ Ratio of AUCLK and FS rate for RX. If specified, allows
+ for a different RX ratio. Requires ti,async-mode to be
+ enabled when the ratio differs from auxclk-fs-ratio.
+ When not specified, it defaults to the value of auxclk-fs-ratio.
+ The property is ignored in DIT mode.
gpio-controller: true
@@ -170,14 +206,38 @@ allOf:
- $ref: dai-common.yaml#
- if:
properties:
- opmode:
+ op-mode:
enum:
- 0
-
then:
required:
- tdm-slots
+ - if:
+ properties:
+ op-mode:
+ const: 1
+ then:
+ properties:
+ tdm-slots: false
+ tdm-slots-rx: false
+ ti,async-mode: false
+ auxclk-fs-ratio-rx: false
+
+ - if:
+ required:
+ - tdm-slots-rx
+ then:
+ required:
+ - ti,async-mode
+
+ - if:
+ required:
+ - auxclk-fs-ratio-rx
+ then:
+ required:
+ - ti,async-mode
+
unevaluatedProperties: false
examples:
@@ -190,6 +250,7 @@ examples:
interrupt-names = "tx", "rx";
op-mode = <0>; /* MCASP_IIS_MODE */
tdm-slots = <2>;
+ ti,async-mode;
dmas = <&main_udmap 0xc400>, <&main_udmap 0x4400>;
dma-names = "tx", "rx";
serial-dir = <
--
2.43.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v2 2/4] ASoC: ti: davinci-mcasp: Disambiguate mcasp_is_synchronous function
2026-02-03 0:36 [PATCH v2 0/4] ASoC: ti: davinci-mcasp: Add asynchronous mode support for McASP Sen Wang
2026-02-03 0:37 ` [PATCH v2 1/4] ASoC: dt-bindings: davinci-mcasp: Add properties for asynchronous mode Sen Wang
@ 2026-02-03 0:37 ` Sen Wang
2026-02-03 0:37 ` [PATCH v2 3/4] ASoC: ti: davinci-mcasp: Streamline pdir behavior across rx & tx streams Sen Wang
` (4 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Sen Wang @ 2026-02-03 0:37 UTC (permalink / raw)
To: peter.ujfalusi, broonie, lgirdwood, perex, tiwai, robh, krzk+dt,
conor+dt
Cc: linux-sound, devicetree, linux-kernel, Sen Wang
The current mcasp_is_synchronous() function does more than what it
proclaims, it also checks if McASP is a frame producer.
Therefore split the original function into two separate ones and
replace all occurrences with the new equivalent logic.
Signed-off-by: Sen Wang <sen@ti.com>
Acked-by: Peter Ujfalusi <peter.ujfalusi@gmail.com>
---
sound/soc/ti/davinci-mcasp.c | 21 ++++++++++++++-------
1 file changed, 14 insertions(+), 7 deletions(-)
diff --git a/sound/soc/ti/davinci-mcasp.c b/sound/soc/ti/davinci-mcasp.c
index 621a9d5f9377..aa14fc1c8011 100644
--- a/sound/soc/ti/davinci-mcasp.c
+++ b/sound/soc/ti/davinci-mcasp.c
@@ -179,10 +179,16 @@ static void mcasp_set_ctl_reg(struct davinci_mcasp *mcasp, u32 ctl_reg, u32 val)
static bool mcasp_is_synchronous(struct davinci_mcasp *mcasp)
{
- u32 rxfmctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_RXFMCTL_REG);
u32 aclkxctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_ACLKXCTL_REG);
- return !(aclkxctl & TX_ASYNC) && rxfmctl & AFSRE;
+ return !(aclkxctl & TX_ASYNC);
+}
+
+static bool mcasp_is_frame_producer(struct davinci_mcasp *mcasp)
+{
+ u32 rxfmctl = mcasp_get_reg(mcasp, DAVINCI_MCASP_RXFMCTL_REG);
+
+ return rxfmctl & AFSRE;
}
static inline void mcasp_set_clk_pdir(struct davinci_mcasp *mcasp, bool enable)
@@ -226,7 +232,7 @@ static void mcasp_start_rx(struct davinci_mcasp *mcasp)
* synchronously from the transmit clock and frame sync. We need to make
* sure that the TX signlas are enabled when starting reception.
*/
- if (mcasp_is_synchronous(mcasp)) {
+ if (mcasp_is_frame_producer(mcasp) && mcasp_is_synchronous(mcasp)) {
mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST);
mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST);
mcasp_set_clk_pdir(mcasp, true);
@@ -239,7 +245,7 @@ static void mcasp_start_rx(struct davinci_mcasp *mcasp)
mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXSMRST);
/* Release Frame Sync generator */
mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXFSRST);
- if (mcasp_is_synchronous(mcasp))
+ if (mcasp_is_frame_producer(mcasp) && mcasp_is_synchronous(mcasp))
mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXFSRST);
/* enable receive IRQs */
@@ -305,7 +311,7 @@ static void mcasp_stop_rx(struct davinci_mcasp *mcasp)
* In synchronous mode stop the TX clocks if no other stream is
* running
*/
- if (mcasp_is_synchronous(mcasp) && !mcasp->streams) {
+ if (mcasp_is_frame_producer(mcasp) && mcasp_is_synchronous(mcasp) && !mcasp->streams) {
mcasp_set_clk_pdir(mcasp, false);
mcasp_set_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, 0);
}
@@ -332,7 +338,7 @@ static void mcasp_stop_tx(struct davinci_mcasp *mcasp)
* In synchronous mode keep TX clocks running if the capture stream is
* still running.
*/
- if (mcasp_is_synchronous(mcasp) && mcasp->streams)
+ if (mcasp_is_frame_producer(mcasp) && mcasp_is_synchronous(mcasp) && mcasp->streams)
val = TXHCLKRST | TXCLKRST | TXFSRST;
else
mcasp_set_clk_pdir(mcasp, false);
@@ -1041,7 +1047,8 @@ static int mcasp_i2s_hw_param(struct davinci_mcasp *mcasp, int stream,
* not running already we need to configure the TX slots in
* order to have correct FSX on the bus
*/
- if (mcasp_is_synchronous(mcasp) && !mcasp->channels)
+ if (mcasp_is_frame_producer(mcasp) && mcasp_is_synchronous(mcasp) &&
+ !mcasp->channels)
mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG,
FSXMOD(total_slots), FSXMOD(0x1FF));
}
--
2.43.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v2 3/4] ASoC: ti: davinci-mcasp: Streamline pdir behavior across rx & tx streams
2026-02-03 0:36 [PATCH v2 0/4] ASoC: ti: davinci-mcasp: Add asynchronous mode support for McASP Sen Wang
2026-02-03 0:37 ` [PATCH v2 1/4] ASoC: dt-bindings: davinci-mcasp: Add properties for asynchronous mode Sen Wang
2026-02-03 0:37 ` [PATCH v2 2/4] ASoC: ti: davinci-mcasp: Disambiguate mcasp_is_synchronous function Sen Wang
@ 2026-02-03 0:37 ` Sen Wang
2026-02-03 0:37 ` [PATCH v2 4/4] ASoC: ti: davinci-mcasp: Add asynchronous mode support Sen Wang
` (3 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Sen Wang @ 2026-02-03 0:37 UTC (permalink / raw)
To: peter.ujfalusi, broonie, lgirdwood, perex, tiwai, robh, krzk+dt,
conor+dt
Cc: linux-sound, devicetree, linux-kernel, Sen Wang
Simplify the mcasp_set_clk_pdir caller convention in start/stop stream
function, to make it so that set_clk_pdir gets called regardless when
stream starts and also disables when stream ends.
Functionality-wise, everything remains the same as the previously skipped
calls are now either correctly configured
(when McASP is SND_SOC_DAIFMT_BP_FC - pdir needs to be enabled)
or called with a bitmask of zero (when McASP is SND_SOC_DAIFMT_BC_FC - pdir
gets disabled).
On brief regarding McASP Clock and Frame sync configurations, refer to [0].
[0]:TRM Section 12.1.1.4.2 https://www.ti.com/lit/ug/sprujd4a/sprujd4a.pdf
Signed-off-by: Sen Wang <sen@ti.com>
---
v2:
- Retained original order of operation in mcasp_stop_rx()
sound/soc/ti/davinci-mcasp.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/sound/soc/ti/davinci-mcasp.c b/sound/soc/ti/davinci-mcasp.c
index aa14fc1c8011..f9015b50e99d 100644
--- a/sound/soc/ti/davinci-mcasp.c
+++ b/sound/soc/ti/davinci-mcasp.c
@@ -235,8 +235,8 @@ static void mcasp_start_rx(struct davinci_mcasp *mcasp)
if (mcasp_is_frame_producer(mcasp) && mcasp_is_synchronous(mcasp)) {
mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST);
mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST);
- mcasp_set_clk_pdir(mcasp, true);
}
+ mcasp_set_clk_pdir(mcasp, true);
/* Activate serializer(s) */
mcasp_set_reg(mcasp, DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF);
@@ -311,10 +311,10 @@ static void mcasp_stop_rx(struct davinci_mcasp *mcasp)
* In synchronous mode stop the TX clocks if no other stream is
* running
*/
- if (mcasp_is_frame_producer(mcasp) && mcasp_is_synchronous(mcasp) && !mcasp->streams) {
+ if (!mcasp->streams)
mcasp_set_clk_pdir(mcasp, false);
+ if (mcasp_is_frame_producer(mcasp) && mcasp_is_synchronous(mcasp) && !mcasp->streams)
mcasp_set_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, 0);
- }
mcasp_set_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, 0);
mcasp_set_reg(mcasp, DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF);
@@ -340,7 +340,7 @@ static void mcasp_stop_tx(struct davinci_mcasp *mcasp)
*/
if (mcasp_is_frame_producer(mcasp) && mcasp_is_synchronous(mcasp) && mcasp->streams)
val = TXHCLKRST | TXCLKRST | TXFSRST;
- else
+ if (!mcasp->streams)
mcasp_set_clk_pdir(mcasp, false);
--
2.43.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v2 4/4] ASoC: ti: davinci-mcasp: Add asynchronous mode support
2026-02-03 0:36 [PATCH v2 0/4] ASoC: ti: davinci-mcasp: Add asynchronous mode support for McASP Sen Wang
` (2 preceding siblings ...)
2026-02-03 0:37 ` [PATCH v2 3/4] ASoC: ti: davinci-mcasp: Streamline pdir behavior across rx & tx streams Sen Wang
@ 2026-02-03 0:37 ` Sen Wang
2026-02-04 11:44 ` [PATCH v2 0/4] ASoC: ti: davinci-mcasp: Add asynchronous mode support for McASP Paresh Bhagat
` (2 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Sen Wang @ 2026-02-03 0:37 UTC (permalink / raw)
To: peter.ujfalusi, broonie, lgirdwood, perex, tiwai, robh, krzk+dt,
conor+dt
Cc: linux-sound, devicetree, linux-kernel, Sen Wang
McASP has dedicated clock & frame sync registers for both transmit
and receive. Currently McASP driver only supports synchronous behavior and
couples both TX & RX settings.
Add logic that enables asynchronous mode via ti,async-mode property. In
async mode, playback & record can be done simultaneously with different
audio configurations (tdm slots, tdm width, audio bit depth).
Note the ability to have different tx/rx DSP formats (i2s, dsp_a, etc.),
while possible in hardware, remains to be a gap as it require changes
to the corresponding machine driver interface.
Existing IIS (sync mode) and DIT mode logic remains mostly unchanged.
Exceptions are IIS mode logic that previously assumed sync mode, which has
now been made aware of the distinction. And shared logic across all modes
also now checks for McASP tx/rx-specific driver attributes. Those
attributes have been populated according to the original extent, ensuring
no divergence in functionality.
Constraints no longer applicable for async mode are skipped.
Clock selection options have also been added to include rx/tx-only clk_ids,
exposing independent configuration via the machine driver as well.
Note that asynchronous mode is not applicable for McASP in DIT mode,
which is a transmitter-only mode to interface w/ self-clocking formats.
Signed-off-by: Sen Wang <sen@ti.com>
Acked-by: Peter Ujfalusi <peter.ujfalusi@gmail.com>
---
v2:
- Corrected code comments to use inclusive terminology
include/linux/platform_data/davinci_asp.h | 3 +-
sound/soc/ti/davinci-mcasp.c | 489 +++++++++++++++++-----
sound/soc/ti/davinci-mcasp.h | 10 +
3 files changed, 401 insertions(+), 101 deletions(-)
diff --git a/include/linux/platform_data/davinci_asp.h b/include/linux/platform_data/davinci_asp.h
index b9c8520b4bd3..509c5592aab0 100644
--- a/include/linux/platform_data/davinci_asp.h
+++ b/include/linux/platform_data/davinci_asp.h
@@ -59,7 +59,8 @@ struct davinci_mcasp_pdata {
bool i2s_accurate_sck;
/* McASP specific fields */
- int tdm_slots;
+ int tdm_slots_tx;
+ int tdm_slots_rx;
u8 op_mode;
u8 dismod;
u8 num_serializer;
diff --git a/sound/soc/ti/davinci-mcasp.c b/sound/soc/ti/davinci-mcasp.c
index f9015b50e99d..b2788c4ce83c 100644
--- a/sound/soc/ti/davinci-mcasp.c
+++ b/sound/soc/ti/davinci-mcasp.c
@@ -70,6 +70,7 @@ struct davinci_mcasp_context {
struct davinci_mcasp_ruledata {
struct davinci_mcasp *mcasp;
int serializers;
+ int stream;
};
struct davinci_mcasp {
@@ -87,21 +88,27 @@ struct davinci_mcasp {
bool missing_audio_param;
/* McASP specific data */
- int tdm_slots;
+ int tdm_slots_tx;
+ int tdm_slots_rx;
u32 tdm_mask[2];
- int slot_width;
+ int slot_width_tx;
+ int slot_width_rx;
u8 op_mode;
u8 dismod;
u8 num_serializer;
u8 *serial_dir;
u8 version;
- u8 bclk_div;
+ u8 bclk_div_tx;
+ u8 bclk_div_rx;
int streams;
u32 irq_request[2];
- int sysclk_freq;
+ unsigned int sysclk_freq_tx;
+ unsigned int sysclk_freq_rx;
bool bclk_master;
- u32 auxclk_fs_ratio;
+ bool async_mode;
+ u32 auxclk_fs_ratio_tx;
+ u32 auxclk_fs_ratio_rx;
unsigned long pdir; /* Pin direction bitfield */
@@ -203,6 +210,27 @@ static inline void mcasp_set_clk_pdir(struct davinci_mcasp *mcasp, bool enable)
}
}
+static inline void mcasp_set_clk_pdir_stream(struct davinci_mcasp *mcasp,
+ int stream, bool enable)
+{
+ u32 bit, bit_end;
+
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ bit = PIN_BIT_ACLKX;
+ bit_end = PIN_BIT_AFSX + 1;
+ } else {
+ bit = PIN_BIT_ACLKR;
+ bit_end = PIN_BIT_AFSR + 1;
+ }
+
+ for_each_set_bit_from(bit, &mcasp->pdir, bit_end) {
+ if (enable)
+ mcasp_set_bits(mcasp, DAVINCI_MCASP_PDIR_REG, BIT(bit));
+ else
+ mcasp_clr_bits(mcasp, DAVINCI_MCASP_PDIR_REG, BIT(bit));
+ }
+}
+
static inline void mcasp_set_axr_pdir(struct davinci_mcasp *mcasp, bool enable)
{
u32 bit;
@@ -215,6 +243,36 @@ static inline void mcasp_set_axr_pdir(struct davinci_mcasp *mcasp, bool enable)
}
}
+static inline int mcasp_get_tdm_slots(struct davinci_mcasp *mcasp, int stream)
+{
+ return (stream == SNDRV_PCM_STREAM_PLAYBACK) ?
+ mcasp->tdm_slots_tx : mcasp->tdm_slots_rx;
+}
+
+static inline int mcasp_get_slot_width(struct davinci_mcasp *mcasp, int stream)
+{
+ return (stream == SNDRV_PCM_STREAM_PLAYBACK) ?
+ mcasp->slot_width_tx : mcasp->slot_width_rx;
+}
+
+static inline unsigned int mcasp_get_sysclk_freq(struct davinci_mcasp *mcasp, int stream)
+{
+ return (stream == SNDRV_PCM_STREAM_PLAYBACK) ?
+ mcasp->sysclk_freq_tx : mcasp->sysclk_freq_rx;
+}
+
+static inline unsigned int mcasp_get_bclk_div(struct davinci_mcasp *mcasp, int stream)
+{
+ return (stream == SNDRV_PCM_STREAM_PLAYBACK) ?
+ mcasp->bclk_div_tx : mcasp->bclk_div_rx;
+}
+
+static inline unsigned int mcasp_get_auxclk_fs_ratio(struct davinci_mcasp *mcasp, int stream)
+{
+ return (stream == SNDRV_PCM_STREAM_PLAYBACK) ?
+ mcasp->auxclk_fs_ratio_tx : mcasp->auxclk_fs_ratio_rx;
+}
+
static void mcasp_start_rx(struct davinci_mcasp *mcasp)
{
if (mcasp->rxnumevt) { /* enable FIFO */
@@ -230,13 +288,17 @@ static void mcasp_start_rx(struct davinci_mcasp *mcasp)
/*
* When ASYNC == 0 the transmit and receive sections operate
* synchronously from the transmit clock and frame sync. We need to make
- * sure that the TX signlas are enabled when starting reception.
+ * sure that the TX signals are enabled when starting reception,
+ * when the McASP is the producer.
*/
if (mcasp_is_frame_producer(mcasp) && mcasp_is_synchronous(mcasp)) {
mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST);
mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST);
}
- mcasp_set_clk_pdir(mcasp, true);
+ if (mcasp_is_synchronous(mcasp))
+ mcasp_set_clk_pdir(mcasp, true);
+ else
+ mcasp_set_clk_pdir_stream(mcasp, SNDRV_PCM_STREAM_CAPTURE, true);
/* Activate serializer(s) */
mcasp_set_reg(mcasp, DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF);
@@ -267,7 +329,10 @@ static void mcasp_start_tx(struct davinci_mcasp *mcasp)
/* Start clocks */
mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST);
mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST);
- mcasp_set_clk_pdir(mcasp, true);
+ if (mcasp_is_synchronous(mcasp))
+ mcasp_set_clk_pdir(mcasp, true);
+ else
+ mcasp_set_clk_pdir_stream(mcasp, SNDRV_PCM_STREAM_PLAYBACK, true);
/* Activate serializer(s) */
mcasp_set_reg(mcasp, DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF);
@@ -310,9 +375,17 @@ static void mcasp_stop_rx(struct davinci_mcasp *mcasp)
/*
* In synchronous mode stop the TX clocks if no other stream is
* running
+ * Otherwise in async mode only stop RX clocks
*/
- if (!mcasp->streams)
+ if (mcasp_is_synchronous(mcasp) && !mcasp->streams)
mcasp_set_clk_pdir(mcasp, false);
+ else if (!mcasp_is_synchronous(mcasp))
+ mcasp_set_clk_pdir_stream(mcasp, SNDRV_PCM_STREAM_CAPTURE, false);
+ /*
+ * When McASP is the producer and operating in synchronous mode,
+ * stop the transmit clocks if no other stream is running. As
+ * tx & rx operate synchronously from the transmit clock.
+ */
if (mcasp_is_frame_producer(mcasp) && mcasp_is_synchronous(mcasp) && !mcasp->streams)
mcasp_set_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, 0);
@@ -337,11 +410,14 @@ static void mcasp_stop_tx(struct davinci_mcasp *mcasp)
/*
* In synchronous mode keep TX clocks running if the capture stream is
* still running.
+ * Otherwise in async mode only stop TX clocks
*/
if (mcasp_is_frame_producer(mcasp) && mcasp_is_synchronous(mcasp) && mcasp->streams)
val = TXHCLKRST | TXCLKRST | TXFSRST;
- if (!mcasp->streams)
+ if (mcasp_is_synchronous(mcasp) && !mcasp->streams)
mcasp_set_clk_pdir(mcasp, false);
+ else if (!mcasp_is_synchronous(mcasp))
+ mcasp_set_clk_pdir_stream(mcasp, SNDRV_PCM_STREAM_PLAYBACK, false);
mcasp_set_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, val);
@@ -625,13 +701,39 @@ static int __davinci_mcasp_set_clkdiv(struct davinci_mcasp *mcasp, int div_id,
AHCLKRDIV(div - 1), AHCLKRDIV_MASK);
break;
+ case MCASP_CLKDIV_AUXCLK_TXONLY: /* MCLK divider for TX only */
+ mcasp_mod_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG,
+ AHCLKXDIV(div - 1), AHCLKXDIV_MASK);
+ break;
+
+ case MCASP_CLKDIV_AUXCLK_RXONLY: /* MCLK divider for RX only */
+ mcasp_mod_bits(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG,
+ AHCLKRDIV(div - 1), AHCLKRDIV_MASK);
+ break;
+
case MCASP_CLKDIV_BCLK: /* BCLK divider */
mcasp_mod_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG,
ACLKXDIV(div - 1), ACLKXDIV_MASK);
+ mcasp_mod_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG,
+ ACLKRDIV(div - 1), ACLKRDIV_MASK);
+ if (explicit) {
+ mcasp->bclk_div_tx = div;
+ mcasp->bclk_div_rx = div;
+ }
+ break;
+
+ case MCASP_CLKDIV_BCLK_TXONLY: /* BCLK divider for TX only */
+ mcasp_mod_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG,
+ ACLKXDIV(div - 1), ACLKXDIV_MASK);
+ if (explicit)
+ mcasp->bclk_div_tx = div;
+ break;
+
+ case MCASP_CLKDIV_BCLK_RXONLY: /* BCLK divider for RX only */
mcasp_mod_bits(mcasp, DAVINCI_MCASP_ACLKRCTL_REG,
ACLKRDIV(div - 1), ACLKRDIV_MASK);
if (explicit)
- mcasp->bclk_div = div;
+ mcasp->bclk_div_rx = div;
break;
case MCASP_CLKDIV_BCLK_FS_RATIO:
@@ -645,11 +747,33 @@ static int __davinci_mcasp_set_clkdiv(struct davinci_mcasp *mcasp, int div_id,
* tdm_slot width by dividing the ratio by the
* number of configured tdm slots.
*/
- mcasp->slot_width = div / mcasp->tdm_slots;
- if (div % mcasp->tdm_slots)
+ mcasp->slot_width_tx = div / mcasp->tdm_slots_tx;
+ if (div % mcasp->tdm_slots_tx)
dev_warn(mcasp->dev,
- "%s(): BCLK/LRCLK %d is not divisible by %d tdm slots",
- __func__, div, mcasp->tdm_slots);
+ "%s(): BCLK/LRCLK %d is not divisible by %d tx tdm slots",
+ __func__, div, mcasp->tdm_slots_tx);
+
+ mcasp->slot_width_rx = div / mcasp->tdm_slots_rx;
+ if (div % mcasp->tdm_slots_rx)
+ dev_warn(mcasp->dev,
+ "%s(): BCLK/LRCLK %d is not divisible by %d rx tdm slots",
+ __func__, div, mcasp->tdm_slots_rx);
+ break;
+
+ case MCASP_CLKDIV_BCLK_FS_RATIO_TXONLY:
+ mcasp->slot_width_tx = div / mcasp->tdm_slots_tx;
+ if (div % mcasp->tdm_slots_tx)
+ dev_warn(mcasp->dev,
+ "%s(): BCLK/LRCLK %d is not divisible by %d tx tdm slots",
+ __func__, div, mcasp->tdm_slots_tx);
+ break;
+
+ case MCASP_CLKDIV_BCLK_FS_RATIO_RXONLY:
+ mcasp->slot_width_rx = div / mcasp->tdm_slots_rx;
+ if (div % mcasp->tdm_slots_rx)
+ dev_warn(mcasp->dev,
+ "%s(): BCLK/LRCLK %d is not divisible by %d rx tdm slots",
+ __func__, div, mcasp->tdm_slots_rx);
break;
default:
@@ -683,6 +807,20 @@ static int davinci_mcasp_set_sysclk(struct snd_soc_dai *dai, int clk_id,
mcasp_clr_bits(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG,
AHCLKRE);
clear_bit(PIN_BIT_AHCLKX, &mcasp->pdir);
+ mcasp->sysclk_freq_tx = freq;
+ mcasp->sysclk_freq_rx = freq;
+ break;
+ case MCASP_CLK_HCLK_AHCLK_TXONLY:
+ mcasp_clr_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG,
+ AHCLKXE);
+ clear_bit(PIN_BIT_AHCLKX, &mcasp->pdir);
+ mcasp->sysclk_freq_tx = freq;
+ break;
+ case MCASP_CLK_HCLK_AHCLK_RXONLY:
+ mcasp_clr_bits(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG,
+ AHCLKRE);
+ clear_bit(PIN_BIT_AHCLKR, &mcasp->pdir);
+ mcasp->sysclk_freq_rx = freq;
break;
case MCASP_CLK_HCLK_AUXCLK:
mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG,
@@ -690,22 +828,56 @@ static int davinci_mcasp_set_sysclk(struct snd_soc_dai *dai, int clk_id,
mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG,
AHCLKRE);
set_bit(PIN_BIT_AHCLKX, &mcasp->pdir);
+ mcasp->sysclk_freq_tx = freq;
+ mcasp->sysclk_freq_rx = freq;
+ break;
+ case MCASP_CLK_HCLK_AUXCLK_TXONLY:
+ mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG,
+ AHCLKXE);
+ set_bit(PIN_BIT_AHCLKX, &mcasp->pdir);
+ mcasp->sysclk_freq_tx = freq;
+ break;
+ case MCASP_CLK_HCLK_AUXCLK_RXONLY:
+ mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG,
+ AHCLKRE);
+ set_bit(PIN_BIT_AHCLKR, &mcasp->pdir);
+ mcasp->sysclk_freq_rx = freq;
break;
default:
dev_err(mcasp->dev, "Invalid clk id: %d\n", clk_id);
goto out;
}
} else {
- /* Select AUXCLK as HCLK */
- mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXE);
- mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG, AHCLKRE);
- set_bit(PIN_BIT_AHCLKX, &mcasp->pdir);
+ /* McASP is clock master, select AUXCLK as HCLK */
+ switch (clk_id) {
+ case MCASP_CLK_HCLK_AUXCLK_TXONLY:
+ mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG,
+ AHCLKXE);
+ set_bit(PIN_BIT_AHCLKX, &mcasp->pdir);
+ mcasp->sysclk_freq_tx = freq;
+ break;
+ case MCASP_CLK_HCLK_AUXCLK_RXONLY:
+ mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG,
+ AHCLKRE);
+ set_bit(PIN_BIT_AHCLKR, &mcasp->pdir);
+ mcasp->sysclk_freq_rx = freq;
+ break;
+ default:
+ mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG,
+ AHCLKXE);
+ mcasp_set_bits(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG,
+ AHCLKRE);
+ set_bit(PIN_BIT_AHCLKX, &mcasp->pdir);
+ set_bit(PIN_BIT_AHCLKR, &mcasp->pdir);
+ mcasp->sysclk_freq_tx = freq;
+ mcasp->sysclk_freq_rx = freq;
+ break;
+ }
}
/*
* When AHCLK X/R is selected to be output it means that the HCLK is
* the same clock - coming via AUXCLK.
*/
- mcasp->sysclk_freq = freq;
out:
pm_runtime_put(mcasp->dev);
return 0;
@@ -717,9 +889,11 @@ static int davinci_mcasp_ch_constraint(struct davinci_mcasp *mcasp, int stream,
{
struct snd_pcm_hw_constraint_list *cl = &mcasp->chconstr[stream];
unsigned int *list = (unsigned int *) cl->list;
- int slots = mcasp->tdm_slots;
+ int slots;
int i, count = 0;
+ slots = mcasp_get_tdm_slots(mcasp, stream);
+
if (mcasp->tdm_mask[stream])
slots = hweight32(mcasp->tdm_mask[stream]);
@@ -784,27 +958,42 @@ static int davinci_mcasp_set_tdm_slot(struct snd_soc_dai *dai,
return -EINVAL;
}
- mcasp->tdm_slots = slots;
+ if (mcasp->async_mode) {
+ if (tx_mask) {
+ mcasp->tdm_slots_tx = slots;
+ mcasp->slot_width_tx = slot_width;
+ }
+ if (rx_mask) {
+ mcasp->tdm_slots_rx = slots;
+ mcasp->slot_width_rx = slot_width;
+ }
+ } else {
+ mcasp->tdm_slots_tx = slots;
+ mcasp->tdm_slots_rx = slots;
+ mcasp->slot_width_tx = slot_width;
+ mcasp->slot_width_rx = slot_width;
+ }
+
mcasp->tdm_mask[SNDRV_PCM_STREAM_PLAYBACK] = tx_mask;
mcasp->tdm_mask[SNDRV_PCM_STREAM_CAPTURE] = rx_mask;
- mcasp->slot_width = slot_width;
return davinci_mcasp_set_ch_constraints(mcasp);
}
static int davinci_config_channel_size(struct davinci_mcasp *mcasp,
- int sample_width)
+ int sample_width, int stream)
{
u32 fmt;
u32 tx_rotate, rx_rotate, slot_width;
u32 mask = (1ULL << sample_width) - 1;
- if (mcasp->slot_width)
- slot_width = mcasp->slot_width;
- else if (mcasp->max_format_width)
- slot_width = mcasp->max_format_width;
- else
- slot_width = sample_width;
+ slot_width = mcasp_get_slot_width(mcasp, stream);
+ if (!slot_width) {
+ if (mcasp->max_format_width)
+ slot_width = mcasp->max_format_width;
+ else
+ slot_width = sample_width;
+ }
/*
* TX rotation:
* right aligned formats: rotate w/ slot_width
@@ -827,17 +1016,23 @@ static int davinci_config_channel_size(struct davinci_mcasp *mcasp,
fmt = (slot_width >> 1) - 1;
if (mcasp->op_mode != DAVINCI_MCASP_DIT_MODE) {
- mcasp_mod_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, RXSSZ(fmt),
- RXSSZ(0x0F));
- mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXSSZ(fmt),
- TXSSZ(0x0F));
- mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXROT(tx_rotate),
- TXROT(7));
- mcasp_mod_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, RXROT(rx_rotate),
- RXROT(7));
- mcasp_set_reg(mcasp, DAVINCI_MCASP_RXMASK_REG, mask);
+ if (!mcasp->async_mode || stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXSSZ(fmt),
+ TXSSZ(0x0F));
+ mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXROT(tx_rotate),
+ TXROT(7));
+ mcasp_set_reg(mcasp, DAVINCI_MCASP_TXMASK_REG, mask);
+ }
+ if (!mcasp->async_mode || stream == SNDRV_PCM_STREAM_CAPTURE) {
+ mcasp_mod_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, RXSSZ(fmt),
+ RXSSZ(0x0F));
+ mcasp_mod_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, RXROT(rx_rotate),
+ RXROT(7));
+ mcasp_set_reg(mcasp, DAVINCI_MCASP_RXMASK_REG, mask);
+ }
} else {
/*
+ * DIT mode only use TX serializers
* according to the TRM it should be TXROT=0, this one works:
* 16 bit to 23-8 (TXROT=6, rotate 24 bits)
* 24 bit to 23-0 (TXROT=0, rotate 0 bits)
@@ -850,10 +1045,9 @@ static int davinci_config_channel_size(struct davinci_mcasp *mcasp,
TXROT(7));
mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, TXSSZ(15),
TXSSZ(0x0F));
+ mcasp_set_reg(mcasp, DAVINCI_MCASP_TXMASK_REG, mask);
}
- mcasp_set_reg(mcasp, DAVINCI_MCASP_TXMASK_REG, mask);
-
return 0;
}
@@ -864,11 +1058,13 @@ static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream,
int i;
u8 tx_ser = 0;
u8 rx_ser = 0;
- u8 slots = mcasp->tdm_slots;
+ int slots;
u8 max_active_serializers, max_rx_serializers, max_tx_serializers;
int active_serializers, numevt;
u32 reg;
+ slots = mcasp_get_tdm_slots(mcasp, stream);
+
/* In DIT mode we only allow maximum of one serializers for now */
if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE)
max_active_serializers = 1;
@@ -996,7 +1192,7 @@ static int mcasp_i2s_hw_param(struct davinci_mcasp *mcasp, int stream,
u32 mask = 0;
u32 busel = 0;
- total_slots = mcasp->tdm_slots;
+ total_slots = mcasp_get_tdm_slots(mcasp, stream);
/*
* If more than one serializer is needed, then use them with
@@ -1027,7 +1223,10 @@ static int mcasp_i2s_hw_param(struct davinci_mcasp *mcasp, int stream,
mask |= (1 << i);
}
- mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, TX_ASYNC);
+ if (mcasp->async_mode)
+ mcasp_set_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, TX_ASYNC);
+ else
+ mcasp_clr_bits(mcasp, DAVINCI_MCASP_ACLKXCTL_REG, TX_ASYNC);
if (!mcasp->dat_port)
busel = TXSEL;
@@ -1126,16 +1325,33 @@ static int mcasp_dit_hw_param(struct davinci_mcasp *mcasp,
static int davinci_mcasp_calc_clk_div(struct davinci_mcasp *mcasp,
unsigned int sysclk_freq,
- unsigned int bclk_freq, bool set)
+ unsigned int bclk_freq,
+ int stream,
+ bool set)
{
- u32 reg = mcasp_get_reg(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG);
int div = sysclk_freq / bclk_freq;
int rem = sysclk_freq % bclk_freq;
int error_ppm;
int aux_div = 1;
+ int bclk_div_id, auxclk_div_id;
+ bool auxclk_enabled;
+
+ if (mcasp->async_mode && stream == SNDRV_PCM_STREAM_CAPTURE) {
+ auxclk_enabled = mcasp_get_reg(mcasp, DAVINCI_MCASP_AHCLKRCTL_REG) & AHCLKRE;
+ bclk_div_id = MCASP_CLKDIV_BCLK_RXONLY;
+ auxclk_div_id = MCASP_CLKDIV_AUXCLK_RXONLY;
+ } else if (mcasp->async_mode && stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ auxclk_enabled = mcasp_get_reg(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG) & AHCLKXE;
+ bclk_div_id = MCASP_CLKDIV_BCLK_TXONLY;
+ auxclk_div_id = MCASP_CLKDIV_AUXCLK_TXONLY;
+ } else {
+ auxclk_enabled = mcasp_get_reg(mcasp, DAVINCI_MCASP_AHCLKXCTL_REG) & AHCLKXE;
+ bclk_div_id = MCASP_CLKDIV_BCLK;
+ auxclk_div_id = MCASP_CLKDIV_AUXCLK;
+ }
if (div > (ACLKXDIV_MASK + 1)) {
- if (reg & AHCLKXE) {
+ if (auxclk_enabled) {
aux_div = div / (ACLKXDIV_MASK + 1);
if (div % (ACLKXDIV_MASK + 1))
aux_div++;
@@ -1165,10 +1381,10 @@ static int davinci_mcasp_calc_clk_div(struct davinci_mcasp *mcasp,
dev_info(mcasp->dev, "Sample-rate is off by %d PPM\n",
error_ppm);
- __davinci_mcasp_set_clkdiv(mcasp, MCASP_CLKDIV_BCLK, div, 0);
- if (reg & AHCLKXE)
- __davinci_mcasp_set_clkdiv(mcasp, MCASP_CLKDIV_AUXCLK,
- aux_div, 0);
+ __davinci_mcasp_set_clkdiv(mcasp, bclk_div_id, div, false);
+ if (auxclk_enabled)
+ __davinci_mcasp_set_clkdiv(mcasp, auxclk_div_id,
+ aux_div, false);
}
return error_ppm;
@@ -1219,6 +1435,7 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
int channels = params_channels(params);
int period_size = params_period_size(params);
int ret;
+ unsigned int sysclk_freq = mcasp_get_sysclk_freq(mcasp, substream->stream);
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_U8:
@@ -1259,22 +1476,26 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
* If mcasp is BCLK master, and a BCLK divider was not provided by
* the machine driver, we need to calculate the ratio.
*/
- if (mcasp->bclk_master && mcasp->bclk_div == 0 && mcasp->sysclk_freq) {
- int slots = mcasp->tdm_slots;
+ if (mcasp->bclk_master && mcasp_get_bclk_div(mcasp, substream->stream) == 0 &&
+ sysclk_freq) {
+ int slots, slot_width;
int rate = params_rate(params);
int sbits = params_width(params);
unsigned int bclk_target;
- if (mcasp->slot_width)
- sbits = mcasp->slot_width;
+ slots = mcasp_get_tdm_slots(mcasp, substream->stream);
+
+ slot_width = mcasp_get_slot_width(mcasp, substream->stream);
+ if (slot_width)
+ sbits = slot_width;
if (mcasp->op_mode == DAVINCI_MCASP_IIS_MODE)
bclk_target = rate * sbits * slots;
else
bclk_target = rate * 128;
- davinci_mcasp_calc_clk_div(mcasp, mcasp->sysclk_freq,
- bclk_target, true);
+ davinci_mcasp_calc_clk_div(mcasp, sysclk_freq,
+ bclk_target, substream->stream, true);
}
ret = mcasp_common_hw_param(mcasp, substream->stream,
@@ -1291,9 +1512,10 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
if (ret)
return ret;
- davinci_config_channel_size(mcasp, word_length);
+ davinci_config_channel_size(mcasp, word_length, substream->stream);
- if (mcasp->op_mode == DAVINCI_MCASP_IIS_MODE) {
+ /* Channel constraints are disabled for async mode */
+ if (mcasp->op_mode == DAVINCI_MCASP_IIS_MODE && !mcasp->async_mode) {
mcasp->channels = channels;
if (!mcasp->max_format_width)
mcasp->max_format_width = word_length;
@@ -1337,7 +1559,7 @@ static int davinci_mcasp_hw_rule_slot_width(struct snd_pcm_hw_params *params,
snd_pcm_format_t i;
snd_mask_none(&nfmt);
- slot_width = rd->mcasp->slot_width;
+ slot_width = mcasp_get_slot_width(rd->mcasp, rd->stream);
pcm_for_each_format(i) {
if (snd_mask_test_format(fmt, i)) {
@@ -1387,12 +1609,15 @@ static int davinci_mcasp_hw_rule_rate(struct snd_pcm_hw_params *params,
struct snd_interval *ri =
hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
int sbits = params_width(params);
- int slots = rd->mcasp->tdm_slots;
+ int slots, slot_width;
struct snd_interval range;
int i;
- if (rd->mcasp->slot_width)
- sbits = rd->mcasp->slot_width;
+ slots = mcasp_get_tdm_slots(rd->mcasp, rd->stream);
+
+ slot_width = mcasp_get_slot_width(rd->mcasp, rd->stream);
+ if (slot_width)
+ sbits = slot_width;
snd_interval_any(&range);
range.empty = 1;
@@ -1402,16 +1627,17 @@ static int davinci_mcasp_hw_rule_rate(struct snd_pcm_hw_params *params,
uint bclk_freq = sbits * slots *
davinci_mcasp_dai_rates[i];
unsigned int sysclk_freq;
+ unsigned int ratio;
int ppm;
- if (rd->mcasp->auxclk_fs_ratio)
- sysclk_freq = davinci_mcasp_dai_rates[i] *
- rd->mcasp->auxclk_fs_ratio;
+ ratio = mcasp_get_auxclk_fs_ratio(rd->mcasp, rd->stream);
+ if (ratio)
+ sysclk_freq = davinci_mcasp_dai_rates[i] * ratio;
else
- sysclk_freq = rd->mcasp->sysclk_freq;
+ sysclk_freq = mcasp_get_sysclk_freq(rd->mcasp, rd->stream);
ppm = davinci_mcasp_calc_clk_div(rd->mcasp, sysclk_freq,
- bclk_freq, false);
+ bclk_freq, rd->stream, false);
if (abs(ppm) < DAVINCI_MAX_RATE_ERROR_PPM) {
if (range.empty) {
range.min = davinci_mcasp_dai_rates[i];
@@ -1437,30 +1663,34 @@ static int davinci_mcasp_hw_rule_format(struct snd_pcm_hw_params *params,
struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
struct snd_mask nfmt;
int rate = params_rate(params);
- int slots = rd->mcasp->tdm_slots;
+ int slots;
int count = 0;
snd_pcm_format_t i;
+ slots = mcasp_get_tdm_slots(rd->mcasp, rd->stream);
+
snd_mask_none(&nfmt);
pcm_for_each_format(i) {
if (snd_mask_test_format(fmt, i)) {
uint sbits = snd_pcm_format_width(i);
unsigned int sysclk_freq;
- int ppm;
+ unsigned int ratio;
+ int ppm, slot_width;
- if (rd->mcasp->auxclk_fs_ratio)
- sysclk_freq = rate *
- rd->mcasp->auxclk_fs_ratio;
+ ratio = mcasp_get_auxclk_fs_ratio(rd->mcasp, rd->stream);
+ if (ratio)
+ sysclk_freq = rate * ratio;
else
- sysclk_freq = rd->mcasp->sysclk_freq;
+ sysclk_freq = mcasp_get_sysclk_freq(rd->mcasp, rd->stream);
- if (rd->mcasp->slot_width)
- sbits = rd->mcasp->slot_width;
+ slot_width = mcasp_get_slot_width(rd->mcasp, rd->stream);
+ if (slot_width)
+ sbits = slot_width;
ppm = davinci_mcasp_calc_clk_div(rd->mcasp, sysclk_freq,
sbits * slots * rate,
- false);
+ rd->stream, false);
if (abs(ppm) < DAVINCI_MAX_RATE_ERROR_PPM) {
snd_mask_set_format(&nfmt, i);
count++;
@@ -1497,7 +1727,7 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream,
&mcasp->ruledata[substream->stream];
u32 max_channels = 0;
int i, dir, ret;
- int tdm_slots = mcasp->tdm_slots;
+ int tdm_slots;
u8 *numevt;
/* Do not allow more then one stream per direction */
@@ -1506,6 +1736,8 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream,
mcasp->substreams[substream->stream] = substream;
+ tdm_slots = mcasp_get_tdm_slots(mcasp, substream->stream);
+
if (mcasp->tdm_mask[substream->stream])
tdm_slots = hweight32(mcasp->tdm_mask[substream->stream]);
@@ -1527,6 +1759,7 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream,
}
ruledata->serializers = max_channels;
ruledata->mcasp = mcasp;
+ ruledata->stream = substream->stream;
max_channels *= tdm_slots;
/*
* If the already active stream has less channels than the calculated
@@ -1534,9 +1767,13 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream,
* is in use we need to use that as a constraint for the second stream.
* Otherwise (first stream or less allowed channels or more than one
* serializer in use) we use the calculated constraint.
+ *
+ * However, in async mode, TX and RX have independent clocks and can
+ * use different configurations, so don't apply the constraint.
*/
if (mcasp->channels && mcasp->channels < max_channels &&
- ruledata->serializers == 1)
+ ruledata->serializers == 1 &&
+ !mcasp->async_mode)
max_channels = mcasp->channels;
/*
* But we can always allow channels upto the amount of
@@ -1553,10 +1790,10 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream,
0, SNDRV_PCM_HW_PARAM_CHANNELS,
&mcasp->chconstr[substream->stream]);
- if (mcasp->max_format_width) {
+ if (mcasp->max_format_width && !mcasp->async_mode) {
/*
* Only allow formats which require same amount of bits on the
- * bus as the currently running stream
+ * bus as the currently running stream to ensure sync mode
*/
ret = snd_pcm_hw_rule_add(substream->runtime, 0,
SNDRV_PCM_HW_PARAM_FORMAT,
@@ -1565,8 +1802,7 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream,
SNDRV_PCM_HW_PARAM_FORMAT, -1);
if (ret)
return ret;
- }
- else if (mcasp->slot_width) {
+ } else if (mcasp_get_slot_width(mcasp, substream->stream)) {
/* Only allow formats require <= slot_width bits on the bus */
ret = snd_pcm_hw_rule_add(substream->runtime, 0,
SNDRV_PCM_HW_PARAM_FORMAT,
@@ -1581,7 +1817,8 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream,
* If we rely on implicit BCLK divider setting we should
* set constraints based on what we can provide.
*/
- if (mcasp->bclk_master && mcasp->bclk_div == 0 && mcasp->sysclk_freq) {
+ if (mcasp->bclk_master && mcasp_get_bclk_div(mcasp, substream->stream) == 0 &&
+ mcasp_get_sysclk_freq(mcasp, substream->stream)) {
ret = snd_pcm_hw_rule_add(substream->runtime, 0,
SNDRV_PCM_HW_PARAM_RATE,
davinci_mcasp_hw_rule_rate,
@@ -1758,8 +1995,6 @@ static struct snd_soc_dai_driver davinci_mcasp_dai[] = {
.formats = DAVINCI_MCASP_PCM_FMTS,
},
.ops = &davinci_mcasp_dai_ops,
-
- .symmetric_rate = 1,
},
{
.name = "davinci-mcasp.1",
@@ -1921,18 +2156,33 @@ static int davinci_mcasp_get_config(struct davinci_mcasp *mcasp,
goto out;
}
+ /* Parse TX-specific TDM slot and use it as default for RX */
if (of_property_read_u32(np, "tdm-slots", &val) == 0) {
if (val < 2 || val > 32) {
- dev_err(&pdev->dev, "tdm-slots must be in rage [2-32]\n");
+ dev_err(&pdev->dev, "tdm-slots must be in range [2-32]\n");
return -EINVAL;
}
- pdata->tdm_slots = val;
+ pdata->tdm_slots_tx = val;
+ pdata->tdm_slots_rx = val;
} else if (pdata->op_mode == DAVINCI_MCASP_IIS_MODE) {
mcasp->missing_audio_param = true;
goto out;
}
+ /* Parse RX-specific TDM slot count if provided */
+ if (of_property_read_u32(np, "tdm-slots-rx", &val) == 0) {
+ if (val < 2 || val > 32) {
+ dev_err(&pdev->dev, "tdm-slots-rx must be in range [2-32]\n");
+ return -EINVAL;
+ }
+
+ pdata->tdm_slots_rx = val;
+ }
+
+ if (pdata->op_mode != DAVINCI_MCASP_DIT_MODE)
+ mcasp->async_mode = of_property_read_bool(np, "ti,async-mode");
+
of_serial_dir32 = of_get_property(np, "serial-dir", &val);
val /= sizeof(u32);
if (of_serial_dir32) {
@@ -1958,8 +2208,15 @@ static int davinci_mcasp_get_config(struct davinci_mcasp *mcasp,
if (of_property_read_u32(np, "rx-num-evt", &val) == 0)
pdata->rxnumevt = val;
- if (of_property_read_u32(np, "auxclk-fs-ratio", &val) == 0)
- mcasp->auxclk_fs_ratio = val;
+ /* Parse TX-specific auxclk/fs ratio and use it as default for RX */
+ if (of_property_read_u32(np, "auxclk-fs-ratio", &val) == 0) {
+ mcasp->auxclk_fs_ratio_tx = val;
+ mcasp->auxclk_fs_ratio_rx = val;
+ }
+
+ /* Parse RX-specific auxclk/fs ratio if provided */
+ if (of_property_read_u32(np, "auxclk-fs-ratio-rx", &val) == 0)
+ mcasp->auxclk_fs_ratio_rx = val;
if (of_property_read_u32(np, "dismod", &val) == 0) {
if (val == 0 || val == 2 || val == 3) {
@@ -1988,19 +2245,51 @@ static int davinci_mcasp_get_config(struct davinci_mcasp *mcasp,
mcasp->op_mode = pdata->op_mode;
/* sanity check for tdm slots parameter */
if (mcasp->op_mode == DAVINCI_MCASP_IIS_MODE) {
- if (pdata->tdm_slots < 2) {
- dev_warn(&pdev->dev, "invalid tdm slots: %d\n",
- pdata->tdm_slots);
- mcasp->tdm_slots = 2;
- } else if (pdata->tdm_slots > 32) {
- dev_warn(&pdev->dev, "invalid tdm slots: %d\n",
- pdata->tdm_slots);
- mcasp->tdm_slots = 32;
+ if (pdata->tdm_slots_tx < 2) {
+ dev_warn(&pdev->dev, "invalid tdm tx slots: %d\n",
+ pdata->tdm_slots_tx);
+ mcasp->tdm_slots_tx = 2;
+ } else if (pdata->tdm_slots_tx > 32) {
+ dev_warn(&pdev->dev, "invalid tdm tx slots: %d\n",
+ pdata->tdm_slots_tx);
+ mcasp->tdm_slots_tx = 32;
+ } else {
+ mcasp->tdm_slots_tx = pdata->tdm_slots_tx;
+ }
+
+ if (pdata->tdm_slots_rx < 2) {
+ dev_warn(&pdev->dev, "invalid tdm rx slots: %d\n",
+ pdata->tdm_slots_rx);
+ mcasp->tdm_slots_rx = 2;
+ } else if (pdata->tdm_slots_rx > 32) {
+ dev_warn(&pdev->dev, "invalid tdm rx slots: %d\n",
+ pdata->tdm_slots_rx);
+ mcasp->tdm_slots_rx = 32;
} else {
- mcasp->tdm_slots = pdata->tdm_slots;
+ mcasp->tdm_slots_rx = pdata->tdm_slots_rx;
}
} else {
- mcasp->tdm_slots = 32;
+ mcasp->tdm_slots_tx = 32;
+ mcasp->tdm_slots_rx = 32;
+ }
+
+ /* Different TX/RX slot counts require async mode */
+ if (pdata->op_mode != DAVINCI_MCASP_DIT_MODE &&
+ mcasp->tdm_slots_tx != mcasp->tdm_slots_rx && !mcasp->async_mode) {
+ dev_err(&pdev->dev,
+ "Different TX (%d) and RX (%d) TDM slots require ti,async-mode\n",
+ mcasp->tdm_slots_tx, mcasp->tdm_slots_rx);
+ return -EINVAL;
+ }
+
+ /* Different TX/RX auxclk-fs-ratio require async mode */
+ if (pdata->op_mode != DAVINCI_MCASP_DIT_MODE &&
+ mcasp->auxclk_fs_ratio_tx && mcasp->auxclk_fs_ratio_rx &&
+ mcasp->auxclk_fs_ratio_tx != mcasp->auxclk_fs_ratio_rx && !mcasp->async_mode) {
+ dev_err(&pdev->dev,
+ "Different TX (%d) and RX (%d) auxclk-fs-ratio require ti,async-mode\n",
+ mcasp->auxclk_fs_ratio_tx, mcasp->auxclk_fs_ratio_rx);
+ return -EINVAL;
}
mcasp->num_serializer = pdata->num_serializer;
diff --git a/sound/soc/ti/davinci-mcasp.h b/sound/soc/ti/davinci-mcasp.h
index 5de2b8a31061..83b3c67f4a2b 100644
--- a/sound/soc/ti/davinci-mcasp.h
+++ b/sound/soc/ti/davinci-mcasp.h
@@ -298,10 +298,20 @@
/* Source of High-frequency transmit/receive clock */
#define MCASP_CLK_HCLK_AHCLK 0 /* AHCLKX/R */
#define MCASP_CLK_HCLK_AUXCLK 1 /* Internal functional clock */
+#define MCASP_CLK_HCLK_AHCLK_TXONLY 2 /* AHCLKX for TX only */
+#define MCASP_CLK_HCLK_AHCLK_RXONLY 3 /* AHCLKR for RX only */
+#define MCASP_CLK_HCLK_AUXCLK_TXONLY 4 /* AUXCLK for TX only */
+#define MCASP_CLK_HCLK_AUXCLK_RXONLY 5 /* AUXCLK for RX only */
/* clock divider IDs */
#define MCASP_CLKDIV_AUXCLK 0 /* HCLK divider from AUXCLK */
#define MCASP_CLKDIV_BCLK 1 /* BCLK divider from HCLK */
#define MCASP_CLKDIV_BCLK_FS_RATIO 2 /* to set BCLK FS ration */
+#define MCASP_CLKDIV_AUXCLK_TXONLY 3 /* AUXCLK divider for TX only */
+#define MCASP_CLKDIV_AUXCLK_RXONLY 4 /* AUXCLK divider for RX only */
+#define MCASP_CLKDIV_BCLK_TXONLY 5 /* BCLK divider for TX only */
+#define MCASP_CLKDIV_BCLK_RXONLY 6 /* BCLK divider for RX only */
+#define MCASP_CLKDIV_BCLK_FS_RATIO_TXONLY 7 /* BCLK/FS ratio for TX only */
+#define MCASP_CLKDIV_BCLK_FS_RATIO_RXONLY 8 /* BCLK/FS ratio for RX only*/
#endif /* DAVINCI_MCASP_H */
--
2.43.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH v2 0/4] ASoC: ti: davinci-mcasp: Add asynchronous mode support for McASP
2026-02-03 0:36 [PATCH v2 0/4] ASoC: ti: davinci-mcasp: Add asynchronous mode support for McASP Sen Wang
` (3 preceding siblings ...)
2026-02-03 0:37 ` [PATCH v2 4/4] ASoC: ti: davinci-mcasp: Add asynchronous mode support Sen Wang
@ 2026-02-04 11:44 ` Paresh Bhagat
2026-02-04 16:05 ` Péter Ujfalusi
2026-02-05 11:04 ` Mark Brown
6 siblings, 0 replies; 8+ messages in thread
From: Paresh Bhagat @ 2026-02-04 11:44 UTC (permalink / raw)
To: sen
Cc: broonie, conor+dt, devicetree, krzk+dt, lgirdwood, linux-kernel,
linux-sound, perex, peter.ujfalusi, robh, tiwai
On 02/02/2026 18:36 PM, Sen Wang wrote:
> This series adds asynchronous mode support to the McASP driver, which
> enables independent configuration of bitclocks, frame sync, and audio
> configurations between tx(playback) and rx(record). And achieves
> simultaneous playback & record using different audio configurations.
>
> It also adds two clean up patches to the McASP driver that disambiguate
> and simplifies the logic which avoids the async enhancement from being
> too convoluted to review and analyze.
>
> The implementation is based on vendor documentation and patches tested in
> both SK-AM62P-LP (sync mode, McASP slave) and AM62D-EVM
> (async mode, McASP master, rx & tx has different TDM configs).
> Testing verifies async mode functionality while maintaining backward
> compatibility with the default sync mode.
>
> Bootlog and Async mode tests on AM62D-EVM: [0]
>
> [0]: https://gist.github.com/SenWang125/f31f9172b186d414695e37c8b9ef127d
>
> Signed-off-by: Sen Wang <sen@ti.com>
Tested-by: Paresh Bhagat <p-bhagat@ti.com>
>
> Changes in v2:
> - Corrected patch 1 subject title
> - Retained original order of operation in patch 3
> - Corrected code comments to use inclusive terminology in patch 4
>
> Sen Wang (4):
> ASoC: dt-bindings: davinci-mcasp: Add properties for asynchronous mode
> ASoC: ti: davinci-mcasp: Disambiguate mcasp_is_synchronous function
> ASoC: ti: davinci-mcasp: Streamline pdir behavior across rx & tx streams
> ASoC: ti: davinci-mcasp: Add asynchronous mode support
>
> .../bindings/sound/davinci-mcasp-audio.yaml | 71 ++-
> include/linux/platform_data/davinci_asp.h | 3 +-
> sound/soc/ti/davinci-mcasp.c | 510 ++++++++++++++----
> sound/soc/ti/davinci-mcasp.h | 10 +
> 4 files changed, 481 insertions(+), 113 deletions(-)
>
>
> base-commit: dbf8fe85a16a33d6b6bd01f2bc606fc017771465
> --
> 2.43.0
>
>
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v2 0/4] ASoC: ti: davinci-mcasp: Add asynchronous mode support for McASP
2026-02-03 0:36 [PATCH v2 0/4] ASoC: ti: davinci-mcasp: Add asynchronous mode support for McASP Sen Wang
` (4 preceding siblings ...)
2026-02-04 11:44 ` [PATCH v2 0/4] ASoC: ti: davinci-mcasp: Add asynchronous mode support for McASP Paresh Bhagat
@ 2026-02-04 16:05 ` Péter Ujfalusi
2026-02-05 11:04 ` Mark Brown
6 siblings, 0 replies; 8+ messages in thread
From: Péter Ujfalusi @ 2026-02-04 16:05 UTC (permalink / raw)
To: Sen Wang, broonie, lgirdwood, perex, tiwai, robh, krzk+dt,
conor+dt
Cc: linux-sound, devicetree, linux-kernel
On 03/02/2026 02:36, Sen Wang wrote:
> This series adds asynchronous mode support to the McASP driver, which
> enables independent configuration of bitclocks, frame sync, and audio
> configurations between tx(playback) and rx(record). And achieves
> simultaneous playback & record using different audio configurations.
>
> It also adds two clean up patches to the McASP driver that disambiguate
> and simplifies the logic which avoids the async enhancement from being
> too convoluted to review and analyze.
>
> The implementation is based on vendor documentation and patches tested in
> both SK-AM62P-LP (sync mode, McASP slave) and AM62D-EVM
> (async mode, McASP master, rx & tx has different TDM configs).
> Testing verifies async mode functionality while maintaining backward
> compatibility with the default sync mode.
>
> Bootlog and Async mode tests on AM62D-EVM: [0]
>
> [0]: https://gist.github.com/SenWang125/f31f9172b186d414695e37c8b9ef127d
it is a shame that I never had a setup where this can be tested.
Acked-by: Peter Ujfalusi <peter.ujfalusi@gmail.com>
>
> Signed-off-by: Sen Wang <sen@ti.com>
>
> Changes in v2:
> - Corrected patch 1 subject title
> - Retained original order of operation in patch 3
> - Corrected code comments to use inclusive terminology in patch 4
>
> Sen Wang (4):
> ASoC: dt-bindings: davinci-mcasp: Add properties for asynchronous mode
> ASoC: ti: davinci-mcasp: Disambiguate mcasp_is_synchronous function
> ASoC: ti: davinci-mcasp: Streamline pdir behavior across rx & tx streams
> ASoC: ti: davinci-mcasp: Add asynchronous mode support
>
> .../bindings/sound/davinci-mcasp-audio.yaml | 71 ++-
> include/linux/platform_data/davinci_asp.h | 3 +-
> sound/soc/ti/davinci-mcasp.c | 510 ++++++++++++++----
> sound/soc/ti/davinci-mcasp.h | 10 +
> 4 files changed, 481 insertions(+), 113 deletions(-)
>
>
> base-commit: dbf8fe85a16a33d6b6bd01f2bc606fc017771465
--
Péter
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v2 0/4] ASoC: ti: davinci-mcasp: Add asynchronous mode support for McASP
2026-02-03 0:36 [PATCH v2 0/4] ASoC: ti: davinci-mcasp: Add asynchronous mode support for McASP Sen Wang
` (5 preceding siblings ...)
2026-02-04 16:05 ` Péter Ujfalusi
@ 2026-02-05 11:04 ` Mark Brown
6 siblings, 0 replies; 8+ messages in thread
From: Mark Brown @ 2026-02-05 11:04 UTC (permalink / raw)
To: peter.ujfalusi, lgirdwood, perex, tiwai, robh, krzk+dt, conor+dt,
Sen Wang
Cc: linux-sound, devicetree, linux-kernel
On Mon, 02 Feb 2026 18:36:59 -0600, Sen Wang wrote:
> This series adds asynchronous mode support to the McASP driver, which
> enables independent configuration of bitclocks, frame sync, and audio
> configurations between tx(playback) and rx(record). And achieves
> simultaneous playback & record using different audio configurations.
>
> It also adds two clean up patches to the McASP driver that disambiguate
> and simplifies the logic which avoids the async enhancement from being
> too convoluted to review and analyze.
>
> [...]
Applied to
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next
Thanks!
[1/4] ASoC: dt-bindings: davinci-mcasp: Add properties for asynchronous mode
commit: f1ef70a4a32042984d29b8d02bdf6167474373af
[2/4] ASoC: ti: davinci-mcasp: Disambiguate mcasp_is_synchronous function
commit: e683cb088fdcbdc86fc30008319312cc0bb80226
[3/4] ASoC: ti: davinci-mcasp: Streamline pdir behavior across rx & tx streams
commit: 016efcaa470cdbc658df46d968d875f6a1cf9a78
[4/4] ASoC: ti: davinci-mcasp: Add asynchronous mode support
commit: 9db327083f7e0da702e2ec0169f8a34f3576f371
All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying
to this mail.
Thanks,
Mark
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2026-02-05 11:05 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-02-03 0:36 [PATCH v2 0/4] ASoC: ti: davinci-mcasp: Add asynchronous mode support for McASP Sen Wang
2026-02-03 0:37 ` [PATCH v2 1/4] ASoC: dt-bindings: davinci-mcasp: Add properties for asynchronous mode Sen Wang
2026-02-03 0:37 ` [PATCH v2 2/4] ASoC: ti: davinci-mcasp: Disambiguate mcasp_is_synchronous function Sen Wang
2026-02-03 0:37 ` [PATCH v2 3/4] ASoC: ti: davinci-mcasp: Streamline pdir behavior across rx & tx streams Sen Wang
2026-02-03 0:37 ` [PATCH v2 4/4] ASoC: ti: davinci-mcasp: Add asynchronous mode support Sen Wang
2026-02-04 11:44 ` [PATCH v2 0/4] ASoC: ti: davinci-mcasp: Add asynchronous mode support for McASP Paresh Bhagat
2026-02-04 16:05 ` Péter Ujfalusi
2026-02-05 11:04 ` Mark Brown
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox