* [PATCH 1/3] sound: soc: codecs: Add es8328 codec
[not found] ` <1391749517-11787-1-git-send-email-xobs-nXMMniAx+RbQT0dZR+AlfA@public.gmane.org>
@ 2014-02-07 5:05 ` Sean Cross
2014-02-07 18:12 ` Mark Brown
[not found] ` <1391749517-11787-2-git-send-email-xobs-nXMMniAx+RbQT0dZR+AlfA@public.gmane.org>
2014-02-07 5:05 ` [PATCH 2/3] sound: soc: fsl: Add support for Novena onboard audio Sean Cross
2014-02-07 5:05 ` [PATCH 3/3] dts: imx: add kosagi novena imx6q dts file Sean Cross
2 siblings, 2 replies; 14+ messages in thread
From: Sean Cross @ 2014-02-07 5:05 UTC (permalink / raw)
To: devicetree-u79uwXL29TY76Z2rM5mHXA,
alsa-devel-K7yf7f+aM1XWsZ/bQMPhNw
Cc: Shawn Guo, Sascha Hauer, Mark Brown, Liam Girdwood, Sean Cross
Add support for the ES8328 audio codec.
---
sound/soc/codecs/Kconfig | 4 +
sound/soc/codecs/Makefile | 2 +
sound/soc/codecs/es8328.c | 611 ++++++++++++++++++++++++++++++++++++++++++++++
sound/soc/codecs/es8328.h | 240 ++++++++++++++++++
4 files changed, 857 insertions(+)
create mode 100644 sound/soc/codecs/es8328.c
create mode 100644 sound/soc/codecs/es8328.h
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 983d087a..2b0a821 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -43,6 +43,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_DA732X if I2C
select SND_SOC_DA9055 if I2C
select SND_SOC_BT_SCO
+ select SND_SOC_ES8328 if I2C
select SND_SOC_ISABELLE if I2C
select SND_SOC_JZ4740_CODEC
select SND_SOC_LM4857 if I2C
@@ -283,6 +284,9 @@ config SND_SOC_BT_SCO
config SND_SOC_DMIC
tristate
+config SND_SOC_ES8328
+ tristate
+
config SND_SOC_ISABELLE
tristate
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index bc12676..1b62c93 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -30,6 +30,7 @@ snd-soc-da732x-objs := da732x.o
snd-soc-da9055-objs := da9055.o
snd-soc-bt-sco-objs := bt-sco.o
snd-soc-dmic-objs := dmic.o
+snd-soc-es8328-objs := es8328.o
snd-soc-isabelle-objs := isabelle.o
snd-soc-jz4740-codec-objs := jz4740.o
snd-soc-l3-objs := l3.o
@@ -163,6 +164,7 @@ obj-$(CONFIG_SND_SOC_DA732X) += snd-soc-da732x.o
obj-$(CONFIG_SND_SOC_DA9055) += snd-soc-da9055.o
obj-$(CONFIG_SND_SOC_BT_SCO) += snd-soc-bt-sco.o
obj-$(CONFIG_SND_SOC_DMIC) += snd-soc-dmic.o
+obj-$(CONFIG_SND_SOC_ES8328) += snd-soc-es8328.o
obj-$(CONFIG_SND_SOC_ISABELLE) += snd-soc-isabelle.o
obj-$(CONFIG_SND_SOC_JZ4740_CODEC) += snd-soc-jz4740-codec.o
obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o
diff --git a/sound/soc/codecs/es8328.c b/sound/soc/codecs/es8328.c
new file mode 100644
index 0000000..db118f4
--- /dev/null
+++ b/sound/soc/codecs/es8328.c
@@ -0,0 +1,611 @@
+/*
+ * es8328.c -- ES8328 ALSA SoC Audio driver
+ *
+ * Copyright 2014 Sutajio Ko-Usagi PTE LTD
+ *
+ * Author: Sean Cross <xobs-nXMMniAx+RbQT0dZR+AlfA@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/spi/spi.h>
+#include <linux/slab.h>
+#include <linux/of_device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+#include "es8328.h"
+
+/* Run the codec at 22.5792 MHz to support these rates */
+enum es8328_rate {
+ ES8328_RATE_8019,
+ ES8328_RATE_11025,
+ ES8328_RATE_22050,
+ ES8328_RATE_44100,
+};
+
+uint8_t sample_ratios[] = {
+ [ES8328_RATE_8019 ] = 0x9,
+ [ES8328_RATE_11025] = 0x7,
+ [ES8328_RATE_22050] = 0x4,
+ [ES8328_RATE_44100] = 0x2,
+};
+
+#define ES8328_RATES (SNDRV_PCM_RATE_44100 | \
+ SNDRV_PCM_RATE_22050 | \
+ SNDRV_PCM_RATE_11025)
+#define ES8328_FORMATS (SNDRV_PCM_FMTBIT_S16_LE)
+
+/* codec private data */
+struct es8328_priv {
+ struct regmap *regmap;
+ int sysclk;
+};
+
+static const DECLARE_TLV_DB_SCALE(play_tlv, -3000, 100, 0);
+static const DECLARE_TLV_DB_SCALE(cap_tlv, -9600, 50, 0);
+static const DECLARE_TLV_DB_SCALE(pga_tlv, 0, 300, 0);
+
+static const struct snd_kcontrol_new es8328_snd_controls[] = {
+SOC_DOUBLE_R_TLV("Speaker Playback Volume",
+ ES8328_DACCONTROL26, ES8328_DACCONTROL27, 0, 0x24, 0, play_tlv),
+SOC_DOUBLE_R_TLV("Headphone Playback Volume",
+ ES8328_DACCONTROL24, ES8328_DACCONTROL25, 0, 0x24, 0, play_tlv),
+
+SOC_DOUBLE_R_TLV("Mic Capture Volume",
+ ES8328_ADCCONTROL8, ES8328_ADCCONTROL9, 0, 0xc0, 1, cap_tlv),
+SOC_DOUBLE_TLV("Mic PGA Volume",
+ ES8328_ADCCONTROL1, 4, 0, 0x08, 0, pga_tlv),
+};
+
+/*
+ * DAPM controls.
+ */
+static const struct snd_soc_dapm_widget es8328_dapm_widgets[] = {
+ SND_SOC_DAPM_DAC("Speaker Volume", "HiFi Playback", SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_OUTPUT("VOUTL"),
+ SND_SOC_DAPM_OUTPUT("VOUTR"),
+ SND_SOC_DAPM_INPUT("LINE_IN"),
+ SND_SOC_DAPM_INPUT("MIC_IN"),
+ SND_SOC_DAPM_OUTPUT("HP_OUT"),
+ SND_SOC_DAPM_OUTPUT("SPK_OUT"),
+};
+
+
+static const struct snd_soc_dapm_route es8328_intercon[] = {
+ {"VOUTL", NULL, "DAC"},
+ {"VOUTR", NULL, "DAC"},
+};
+
+static int es8328_mute(struct snd_soc_dai *dai, int mute)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ u16 mute_reg = snd_soc_read(codec, ES8328_DACCONTROL3);
+
+ if (mute)
+ mute_reg |= ES8328_DACCONTROL3_DACMUTE;
+ else
+ mute_reg &= ~ES8328_DACCONTROL3_DACMUTE;
+ return snd_soc_write(codec, ES8328_DACCONTROL3, mute_reg);
+}
+
+static int es8328_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_codec *codec = dai->codec;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ u8 dac = snd_soc_read(codec, ES8328_DACCONTROL2);
+ dac &= ~ES8328_DACCONTROL2_RATEMASK;
+
+ switch (params_rate(params)) {
+ case 8000:
+ dac |= sample_ratios[ES8328_RATE_8019];
+ break;
+ case 11025:
+ dac |= sample_ratios[ES8328_RATE_11025];
+ break;
+ case 22050:
+ dac |= sample_ratios[ES8328_RATE_22050];
+ break;
+ case 44100:
+ dac |= sample_ratios[ES8328_RATE_44100];
+ break;
+ default:
+ dev_err(codec->dev, "%s: unknown rate %d\n",
+ __func__, params_rate(params));
+ return -EINVAL;
+ }
+ snd_soc_write(codec, ES8328_DACCONTROL2, dac);
+ }
+
+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+ u8 adc = snd_soc_read(codec, ES8328_ADCCONTROL5);
+ adc &= ~ES8328_ADCCONTROL5_RATEMASK;
+
+ switch (params_rate(params)) {
+ case 8000:
+ adc |= sample_ratios[ES8328_RATE_8019];
+ break;
+ case 11025:
+ adc |= sample_ratios[ES8328_RATE_11025];
+ break;
+ case 22050:
+ adc |= sample_ratios[ES8328_RATE_22050];
+ break;
+ case 44100:
+ adc |= sample_ratios[ES8328_RATE_44100];
+ break;
+ default:
+ dev_err(codec->dev, "%s: unknown rate %d\n",
+ __func__, params_rate(params));
+ return -EINVAL;
+ }
+ snd_soc_write(codec, ES8328_ADCCONTROL5, adc);
+ }
+
+ return 0;
+}
+
+static int es8328_set_dai_fmt(struct snd_soc_dai *codec_dai,
+ unsigned int fmt)
+{
+ if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) != SND_SOC_DAIFMT_I2S)
+ return -EINVAL;
+
+ if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBM_CFM)
+ return -EINVAL;
+
+ if ((fmt & SND_SOC_DAIFMT_INV_MASK) != SND_SOC_DAIFMT_NB_NF)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int es8328_set_dai_sysclk(struct snd_soc_dai *codec_dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct es8328_priv *es8328 = snd_soc_codec_get_drvdata(codec);
+
+ switch (clk_id) {
+ case 0:
+ es8328->sysclk = freq;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int es8328_adc_enable(struct snd_soc_codec *codec)
+{
+ u16 reg = snd_soc_read(codec, ES8328_CHIPPOWER);
+ reg &= ~(ES8328_CHIPPOWER_ADCVREF_OFF |
+ ES8328_CHIPPOWER_ADCPLL_OFF |
+ ES8328_CHIPPOWER_ADCSTM_RESET |
+ ES8328_CHIPPOWER_ADCDIG_OFF);
+ snd_soc_write(codec, ES8328_CHIPPOWER, reg);
+
+ /* Set up microphone to be differential input */
+ snd_soc_write(codec, ES8328_ADCCONTROL2, 0xf0);
+
+ /* Set ADC to act as I2S master */
+ snd_soc_write(codec, ES8328_ADCCONTROL3, 0x02);
+
+ /* Set I2S to 16-bit mode */
+ snd_soc_write(codec, ES8328_ADCCONTROL4, 0x18);
+
+ /* Frequency clock of 272 */
+ snd_soc_write(codec, ES8328_ADCCONTROL5, 0x02);
+
+ return 0;
+}
+
+static int es8328_dac_enable(struct snd_soc_codec *codec)
+{
+ u16 old_volumes[4];
+ u16 reg;
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ old_volumes[i] = snd_soc_read(codec, i + ES8328_DACCONTROL24);
+ snd_soc_write(codec, i + ES8328_DACCONTROL24, 0);
+ }
+
+ /* Power up LOUT2 ROUT2, and power down xOUT1 */
+ snd_soc_write(codec, ES8328_DACPOWER,
+ ES8328_DACPOWER_ROUT2_ON |
+ ES8328_DACPOWER_LOUT2_ON);
+
+ /* Enable click-free power up */
+ snd_soc_write(codec, ES8328_DACCONTROL6, ES8328_DACCONTROL6_CLICKFREE);
+ snd_soc_write(codec, ES8328_DACCONTROL3, 0x36);
+
+ /* Set I2S to 16-bit mode */
+ snd_soc_write(codec, ES8328_DACCONTROL1, ES8328_DACCONTROL1_DACWL_16);
+
+ /* No attenuation */
+ snd_soc_write(codec, ES8328_DACCONTROL4, 0x00);
+ snd_soc_write(codec, ES8328_DACCONTROL5, 0x00);
+
+ /* Set LIN2 for the output mixer */
+ snd_soc_write(codec, ES8328_DACCONTROL16,
+ ES8328_DACCONTROL16_RMIXSEL_RIN2 |
+ ES8328_DACCONTROL16_LMIXSEL_LIN2);
+
+ /* Point the left DAC at the left mixer */
+ snd_soc_write(codec, ES8328_DACCONTROL17, ES8328_DACCONTROL17_LD2LO);
+ /* Point the right DAC at the right mixer */
+ snd_soc_write(codec, ES8328_DACCONTROL20, ES8328_DACCONTROL20_RD2RO);
+
+ /* Disable all other outputs */
+ snd_soc_write(codec, ES8328_DACCONTROL18, 0x00);
+ snd_soc_write(codec, ES8328_DACCONTROL19, 0x00);
+
+
+ /* Disable mono mode for DACL, and mute DACR */
+ snd_soc_write(codec, ES8328_DACCONTROL7, 0x00);
+
+ for (i = 0; i < 4; i++)
+ snd_soc_write(codec, i + ES8328_DACCONTROL24, old_volumes[i]);
+
+ reg = snd_soc_read(codec, ES8328_CHIPPOWER);
+ reg &= ~(ES8328_CHIPPOWER_DACVREF_OFF |
+ ES8328_CHIPPOWER_DACPLL_OFF |
+ ES8328_CHIPPOWER_DACSTM_RESET |
+ ES8328_CHIPPOWER_DACDIG_OFF);
+ snd_soc_write(codec, ES8328_CHIPPOWER, reg);
+ snd_soc_write(codec, ES8328_DACCONTROL3, 0x32);
+
+ return 0;
+}
+
+static int es8328_pcm_prepare(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_codec *codec = dai->codec;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ es8328_dac_enable(codec);
+
+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+ es8328_adc_enable(codec);
+
+ return 0;
+}
+
+static void es8328_pcm_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ u16 reg;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ /* Mute DAC */
+ snd_soc_write(codec, ES8328_DACCONTROL3,
+ ES8328_DACCONTROL3_DACZEROCROSS |
+ ES8328_DACCONTROL3_DACSOFTRAMP |
+ ES8328_DACCONTROL3_DACMUTE);
+
+ /* Power down DAC and disable LOUT/ROUT */
+ snd_soc_write(codec, ES8328_DACPOWER,
+ ES8328_DACPOWER_LDAC_OFF |
+ ES8328_DACPOWER_RDAC_OFF);
+
+ /* Power down DEM and STM */
+ reg = snd_soc_read(codec, ES8328_CHIPPOWER);
+ reg |= (ES8328_CHIPPOWER_DACVREF_OFF |
+ ES8328_CHIPPOWER_DACPLL_OFF |
+ ES8328_CHIPPOWER_DACDIG_OFF);
+ snd_soc_write(codec, ES8328_CHIPPOWER, reg);
+ }
+
+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+ /* Mute ADC */
+ snd_soc_write(codec, ES8328_ADCCONTROL7,
+ ES8328_ADCCONTROL7_ADC_LER |
+ ES8328_ADCCONTROL7_ADC_ZERO_CROSS |
+ ES8328_ADCCONTROL7_ADC_SOFT_RAMP);
+
+ /* Power down ADC */
+ snd_soc_write(codec, ES8328_ADCPOWER,
+ ES8328_ADCPOWER_ADC_BIAS_GEN_OFF |
+ ES8328_ADCPOWER_MIC_BIAS_OFF |
+ ES8328_ADCPOWER_ADCR_OFF |
+ ES8328_ADCPOWER_ADCL_OFF |
+ ES8328_ADCPOWER_AINR_OFF |
+ ES8328_ADCPOWER_AINL_OFF);
+
+ /* Power down DEM and STM */
+ reg = snd_soc_read(codec, ES8328_CHIPPOWER);
+ reg |= (ES8328_CHIPPOWER_ADCVREF_OFF |
+ ES8328_CHIPPOWER_ADCPLL_OFF |
+ ES8328_CHIPPOWER_ADCDIG_OFF);
+ snd_soc_write(codec, ES8328_CHIPPOWER, reg);
+ }
+
+ return;
+}
+
+static int es8328_init(struct snd_soc_codec *codec)
+{
+ /* Master serial port mode */
+ snd_soc_write(codec, ES8328_MASTERMODE,
+ ES8328_MASTERMODE_MCLKDIV2 |
+ ES8328_MASTERMODE_MSC);
+
+ /* Power everything down and reset the cip */
+ snd_soc_write(codec, ES8328_CHIPPOWER,
+ ES8328_CHIPPOWER_DACSTM_RESET |
+ ES8328_CHIPPOWER_ADCSTM_RESET |
+ ES8328_CHIPPOWER_DACDIG_OFF |
+ ES8328_CHIPPOWER_ADCDIG_OFF |
+ ES8328_CHIPPOWER_DACVREF_OFF |
+ ES8328_CHIPPOWER_ADCVREF_OFF);
+
+ /* Power up. Set ADC and DAC to use different frequency ratios */
+ snd_soc_write(codec, ES8328_CONTROL1,
+ ES8328_CONTROL1_VMIDSEL_50k |
+ ES8328_CONTROL1_ENREF);
+
+ /* Power up more blocks */
+ snd_soc_write(codec, ES8328_CONTROL2,
+ ES8328_CONTROL2_OVERCURRENT_ON |
+ ES8328_CONTROL2_THERMAL_SHUTDOWN_ON);
+
+
+ /* Power on the chip (but leave VRET off) */
+ /*
+ snd_soc_write(codec, ES8328_CHIPPOWER,
+ ES8328_CHIPPOWER_DACVREF_OFF |
+ ES8328_CHIPPOWER_ADCVREF_OFF);
+ */
+
+
+ /* Enable muting, and turn on zerocross */
+ snd_soc_write(codec, ES8328_DACCONTROL3,
+ ES8328_DACCONTROL3_DACZEROCROSS |
+ ES8328_DACCONTROL3_DACSOFTRAMP |
+ ES8328_DACCONTROL3_DACMUTE);
+
+ return 0;
+}
+
+static const struct snd_soc_dai_ops es8328_dai_ops = {
+ .hw_params = es8328_hw_params,
+ .prepare = es8328_pcm_prepare,
+ .shutdown = es8328_pcm_shutdown,
+// .digital_mute = es8328_mute,
+ .set_fmt = es8328_set_dai_fmt,
+ .set_sysclk = es8328_set_dai_sysclk,
+};
+
+static struct snd_soc_dai_driver es8328_dai = {
+ .name = "es8328-hifi-analog",
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = ES8328_RATES,
+ .formats = ES8328_FORMATS,
+ },
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = ES8328_RATES,
+ .formats = ES8328_FORMATS,
+ },
+ .ops = &es8328_dai_ops,
+};
+
+static int es8328_suspend(struct snd_soc_codec *codec)
+{
+ return 0;
+}
+
+static int es8328_resume(struct snd_soc_codec *codec)
+{
+ es8328_init(codec);
+ return 0;
+}
+
+static int es8328_probe(struct snd_soc_codec *codec)
+{
+ int ret;
+ struct device *dev = codec->dev;
+
+ ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
+ if (ret < 0) {
+ dev_err(dev, "failed to configure cache I/O: %d\n", ret);
+ return ret;
+ }
+
+ /* power on device */
+ es8328_init(codec);
+
+ return 0;
+}
+
+static int es8328_remove(struct snd_soc_codec *codec)
+{
+ /* Power everything down and reset the cip */
+ snd_soc_write(codec, ES8328_CHIPPOWER,
+ ES8328_CHIPPOWER_DACSTM_RESET |
+ ES8328_CHIPPOWER_ADCSTM_RESET |
+ ES8328_CHIPPOWER_DACDIG_OFF |
+ ES8328_CHIPPOWER_ADCDIG_OFF |
+ ES8328_CHIPPOWER_DACVREF_OFF |
+ ES8328_CHIPPOWER_ADCVREF_OFF);
+
+ return 0;
+}
+
+static struct snd_soc_codec_driver soc_codec_dev_es8328 = {
+ .probe = es8328_probe,
+ .remove = es8328_remove,
+ .suspend = es8328_suspend,
+ .resume = es8328_resume,
+ .controls = es8328_snd_controls,
+ .num_controls = ARRAY_SIZE(es8328_snd_controls),
+ .dapm_widgets = es8328_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(es8328_dapm_widgets),
+ .dapm_routes = es8328_intercon,
+ .num_dapm_routes = ARRAY_SIZE(es8328_intercon),
+};
+
+static const struct of_device_id es8328_of_match[] = {
+ { .compatible = "everest,es8328", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, es8328_of_match);
+
+static const struct regmap_config es8328_regmap = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = ES8328_REG_MAX,
+
+ .cache_type = REGCACHE_NONE,
+};
+
+#if defined(CONFIG_SPI_MASTER)
+static int es8328_spi_probe(struct spi_device *spi)
+{
+ struct es8328_priv *es8328;
+ int ret;
+
+ es8328 = devm_kzalloc(&spi->dev, sizeof(struct es8328_priv),
+ GFP_KERNEL);
+ if (es8328 == NULL)
+ return -ENOMEM;
+
+ es8328->regmap = devm_regmap_init_spi(spi, &es8328_regmap);
+ if (IS_ERR(es8328->regmap))
+ return PTR_ERR(es8328->regmap);
+
+ spi_set_drvdata(spi, es8328);
+
+ ret = snd_soc_register_codec(&spi->dev,
+ &soc_codec_dev_es8328, &es8328_dai, 1);
+ if (ret < 0)
+ dev_err(&spi->dev, "unable to register codec: %d\n", ret);
+
+ return ret;
+}
+
+static int es8328_spi_remove(struct spi_device *spi)
+{
+ snd_soc_unregister_codec(&spi->dev);
+
+ return 0;
+}
+
+static struct spi_driver es8328_spi_driver = {
+ .driver = {
+ .name = "es8328",
+ .owner = THIS_MODULE,
+ .of_match_table = es8328_of_match,
+ },
+ .probe = es8328_spi_probe,
+ .remove = es8328_spi_remove,
+};
+#endif /* CONFIG_SPI_MASTER */
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+static int es8328_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct es8328_priv *es8328;
+ int ret;
+
+ es8328 = devm_kzalloc(&i2c->dev, sizeof(struct es8328_priv),
+ GFP_KERNEL);
+ if (es8328 == NULL)
+ return -ENOMEM;
+
+ es8328->regmap = devm_regmap_init_i2c(i2c, &es8328_regmap);
+ if (IS_ERR(es8328->regmap))
+ return PTR_ERR(es8328->regmap);
+
+ i2c_set_clientdata(i2c, es8328);
+
+ ret = snd_soc_register_codec(&i2c->dev,
+ &soc_codec_dev_es8328, &es8328_dai, 1);
+
+ return ret;
+}
+
+static int es8328_i2c_remove(struct i2c_client *client)
+{
+ snd_soc_unregister_codec(&client->dev);
+ return 0;
+}
+
+static const struct i2c_device_id es8328_i2c_id[] = {
+ { "es8328", 0x11 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, es8328_i2c_id);
+
+static struct i2c_driver es8328_i2c_driver = {
+ .driver = {
+ .name = "es8328-codec",
+ .owner = THIS_MODULE,
+ .of_match_table = es8328_of_match,
+ },
+ .probe = es8328_i2c_probe,
+ .remove = es8328_i2c_remove,
+ .id_table = es8328_i2c_id,
+};
+#endif
+
+static int __init es8328_modinit(void)
+{
+ int ret = 0;
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+ ret = i2c_add_driver(&es8328_i2c_driver);
+ if (ret != 0) {
+ pr_err("failed to register es8328 I2C driver: %d\n", ret);
+ }
+#endif
+#if defined(CONFIG_SPI_MASTER)
+ ret = spi_register_driver(&es8328_spi_driver);
+ if (ret != 0) {
+ pr_err("Failed to register es8328 SPI driver: %d\n", ret);
+ }
+#endif
+ return ret;
+}
+module_init(es8328_modinit);
+
+static void __exit es8328_exit(void)
+{
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+ i2c_del_driver(&es8328_i2c_driver);
+#endif
+#if defined(CONFIG_SPI_MASTER)
+ spi_unregister_driver(&es8328_spi_driver);
+#endif
+}
+module_exit(es8328_exit);
+
+MODULE_DESCRIPTION("ASoC ES8328 driver");
+MODULE_AUTHOR("Sean Cross <xobs-nXMMniAx+RbQT0dZR+AlfA@public.gmane.org>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/es8328.h b/sound/soc/codecs/es8328.h
new file mode 100644
index 0000000..234a6cb
--- /dev/null
+++ b/sound/soc/codecs/es8328.h
@@ -0,0 +1,240 @@
+/*
+ * es8328.h -- ES8328 ALSA SoC Audio driver
+ */
+
+#ifndef _ES8328_H
+#define _ES8328_H
+
+#define ES8328_DACLVOL 46
+#define ES8328_DACRVOL 47
+#define ES8328_DACCTL 28
+
+#define ES8328_CONTROL1 0x00
+#define ES8328_CONTROL1_VMIDSEL_OFF (0 << 0)
+#define ES8328_CONTROL1_VMIDSEL_50k (1 << 0)
+#define ES8328_CONTROL1_VMIDSEL_500k (2 << 0)
+#define ES8328_CONTROL1_VMIDSEL_5k (3 << 0)
+#define ES8328_CONTROL1_ENREF (1 << 2)
+#define ES8328_CONTROL1_SEQEN (1 << 3)
+#define ES8328_CONTROL1_SAMEFS (1 << 4)
+#define ES8328_CONTROL1_DACMCLK_ADC (0 << 5)
+#define ES8328_CONTROL1_DACMCLK_DAC (1 << 5)
+#define ES8328_CONTROL1_LRCM (1 << 6)
+#define ES8328_CONTROL1_SCP_RESET (1 << 7)
+
+#define ES8328_CONTROL2 0x01
+#define ES8328_CONTROL2_VREF_BUF_OFF (1 << 0)
+#define ES8328_CONTROL2_VREF_LOWPOWER (1 << 1)
+#define ES8328_CONTROL2_IBIASGEN_OFF (1 << 2)
+#define ES8328_CONTROL2_ANALOG_OFF (1 << 3)
+#define ES8328_CONTROL2_VREF_BUF_LOWPOWER (1 << 4)
+#define ES8328_CONTROL2_VCM_MOD_LOWPOWER (1 << 5)
+#define ES8328_CONTROL2_OVERCURRENT_ON (1 << 6)
+#define ES8328_CONTROL2_THERMAL_SHUTDOWN_ON (1 << 7)
+
+#define ES8328_CHIPPOWER 0x02
+#define ES8328_CHIPPOWER_DACVREF_OFF (1 << 0)
+#define ES8328_CHIPPOWER_ADCVREF_OFF (1 << 1)
+#define ES8328_CHIPPOWER_DACPLL_OFF (1 << 2)
+#define ES8328_CHIPPOWER_ADCPLL_OFF (1 << 3)
+#define ES8328_CHIPPOWER_DACSTM_RESET (1 << 4)
+#define ES8328_CHIPPOWER_ADCSTM_RESET (1 << 5)
+#define ES8328_CHIPPOWER_DACDIG_OFF (1 << 6)
+#define ES8328_CHIPPOWER_ADCDIG_OFF (1 << 7)
+
+#define ES8328_ADCPOWER 0x03
+#define ES8328_ADCPOWER_INT1_LOWPOWER (1 << 0)
+#define ES8328_ADCPOWER_FLASH_ADC_LOWPOWER (1 << 1)
+#define ES8328_ADCPOWER_ADC_BIAS_GEN_OFF (1 << 2)
+#define ES8328_ADCPOWER_MIC_BIAS_OFF (1 << 3)
+#define ES8328_ADCPOWER_ADCR_OFF (1 << 4)
+#define ES8328_ADCPOWER_ADCL_OFF (1 << 5)
+#define ES8328_ADCPOWER_AINR_OFF (1 << 6)
+#define ES8328_ADCPOWER_AINL_OFF (1 << 7)
+
+#define ES8328_DACPOWER 0x04
+#define ES8328_DACPOWER_OUT3_ON (1 << 0)
+#define ES8328_DACPOWER_MONO_ON (1 << 1)
+#define ES8328_DACPOWER_ROUT2_ON (1 << 2)
+#define ES8328_DACPOWER_LOUT2_ON (1 << 3)
+#define ES8328_DACPOWER_ROUT1_ON (1 << 4)
+#define ES8328_DACPOWER_LOUT1_ON (1 << 5)
+#define ES8328_DACPOWER_RDAC_OFF (1 << 6)
+#define ES8328_DACPOWER_LDAC_OFF (1 << 7)
+
+#define ES8328_CHIPLOPOW1 0x05
+#define ES8328_CHIPLOPOW2 0x06
+#define ES8328_ANAVOLMANAG 0x07
+
+#define ES8328_MASTERMODE 0x08
+#define ES8328_MASTERMODE_BCLKDIV (0 << 0)
+#define ES8328_MASTERMODE_BCLK_INV (1 << 5)
+#define ES8328_MASTERMODE_MCLKDIV2 (1 << 6)
+#define ES8328_MASTERMODE_MSC (1 << 7)
+
+#define ES8328_ADCCONTROL1 0x09
+#define ES8328_ADCCONTROL2 0x0a
+#define ES8328_ADCCONTROL3 0x0b
+#define ES8328_ADCCONTROL4 0x0c
+#define ES8328_ADCCONTROL5 0x0d
+#define ES8328_ADCCONTROL5_RATEMASK (0x1f << 0)
+
+#define ES8328_ADCCONTROL6 0x0e
+
+#define ES8328_ADCCONTROL7 0x0f
+#define ES8328_ADCCONTROL7_ADC_MUTE (1 << 2)
+#define ES8328_ADCCONTROL7_ADC_LER (1 << 3)
+#define ES8328_ADCCONTROL7_ADC_ZERO_CROSS (1 << 4)
+#define ES8328_ADCCONTROL7_ADC_SOFT_RAMP (1 << 5)
+#define ES8328_ADCCONTROL7_ADC_RAMP_RATE_4 (0 << 6)
+#define ES8328_ADCCONTROL7_ADC_RAMP_RATE_8 (1 << 6)
+#define ES8328_ADCCONTROL7_ADC_RAMP_RATE_16 (2 << 6)
+#define ES8328_ADCCONTROL7_ADC_RAMP_RATE_32 (3 << 6)
+
+#define ES8328_ADCCONTROL8 0x10
+#define ES8328_ADCCONTROL9 0x11
+#define ES8328_ADCCONTROL10 0x12
+#define ES8328_ADCCONTROL11 0x13
+#define ES8328_ADCCONTROL12 0x14
+#define ES8328_ADCCONTROL13 0x15
+#define ES8328_ADCCONTROL14 0x16
+
+#define ES8328_DACCONTROL1 0x17
+#define ES8328_DACCONTROL1_DACFORMAT_I2S (0 << 1)
+#define ES8328_DACCONTROL1_DACFORMAT_LJUST (1 << 1)
+#define ES8328_DACCONTROL1_DACFORMAT_RJUST (2 << 1)
+#define ES8328_DACCONTROL1_DACFORMAT_PCM (3 << 1)
+#define ES8328_DACCONTROL1_DACWL_24 (0 << 3)
+#define ES8328_DACCONTROL1_DACWL_20 (1 << 3)
+#define ES8328_DACCONTROL1_DACWL_18 (2 << 3)
+#define ES8328_DACCONTROL1_DACWL_16 (3 << 3)
+#define ES8328_DACCONTROL1_DACWL_32 (4 << 3)
+#define ES8328_DACCONTROL1_DACLRP_I2S_POL_NORMAL (0 << 6)
+#define ES8328_DACCONTROL1_DACLRP_I2S_POL_INV (1 << 6)
+#define ES8328_DACCONTROL1_DACLRP_PCM_MSB_CLK2 (0 << 6)
+#define ES8328_DACCONTROL1_DACLRP_PCM_MSB_CLK1 (0 << 6)
+#define ES8328_DACCONTROL1_LRSWAP (1 << 7)
+
+#define ES8328_DACCONTROL2 0x18
+#define ES8328_DACCONTROL2_RATEMASK (0x1f << 0)
+
+#define ES8328_DACCONTROL3 0x19
+#define ES8328_DACCONTROL3_AUTOMUTE (1 << 2)
+#define ES8328_DACCONTROL3_DACMUTE (1 << 2)
+#define ES8328_DACCONTROL3_LEFTGAINVOL (1 << 3)
+#define ES8328_DACCONTROL3_DACZEROCROSS (1 << 4)
+#define ES8328_DACCONTROL3_DACSOFTRAMP (1 << 5)
+#define ES8328_DACCONTROL3_DACRAMPRATE (3 << 6)
+
+#define ES8328_DACCONTROL4 0x1a
+#define ES8328_DACCONTROL5 0x1b
+
+#define ES8328_DACCONTROL6 0x1c
+#define ES8328_DACCONTROL6_CLICKFREE (1 << 3)
+#define ES8328_DACCONTROL6_DAC_INVR (1 << 4)
+#define ES8328_DACCONTROL6_DAC_INVL (1 << 5)
+#define ES8328_DACCONTROL6_DEEMPH_OFF (0 << 6)
+#define ES8328_DACCONTROL6_DEEMPH_32k (1 << 6)
+#define ES8328_DACCONTROL6_DEEMPH_44_1k (2 << 6)
+#define ES8328_DACCONTROL6_DEEMPH_48k (3 << 6)
+
+#define ES8328_DACCONTROL7 0x1d
+#define ES8328_DACCONTROL8 0x1e
+#define ES8328_DACCONTROL9 0x1f
+#define ES8328_DACCONTROL10 0x20
+#define ES8328_DACCONTROL11 0x21
+#define ES8328_DACCONTROL12 0x22
+#define ES8328_DACCONTROL13 0x23
+#define ES8328_DACCONTROL14 0x24
+#define ES8328_DACCONTROL15 0x25
+
+#define ES8328_DACCONTROL16 0x26
+#define ES8328_DACCONTROL16_RMIXSEL_RIN1 (0 << 0)
+#define ES8328_DACCONTROL16_RMIXSEL_RIN2 (1 << 0)
+#define ES8328_DACCONTROL16_RMIXSEL_RIN3 (2 << 0)
+#define ES8328_DACCONTROL16_RMIXSEL_RADC (3 << 0)
+#define ES8328_DACCONTROL16_LMIXSEL_LIN1 (0 << 3)
+#define ES8328_DACCONTROL16_LMIXSEL_LIN2 (1 << 3)
+#define ES8328_DACCONTROL16_LMIXSEL_LIN3 (2 << 3)
+#define ES8328_DACCONTROL16_LMIXSEL_LADC (3 << 3)
+
+#define ES8328_DACCONTROL17 0x27
+#define ES8328_DACCONTROL17_LI2LOVOL (7 << 3)
+#define ES8328_DACCONTROL17_LI2LO (1 << 6)
+#define ES8328_DACCONTROL17_LD2LO (1 << 7)
+
+#define ES8328_DACCONTROL18 0x28
+#define ES8328_DACCONTROL18_RI2LOVOL (7 << 3)
+#define ES8328_DACCONTROL18_RI2LO (1 << 6)
+#define ES8328_DACCONTROL18_RD2LO (1 << 7)
+
+#define ES8328_DACCONTROL19 0x29
+#define ES8328_DACCONTROL19_LI2ROVOL (7 << 3)
+#define ES8328_DACCONTROL19_LI2RO (1 << 6)
+#define ES8328_DACCONTROL19_LD2RO (1 << 7)
+
+#define ES8328_DACCONTROL20 0x2a
+#define ES8328_DACCONTROL20_RI2ROVOL (7 << 3)
+#define ES8328_DACCONTROL20_RI2RO (1 << 6)
+#define ES8328_DACCONTROL20_RD2RO (1 << 7)
+
+#define ES8328_DACCONTROL21 0x2b
+#define ES8328_DACCONTROL22 0x2c
+#define ES8328_DACCONTROL23 0x2d
+#define ES8328_DACCONTROL24 0x2e
+#define ES8328_DACCONTROL25 0x2f
+#define ES8328_DACCONTROL26 0x30
+#define ES8328_DACCONTROL27 0x31
+#define ES8328_DACCONTROL28 0x32
+#define ES8328_DACCONTROL29 0x33
+#define ES8328_DACCONTROL30 0x34
+#define ES8328_SYSCLK 0
+
+#define ES8328_REG_MAX 0x35
+
+#define ES8328_PLL1 0
+#define ES8328_PLL2 1
+
+/* clock inputs */
+#define ES8328_MCLK 0
+#define ES8328_PCMCLK 1
+
+/* clock divider id's */
+#define ES8328_PCMDIV 0
+#define ES8328_BCLKDIV 1
+#define ES8328_VXCLKDIV 2
+
+/* PCM clock dividers */
+#define ES8328_PCM_DIV_1 (0 << 6)
+#define ES8328_PCM_DIV_3 (2 << 6)
+#define ES8328_PCM_DIV_5_5 (3 << 6)
+#define ES8328_PCM_DIV_2 (4 << 6)
+#define ES8328_PCM_DIV_4 (5 << 6)
+#define ES8328_PCM_DIV_6 (6 << 6)
+#define ES8328_PCM_DIV_8 (7 << 6)
+
+/* BCLK clock dividers */
+#define ES8328_BCLK_DIV_1 (0 << 7)
+#define ES8328_BCLK_DIV_2 (1 << 7)
+#define ES8328_BCLK_DIV_4 (2 << 7)
+#define ES8328_BCLK_DIV_8 (3 << 7)
+
+/* VXCLK clock dividers */
+#define ES8328_VXCLK_DIV_1 (0 << 6)
+#define ES8328_VXCLK_DIV_2 (1 << 6)
+#define ES8328_VXCLK_DIV_4 (2 << 6)
+#define ES8328_VXCLK_DIV_8 (3 << 6)
+#define ES8328_VXCLK_DIV_16 (4 << 6)
+
+#define ES8328_DAI_HIFI 0
+#define ES8328_DAI_VOICE 1
+
+#define ES8328_1536FS 1536
+#define ES8328_1024FS 1024
+#define ES8328_768FS 768
+#define ES8328_512FS 512
+#define ES8328_384FS 384
+#define ES8328_256FS 256
+#define ES8328_128FS 128
+
+#endif
--
1.8.3.2
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 2/3] sound: soc: fsl: Add support for Novena onboard audio
[not found] ` <1391749517-11787-1-git-send-email-xobs-nXMMniAx+RbQT0dZR+AlfA@public.gmane.org>
2014-02-07 5:05 ` [PATCH 1/3] sound: soc: codecs: Add es8328 codec Sean Cross
@ 2014-02-07 5:05 ` Sean Cross
[not found] ` <1391749517-11787-3-git-send-email-xobs-nXMMniAx+RbQT0dZR+AlfA@public.gmane.org>
2014-02-07 5:05 ` [PATCH 3/3] dts: imx: add kosagi novena imx6q dts file Sean Cross
2 siblings, 1 reply; 14+ messages in thread
From: Sean Cross @ 2014-02-07 5:05 UTC (permalink / raw)
To: devicetree-u79uwXL29TY76Z2rM5mHXA,
alsa-devel-K7yf7f+aM1XWsZ/bQMPhNw
Cc: Shawn Guo, Sascha Hauer, Mark Brown, Liam Girdwood, Sean Cross
Novena uses an ES8328 audio codec connected via I2S.
---
sound/soc/fsl/Kconfig | 13 ++
sound/soc/fsl/Makefile | 2 +
sound/soc/fsl/imx-novena.c | 344 +++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 359 insertions(+)
create mode 100644 sound/soc/fsl/imx-novena.c
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index 07f8f14..88e7fbf 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -163,6 +163,19 @@ config SND_SOC_PHYCORE_AC97
Say Y if you want to add support for SoC audio on Phytec phyCORE
and phyCARD boards in AC97 mode
+config SND_SOC_IMX_NOVENA
+ tristate "SoC Audio support for i.MX6-based Novena boards"
+ depends on OF && I2C
+ select SND_SOC_ES8328
+ select SND_SOC_IMX_PCM_DMA
+ select SND_SOC_IMX_AUDMUX
+ select SND_SOC_FSL_SSI
+ select SND_SOC_FSL_UTILS
+ select SND_SOC_IMX_PCM_FIQ
+ help
+ Say Y if you want to add support for SoC audio on an i.MX board with
+ an audio codec connected via SSI/I2S.
+
config SND_SOC_EUKREA_TLV320
tristate "Eukrea TLV320"
depends on MACH_EUKREA_MBIMX27_BASEBOARD \
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile
index b12ad4b..fc89017 100644
--- a/sound/soc/fsl/Makefile
+++ b/sound/soc/fsl/Makefile
@@ -47,6 +47,7 @@ snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o
snd-soc-phycore-ac97-objs := phycore-ac97.o
snd-soc-mx27vis-aic32x4-objs := mx27vis-aic32x4.o
snd-soc-wm1133-ev1-objs := wm1133-ev1.o
+snd-soc-imx-novena-objs := imx-novena.o
snd-soc-imx-sgtl5000-objs := imx-sgtl5000.o
snd-soc-imx-wm8962-objs := imx-wm8962.o
snd-soc-imx-spdif-objs := imx-spdif.o
@@ -56,6 +57,7 @@ obj-$(CONFIG_SND_SOC_EUKREA_TLV320) += snd-soc-eukrea-tlv320.o
obj-$(CONFIG_SND_SOC_PHYCORE_AC97) += snd-soc-phycore-ac97.o
obj-$(CONFIG_SND_SOC_MX27VIS_AIC32X4) += snd-soc-mx27vis-aic32x4.o
obj-$(CONFIG_SND_MXC_SOC_WM1133_EV1) += snd-soc-wm1133-ev1.o
+obj-$(CONFIG_SND_SOC_IMX_NOVENA) += snd-soc-imx-novena.o
obj-$(CONFIG_SND_SOC_IMX_SGTL5000) += snd-soc-imx-sgtl5000.o
obj-$(CONFIG_SND_SOC_IMX_WM8962) += snd-soc-imx-wm8962.o
obj-$(CONFIG_SND_SOC_IMX_SPDIF) += snd-soc-imx-spdif.o
diff --git a/sound/soc/fsl/imx-novena.c b/sound/soc/fsl/imx-novena.c
new file mode 100644
index 0000000..6e06de9
--- /dev/null
+++ b/sound/soc/fsl/imx-novena.c
@@ -0,0 +1,344 @@
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ * Copyright 2012 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/i2c.h>
+#include <linux/clk.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <linux/clk-provider.h>
+#include <sound/soc.h>
+#include <sound/jack.h>
+
+#include "imx-audmux.h"
+
+#define DAI_NAME_SIZE 32
+#define IMX6Q_SYSCLK 0x00
+
+struct imx_novena_data {
+ struct device *dev;
+ struct snd_soc_dai_link dai;
+ struct snd_soc_card card;
+ char codec_dai_name[DAI_NAME_SIZE];
+ char platform_name[DAI_NAME_SIZE];
+ struct clk *codec_clk;
+ struct clk *codec_clk_src;
+ struct clk *codec_clk_sel;
+ struct clk *codec_clk_post_div;
+ struct clk *system_cko;
+ unsigned int clk_freq_src;
+ unsigned int clk_frequency;
+ int power_gpio;
+ int jack_gpio;
+};
+
+static struct snd_soc_jack_gpio headset_jack_gpios[] = {
+ {
+ .gpio = -1,
+ .name = "headset-gpio",
+ .report = SND_JACK_HEADSET,
+ .invert = 0,
+ .debounce_time = 200,
+ },
+};
+
+static struct snd_soc_jack headset_jack;
+
+static int imx_novena_dai_init(struct snd_soc_pcm_runtime *rtd)
+{
+ struct imx_novena_data *data = container_of(rtd->card,
+ struct imx_novena_data, card);
+ struct device *dev = rtd->card->dev;
+ int ret;
+
+ ret = snd_soc_dai_set_sysclk(rtd->codec_dai, IMX6Q_SYSCLK,
+ data->clk_frequency, SND_SOC_CLOCK_IN);
+ if (ret) {
+ dev_err(dev, "could not set codec driver clock params to %d\n",
+ data->clk_frequency);
+ return ret;
+ }
+
+ /* Headphone jack detection */
+ if (gpio_is_valid(data->jack_gpio)) {
+ ret = snd_soc_jack_new(rtd->codec, "Headset",
+ SND_JACK_HEADSET | SND_JACK_BTN_0,
+ &headset_jack);
+ if (ret)
+ return ret;
+
+ headset_jack_gpios[0].gpio = data->jack_gpio;
+ ret = snd_soc_jack_add_gpios(&headset_jack,
+ ARRAY_SIZE(headset_jack_gpios),
+ headset_jack_gpios);
+ }
+
+ return ret;
+}
+
+static const struct snd_soc_dapm_widget imx_novena_dapm_widgets[] = {
+ SND_SOC_DAPM_MIC("Mic Jack", NULL),
+ SND_SOC_DAPM_HP("Headphone Jack", NULL),
+ SND_SOC_DAPM_SPK("Ext Spk", NULL),
+};
+
+static int imx_set_frequency(struct imx_novena_data *data, int freq) {
+ int ret;
+
+ ret = clk_set_parent(data->system_cko, data->codec_clk);
+ if (ret) {
+ dev_err(data->dev, "unable to set clk output");
+ return ret;
+ }
+
+ ret = clk_set_parent(data->codec_clk_sel, data->codec_clk_post_div);
+ if (ret) {
+ dev_err(data->dev, "unable to set clk parent");
+ return ret;
+ }
+
+ data->clk_freq_src = clk_round_rate(data->codec_clk_src, freq*32);
+ data->clk_frequency = clk_round_rate(data->codec_clk, freq);
+ dev_dbg(data->dev, "clock source frequency: %d\n", data->clk_freq_src);
+ dev_dbg(data->dev, "clock frequency: %d\n", data->clk_frequency);
+
+ ret = clk_set_rate(data->codec_clk_src, data->clk_freq_src);
+ if (ret) {
+ dev_err(data->dev, "unable to set source clock rate\n");
+ return ret;
+ }
+
+ ret = clk_set_rate(data->codec_clk, data->clk_frequency);
+ if (ret) {
+ dev_err(data->dev, "unable to set codec clock rate\n");
+ return ret;
+ }
+
+ ret = clk_prepare_enable(data->codec_clk);
+ if (ret) {
+ dev_err(data->dev, "unable to prepare codec clk\n");
+ return ret;
+ }
+
+ ret = clk_prepare_enable(data->codec_clk_src);
+ if (ret) {
+ dev_err(data->dev, "unable to prepare codec clk source\n");
+ return ret;
+ }
+ return ret;
+}
+
+static int imx_novena_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct device_node *ssi_np, *codec_np;
+ struct platform_device *ssi_pdev;
+ struct i2c_client *codec_dev;
+ struct imx_novena_data *data;
+ int int_port, ext_port;
+ int ret;
+ struct device *dev = &pdev->dev;
+
+ ret = of_property_read_u32(np, "mux-int-port", &int_port);
+ if (ret) {
+ dev_err(&pdev->dev, "mux-int-port missing or invalid\n");
+ return ret;
+ }
+ ret = of_property_read_u32(np, "mux-ext-port", &ext_port);
+ if (ret) {
+ dev_err(&pdev->dev, "mux-ext-port missing or invalid\n");
+ return ret;
+ }
+
+ /*
+ * The port numbering in the hardware manual starts at 1, while
+ * the audmux API expects it starts at 0.
+ */
+ int_port--;
+ ext_port--;
+ ret = imx_audmux_v2_configure_port(int_port,
+ IMX_AUDMUX_V2_PTCR_SYN |
+ IMX_AUDMUX_V2_PTCR_TFSEL(ext_port) |
+ IMX_AUDMUX_V2_PTCR_TCSEL(ext_port) |
+ IMX_AUDMUX_V2_PTCR_TFSDIR |
+ IMX_AUDMUX_V2_PTCR_TCLKDIR,
+ IMX_AUDMUX_V2_PDCR_RXDSEL(ext_port));
+ if (ret) {
+ dev_err(&pdev->dev, "audmux internal port setup failed\n");
+ return ret;
+ }
+ ret = imx_audmux_v2_configure_port(ext_port,
+ IMX_AUDMUX_V2_PTCR_SYN,
+ IMX_AUDMUX_V2_PDCR_RXDSEL(int_port));
+ if (ret) {
+ dev_err(&pdev->dev, "audmux external port setup failed\n");
+ return ret;
+ }
+
+ ssi_np = of_parse_phandle(pdev->dev.of_node, "ssi-controller", 0);
+ codec_np = of_parse_phandle(pdev->dev.of_node, "audio-codec", 0);
+ if (!ssi_np || !codec_np) {
+ dev_err(&pdev->dev, "phandle missing or invalid\n");
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ ssi_pdev = of_find_device_by_node(ssi_np);
+ if (!ssi_pdev) {
+ dev_err(&pdev->dev, "failed to find SSI platform device\n");
+ ret = -EINVAL;
+ goto fail;
+ }
+ codec_dev = of_find_i2c_device_by_node(codec_np);
+ if (!codec_dev) {
+ dev_err(&pdev->dev, "failed to find codec platform device\n");
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+ if (!data) {
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+ data->dev = dev;
+
+ data->jack_gpio = of_get_named_gpio(pdev->dev.of_node,
+ "jack-gpio", 0);
+
+ data->power_gpio = of_get_named_gpio(pdev->dev.of_node,
+ "power-gpio", 0);
+ if (gpio_is_valid(data->power_gpio))
+ devm_gpio_request_one(&pdev->dev, data->power_gpio,
+ GPIOF_OUT_INIT_HIGH,
+ "audio codec power switch");
+
+ /* Setup clocks */
+ data->codec_clk = devm_clk_get(dev, "cko1");
+ if (IS_ERR(data->codec_clk)) {
+ dev_err(dev,
+ "codec clock missing or invalid\n");
+ goto fail;
+ }
+
+ data->codec_clk_sel = devm_clk_get(dev, "cko1_sel");
+ if (IS_ERR(data->codec_clk_sel)) {
+ dev_err(dev,
+ "codec clock select missing or invalid\n");
+ goto fail;
+ }
+
+ data->codec_clk_src = devm_clk_get(dev, "pll4_audio");
+ if (IS_ERR(data->codec_clk_src)) {
+ dev_err(dev,
+ "codec clock source missing or invalid\n");
+ goto fail;
+ }
+
+ data->codec_clk_post_div = devm_clk_get(dev, "pll4_post_div");
+ if (IS_ERR(data->codec_clk_post_div)) {
+ dev_err(dev,
+ "codec clock post-div missing or invalid\n");
+ goto fail;
+ }
+
+ data->system_cko = devm_clk_get(dev, "cko_sel");
+ if (IS_ERR(data->system_cko)) {
+ dev_err(dev,
+ "system clock missing or invalid\n");
+ goto fail;
+ }
+
+ ret = imx_set_frequency(data, 22579200);
+ if (ret)
+ goto fail;
+
+
+ data->dai.name = "hifi";
+ data->dai.stream_name = "hifi";
+ data->dai.codec_dai_name = "es8328-hifi-analog";
+ data->dai.codec_of_node = codec_np;
+ data->dai.cpu_of_node = ssi_np;
+ data->dai.platform_of_node = ssi_np;
+ data->dai.init = &imx_novena_dai_init;
+ data->dai.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBM_CFM;
+
+ data->card.dev = &pdev->dev;
+ ret = snd_soc_of_parse_card_name(&data->card, "model");
+ if (ret)
+ goto fail;
+ ret = snd_soc_of_parse_audio_routing(&data->card, "audio-routing");
+ if (ret)
+ goto fail;
+ data->card.num_links = 1;
+ data->card.owner = THIS_MODULE;
+ data->card.dai_link = &data->dai;
+ data->card.dapm_widgets = imx_novena_dapm_widgets;
+ data->card.num_dapm_widgets = ARRAY_SIZE(imx_novena_dapm_widgets);
+
+ ret = snd_soc_register_card(&data->card);
+ if (ret)
+ goto fail;
+
+ platform_set_drvdata(pdev, data);
+fail:
+ if (ssi_np)
+ of_node_put(ssi_np);
+ if (codec_np)
+ of_node_put(codec_np);
+
+ return ret;
+}
+
+static int imx_novena_remove(struct platform_device *pdev)
+{
+ struct imx_novena_data *data = platform_get_drvdata(pdev);
+
+ snd_soc_jack_free_gpios(&headset_jack, ARRAY_SIZE(headset_jack_gpios),
+ headset_jack_gpios);
+
+ if (data->codec_clk)
+ clk_disable_unprepare(data->codec_clk);
+
+ if (data->codec_clk_src)
+ clk_disable_unprepare(data->codec_clk_src);
+
+ snd_soc_unregister_card(&data->card);
+
+ return 0;
+}
+
+static const struct of_device_id imx_novena_dt_ids[] = {
+ { .compatible = "kosagi,imx-audio-novena", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, imx_novena_dt_ids);
+
+static struct platform_driver imx_novena_driver = {
+ .driver = {
+ .name = "imx-novena",
+ .owner = THIS_MODULE,
+ .of_match_table = imx_novena_dt_ids,
+ },
+ .probe = imx_novena_probe,
+ .remove = imx_novena_remove,
+};
+module_platform_driver(imx_novena_driver);
+
+MODULE_AUTHOR("Shawn Guo <shawn.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>");
+MODULE_DESCRIPTION("Kosagi i.MX6 Novena ASoC machine driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:imx-audio-novena");
--
1.8.3.2
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 3/3] dts: imx: add kosagi novena imx6q dts file
[not found] ` <1391749517-11787-1-git-send-email-xobs-nXMMniAx+RbQT0dZR+AlfA@public.gmane.org>
2014-02-07 5:05 ` [PATCH 1/3] sound: soc: codecs: Add es8328 codec Sean Cross
2014-02-07 5:05 ` [PATCH 2/3] sound: soc: fsl: Add support for Novena onboard audio Sean Cross
@ 2014-02-07 5:05 ` Sean Cross
2 siblings, 0 replies; 14+ messages in thread
From: Sean Cross @ 2014-02-07 5:05 UTC (permalink / raw)
To: devicetree-u79uwXL29TY76Z2rM5mHXA,
alsa-devel-K7yf7f+aM1XWsZ/bQMPhNw
Cc: Shawn Guo, Sascha Hauer, Mark Brown, Liam Girdwood, Sean Cross
Add a device tree file for the Novena i.MX6q-based board.
---
arch/arm/boot/dts/imx6q-novena.dts | 517 +++++++++++++++++++++++++++++++++++++
1 file changed, 517 insertions(+)
create mode 100644 arch/arm/boot/dts/imx6q-novena.dts
diff --git a/arch/arm/boot/dts/imx6q-novena.dts b/arch/arm/boot/dts/imx6q-novena.dts
new file mode 100644
index 0000000..ea95168
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-novena.dts
@@ -0,0 +1,517 @@
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+#include "imx6q.dtsi"
+
+/ {
+ model = "Kosagi Novena (i.MX6 Quad)";
+ compatible = "kosagi,imx6q-novena", "fsl,imx6q";
+
+ memory {
+ reg = <0x10000000 0x40000000>;
+ };
+
+ regulators {
+ compatible = "simple-bus";
+
+ reg_2p5v: 2p5v {
+ compatible = "regulator-fixed";
+ regulator-name = "2P5V";
+ regulator-min-microvolt = <2500000>;
+ regulator-max-microvolt = <2500000>;
+ regulator-always-on;
+ };
+
+ reg_3p3v: 3p3v {
+ compatible = "regulator-fixed";
+ regulator-name = "3P3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ reg_usb_otg_vbus: usb_otg_vbus {
+ compatible = "regulator-fixed";
+ regulator-name = "usb_otg_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ enable-active-high;
+ };
+ reg_audio_codec: es8328-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "es8328-power";
+ regulator-boot-on;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ startup-delay-us = <400000>;
+ gpio = <&gpio5 17 0>;
+ enable-active-high;
+ };
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ user-button {
+ label = "User Button";
+ gpios = <&gpio4 14 1>;
+ gpio-key,wakeup;
+ linux,code = <116>; /* KEY_POWER */
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ heartbeat {
+ label = "novena::usr0";
+ gpios = <&gpio3 19 0>;
+ linux,default-trigger = "heartbeat";
+ };
+ };
+
+ backlight {
+ compatible = "pwm-backlight";
+ pwms = <&pwm1 0 10000>;
+
+ brightness-levels = <0 3 6 12 16 24 32 48 64 96 128 192 255>;
+ default-brightness-level = <12>;
+ };
+
+ imx-drm {
+ compatible = "fsl,imx-drm";
+ crtcs = <&ipu1 0>, <&ipu1 1>;
+ connectors = <&ldb>;
+ };
+
+ sound {
+ compatible = "fsl,imx-audio-novena";
+ model = "imx-audio-novena";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sound_novena>;
+ clocks = <&clks 169>, <&clks 57>, <&clks 173>, <&clks 203>, <&clks 201>;
+ clock-names = "cko1", "cko1_sel", "pll4_audio", "pll4_post_div", "cko_sel";
+ ssi-controller = <&ssi1>;
+ audio-codec = <&codec>;
+ jack-gpio = <&gpio5 15 0>;
+ audio-routing =
+ "MIC_IN", "Mic Jack",
+ "Mic Jack", "Mic Bias",
+ "Headphone Jack", "HP_OUT",
+ "Ext Spk", "SPK_OUT";
+ mux-int-port = <1>;
+ mux-ext-port = <3>;
+ };
+};
+
+&ssi1 {
+ fsl,mode = "i2s-slave";
+ status = "okay";
+};
+
+&uart2 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart2_1>;
+};
+
+&uart3 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart3_1>;
+};
+
+&uart4 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart4_novena>;
+};
+
+&sata {
+ status = "okay";
+};
+
+&iomuxc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hog>;
+
+ hog {
+ pinctrl_hog: hoggrp {
+ fsl,pins = <
+ /* Touchscreen interrupt */
+ MX6QDL_PAD_DISP0_DAT19__GPIO5_IO13 0x80000000
+
+ /* GPIO LED */
+ MX6QDL_PAD_EIM_D19__GPIO3_IO19 0x80000000
+
+ /* FPGA power */
+ MX6QDL_PAD_SD1_DAT1__GPIO1_IO17 0x80000000
+
+ /* User button */
+ MX6QDL_PAD_SD2_DAT1__GPIO1_IO14 0x80000000
+ >;
+ };
+ };
+
+ pcie {
+ pinctrl_pcie_novena: pciegrp-novena {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x80000000 /* Wakeup */
+ MX6QDL_PAD_EIM_D29__GPIO3_IO29 0x80000000 /* Reset */
+ MX6QDL_PAD_GPIO_17__GPIO7_IO12 0x80000000 /* Power On */
+ MX6QDL_PAD_EIM_A22__GPIO2_IO16 0x80000000 /* Wifi kill */
+ >;
+ };
+ };
+
+ enet {
+ pinctrl_enet_novena: enetgrp-novena {
+ fsl,pins = <
+ MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
+ MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
+ MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b020
+ MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b028
+ MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b028
+ MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b028
+ MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b028
+ MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b028
+ MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0
+ MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0
+ MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0
+ MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0
+ MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0
+ MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0
+ MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0
+ MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8
+
+ /* Ethernet reset */
+ MX6QDL_PAD_EIM_D23__GPIO3_IO23 0x80000000
+ >;
+ };
+ };
+
+ uart4 {
+ pinctrl_uart4_novena: uart4-novena {
+ fsl,pins = <
+ MX6QDL_PAD_CSI0_DAT12__UART4_TX_DATA 0x1b0b1
+ MX6QDL_PAD_CSI0_DAT13__UART4_RX_DATA 0x1b0b1
+ >;
+ };
+ };
+
+ sound {
+ pinctrl_sound_novena: sound-novena {
+ fsl,pins = <
+ /* Audio power regulator */
+ MX6QDL_PAD_DISP0_DAT23__GPIO5_IO17 0x80000000
+
+ /* Headphone plug */
+ MX6QDL_PAD_DISP0_DAT21__GPIO5_IO15 0x80000000
+
+ MX6QDL_PAD_GPIO_0__CCM_CLKO1 0x80000000
+ >;
+ };
+ };
+
+ usdhc2 {
+ pinctrl_usdhc2_novena: usdhc2-novena {
+ fsl,pins = <
+ MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059
+ MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059
+ MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
+ MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
+ MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
+ MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059
+
+ /* Write protect */
+ MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x80000000
+
+ /* Card detect */
+ MX6QDL_PAD_GPIO_4__GPIO1_IO04 0x80000000
+ >;
+ };
+ };
+};
+
+&fec {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_enet_novena>;
+ phy-mode = "rgmii";
+ phy-reset-gpios = <&gpio3 23 0>;
+ mac-address = [00 22 C6 87 72 03];
+ rxc-skew-ps = <3000>;
+ rxdv-skew-ps = <0>;
+ txc-skew-ps = <3000>;
+ txen-skew-ps = <0>;
+ rxd0-skew-ps = <0>;
+ rxd1-skew-ps = <0>;
+ rxd2-skew-ps = <0>;
+ rxd3-skew-ps = <0>;
+ txd0-skew-ps = <3000>;
+ txd1-skew-ps = <3000>;
+ txd2-skew-ps = <3000>;
+ txd3-skew-ps = <3000>;
+};
+
+&usdhc2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc2_1>;
+ pinctrl-0 = <&pinctrl_usdhc2_novena>;
+ cd-gpios = <&gpio1 4 0>;
+ wp-gpios = <&gpio1 2 0>;
+ status = "okay";
+};
+
+&usdhc3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc3_2>;
+ non-removable;
+ status = "okay";
+};
+
+&usbotg {
+ vbus-supply = <®_usb_otg_vbus>;
+ dr_mode = "otg";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbotg_2>;
+ disable-over-current;
+ status = "okay";
+};
+
+&usbh1 {
+ status = "okay";
+};
+
+&audmux {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_audmux_2>;
+};
+
+&i2c1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c1_1>;
+ status = "okay";
+
+ stmpe610@0 {
+ compatible = "st,stmpe610";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x44>;
+ irq-over-gpio;
+ irq-gpios = <&gpio5 13 0>;
+ id = <0>;
+ blocks = <0x5>;
+ irq-trigger = <0x1>;
+
+ stmpe_adc {
+ compatible = "st,stmpe-adc";
+ };
+ stmpe_touchscreen {
+ compatible = "st,stmpe-ts";
+ ts,sample-time = <4>;
+ ts,mod-12b = <1>;
+ ts,ref-sel = <0>;
+ ts,adc-freq = <1>;
+ ts,ave-ctrl = <1>;
+ ts,touch-det-delay = <2>;
+ ts,settling = <2>;
+ ts,fraction-z = <7>;
+ ts,i-drive = <1>;
+ };
+ };
+};
+
+&i2c2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c2_1>;
+ status = "okay";
+
+ pmic: pfuze100@08 {
+ compatible = "fsl,pfuze100";
+ reg = <0x08>;
+
+ regulators {
+ sw1a_reg: sw1ab {
+ regulator-min-microvolt = <300000>;
+ regulator-max-microvolt = <1875000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <6250>;
+ };
+
+ sw1c_reg: sw1c {
+ regulator-min-microvolt = <300000>;
+ regulator-max-microvolt = <1875000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sw2_reg: sw2 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sw3a_reg: sw3a {
+ regulator-min-microvolt = <400000>;
+ regulator-max-microvolt = <1975000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sw3b_reg: sw3b {
+ regulator-min-microvolt = <400000>;
+ regulator-max-microvolt = <1975000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sw4_reg: sw4 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ swbst_reg: swbst {
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5150000>;
+ };
+
+ snvs_reg: vsnvs {
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ vref_reg: vrefddr {
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ vgen1_reg: vgen1 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1550000>;
+ };
+
+ vgen2_reg: vgen2 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1550000>;
+ };
+
+ vgen3_reg: vgen3 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ vgen4_reg: vgen4 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vgen5_reg: vgen5 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vgen6_reg: vgen6 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ coin_reg: coin {
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+ };
+ };
+};
+
+&i2c3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c3_1>;
+ status = "okay";
+
+ codec: es8328@11 {
+ compatible = "everest,es8328";
+ reg = <0x11>;
+ status = "disabled";
+ };
+
+ stdp4028@73 {
+ compatible = "st,stdp4028";
+ power-switch = <&gpio5 28 0>;
+ reg = <0x73>;
+ status = "disabled";
+ };
+
+ /*
+ eepromoops@56 {
+ compatible = "kosagi,eepromoops";
+ reg = <0x56>;
+ status = "okay";
+ };
+ */
+};
+
+&ecspi3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ecspi3_1>;
+ fsl,spi-num-chipselects = <3>;
+ status = "okay";
+
+ spidev@0x00 {
+ compatible = "spidev";
+ spi-max-frequency = <30000000>;
+ reg = <0>;
+ };
+};
+
+&pcie {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pcie_novena>;
+ reset-gpio = <&gpio3 29 0>;
+ power-on-gpio = <&gpio7 12 0>;
+ wake-up-gpio = <&gpio3 22 0>;
+ disable-gpio = <&gpio2 16 0>;
+};
+
+&ldb {
+ fsl,dual-channel;
+ status = "disabled";
+ lvds-channel@0 {
+ fsl,data-mapping = "jeida";
+ fsl,data-width = <24>;
+ crtcs = <&ipu2 0>, <&ipu2 1>;
+ display-timings {
+ 2560x1700p50 {
+ clock-frequency = <185000000>;
+ hactive = <2560>;
+ vactive = <1700>;
+ hback-porch = <80>;
+ hfront-porch = <48>;
+ hsync-len = <32>;
+ vback-porch = <36>;
+ vfront-porch = <3>;
+ vsync-len = <10>;
+ hsync-active = <1>;
+ vsync-active = <1>;
+ };
+ };
+ };
+};
--
1.8.3.2
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 14+ messages in thread