Skip to content

Commit

Permalink
Merge tag 'asoc-fix-v6.15-merge-window' of https://git.kernel.org/pub…
Browse files Browse the repository at this point in the history
…/scm/linux/kernel/git/broonie/sound into for-linus

ASoC: Fixes for v6.15

A relatively large set of fixes that came in since the release, mostly
for Qualcomm platforms.  The biggest block of fixes is the set from
Srini which fixes various quality and glitching issues on AudioReach
systems.
  • Loading branch information
Takashi Iwai committed Apr 2, 2025
2 parents 8983dc1 + 93d3460 commit 02dc9b9
Show file tree
Hide file tree
Showing 14 changed files with 128 additions and 70 deletions.
2 changes: 2 additions & 0 deletions drivers/firmware/cirrus/cs_dsp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1631,6 +1631,7 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware,

cs_dsp_debugfs_save_wmfwname(dsp, file);

ret = 0;
out_fw:
cs_dsp_buf_free(&buf_list);

Expand Down Expand Up @@ -2338,6 +2339,7 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware

cs_dsp_debugfs_save_binname(dsp, file);

ret = 0;
out_fw:
cs_dsp_buf_free(&buf_list);

Expand Down
24 changes: 4 additions & 20 deletions sound/soc/codecs/rt5665.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,7 @@
#include "rl6231.h"
#include "rt5665.h"

#define RT5665_NUM_SUPPLIES 3

