Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 631657c6 authored by Mark Brown's avatar Mark Brown
Browse files

Merge remote-tracking branches 'asoc/topic/sh', 'asoc/topic/sigmadsp',...

Merge remote-tracking branches 'asoc/topic/sh', 'asoc/topic/sigmadsp', 'asoc/topic/simple', 'asoc/topic/sirf' and 'asoc/topic/sn95031' into asoc-next
Loading
Loading
Loading
Loading
+7 −2
Original line number Diff line number Diff line
Renesas FSI

Required properties:
- compatible			: "renesas,sh_fsi2" or "renesas,sh_fsi"
- compatible			: "renesas,fsi2-<soctype>",
				  "renesas,sh_fsi2" or "renesas,sh_fsi" as
				  fallback.
				  Examples with soctypes are:
				    - "renesas,fsi2-r8a7740" (R-Mobile A1)
				    - "renesas,fsi2-sh73a0" (SH-Mobile AG5)
- reg				: Should contain the register physical address and length
- interrupts			: Should contain FSI interrupt

- fsia,spdif-connection		: FSI is connected by S/PDFI
- fsia,spdif-connection		: FSI is connected by S/PDIF
- fsia,stream-mode-support	: FSI supports 16bit stream mode.
- fsia,use-internal-clock	: FSI uses internal clock when master mode.

+81 −5
Original line number Diff line number Diff line
@@ -22,9 +22,14 @@
#include <sound/pcm_params.h>
#include <sound/soc.h>

#include <asm/unaligned.h>

#include "sigmadsp.h"
#include "adau1701.h"

#define ADAU1701_SAFELOAD_DATA(i) (0x0810 + (i))
#define ADAU1701_SAFELOAD_ADDR(i) (0x0815 + (i))

#define ADAU1701_DSPCTRL	0x081c
#define ADAU1701_SEROCTL	0x081e
#define ADAU1701_SERICTL	0x081f
@@ -42,6 +47,7 @@
#define ADAU1701_DSPCTRL_CR		(1 << 2)
#define ADAU1701_DSPCTRL_DAM		(1 << 3)
#define ADAU1701_DSPCTRL_ADM		(1 << 4)
#define ADAU1701_DSPCTRL_IST		(1 << 5)
#define ADAU1701_DSPCTRL_SR_48		0x00
#define ADAU1701_DSPCTRL_SR_96		0x01
#define ADAU1701_DSPCTRL_SR_192		0x02
@@ -102,7 +108,10 @@ struct adau1701 {
	unsigned int pll_clkdiv;
	unsigned int sysclk;
	struct regmap *regmap;
	struct i2c_client *client;
	u8 pin_config[12];

	struct sigmadsp *sigmadsp;
};

static const struct snd_kcontrol_new adau1701_controls[] = {
@@ -159,6 +168,7 @@ static bool adau1701_volatile_reg(struct device *dev, unsigned int reg)
{
	switch (reg) {
	case ADAU1701_DACSET:
	case ADAU1701_DSPCTRL:
		return true;
	default:
		return false;
@@ -238,12 +248,58 @@ 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_safeload(struct sigmadsp *sigmadsp, unsigned int addr,
	const uint8_t bytes[], size_t len)
{
	struct i2c_client *client = to_i2c_client(sigmadsp->dev);
	struct adau1701 *adau1701 = i2c_get_clientdata(client);
	unsigned int val;
	unsigned int i;
	uint8_t buf[10];
	int ret;

	ret = regmap_read(adau1701->regmap, ADAU1701_DSPCTRL, &val);
	if (ret)
		return ret;

	if (val & ADAU1701_DSPCTRL_IST)
		msleep(50);

	for (i = 0; i < len / 4; i++) {
		put_unaligned_le16(ADAU1701_SAFELOAD_DATA(i), buf);
		buf[2] = 0x00;
		memcpy(buf + 3, bytes + i * 4, 4);
		ret = i2c_master_send(client, buf, 7);
		if (ret < 0)
			return ret;
		else if (ret != 7)
			return -EIO;

		put_unaligned_le16(ADAU1701_SAFELOAD_ADDR(i), buf);
		put_unaligned_le16(addr + i, buf + 2);
		ret = i2c_master_send(client, buf, 4);
		if (ret < 0)
			return ret;
		else if (ret != 4)
			return -EIO;
	}

	return regmap_update_bits(adau1701->regmap, ADAU1701_DSPCTRL,
		ADAU1701_DSPCTRL_IST, ADAU1701_DSPCTRL_IST);
}

static const struct sigmadsp_ops adau1701_sigmadsp_ops = {
	.safeload = adau1701_safeload,
};

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])) {
@@ -284,7 +340,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;
@@ -385,7 +441,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;
	}
