Skip to content

Commit

Permalink
ASoC: sigmadsp: Restructure in preparation for fw v2 support
Browse files Browse the repository at this point in the history
The v2 file format of the SigmaDSP takes a more declarative style compared
to the imperative style of the v1 format. In addition some features that are
supported with v2 require the driver to keep state around for the firmware.
This requires a bit of restructuring of both the firmware loader itself and
the drivers making use of the firmware loader.

Instead of loading and executing the firmware in place when the DSP is
configured the firmware is now loaded at driver probe time. This is required
since the new firmware format will in addition to the firmware data itself
contain meta information describing the firmware and its requirements and
capabilities. Those will for example be used to restrict the supported
samplerates advertised by the driver to userspace to the list of samplerates
supported for the firmware.

This only does the restructuring required by the v2 format, but does not
yet add support for the new format itself.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Mark Brown <broonie@kernel.org>
  • Loading branch information
Lars-Peter Clausen authored and Mark Brown committed Nov 20, 2014
1 parent 6b25730 commit d48b088
Show file tree
Hide file tree
Showing 9 changed files with 424 additions and 121 deletions.
33 changes: 28 additions & 5 deletions sound/soc/codecs/adau1701.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ struct adau1701 {
unsigned int sysclk;
struct regmap *regmap;
u8 pin_config[12];

struct sigmadsp *sigmadsp;
};

