Skip to content

Commit

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

ASoC: Fixes for v5.3

A relatively large batch of mostly unremarkable fixes here, a couple of
small core fixes for fairly obscure issues, more comment/email updates
with no code impact than usual and a bunch of small driver fixes.

The support for new sample rates in the max98373 driver is a fix for the
fact that the driver declared support for those rates but would in fact
return an error if these rates were selected.
  • Loading branch information
tiwai committed Aug 6, 2019
2 parents 5d78e1c + 30c2173 commit c2913b1
Show file tree
Hide file tree
Showing 40 changed files with 304 additions and 147 deletions.
3 changes: 2 additions & 1 deletion MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -7871,6 +7871,7 @@ S: Maintained
F: drivers/video/fbdev/i810/

INTEL ASoC DRIVERS
M: Cezary Rojewski <[email protected]>
M: Pierre-Louis Bossart <[email protected]>
M: Liam Girdwood <[email protected]>
M: Jie Yang <[email protected]>
Expand Down Expand Up @@ -15805,7 +15806,7 @@ S: Maintained
F: drivers/net/ethernet/ti/netcp*

TI PCM3060 ASoC CODEC DRIVER
M: Kirill Marinushkin <kmarinushkin@birdec.tech>
M: Kirill Marinushkin <kmarinushkin@birdec.com>
L: [email protected] (moderated for non-subscribers)
S: Maintained
F: Documentation/devicetree/bindings/sound/pcm3060.txt
Expand Down
4 changes: 4 additions & 0 deletions include/sound/simple_card_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,10 @@ inline void asoc_simple_debug_dai(struct asoc_simple_priv *priv,
{
struct device *dev = simple_priv_to_dev(priv);

/* dai might be NULL */
if (!dai)
return;

if (dai->name)
dev_dbg(dev, "%s dai name = %s\n",
name, dai->name);
Expand Down
16 changes: 9 additions & 7 deletions include/uapi/sound/sof/fw.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
#ifndef __INCLUDE_UAPI_SOF_FW_H__
#define __INCLUDE_UAPI_SOF_FW_H__

#include <linux/types.h>

#define SND_SOF_FW_SIG_SIZE 4
#define SND_SOF_FW_ABI 1
#define SND_SOF_FW_SIG "Reef"
Expand Down Expand Up @@ -46,8 +48,8 @@ enum snd_sof_fw_blk_type {

struct snd_sof_blk_hdr {
enum snd_sof_fw_blk_type type;
uint32_t size; /* bytes minus this header */
uint32_t offset; /* offset from base */
__u32 size; /* bytes minus this header */
__u32 offset; /* offset from base */
} __packed;

/*
Expand All @@ -61,18 +63,18 @@ enum snd_sof_fw_mod_type {

struct snd_sof_mod_hdr {
enum snd_sof_fw_mod_type type;
uint32_t size; /* bytes minus this header */
uint32_t num_blocks; /* number of blocks */
__u32 size; /* bytes minus this header */
__u32 num_blocks; /* number of blocks */
} __packed;

/*
* Firmware file header.
*/
struct snd_sof_fw_header {
unsigned char sig[SND_SOF_FW_SIG_SIZE]; /* "Reef" */
uint32_t file_size; /* size of file minus this header */
uint32_t num_modules; /* number of modules */
uint32_t abi; /* version of header format */
__u32 file_size; /* size of file minus this header */
__u32 num_modules; /* number of modules */
__u32 abi; /* version of header format */
} __packed;

#endif
14 changes: 8 additions & 6 deletions include/uapi/sound/sof/header.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,21 @@
#ifndef __INCLUDE_UAPI_SOUND_SOF_USER_HEADER_H__
#define __INCLUDE_UAPI_SOUND_SOF_USER_HEADER_H__

#include <linux/types.h>

/*
* Header for all non IPC ABI data.
*
* Identifies data type, size and ABI.
* Used by any bespoke component data structures or binary blobs.
*/
struct sof_abi_hdr {
uint32_t magic; /**< 'S', 'O', 'F', '\0' */
uint32_t type; /**< component specific type */
uint32_t size; /**< size in bytes of data excl. this struct */
uint32_t abi; /**< SOF ABI version */
uint32_t reserved[4]; /**< reserved for future use */
uint32_t data[0]; /**< Component data - opaque to core */
__u32 magic; /**< 'S', 'O', 'F', '\0' */
__u32 type; /**< component specific type */
__u32 size; /**< size in bytes of data excl. this struct */
__u32 abi; /**< SOF ABI version */
__u32 reserved[4]; /**< reserved for future use */
__u32 data[0]; /**< Component data - opaque to core */
} __packed;

#endif
20 changes: 9 additions & 11 deletions sound/soc/amd/raven/acp3x-pcm-dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ struct i2s_stream_instance {
u16 num_pages;
u16 channels;
u32 xfer_resolution;
struct page *pg;
u64 bytescount;
dma_addr_t dma_addr;
void __iomem *acp3x_base;
};

Expand Down Expand Up @@ -211,9 +211,8 @@ static irqreturn_t i2s_irq_handler(int irq, void *dev_id)
static void config_acp3x_dma(struct i2s_stream_instance *rtd, int direction)
{
u16 page_idx;
u64 addr;
u32 low, high, val, acp_fifo_addr;
struct page *pg = rtd->pg;
dma_addr_t addr = rtd->dma_addr;

/* 8 scratch registers used to map one 64 bit address */
if (direction == SNDRV_PCM_STREAM_PLAYBACK)
Expand All @@ -229,7 +228,6 @@ static void config_acp3x_dma(struct i2s_stream_instance *rtd, int direction)

for (page_idx = 0; page_idx < rtd->num_pages; page_idx++) {
/* Load the low address of page int ACP SRAM through SRBM */
addr = page_to_phys(pg);
low = lower_32_bits(addr);
high = upper_32_bits(addr);

Expand All @@ -239,7 +237,7 @@ static void config_acp3x_dma(struct i2s_stream_instance *rtd, int direction)
+ 4);
/* Move to next physically contiguos page */
val += 8;
pg++;
addr += PAGE_SIZE;
}

if (direction == SNDRV_PCM_STREAM_PLAYBACK) {
Expand Down Expand Up @@ -341,7 +339,6 @@ static int acp3x_dma_hw_params(struct snd_pcm_substream *substream,
{
int status;
u64 size;
struct page *pg;
struct snd_pcm_runtime *runtime = substream->runtime;
struct i2s_stream_instance *rtd = runtime->private_data;

Expand All @@ -354,9 +351,8 @@ static int acp3x_dma_hw_params(struct snd_pcm_substream *substream,
return status;

memset(substream->runtime->dma_area, 0, params_buffer_bytes(params));
pg = virt_to_page(substream->dma_buffer.area);
if (pg) {
rtd->pg = pg;
if (substream->dma_buffer.area) {
rtd->dma_addr = substream->dma_buffer.addr;
rtd->num_pages = (PAGE_ALIGN(size) >> PAGE_SHIFT);
config_acp3x_dma(rtd, substream->stream);
status = 0;
Expand Down Expand Up @@ -385,9 +381,11 @@ static snd_pcm_uframes_t acp3x_dma_pointer(struct snd_pcm_substream *substream)

static int acp3x_dma_new(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,
rtd->pcm->card->dev,
MIN_BUFFER, MAX_BUFFER);
parent, MIN_BUFFER, MAX_BUFFER);
return 0;
}

Expand Down
116 changes: 97 additions & 19 deletions sound/soc/codecs/cs42xx8.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ struct cs42xx8_priv {
unsigned long sysclk;
u32 tx_channels;
struct gpio_desc *gpiod_reset;
u32 rate[2];
};

/* -127.5dB to 0dB with step of 0.5dB */
Expand Down Expand Up @@ -176,21 +177,27 @@ static const struct snd_soc_dapm_route cs42xx8_adc3_dapm_routes[] = {
};

struct cs42xx8_ratios {
unsigned int ratio;
unsigned char speed;
unsigned char mclk;
unsigned int mfreq;
unsigned int min_mclk;
unsigned int max_mclk;
unsigned int ratio[3];
};

/*
* According to reference mannual, define the cs42xx8_ratio struct
* MFreq2 | MFreq1 | MFreq0 | Description | SSM | DSM | QSM |
* 0 | 0 | 0 |1.029MHz to 12.8MHz | 256 | 128 | 64 |
* 0 | 0 | 1 |1.536MHz to 19.2MHz | 384 | 192 | 96 |
* 0 | 1 | 0 |2.048MHz to 25.6MHz | 512 | 256 | 128 |
* 0 | 1 | 1 |3.072MHz to 38.4MHz | 768 | 384 | 192 |
* 1 | x | x |4.096MHz to 51.2MHz |1024 | 512 | 256 |
*/
static const struct cs42xx8_ratios cs42xx8_ratios[] = {
{ 64, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_256(4) },
{ 96, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_384(4) },
{ 128, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_512(4) },
{ 192, CS42XX8_FM_QUAD, CS42XX8_FUNCMOD_MFREQ_768(4) },
{ 256, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_256(1) },
{ 384, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_384(1) },
{ 512, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_512(1) },
{ 768, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_768(1) },
{ 1024, CS42XX8_FM_SINGLE, CS42XX8_FUNCMOD_MFREQ_1024(1) }
{ 0, 1029000, 12800000, {256, 128, 64} },
{ 2, 1536000, 19200000, {384, 192, 96} },
{ 4, 2048000, 25600000, {512, 256, 128} },
{ 6, 3072000, 38400000, {768, 384, 192} },
{ 8, 4096000, 51200000, {1024, 512, 256} },
};

static int cs42xx8_set_dai_sysclk(struct snd_soc_dai *codec_dai,
Expand Down Expand Up @@ -257,14 +264,68 @@ static int cs42xx8_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_component *component = dai->component;
struct cs42xx8_priv *cs42xx8 = snd_soc_component_get_drvdata(component);
bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
u32 ratio = cs42xx8->sysclk / params_rate(params);
u32 i, fm, val, mask;
u32 ratio[2];
u32 rate[2];
u32 fm[2];
u32 i, val, mask;
bool condition1, condition2;

if (tx)
cs42xx8->tx_channels = params_channels(params);

rate[tx] = params_rate(params);
rate[!tx] = cs42xx8->rate[!tx];

ratio[tx] = rate[tx] > 0 ? cs42xx8->sysclk / rate[tx] : 0;
ratio[!tx] = rate[!tx] > 0 ? cs42xx8->sysclk / rate[!tx] : 0;

/* Get functional mode for tx and rx according to rate */
for (i = 0; i < 2; i++) {
if (cs42xx8->slave_mode) {
fm[i] = CS42XX8_FM_AUTO;
} else {
if (rate[i] < 50000) {
fm[i] = CS42XX8_FM_SINGLE;
} else if (rate[i] > 50000 && rate[i] < 100000) {
fm[i] = CS42XX8_FM_DOUBLE;
} else if (rate[i] > 100000 && rate[i] < 200000) {
fm[i] = CS42XX8_FM_QUAD;
} else {
dev_err(component->dev,
"unsupported sample rate\n");
return -EINVAL;
}
}
}

for (i = 0; i < ARRAY_SIZE(cs42xx8_ratios); i++) {
if (cs42xx8_ratios[i].ratio == ratio)
/* Is the ratio[tx] valid ? */
condition1 = ((fm[tx] == CS42XX8_FM_AUTO) ?
(cs42xx8_ratios[i].ratio[0] == ratio[tx] ||
cs42xx8_ratios[i].ratio[1] == ratio[tx] ||
cs42xx8_ratios[i].ratio[2] == ratio[tx]) :
(cs42xx8_ratios[i].ratio[fm[tx]] == ratio[tx])) &&
cs42xx8->sysclk >= cs42xx8_ratios[i].min_mclk &&
cs42xx8->sysclk <= cs42xx8_ratios[i].max_mclk;

if (!ratio[tx])
condition1 = true;

/* Is the ratio[!tx] valid ? */
condition2 = ((fm[!tx] == CS42XX8_FM_AUTO) ?
(cs42xx8_ratios[i].ratio[0] == ratio[!tx] ||
cs42xx8_ratios[i].ratio[1] == ratio[!tx] ||
cs42xx8_ratios[i].ratio[2] == ratio[!tx]) :
(cs42xx8_ratios[i].ratio[fm[!tx]] == ratio[!tx]));

if (!ratio[!tx])
condition2 = true;

/*
* Both ratio[tx] and ratio[!tx] is valid, then we get
* a proper MFreq.
*/
if (condition1 && condition2)
break;
}

Expand All @@ -273,15 +334,31 @@ static int cs42xx8_hw_params(struct snd_pcm_substream *substream,
return -EINVAL;
}

mask = CS42XX8_FUNCMOD_MFREQ_MASK;
val = cs42xx8_ratios[i].mclk;
cs42xx8->rate[tx] = params_rate(params);

fm = cs42xx8->slave_mode ? CS42XX8_FM_AUTO : cs42xx8_ratios[i].speed;
mask = CS42XX8_FUNCMOD_MFREQ_MASK;
val = cs42xx8_ratios[i].mfreq;

regmap_update_bits(cs42xx8->regmap, CS42XX8_FUNCMOD,
CS42XX8_FUNCMOD_xC_FM_MASK(tx) | mask,
CS42XX8_FUNCMOD_xC_FM(tx, fm) | val);
CS42XX8_FUNCMOD_xC_FM(tx, fm[tx]) | val);

return 0;
}

static int cs42xx8_hw_free(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_component *component = dai->component;
struct cs42xx8_priv *cs42xx8 = snd_soc_component_get_drvdata(component);
bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;

/* Clear stored rate */
cs42xx8->rate[tx] = 0;

regmap_update_bits(cs42xx8->regmap, CS42XX8_FUNCMOD,
CS42XX8_FUNCMOD_xC_FM_MASK(tx),
CS42XX8_FUNCMOD_xC_FM(tx, CS42XX8_FM_AUTO));
return 0;
}

Expand All @@ -302,6 +379,7 @@ static const struct snd_soc_dai_ops cs42xx8_dai_ops = {
.set_fmt = cs42xx8_set_dai_fmt,
.set_sysclk = cs42xx8_set_dai_sysclk,
.hw_params = cs42xx8_hw_params,
.hw_free = cs42xx8_hw_free,
.digital_mute = cs42xx8_digital_mute,
};

Expand Down
Loading

0 comments on commit c2913b1

Please sign in to comment.