Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
151 changes: 143 additions & 8 deletions audioreach-driver/audioreach_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,9 @@
#include <sound/jack.h>
#include <linux/input-event-codes.h>
#include <sound/simple_card_utils.h>
#include "q6afe.h"
#include "sdw.h"
#include "q6prm_audioreach.h"

#define AFE_PORT_MAX 137
#define NAME_SIZE 32

struct qcs6490_snd_data {
Expand Down Expand Up @@ -388,6 +387,64 @@ static int qcs6490_snd_init(struct snd_soc_pcm_runtime *rtd)
return qcs6490_snd_wcd_jack_setup(rtd, &data->jack, &data->jack_setup);
}

static int qcs6490_snd_startup(struct snd_pcm_substream *substream)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not getting the context of this change. How is it related to debian compilation? I thought we are just duplicating definitions from header files which are not residing in /inc

Copy link
Contributor Author

@mohsRafi mohsRafi Nov 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in existing machine driver in upstream, the startup snd-ops function defined in sound/soc/qcom/sdw.c and not in machine driver, the function declarations done in sound/soc/qcom/sdw.c not in Include.

As part of independed machine driver compilation startup defined in machine driver since it's driver specific snd ops.

{
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
u32 rx_ch[SDW_MAX_PORTS], tx_ch[SDW_MAX_PORTS];
struct sdw_stream_runtime *sruntime;
struct snd_soc_dai *codec_dai;
u32 rx_ch_cnt = 0, tx_ch_cnt = 0;
int ret, i, j;

sruntime = sdw_alloc_stream(cpu_dai->name, SDW_STREAM_PCM);
if (!sruntime)
return -ENOMEM;

for_each_rtd_codec_dais(rtd, i, codec_dai) {
ret = snd_soc_dai_set_stream(codec_dai, sruntime,
substream->stream);
if (ret < 0 && ret != -ENOTSUPP) {
dev_err(rtd->dev, "Failed to set sdw stream on %s\n", codec_dai->name);
goto err_set_stream;
} else if (ret == -ENOTSUPP) {
/* Ignore unsupported */
continue;
}

ret = snd_soc_dai_get_channel_map(codec_dai, &tx_ch_cnt, tx_ch,
&rx_ch_cnt, rx_ch);
if (ret != 0 && ret != -ENOTSUPP) {
dev_err(rtd->dev, "Failed to get codec chan map %s\n", codec_dai->name);
goto err_set_stream;
} else if (ret == -ENOTSUPP) {
/* Ignore unsupported */
continue;
}
}

switch (cpu_dai->id) {
case RX_CODEC_DMA_RX_0:
case TX_CODEC_DMA_TX_3:
if (tx_ch_cnt || rx_ch_cnt) {
for_each_rtd_codec_dais(rtd, j, codec_dai) {
ret = snd_soc_dai_set_channel_map(codec_dai,
tx_ch_cnt, tx_ch,
rx_ch_cnt, rx_ch);
if (ret != 0 && ret != -ENOTSUPP)
goto err_set_stream;
}
}
}

return 0;

err_set_stream:
sdw_release_stream(sruntime);

return ret;
}

static void qcs6490_snd_shutdown(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
Expand Down Expand Up @@ -430,10 +487,29 @@ static int qcs6490_snd_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
struct qcs6490_snd_data *pdata = snd_soc_card_get_drvdata(rtd->card);
struct sdw_stream_runtime *sruntime;
int i;

switch (cpu_dai->id) {
case WSA_CODEC_DMA_RX_0:
case RX_CODEC_DMA_RX_0:
case RX_CODEC_DMA_RX_1:
case TX_CODEC_DMA_TX_0:
case TX_CODEC_DMA_TX_1:
case TX_CODEC_DMA_TX_2:
case TX_CODEC_DMA_TX_3:
for_each_rtd_codec_dais(rtd, i, codec_dai) {
sruntime = snd_soc_dai_get_stream(codec_dai, substream->stream);
if (sruntime != ERR_PTR(-ENOTSUPP))
pdata->sruntime[cpu_dai->id] = sruntime;
}
break;
}

return qcom_snd_sdw_hw_params(substream, params, &pdata->sruntime[cpu_dai->id]);
return 0;
}

