提交 dd7a7bb5 编写于 作者: M Mark Brown

Merge remote-tracking branches 'asoc/topic/adau' and 'asoc/topic/adsp' into asoc-next

/*
* Driver for ADAU1761/ADAU1461/ADAU1761/ADAU1961/ADAU1781/ADAU1781 codecs
*
* Copyright 2011-2014 Analog Devices Inc.
* Author: Lars-Peter Clausen <lars@metafoo.de>
*
* Licensed under the GPL-2 or later.
*/
#ifndef __LINUX_PLATFORM_DATA_ADAU17X1_H__
#define __LINUX_PLATFORM_DATA_ADAU17X1_H__
/**
* enum adau17x1_micbias_voltage - Microphone bias voltage
* @ADAU17X1_MICBIAS_0_90_AVDD: 0.9 * AVDD
* @ADAU17X1_MICBIAS_0_65_AVDD: 0.65 * AVDD
*/
enum adau17x1_micbias_voltage {
ADAU17X1_MICBIAS_0_90_AVDD = 0,
ADAU17X1_MICBIAS_0_65_AVDD = 1,
};
/**
* enum adau1761_digmic_jackdet_pin_mode - Configuration of the JACKDET/MICIN pin
* @ADAU1761_DIGMIC_JACKDET_PIN_MODE_NONE: Disable the pin
* @ADAU1761_DIGMIC_JACKDET_PIN_MODE_DIGMIC: Configure the pin for usage as
* digital microphone input.
* @ADAU1761_DIGMIC_JACKDET_PIN_MODE_JACKDETECT: Configure the pin for jack
* insertion detection.
*/
enum adau1761_digmic_jackdet_pin_mode {
ADAU1761_DIGMIC_JACKDET_PIN_MODE_NONE,
ADAU1761_DIGMIC_JACKDET_PIN_MODE_DIGMIC,
ADAU1761_DIGMIC_JACKDET_PIN_MODE_JACKDETECT,
};
/**
* adau1761_jackdetect_debounce_time - Jack insertion detection debounce time
* @ADAU1761_JACKDETECT_DEBOUNCE_5MS: 5 milliseconds
* @ADAU1761_JACKDETECT_DEBOUNCE_10MS: 10 milliseconds
* @ADAU1761_JACKDETECT_DEBOUNCE_20MS: 20 milliseconds
* @ADAU1761_JACKDETECT_DEBOUNCE_40MS: 40 milliseconds
*/
enum adau1761_jackdetect_debounce_time {
ADAU1761_JACKDETECT_DEBOUNCE_5MS = 0,
ADAU1761_JACKDETECT_DEBOUNCE_10MS = 1,
ADAU1761_JACKDETECT_DEBOUNCE_20MS = 2,
ADAU1761_JACKDETECT_DEBOUNCE_40MS = 3,
};
/**
* enum adau1761_output_mode - Output mode configuration
* @ADAU1761_OUTPUT_MODE_HEADPHONE: Headphone output
* @ADAU1761_OUTPUT_MODE_HEADPHONE_CAPLESS: Capless headphone output
* @ADAU1761_OUTPUT_MODE_LINE: Line output
*/
enum adau1761_output_mode {
ADAU1761_OUTPUT_MODE_HEADPHONE,
ADAU1761_OUTPUT_MODE_HEADPHONE_CAPLESS,
ADAU1761_OUTPUT_MODE_LINE,
};
/**
* struct adau1761_platform_data - ADAU1761 Codec driver platform data
* @input_differential: If true the input pins will be configured in
* differential mode.
* @lineout_mode: Output mode for the LOUT/ROUT pins
* @headphone_mode: Output mode for the LHP/RHP pins
* @digmic_jackdetect_pin_mode: JACKDET/MICIN pin configuration
* @jackdetect_debounce_time: Jack insertion detection debounce time.
* Note: This value will only be used, if the JACKDET/MICIN pin is configured
* for jack insertion detection.
* @jackdetect_active_low: If true the jack insertion detection is active low.
* Othwise it will be active high.
* @micbias_voltage: Microphone voltage bias
*/
struct adau1761_platform_data {
bool input_differential;
enum adau1761_output_mode lineout_mode;
enum adau1761_output_mode headphone_mode;
enum adau1761_digmic_jackdet_pin_mode digmic_jackdetect_pin_mode;
enum adau1761_jackdetect_debounce_time jackdetect_debounce_time;
bool jackdetect_active_low;
enum adau17x1_micbias_voltage micbias_voltage;
};
/**
* struct adau1781_platform_data - ADAU1781 Codec driver platform data
* @left_input_differential: If true configure the left input as
* differential input.
* @right_input_differential: If true configure the right input as differntial
* input.
* @use_dmic: If true configure the MIC pins as digital microphone pins instead
* of analog microphone pins.
* @micbias_voltage: Microphone voltage bias
*/
struct adau1781_platform_data {
bool left_input_differential;
bool right_input_differential;
bool use_dmic;
enum adau17x1_micbias_voltage micbias_voltage;
};
#endif
......@@ -43,6 +43,32 @@ config SND_SOC_BFIN_EVAL_ADAU1373
Note: This driver assumes that first ADAU1373 DAI is connected to the
first SPORT port on the BF5XX board.
config SND_SOC_BFIN_EVAL_ADAU1X61
tristate "Support for the EVAL-ADAU1X61 board on Blackfin eval boards"
depends on SND_BF5XX_I2S && I2C
select SND_BF5XX_SOC_I2S
select SND_SOC_ADAU1761_I2C
help
Say Y if you want to add support for the Analog Devices EVAL-ADAU1X61
board connected to one of the Blackfin evaluation boards like the
BF5XX-STAMP or BF5XX-EZKIT.
Note: This driver assumes that the ADAU1X61 is connected to the
first SPORT port on the BF5XX board.
config SND_SOC_BFIN_EVAL_ADAU1X81
tristate "Support for the EVAL-ADAU1X81 boards on Blackfin eval boards"
depends on SND_BF5XX_I2S && I2C
select SND_BF5XX_SOC_I2S
select SND_SOC_ADAU1781_I2C
help
Say Y if you want to add support for the Analog Devices EVAL-ADAU1X81
board connected to one of the Blackfin evaluation boards like the
BF5XX-STAMP or BF5XX-EZKIT.
Note: This driver assumes that the ADAU1X81 is connected to the
first SPORT port on the BF5XX board.
config SND_SOC_BFIN_EVAL_ADAV80X
tristate "Support for the EVAL-ADAV80X boards on Blackfin eval boards"
depends on SND_BF5XX_I2S && SND_SOC_I2C_AND_SPI
......
......@@ -22,6 +22,8 @@ snd-ssm2602-objs := bf5xx-ssm2602.o
snd-ad73311-objs := bf5xx-ad73311.o
snd-ad193x-objs := bf5xx-ad193x.o
snd-soc-bfin-eval-adau1373-objs := bfin-eval-adau1373.o
snd-soc-bfin-eval-adau1x61-objs := bfin-eval-adau1x61.o
snd-soc-bfin-eval-adau1x81-objs := bfin-eval-adau1x81.o
snd-soc-bfin-eval-adau1701-objs := bfin-eval-adau1701.o
snd-soc-bfin-eval-adav80x-objs := bfin-eval-adav80x.o
......@@ -31,5 +33,7 @@ obj-$(CONFIG_SND_BF5XX_SOC_SSM2602) += snd-ssm2602.o
obj-$(CONFIG_SND_BF5XX_SOC_AD73311) += snd-ad73311.o
obj-$(CONFIG_SND_BF5XX_SOC_AD193X) += snd-ad193x.o
obj-$(CONFIG_SND_SOC_BFIN_EVAL_ADAU1373) += snd-soc-bfin-eval-adau1373.o
obj-$(CONFIG_SND_SOC_BFIN_EVAL_ADAU1X61) += snd-soc-bfin-eval-adau1x61.o
obj-$(CONFIG_SND_SOC_BFIN_EVAL_ADAU1X81) += snd-soc-bfin-eval-adau1x81.o
obj-$(CONFIG_SND_SOC_BFIN_EVAL_ADAU1701) += snd-soc-bfin-eval-adau1701.o
obj-$(CONFIG_SND_SOC_BFIN_EVAL_ADAV80X) += snd-soc-bfin-eval-adav80x.o
/*
* Machine driver for EVAL-ADAU1x61MINIZ on Analog Devices bfin
* evaluation boards.
*
* Copyright 2011-2014 Analog Devices Inc.
* Author: Lars-Peter Clausen <lars@metafoo.de>
*
* Licensed under the GPL-2 or later.
*/
#include <linux/module.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/soc.h>
#include <sound/pcm_params.h>
#include "../codecs/adau17x1.h"
static const struct snd_soc_dapm_widget bfin_eval_adau1x61_dapm_widgets[] = {
SND_SOC_DAPM_LINE("In 1", NULL),
SND_SOC_DAPM_LINE("In 2", NULL),
SND_SOC_DAPM_LINE("In 3-4", NULL),
SND_SOC_DAPM_LINE("Diff Out L", NULL),
SND_SOC_DAPM_LINE("Diff Out R", NULL),
SND_SOC_DAPM_LINE("Stereo Out", NULL),
SND_SOC_DAPM_HP("Capless HP Out", NULL),
};
static const struct snd_soc_dapm_route bfin_eval_adau1x61_dapm_routes[] = {
{ "LAUX", NULL, "In 3-4" },
{ "RAUX", NULL, "In 3-4" },
{ "LINP", NULL, "In 1" },
{ "LINN", NULL, "In 1"},
{ "RINP", NULL, "In 2" },
{ "RINN", NULL, "In 2" },
{ "In 1", NULL, "MICBIAS" },
{ "In 2", NULL, "MICBIAS" },
{ "Capless HP Out", NULL, "LHP" },
{ "Capless HP Out", NULL, "RHP" },
{ "Diff Out L", NULL, "LOUT" },
{ "Diff Out R", NULL, "ROUT" },
{ "Stereo Out", NULL, "LOUT" },
{ "Stereo Out", NULL, "ROUT" },
};
static int bfin_eval_adau1x61_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *codec_dai = rtd->codec_dai;
int pll_rate;
int ret;
switch (params_rate(params)) {
case 48000:
case 8000:
case 12000:
case 16000:
case 24000:
case 32000:
case 96000:
pll_rate = 48000 * 1024;
break;
case 44100:
case 7350:
case 11025:
case 14700:
case 22050:
case 29400:
case 88200:
pll_rate = 44100 * 1024;
break;
default:
return -EINVAL;
}
ret = snd_soc_dai_set_pll(codec_dai, ADAU17X1_PLL,
ADAU17X1_PLL_SRC_MCLK, 12288000, pll_rate);
if (ret)
return ret;
ret = snd_soc_dai_set_sysclk(codec_dai, ADAU17X1_CLK_SRC_PLL, pll_rate,
SND_SOC_CLOCK_IN);
return ret;
}
static const struct snd_soc_ops bfin_eval_adau1x61_ops = {
.hw_params = bfin_eval_adau1x61_hw_params,
};
static struct snd_soc_dai_link bfin_eval_adau1x61_dai = {
.name = "adau1x61",
.stream_name = "adau1x61",
.cpu_dai_name = "bfin-i2s.0",
.codec_dai_name = "adau-hifi",
.platform_name = "bfin-i2s-pcm-audio",
.codec_name = "adau1761.0-0038",
.ops = &bfin_eval_adau1x61_ops,
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBM_CFM,
};
static struct snd_soc_card bfin_eval_adau1x61 = {
.name = "bfin-eval-adau1x61",
.driver_name = "eval-adau1x61",
.dai_link = &bfin_eval_adau1x61_dai,
.num_links = 1,
.dapm_widgets = bfin_eval_adau1x61_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(bfin_eval_adau1x61_dapm_widgets),
.dapm_routes = bfin_eval_adau1x61_dapm_routes,
.num_dapm_routes = ARRAY_SIZE(bfin_eval_adau1x61_dapm_routes),
.fully_routed = true,
};
static int bfin_eval_adau1x61_probe(struct platform_device *pdev)
{
bfin_eval_adau1x61.dev = &pdev->dev;
return devm_snd_soc_register_card(&pdev->dev, &bfin_eval_adau1x61);
}
static struct platform_driver bfin_eval_adau1x61_driver = {
.driver = {
.name = "bfin-eval-adau1x61",
.owner = THIS_MODULE,
.pm = &snd_soc_pm_ops,
},
.probe = bfin_eval_adau1x61_probe,
};
module_platform_driver(bfin_eval_adau1x61_driver);
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
MODULE_DESCRIPTION("ALSA SoC bfin adau1x61 driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:bfin-eval-adau1x61");
/*
* Machine driver for EVAL-ADAU1x81 on Analog Devices bfin
* evaluation boards.
*
* Copyright 2011-2014 Analog Devices Inc.
* Author: Lars-Peter Clausen <lars@metafoo.de>
*
* Licensed under the GPL-2 or later.
*/
#include <linux/module.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/soc.h>
#include <sound/pcm_params.h>
#include "../codecs/adau17x1.h"
static const struct snd_soc_dapm_widget bfin_eval_adau1x81_dapm_widgets[] = {
SND_SOC_DAPM_LINE("Stereo In", NULL),
SND_SOC_DAPM_LINE("Beep", NULL),
SND_SOC_DAPM_SPK("Speaker", NULL),
SND_SOC_DAPM_HP("Headphone", NULL),
};
static const struct snd_soc_dapm_route bfin_eval_adau1x81_dapm_routes[] = {
{ "BEEP", NULL, "Beep" },
{ "LMIC", NULL, "Stereo In" },
{ "LMIC", NULL, "Stereo In" },
{ "Headphone", NULL, "AOUTL" },
{ "Headphone", NULL, "AOUTR" },
{ "Speaker", NULL, "SP" },
};
static int bfin_eval_adau1x81_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *codec_dai = rtd->codec_dai;
int pll_rate;
int ret;
switch (params_rate(params)) {
case 48000:
case 8000:
case 12000:
case 16000:
case 24000:
case 32000:
case 96000:
pll_rate = 48000 * 1024;
break;
case 44100:
case 7350:
case 11025:
case 14700:
case 22050:
case 29400:
case 88200:
pll_rate = 44100 * 1024;
break;
default:
return -EINVAL;
}
ret = snd_soc_dai_set_pll(codec_dai, ADAU17X1_PLL,
ADAU17X1_PLL_SRC_MCLK, 12288000, pll_rate);
if (ret)
return ret;
ret = snd_soc_dai_set_sysclk(codec_dai, ADAU17X1_CLK_SRC_PLL, pll_rate,
SND_SOC_CLOCK_IN);
return ret;
}
static const struct snd_soc_ops bfin_eval_adau1x81_ops = {
.hw_params = bfin_eval_adau1x81_hw_params,
};
static struct snd_soc_dai_link bfin_eval_adau1x81_dai = {
.name = "adau1x81",
.stream_name = "adau1x81",
.cpu_dai_name = "bfin-i2s.0",
.codec_dai_name = "adau-hifi",
.platform_name = "bfin-i2s-pcm-audio",
.codec_name = "adau1781.0-0038",
.ops = &bfin_eval_adau1x81_ops,
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBM_CFM,
};
static struct snd_soc_card bfin_eval_adau1x81 = {
.name = "bfin-eval-adau1x81",
.driver_name = "eval-adau1x81",
.dai_link = &bfin_eval_adau1x81_dai,
.num_links = 1,
.dapm_widgets = bfin_eval_adau1x81_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(bfin_eval_adau1x81_dapm_widgets),
.dapm_routes = bfin_eval_adau1x81_dapm_routes,
.num_dapm_routes = ARRAY_SIZE(bfin_eval_adau1x81_dapm_routes),
.fully_routed = true,
};
static int bfin_eval_adau1x81_probe(struct platform_device *pdev)
{
bfin_eval_adau1x81.dev = &pdev->dev;
return devm_snd_soc_register_card(&pdev->dev, &bfin_eval_adau1x81);
}
static struct platform_driver bfin_eval_adau1x81_driver = {
.driver = {
.name = "bfin-eval-adau1x81",
.owner = THIS_MODULE,
.pm = &snd_soc_pm_ops,
},
.probe = bfin_eval_adau1x81_probe,
};
module_platform_driver(bfin_eval_adau1x81_driver);
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
MODULE_DESCRIPTION("ALSA SoC bfin adau1x81 driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:bfin-eval-adau1x81");
......@@ -23,6 +23,10 @@ config SND_SOC_ALL_CODECS
select SND_SOC_AD1980 if SND_SOC_AC97_BUS
select SND_SOC_AD73311
select SND_SOC_ADAU1373 if I2C
select SND_SOC_ADAU1761_I2C if I2C
select SND_SOC_ADAU1761_SPI if SPI
select SND_SOC_ADAU1781_I2C if I2C
select SND_SOC_ADAU1781_SPI if SPI
select SND_SOC_ADAV801 if SPI_MASTER
select SND_SOC_ADAV803 if I2C
select SND_SOC_ADAU1977_SPI if SPI_MASTER
......@@ -214,13 +218,45 @@ config SND_SOC_AD1980
config SND_SOC_AD73311
tristate
config SND_SOC_ADAU1373
tristate
config SND_SOC_ADAU1701
tristate "Analog Devices ADAU1701 CODEC"
depends on I2C
select SND_SOC_SIGMADSP
config SND_SOC_ADAU1373
config SND_SOC_ADAU17X1
tristate
select SND_SOC_SIGMADSP
config SND_SOC_ADAU1761
tristate
select SND_SOC_ADAU17X1
config SND_SOC_ADAU1761_I2C
tristate
select SND_SOC_ADAU1761
select REGMAP_I2C
config SND_SOC_ADAU1761_SPI
tristate
select SND_SOC_ADAU1761
select REGMAP_SPI
config SND_SOC_ADAU1781
select SND_SOC_ADAU17X1
tristate
config SND_SOC_ADAU1781_I2C
tristate
select SND_SOC_ADAU1781
select REGMAP_I2C
config SND_SOC_ADAU1781_SPI
tristate
select SND_SOC_ADAU1781
select REGMAP_SPI
config SND_SOC_ADAU1977
tristate
......
......@@ -7,8 +7,15 @@ snd-soc-ad193x-spi-objs := ad193x-spi.o
snd-soc-ad193x-i2c-objs := ad193x-i2c.o
snd-soc-ad1980-objs := ad1980.o
snd-soc-ad73311-objs := ad73311.o
snd-soc-adau1701-objs := adau1701.o
snd-soc-adau1373-objs := adau1373.o
snd-soc-adau1701-objs := adau1701.o
snd-soc-adau17x1-objs := adau17x1.o
snd-soc-adau1761-objs := adau1761.o
snd-soc-adau1761-i2c-objs := adau1761-i2c.o
snd-soc-adau1761-spi-objs := adau1761-spi.o
snd-soc-adau1781-objs := adau1781.o
snd-soc-adau1781-i2c-objs := adau1781-i2c.o
snd-soc-adau1781-spi-objs := adau1781-spi.o
snd-soc-adau1977-objs := adau1977.o
snd-soc-adau1977-spi-objs := adau1977-spi.o
snd-soc-adau1977-i2c-objs := adau1977-i2c.o
......@@ -162,10 +169,17 @@ obj-$(CONFIG_SND_SOC_AD193X_I2C) += snd-soc-ad193x-i2c.o
obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o
obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o
obj-$(CONFIG_SND_SOC_ADAU1373) += snd-soc-adau1373.o
obj-$(CONFIG_SND_SOC_ADAU1701) += snd-soc-adau1701.o
obj-$(CONFIG_SND_SOC_ADAU17X1) += snd-soc-adau17x1.o
obj-$(CONFIG_SND_SOC_ADAU1761) += snd-soc-adau1761.o
obj-$(CONFIG_SND_SOC_ADAU1761_I2C) += snd-soc-adau1761-i2c.o
obj-$(CONFIG_SND_SOC_ADAU1761_SPI) += snd-soc-adau1761-spi.o
obj-$(CONFIG_SND_SOC_ADAU1781) += snd-soc-adau1781.o
obj-$(CONFIG_SND_SOC_ADAU1781_I2C) += snd-soc-adau1781-i2c.o
obj-$(CONFIG_SND_SOC_ADAU1781_SPI) += snd-soc-adau1781-spi.o
obj-$(CONFIG_SND_SOC_ADAU1977) += snd-soc-adau1977.o
obj-$(CONFIG_SND_SOC_ADAU1977_SPI) += snd-soc-adau1977-spi.o
obj-$(CONFIG_SND_SOC_ADAU1977_I2C) += snd-soc-adau1977-i2c.o
obj-$(CONFIG_SND_SOC_ADAU1701) += snd-soc-adau1701.o
obj-$(CONFIG_SND_SOC_ADAV80X) += snd-soc-adav80x.o
obj-$(CONFIG_SND_SOC_ADAV801) += snd-soc-adav801.o
obj-$(CONFIG_SND_SOC_ADAV803) += snd-soc-adav803.o
......
/*
* Driver for ADAU1761/ADAU1461/ADAU1761/ADAU1961 codec
*
* Copyright 2014 Analog Devices Inc.
* Author: Lars-Peter Clausen <lars@metafoo.de>
*
* Licensed under the GPL-2.
*/
#include <linux/i2c.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include <sound/soc.h>
#include "adau1761.h"
static int adau1761_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct regmap_config config;
config = adau1761_regmap_config;
config.val_bits = 8;
config.reg_bits = 16;
return adau1761_probe(&client->dev,
devm_regmap_init_i2c(client, &config),
id->driver_data, NULL);
}
static int adau1761_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
}
static const struct i2c_device_id adau1761_i2c_ids[] = {
{ "adau1361", ADAU1361 },
{ "adau1461", ADAU1761 },
{ "adau1761", ADAU1761 },
{ "adau1961", ADAU1361 },
{ }
};
MODULE_DEVICE_TABLE(i2c, adau1761_i2c_ids);
static struct i2c_driver adau1761_i2c_driver = {
.driver = {
.name = "adau1761",
.owner = THIS_MODULE,
},
.probe = adau1761_i2c_probe,
.remove = adau1761_i2c_remove,
.id_table = adau1761_i2c_ids,
};
module_i2c_driver(adau1761_i2c_driver);
MODULE_DESCRIPTION("ASoC ADAU1361/ADAU1461/ADAU1761/ADAU1961 CODEC I2C driver");
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
MODULE_LICENSE("GPL");
/*
* Driver for ADAU1761/ADAU1461/ADAU1761/ADAU1961 codec
*
* Copyright 2014 Analog Devices Inc.
* Author: Lars-Peter Clausen <lars@metafoo.de>
*
* Licensed under the GPL-2.
*/
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include <linux/spi/spi.h>
#include <sound/soc.h>
#include "adau1761.h"
static void adau1761_spi_switch_mode(struct device *dev)
{
struct spi_device *spi = to_spi_device(dev);
/*
* To get the device into SPI mode CLATCH has to be pulled low three
* times. Do this by issuing three dummy reads.
*/
spi_w8r8(spi, 0x00);
spi_w8r8(spi, 0x00);
spi_w8r8(spi, 0x00);
}
static int adau1761_spi_probe(struct spi_device *spi)
{
const struct spi_device_id *id = spi_get_device_id(spi);
struct regmap_config config;
if (!id)
return -EINVAL;
config = adau1761_regmap_config;
config.val_bits = 8;
config.reg_bits = 24;
config.read_flag_mask = 0x1;
return adau1761_probe(&spi->dev,
devm_regmap_init_spi(spi, &config),
id->driver_data, adau1761_spi_switch_mode);
}
static int adau1761_spi_remove(struct spi_device *spi)
{
snd_soc_unregister_codec(&spi->dev);
return 0;
}
static const struct spi_device_id adau1761_spi_id[] = {
{ "adau1361", ADAU1361 },
{ "adau1461", ADAU1761 },
{ "adau1761", ADAU1761 },
{ "adau1961", ADAU1361 },
{ }
};
MODULE_DEVICE_TABLE(spi, adau1761_spi_id);
static struct spi_driver adau1761_spi_driver = {
.driver = {
.name = "adau1761",
.owner = THIS_MODULE,
},
.probe = adau1761_spi_probe,
.remove = adau1761_spi_remove,
.id_table = adau1761_spi_id,
};
module_spi_driver(adau1761_spi_driver);
MODULE_DESCRIPTION("ASoC ADAU1361/ADAU1461/ADAU1761/ADAU1961 CODEC SPI driver");
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
MODULE_LICENSE("GPL");
此差异已折叠。
/*
* ADAU1361/ADAU1461/ADAU1761/ADAU1961 driver
*
* Copyright 2014 Analog Devices Inc.
* Author: Lars-Peter Clausen <lars@metafoo.de>
*
* Licensed under the GPL-2.
*/
#ifndef __SOUND_SOC_CODECS_ADAU1761_H__
#define __SOUND_SOC_CODECS_ADAU1761_H__
#include <linux/regmap.h>
#include "adau17x1.h"
struct device;
int adau1761_probe(struct device *dev, struct regmap *regmap,
enum adau17x1_type type, void (*switch_mode)(struct device *dev));
extern const struct regmap_config adau1761_regmap_config;
#endif
/*
* Driver for ADAU1381/ADAU1781 CODEC
*
* Copyright 2014 Analog Devices Inc.
* Author: Lars-Peter Clausen <lars@metafoo.de>
*
* Licensed under the GPL-2.
*/
#include <linux/i2c.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include <sound/soc.h>
#include "adau1781.h"
static int adau1781_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct regmap_config config;
config = adau1781_regmap_config;
config.val_bits = 8;
config.reg_bits = 16;
return adau1781_probe(&client->dev,
devm_regmap_init_i2c(client, &config),
id->driver_data, NULL);
}
static int adau1781_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
return 0;
}
static const struct i2c_device_id adau1781_i2c_ids[] = {
{ "adau1381", ADAU1381 },
{ "adau1781", ADAU1781 },
{ }
};
MODULE_DEVICE_TABLE(i2c, adau1781_i2c_ids);
static struct i2c_driver adau1781_i2c_driver = {
.driver = {
.name = "adau1781",
.owner = THIS_MODULE,
},
.probe = adau1781_i2c_probe,
.remove = adau1781_i2c_remove,
.id_table = adau1781_i2c_ids,
};
module_i2c_driver(adau1781_i2c_driver);
MODULE_DESCRIPTION("ASoC ADAU1381/ADAU1781 CODEC I2C driver");
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
MODULE_LICENSE("GPL");
/*
* Driver for ADAU1381/ADAU1781 CODEC
*
* Copyright 2014 Analog Devices Inc.
* Author: Lars-Peter Clausen <lars@metafoo.de>
*
* Licensed under the GPL-2.
*/
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include <linux/spi/spi.h>
#include <sound/soc.h>
#include "adau1781.h"
static void adau1781_spi_switch_mode(struct device *dev)
{
struct spi_device *spi = to_spi_device(dev);
/*
* To get the device into SPI mode CLATCH has to be pulled low three
* times. Do this by issuing three dummy reads.
*/
spi_w8r8(spi, 0x00);
spi_w8r8(spi, 0x00);
spi_w8r8(spi, 0x00);
}
static int adau1781_spi_probe(struct spi_device *spi)
{
const struct spi_device_id *id = spi_get_device_id(spi);
struct regmap_config config;
if (!id)
return -EINVAL;
config = adau1781_regmap_config;
config.val_bits = 8;
config.reg_bits = 24;
config.read_flag_mask = 0x1;
return adau1781_probe(&spi->dev,
devm_regmap_init_spi(spi, &config),
id->driver_data, adau1781_spi_switch_mode);
}
static int adau1781_spi_remove(struct spi_device *spi)
{
snd_soc_unregister_codec(&spi->dev);
return 0;
}
static const struct spi_device_id adau1781_spi_id[] = {
{ "adau1381", ADAU1381 },
{ "adau1781", ADAU1781 },
{ }
};
MODULE_DEVICE_TABLE(spi, adau1781_spi_id);
static struct spi_driver adau1781_spi_driver = {
.driver = {
.name = "adau1781",
.owner = THIS_MODULE,
},
.probe = adau1781_spi_probe,
.remove = adau1781_spi_remove,
.id_table = adau1781_spi_id,
};
module_spi_driver(adau1781_spi_driver);
MODULE_DESCRIPTION("ASoC ADAU1381/ADAU1781 CODEC SPI driver");
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
MODULE_LICENSE("GPL");
/*
* Driver for ADAU1781/ADAU1781 codec
*
* Copyright 2011-2013 Analog Devices Inc.
* Author: Lars-Peter Clausen <lars@metafoo.de>
*
* Licensed under the GPL-2 or later.
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/i2c.h>
#include <linux/spi/spi.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/tlv.h>
#include <linux/platform_data/adau17x1.h>
#include "adau17x1.h"
#include "adau1781.h"
#define ADAU1781_DMIC_BEEP_CTRL 0x4008
#define ADAU1781_LEFT_PGA 0x400e
#define ADAU1781_RIGHT_PGA 0x400f
#define ADAU1781_LEFT_PLAYBACK_MIXER 0x401c
#define ADAU1781_RIGHT_PLAYBACK_MIXER 0x401e
#define ADAU1781_MONO_PLAYBACK_MIXER 0x401f
#define ADAU1781_LEFT_LINEOUT 0x4025
#define ADAU1781_RIGHT_LINEOUT 0x4026
#define ADAU1781_SPEAKER 0x4027
#define ADAU1781_BEEP_ZC 0x4028
#define ADAU1781_DEJITTER 0x4032
#define ADAU1781_DIG_PWDN0 0x4080
#define ADAU1781_DIG_PWDN1 0x4081
#define ADAU1781_INPUT_DIFFERNTIAL BIT(3)
#define ADAU1381_FIRMWARE "adau1381.bin"
#define ADAU1781_FIRMWARE "adau1781.bin"
static const struct reg_default adau1781_reg_defaults[] = {
{ ADAU1781_DMIC_BEEP_CTRL, 0x00 },
{ ADAU1781_LEFT_PGA, 0xc7 },
{ ADAU1781_RIGHT_PGA, 0xc7 },
{ ADAU1781_LEFT_PLAYBACK_MIXER, 0x00 },
{ ADAU1781_RIGHT_PLAYBACK_MIXER, 0x00 },
{ ADAU1781_MONO_PLAYBACK_MIXER, 0x00 },
{ ADAU1781_LEFT_LINEOUT, 0x00 },
{ ADAU1781_RIGHT_LINEOUT, 0x00 },
{ ADAU1781_SPEAKER, 0x00 },
{ ADAU1781_BEEP_ZC, 0x19 },
{ ADAU1781_DEJITTER, 0x60 },
{ ADAU1781_DIG_PWDN1, 0x0c },
{ ADAU1781_DIG_PWDN1, 0x00 },
{ ADAU17X1_CLOCK_CONTROL, 0x00 },
{ ADAU17X1_PLL_CONTROL, 0x00 },
{ ADAU17X1_REC_POWER_MGMT, 0x00 },
{ ADAU17X1_MICBIAS, 0x04 },
{ ADAU17X1_SERIAL_PORT0, 0x00 },
{ ADAU17X1_SERIAL_PORT1, 0x00 },
{ ADAU17X1_CONVERTER0, 0x00 },
{ ADAU17X1_CONVERTER1, 0x00 },
{ ADAU17X1_LEFT_INPUT_DIGITAL_VOL, 0x00 },
{ ADAU17X1_RIGHT_INPUT_DIGITAL_VOL, 0x00 },
{ ADAU17X1_ADC_CONTROL, 0x00 },
{ ADAU17X1_PLAY_POWER_MGMT, 0x00 },
{ ADAU17X1_DAC_CONTROL0, 0x00 },
{ ADAU17X1_DAC_CONTROL1, 0x00 },
{ ADAU17X1_DAC_CONTROL2, 0x00 },
{ ADAU17X1_SERIAL_PORT_PAD, 0x00 },
{ ADAU17X1_CONTROL_PORT_PAD0, 0x00 },
{ ADAU17X1_CONTROL_PORT_PAD1, 0x00 },
{ ADAU17X1_DSP_SAMPLING_RATE, 0x01 },
{ ADAU17X1_SERIAL_INPUT_ROUTE, 0x00 },
{ ADAU17X1_SERIAL_OUTPUT_ROUTE, 0x00 },
{ ADAU17X1_DSP_ENABLE, 0x00 },
{ ADAU17X1_DSP_RUN, 0x00 },
{ ADAU17X1_SERIAL_SAMPLING_RATE, 0x00 },
};
static const DECLARE_TLV_DB_SCALE(adau1781_speaker_tlv, 0, 200, 0);
static const DECLARE_TLV_DB_RANGE(adau1781_pga_tlv,
0, 1, TLV_DB_SCALE_ITEM(0, 600, 0),
2, 3, TLV_DB_SCALE_ITEM(1000, 400, 0),
4, 4, TLV_DB_SCALE_ITEM(1700, 0, 0),
5, 7, TLV_DB_SCALE_ITEM(2000, 600, 0)
);
static const DECLARE_TLV_DB_RANGE(adau1781_beep_tlv,
0, 1, TLV_DB_SCALE_ITEM(0, 600, 0),
2, 3, TLV_DB_SCALE_ITEM(1000, 400, 0),
4, 4, TLV_DB_SCALE_ITEM(-2300, 0, 0),
5, 7, TLV_DB_SCALE_ITEM(2000, 600, 0)
);
static const DECLARE_TLV_DB_SCALE(adau1781_sidetone_tlv, -1800, 300, 1);
static const char * const adau1781_speaker_bias_select_text[] = {
"Normal operation", "Power saving", "Enhanced performance",
};
static const char * const adau1781_bias_select_text[] = {
"Normal operation", "Extreme power saving", "Power saving",
"Enhanced performance",
};
static SOC_ENUM_SINGLE_DECL(adau1781_adc_bias_enum,
ADAU17X1_REC_POWER_MGMT, 3, adau1781_bias_select_text);
static SOC_ENUM_SINGLE_DECL(adau1781_speaker_bias_enum,
ADAU17X1_PLAY_POWER_MGMT, 6, adau1781_speaker_bias_select_text);
static SOC_ENUM_SINGLE_DECL(adau1781_dac_bias_enum,
ADAU17X1_PLAY_POWER_MGMT, 4, adau1781_bias_select_text);
static SOC_ENUM_SINGLE_DECL(adau1781_playback_bias_enum,
ADAU17X1_PLAY_POWER_MGMT, 2, adau1781_bias_select_text);
static SOC_ENUM_SINGLE_DECL(adau1781_capture_bias_enum,
ADAU17X1_REC_POWER_MGMT, 1, adau1781_bias_select_text);
static const struct snd_kcontrol_new adau1781_controls[] = {
SOC_SINGLE_TLV("Beep Capture Volume", ADAU1781_DMIC_BEEP_CTRL, 0, 7, 0,
adau1781_beep_tlv),
SOC_DOUBLE_R_TLV("PGA Capture Volume", ADAU1781_LEFT_PGA,
ADAU1781_RIGHT_PGA, 5, 7, 0, adau1781_pga_tlv),
SOC_DOUBLE_R("PGA Capture Switch", ADAU1781_LEFT_PGA,
ADAU1781_RIGHT_PGA, 1, 1, 0),
SOC_DOUBLE_R("Lineout Playback Switch", ADAU1781_LEFT_LINEOUT,
ADAU1781_RIGHT_LINEOUT, 1, 1, 0),
SOC_SINGLE("Beep ZC Switch", ADAU1781_BEEP_ZC, 0, 1, 0),
SOC_SINGLE("Mono Playback Switch", ADAU1781_MONO_PLAYBACK_MIXER,
0, 1, 0),
SOC_SINGLE_TLV("Mono Playback Volume", ADAU1781_SPEAKER, 6, 3, 0,
adau1781_speaker_tlv),
SOC_ENUM("ADC Bias", adau1781_adc_bias_enum),
SOC_ENUM("DAC Bias", adau1781_dac_bias_enum),
SOC_ENUM("Capture Bias", adau1781_capture_bias_enum),
SOC_ENUM("Playback Bias", adau1781_playback_bias_enum),
SOC_ENUM("Speaker Bias", adau1781_speaker_bias_enum),
};
static const struct snd_kcontrol_new adau1781_beep_mixer_controls[] = {
SOC_DAPM_SINGLE("Beep Capture Switch", ADAU1781_DMIC_BEEP_CTRL,
3, 1, 0),
};
static const struct snd_kcontrol_new adau1781_left_mixer_controls[] = {
SOC_DAPM_SINGLE_AUTODISABLE("Switch",
ADAU1781_LEFT_PLAYBACK_MIXER, 5, 1, 0),
SOC_DAPM_SINGLE_TLV("Beep Playback Volume",
ADAU1781_LEFT_PLAYBACK_MIXER, 1, 8, 0, adau1781_sidetone_tlv),
};
static const struct snd_kcontrol_new adau1781_right_mixer_controls[] = {
SOC_DAPM_SINGLE_AUTODISABLE("Switch",
ADAU1781_RIGHT_PLAYBACK_MIXER, 6, 1, 0),
SOC_DAPM_SINGLE_TLV("Beep Playback Volume",
ADAU1781_LEFT_PLAYBACK_MIXER, 1, 8, 0, adau1781_sidetone_tlv),
};
static const struct snd_kcontrol_new adau1781_mono_mixer_controls[] = {
SOC_DAPM_SINGLE_AUTODISABLE("Left Switch",
ADAU1781_MONO_PLAYBACK_MIXER, 7, 1, 0),
SOC_DAPM_SINGLE_AUTODISABLE("Right Switch",
ADAU1781_MONO_PLAYBACK_MIXER, 6, 1, 0),
SOC_DAPM_SINGLE_TLV("Beep Playback Volume",
ADAU1781_MONO_PLAYBACK_MIXER, 2, 8, 0, adau1781_sidetone_tlv),
};
static int adau1781_dejitter_fixup(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct adau *adau = snd_soc_codec_get_drvdata(codec);
/* After any power changes have been made the dejitter circuit
* has to be reinitialized. */
regmap_write(adau->regmap, ADAU1781_DEJITTER, 0);
if (!adau->master)
regmap_write(adau->regmap, ADAU1781_DEJITTER, 5);
return 0;
}
static const struct snd_soc_dapm_widget adau1781_dapm_widgets[] = {
SND_SOC_DAPM_PGA("Left PGA", ADAU1781_LEFT_PGA, 0, 0, NULL, 0),
SND_SOC_DAPM_PGA("Right PGA", ADAU1781_RIGHT_PGA, 0, 0, NULL, 0),
SND_SOC_DAPM_OUT_DRV("Speaker", ADAU1781_SPEAKER, 0, 0, NULL, 0),
SOC_MIXER_NAMED_CTL_ARRAY("Beep Mixer", ADAU17X1_MICBIAS, 4, 0,
adau1781_beep_mixer_controls),
SOC_MIXER_ARRAY("Left Lineout Mixer", SND_SOC_NOPM, 0, 0,
adau1781_left_mixer_controls),
SOC_MIXER_ARRAY("Right Lineout Mixer", SND_SOC_NOPM, 0, 0,
adau1781_right_mixer_controls),
SOC_MIXER_ARRAY("Mono Mixer", SND_SOC_NOPM, 0, 0,
adau1781_mono_mixer_controls),
SND_SOC_DAPM_SUPPLY("Serial Input Routing", ADAU1781_DIG_PWDN0,
2, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("Serial Output Routing", ADAU1781_DIG_PWDN0,
3, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("Clock Domain Transfer", ADAU1781_DIG_PWDN0,
5, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("Serial Ports", ADAU1781_DIG_PWDN0, 4, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("ADC Engine", ADAU1781_DIG_PWDN0, 7, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("DAC Engine", ADAU1781_DIG_PWDN1, 0, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("Digital Mic", ADAU1781_DIG_PWDN1, 1, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("Sound Engine", ADAU1781_DIG_PWDN0, 0, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY_S("SYSCLK", 1, ADAU1781_DIG_PWDN0, 1, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("Zero Crossing Detector", ADAU1781_DIG_PWDN1, 2, 0,
NULL, 0),
SND_SOC_DAPM_POST("Dejitter fixup", adau1781_dejitter_fixup),
SND_SOC_DAPM_INPUT("BEEP"),
SND_SOC_DAPM_OUTPUT("AOUTL"),
SND_SOC_DAPM_OUTPUT("AOUTR"),
SND_SOC_DAPM_OUTPUT("SP"),
SND_SOC_DAPM_INPUT("LMIC"),
SND_SOC_DAPM_INPUT("RMIC"),
};
static const struct snd_soc_dapm_route adau1781_dapm_routes[] = {
{ "Left Lineout Mixer", NULL, "Left Playback Enable" },
{ "Right Lineout Mixer", NULL, "Right Playback Enable" },
{ "Left Lineout Mixer", "Beep Playback Volume", "Beep Mixer" },
{ "Left Lineout Mixer", "Switch", "Left DAC" },
{ "Right Lineout Mixer", "Beep Playback Volume", "Beep Mixer" },
{ "Right Lineout Mixer", "Switch", "Right DAC" },
{ "Mono Mixer", "Beep Playback Volume", "Beep Mixer" },
{ "Mono Mixer", "Right Switch", "Right DAC" },
{ "Mono Mixer", "Left Switch", "Left DAC" },
{ "Speaker", NULL, "Mono Mixer" },
{ "Mono Mixer", NULL, "SYSCLK" },
{ "Left Lineout Mixer", NULL, "SYSCLK" },
{ "Left Lineout Mixer", NULL, "SYSCLK" },
{ "Beep Mixer", "Beep Capture Switch", "BEEP" },
{ "Beep Mixer", NULL, "Zero Crossing Detector" },
{ "Left DAC", NULL, "DAC Engine" },
{ "Right DAC", NULL, "DAC Engine" },
{ "Sound Engine", NULL, "SYSCLK" },
{ "DSP", NULL, "Sound Engine" },
{ "Left Decimator", NULL, "ADC Engine" },
{ "Right Decimator", NULL, "ADC Engine" },
{ "AIFCLK", NULL, "SYSCLK" },
{ "Playback", NULL, "Serial Input Routing" },
{ "Playback", NULL, "Serial Ports" },
{ "Playback", NULL, "Clock Domain Transfer" },
{ "Capture", NULL, "Serial Output Routing" },
{ "Capture", NULL, "Serial Ports" },
{ "Capture", NULL, "Clock Domain Transfer" },
{ "AOUTL", NULL, "Left Lineout Mixer" },
{ "AOUTR", NULL, "Right Lineout Mixer" },
{ "SP", NULL, "Speaker" },
};
static const struct snd_soc_dapm_route adau1781_adc_dapm_routes[] = {
{ "Left PGA", NULL, "LMIC" },
{ "Right PGA", NULL, "RMIC" },
{ "Left Decimator", NULL, "Left PGA" },
{ "Right Decimator", NULL, "Right PGA" },
};
static const char * const adau1781_dmic_select_text[] = {
"DMIC1", "DMIC2",
};
static SOC_ENUM_SINGLE_VIRT_DECL(adau1781_dmic_select_enum,
adau1781_dmic_select_text);
static const struct snd_kcontrol_new adau1781_dmic_mux =
SOC_DAPM_ENUM("DMIC Select", adau1781_dmic_select_enum);
static const struct snd_soc_dapm_widget adau1781_dmic_dapm_widgets[] = {
SND_SOC_DAPM_MUX("DMIC Select", SND_SOC_NOPM, 0, 0, &adau1781_dmic_mux),
SND_SOC_DAPM_ADC("DMIC1", NULL, ADAU1781_DMIC_BEEP_CTRL, 4, 0),
SND_SOC_DAPM_ADC("DMIC2", NULL, ADAU1781_DMIC_BEEP_CTRL, 5, 0),
};
static const struct snd_soc_dapm_route adau1781_dmic_dapm_routes[] = {
{ "DMIC1", NULL, "LMIC" },
{ "DMIC2", NULL, "RMIC" },
{ "DMIC1", NULL, "Digital Mic" },
{ "DMIC2", NULL, "Digital Mic" },
{ "DMIC Select", "DMIC1", "DMIC1" },
{ "DMIC Select", "DMIC2", "DMIC2" },
{ "Left Decimator", NULL, "DMIC Select" },
{ "Right Decimator", NULL, "DMIC Select" },
};
static int adau1781_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
struct adau *adau = snd_soc_codec_get_drvdata(codec);
switch (level) {
case SND_SOC_BIAS_ON:
break;
case SND_SOC_BIAS_PREPARE:
break;
case SND_SOC_BIAS_STANDBY:
regmap_update_bits(adau->regmap, ADAU17X1_CLOCK_CONTROL,
ADAU17X1_CLOCK_CONTROL_SYSCLK_EN,
ADAU17X1_CLOCK_CONTROL_SYSCLK_EN);
/* Precharge */
regmap_update_bits(adau->regmap, ADAU1781_DIG_PWDN1, 0x8, 0x8);
break;
case SND_SOC_BIAS_OFF:
regmap_update_bits(adau->regmap, ADAU1781_DIG_PWDN1, 0xc, 0x0);
regmap_update_bits(adau->regmap, ADAU17X1_CLOCK_CONTROL,
ADAU17X1_CLOCK_CONTROL_SYSCLK_EN, 0);
break;
}
codec->dapm.bias_level = level;
return 0;
}
static bool adau1781_readable_register(struct device *dev, unsigned int reg)
{
switch (reg) {
case ADAU1781_DMIC_BEEP_CTRL:
case ADAU1781_LEFT_PGA:
case ADAU1781_RIGHT_PGA:
case ADAU1781_LEFT_PLAYBACK_MIXER:
case ADAU1781_RIGHT_PLAYBACK_MIXER:
case ADAU1781_MONO_PLAYBACK_MIXER:
case ADAU1781_LEFT_LINEOUT:
case ADAU1781_RIGHT_LINEOUT:
case ADAU1781_SPEAKER:
case ADAU1781_BEEP_ZC:
case ADAU1781_DEJITTER:
case ADAU1781_DIG_PWDN0:
case ADAU1781_DIG_PWDN1:
return true;
default:
break;
}
return adau17x1_readable_register(dev, reg);
}
static int adau1781_set_input_mode(struct adau *adau, unsigned int reg,
bool differential)
{
unsigned int val;
if (differential)
val = ADAU1781_INPUT_DIFFERNTIAL;
else
val = 0;
return regmap_update_bits(adau->regmap, reg,
ADAU1781_INPUT_DIFFERNTIAL, val);
}
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);
if (ret)
return ret;
if (pdata) {
ret = adau1781_set_input_mode(adau, ADAU1781_LEFT_PGA,
pdata->left_input_differential);
if (ret)
return ret;
ret = adau1781_set_input_mode(adau, ADAU1781_RIGHT_PGA,
pdata->right_input_differential);
if (ret)
return ret;
}
if (pdata && pdata->use_dmic) {
ret = snd_soc_dapm_new_controls(&codec->dapm,
adau1781_dmic_dapm_widgets,
ARRAY_SIZE(adau1781_dmic_dapm_widgets));
if (ret)
return ret;
ret = snd_soc_dapm_add_routes(&codec->dapm,
adau1781_dmic_dapm_routes,
ARRAY_SIZE(adau1781_dmic_dapm_routes));
if (ret)
return ret;
} else {
ret = snd_soc_dapm_add_routes(&codec->dapm,
adau1781_adc_dapm_routes,
ARRAY_SIZE(adau1781_adc_dapm_routes));
if (ret)
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;
}
static const struct snd_soc_codec_driver adau1781_codec_driver = {
.probe = adau1781_codec_probe,
.suspend = adau17x1_suspend,
.resume = adau17x1_resume,
.set_bias_level = adau1781_set_bias_level,
.controls = adau1781_controls,
.num_controls = ARRAY_SIZE(adau1781_controls),
.dapm_widgets = adau1781_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(adau1781_dapm_widgets),
.dapm_routes = adau1781_dapm_routes,
.num_dapm_routes = ARRAY_SIZE(adau1781_dapm_routes),
};
#define ADAU1781_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | \
SNDRV_PCM_FMTBIT_S32_LE)
static struct snd_soc_dai_driver adau1781_dai_driver = {
.name = "adau-hifi",
.playback = {
.stream_name = "Playback",
.channels_min = 2,
.channels_max = 8,
.rates = SNDRV_PCM_RATE_8000_96000,
.formats = ADAU1781_FORMATS,
},
.capture = {
.stream_name = "Capture",
.channels_min = 2,
.channels_max = 8,
.rates = SNDRV_PCM_RATE_8000_96000,
.formats = ADAU1781_FORMATS,
},
.ops = &adau17x1_dai_ops,
};
const struct regmap_config adau1781_regmap_config = {
.val_bits = 8,
.reg_bits = 16,
.max_register = 0x40f8,
.reg_defaults = adau1781_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(adau1781_reg_defaults),
.readable_reg = adau1781_readable_register,
.volatile_reg = adau17x1_volatile_register,
.cache_type = REGCACHE_RBTREE,
};
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))
{
int ret;
ret = adau17x1_probe(dev, regmap, type, switch_mode);
if (ret)
return ret;
return snd_soc_register_codec(dev, &adau1781_codec_driver,
&adau1781_dai_driver, 1);
}
EXPORT_SYMBOL_GPL(adau1781_probe);
MODULE_DESCRIPTION("ASoC ADAU1381/ADAU1781 driver");
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
MODULE_LICENSE("GPL");
/*
* ADAU1381/ADAU1781 driver
*
* Copyright 2014 Analog Devices Inc.
* Author: Lars-Peter Clausen <lars@metafoo.de>
*
* Licensed under the GPL-2.
*/
#ifndef __SOUND_SOC_CODECS_ADAU1781_H__
#define __SOUND_SOC_CODECS_ADAU1781_H__
#include <linux/regmap.h>
#include "adau17x1.h"
struct device;
int adau1781_probe(struct device *dev, struct regmap *regmap,
enum adau17x1_type type, void (*switch_mode)(struct device *dev));
extern const struct regmap_config adau1781_regmap_config;
#endif
此差异已折叠。
#ifndef __ADAU17X1_H__
#define __ADAU17X1_H__
#include <linux/regmap.h>
#include <linux/platform_data/adau17x1.h>
enum adau17x1_type {
ADAU1361,
ADAU1761,
ADAU1381,
ADAU1781,
};
enum adau17x1_pll {
ADAU17X1_PLL,
};
enum adau17x1_pll_src {
ADAU17X1_PLL_SRC_MCLK,
};
enum adau17x1_clk_src {
ADAU17X1_CLK_SRC_MCLK,
ADAU17X1_CLK_SRC_PLL,
};
struct adau {
unsigned int sysclk;
unsigned int pll_freq;
enum adau17x1_clk_src clk_src;
enum adau17x1_type type;
void (*switch_mode)(struct device *dev);
unsigned int dai_fmt;
uint8_t pll_regs[6];
bool master;
unsigned int tdm_slot[2];
bool dsp_bypass[2];
struct regmap *regmap;
};
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));
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);
bool adau17x1_volatile_register(struct device *dev, unsigned int reg);
int adau17x1_suspend(struct snd_soc_codec *codec);
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);
bool adau17x1_has_dsp(struct adau *adau);
#define ADAU17X1_CLOCK_CONTROL 0x4000
#define ADAU17X1_PLL_CONTROL 0x4002
#define ADAU17X1_REC_POWER_MGMT 0x4009
#define ADAU17X1_MICBIAS 0x4010
#define ADAU17X1_SERIAL_PORT0 0x4015
#define ADAU17X1_SERIAL_PORT1 0x4016
#define ADAU17X1_CONVERTER0 0x4017
#define ADAU17X1_CONVERTER1 0x4018
#define ADAU17X1_LEFT_INPUT_DIGITAL_VOL 0x401a
#define ADAU17X1_RIGHT_INPUT_DIGITAL_VOL 0x401b
#define ADAU17X1_ADC_CONTROL 0x4019
#define ADAU17X1_PLAY_POWER_MGMT 0x4029
#define ADAU17X1_DAC_CONTROL0 0x402a
#define ADAU17X1_DAC_CONTROL1 0x402b
#define ADAU17X1_DAC_CONTROL2 0x402c
#define ADAU17X1_SERIAL_PORT_PAD 0x402d
#define ADAU17X1_CONTROL_PORT_PAD0 0x402f
#define ADAU17X1_CONTROL_PORT_PAD1 0x4030
#define ADAU17X1_DSP_SAMPLING_RATE 0x40eb
#define ADAU17X1_SERIAL_INPUT_ROUTE 0x40f2
#define ADAU17X1_SERIAL_OUTPUT_ROUTE 0x40f3
#define ADAU17X1_DSP_ENABLE 0x40f5
#define ADAU17X1_DSP_RUN 0x40f6
#define ADAU17X1_SERIAL_SAMPLING_RATE 0x40f8
#define ADAU17X1_SERIAL_PORT0_BCLK_POL BIT(4)
#define ADAU17X1_SERIAL_PORT0_LRCLK_POL BIT(3)
#define ADAU17X1_SERIAL_PORT0_MASTER BIT(0)
#define ADAU17X1_SERIAL_PORT1_DELAY1 0x00
#define ADAU17X1_SERIAL_PORT1_DELAY0 0x01
#define ADAU17X1_SERIAL_PORT1_DELAY8 0x02
#define ADAU17X1_SERIAL_PORT1_DELAY16 0x03
#define ADAU17X1_SERIAL_PORT1_DELAY_MASK 0x03
#define ADAU17X1_CLOCK_CONTROL_INFREQ_MASK 0x6
#define ADAU17X1_CLOCK_CONTROL_CORECLK_SRC_PLL BIT(3)
#define ADAU17X1_CLOCK_CONTROL_SYSCLK_EN BIT(0)
#define ADAU17X1_SERIAL_PORT1_BCLK32 (0x0 << 5)
#define ADAU17X1_SERIAL_PORT1_BCLK48 (0x1 << 5)
#define ADAU17X1_SERIAL_PORT1_BCLK64 (0x2 << 5)
#define ADAU17X1_SERIAL_PORT1_BCLK128 (0x3 << 5)
#define ADAU17X1_SERIAL_PORT1_BCLK256 (0x4 << 5)
#define ADAU17X1_SERIAL_PORT1_BCLK_MASK (0x7 << 5)
#define ADAU17X1_SERIAL_PORT0_STEREO (0x0 << 1)
#define ADAU17X1_SERIAL_PORT0_TDM4 (0x1 << 1)
#define ADAU17X1_SERIAL_PORT0_TDM8 (0x2 << 1)
#define ADAU17X1_SERIAL_PORT0_TDM_MASK (0x3 << 1)
#define ADAU17X1_SERIAL_PORT0_PULSE_MODE BIT(5)
#define ADAU17X1_CONVERTER0_DAC_PAIR(x) (((x) - 1) << 5)
#define ADAU17X1_CONVERTER0_DAC_PAIR_MASK (0x3 << 5)
#define ADAU17X1_CONVERTER1_ADC_PAIR(x) ((x) - 1)
#define ADAU17X1_CONVERTER1_ADC_PAIR_MASK 0x3
#define ADAU17X1_CONVERTER0_CONVSR_MASK 0x7
#endif
......@@ -1543,16 +1543,16 @@ static void wm_adsp2_boot_work(struct work_struct *work)
ret = regmap_read(dsp->regmap,
dsp->base + ADSP2_CLOCKING, &val);
if (ret != 0) {
dev_err(dsp->dev, "Failed to read clocking: %d\n", ret);
adsp_err(dsp, "Failed to read clocking: %d\n", ret);
return;
}
if ((val & ADSP2_CLK_SEL_MASK) >= 3) {
ret = regulator_enable(dsp->dvfs);
if (ret != 0) {
dev_err(dsp->dev,
"Failed to enable supply: %d\n",
ret);
adsp_err(dsp,
"Failed to enable supply: %d\n",
ret);
return;
}
......@@ -1560,9 +1560,9 @@ static void wm_adsp2_boot_work(struct work_struct *work)
1800000,
1800000);
if (ret != 0) {
dev_err(dsp->dev,
"Failed to raise supply: %d\n",
ret);
adsp_err(dsp,
"Failed to raise supply: %d\n",
ret);
return;
}
}
......@@ -1672,15 +1672,15 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
ret = regulator_set_voltage(dsp->dvfs, 1200000,
1800000);
if (ret != 0)
dev_warn(dsp->dev,
"Failed to lower supply: %d\n",
ret);
adsp_warn(dsp,
"Failed to lower supply: %d\n",
ret);
ret = regulator_disable(dsp->dvfs);
if (ret != 0)
dev_err(dsp->dev,
"Failed to enable supply: %d\n",
ret);
adsp_err(dsp,
"Failed to enable supply: %d\n",
ret);
}
list_for_each_entry(ctl, &dsp->ctl_list, list)
......@@ -1732,28 +1732,25 @@ int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs)
adsp->dvfs = devm_regulator_get(adsp->dev, "DCVDD");
if (IS_ERR(adsp->dvfs)) {
ret = PTR_ERR(adsp->dvfs);
dev_err(adsp->dev, "Failed to get DCVDD: %d\n", ret);
adsp_err(adsp, "Failed to get DCVDD: %d\n", ret);
return ret;
}
ret = regulator_enable(adsp->dvfs);
if (ret != 0) {
dev_err(adsp->dev, "Failed to enable DCVDD: %d\n",
ret);
adsp_err(adsp, "Failed to enable DCVDD: %d\n", ret);
return ret;
}
ret = regulator_set_voltage(adsp->dvfs, 1200000, 1800000);
if (ret != 0) {
dev_err(adsp->dev, "Failed to initialise DVFS: %d\n",
ret);
adsp_err(adsp, "Failed to initialise DVFS: %d\n", ret);
return ret;
}
ret = regulator_disable(adsp->dvfs);
if (ret != 0) {
dev_err(adsp->dev, "Failed to disable DCVDD: %d\n",
ret);
adsp_err(adsp, "Failed to disable DCVDD: %d\n", ret);
return ret;
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册