Skip to content

Commit

Permalink
Merge remote-tracking branches 'asoc/topic/max98925', 'asoc/topic/max…
Browse files Browse the repository at this point in the history
…98927', 'asoc/topic/msm8916' and 'asoc/topic/omap' into asoc-next
  • Loading branch information
broonie committed Nov 10, 2017
5 parents c9e38f3 + d6e18b8 + d4a8bce + 79f01fe + 94a6a8e commit 5b04644
Show file tree
Hide file tree
Showing 5 changed files with 204 additions and 96 deletions.
23 changes: 13 additions & 10 deletions sound/soc/codecs/max98925.c
Original file line number Diff line number Diff line change
Expand Up @@ -579,7 +579,7 @@ static int max98925_i2c_probe(struct i2c_client *i2c,
ret = PTR_ERR(max98925->regmap);
dev_err(&i2c->dev,
"Failed to allocate regmap: %d\n", ret);
goto err_out;
return ret;
}

if (!of_property_read_u32(i2c->dev.of_node, "vmon-slot-no", &value)) {
Expand All @@ -596,24 +596,27 @@ static int max98925_i2c_probe(struct i2c_client *i2c,
}
max98925->i_slot = value;
}
ret = regmap_read(max98925->regmap,
MAX98925_REV_VERSION, &reg);
if ((ret < 0) ||
((reg != MAX98925_VERSION) &&
(reg != MAX98925_VERSION1))) {
dev_err(&i2c->dev,
"device initialization error (%d 0x%02X)\n",

ret = regmap_read(max98925->regmap, MAX98925_REV_VERSION, &reg);
if (ret < 0) {
dev_err(&i2c->dev, "Read revision failed\n");
return ret;
}

if ((reg != MAX98925_VERSION) && (reg != MAX98925_VERSION1)) {
ret = -ENODEV;
dev_err(&i2c->dev, "Invalid revision (%d 0x%02X)\n",
ret, reg);
goto err_out;
return ret;
}

dev_info(&i2c->dev, "device version 0x%02X\n", reg);

ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_max98925,
max98925_dai, ARRAY_SIZE(max98925_dai));
if (ret < 0)
dev_err(&i2c->dev,
"Failed to register codec: %d\n", ret);
err_out:
return ret;
}

Expand Down
155 changes: 124 additions & 31 deletions sound/soc/codecs/max98927.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* max98927.c -- MAX98927 ALSA Soc Audio driver
*
* Copyright (C) 2016 Maxim Integrated Products
* Copyright (C) 2016-2017 Maxim Integrated Products
* Author: Ryan Lee <[email protected]>
*
* This program is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -146,6 +146,7 @@ static int max98927_dai_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec);
unsigned int mode = 0;
unsigned int format = 0;
bool use_pdm = false;
unsigned int invert = 0;

dev_dbg(codec->dev, "%s: fmt 0x%08X\n", __func__, fmt);
Expand Down Expand Up @@ -187,22 +188,27 @@ static int max98927_dai_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
/* interface format */
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_I2S:
max98927->iface |= SND_SOC_DAIFMT_I2S;
format = MAX98927_PCM_FORMAT_I2S;
break;
case SND_SOC_DAIFMT_LEFT_J:
max98927->iface |= SND_SOC_DAIFMT_LEFT_J;
format = MAX98927_PCM_FORMAT_LJ;
break;
case SND_SOC_DAIFMT_DSP_A:
format = MAX98927_PCM_FORMAT_TDM_MODE1;
break;
case SND_SOC_DAIFMT_DSP_B:
format = MAX98927_PCM_FORMAT_TDM_MODE0;
break;
case SND_SOC_DAIFMT_PDM:
max98927->iface |= SND_SOC_DAIFMT_PDM;
use_pdm = true;
break;
default:
return -EINVAL;
}
max98927->iface = fmt & SND_SOC_DAIFMT_FORMAT_MASK;

