brintos

brintos / linux-shallow public Read only

0
0
Text · 26.6 KiB · d682b98 Raw
935 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * ALSA SoC I2S (McBSP) Audio Layer for TI DAVINCI processor4 *5 * Author:      Vladimir Barinov, <vbarinov@embeddedalley.com>6 * Copyright:   (C) 2007 MontaVista Software, Inc., <source@mvista.com>7 *8 * DT support	(c) 2016 Petr Kulhavy, Barix AG <petr@barix.com>9 *		based on davinci-mcasp.c DT support10 *11 * TODO:12 * on DA850 implement HW FIFOs instead of DMA into DXR and DRR registers13 */14 15#include <linux/init.h>16#include <linux/module.h>17#include <linux/device.h>18#include <linux/slab.h>19#include <linux/delay.h>20#include <linux/io.h>21#include <linux/clk.h>22 23#include <sound/core.h>24#include <sound/pcm.h>25#include <sound/pcm_params.h>26#include <sound/initval.h>27#include <sound/soc.h>28#include <sound/dmaengine_pcm.h>29 30#include "edma-pcm.h"31#include "davinci-i2s.h"32 33#define DRV_NAME "davinci-i2s"34 35/*36 * NOTE:  terminology here is confusing.37 *38 *  - This driver supports the "Audio Serial Port" (ASP),39 *    found on dm6446, dm355, and other DaVinci chips.40 *41 *  - But it labels it a "Multi-channel Buffered Serial Port"42 *    (McBSP) as on older chips like the dm642 ... which was43 *    backward-compatible, possibly explaining that confusion.44 *45 *  - OMAP chips have a controller called McBSP, which is46 *    incompatible with the DaVinci flavor of McBSP.47 *48 *  - Newer DaVinci chips have a controller called McASP,49 *    incompatible with ASP and with either McBSP.50 *51 * In short:  this uses ASP to implement I2S, not McBSP.52 * And it won't be the only DaVinci implemention of I2S.53 */54#define DAVINCI_MCBSP_DRR_REG	0x0055#define DAVINCI_MCBSP_DXR_REG	0x0456#define DAVINCI_MCBSP_SPCR_REG	0x0857#define DAVINCI_MCBSP_RCR_REG	0x0c58#define DAVINCI_MCBSP_XCR_REG	0x1059#define DAVINCI_MCBSP_SRGR_REG	0x1460#define DAVINCI_MCBSP_PCR_REG	0x2461 62#define DAVINCI_MCBSP_SPCR_RRST		(1 << 0)63#define DAVINCI_MCBSP_SPCR_RINTM(v)	((v) << 4)64#define DAVINCI_MCBSP_SPCR_RJUST(v)	((v) << 13)65#define DAVINCI_MCBSP_SPCR_RJUST_Z_LE	DAVINCI_MCBSP_SPCR_RJUST(0)66#define DAVINCI_MCBSP_SPCR_RJUST_S_LE	DAVINCI_MCBSP_SPCR_RJUST(1)67#define DAVINCI_MCBSP_SPCR_XRST		(1 << 16)68#define DAVINCI_MCBSP_SPCR_XINTM(v)	((v) << 20)69#define DAVINCI_MCBSP_SPCR_GRST		(1 << 22)70#define DAVINCI_MCBSP_SPCR_FRST		(1 << 23)71#define DAVINCI_MCBSP_SPCR_FREE		(1 << 25)72 73#define DAVINCI_MCBSP_RCR_RWDLEN1(v)	((v) << 5)74#define DAVINCI_MCBSP_RCR_RFRLEN1(v)	((v) << 8)75#define DAVINCI_MCBSP_RCR_RDATDLY(v)	((v) << 16)76#define DAVINCI_MCBSP_RCR_RFIG		(1 << 18)77#define DAVINCI_MCBSP_RCR_RWDLEN2(v)	((v) << 21)78#define DAVINCI_MCBSP_RCR_RFRLEN2(v)	((v) << 24)79#define DAVINCI_MCBSP_RCR_RPHASE	BIT(31)80 81#define DAVINCI_MCBSP_XCR_XWDLEN1(v)	((v) << 5)82#define DAVINCI_MCBSP_XCR_XFRLEN1(v)	((v) << 8)83#define DAVINCI_MCBSP_XCR_XDATDLY(v)	((v) << 16)84#define DAVINCI_MCBSP_XCR_XFIG		(1 << 18)85#define DAVINCI_MCBSP_XCR_XWDLEN2(v)	((v) << 21)86#define DAVINCI_MCBSP_XCR_XFRLEN2(v)	((v) << 24)87#define DAVINCI_MCBSP_XCR_XPHASE	BIT(31)88 89#define DAVINCI_MCBSP_SRGR_FWID(v)	((v) << 8)90#define DAVINCI_MCBSP_SRGR_FPER(v)	((v) << 16)91#define DAVINCI_MCBSP_SRGR_FSGM		(1 << 28)92#define DAVINCI_MCBSP_SRGR_CLKSM	BIT(29)93 94#define DAVINCI_MCBSP_PCR_CLKRP		(1 << 0)95#define DAVINCI_MCBSP_PCR_CLKXP		(1 << 1)96#define DAVINCI_MCBSP_PCR_FSRP		(1 << 2)97#define DAVINCI_MCBSP_PCR_FSXP		(1 << 3)98#define DAVINCI_MCBSP_PCR_SCLKME	(1 << 7)99#define DAVINCI_MCBSP_PCR_CLKRM		(1 << 8)100#define DAVINCI_MCBSP_PCR_CLKXM		(1 << 9)101#define DAVINCI_MCBSP_PCR_FSRM		(1 << 10)102#define DAVINCI_MCBSP_PCR_FSXM		(1 << 11)103 104enum {105	DAVINCI_MCBSP_WORD_8 = 0,106	DAVINCI_MCBSP_WORD_12,107	DAVINCI_MCBSP_WORD_16,108	DAVINCI_MCBSP_WORD_20,109	DAVINCI_MCBSP_WORD_24,110	DAVINCI_MCBSP_WORD_32,111};112 113static const unsigned char asp_word_length[SNDRV_PCM_FORMAT_S32_LE + 1] = {114	[SNDRV_PCM_FORMAT_S8]		= DAVINCI_MCBSP_WORD_8,115	[SNDRV_PCM_FORMAT_S16_LE]	= DAVINCI_MCBSP_WORD_16,116	[SNDRV_PCM_FORMAT_S24_LE]	= DAVINCI_MCBSP_WORD_24,117	[SNDRV_PCM_FORMAT_S32_LE]	= DAVINCI_MCBSP_WORD_32,118};119 120static const unsigned char double_fmt[SNDRV_PCM_FORMAT_S32_LE + 1] = {121	[SNDRV_PCM_FORMAT_S8]		= SNDRV_PCM_FORMAT_S16_LE,122	[SNDRV_PCM_FORMAT_S16_LE]	= SNDRV_PCM_FORMAT_S32_LE,123};124 125struct davinci_mcbsp_dev {126	struct device *dev;127	struct snd_dmaengine_dai_dma_data dma_data[2];128	int dma_request[2];129	void __iomem			*base;130#define MOD_DSP_A	0131#define MOD_DSP_B	1132	int				mode;133	u32				pcr;134	struct clk			*clk;135	struct clk			*ext_clk;136	/*137	 * Combining both channels into 1 element will at least double the138	 * amount of time between servicing the dma channel, increase139	 * effiency, and reduce the chance of overrun/underrun. But,140	 * it will result in the left & right channels being swapped.141	 *142	 * If relabeling the left and right channels is not possible,143	 * you may want to let the codec know to swap them back.144	 *145	 * It may allow x10 the amount of time to service dma requests,146	 * if the codec is master and is using an unnecessarily fast bit clock147	 * (ie. tlvaic23b), independent of the sample rate. So, having an148	 * entire frame at once means it can be serviced at the sample rate149	 * instead of the bit clock rate.150	 *151	 * In the now unlikely case that an underrun still152	 * occurs, both the left and right samples will be repeated153	 * so that no pops are heard, and the left and right channels154	 * won't end up being swapped because of the underrun.155	 */156	unsigned enable_channel_combine:1;157 158	unsigned int fmt;159	int clk_div;160	bool i2s_accurate_sck;161 162	int tdm_slots;163	int slot_width;164 165	bool tx_framing_bit;166	bool rx_framing_bit;167};168 169static inline void davinci_mcbsp_write_reg(struct davinci_mcbsp_dev *dev,170					   int reg, u32 val)171{172	__raw_writel(val, dev->base + reg);173}174 175static inline u32 davinci_mcbsp_read_reg(struct davinci_mcbsp_dev *dev, int reg)176{177	return __raw_readl(dev->base + reg);178}179 180static void toggle_clock(struct davinci_mcbsp_dev *dev, int playback)181{182	u32 m = playback ? DAVINCI_MCBSP_PCR_CLKXP : DAVINCI_MCBSP_PCR_CLKRP;183	/* The clock needs to toggle to complete reset.184	 * So, fake it by toggling the clk polarity.185	 */186	davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, dev->pcr ^ m);187	davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, dev->pcr);188}189 190static void davinci_mcbsp_start(struct davinci_mcbsp_dev *dev,191		struct snd_pcm_substream *substream)192{193	int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);194	u32 spcr;195	u32 mask = playback ? DAVINCI_MCBSP_SPCR_XRST : DAVINCI_MCBSP_SPCR_RRST;196 197	/* Enable transmitter or receiver */198	spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);199	spcr |= mask;200 201	if (dev->pcr & (DAVINCI_MCBSP_PCR_FSXM | DAVINCI_MCBSP_PCR_FSRM)) {202		/* Start frame sync */203		spcr |= DAVINCI_MCBSP_SPCR_FRST;204	}205	davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);206}207 208static void davinci_mcbsp_stop(struct davinci_mcbsp_dev *dev, int playback)209{210	u32 spcr;211 212	/* Reset transmitter/receiver and sample rate/frame sync generators */213	spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);214	spcr &= ~(DAVINCI_MCBSP_SPCR_GRST | DAVINCI_MCBSP_SPCR_FRST);215	spcr &= playback ? ~DAVINCI_MCBSP_SPCR_XRST : ~DAVINCI_MCBSP_SPCR_RRST;216	davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);217	toggle_clock(dev, playback);218}219 220static int davinci_i2s_tdm_word_length(int tdm_slot_width)221{222	switch (tdm_slot_width) {223	case 8:224		return DAVINCI_MCBSP_WORD_8;225	case 12:226		return DAVINCI_MCBSP_WORD_12;227	case 16:228		return DAVINCI_MCBSP_WORD_16;229	case 20:230		return DAVINCI_MCBSP_WORD_20;231	case 24:232		return DAVINCI_MCBSP_WORD_24;233	case 32:234		return DAVINCI_MCBSP_WORD_32;235	default:236		return -EINVAL;237	}238}239 240static int davinci_i2s_set_tdm_slot(struct snd_soc_dai *cpu_dai,241				    unsigned int tx_mask,242				    unsigned int rx_mask,243				    int slots, int slot_width)244{245	struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);246 247	dev_dbg(dev->dev, "slots %d, slot_width %d\n", slots, slot_width);248 249	if (slots > 128 || !slots) {250		dev_err(dev->dev, "Invalid number of slots\n");251		return -EINVAL;252	}253 254	if (rx_mask != (1 << slots) - 1) {255		dev_err(dev->dev, "Invalid RX mask (0x%08x) : all slots must be used by McBSP\n",256			rx_mask);257		return -EINVAL;258	}259 260	if (tx_mask != (1 << slots) - 1) {261		dev_err(dev->dev, "Invalid TX mask (0x%08x) : all slots must be used by McBSP\n",262			tx_mask);263		return -EINVAL;264	}265 266	if (davinci_i2s_tdm_word_length(slot_width) < 0) {267		dev_err(dev->dev, "%s: Unsupported slot_width %d\n", __func__, slot_width);268		return -EINVAL;269	}270 271	dev->tdm_slots = slots;272	dev->slot_width = slot_width;273 274	return 0;275}276 277#define DEFAULT_BITPERSAMPLE	16278 279static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,280				   unsigned int fmt)281{282	struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);283	unsigned int pcr;284	unsigned int spcr;285	unsigned int srgr;286	bool inv_fs = false;287	/* Attention srgr is updated by hw_params! */288	srgr = DAVINCI_MCBSP_SRGR_FSGM |289		DAVINCI_MCBSP_SRGR_FPER(DEFAULT_BITPERSAMPLE * 2 - 1) |290		DAVINCI_MCBSP_SRGR_FWID(DEFAULT_BITPERSAMPLE - 1);291 292	dev->fmt = fmt;293 294	spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);295	switch (fmt & SND_SOC_DAIFMT_CLOCK_MASK) {296	case SND_SOC_DAIFMT_CONT:297		spcr |= DAVINCI_MCBSP_SPCR_FREE;298		dev_dbg(dev->dev, "Free-running mode ON\n");299		break;300	case SND_SOC_DAIFMT_GATED:301		spcr &= ~DAVINCI_MCBSP_SPCR_FREE;302		dev_dbg(dev->dev, "Free-running mode OFF\n");303		break;304	default:305		dev_err(dev->dev, "Invalid clock gating\n");306		return -EINVAL;307	}308	davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);309 310	/* set master/slave audio interface */311	switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {312	case SND_SOC_DAIFMT_BP_FP:313		/* cpu is master */314		pcr = DAVINCI_MCBSP_PCR_FSXM |315			DAVINCI_MCBSP_PCR_FSRM |316			DAVINCI_MCBSP_PCR_CLKXM |317			DAVINCI_MCBSP_PCR_CLKRM;318		break;319	case SND_SOC_DAIFMT_BC_FP:320		if (dev->tdm_slots || dev->slot_width) {321			dev_err(dev->dev, "TDM is not supported for BC_FP format\n");322			return -EINVAL;323		}324 325		/*326		 * McBSP CLKR pin is the input for the Sample Rate Generator.327		 * McBSP FSR and FSX are driven by the Sample Rate Generator.328		 */329		pcr = DAVINCI_MCBSP_PCR_FSRM | DAVINCI_MCBSP_PCR_FSXM;330		pcr |= DAVINCI_MCBSP_PCR_SCLKME;331		break;332	case SND_SOC_DAIFMT_BP_FC:333		/* cpu is bitclock provider */334		pcr = DAVINCI_MCBSP_PCR_CLKXM |335			DAVINCI_MCBSP_PCR_CLKRM;336		break;337 338	case SND_SOC_DAIFMT_BC_FC:339		if (dev->tdm_slots || dev->slot_width) {340			dev_err(dev->dev, "TDM is not supported for BC_FC format\n");341			return -EINVAL;342		}343 344		/* codec is master */345		pcr = 0;346		break;347	default:348		printk(KERN_ERR "%s:bad master\n", __func__);349		return -EINVAL;350	}351 352	/* interface format */353	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {354	case SND_SOC_DAIFMT_I2S:355		/* Davinci doesn't support TRUE I2S, but some codecs will have356		 * the left and right channels contiguous. This allows357		 * dsp_a mode to be used with an inverted normal frame clk.358		 * If your codec is master and does not have contiguous359		 * channels, then you will have sound on only one channel.360		 * Try using a different mode, or codec as slave.361		 *362		 * The TLV320AIC33 is an example of a codec where this works.363		 * It has a variable bit clock frequency allowing it to have364		 * valid data on every bit clock.365		 *366		 * The TLV320AIC23 is an example of a codec where this does not367		 * work. It has a fixed bit clock frequency with progressively368		 * more empty bit clock slots between channels as the sample369		 * rate is lowered.370		 */371		inv_fs = true;372		fallthrough;373	case SND_SOC_DAIFMT_DSP_A:374		dev->mode = MOD_DSP_A;375		break;376	case SND_SOC_DAIFMT_DSP_B:377		dev->mode = MOD_DSP_B;378		break;379	default:380		printk(KERN_ERR "%s:bad format\n", __func__);381		return -EINVAL;382	}383 384	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {385	case SND_SOC_DAIFMT_NB_NF:386		/* CLKRP Receive clock polarity,387		 *	1 - sampled on rising edge of CLKR388		 *	valid on rising edge389		 * CLKXP Transmit clock polarity,390		 *	1 - clocked on falling edge of CLKX391		 *	valid on rising edge392		 * FSRP  Receive frame sync pol, 0 - active high393		 * FSXP  Transmit frame sync pol, 0 - active high394		 */395		pcr |= (DAVINCI_MCBSP_PCR_CLKXP | DAVINCI_MCBSP_PCR_CLKRP);396		break;397	case SND_SOC_DAIFMT_IB_IF:398		/* CLKRP Receive clock polarity,399		 *	0 - sampled on falling edge of CLKR400		 *	valid on falling edge401		 * CLKXP Transmit clock polarity,402		 *	0 - clocked on rising edge of CLKX403		 *	valid on falling edge404		 * FSRP  Receive frame sync pol, 1 - active low405		 * FSXP  Transmit frame sync pol, 1 - active low406		 */407		pcr |= (DAVINCI_MCBSP_PCR_FSXP | DAVINCI_MCBSP_PCR_FSRP);408		break;409	case SND_SOC_DAIFMT_NB_IF:410		/* CLKRP Receive clock polarity,411		 *	1 - sampled on rising edge of CLKR412		 *	valid on rising edge413		 * CLKXP Transmit clock polarity,414		 *	1 - clocked on falling edge of CLKX415		 *	valid on rising edge416		 * FSRP  Receive frame sync pol, 1 - active low417		 * FSXP  Transmit frame sync pol, 1 - active low418		 */419		pcr |= (DAVINCI_MCBSP_PCR_CLKXP | DAVINCI_MCBSP_PCR_CLKRP |420			DAVINCI_MCBSP_PCR_FSXP | DAVINCI_MCBSP_PCR_FSRP);421		break;422	case SND_SOC_DAIFMT_IB_NF:423		/* CLKRP Receive clock polarity,424		 *	0 - sampled on falling edge of CLKR425		 *	valid on falling edge426		 * CLKXP Transmit clock polarity,427		 *	0 - clocked on rising edge of CLKX428		 *	valid on falling edge429		 * FSRP  Receive frame sync pol, 0 - active high430		 * FSXP  Transmit frame sync pol, 0 - active high431		 */432		break;433	default:434		return -EINVAL;435	}436	if (inv_fs == true)437		pcr ^= (DAVINCI_MCBSP_PCR_FSXP | DAVINCI_MCBSP_PCR_FSRP);438	davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, srgr);439	dev->pcr = pcr;440	davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, pcr);441	return 0;442}443 444static int davinci_i2s_dai_set_clkdiv(struct snd_soc_dai *cpu_dai,445				int div_id, int div)446{447	struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);448 449	if (div_id != DAVINCI_MCBSP_CLKGDV)450		return -ENODEV;451 452	dev->clk_div = div;453	return 0;454}455 456static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,457				 struct snd_pcm_hw_params *params,458				 struct snd_soc_dai *dai)459{460	struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai);461	struct snd_interval *i = NULL;462	int mcbsp_word_length, master;463	unsigned int clk_div, freq, framesize;464	unsigned int srgr = 0;465	unsigned int rcr = 0;466	unsigned int xcr = 0;467	u32 spcr;468	snd_pcm_format_t fmt;469	unsigned element_cnt = 1;470 471	spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);472 473	/* Determine xfer data type */474	fmt = params_format(params);475	switch (fmt) {476	case SNDRV_PCM_FORMAT_S16_LE:477	case SNDRV_PCM_FORMAT_S32_LE:478		break;479	case SNDRV_PCM_FORMAT_S24_LE:480		spcr |= DAVINCI_MCBSP_SPCR_RJUST_S_LE;481		break;482	default:483		dev_warn(dev->dev, "davinci-i2s: unsupported PCM format\n");484		return -EINVAL;485	}486 487	/* general line settings */488	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {489		spcr |= DAVINCI_MCBSP_SPCR_RINTM(3);490		davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);491	} else {492		spcr |= DAVINCI_MCBSP_SPCR_XINTM(3);493		davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);494	}495 496	master = dev->fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK;497	fmt = params_format(params);498	if (dev->slot_width)499		mcbsp_word_length = davinci_i2s_tdm_word_length(dev->slot_width);500	else501		mcbsp_word_length = asp_word_length[fmt];502 503	if (mcbsp_word_length < 0)504		return mcbsp_word_length;505 506	switch (master) {507	case SND_SOC_DAIFMT_BP_FP:508		if (dev->ext_clk) {509			freq = clk_get_rate(dev->ext_clk);510		} else {511			freq = clk_get_rate(dev->clk);512			srgr = DAVINCI_MCBSP_SRGR_CLKSM;513		}514		srgr |= DAVINCI_MCBSP_SRGR_FSGM;515		srgr |= DAVINCI_MCBSP_SRGR_FWID(mcbsp_word_length *516						8 - 1);517		if (dev->i2s_accurate_sck) {518			clk_div = 256;519			do {520				framesize = (freq / (--clk_div)) /521				params->rate_num *522					params->rate_den;523			} while (((framesize < 33) || (framesize > 4095)) &&524				 (clk_div));525			clk_div--;526			srgr |= DAVINCI_MCBSP_SRGR_FPER(framesize - 1);527		} else {528			/* symmetric waveforms */529			clk_div = freq / (mcbsp_word_length * 16) /530				  params->rate_num * params->rate_den;531			srgr |= DAVINCI_MCBSP_SRGR_FPER(mcbsp_word_length *532							16 - 1);533		}534		clk_div &= 0xFF;535		srgr |= clk_div;536		break;537	case SND_SOC_DAIFMT_BC_FP:538		srgr = DAVINCI_MCBSP_SRGR_FSGM;539		clk_div = dev->clk_div - 1;540		srgr |= DAVINCI_MCBSP_SRGR_FWID(mcbsp_word_length * 8 - 1);541		srgr |= DAVINCI_MCBSP_SRGR_FPER(mcbsp_word_length * 16 - 1);542		clk_div &= 0xFF;543		srgr |= clk_div;544		break;545	case SND_SOC_DAIFMT_BP_FC:546		if (dev->ext_clk) {547			freq = clk_get_rate(dev->ext_clk);548		} else {549			freq = clk_get_rate(dev->clk);550			srgr = DAVINCI_MCBSP_SRGR_CLKSM;551		}552		if (dev->tdm_slots && dev->slot_width) {553			clk_div = freq / (params->rate_num * params->rate_den)554				 / (dev->tdm_slots * dev->slot_width) - 1;555		} else {556			clk_div = freq / (mcbsp_word_length * 16) /557				  params->rate_num * params->rate_den;558		}559		clk_div &= 0xFF;560		srgr |= clk_div;561		break;562	case SND_SOC_DAIFMT_BC_FC:563		/* Clock and frame sync given from external sources */564		i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS);565		srgr = DAVINCI_MCBSP_SRGR_FSGM;566		srgr |= DAVINCI_MCBSP_SRGR_FWID(snd_interval_value(i) - 1);567		pr_debug("%s - %d  FWID set: re-read srgr = %X\n",568			__func__, __LINE__, snd_interval_value(i) - 1);569 570		i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_FRAME_BITS);571		srgr |= DAVINCI_MCBSP_SRGR_FPER(snd_interval_value(i) - 1);572		break;573	default:574		return -EINVAL;575	}576	davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, srgr);577 578	if (dev->mode == MOD_DSP_B) {579		rcr |= DAVINCI_MCBSP_RCR_RDATDLY(0);580		xcr |= DAVINCI_MCBSP_XCR_XDATDLY(0);581	} else {582		rcr |= DAVINCI_MCBSP_RCR_RDATDLY(1);583		xcr |= DAVINCI_MCBSP_XCR_XDATDLY(1);584	}585 586	if (dev->tx_framing_bit) {587		xcr &= ~DAVINCI_MCBSP_XCR_XDATDLY(1);588		xcr |= DAVINCI_MCBSP_XCR_XDATDLY(2);589	}590	if (dev->rx_framing_bit) {591		rcr &= ~DAVINCI_MCBSP_RCR_RDATDLY(1);592		rcr |= DAVINCI_MCBSP_RCR_RDATDLY(2);593	}594 595	if (params_channels(params) == 2) {596		element_cnt = 2;597		if (double_fmt[fmt] && dev->enable_channel_combine) {598			element_cnt = 1;599			fmt = double_fmt[fmt];600		}601		switch (master) {602		case SND_SOC_DAIFMT_BP_FP:603		case SND_SOC_DAIFMT_BP_FC:604			rcr |= DAVINCI_MCBSP_RCR_RFRLEN2(0);605			xcr |= DAVINCI_MCBSP_XCR_XFRLEN2(0);606			rcr |= DAVINCI_MCBSP_RCR_RPHASE;607			xcr |= DAVINCI_MCBSP_XCR_XPHASE;608			break;609		case SND_SOC_DAIFMT_BC_FC:610		case SND_SOC_DAIFMT_BC_FP:611			rcr |= DAVINCI_MCBSP_RCR_RFRLEN2(element_cnt - 1);612			xcr |= DAVINCI_MCBSP_XCR_XFRLEN2(element_cnt - 1);613			break;614		default:615			return -EINVAL;616		}617	}618 619	switch (master) {620	case SND_SOC_DAIFMT_BP_FP:621	case SND_SOC_DAIFMT_BP_FC:622		if (dev->tdm_slots > 0) {623			rcr |= DAVINCI_MCBSP_RCR_RFRLEN1(dev->tdm_slots - 1);624			xcr |= DAVINCI_MCBSP_XCR_XFRLEN1(dev->tdm_slots - 1);625		} else {626			rcr |= DAVINCI_MCBSP_RCR_RFRLEN1(0);627			xcr |= DAVINCI_MCBSP_XCR_XFRLEN1(0);628		}629		break;630	case SND_SOC_DAIFMT_BC_FC:631	case SND_SOC_DAIFMT_BC_FP:632		rcr |= DAVINCI_MCBSP_RCR_RFRLEN1(element_cnt - 1);633		xcr |= DAVINCI_MCBSP_XCR_XFRLEN1(element_cnt - 1);634		break;635	default:636		return -EINVAL;637	}638 639	rcr |= DAVINCI_MCBSP_RCR_RWDLEN1(mcbsp_word_length) |640		DAVINCI_MCBSP_RCR_RWDLEN2(mcbsp_word_length);641	xcr |= DAVINCI_MCBSP_XCR_XWDLEN1(mcbsp_word_length) |642		DAVINCI_MCBSP_XCR_XWDLEN2(mcbsp_word_length);643 644	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)645		davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG, xcr);646	else647		davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG, rcr);648 649	pr_debug("%s - %d  srgr=%X\n", __func__, __LINE__, srgr);650	pr_debug("%s - %d  xcr=%X\n", __func__, __LINE__, xcr);651	pr_debug("%s - %d  rcr=%X\n", __func__, __LINE__, rcr);652	return 0;653}654 655static int davinci_i2s_prepare(struct snd_pcm_substream *substream,656		struct snd_soc_dai *dai)657{658	struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai);659	int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);660	u32 spcr;661	u32 mask = playback ? DAVINCI_MCBSP_SPCR_XRST : DAVINCI_MCBSP_SPCR_RRST;662 663	davinci_mcbsp_stop(dev, playback);664 665	spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);666	if (spcr & mask) {667		/* start off disabled */668		davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG,669					spcr & ~mask);670		toggle_clock(dev, playback);671	}672	if (dev->pcr & (DAVINCI_MCBSP_PCR_FSXM | DAVINCI_MCBSP_PCR_FSRM |673			DAVINCI_MCBSP_PCR_CLKXM | DAVINCI_MCBSP_PCR_CLKRM)) {674		/* Start the sample generator */675		spcr |= DAVINCI_MCBSP_SPCR_GRST;676		davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);677	}678 679	if (playback) {680		/* Enable the transmitter */681		spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);682		spcr |= DAVINCI_MCBSP_SPCR_XRST;683		davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);684 685		/* wait for any unexpected frame sync error to occur */686		udelay(100);687 688		/* Disable the transmitter to clear any outstanding XSYNCERR */689		spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);690		spcr &= ~DAVINCI_MCBSP_SPCR_XRST;691		davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr);692		toggle_clock(dev, playback);693	}694 695	return 0;696}697 698static int davinci_i2s_trigger(struct snd_pcm_substream *substream, int cmd,699			       struct snd_soc_dai *dai)700{701	struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai);702	int ret = 0;703	int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);704 705	switch (cmd) {706	case SNDRV_PCM_TRIGGER_START:707	case SNDRV_PCM_TRIGGER_RESUME:708	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:709		davinci_mcbsp_start(dev, substream);710		break;711	case SNDRV_PCM_TRIGGER_STOP:712	case SNDRV_PCM_TRIGGER_SUSPEND:713	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:714		davinci_mcbsp_stop(dev, playback);715		break;716	default:717		ret = -EINVAL;718	}719	return ret;720}721 722static void davinci_i2s_shutdown(struct snd_pcm_substream *substream,723		struct snd_soc_dai *dai)724{725	struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai);726	int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);727	davinci_mcbsp_stop(dev, playback);728}729 730#define DAVINCI_I2S_RATES	SNDRV_PCM_RATE_8000_96000731#define DAVINCI_I2S_FORMATS	(SNDRV_PCM_FMTBIT_S16_LE | \732				 SNDRV_PCM_FMTBIT_S24_LE | \733				 SNDRV_PCM_FMTBIT_S32_LE)734 735static int davinci_i2s_dai_probe(struct snd_soc_dai *dai)736{737	struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai);738	int stream;739 740	for_each_pcm_streams(stream)741		snd_soc_dai_dma_data_set(dai, stream, &dev->dma_data[stream]);742 743	return 0;744}745 746static const struct snd_soc_dai_ops davinci_i2s_dai_ops = {747	.probe		= davinci_i2s_dai_probe,748	.shutdown	= davinci_i2s_shutdown,749	.prepare	= davinci_i2s_prepare,750	.trigger	= davinci_i2s_trigger,751	.hw_params	= davinci_i2s_hw_params,752	.set_fmt	= davinci_i2s_set_dai_fmt,753	.set_clkdiv	= davinci_i2s_dai_set_clkdiv,754	.set_tdm_slot   = davinci_i2s_set_tdm_slot,755 756};757 758static struct snd_soc_dai_driver davinci_i2s_dai = {759	.playback = {760		.channels_min = 2,761		.channels_max = 128,762		.rates = DAVINCI_I2S_RATES,763		.formats = DAVINCI_I2S_FORMATS,764	},765	.capture = {766		.channels_min = 2,767		.channels_max = 128,768		.rates = DAVINCI_I2S_RATES,769		.formats = DAVINCI_I2S_FORMATS,770	},771	.ops = &davinci_i2s_dai_ops,772 773};774 775static const struct snd_soc_component_driver davinci_i2s_component = {776	.name			= DRV_NAME,777	.legacy_dai_naming	= 1,778};779 780static int davinci_i2s_probe(struct platform_device *pdev)781{782	struct snd_dmaengine_dai_dma_data *dma_data;783	struct davinci_mcbsp_dev *dev;784	struct resource *mem, *res;785	void __iomem *io_base;786	int *dma;787	int ret;788 789	mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu");790	if (!mem) {791		dev_warn(&pdev->dev,792			 "\"mpu\" mem resource not found, using index 0\n");793		mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);794		if (!mem) {795			dev_err(&pdev->dev, "no mem resource?\n");796			return -ENODEV;797		}798	}799 800	io_base = devm_ioremap_resource(&pdev->dev, mem);801	if (IS_ERR(io_base))802		return PTR_ERR(io_base);803 804	dev = devm_kzalloc(&pdev->dev, sizeof(struct davinci_mcbsp_dev),805			   GFP_KERNEL);806	if (!dev)807		return -ENOMEM;808 809	dev->base = io_base;810 811	dev->tx_framing_bit = of_property_read_bool(pdev->dev.of_node, "ti,T1-framing-tx");812	dev->rx_framing_bit = of_property_read_bool(pdev->dev.of_node, "ti,T1-framing-rx");813 814	/* setup DMA, first TX, then RX */815	dma_data = &dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK];816	dma_data->addr = (dma_addr_t)(mem->start + DAVINCI_MCBSP_DXR_REG);817 818	res = platform_get_resource(pdev, IORESOURCE_DMA, 0);819	if (res) {820		dma = &dev->dma_request[SNDRV_PCM_STREAM_PLAYBACK];821		*dma = res->start;822		dma_data->filter_data = dma;823	} else if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) {824		dma_data->filter_data = "tx";825	} else {826		dev_err(&pdev->dev, "Missing DMA tx resource\n");827		return -ENODEV;828	}829 830	dma_data = &dev->dma_data[SNDRV_PCM_STREAM_CAPTURE];831	dma_data->addr = (dma_addr_t)(mem->start + DAVINCI_MCBSP_DRR_REG);832 833	res = platform_get_resource(pdev, IORESOURCE_DMA, 1);834	if (res) {835		dma = &dev->dma_request[SNDRV_PCM_STREAM_CAPTURE];836		*dma = res->start;837		dma_data->filter_data = dma;838	} else if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) {839		dma_data->filter_data = "rx";840	} else {841		dev_err(&pdev->dev, "Missing DMA rx resource\n");842		return -ENODEV;843	}844 845	/*846	 * The optional is there for backward compatibility.847	 * If 'fck' is not present, the clk_get(dev, NULL) that follows may find something848	 */849	dev->clk = devm_clk_get_optional(&pdev->dev, "fck");850	if (IS_ERR(dev->clk))851		return dev_err_probe(&pdev->dev, PTR_ERR(dev->clk), "Invalid functional clock\n");852	if (!dev->clk) {853		dev->clk = devm_clk_get(&pdev->dev, NULL);854		if (IS_ERR(dev->clk))855			return dev_err_probe(&pdev->dev, PTR_ERR(dev->clk),856					     "Missing functional clock\n");857	}858 859	dev->ext_clk = devm_clk_get_optional(&pdev->dev, "clks");860	if (IS_ERR(dev->ext_clk))861		return dev_err_probe(&pdev->dev, PTR_ERR(dev->ext_clk), "Invalid external clock\n");862 863	ret = clk_prepare_enable(dev->clk);864	if (ret)865		return ret;866 867	if (dev->ext_clk) {868		dev_dbg(&pdev->dev, "External clock used for sample rate generator\n");869		ret = clk_prepare_enable(dev->ext_clk);870		if (ret) {871			dev_err_probe(&pdev->dev, ret, "Failed to enable external clock\n");872			goto err_disable_clk;873		}874	}875 876	dev->dev = &pdev->dev;877	dev_set_drvdata(&pdev->dev, dev);878 879	ret = snd_soc_register_component(&pdev->dev, &davinci_i2s_component,880					 &davinci_i2s_dai, 1);881	if (ret != 0)882		goto err_disable_ext_clk;883 884	ret = edma_pcm_platform_register(&pdev->dev);885	if (ret) {886		dev_err_probe(&pdev->dev, ret, "register PCM failed\n");887		goto err_unregister_component;888	}889 890	return 0;891 892err_unregister_component:893	snd_soc_unregister_component(&pdev->dev);894err_disable_ext_clk:895	if (dev->ext_clk)896		clk_disable_unprepare(dev->ext_clk);897err_disable_clk:898	clk_disable_unprepare(dev->clk);899 900	return ret;901}902 903static void davinci_i2s_remove(struct platform_device *pdev)904{905	struct davinci_mcbsp_dev *dev = dev_get_drvdata(&pdev->dev);906 907	snd_soc_unregister_component(&pdev->dev);908 909	clk_disable_unprepare(dev->clk);910 911	if (dev->ext_clk)912		clk_disable_unprepare(dev->ext_clk);913}914 915static const struct of_device_id davinci_i2s_match[] __maybe_unused = {916	{ .compatible = "ti,da850-mcbsp" },917	{},918};919MODULE_DEVICE_TABLE(of, davinci_i2s_match);920 921static struct platform_driver davinci_mcbsp_driver = {922	.probe		= davinci_i2s_probe,923	.remove		= davinci_i2s_remove,924	.driver		= {925		.name	= "davinci-mcbsp",926		.of_match_table = of_match_ptr(davinci_i2s_match),927	},928};929 930module_platform_driver(davinci_mcbsp_driver);931 932MODULE_AUTHOR("Vladimir Barinov");933MODULE_DESCRIPTION("TI DAVINCI I2S (McBSP) SoC Interface");934MODULE_LICENSE("GPL");935