summaryrefslogtreecommitdiffstats
path: root/sound/soc/ti
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/ti')
-rw-r--r--sound/soc/ti/Kconfig4
-rw-r--r--sound/soc/ti/davinci-evm.c2
-rw-r--r--sound/soc/ti/davinci-i2s.c8
-rw-r--r--sound/soc/ti/davinci-mcasp.c185
-rw-r--r--sound/soc/ti/edma-pcm.c17
-rw-r--r--sound/soc/ti/n810.c1
-rw-r--r--sound/soc/ti/rx51.c15
7 files changed, 151 insertions, 81 deletions
diff --git a/sound/soc/ti/Kconfig b/sound/soc/ti/Kconfig
index 2197f3e1eaed..87a9b9dd4e98 100644
--- a/sound/soc/ti/Kconfig
+++ b/sound/soc/ti/Kconfig
@@ -12,7 +12,7 @@ config SND_SOC_TI_SDMA_PCM
comment "Texas Instruments DAI support for:"
config SND_SOC_DAVINCI_ASP
- tristate "daVinci Audio Serial Port (ASP) or McBSP suport"
+ tristate "daVinci Audio Serial Port (ASP) or McBSP support"
depends on ARCH_DAVINCI || COMPILE_TEST
select SND_SOC_TI_EDMA_PCM
help
@@ -33,7 +33,7 @@ config SND_SOC_DAVINCI_MCASP
- Keystone devices
config SND_SOC_DAVINCI_VCIF
- tristate "daVinci Voice Interface (VCIF) suport"
+ tristate "daVinci Voice Interface (VCIF) support"
depends on ARCH_DAVINCI || COMPILE_TEST
select SND_SOC_TI_EDMA_PCM
help
diff --git a/sound/soc/ti/davinci-evm.c b/sound/soc/ti/davinci-evm.c
index bfd8d1a03ba7..686b23d7a90d 100644
--- a/sound/soc/ti/davinci-evm.c
+++ b/sound/soc/ti/davinci-evm.c
@@ -68,7 +68,7 @@ static int evm_hw_params(struct snd_pcm_substream *substream,
/* set the CPU system clock */
ret = snd_soc_dai_set_sysclk(cpu_dai, 0, sysclk, SND_SOC_CLOCK_OUT);
- if (ret < 0)
+ if (ret < 0 && ret != -ENOTSUPP)
return ret;
return 0;
diff --git a/sound/soc/ti/davinci-i2s.c b/sound/soc/ti/davinci-i2s.c
index 27afdbb9adf3..d89b5c928c4d 100644
--- a/sound/soc/ti/davinci-i2s.c
+++ b/sound/soc/ti/davinci-i2s.c
@@ -598,6 +598,8 @@ static void davinci_i2s_shutdown(struct snd_pcm_substream *substream,
}
#define DAVINCI_I2S_RATES SNDRV_PCM_RATE_8000_96000
+#define DAVINCI_I2S_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_S32_LE)
static const struct snd_soc_dai_ops davinci_i2s_dai_ops = {
.shutdown = davinci_i2s_shutdown,
@@ -625,12 +627,14 @@ static struct snd_soc_dai_driver davinci_i2s_dai = {
.channels_min = 2,
.channels_max = 2,
.rates = DAVINCI_I2S_RATES,
- .formats = SNDRV_PCM_FMTBIT_S16_LE,},
+ .formats = DAVINCI_I2S_FORMATS,
+ },
.capture = {
.channels_min = 2,
.channels_max = 2,
.rates = DAVINCI_I2S_RATES,
- .formats = SNDRV_PCM_FMTBIT_S16_LE,},
+ .formats = DAVINCI_I2S_FORMATS,
+ },
.ops = &davinci_i2s_dai_ops,
};
diff --git a/sound/soc/ti/davinci-mcasp.c b/sound/soc/ti/davinci-mcasp.c
index bc7bf15ed7a4..7aa3c32e4a49 100644
--- a/sound/soc/ti/davinci-mcasp.c
+++ b/sound/soc/ti/davinci-mcasp.c
@@ -109,6 +109,8 @@ struct davinci_mcasp {
/* Used for comstraint setting on the second stream */
u32 channels;
+ int max_format_width;
+ u8 active_serializers[2];
#ifdef CONFIG_GPIOLIB
struct gpio_chip gpio_chip;
@@ -466,6 +468,7 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
/* FS need to be inverted */
inv_fs = true;
break;
+ case SND_SOC_DAIFMT_RIGHT_J:
case SND_SOC_DAIFMT_LEFT_J:
/* configure a full-word SYNC pulse (LRCLK) */
mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG, FSXDUR);
@@ -759,34 +762,30 @@ static int davinci_config_channel_size(struct davinci_mcasp *mcasp,
int sample_width)
{
u32 fmt;
- u32 tx_rotate = (sample_width / 4) & 0x7;
+ u32 tx_rotate, rx_rotate, slot_width;
u32 mask = (1ULL << sample_width) - 1;
- u32 slot_width = sample_width;
-
- /*
- * For captured data we should not rotate, inversion and masking is
- * enoguh to get the data to the right position:
- * Format data from bus after reverse (XRBUF)
- * S16_LE: |LSB|MSB|xxx|xxx| |xxx|xxx|MSB|LSB|
- * S24_3LE: |LSB|DAT|MSB|xxx| |xxx|MSB|DAT|LSB|
- * S24_LE: |LSB|DAT|MSB|xxx| |xxx|MSB|DAT|LSB|
- * S32_LE: |LSB|DAT|DAT|MSB| |MSB|DAT|DAT|LSB|
- */
- u32 rx_rotate = 0;
+ if (mcasp->slot_width)
+ slot_width = mcasp->slot_width;
+ else if (mcasp->max_format_width)
+ slot_width = mcasp->max_format_width;
+ else
+ slot_width = sample_width;
/*
- * Setting the tdm slot width either with set_clkdiv() or
- * set_tdm_slot() allows us to for example send 32 bits per
- * channel to the codec, while only 16 of them carry audio
- * payload.
+ * TX rotation:
+ * right aligned formats: rotate w/ slot_width
+ * left aligned formats: rotate w/ sample_width
+ *
+ * RX rotation:
+ * right aligned formats: no rotation needed
+ * left aligned formats: rotate w/ (slot_width - sample_width)
*/
- if (mcasp->slot_width) {
- /*
- * When we have more bclk then it is needed for the
- * data, we need to use the rotation to move the
- * received samples to have correct alignment.
- */
- slot_width = mcasp->slot_width;
+ if ((mcasp->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) ==
+ SND_SOC_DAIFMT_RIGHT_J) {
+ tx_rotate = (slot_width / 4) & 0x7;
+ rx_rotate = 0;
+ } else {
+ tx_rotate = (sample_width / 4) & 0x7;
rx_rotate = (slot_width - sample_width) / 4;
}
@@ -819,6 +818,7 @@ static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream,
u8 rx_ser = 0;
u8 slots = mcasp->tdm_slots;
u8 max_active_serializers = (channels + slots - 1) / slots;
+ u8 max_rx_serializers, max_tx_serializers;
int active_serializers, numevt;
u32 reg;
/* Default configuration */
@@ -828,22 +828,28 @@ static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream,
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
mcasp_set_reg(mcasp, DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF);
mcasp_clr_bits(mcasp, DAVINCI_MCASP_XEVTCTL_REG, TXDATADMADIS);
+ max_tx_serializers = max_active_serializers;
+ max_rx_serializers =
+ mcasp->active_serializers[SNDRV_PCM_STREAM_CAPTURE];
} else {
mcasp_set_reg(mcasp, DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF);
mcasp_clr_bits(mcasp, DAVINCI_MCASP_REVTCTL_REG, RXDATADMADIS);
+ max_tx_serializers =
+ mcasp->active_serializers[SNDRV_PCM_STREAM_PLAYBACK];
+ max_rx_serializers = max_active_serializers;
}
for (i = 0; i < mcasp->num_serializer; i++) {
mcasp_set_bits(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i),
mcasp->serial_dir[i]);
if (mcasp->serial_dir[i] == TX_MODE &&
- tx_ser < max_active_serializers) {
+ tx_ser < max_tx_serializers) {
mcasp_mod_bits(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i),
mcasp->dismod, DISMOD_MASK);
set_bit(PIN_BIT_AXR(i), &mcasp->pdir);
tx_ser++;
} else if (mcasp->serial_dir[i] == RX_MODE &&
- rx_ser < max_active_serializers) {
+ rx_ser < max_rx_serializers) {
clear_bit(PIN_BIT_AXR(i), &mcasp->pdir);
rx_ser++;
} else {
@@ -890,7 +896,8 @@ static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream,
} else {
dma_data->maxburst = 0;
}
- return 0;
+
+ goto out;
}
if (period_words % active_serializers) {
@@ -920,6 +927,9 @@ static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream,
numevt = 0;
dma_data->maxburst = numevt;
+out:
+ mcasp->active_serializers[stream] = active_serializers;
+
return 0;
}
@@ -1159,6 +1169,37 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
int period_size = params_period_size(params);
int ret;
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_U8:
+ case SNDRV_PCM_FORMAT_S8:
+ word_length = 8;
+ break;
+
+ case SNDRV_PCM_FORMAT_U16_LE:
+ case SNDRV_PCM_FORMAT_S16_LE:
+ word_length = 16;
+ break;
+
+ case SNDRV_PCM_FORMAT_U24_3LE:
+ case SNDRV_PCM_FORMAT_S24_3LE:
+ word_length = 24;
+ break;
+
+ case SNDRV_PCM_FORMAT_U24_LE:
+ case SNDRV_PCM_FORMAT_S24_LE:
+ word_length = 24;
+ break;
+
+ case SNDRV_PCM_FORMAT_U32_LE:
+ case SNDRV_PCM_FORMAT_S32_LE:
+ word_length = 32;
+ break;
+
+ default:
+ printk(KERN_WARNING "davinci-mcasp: unsupported PCM format");
+ return -EINVAL;
+ }
+
ret = davinci_mcasp_set_dai_fmt(cpu_dai, mcasp->dai_fmt);
if (ret)
return ret;
@@ -1193,41 +1234,13 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
if (ret)
return ret;
- switch (params_format(params)) {
- case SNDRV_PCM_FORMAT_U8:
- case SNDRV_PCM_FORMAT_S8:
- word_length = 8;
- break;
-
- case SNDRV_PCM_FORMAT_U16_LE:
- case SNDRV_PCM_FORMAT_S16_LE:
- word_length = 16;
- break;
-
- case SNDRV_PCM_FORMAT_U24_3LE:
- case SNDRV_PCM_FORMAT_S24_3LE:
- word_length = 24;
- break;
-
- case SNDRV_PCM_FORMAT_U24_LE:
- case SNDRV_PCM_FORMAT_S24_LE:
- word_length = 24;
- break;
-
- case SNDRV_PCM_FORMAT_U32_LE:
- case SNDRV_PCM_FORMAT_S32_LE:
- word_length = 32;
- break;
-
- default:
- printk(KERN_WARNING "davinci-mcasp: unsupported PCM format");
- return -EINVAL;
- }
-
davinci_config_channel_size(mcasp, word_length);
- if (mcasp->op_mode == DAVINCI_MCASP_IIS_MODE)
+ if (mcasp->op_mode == DAVINCI_MCASP_IIS_MODE) {
mcasp->channels = channels;
+ if (!mcasp->max_format_width)
+ mcasp->max_format_width = word_length;
+ }
return 0;
}
@@ -1279,6 +1292,28 @@ static int davinci_mcasp_hw_rule_slot_width(struct snd_pcm_hw_params *params,
return snd_mask_refine(fmt, &nfmt);
}
+static int davinci_mcasp_hw_rule_format_width(struct snd_pcm_hw_params *params,
+ struct snd_pcm_hw_rule *rule)
+{
+ struct davinci_mcasp_ruledata *rd = rule->private;
+ struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
+ struct snd_mask nfmt;
+ int i, format_width;
+
+ snd_mask_none(&nfmt);
+ format_width = rd->mcasp->max_format_width;
+
+ for (i = 0; i <= SNDRV_PCM_FORMAT_LAST; i++) {
+ if (snd_mask_test(fmt, i)) {
+ if (snd_pcm_format_width(i) == format_width) {
+ snd_mask_set(&nfmt, i);
+ }
+ }
+ }
+
+ return snd_mask_refine(fmt, &nfmt);
+}
+
static const unsigned int davinci_mcasp_dai_rates[] = {
8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000,
88200, 96000, 176400, 192000,
@@ -1433,12 +1468,13 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream,
max_channels *= tdm_slots;
/*
* If the already active stream has less channels than the calculated
- * limnit based on the seirializers * tdm_slots, we need to use that as
- * a constraint for the second stream.
- * Otherwise (first stream or less allowed channels) we use the
- * calculated constraint.
+ * limit based on the seirializers * tdm_slots, and only one serializer
+ * is in use we need to use that as a constraint for the second stream.
+ * Otherwise (first stream or less allowed channels or more than one
+ * serializer in use) we use the calculated constraint.
*/
- if (mcasp->channels && mcasp->channels < max_channels)
+ if (mcasp->channels && mcasp->channels < max_channels &&
+ ruledata->serializers == 1)
max_channels = mcasp->channels;
/*
* But we can always allow channels upto the amount of
@@ -1455,7 +1491,20 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream,
0, SNDRV_PCM_HW_PARAM_CHANNELS,
&mcasp->chconstr[substream->stream]);
- if (mcasp->slot_width) {
+ if (mcasp->max_format_width) {
+ /*
+ * Only allow formats which require same amount of bits on the
+ * bus as the currently running stream
+ */
+ ret = snd_pcm_hw_rule_add(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_FORMAT,
+ davinci_mcasp_hw_rule_format_width,
+ ruledata,
+ SNDRV_PCM_HW_PARAM_FORMAT, -1);
+ if (ret)
+ return ret;
+ }
+ else if (mcasp->slot_width) {
/* Only allow formats require <= slot_width bits on the bus */
ret = snd_pcm_hw_rule_add(substream->runtime, 0,
SNDRV_PCM_HW_PARAM_FORMAT,
@@ -1501,12 +1550,15 @@ static void davinci_mcasp_shutdown(struct snd_pcm_substream *substream,
struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai);
mcasp->substreams[substream->stream] = NULL;
+ mcasp->active_serializers[substream->stream] = 0;
if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE)
return;
- if (!cpu_dai->active)
+ if (!cpu_dai->active) {
mcasp->channels = 0;
+ mcasp->max_format_width = 0;
+ }
}
static const struct snd_soc_dai_ops davinci_mcasp_dai_ops = {
@@ -1562,7 +1614,6 @@ static struct snd_soc_dai_driver davinci_mcasp_dai[] = {
},
.ops = &davinci_mcasp_dai_ops,
- .symmetric_samplebits = 1,
.symmetric_rates = 1,
},
{
diff --git a/sound/soc/ti/edma-pcm.c b/sound/soc/ti/edma-pcm.c
index 3ebea1bd15cb..634b040b65f0 100644
--- a/sound/soc/ti/edma-pcm.c
+++ b/sound/soc/ti/edma-pcm.c
@@ -39,7 +39,22 @@ static const struct snd_dmaengine_pcm_config edma_dmaengine_pcm_config = {
int edma_pcm_platform_register(struct device *dev)
{
- return devm_snd_dmaengine_pcm_register(dev, &edma_dmaengine_pcm_config, 0);
+ struct snd_dmaengine_pcm_config *config;
+
+ if (dev->of_node)
+ return devm_snd_dmaengine_pcm_register(dev,
+ &edma_dmaengine_pcm_config, 0);
+
+ config = devm_kzalloc(dev, sizeof(*config), GFP_KERNEL);
+ if (!config)
+ return -ENOMEM;
+
+ *config = edma_dmaengine_pcm_config;
+
+ config->chan_names[0] = "tx";
+ config->chan_names[1] = "rx";
+
+ return devm_snd_dmaengine_pcm_register(dev, config, 0);
}
EXPORT_SYMBOL_GPL(edma_pcm_platform_register);
diff --git a/sound/soc/ti/n810.c b/sound/soc/ti/n810.c
index 2c3f2a4c1700..3ad2b6daf31e 100644
--- a/sound/soc/ti/n810.c
+++ b/sound/soc/ti/n810.c
@@ -46,6 +46,7 @@ static void n810_ext_control(struct snd_soc_dapm_context *dapm)
switch (n810_jack_func) {
case N810_JACK_HS:
line1l = 1;
+ /* fall through */
case N810_JACK_HP:
hp = 1;
break;
diff --git a/sound/soc/ti/rx51.c b/sound/soc/ti/rx51.c
index bc6046534fa5..588f680a9c24 100644
--- a/sound/soc/ti/rx51.c
+++ b/sound/soc/ti/rx51.c
@@ -55,6 +55,7 @@ static void rx51_ext_control(struct snd_soc_dapm_context *dapm)
break;
case RX51_JACK_HS:
hs = 1;
+ /* fall through */
case RX51_JACK_HP:
hp = 1;
break;
@@ -318,12 +319,10 @@ static struct snd_soc_dai_link rx51_dai[] = {
static struct snd_soc_aux_dev rx51_aux_dev[] = {
{
- .name = "TLV320AIC34b",
- .codec_name = "tlv320aic3x-codec.2-0019",
+ .dlc = COMP_AUX("tlv320aic3x-codec.2-0019"),
},
{
- .name = "TPA61320A2",
- .codec_name = "tpa6130a2.2-0060",
+ .dlc = COMP_AUX("tpa6130a2.2-0060"),
},
};
@@ -396,8 +395,8 @@ static int rx51_soc_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "Auxiliary Codec node is not provided\n");
return -EINVAL;
}
- rx51_aux_dev[0].codec_name = NULL;
- rx51_aux_dev[0].codec_of_node = dai_node;
+ rx51_aux_dev[0].dlc.name = NULL;
+ rx51_aux_dev[0].dlc.of_node = dai_node;
rx51_codec_conf[0].dev_name = NULL;
rx51_codec_conf[0].of_node = dai_node;
@@ -406,8 +405,8 @@ static int rx51_soc_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "Headphone amplifier node is not provided\n");
return -EINVAL;
}
- rx51_aux_dev[1].codec_name = NULL;
- rx51_aux_dev[1].codec_of_node = dai_node;
+ rx51_aux_dev[1].dlc.name = NULL;
+ rx51_aux_dev[1].dlc.of_node = dai_node;
rx51_codec_conf[1].dev_name = NULL;
rx51_codec_conf[1].of_node = dai_node;
}