static const char *rt5665_supply_names[RT5665_NUM_SUPPLIES] = {
static const char * const rt5665_supply_names[] = {
"AVDD",
"MICVDD",
"VBAT",
Expand All @@ -46,7 +44,6 @@ struct rt5665_priv {
struct gpio_desc *gpiod_ldo1_en;
struct gpio_desc *gpiod_reset;
struct snd_soc_jack *hs_jack;
struct regulator_bulk_data supplies[RT5665_NUM_SUPPLIES];
struct delayed_work jack_detect_work;
struct delayed_work calibrate_work;
struct delayed_work jd_check_work;
Expand Down Expand Up @@ -4471,8 +4468,6 @@ static void rt5665_remove(struct snd_soc_component *component)
struct rt5665_priv *rt5665 = snd_soc_component_get_drvdata(component);

regmap_write(rt5665->regmap, RT5665_RESET, 0);

regulator_bulk_disable(ARRAY_SIZE(rt5665->supplies), rt5665->supplies);
}

#ifdef CONFIG_PM
Expand Down Expand Up @@ -4758,7 +4753,7 @@ static int rt5665_i2c_probe(struct i2c_client *i2c)
{
struct rt5665_platform_data *pdata = dev_get_platdata(&i2c->dev);
struct rt5665_priv *rt5665;
int i, ret;
int ret;
unsigned int val;

rt5665 = devm_kzalloc(&i2c->dev, sizeof(struct rt5665_priv),
Expand All @@ -4774,24 +4769,13 @@ static int rt5665_i2c_probe(struct i2c_client *i2c)
else
rt5665_parse_dt(rt5665, &i2c->dev);

for (i = 0; i < ARRAY_SIZE(rt5665->supplies); i++)
rt5665->supplies[i].supply = rt5665_supply_names[i];

ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(rt5665->supplies),
rt5665->supplies);
ret = devm_regulator_bulk_get_enable(&i2c->dev, ARRAY_SIZE(rt5665_supply_names),
rt5665_supply_names);
if (ret != 0) {
dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret);
return ret;
}

ret = regulator_bulk_enable(ARRAY_SIZE(rt5665->supplies),
rt5665->supplies);
if (ret != 0) {
dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret);
return ret;
}


rt5665->gpiod_ldo1_en = devm_gpiod_get_optional(&i2c->dev,
"realtek,ldo1-en",
GPIOD_OUT_HIGH);
Expand Down
11 changes: 2 additions & 9 deletions sound/soc/codecs/sma1307.c
Original file line number Diff line number Diff line change
Expand Up @@ -1705,7 +1705,7 @@ static void sma1307_check_fault_worker(struct work_struct *work)
static void sma1307_setting_loaded(struct sma1307_priv *sma1307, const char *file)
{
const struct firmware *fw;
int *data, size, offset, num_mode;
int size, offset, num_mode;
int ret;

ret = request_firmware(&fw, file, sma1307->dev);
Expand All @@ -1722,7 +1722,7 @@ static void sma1307_setting_loaded(struct sma1307_priv *sma1307, const char *fil
return;
}

data = kzalloc(fw->size, GFP_KERNEL);
int *data __free(kfree) = kzalloc(fw->size, GFP_KERNEL);
if (!data) {
release_firmware(fw);
sma1307->set.status = false;
Expand All @@ -1742,7 +1742,6 @@ static void sma1307_setting_loaded(struct sma1307_priv *sma1307, const char *fil
sma1307->set.header_size,
GFP_KERNEL);
if (!sma1307->set.header) {
kfree(data);
sma1307->set.status = false;
return;
}
Expand All @@ -1763,8 +1762,6 @@ static void sma1307_setting_loaded(struct sma1307_priv *sma1307, const char *fil
= devm_kzalloc(sma1307->dev,
sma1307->set.def_size * sizeof(int), GFP_KERNEL);
if (!sma1307->set.def) {
kfree(data);
kfree(sma1307->set.header);
sma1307->set.status = false;
return;
}
Expand All @@ -1782,9 +1779,6 @@ static void sma1307_setting_loaded(struct sma1307_priv *sma1307, const char *fil
sma1307->set.mode_size * 2 * sizeof(int),
GFP_KERNEL);
if (!sma1307->set.mode_set[i]) {
kfree(data);
kfree(sma1307->set.header);
kfree(sma1307->set.def);
for (int j = 0; j < i; j++)
kfree(sma1307->set.mode_set[j]);
sma1307->set.status = false;
Expand All @@ -1799,7 +1793,6 @@ static void sma1307_setting_loaded(struct sma1307_priv *sma1307, const char *fil
}
}

kfree(data);
sma1307->set.status = true;

}
Expand Down
2 changes: 1 addition & 1 deletion sound/soc/codecs/wsa883x.c
Original file line number Diff line number Diff line change
Expand Up @@ -568,7 +568,7 @@ static const struct sdw_port_config wsa883x_pconfig[WSA883X_MAX_SWR_PORTS] = {
},
[WSA883X_PORT_VISENSE] = {
.num = WSA883X_PORT_VISENSE + 1,
.ch_mask = 0x3,
.ch_mask = 0x1,
},
};

Expand Down
2 changes: 1 addition & 1 deletion sound/soc/codecs/wsa884x.c
Original file line number Diff line number Diff line change
Expand Up @@ -891,7 +891,7 @@ static const struct sdw_port_config wsa884x_pconfig[WSA884X_MAX_SWR_PORTS] = {
},
[WSA884X_PORT_VISENSE] = {
.num = WSA884X_PORT_VISENSE + 1,
.ch_mask = 0x3,
.ch_mask = 0x1,
},
[WSA884X_PORT_CPS] = {
.num = WSA884X_PORT_CPS + 1,
Expand Down
4 changes: 4 additions & 0 deletions sound/soc/fsl/imx-card.c
Original file line number Diff line number Diff line change
Expand Up @@ -772,6 +772,8 @@ static int imx_card_probe(struct platform_device *pdev)
data->dapm_routes[i].sink =
devm_kasprintf(&pdev->dev, GFP_KERNEL, "%d %s",
i + 1, "Playback");
if (!data->dapm_routes[i].sink)
return -ENOMEM;
data->dapm_routes[i].source = "CPU-Playback";
}
}
Expand All @@ -789,6 +791,8 @@ static int imx_card_probe(struct platform_device *pdev)
data->dapm_routes[i].source =
devm_kasprintf(&pdev->dev, GFP_KERNEL, "%d %s",
i + 1, "Capture");
if (!data->dapm_routes[i].source)
return -ENOMEM;
data->dapm_routes[i].sink = "CPU-Capture";
}
}
Expand Down
60 changes: 32 additions & 28 deletions sound/soc/qcom/qdsp6/q6apm-dai.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@
#define PLAYBACK_MIN_PERIOD_SIZE 128
#define CAPTURE_MIN_NUM_PERIODS 2
#define CAPTURE_MAX_NUM_PERIODS 8
#define CAPTURE_MAX_PERIOD_SIZE 4096
#define CAPTURE_MIN_PERIOD_SIZE 320
#define CAPTURE_MAX_PERIOD_SIZE 65536
#define CAPTURE_MIN_PERIOD_SIZE 6144
#define BUFFER_BYTES_MAX (PLAYBACK_MAX_NUM_PERIODS * PLAYBACK_MAX_PERIOD_SIZE)
#define BUFFER_BYTES_MIN (PLAYBACK_MIN_NUM_PERIODS * PLAYBACK_MIN_PERIOD_SIZE)
#define COMPR_PLAYBACK_MAX_FRAGMENT_SIZE (128 * 1024)
Expand Down Expand Up @@ -64,12 +64,12 @@ struct q6apm_dai_rtd {
phys_addr_t phys;
unsigned int pcm_size;
unsigned int pcm_count;
unsigned int pos; /* Buffer position */
unsigned int periods;
unsigned int bytes_sent;
unsigned int bytes_received;
unsigned int copied_total;
uint16_t bits_per_sample;
snd_pcm_uframes_t queue_ptr;
bool next_track;
enum stream_state state;
struct q6apm_graph *graph;
Expand Down Expand Up @@ -123,25 +123,16 @@ static void event_handler(uint32_t opcode, uint32_t token, void *payload, void *
{
struct q6apm_dai_rtd *prtd = priv;
struct snd_pcm_substream *substream = prtd->substream;
unsigned long flags;

switch (opcode) {
case APM_CLIENT_EVENT_CMD_EOS_DONE:
prtd->state = Q6APM_STREAM_STOPPED;
break;
case APM_CLIENT_EVENT_DATA_WRITE_DONE:
spin_lock_irqsave(&prtd->lock, flags);
prtd->pos += prtd->pcm_count;
spin_unlock_irqrestore(&prtd->lock, flags);
snd_pcm_period_elapsed(substream);
if (prtd->state == Q6APM_STREAM_RUNNING)
q6apm_write_async(prtd->graph, prtd->pcm_count, 0, 0, 0);

break;
case APM_CLIENT_EVENT_DATA_READ_DONE:
spin_lock_irqsave(&prtd->lock, flags);
prtd->pos += prtd->pcm_count;
spin_unlock_irqrestore(&prtd->lock, flags);
snd_pcm_period_elapsed(substream);
if (prtd->state == Q6APM_STREAM_RUNNING)
q6apm_read(prtd->graph);
Expand Down Expand Up @@ -248,7 +239,6 @@ static int q6apm_dai_prepare(struct snd_soc_component *component,
}

prtd->pcm_count = snd_pcm_lib_period_bytes(substream);
prtd->pos = 0;
/* rate and channels are sent to audio driver */
ret = q6apm_graph_media_format_shmem(prtd->graph, &cfg);
if (ret < 0) {
Expand Down Expand Up @@ -294,6 +284,27 @@ static int q6apm_dai_prepare(struct snd_soc_component *component,
return 0;
}

static int q6apm_dai_ack(struct snd_soc_component *component, struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct q6apm_dai_rtd *prtd = runtime->private_data;
int i, ret = 0, avail_periods;

if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
avail_periods = (runtime->control->appl_ptr - prtd->queue_ptr)/runtime->period_size;
for (i = 0; i < avail_periods; i++) {
ret = q6apm_write_async(prtd->graph, prtd->pcm_count, 0, 0, NO_TIMESTAMP);
if (ret < 0) {
dev_err(component->dev, "Error queuing playback buffer %d\n", ret);
return ret;
}
prtd->queue_ptr += runtime->period_size;
}
}

return ret;
}

static int q6apm_dai_trigger(struct snd_soc_component *component,
struct snd_pcm_substream *substream, int cmd)
{
Expand All @@ -305,9 +316,6 @@ static int q6apm_dai_trigger(struct snd_soc_component *component,
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
/* start writing buffers for playback only as we already queued capture buffers */
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
ret = q6apm_write_async(prtd->graph, prtd->pcm_count, 0, 0, 0);
break;
case SNDRV_PCM_TRIGGER_STOP:
/* TODO support be handled via SoftPause Module */
Expand Down Expand Up @@ -377,13 +385,14 @@ static int q6apm_dai_open(struct snd_soc_component *component,
}
}

ret = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32);
/* setup 10ms latency to accommodate DSP restrictions */
ret = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 480);
if (ret < 0) {
dev_err(dev, "constraint for period bytes step ret = %d\n", ret);
goto err;
}

ret = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 32);
ret = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 480);
if (ret < 0) {
dev_err(dev, "constraint for buffer bytes step ret = %d\n", ret);
goto err;
Expand Down Expand Up @@ -428,16 +437,12 @@ static snd_pcm_uframes_t q6apm_dai_pointer(struct snd_soc_component *component,
struct snd_pcm_runtime *runtime = substream->runtime;
struct q6apm_dai_rtd *prtd = runtime->private_data;
snd_pcm_uframes_t ptr;
unsigned long flags;

spin_lock_irqsave(&prtd->lock, flags);
if (prtd->pos == prtd->pcm_size)
prtd->pos = 0;

ptr = bytes_to_frames(runtime, prtd->pos);
spin_unlock_irqrestore(&prtd->lock, flags);
ptr = q6apm_get_hw_pointer(prtd->graph, substream->stream) * runtime->period_size;
if (ptr)
return ptr - 1;

return ptr;
return 0;
}

static int q6apm_dai_hw_params(struct snd_soc_component *component,
Expand Down Expand Up @@ -652,8 +657,6 @@ static int q6apm_dai_compr_set_params(struct snd_soc_component *component,
prtd->pcm_size = runtime->fragments * runtime->fragment_size;
prtd->bits_per_sample = 16;

prtd->pos = 0;

if (prtd->next_track != true) {
memcpy(&prtd->codec, codec, sizeof(*codec));

Expand Down Expand Up @@ -836,6 +839,7 @@ static const struct snd_soc_component_driver q6apm_fe_dai_component = {
.hw_params = q6apm_dai_hw_params,
.pointer = q6apm_dai_pointer,
.trigger = q6apm_dai_trigger,
.ack = q6apm_dai_ack,
.compress_ops = &q6apm_dai_compress_ops,
.use_dai_pcm_id = true,
};
Expand Down
18 changes: 17 additions & 1 deletion sound/soc/qcom/qdsp6/q6apm.c
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,19 @@ int q6apm_read(struct q6apm_graph *graph)
}
EXPORT_SYMBOL_GPL(q6apm_read);

int q6apm_get_hw_pointer(struct q6apm_graph *graph, int dir)
{
struct audioreach_graph_data *data;

if (dir == SNDRV_PCM_STREAM_PLAYBACK)
data = &graph->rx_data;
else
data = &graph->tx_data;

return (int)atomic_read(&data->hw_ptr);
}
EXPORT_SYMBOL_GPL(q6apm_get_hw_pointer);

static int graph_callback(struct gpr_resp_pkt *data, void *priv, int op)
{
struct data_cmd_rsp_rd_sh_mem_ep_data_buffer_done_v2 *rd_done;
Expand All @@ -520,7 +533,8 @@ static int graph_callback(struct gpr_resp_pkt *data, void *priv, int op)
done = data->payload;
phys = graph->rx_data.buf[token].phys;
mutex_unlock(&graph->lock);

/* token numbering starts at 0 */
atomic_set(&graph->rx_data.hw_ptr, token + 1);
if (lower_32_bits(phys) == done->buf_addr_lsw &&
upper_32_bits(phys) == done->buf_addr_msw) {
graph->result.opcode = hdr->opcode;
Expand Down Expand Up @@ -553,6 +567,8 @@ static int graph_callback(struct gpr_resp_pkt *data, void *priv, int op)
rd_done = data->payload;
phys = graph->tx_data.buf[hdr->token].phys;
mutex_unlock(&graph->lock);
/* token numbering starts at 0 */
atomic_set(&graph->tx_data.hw_ptr, hdr->token + 1);

if (upper_32_bits(phys) == rd_done->buf_addr_msw &&
lower_32_bits(phys) == rd_done->buf_addr_lsw) {
Expand Down
3 changes: 3 additions & 0 deletions sound/soc/qcom/qdsp6/q6apm.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#ifndef __Q6APM_H__
#define __Q6APM_H__
#include <linux/types.h>
#include <linux/atomic.h>
#include <linux/slab.h>
#include <linux/wait.h>
#include <linux/kernel.h>
Expand Down Expand Up @@ -77,6 +78,7 @@ struct audioreach_graph_data {
uint32_t num_periods;
uint32_t dsp_buf;
uint32_t mem_map_handle;
atomic_t hw_ptr;
};

struct audioreach_graph {
Expand Down Expand Up @@ -150,4 +152,5 @@ int q6apm_enable_compress_module(struct device *dev, struct q6apm_graph *graph,
int q6apm_remove_initial_silence(struct device *dev, struct q6apm_graph *graph, uint32_t samples);
int q6apm_remove_trailing_silence(struct device *dev, struct q6apm_graph *graph, uint32_t samples);
int q6apm_set_real_module_id(struct device *dev, struct q6apm_graph *graph, uint32_t codec_id);
int q6apm_get_hw_pointer(struct q6apm_graph *graph, int dir);
#endif /* __APM_GRAPH_ */
Loading

0 comments on commit 02dc9b9

Please sign in to comment.