@@ -554,6 +610,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)

@@ -564,6 +628,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 = {
@@ -600,6 +665,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
@@ -609,7 +678,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;

@@ -667,6 +736,7 @@ static int adau1701_i2c_probe(struct i2c_client *client,
	if (!adau1701)
		return -ENOMEM;

	adau1701->client = client;
	adau1701->regmap = devm_regmap_init(dev, NULL, client,
					    &adau1701_regmap);
	if (IS_ERR(adau1701->regmap))
@@ -722,6 +792,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,
		&adau1701_sigmadsp_ops, 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;
+11 −11
Original line number Diff line number Diff line
@@ -703,11 +703,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);
@@ -776,16 +771,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);
}
@@ -799,6 +798,7 @@ const struct regmap_config adau1761_regmap_config = {
	.num_reg_defaults = ARRAY_SIZE(adau1761_reg_defaults),
	.readable_reg = adau1761_readable_register,
	.volatile_reg = adau17x1_volatile_register,
	.precious_reg = adau17x1_precious_register,
	.cache_type = REGCACHE_RBTREE,
};
EXPORT_SYMBOL_GPL(adau1761_regmap_config);
+14 −17
Original line number Diff line number Diff line
@@ -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);
@@ -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;
}

@@ -488,6 +472,7 @@ const struct regmap_config adau1781_regmap_config = {
	.num_reg_defaults	= ARRAY_SIZE(adau1781_reg_defaults),
	.readable_reg		= adau1781_readable_register,
	.volatile_reg		= adau17x1_volatile_register,
	.precious_reg		= adau17x1_precious_register,
	.cache_type		= REGCACHE_RBTREE,
};
EXPORT_SYMBOL_GPL(adau1781_regmap_config);
@@ -495,9 +480,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;

+62 −6
Original line number Diff line number Diff line
@@ -308,6 +308,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;
@@ -357,6 +358,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;

@@ -662,12 +669,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);

@@ -688,8 +707,22 @@ int adau17x1_set_micbias_voltage(struct snd_soc_codec *codec,
}
EXPORT_SYMBOL_GPL(adau17x1_set_micbias_voltage);

bool adau17x1_precious_register(struct device *dev, unsigned int reg)
{
	/* SigmaDSP parameter memory */
	if (reg < 0x400)
		return true;

	return false;
}
EXPORT_SYMBOL_GPL(adau17x1_precious_register);

bool adau17x1_readable_register(struct device *dev, unsigned int reg)
{
	/* SigmaDSP parameter memory */
	if (reg < 0x400)
		return true;

	switch (reg) {
	case ADAU17X1_CLOCK_CONTROL:
	case ADAU17X1_PLL_CONTROL:
@@ -746,8 +779,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;
@@ -759,7 +791,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;
@@ -768,7 +800,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)
{
@@ -788,9 +820,22 @@ 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 0;
}
EXPORT_SYMBOL_GPL(adau17x1_add_widgets);

int adau17x1_add_routes(struct snd_soc_codec *codec)
@@ -830,7 +875,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;

@@ -847,6 +893,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);

Loading