/* pcm channel configuration */
if (max98927->iface & (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_LEFT_J)) {
if (!use_pdm) {
/* pcm channel configuration */
regmap_update_bits(max98927->regmap,
MAX98927_R0018_PCM_RX_EN_A,
MAX98927_PCM_RX_CH0_EN | MAX98927_PCM_RX_CH1_EN,
Expand All @@ -217,24 +223,23 @@ static int max98927_dai_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
MAX98927_R003B_SPK_SRC_SEL,
MAX98927_SPK_SRC_MASK, 0);

} else
regmap_update_bits(max98927->regmap,
MAX98927_R0018_PCM_RX_EN_A,
MAX98927_PCM_RX_CH0_EN | MAX98927_PCM_RX_CH1_EN, 0);

/* pdm channel configuration */
if (max98927->iface & SND_SOC_DAIFMT_PDM) {
MAX98927_R0035_PDM_RX_CTRL,
MAX98927_PDM_RX_EN_MASK, 0);
} else {
/* pdm channel configuration */
regmap_update_bits(max98927->regmap,
MAX98927_R0035_PDM_RX_CTRL,
MAX98927_PDM_RX_EN_MASK, 1);

regmap_update_bits(max98927->regmap,
MAX98927_R003B_SPK_SRC_SEL,
MAX98927_SPK_SRC_MASK, 3);
} else

regmap_update_bits(max98927->regmap,
MAX98927_R0035_PDM_RX_CTRL,
MAX98927_PDM_RX_EN_MASK, 0);
MAX98927_R0018_PCM_RX_EN_A,
MAX98927_PCM_RX_CH0_EN | MAX98927_PCM_RX_CH1_EN, 0);
}
return 0;
}

Expand All @@ -245,6 +250,21 @@ static const int rate_table[] = {
13000000, 19200000,
};

/* BCLKs per LRCLK */
static const int bclk_sel_table[] = {
32, 48, 64, 96, 128, 192, 256, 384, 512,
};

static int max98927_get_bclk_sel(int bclk)
{
int i;
/* match BCLKs per LRCLK */
for (i = 0; i < ARRAY_SIZE(bclk_sel_table); i++) {
if (bclk_sel_table[i] == bclk)
return i + 2;
}
return 0;
}
static int max98927_set_clock(struct max98927_priv *max98927,
struct snd_pcm_hw_params *params)
{
Expand All @@ -270,23 +290,20 @@ static int max98927_set_clock(struct max98927_priv *max98927,
i << MAX98927_PCM_MASTER_MODE_MCLK_RATE_SHIFT);
}

switch (blr_clk_ratio) {
case 32:
value = 2;
break;
case 48:
value = 3;
break;
case 64:
value = 4;
break;
default:
return -EINVAL;
if (!max98927->tdm_mode) {
/* BCLK configuration */
value = max98927_get_bclk_sel(blr_clk_ratio);
if (!value) {
dev_err(codec->dev, "format unsupported %d\n",
params_format(params));
return -EINVAL;
}

regmap_update_bits(max98927->regmap,
MAX98927_R0022_PCM_CLK_SETUP,
MAX98927_PCM_CLK_SETUP_BSEL_MASK,
value);
}
regmap_update_bits(max98927->regmap,
MAX98927_R0022_PCM_CLK_SETUP,
MAX98927_PCM_CLK_SETUP_BSEL_MASK,
value);
return 0;
}

Expand Down Expand Up @@ -386,6 +403,78 @@ static int max98927_dai_hw_params(struct snd_pcm_substream *substream,
return -EINVAL;
}

static int max98927_dai_tdm_slot(struct snd_soc_dai *dai,
unsigned int tx_mask, unsigned int rx_mask,
int slots, int slot_width)
{
struct snd_soc_codec *codec = dai->codec;
struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec);
int bsel = 0;
unsigned int chan_sz = 0;

max98927->tdm_mode = true;

/* BCLK configuration */
bsel = max98927_get_bclk_sel(slots * slot_width);
if (bsel == 0) {
dev_err(codec->dev, "BCLK %d not supported\n",
slots * slot_width);
return -EINVAL;
}

regmap_update_bits(max98927->regmap,
MAX98927_R0022_PCM_CLK_SETUP,
MAX98927_PCM_CLK_SETUP_BSEL_MASK,
bsel);

