select SND_SOC_MAX9877 if I2C
select SND_SOC_MC13783 if MFD_MC13XXX
select SND_SOC_ML26124 if I2C
++++ select SND_SOC_NAU8810 if I2C
select SND_SOC_NAU8825 if I2C
select SND_SOC_HDMI_CODEC
select SND_SOC_PCM1681 if I2C
select SND_SOC_RT5645 if I2C
select SND_SOC_RT5651 if I2C
select SND_SOC_RT5659 if I2C
++ ++ select SND_SOC_RT5660 if I2C
++ ++ select SND_SOC_RT5663 if I2C
select SND_SOC_RT5670 if I2C
select SND_SOC_RT5677 if I2C && SPI_MASTER
select SND_SOC_SGTL5000 if I2C
default y if SND_SOC_RT5645=y
default y if SND_SOC_RT5651=y
default y if SND_SOC_RT5659=y
++ ++ default y if SND_SOC_RT5660=y
++ ++ default y if SND_SOC_RT5663=y
default y if SND_SOC_RT5670=y
default y if SND_SOC_RT5677=y
default m if SND_SOC_RT5514=m
default m if SND_SOC_RT5645=m
default m if SND_SOC_RT5651=m
default m if SND_SOC_RT5659=m
++ ++ default m if SND_SOC_RT5660=m
++ ++ default m if SND_SOC_RT5663=m
default m if SND_SOC_RT5670=m
default m if SND_SOC_RT5677=m
config SND_SOC_RT286
tristate
++ ++ select SND_SOC_RT5663
depends on I2C
config SND_SOC_RT298
config SND_SOC_RT5659
tristate
++ ++config SND_SOC_RT5660
++ ++ tristate
++ ++
++ ++config SND_SOC_RT5663
++ ++ tristate
++ ++
config SND_SOC_RT5670
tristate
config SND_SOC_ML26124
tristate
++++config SND_SOC_NAU8810
++++ tristate "Nuvoton Technology Corporation NAU88C10 CODEC"
++++ depends on I2C
++++
config SND_SOC_NAU8825
tristate
snd-soc-max9860-objs := max9860.o
snd-soc-mc13783-objs := mc13783.o
snd-soc-ml26124-objs := ml26124.o
++++snd-soc-nau8810-objs := nau8810.o
snd-soc-nau8825-objs := nau8825.o
snd-soc-hdmi-codec-objs := hdmi-codec.o
snd-soc-pcm1681-objs := pcm1681.o
snd-soc-rt5645-objs := rt5645.o
snd-soc-rt5651-objs := rt5651.o
snd-soc-rt5659-objs := rt5659.o
++ ++snd-soc-rt5660-objs := rt5660.o
++ ++snd-soc-rt5663-objs := rt5663.o
snd-soc-rt5670-objs := rt5670.o
snd-soc-rt5677-objs := rt5677.o
snd-soc-rt5677-spi-objs := rt5677-spi.o
obj-$(CONFIG_SND_SOC_MAX9860) += snd-soc-max9860.o
obj-$(CONFIG_SND_SOC_MC13783) += snd-soc-mc13783.o
obj-$(CONFIG_SND_SOC_ML26124) += snd-soc-ml26124.o
++++obj-$(CONFIG_SND_SOC_NAU8810) += snd-soc-nau8810.o
obj-$(CONFIG_SND_SOC_NAU8825) += snd-soc-nau8825.o
obj-$(CONFIG_SND_SOC_HDMI_CODEC) += snd-soc-hdmi-codec.o
obj-$(CONFIG_SND_SOC_PCM1681) += snd-soc-pcm1681.o
obj-$(CONFIG_SND_SOC_RT5645) += snd-soc-rt5645.o
obj-$(CONFIG_SND_SOC_RT5651) += snd-soc-rt5651.o
obj-$(CONFIG_SND_SOC_RT5659) += snd-soc-rt5659.o
++ ++obj-$(CONFIG_SND_SOC_RT5660) += snd-soc-rt5660.o
++ ++obj-$(CONFIG_SND_SOC_RT5663) += snd-soc-rt5663.o
obj-$(CONFIG_SND_SOC_RT5670) += snd-soc-rt5670.o
obj-$(CONFIG_SND_SOC_RT5677) += snd-soc-rt5677.o
obj-$(CONFIG_SND_SOC_RT5677_SPI) += snd-soc-rt5677-spi.o
* published by the Free Software Foundation.
*/
+ +++#include <linux/clk.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
static int rt5659_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
+ +++ struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
struct rt5659_priv *rt5659 = snd_soc_codec_get_drvdata(codec);
+ +++ int ret;
switch (level) {
case SND_SOC_BIAS_PREPARE:
RT5659_PWR_FV1 | RT5659_PWR_FV2);
break;
+ +++ case SND_SOC_BIAS_STANDBY:
+ +++ if (dapm->bias_level == SND_SOC_BIAS_OFF) {
+ +++ ret = clk_prepare_enable(rt5659->mclk);
+ +++ if (ret) {
+ +++ dev_err(codec->dev,
+ +++ "failed to enable MCLK: %d\n", ret);
+ +++ return ret;
+ +++ }
+ +++ }
+ +++ break;
+ +++
case SND_SOC_BIAS_OFF:
regmap_update_bits(rt5659->regmap, RT5659_PWR_DIG_1,
RT5659_PWR_LDO, 0);
RT5659_PWR_MB | RT5659_PWR_VREF2);
regmap_update_bits(rt5659->regmap, RT5659_DIG_MISC,
RT5659_DIG_GATE_CTRL, 0);
+ +++ clk_disable_unprepare(rt5659->mclk);
break;
default:
.resume = rt5659_resume,
.set_bias_level = rt5659_set_bias_level,
.idle_bias_off = true,
---- .controls = rt5659_snd_controls,
---- .num_controls = ARRAY_SIZE(rt5659_snd_controls),
---- .dapm_widgets = rt5659_dapm_widgets,
---- .num_dapm_widgets = ARRAY_SIZE(rt5659_dapm_widgets),
---- .dapm_routes = rt5659_dapm_routes,
---- .num_dapm_routes = ARRAY_SIZE(rt5659_dapm_routes),
++++ .component_driver = {
++++ .controls = rt5659_snd_controls,
++++ .num_controls = ARRAY_SIZE(rt5659_snd_controls),
++++ .dapm_widgets = rt5659_dapm_widgets,
++++ .num_dapm_widgets = ARRAY_SIZE(rt5659_dapm_widgets),
++++ .dapm_routes = rt5659_dapm_routes,
++++ .num_dapm_routes = ARRAY_SIZE(rt5659_dapm_routes),
++++ },
};
regmap_write(rt5659->regmap, RT5659_RESET, 0);
+ +++ /* Check if MCLK provided */
+ +++ rt5659->mclk = devm_clk_get(&i2c->dev, "mclk");
+ +++ if (IS_ERR(rt5659->mclk)) {
+ +++ if (PTR_ERR(rt5659->mclk) != -ENOENT)
+ +++ return PTR_ERR(rt5659->mclk);
+ +++ /* Otherwise mark the mclk pointer to NULL */
+ +++ rt5659->mclk = NULL;
+ +++ }
+ +++
rt5659_calibrate(rt5659);
/* line in diff mode*/
if (ret)
dev_err(&i2c->dev, "Failed to reguest IRQ: %d\n", ret);
+ +++ /* Enable IRQ output for GPIO1 pin any way */
+ +++ regmap_update_bits(rt5659->regmap, RT5659_GPIO_CTRL_1,
+ +++ RT5659_GP1_PIN_MASK, RT5659_GP1_PIN_IRQ);
}
return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5659,
* published by the Free Software Foundation.
*/
+++ +#include <linux/acpi.h>
#include <linux/fs.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#define RT5677_PR_BASE (RT5677_PR_RANGE_BASE + (0 * RT5677_PR_SPACING))
+++ +/* GPIO indexes defined by ACPI */
+++ +enum {
+++ + RT5677_GPIO_PLUG_DET = 0,
+++ + RT5677_GPIO_MIC_PRESENT_L = 1,
+++ + RT5677_GPIO_HOTWORD_DET_L = 2,
+++ + RT5677_GPIO_DSP_INT = 3,
+++ + RT5677_GPIO_HP_AMP_SHDN_L = 4,
+++ +};
+++ +
static const struct regmap_range_cfg rt5677_ranges[] = {
{
.name = "PR",
return regmap_irq_get_virq(data, irq);
}
----static struct gpio_chip rt5677_template_chip = {
++++static const struct gpio_chip rt5677_template_chip = {
.label = "rt5677",
.owner = THIS_MODULE,
.direction_output = rt5677_gpio_direction_out,
.resume = rt5677_resume,
.set_bias_level = rt5677_set_bias_level,
.idle_bias_off = true,
---- .controls = rt5677_snd_controls,
---- .num_controls = ARRAY_SIZE(rt5677_snd_controls),
---- .dapm_widgets = rt5677_dapm_widgets,
---- .num_dapm_widgets = ARRAY_SIZE(rt5677_dapm_widgets),
---- .dapm_routes = rt5677_dapm_routes,
---- .num_dapm_routes = ARRAY_SIZE(rt5677_dapm_routes),
++++ .component_driver = {
++++ .controls = rt5677_snd_controls,
++++ .num_controls = ARRAY_SIZE(rt5677_snd_controls),
++++ .dapm_widgets = rt5677_dapm_widgets,
++++ .num_dapm_widgets = ARRAY_SIZE(rt5677_dapm_widgets),
++++ .dapm_routes = rt5677_dapm_routes,
++++ .num_dapm_routes = ARRAY_SIZE(rt5677_dapm_routes),
++++ },
};
static const struct regmap_config rt5677_regmap_physical = {
static const struct i2c_device_id rt5677_i2c_id[] = {
{ "rt5677", RT5677 },
{ "rt5676", RT5676 },
+++ + { "RT5677CE:00", RT5677 },
{ }
};
MODULE_DEVICE_TABLE(i2c, rt5677_i2c_id);
+++ +static const struct acpi_gpio_params plug_det_gpio = { RT5677_GPIO_PLUG_DET, 0, false };
+++ +static const struct acpi_gpio_params mic_present_gpio = { RT5677_GPIO_MIC_PRESENT_L, 0, false };
+++ +static const struct acpi_gpio_params headphone_enable_gpio = { RT5677_GPIO_HP_AMP_SHDN_L, 0, false };
+++ +
+++ +static const struct acpi_gpio_mapping bdw_rt5677_gpios[] = {
+++ + { "plug-det-gpios", &plug_det_gpio, 1 },
+++ + { "mic-present-gpios", &mic_present_gpio, 1 },
+++ + { "headphone-enable-gpios", &headphone_enable_gpio, 1 },
+++ + { NULL },
+++ +};
+++ +
+++ +static void rt5677_read_acpi_properties(struct rt5677_priv *rt5677,
+++ + struct device *dev)
+++ +{
+++ + int ret;
+++ + u32 val;
+++ +
+++ + ret = acpi_dev_add_driver_gpios(ACPI_COMPANION(dev),
+++ + bdw_rt5677_gpios);
+++ + if (ret)
+++ + dev_warn(dev, "Failed to add driver gpios\n");
+++ +
+++ + if (!device_property_read_u32(dev, "DCLK", &val))
+++ + rt5677->pdata.dmic2_clk_pin = val;
+++ +
+++ + rt5677->pdata.in1_diff = device_property_read_bool(dev, "IN1");
+++ + rt5677->pdata.in2_diff = device_property_read_bool(dev, "IN2");
+++ + rt5677->pdata.lout1_diff = device_property_read_bool(dev, "OUT1");
+++ + rt5677->pdata.lout2_diff = device_property_read_bool(dev, "OUT2");
+++ + rt5677->pdata.lout3_diff = device_property_read_bool(dev, "OUT3");
+++ +
+++ + device_property_read_u32(dev, "JD1", &rt5677->pdata.jd1_gpio);
+++ + device_property_read_u32(dev, "JD2", &rt5677->pdata.jd2_gpio);
+++ + device_property_read_u32(dev, "JD3", &rt5677->pdata.jd3_gpio);
+++ +}
+++ +
static void rt5677_read_device_properties(struct rt5677_priv *rt5677,
struct device *dev)
{
if (pdata)
rt5677->pdata = *pdata;
--- - else
+++ + else if (i2c->dev.of_node)
rt5677_read_device_properties(rt5677, &i2c->dev);
+++ + else if (ACPI_HANDLE(&i2c->dev))
+++ + rt5677_read_acpi_properties(rt5677, &i2c->dev);
+++ + else
+++ + return -EINVAL;
/* pow-ldo2 and reset are optional. The codec pins may be statically
* connected on the board without gpios. If the gpio device property
.set_bias_level = uda134x_set_bias_level,
.suspend_bias_off = true,
---- .dapm_widgets = uda134x_dapm_widgets,
---- .num_dapm_widgets = ARRAY_SIZE(uda134x_dapm_widgets),
---- .dapm_routes = uda134x_dapm_routes,
---- .num_dapm_routes = ARRAY_SIZE(uda134x_dapm_routes),
++++ .component_driver = {
++++ .dapm_widgets = uda134x_dapm_widgets,
++++ .num_dapm_widgets = ARRAY_SIZE(uda134x_dapm_widgets),
++++ .dapm_routes = uda134x_dapm_routes,
++++ .num_dapm_routes = ARRAY_SIZE(uda134x_dapm_routes),
++++ },
};
static const struct regmap_config uda134x_regmap_config = {
{
struct uda134x_platform_data *pd = pdev->dev.platform_data;
struct uda134x_priv *uda134x;
++++ int ret;
if (!pd) {
dev_err(&pdev->dev, "Missing L3 bitbang function\n");
uda134x->pd = pd;
platform_set_drvdata(pdev, uda134x);
++++ if (pd->l3.use_gpios) {
++++ ret = l3_set_gpio_ops(&pdev->dev, &uda134x->pd->l3);
++++ if (ret < 0)
++++ return ret;
++++ }
++++
uda134x->regmap = devm_regmap_init(&pdev->dev, NULL, pd,
&uda134x_regmap_config);
if (IS_ERR(uda134x->regmap))
};
#endif
---- static struct platform_device *s3c24xx_uda134x_snd_device;
----
static int s3c24xx_uda134x_startup(struct snd_pcm_substream *substream)
{
---- int ret = 0;
++++ struct snd_soc_pcm_runtime *rtd = substream->private_data;
++++ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
#ifdef ENFORCE_RATES
struct snd_pcm_runtime *runtime = substream->runtime;
#endif
++++ int ret = 0;
mutex_lock(&clk_lock);
---- pr_debug("%s %d\n", __func__, clk_users);
++++
if (clk_users == 0) {
---- xtal = clk_get(&s3c24xx_uda134x_snd_device->dev, "xtal");
++++ xtal = clk_get(rtd->dev, "xtal");
if (IS_ERR(xtal)) {
---- printk(KERN_ERR "%s cannot get xtal\n", __func__);
++++ dev_err(rtd->dev, "%s cannot get xtal\n", __func__);
ret = PTR_ERR(xtal);
} else {
---- pclk = clk_get(&s3c24xx_uda134x_snd_device->dev,
---- "pclk");
++++ pclk = clk_get(cpu_dai->dev, "iis");
if (IS_ERR(pclk)) {
---- printk(KERN_ERR "%s cannot get pclk\n",
---- __func__);
++++ dev_err(rtd->dev, "%s cannot get pclk\n",
++++ __func__);
clk_put(xtal);
ret = PTR_ERR(pclk);
}
SNDRV_PCM_HW_PARAM_RATE,
&hw_constraints_rates);
if (ret < 0)
---- printk(KERN_ERR "%s cannot set constraints\n",
---- __func__);
++++ dev_err(rtd->dev, "%s cannot set constraints\n",
++++ __func__);
#endif
}
return ret;
static void s3c24xx_uda134x_shutdown(struct snd_pcm_substream *substream)
{
mutex_lock(&clk_lock);
---- pr_debug("%s %d\n", __func__, clk_users);
clk_users -= 1;
if (clk_users == 0) {
clk_put(xtal);
clk_source = S3C24XX_CLKSRC_PCLK;
div = bi % 33;
}
---- pr_debug("%s desired rate %lu, %d\n", __func__, rate, bi);
++++
++++ dev_dbg(rtd->dev, "%s desired rate %lu, %d\n", __func__, rate, bi);
clk = (fs_mode == S3C2410_IISMOD_384FS ? 384 : 256) * rate;
---- pr_debug("%s will use: %s %s %d sysclk %d err %ld\n", __func__,
---- fs_mode == S3C2410_IISMOD_384FS ? "384FS" : "256FS",
---- clk_source == S3C24XX_CLKSRC_MPLL ? "MPLLin" : "PCLK",
---- div, clk, err);
++++
++++ dev_dbg(rtd->dev, "%s will use: %s %s %d sysclk %d err %ld\n", __func__,
++++ fs_mode == S3C2410_IISMOD_384FS ? "384FS" : "256FS",
++++ clk_source == S3C24XX_CLKSRC_MPLL ? "MPLLin" : "PCLK",
++++ div, clk, err);
if ((err * 100 / rate) > 5) {
---- printk(KERN_ERR "S3C24XX_UDA134X: effective frequency "
---- "too different from desired (%ld%%)\n",
---- err * 100 / rate);
++++ dev_err(rtd->dev, "effective frequency too different "
++++ "from desired (%ld%%)\n", err * 100 / rate);
return -EINVAL;
}
.num_links = 1,
};
---- static struct s3c24xx_uda134x_platform_data *s3c24xx_uda134x_l3_pins;
----
---- static void setdat(int v)
---- {
---- gpio_set_value(s3c24xx_uda134x_l3_pins->l3_data, v > 0);
---- }
----
---- static void setclk(int v)
---- {
---- gpio_set_value(s3c24xx_uda134x_l3_pins->l3_clk, v > 0);
---- }
----
---- static void setmode(int v)
---- {
---- gpio_set_value(s3c24xx_uda134x_l3_pins->l3_mode, v > 0);
---- }
----
---- /* FIXME - This must be codec platform data but in which board file ?? */
---- static struct uda134x_platform_data s3c24xx_uda134x = {
---- .l3 = {
---- .setdat = setdat,
---- .setclk = setclk,
---- .setmode = setmode,
---- .data_hold = 1,
---- .data_setup = 1,
---- .clock_high = 1,
---- .mode_hold = 1,
---- .mode = 1,
---- .mode_setup = 1,
---- },
---- };
----
---- static int s3c24xx_uda134x_setup_pin(int pin, char *fun)
---- {
---- if (gpio_request(pin, "s3c24xx_uda134x") < 0) {
---- printk(KERN_ERR "S3C24XX_UDA134X SoC Audio: "
---- "l3 %s pin already in use", fun);
---- return -EBUSY;
---- }
---- gpio_direction_output(pin, 0);
---- return 0;
---- }
----
static int s3c24xx_uda134x_probe(struct platform_device *pdev)
{
++++ struct snd_soc_card *card = &snd_soc_s3c24xx_uda134x;
int ret;
---- printk(KERN_INFO "S3C24XX_UDA134X SoC Audio driver\n");
++++ platform_set_drvdata(pdev, card);
++++ card->dev = &pdev->dev;
---- s3c24xx_uda134x_l3_pins = pdev->dev.platform_data;
---- if (s3c24xx_uda134x_l3_pins == NULL) {
---- printk(KERN_ERR "S3C24XX_UDA134X SoC Audio: "
---- "unable to find platform data\n");
---- return -ENODEV;
---- }
---- s3c24xx_uda134x.power = s3c24xx_uda134x_l3_pins->power;
---- s3c24xx_uda134x.model = s3c24xx_uda134x_l3_pins->model;
----
---- if (s3c24xx_uda134x_setup_pin(s3c24xx_uda134x_l3_pins->l3_data,
---- "data") < 0)
---- return -EBUSY;
---- if (s3c24xx_uda134x_setup_pin(s3c24xx_uda134x_l3_pins->l3_clk,
---- "clk") < 0) {
---- gpio_free(s3c24xx_uda134x_l3_pins->l3_data);
---- return -EBUSY;
---- }
---- if (s3c24xx_uda134x_setup_pin(s3c24xx_uda134x_l3_pins->l3_mode,
---- "mode") < 0) {
---- gpio_free(s3c24xx_uda134x_l3_pins->l3_data);
---- gpio_free(s3c24xx_uda134x_l3_pins->l3_clk);
---- return -EBUSY;
---- }
----
---- s3c24xx_uda134x_snd_device = platform_device_alloc("soc-audio", -1);
---- if (!s3c24xx_uda134x_snd_device) {
---- printk(KERN_ERR "S3C24XX_UDA134X SoC Audio: "
---- "Unable to register\n");
---- return -ENOMEM;
---- }
----
---- platform_set_drvdata(s3c24xx_uda134x_snd_device,
---- &snd_soc_s3c24xx_uda134x);
---- platform_device_add_data(s3c24xx_uda134x_snd_device, &s3c24xx_uda134x, sizeof(s3c24xx_uda134x));
---- ret = platform_device_add(s3c24xx_uda134x_snd_device);
---- if (ret) {
---- printk(KERN_ERR "S3C24XX_UDA134X SoC Audio: Unable to add\n");
---- platform_device_put(s3c24xx_uda134x_snd_device);
---- }
++++ ret = devm_snd_soc_register_card(&pdev->dev, card);
++++ if (ret)
++++ dev_err(&pdev->dev, "failed to register card: %d\n", ret);
return ret;
}
---- static int s3c24xx_uda134x_remove(struct platform_device *pdev)
---- {
---- platform_device_unregister(s3c24xx_uda134x_snd_device);
---- gpio_free(s3c24xx_uda134x_l3_pins->l3_data);
---- gpio_free(s3c24xx_uda134x_l3_pins->l3_clk);
---- gpio_free(s3c24xx_uda134x_l3_pins->l3_mode);
---- return 0;
---- }
----
static struct platform_driver s3c24xx_uda134x_driver = {
.probe = s3c24xx_uda134x_probe,
---- .remove = s3c24xx_uda134x_remove,
.driver = {
.name = "s3c24xx_uda134x",
},
};
----
module_platform_driver(s3c24xx_uda134x_driver);
MODULE_AUTHOR("Zoltan Devai, Christian Pellegrin <chripell@evolware.org>");