static const struct snd_kcontrol_new adau1701_controls[] = {
Expand Down Expand Up @@ -238,12 +240,14 @@ static int adau1701_reg_read(void *context, unsigned int reg,
return 0;
}

static int adau1701_reset(struct snd_soc_codec *codec, unsigned int clkdiv)
static int adau1701_reset(struct snd_soc_codec *codec, unsigned int clkdiv,
unsigned int rate)
{
struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec);
struct i2c_client *client = to_i2c_client(codec->dev);
int ret;

sigmadsp_reset(adau1701->sigmadsp);

if (clkdiv != ADAU1707_CLKDIV_UNSET &&
gpio_is_valid(adau1701->gpio_pll_mode[0]) &&
gpio_is_valid(adau1701->gpio_pll_mode[1])) {
Expand Down Expand Up @@ -284,7 +288,7 @@ static int adau1701_reset(struct snd_soc_codec *codec, unsigned int clkdiv)
* know the correct PLL setup
*/
if (clkdiv != ADAU1707_CLKDIV_UNSET) {
ret = process_sigma_firmware(client, ADAU1701_FIRMWARE);
ret = sigmadsp_setup(adau1701->sigmadsp, rate);
if (ret) {
dev_warn(codec->dev, "Failed to load firmware\n");
return ret;
Expand Down Expand Up @@ -385,7 +389,7 @@ static int adau1701_hw_params(struct snd_pcm_substream *substream,
* firmware upload.
*/
if (clkdiv != adau1701->pll_clkdiv) {
ret = adau1701_reset(codec, clkdiv);
ret = adau1701_reset(codec, clkdiv, params_rate(params));
if (ret < 0)
return ret;
}
Expand Down Expand Up @@ -554,6 +558,14 @@ static int adau1701_set_sysclk(struct snd_soc_codec *codec, int clk_id,
return 0;
}

static int adau1701_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(dai->codec);

return sigmadsp_restrict_params(adau1701->sigmadsp, substream);
}

#define ADAU1701_RATES (SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | \
SNDRV_PCM_RATE_192000)

Expand All @@ -564,6 +576,7 @@ static const struct snd_soc_dai_ops adau1701_dai_ops = {
.set_fmt = adau1701_set_dai_fmt,
.hw_params = adau1701_hw_params,
.digital_mute = adau1701_digital_mute,
.startup = adau1701_startup,
};

static struct snd_soc_dai_driver adau1701_dai = {
Expand Down Expand Up @@ -600,6 +613,10 @@ static int adau1701_probe(struct snd_soc_codec *codec)
unsigned int val;
struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec);

ret = sigmadsp_attach(adau1701->sigmadsp, &codec->component);
if (ret)
return ret;

/*
* Let the pll_clkdiv variable default to something that won't happen
* at runtime. That way, we can postpone the firmware download from
Expand All @@ -609,7 +626,7 @@ static int adau1701_probe(struct snd_soc_codec *codec)
adau1701->pll_clkdiv = ADAU1707_CLKDIV_UNSET;

/* initalize with pre-configured pll mode settings */
ret = adau1701_reset(codec, adau1701->pll_clkdiv);
ret = adau1701_reset(codec, adau1701->pll_clkdiv, 0);
if (ret < 0)
return ret;

Expand Down Expand Up @@ -722,6 +739,12 @@ static int adau1701_i2c_probe(struct i2c_client *client,
adau1701->gpio_pll_mode[1] = gpio_pll_mode[1];

i2c_set_clientdata(client, adau1701);

adau1701->sigmadsp = devm_sigmadsp_init_i2c(client, NULL,
ADAU1701_FIRMWARE);
if (IS_ERR(adau1701->sigmadsp))
return PTR_ERR(adau1701->sigmadsp);

ret = snd_soc_register_codec(&client->dev, &adau1701_codec_drv,
&adau1701_dai, 1);
return ret;
Expand Down
21 changes: 10 additions & 11 deletions sound/soc/codecs/adau1761.c
Original file line number Diff line number Diff line change
Expand Up @@ -698,11 +698,6 @@ static int adau1761_codec_probe(struct snd_soc_codec *codec)
ARRAY_SIZE(adau1761_dapm_routes));
if (ret)
return ret;

ret = adau17x1_load_firmware(adau, codec->dev,
ADAU1761_FIRMWARE);
if (ret)
dev_warn(codec->dev, "Failed to firmware\n");
}

ret = adau17x1_add_routes(codec);
Expand Down Expand Up @@ -771,16 +766,20 @@ int adau1761_probe(struct device *dev, struct regmap *regmap,
enum adau17x1_type type, void (*switch_mode)(struct device *dev))
{
struct snd_soc_dai_driver *dai_drv;
const char *firmware_name;
int ret;

ret = adau17x1_probe(dev, regmap, type, switch_mode);
if (ret)
return ret;

if (type == ADAU1361)
if (type == ADAU1361) {
dai_drv = &adau1361_dai_driver;
else
firmware_name = NULL;
} else {
dai_drv = &adau1761_dai_driver;
firmware_name = ADAU1761_FIRMWARE;
}

ret = adau17x1_probe(dev, regmap, type, switch_mode, firmware_name);
if (ret)
return ret;

return snd_soc_register_codec(dev, &adau1761_codec_driver, dai_drv, 1);
}
Expand Down
30 changes: 13 additions & 17 deletions sound/soc/codecs/adau1781.c
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,6 @@ static int adau1781_codec_probe(struct snd_soc_codec *codec)
{
struct adau1781_platform_data *pdata = dev_get_platdata(codec->dev);
struct adau *adau = snd_soc_codec_get_drvdata(codec);
const char *firmware;
int ret;

ret = adau17x1_add_widgets(codec);
Expand Down Expand Up @@ -422,25 +421,10 @@ static int adau1781_codec_probe(struct snd_soc_codec *codec)
return ret;
}

switch (adau->type) {
case ADAU1381:
firmware = ADAU1381_FIRMWARE;
break;
case ADAU1781:
firmware = ADAU1781_FIRMWARE;
break;
default:
return -EINVAL;
}

ret = adau17x1_add_routes(codec);
if (ret < 0)
return ret;

ret = adau17x1_load_firmware(adau, codec->dev, firmware);
if (ret)
dev_warn(codec->dev, "Failed to load firmware\n");

return 0;
}

Expand Down Expand Up @@ -495,9 +479,21 @@ EXPORT_SYMBOL_GPL(adau1781_regmap_config);
int adau1781_probe(struct device *dev, struct regmap *regmap,
enum adau17x1_type type, void (*switch_mode)(struct device *dev))
{
const char *firmware_name;
int ret;

ret = adau17x1_probe(dev, regmap, type, switch_mode);
switch (type) {
case ADAU1381:
firmware_name = ADAU1381_FIRMWARE;
break;
case ADAU1781:
firmware_name = ADAU1781_FIRMWARE;
break;
default:
return -EINVAL;
}

ret = adau17x1_probe(dev, regmap, type, switch_mode, firmware_name);
if (ret)
return ret;

Expand Down
54 changes: 48 additions & 6 deletions sound/soc/codecs/adau17x1.c
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,7 @@ static int adau17x1_hw_params(struct snd_pcm_substream *substream,
struct adau *adau = snd_soc_codec_get_drvdata(codec);
unsigned int val, div, dsp_div;
unsigned int freq;
int ret;

if (adau->clk_src == ADAU17X1_CLK_SRC_PLL)
freq = adau->pll_freq;
Expand Down Expand Up @@ -356,6 +357,12 @@ static int adau17x1_hw_params(struct snd_pcm_substream *substream,
regmap_write(adau->regmap, ADAU17X1_DSP_SAMPLING_RATE, dsp_div);
}

if (adau->sigmadsp) {
ret = adau17x1_setup_firmware(adau, params_rate(params));
if (ret < 0)
return ret;
}

if (adau->dai_fmt != SND_SOC_DAIFMT_RIGHT_J)
return 0;

Expand Down Expand Up @@ -661,12 +668,24 @@ static int adau17x1_set_dai_tdm_slot(struct snd_soc_dai *dai,
return 0;
}

static int adau17x1_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct adau *adau = snd_soc_codec_get_drvdata(dai->codec);

if (adau->sigmadsp)
return sigmadsp_restrict_params(adau->sigmadsp, substream);

return 0;
}

const struct snd_soc_dai_ops adau17x1_dai_ops = {
.hw_params = adau17x1_hw_params,
.set_sysclk = adau17x1_set_dai_sysclk,
.set_fmt = adau17x1_set_dai_fmt,
.set_pll = adau17x1_set_dai_pll,
.set_tdm_slot = adau17x1_set_dai_tdm_slot,
.startup = adau17x1_startup,
};
EXPORT_SYMBOL_GPL(adau17x1_dai_ops);

Expand Down Expand Up @@ -745,8 +764,7 @@ bool adau17x1_volatile_register(struct device *dev, unsigned int reg)
}
EXPORT_SYMBOL_GPL(adau17x1_volatile_register);

int adau17x1_load_firmware(struct adau *adau, struct device *dev,
const char *firmware)
int adau17x1_setup_firmware(struct adau *adau, unsigned int rate)
{
int ret;
int dspsr;
Expand All @@ -758,7 +776,7 @@ int adau17x1_load_firmware(struct adau *adau, struct device *dev,
regmap_write(adau->regmap, ADAU17X1_DSP_ENABLE, 1);
regmap_write(adau->regmap, ADAU17X1_DSP_SAMPLING_RATE, 0xf);

ret = process_sigma_firmware_regmap(dev, adau->regmap, firmware);
ret = sigmadsp_setup(adau->sigmadsp, rate);
if (ret) {
regmap_write(adau->regmap, ADAU17X1_DSP_ENABLE, 0);
return ret;
Expand All @@ -767,7 +785,7 @@ int adau17x1_load_firmware(struct adau *adau, struct device *dev,

return 0;
}
EXPORT_SYMBOL_GPL(adau17x1_load_firmware);
EXPORT_SYMBOL_GPL(adau17x1_setup_firmware);

int adau17x1_add_widgets(struct snd_soc_codec *codec)
{
Expand All @@ -787,8 +805,21 @@ int adau17x1_add_widgets(struct snd_soc_codec *codec)
ret = snd_soc_dapm_new_controls(&codec->dapm,
adau17x1_dsp_dapm_widgets,
ARRAY_SIZE(adau17x1_dsp_dapm_widgets));
if (ret)
return ret;

if (!adau->sigmadsp)
return 0;

ret = sigmadsp_attach(adau->sigmadsp, &codec->component);
if (ret) {
dev_err(codec->dev, "Failed to attach firmware: %d\n",
ret);
return ret;
}
}
return ret;

return 0;
}
EXPORT_SYMBOL_GPL(adau17x1_add_widgets);

Expand Down Expand Up @@ -829,7 +860,8 @@ int adau17x1_resume(struct snd_soc_codec *codec)
EXPORT_SYMBOL_GPL(adau17x1_resume);

int adau17x1_probe(struct device *dev, struct regmap *regmap,
enum adau17x1_type type, void (*switch_mode)(struct device *dev))
enum adau17x1_type type, void (*switch_mode)(struct device *dev),
const char *firmware_name)
{
struct adau *adau;

Expand All @@ -846,6 +878,16 @@ int adau17x1_probe(struct device *dev, struct regmap *regmap,

dev_set_drvdata(dev, adau);

if (firmware_name) {
adau->sigmadsp = devm_sigmadsp_init_regmap(dev, regmap, NULL,
firmware_name);
if (IS_ERR(adau->sigmadsp)) {
dev_warn(dev, "Could not find firmware file: %ld\n",
PTR_ERR(adau->sigmadsp));
adau->sigmadsp = NULL;
}
}

if (switch_mode)
switch_mode(dev);

Expand Down
9 changes: 6 additions & 3 deletions sound/soc/codecs/adau17x1.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#include <linux/regmap.h>
#include <linux/platform_data/adau17x1.h>

#include "sigmadsp.h"

enum adau17x1_type {
ADAU1361,
ADAU1761,
Expand Down Expand Up @@ -42,12 +44,14 @@ struct adau {
bool dsp_bypass[2];

struct regmap *regmap;
struct sigmadsp *sigmadsp;
};

int adau17x1_add_widgets(struct snd_soc_codec *codec);
int adau17x1_add_routes(struct snd_soc_codec *codec);
int adau17x1_probe(struct device *dev, struct regmap *regmap,
enum adau17x1_type type, void (*switch_mode)(struct device *dev));
enum adau17x1_type type, void (*switch_mode)(struct device *dev),
const char *firmware_name);
int adau17x1_set_micbias_voltage(struct snd_soc_codec *codec,
enum adau17x1_micbias_voltage micbias);
bool adau17x1_readable_register(struct device *dev, unsigned int reg);
Expand All @@ -56,8 +60,7 @@ int adau17x1_resume(struct snd_soc_codec *codec);

extern const struct snd_soc_dai_ops adau17x1_dai_ops;

int adau17x1_load_firmware(struct adau *adau, struct device *dev,
const char *firmware);
int adau17x1_setup_firmware(struct adau *adau, unsigned int rate);
bool adau17x1_has_dsp(struct adau *adau);

#define ADAU17X1_CLOCK_CONTROL 0x4000
Expand Down
Loading

0 comments on commit d48b088

Please sign in to comment.