/* Channel size configuration */
switch (slot_width) {
case 16:
chan_sz = MAX98927_PCM_MODE_CFG_CHANSZ_16;
break;
case 24:
chan_sz = MAX98927_PCM_MODE_CFG_CHANSZ_24;
break;
case 32:
chan_sz = MAX98927_PCM_MODE_CFG_CHANSZ_32;
break;
default:
dev_err(codec->dev, "format unsupported %d\n",
slot_width);
return -EINVAL;
}

regmap_update_bits(max98927->regmap,
MAX98927_R0020_PCM_MODE_CFG,
MAX98927_PCM_MODE_CFG_CHANSZ_MASK, chan_sz);

/* Rx slot configuration */
regmap_write(max98927->regmap,
MAX98927_R0018_PCM_RX_EN_A,
rx_mask & 0xFF);
regmap_write(max98927->regmap,
MAX98927_R0019_PCM_RX_EN_B,
(rx_mask & 0xFF00) >> 8);

/* Tx slot configuration */
regmap_write(max98927->regmap,
MAX98927_R001A_PCM_TX_EN_A,
tx_mask & 0xFF);
regmap_write(max98927->regmap,
MAX98927_R001B_PCM_TX_EN_B,
(tx_mask & 0xFF00) >> 8);

/* Tx slot Hi-Z configuration */
regmap_write(max98927->regmap,
MAX98927_R001C_PCM_TX_HIZ_CTRL_A,
~tx_mask & 0xFF);
regmap_write(max98927->regmap,
MAX98927_R001D_PCM_TX_HIZ_CTRL_B,
(~tx_mask & 0xFF00) >> 8);

return 0;
}

#define MAX98927_RATES SNDRV_PCM_RATE_8000_48000

#define MAX98927_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
Expand All @@ -405,6 +494,7 @@ static const struct snd_soc_dai_ops max98927_dai_ops = {
.set_sysclk = max98927_dai_set_sysclk,
.set_fmt = max98927_dai_set_fmt,
.hw_params = max98927_dai_hw_params,
.set_tdm_slot = max98927_dai_tdm_slot,
};

static int max98927_dac_event(struct snd_soc_dapm_widget *w,
Expand All @@ -414,6 +504,9 @@ static int max98927_dac_event(struct snd_soc_dapm_widget *w,
struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec);

switch (event) {
case SND_SOC_DAPM_PRE_PMU:
max98927->tdm_mode = 0;
break;
case SND_SOC_DAPM_POST_PMU:
regmap_update_bits(max98927->regmap,
MAX98927_R003A_AMP_EN,
Expand Down
7 changes: 5 additions & 2 deletions sound/soc/codecs/max98927.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* max98927.h -- MAX98927 ALSA Soc Audio driver
*
* Copyright 2013-15 Maxim Integrated Products
* Copyright (C) 2016-2017 Maxim Integrated Products
* Author: Ryan Lee <[email protected]>
*
* This program is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -161,7 +161,9 @@
#define MAX98927_PCM_MODE_CFG_FORMAT_SHIFT (3)
#define MAX98927_PCM_FORMAT_I2S (0x0 << 0)
#define MAX98927_PCM_FORMAT_LJ (0x1 << 0)

#define MAX98927_PCM_FORMAT_TDM_MODE0 (0x3 << 0)
#define MAX98927_PCM_FORMAT_TDM_MODE1 (0x4 << 0)
#define MAX98927_PCM_FORMAT_TDM_MODE2 (0x5 << 0)
#define MAX98927_PCM_MODE_CFG_CHANSZ_MASK (0x3 << 6)
#define MAX98927_PCM_MODE_CFG_CHANSZ_16 (0x1 << 6)
#define MAX98927_PCM_MODE_CFG_CHANSZ_24 (0x2 << 6)
Expand Down Expand Up @@ -268,5 +270,6 @@ struct max98927_priv {
unsigned int iface;
unsigned int master;
unsigned int digital_gain;
bool tdm_mode;
};
#endif
Loading

0 comments on commit 5b04644

Please sign in to comment.