Merge tag 'asoc-fix-v5.3-rc3' of https://git.kernel.org/pub/scm/linux/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.
This commit is contained in:
@@ -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 */
|
||||
@@ -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,
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -273,18 +334,34 @@ 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;
|
||||
}
|
||||
|
||||
static int cs42xx8_digital_mute(struct snd_soc_dai *dai, int mute)
|
||||
{
|
||||
struct snd_soc_component *component = dai->component;
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
|
@@ -20,20 +20,10 @@
|
||||
#include <sound/soc-dapm.h>
|
||||
|
||||
struct max98357a_priv {
|
||||
struct delayed_work enable_sdmode_work;
|
||||
struct gpio_desc *sdmode;
|
||||
unsigned int sdmode_delay;
|
||||
};
|
||||
|
||||
static void max98357a_enable_sdmode_work(struct work_struct *work)
|
||||
{
|
||||
struct max98357a_priv *max98357a =
|
||||
container_of(work, struct max98357a_priv,
|
||||
enable_sdmode_work.work);
|
||||
|
||||
gpiod_set_value(max98357a->sdmode, 1);
|
||||
}
|
||||
|
||||
static int max98357a_daiops_trigger(struct snd_pcm_substream *substream,
|
||||
int cmd, struct snd_soc_dai *dai)
|
||||
{
|
||||
@@ -46,14 +36,12 @@ static int max98357a_daiops_trigger(struct snd_pcm_substream *substream,
|
||||
case SNDRV_PCM_TRIGGER_START:
|
||||
case SNDRV_PCM_TRIGGER_RESUME:
|
||||
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
|
||||
queue_delayed_work(system_power_efficient_wq,
|
||||
&max98357a->enable_sdmode_work,
|
||||
msecs_to_jiffies(max98357a->sdmode_delay));
|
||||
mdelay(max98357a->sdmode_delay);
|
||||
gpiod_set_value(max98357a->sdmode, 1);
|
||||
break;
|
||||
case SNDRV_PCM_TRIGGER_STOP:
|
||||
case SNDRV_PCM_TRIGGER_SUSPEND:
|
||||
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
|
||||
cancel_delayed_work_sync(&max98357a->enable_sdmode_work);
|
||||
gpiod_set_value(max98357a->sdmode, 0);
|
||||
break;
|
||||
}
|
||||
@@ -112,30 +100,25 @@ static int max98357a_platform_probe(struct platform_device *pdev)
|
||||
int ret;
|
||||
|
||||
max98357a = devm_kzalloc(&pdev->dev, sizeof(*max98357a), GFP_KERNEL);
|
||||
|
||||
if (!max98357a)
|
||||
return -ENOMEM;
|
||||
|
||||
max98357a->sdmode = devm_gpiod_get_optional(&pdev->dev,
|
||||
"sdmode", GPIOD_OUT_LOW);
|
||||
|
||||
if (IS_ERR(max98357a->sdmode))
|
||||
return PTR_ERR(max98357a->sdmode);
|
||||
|
||||
ret = device_property_read_u32(&pdev->dev, "sdmode-delay",
|
||||
&max98357a->sdmode_delay);
|
||||
|
||||
if (ret) {
|
||||
max98357a->sdmode_delay = 0;
|
||||
dev_dbg(&pdev->dev,
|
||||
"no optional property 'sdmode-delay' found, default: no delay\n");
|
||||
"no optional property 'sdmode-delay' found, "
|
||||
"default: no delay\n");
|
||||
}
|
||||
|
||||
dev_set_drvdata(&pdev->dev, max98357a);
|
||||
|
||||
INIT_DELAYED_WORK(&max98357a->enable_sdmode_work,
|
||||
max98357a_enable_sdmode_work);
|
||||
|
||||
return devm_snd_soc_register_component(&pdev->dev,
|
||||
&max98357a_component_driver,
|
||||
&max98357a_dai_driver, 1);
|
||||
|
6
sound/soc/codecs/max98373.c
Normal file → Executable file
6
sound/soc/codecs/max98373.c
Normal file → Executable file
@@ -267,6 +267,12 @@ static int max98373_dai_hw_params(struct snd_pcm_substream *substream,
|
||||
case 48000:
|
||||
sampling_rate = MAX98373_PCM_SR_SET1_SR_48000;
|
||||
break;
|
||||
case 88200:
|
||||
sampling_rate = MAX98373_PCM_SR_SET1_SR_88200;
|
||||
break;
|
||||
case 96000:
|
||||
sampling_rate = MAX98373_PCM_SR_SET1_SR_96000;
|
||||
break;
|
||||
default:
|
||||
dev_err(component->dev, "rate %d not supported\n",
|
||||
params_rate(params));
|
||||
|
2
sound/soc/codecs/max98373.h
Normal file → Executable file
2
sound/soc/codecs/max98373.h
Normal file → Executable file
@@ -130,6 +130,8 @@
|
||||
#define MAX98373_PCM_SR_SET1_SR_32000 (0x6 << 0)
|
||||
#define MAX98373_PCM_SR_SET1_SR_44100 (0x7 << 0)
|
||||
#define MAX98373_PCM_SR_SET1_SR_48000 (0x8 << 0)
|
||||
#define MAX98373_PCM_SR_SET1_SR_88200 (0x9 << 0)
|
||||
#define MAX98373_PCM_SR_SET1_SR_96000 (0xA << 0)
|
||||
|
||||
/* MAX98373_R2028_PCM_SR_SETUP_2 */
|
||||
#define MAX98373_PCM_SR_SET2_SR_MASK (0xF << 4)
|
||||
|
@@ -2,7 +2,7 @@
|
||||
//
|
||||
// PCM3060 I2C driver
|
||||
//
|
||||
// Copyright (C) 2018 Kirill Marinushkin <kmarinushkin@birdec.tech>
|
||||
// Copyright (C) 2018 Kirill Marinushkin <kmarinushkin@birdec.com>
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/module.h>
|
||||
@@ -56,5 +56,5 @@ static struct i2c_driver pcm3060_i2c_driver = {
|
||||
module_i2c_driver(pcm3060_i2c_driver);
|
||||
|
||||
MODULE_DESCRIPTION("PCM3060 I2C driver");
|
||||
MODULE_AUTHOR("Kirill Marinushkin <kmarinushkin@birdec.tech>");
|
||||
MODULE_AUTHOR("Kirill Marinushkin <kmarinushkin@birdec.com>");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
@@ -2,7 +2,7 @@
|
||||
//
|
||||
// PCM3060 SPI driver
|
||||
//
|
||||
// Copyright (C) 2018 Kirill Marinushkin <kmarinushkin@birdec.tech>
|
||||
// Copyright (C) 2018 Kirill Marinushkin <kmarinushkin@birdec.com>
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/spi/spi.h>
|
||||
@@ -55,5 +55,5 @@ static struct spi_driver pcm3060_spi_driver = {
|
||||
module_spi_driver(pcm3060_spi_driver);
|
||||
|
||||
MODULE_DESCRIPTION("PCM3060 SPI driver");
|
||||
MODULE_AUTHOR("Kirill Marinushkin <kmarinushkin@birdec.tech>");
|
||||
MODULE_AUTHOR("Kirill Marinushkin <kmarinushkin@birdec.com>");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
@@ -2,7 +2,7 @@
|
||||
//
|
||||
// PCM3060 codec driver
|
||||
//
|
||||
// Copyright (C) 2018 Kirill Marinushkin <kmarinushkin@birdec.tech>
|
||||
// Copyright (C) 2018 Kirill Marinushkin <kmarinushkin@birdec.com>
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <sound/pcm_params.h>
|
||||
@@ -342,5 +342,5 @@ int pcm3060_probe(struct device *dev)
|
||||
EXPORT_SYMBOL(pcm3060_probe);
|
||||
|
||||
MODULE_DESCRIPTION("PCM3060 codec driver");
|
||||
MODULE_AUTHOR("Kirill Marinushkin <kmarinushkin@birdec.tech>");
|
||||
MODULE_AUTHOR("Kirill Marinushkin <kmarinushkin@birdec.com>");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
@@ -2,7 +2,7 @@
|
||||
/*
|
||||
* PCM3060 codec driver
|
||||
*
|
||||
* Copyright (C) 2018 Kirill Marinushkin <kmarinushkin@birdec.tech>
|
||||
* Copyright (C) 2018 Kirill Marinushkin <kmarinushkin@birdec.com>
|
||||
*/
|
||||
|
||||
#ifndef _SND_SOC_PCM3060_H
|
||||
|
@@ -39,7 +39,7 @@ static const struct reg_sequence init_list[] = {
|
||||
{ RT1011_POWER_9, 0xa840 },
|
||||
|
||||
{ RT1011_ADC_SET_5, 0x0a20 },
|
||||
{ RT1011_DAC_SET_2, 0xa232 },
|
||||
{ RT1011_DAC_SET_2, 0xa032 },
|
||||
{ RT1011_ADC_SET_1, 0x2925 },
|
||||
|
||||
{ RT1011_SPK_PRO_DC_DET_1, 0xb00c },
|
||||
@@ -1917,7 +1917,7 @@ static int rt1011_set_bias_level(struct snd_soc_component *component,
|
||||
snd_soc_component_write(component,
|
||||
RT1011_SYSTEM_RESET_2, 0x0000);
|
||||
snd_soc_component_write(component,
|
||||
RT1011_SYSTEM_RESET_3, 0x0000);
|
||||
RT1011_SYSTEM_RESET_3, 0x0001);
|
||||
snd_soc_component_write(component,
|
||||
RT1011_SYSTEM_RESET_1, 0x003f);
|
||||
snd_soc_component_write(component,
|
||||
|
0
sound/soc/codecs/rt1308.c
Executable file → Normal file
0
sound/soc/codecs/rt1308.c
Executable file → Normal file
0
sound/soc/codecs/rt1308.h
Executable file → Normal file
0
sound/soc/codecs/rt1308.h
Executable file → Normal file
Reference in New Issue
Block a user