static int qcs6490_snd_prepare(struct snd_pcm_substream *substream)
Expand All @@ -442,9 +518,49 @@ static int qcs6490_snd_prepare(struct snd_pcm_substream *substream)
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
struct qcs6490_snd_data *data = snd_soc_card_get_drvdata(rtd->card);
struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id];
bool *stream_prepared = &data->stream_prepared[cpu_dai->id];
int ret;

if (!sruntime)
return 0;

switch (cpu_dai->id) {
case WSA_CODEC_DMA_RX_0:
case WSA_CODEC_DMA_RX_1:
case RX_CODEC_DMA_RX_0:
case RX_CODEC_DMA_RX_1:
case TX_CODEC_DMA_TX_0:
case TX_CODEC_DMA_TX_1:
case TX_CODEC_DMA_TX_2:
case TX_CODEC_DMA_TX_3:
break;
default:
return 0;
}

if (*stream_prepared)
return 0;

return qcom_snd_sdw_prepare(substream, sruntime,
&data->stream_prepared[cpu_dai->id]);
ret = sdw_prepare_stream(sruntime);
if (ret)
return ret;

/**
* NOTE: there is a strict hw requirement about the ordering of port
* enables and actual WSA881x PA enable. PA enable should only happen
* after soundwire ports are enabled if not DC on the line is
* accumulated resulting in Click/Pop Noise
* PA enable/mute are handled as part of codec DAPM and digital mute.
*/

ret = sdw_enable_stream(sruntime);
if (ret) {
sdw_deprepare_stream(sruntime);
return ret;
}
*stream_prepared = true;

return ret;
}

static int qcs6490_snd_hw_free(struct snd_pcm_substream *substream)
Expand All @@ -453,13 +569,32 @@ static int qcs6490_snd_hw_free(struct snd_pcm_substream *substream)
struct qcs6490_snd_data *data = snd_soc_card_get_drvdata(rtd->card);
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id];
bool *stream_prepared = &data->stream_prepared[cpu_dai->id];

return qcom_snd_sdw_hw_free(substream, sruntime,
&data->stream_prepared[cpu_dai->id]);
switch (cpu_dai->id) {
case WSA_CODEC_DMA_RX_0:
case WSA_CODEC_DMA_RX_1:
case RX_CODEC_DMA_RX_0:
case RX_CODEC_DMA_RX_1:
case TX_CODEC_DMA_TX_0:
case TX_CODEC_DMA_TX_1:
case TX_CODEC_DMA_TX_2:
case TX_CODEC_DMA_TX_3:
if (sruntime && *stream_prepared) {
sdw_disable_stream(sruntime);
sdw_deprepare_stream(sruntime);
*stream_prepared = false;
}
break;
default:
break;
}

return 0;
}

