mirror of
https://github.com/armbian/build.git
synced 2025-08-14 15:16:58 +02:00
149 lines
4.3 KiB
Diff
149 lines
4.3 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Jianhua Lu <lujianhua000@gmail.com>
|
|
Date: Fri, 17 Feb 2023 21:31:38 +0800
|
|
Subject: sound: soc: qcom: sm8250: Add tdm support
|
|
|
|
---
|
|
sound/soc/qcom/sdw.c | 65 ++++++++++
|
|
sound/soc/qcom/sm8250.c | 17 +++
|
|
2 files changed, 82 insertions(+)
|
|
|
|
diff --git a/sound/soc/qcom/sdw.c b/sound/soc/qcom/sdw.c
|
|
index 1a41419c7eb8..5e09fb1e3143 100644
|
|
--- a/sound/soc/qcom/sdw.c
|
|
+++ b/sound/soc/qcom/sdw.c
|
|
@@ -4,9 +4,12 @@
|
|
|
|
#include <linux/module.h>
|
|
#include <sound/soc.h>
|
|
+#include <sound/pcm_params.h>
|
|
#include "qdsp6/q6afe.h"
|
|
#include "sdw.h"
|
|
|
|
+static unsigned int tdm_slot_offset[8] = {0, 4, 8, 12, 16, 20, 24, 28};
|
|
+
|
|
int qcom_snd_sdw_prepare(struct snd_pcm_substream *substream,
|
|
struct sdw_stream_runtime *sruntime,
|
|
bool *stream_prepared)
|
|
@@ -58,6 +61,64 @@ int qcom_snd_sdw_prepare(struct snd_pcm_substream *substream,
|
|
}
|
|
EXPORT_SYMBOL_GPL(qcom_snd_sdw_prepare);
|
|
|
|
+static int qcom_tdm_snd_hw_params(struct snd_pcm_substream *substream,
|
|
+ struct snd_pcm_hw_params *params)
|
|
+{
|
|
+ struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
|
|
+ struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
|
|
+
|
|
+ int ret = 0;
|
|
+ int channels, slot_width;
|
|
+
|
|
+ switch (params_format(params)) {
|
|
+ case SNDRV_PCM_FORMAT_S16_LE:
|
|
+ slot_width = 32;
|
|
+ break;
|
|
+ default:
|
|
+ dev_err(rtd->dev, "%s: invalid param format 0x%x\n",
|
|
+ __func__, params_format(params));
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ channels = params_channels(params);
|
|
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
|
+ ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0, 0x03,
|
|
+ 8, slot_width);
|
|
+ if (ret < 0) {
|
|
+ dev_err(rtd->dev, "%s: failed to set tdm slot, err:%d\n",
|
|
+ __func__, ret);
|
|
+ goto end;
|
|
+ }
|
|
+
|
|
+ ret = snd_soc_dai_set_channel_map(cpu_dai, 0, NULL,
|
|
+ channels, tdm_slot_offset);
|
|
+ if (ret < 0) {
|
|
+ dev_err(rtd->dev, "%s: failed to set channel map, err:%d\n",
|
|
+ __func__, ret);
|
|
+ goto end;
|
|
+ }
|
|
+ } else {
|
|
+ ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0xf, 0,
|
|
+ 8, slot_width);
|
|
+ if (ret < 0) {
|
|
+ dev_err(rtd->dev, "%s: failed to set tdm slot, err:%d\n",
|
|
+ __func__, ret);
|
|
+ goto end;
|
|
+ }
|
|
+
|
|
+ ret = snd_soc_dai_set_channel_map(cpu_dai, channels,
|
|
+ tdm_slot_offset, 0, NULL);
|
|
+ if (ret < 0) {
|
|
+ dev_err(rtd->dev, "%s: failed to set channel map, err:%d\n",
|
|
+ __func__, ret);
|
|
+ goto end;
|
|
+ }
|
|
+ }
|
|
+
|
|
+end:
|
|
+ return ret;
|
|
+}
|
|
+
|
|
int qcom_snd_sdw_hw_params(struct snd_pcm_substream *substream,
|
|
struct snd_pcm_hw_params *params,
|
|
struct sdw_stream_runtime **psruntime)
|
|
@@ -82,6 +143,10 @@ int qcom_snd_sdw_hw_params(struct snd_pcm_substream *substream,
|
|
*psruntime = sruntime;
|
|
}
|
|
break;
|
|
+ case TERTIARY_TDM_RX_0:
|
|
+ case TERTIARY_TDM_TX_0:
|
|
+ qcom_tdm_snd_hw_params(substream, params);
|
|
+ break;
|
|
}
|
|
|
|
return 0;
|
|
diff --git a/sound/soc/qcom/sm8250.c b/sound/soc/qcom/sm8250.c
|
|
index 9626a9ef78c2..abeab190337a 100644
|
|
--- a/sound/soc/qcom/sm8250.c
|
|
+++ b/sound/soc/qcom/sm8250.c
|
|
@@ -16,6 +16,7 @@
|
|
|
|
#define DRIVER_NAME "sm8250"
|
|
#define MI2S_BCLK_RATE 1536000
|
|
+#define TDM_BCLK_RATE 12288000
|
|
|
|
struct sm8250_snd_data {
|
|
bool stream_prepared[AFE_PORT_MAX];
|
|
@@ -53,6 +54,7 @@ static int sm8250_snd_startup(struct snd_pcm_substream *substream)
|
|
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
|
struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
|
|
struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
|
|
+ int ret,j;
|
|
|
|
switch (cpu_dai->id) {
|
|
case TERTIARY_MI2S_RX:
|
|
@@ -63,6 +65,21 @@ static int sm8250_snd_startup(struct snd_pcm_substream *substream)
|
|
snd_soc_dai_set_fmt(cpu_dai, fmt);
|
|
snd_soc_dai_set_fmt(codec_dai, codec_dai_fmt);
|
|
break;
|
|
+ case TERTIARY_TDM_RX_0:
|
|
+ codec_dai_fmt |= SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_DSP_A;
|
|
+ snd_soc_dai_set_sysclk(cpu_dai,
|
|
+ Q6AFE_LPASS_CLK_ID_TER_TDM_IBIT,
|
|
+ TDM_BCLK_RATE, SNDRV_PCM_STREAM_PLAYBACK);
|
|
+
|
|
+ for_each_rtd_codec_dais(rtd, j, codec_dai) {
|
|
+ ret = snd_soc_dai_set_fmt(codec_dai, codec_dai_fmt);
|
|
+ snd_soc_dai_set_sysclk(codec_dai, 0, TDM_BCLK_RATE, SNDRV_PCM_STREAM_PLAYBACK);
|
|
+ if (ret < 0) {
|
|
+ dev_err(rtd->dev, "TDM fmt err:%d\n", ret);
|
|
+ return ret;
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
default:
|
|
break;
|
|
}
|
|
--
|
|
Armbian
|
|
|