static const struct snd_soc_ops qcs6490_be_ops = {
.startup = qcom_snd_sdw_startup,
.startup = qcs6490_snd_startup,
.shutdown = qcs6490_snd_shutdown,
.hw_params = qcs6490_snd_hw_params,
.hw_free = qcs6490_snd_hw_free,
Expand Down
56 changes: 56 additions & 0 deletions audioreach-driver/q6apm_audio.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/* SPDX-License-Identifier: GPL-2.0 */
// Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.

#ifndef __Q6APM_AUDIO_H__
#define __Q6APM_AUDIO_H__

#include <sound/soc.h>

#define AR_PCM_MAX_NUM_CHANNEL 8

struct audioreach_module_config {
int direction;
u32 sample_rate;
u16 bit_width;
u16 bits_per_sample;

u16 data_format;
u16 num_channels;
u16 dp_idx;
u32 channel_allocation;
u32 sd_line_mask;
int fmt;
struct snd_codec codec;
u8 channel_map[AR_PCM_MAX_NUM_CHANNEL];
};

struct q6dsp_audio_port_dai_driver_config {
int (*probe)(struct snd_soc_dai *dai);
int (*remove)(struct snd_soc_dai *dai);
const struct snd_soc_dai_ops *q6hdmi_ops;
const struct snd_soc_dai_ops *q6slim_ops;
const struct snd_soc_dai_ops *q6i2s_ops;
const struct snd_soc_dai_ops *q6tdm_ops;
const struct snd_soc_dai_ops *q6dma_ops;
const struct snd_soc_dai_ops *q6usb_ops;
};

struct apm_cmd_header {
uint32_t payload_address_lsw;
uint32_t payload_address_msw;
uint32_t mem_map_handle;
uint32_t payload_size;
} __packed;

#define APM_CMD_HDR_SIZE sizeof(struct apm_cmd_header)

struct apm_module_param_data {
uint32_t module_instance_id;
uint32_t param_id;
uint32_t param_size;
uint32_t error_code;
} __packed;

#define APM_MODULE_PARAM_DATA_SIZE sizeof(struct apm_module_param_data)

#endif
3 changes: 2 additions & 1 deletion audioreach-driver/q6apm_audio_mem.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@
#include <linux/firmware/qcom/qcom_scm.h>
#include <dt-bindings/firmware/qcom,scm.h>
#include <sound/soc.h>
#include "q6prm_audioreach.h"
#include <linux/msm_audio.h>
#include "q6apm_audio.h"
#include "q6prm_audioreach.h"

#define DRV_NAME "q6apm-audio-mem"

Expand Down
17 changes: 10 additions & 7 deletions audioreach-driver/q6apm_audio_pkt.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,14 @@
#include <sound/soc.h>
#include <sound/soc-dapm.h>
#include <sound/pcm.h>
#include "audioreach.h"
#include "q6apm.h"
#include "q6apm_audio.h"
#include "q6prm_audioreach.h"

#define APM_MODULE_INSTANCE_ID 0x00000001
#define APM_CMD_CLOSE_ALL 0x01001013
#define APM_CMD_GET_SPF_STATE 0x01001021
#define APM_CMD_RSP_GET_SPF_STATE 0x02001007
#define APM_CMD_CLOSE_ALL 0x01001013
#define APM_CMD_SHARED_MEM_MAP_REGIONS 0x0100100C
#define APM_MEMORY_MAP_BIT_MASK_IS_OFFSET_MODE 0x00000004UL

Expand Down Expand Up @@ -642,21 +646,20 @@ static int q6apm_audio_pkt_callback(struct gpr_resp_pkt *data, void *priv, int o
struct q6apm_audio_pkt *apm = dev_get_drvdata(&gdev->dev);
struct gpr_ibasic_rsp_result_t *result;
struct gpr_hdr *hdr = &data->hdr;
struct device *dev = &gdev->dev;
uint8_t *pkt = NULL;
uint16_t hdr_size, pkt_size;
unsigned long flags;
struct sk_buff *skb;
struct port_backup backup;
int ret;


hdr_size = hdr->hdr_size * 4;
pkt_size = hdr->pkt_size;

hdr_size = hdr->hdr_size * 4;
pkt_size = hdr->pkt_size;

ret = fifo_pop(&backup);
if (ret < 0)
AUDIO_PKT_ERR("Failed to pop backup ports from FIFO\n");
dev_dbg(dev, "Failed to pop backup ports from FIFO\n");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there AUDIO_PKT_DBG macro? Is AUDIO_PKT_ERR defined to allow log level change at run-time?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AUDIO_PKT_DBG macro not available and there is no log level AUDIO_PKT_ERR.


hdr->dest_port = backup.src_port;
hdr->src_port = backup.dest_port;
Expand Down
Loading
Loading