brintos

brintos / linux-shallow public Read only

0
0
Text · 17.8 KiB · fbfeefa Raw
668 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (C) ST-Ericsson SA 20124 *5 * Author: Ola Lilja <ola.o.lilja@stericsson.com>,6 *         Roger Nilsson <roger.xr.nilsson@stericsson.com>,7 *         Sandeep Kaushik <sandeep.kaushik@st.com>8 *         for ST-Ericsson.9 */10 11#include <linux/module.h>12#include <linux/platform_device.h>13#include <linux/delay.h>14#include <linux/slab.h>15#include <linux/io.h>16#include <linux/of.h>17 18#include <sound/soc.h>19 20#include "ux500_msp_i2s.h"21 22 /* Protocol desciptors */23static const struct msp_protdesc prot_descs[] = {24	{ /* I2S */25		MSP_SINGLE_PHASE,26		MSP_SINGLE_PHASE,27		MSP_PHASE2_START_MODE_IMEDIATE,28		MSP_PHASE2_START_MODE_IMEDIATE,29		MSP_BTF_MS_BIT_FIRST,30		MSP_BTF_MS_BIT_FIRST,31		MSP_FRAME_LEN_1,32		MSP_FRAME_LEN_1,33		MSP_FRAME_LEN_1,34		MSP_FRAME_LEN_1,35		MSP_ELEM_LEN_32,36		MSP_ELEM_LEN_32,37		MSP_ELEM_LEN_32,38		MSP_ELEM_LEN_32,39		MSP_DELAY_1,40		MSP_DELAY_1,41		MSP_RISING_EDGE,42		MSP_FALLING_EDGE,43		MSP_FSYNC_POL_ACT_LO,44		MSP_FSYNC_POL_ACT_LO,45		MSP_SWAP_NONE,46		MSP_SWAP_NONE,47		MSP_COMPRESS_MODE_LINEAR,48		MSP_EXPAND_MODE_LINEAR,49		MSP_FSYNC_IGNORE,50		31,51		15,52		32,53	}, { /* PCM */54		MSP_DUAL_PHASE,55		MSP_DUAL_PHASE,56		MSP_PHASE2_START_MODE_FSYNC,57		MSP_PHASE2_START_MODE_FSYNC,58		MSP_BTF_MS_BIT_FIRST,59		MSP_BTF_MS_BIT_FIRST,60		MSP_FRAME_LEN_1,61		MSP_FRAME_LEN_1,62		MSP_FRAME_LEN_1,63		MSP_FRAME_LEN_1,64		MSP_ELEM_LEN_16,65		MSP_ELEM_LEN_16,66		MSP_ELEM_LEN_16,67		MSP_ELEM_LEN_16,68		MSP_DELAY_0,69		MSP_DELAY_0,70		MSP_RISING_EDGE,71		MSP_FALLING_EDGE,72		MSP_FSYNC_POL_ACT_HI,73		MSP_FSYNC_POL_ACT_HI,74		MSP_SWAP_NONE,75		MSP_SWAP_NONE,76		MSP_COMPRESS_MODE_LINEAR,77		MSP_EXPAND_MODE_LINEAR,78		MSP_FSYNC_IGNORE,79		255,80		0,81		256,82	}, { /* Companded PCM */83		MSP_SINGLE_PHASE,84		MSP_SINGLE_PHASE,85		MSP_PHASE2_START_MODE_FSYNC,86		MSP_PHASE2_START_MODE_FSYNC,87		MSP_BTF_MS_BIT_FIRST,88		MSP_BTF_MS_BIT_FIRST,89		MSP_FRAME_LEN_1,90		MSP_FRAME_LEN_1,91		MSP_FRAME_LEN_1,92		MSP_FRAME_LEN_1,93		MSP_ELEM_LEN_8,94		MSP_ELEM_LEN_8,95		MSP_ELEM_LEN_8,96		MSP_ELEM_LEN_8,97		MSP_DELAY_0,98		MSP_DELAY_0,99		MSP_RISING_EDGE,100		MSP_RISING_EDGE,101		MSP_FSYNC_POL_ACT_HI,102		MSP_FSYNC_POL_ACT_HI,103		MSP_SWAP_NONE,104		MSP_SWAP_NONE,105		MSP_COMPRESS_MODE_LINEAR,106		MSP_EXPAND_MODE_LINEAR,107		MSP_FSYNC_IGNORE,108		255,109		0,110		256,111	},112};113 114static void set_prot_desc_tx(struct ux500_msp *msp,115			struct msp_protdesc *protdesc,116			enum msp_data_size data_size)117{118	u32 temp_reg = 0;119 120	temp_reg |= MSP_P2_ENABLE_BIT(protdesc->tx_phase_mode);121	temp_reg |= MSP_P2_START_MODE_BIT(protdesc->tx_phase2_start_mode);122	temp_reg |= MSP_P1_FRAME_LEN_BITS(protdesc->tx_frame_len_1);123	temp_reg |= MSP_P2_FRAME_LEN_BITS(protdesc->tx_frame_len_2);124	if (msp->def_elem_len) {125		temp_reg |= MSP_P1_ELEM_LEN_BITS(protdesc->tx_elem_len_1);126		temp_reg |= MSP_P2_ELEM_LEN_BITS(protdesc->tx_elem_len_2);127	} else {128		temp_reg |= MSP_P1_ELEM_LEN_BITS(data_size);129		temp_reg |= MSP_P2_ELEM_LEN_BITS(data_size);130	}131	temp_reg |= MSP_DATA_DELAY_BITS(protdesc->tx_data_delay);132	temp_reg |= MSP_SET_ENDIANNES_BIT(protdesc->tx_byte_order);133	temp_reg |= MSP_FSYNC_POL(protdesc->tx_fsync_pol);134	temp_reg |= MSP_DATA_WORD_SWAP(protdesc->tx_half_word_swap);135	temp_reg |= MSP_SET_COMPANDING_MODE(protdesc->compression_mode);136	temp_reg |= MSP_SET_FSYNC_IGNORE(protdesc->frame_sync_ignore);137 138	writel(temp_reg, msp->registers + MSP_TCF);139}140 141static void set_prot_desc_rx(struct ux500_msp *msp,142			struct msp_protdesc *protdesc,143			enum msp_data_size data_size)144{145	u32 temp_reg = 0;146 147	temp_reg |= MSP_P2_ENABLE_BIT(protdesc->rx_phase_mode);148	temp_reg |= MSP_P2_START_MODE_BIT(protdesc->rx_phase2_start_mode);149	temp_reg |= MSP_P1_FRAME_LEN_BITS(protdesc->rx_frame_len_1);150	temp_reg |= MSP_P2_FRAME_LEN_BITS(protdesc->rx_frame_len_2);151	if (msp->def_elem_len) {152		temp_reg |= MSP_P1_ELEM_LEN_BITS(protdesc->rx_elem_len_1);153		temp_reg |= MSP_P2_ELEM_LEN_BITS(protdesc->rx_elem_len_2);154	} else {155		temp_reg |= MSP_P1_ELEM_LEN_BITS(data_size);156		temp_reg |= MSP_P2_ELEM_LEN_BITS(data_size);157	}158 159	temp_reg |= MSP_DATA_DELAY_BITS(protdesc->rx_data_delay);160	temp_reg |= MSP_SET_ENDIANNES_BIT(protdesc->rx_byte_order);161	temp_reg |= MSP_FSYNC_POL(protdesc->rx_fsync_pol);162	temp_reg |= MSP_DATA_WORD_SWAP(protdesc->rx_half_word_swap);163	temp_reg |= MSP_SET_COMPANDING_MODE(protdesc->expansion_mode);164	temp_reg |= MSP_SET_FSYNC_IGNORE(protdesc->frame_sync_ignore);165 166	writel(temp_reg, msp->registers + MSP_RCF);167}168 169static int configure_protocol(struct ux500_msp *msp,170			struct ux500_msp_config *config)171{172	struct msp_protdesc *protdesc;173	enum msp_data_size data_size;174	u32 temp_reg = 0;175 176	data_size = config->data_size;177	msp->def_elem_len = config->def_elem_len;178	if (config->default_protdesc == 1) {179		if (config->protocol >= MSP_INVALID_PROTOCOL) {180			dev_err(msp->dev, "%s: ERROR: Invalid protocol!\n",181				__func__);182			return -EINVAL;183		}184		protdesc =185		    (struct msp_protdesc *)&prot_descs[config->protocol];186	} else {187		protdesc = (struct msp_protdesc *)&config->protdesc;188	}189 190	if (data_size < MSP_DATA_BITS_DEFAULT || data_size > MSP_DATA_BITS_32) {191		dev_err(msp->dev,192			"%s: ERROR: Invalid data-size requested (data_size = %d)!\n",193			__func__, data_size);194		return -EINVAL;195	}196 197	if (config->direction & MSP_DIR_TX)198		set_prot_desc_tx(msp, protdesc, data_size);199	if (config->direction & MSP_DIR_RX)200		set_prot_desc_rx(msp, protdesc, data_size);201 202	/* The code below should not be separated. */203	temp_reg = readl(msp->registers + MSP_GCR) & ~TX_CLK_POL_RISING;204	temp_reg |= MSP_TX_CLKPOL_BIT(~protdesc->tx_clk_pol);205	writel(temp_reg, msp->registers + MSP_GCR);206	temp_reg = readl(msp->registers + MSP_GCR) & ~RX_CLK_POL_RISING;207	temp_reg |= MSP_RX_CLKPOL_BIT(protdesc->rx_clk_pol);208	writel(temp_reg, msp->registers + MSP_GCR);209 210	return 0;211}212 213static int setup_bitclk(struct ux500_msp *msp, struct ux500_msp_config *config)214{215	u32 reg_val_GCR;216	u32 frame_per = 0;217	u32 sck_div = 0;218	u32 frame_width = 0;219	u32 temp_reg = 0;220	struct msp_protdesc *protdesc = NULL;221 222	reg_val_GCR = readl(msp->registers + MSP_GCR);223	writel(reg_val_GCR & ~SRG_ENABLE, msp->registers + MSP_GCR);224 225	if (config->default_protdesc)226		protdesc =227			(struct msp_protdesc *)&prot_descs[config->protocol];228	else229		protdesc = (struct msp_protdesc *)&config->protdesc;230 231	switch (config->protocol) {232	case MSP_PCM_PROTOCOL:233	case MSP_PCM_COMPAND_PROTOCOL:234		frame_width = protdesc->frame_width;235		sck_div = config->f_inputclk / (config->frame_freq *236			(protdesc->clocks_per_frame));237		frame_per = protdesc->frame_period;238		break;239	case MSP_I2S_PROTOCOL:240		frame_width = protdesc->frame_width;241		sck_div = config->f_inputclk / (config->frame_freq *242			(protdesc->clocks_per_frame));243		frame_per = protdesc->frame_period;244		break;245	default:246		dev_err(msp->dev, "%s: ERROR: Unknown protocol (%d)!\n",247			__func__,248			config->protocol);249		return -EINVAL;250	}251 252	temp_reg = (sck_div - 1) & SCK_DIV_MASK;253	temp_reg |= FRAME_WIDTH_BITS(frame_width);254	temp_reg |= FRAME_PERIOD_BITS(frame_per);255	writel(temp_reg, msp->registers + MSP_SRG);256 257	msp->f_bitclk = (config->f_inputclk)/(sck_div + 1);258 259	/* Enable bit-clock */260	udelay(100);261	reg_val_GCR = readl(msp->registers + MSP_GCR);262	writel(reg_val_GCR | SRG_ENABLE, msp->registers + MSP_GCR);263	udelay(100);264 265	return 0;266}267 268static int configure_multichannel(struct ux500_msp *msp,269				struct ux500_msp_config *config)270{271	struct msp_protdesc *protdesc;272	struct msp_multichannel_config *mcfg;273	u32 reg_val_MCR;274 275	if (config->default_protdesc == 1) {276		if (config->protocol >= MSP_INVALID_PROTOCOL) {277			dev_err(msp->dev,278				"%s: ERROR: Invalid protocol (%d)!\n",279				__func__, config->protocol);280			return -EINVAL;281		}282		protdesc = (struct msp_protdesc *)283				&prot_descs[config->protocol];284	} else {285		protdesc = (struct msp_protdesc *)&config->protdesc;286	}287 288	mcfg = &config->multichannel_config;289	if (mcfg->tx_multichannel_enable) {290		if (protdesc->tx_phase_mode == MSP_SINGLE_PHASE) {291			reg_val_MCR = readl(msp->registers + MSP_MCR);292			writel(reg_val_MCR | (mcfg->tx_multichannel_enable ?293						1 << TMCEN_BIT : 0),294				msp->registers + MSP_MCR);295			writel(mcfg->tx_channel_0_enable,296				msp->registers + MSP_TCE0);297			writel(mcfg->tx_channel_1_enable,298				msp->registers + MSP_TCE1);299			writel(mcfg->tx_channel_2_enable,300				msp->registers + MSP_TCE2);301			writel(mcfg->tx_channel_3_enable,302				msp->registers + MSP_TCE3);303		} else {304			dev_err(msp->dev,305				"%s: ERROR: Only single-phase supported (TX-mode: %d)!\n",306				__func__, protdesc->tx_phase_mode);307			return -EINVAL;308		}309	}310	if (mcfg->rx_multichannel_enable) {311		if (protdesc->rx_phase_mode == MSP_SINGLE_PHASE) {312			reg_val_MCR = readl(msp->registers + MSP_MCR);313			writel(reg_val_MCR | (mcfg->rx_multichannel_enable ?314						1 << RMCEN_BIT : 0),315				msp->registers + MSP_MCR);316			writel(mcfg->rx_channel_0_enable,317					msp->registers + MSP_RCE0);318			writel(mcfg->rx_channel_1_enable,319					msp->registers + MSP_RCE1);320			writel(mcfg->rx_channel_2_enable,321					msp->registers + MSP_RCE2);322			writel(mcfg->rx_channel_3_enable,323					msp->registers + MSP_RCE3);324		} else {325			dev_err(msp->dev,326				"%s: ERROR: Only single-phase supported (RX-mode: %d)!\n",327				__func__, protdesc->rx_phase_mode);328			return -EINVAL;329		}330		if (mcfg->rx_comparison_enable_mode) {331			reg_val_MCR = readl(msp->registers + MSP_MCR);332			writel(reg_val_MCR |333				(mcfg->rx_comparison_enable_mode << RCMPM_BIT),334				msp->registers + MSP_MCR);335 336			writel(mcfg->comparison_mask,337					msp->registers + MSP_RCM);338			writel(mcfg->comparison_value,339					msp->registers + MSP_RCV);340 341		}342	}343 344	return 0;345}346 347static int enable_msp(struct ux500_msp *msp, struct ux500_msp_config *config)348{349	int status = 0;350	u32 reg_val_DMACR, reg_val_GCR;351 352	/* Configure msp with protocol dependent settings */353	configure_protocol(msp, config);354	setup_bitclk(msp, config);355	if (config->multichannel_configured == 1) {356		status = configure_multichannel(msp, config);357		if (status)358			dev_warn(msp->dev,359				"%s: WARN: configure_multichannel failed (%d)!\n",360				__func__, status);361	}362 363	reg_val_DMACR = readl(msp->registers + MSP_DMACR);364	if (config->direction & MSP_DIR_RX)365		reg_val_DMACR |= RX_DMA_ENABLE;366	if (config->direction & MSP_DIR_TX)367		reg_val_DMACR |= TX_DMA_ENABLE;368	writel(reg_val_DMACR, msp->registers + MSP_DMACR);369 370	writel(config->iodelay, msp->registers + MSP_IODLY);371 372	/* Enable frame generation logic */373	reg_val_GCR = readl(msp->registers + MSP_GCR);374	writel(reg_val_GCR | FRAME_GEN_ENABLE, msp->registers + MSP_GCR);375 376	return status;377}378 379static void flush_fifo_rx(struct ux500_msp *msp)380{381	u32 reg_val_GCR, reg_val_FLR;382	u32 limit = 32;383 384	reg_val_GCR = readl(msp->registers + MSP_GCR);385	writel(reg_val_GCR | RX_ENABLE, msp->registers + MSP_GCR);386 387	reg_val_FLR = readl(msp->registers + MSP_FLR);388	while (!(reg_val_FLR & RX_FIFO_EMPTY) && limit--) {389		readl(msp->registers + MSP_DR);390		reg_val_FLR = readl(msp->registers + MSP_FLR);391	}392 393	writel(reg_val_GCR, msp->registers + MSP_GCR);394}395 396static void flush_fifo_tx(struct ux500_msp *msp)397{398	u32 reg_val_GCR, reg_val_FLR;399	u32 limit = 32;400 401	reg_val_GCR = readl(msp->registers + MSP_GCR);402	writel(reg_val_GCR | TX_ENABLE, msp->registers + MSP_GCR);403	writel(MSP_ITCR_ITEN | MSP_ITCR_TESTFIFO, msp->registers + MSP_ITCR);404 405	reg_val_FLR = readl(msp->registers + MSP_FLR);406	while (!(reg_val_FLR & TX_FIFO_EMPTY) && limit--) {407		readl(msp->registers + MSP_TSTDR);408		reg_val_FLR = readl(msp->registers + MSP_FLR);409	}410	writel(0x0, msp->registers + MSP_ITCR);411	writel(reg_val_GCR, msp->registers + MSP_GCR);412}413 414int ux500_msp_i2s_open(struct ux500_msp *msp,415		struct ux500_msp_config *config)416{417	u32 old_reg, new_reg, mask;418	int res;419	unsigned int tx_sel, rx_sel, tx_busy, rx_busy;420 421	if (in_interrupt()) {422		dev_err(msp->dev,423			"%s: ERROR: Open called in interrupt context!\n",424			__func__);425		return -1;426	}427 428	tx_sel = (config->direction & MSP_DIR_TX) > 0;429	rx_sel = (config->direction & MSP_DIR_RX) > 0;430	if (!tx_sel && !rx_sel) {431		dev_err(msp->dev, "%s: Error: No direction selected!\n",432			__func__);433		return -EINVAL;434	}435 436	tx_busy = (msp->dir_busy & MSP_DIR_TX) > 0;437	rx_busy = (msp->dir_busy & MSP_DIR_RX) > 0;438	if (tx_busy && tx_sel) {439		dev_err(msp->dev, "%s: Error: TX is in use!\n", __func__);440		return -EBUSY;441	}442	if (rx_busy && rx_sel) {443		dev_err(msp->dev, "%s: Error: RX is in use!\n", __func__);444		return -EBUSY;445	}446 447	msp->dir_busy |= (tx_sel ? MSP_DIR_TX : 0) | (rx_sel ? MSP_DIR_RX : 0);448 449	/* First do the global config register */450	mask = RX_CLK_SEL_MASK | TX_CLK_SEL_MASK | RX_FSYNC_MASK |451	    TX_FSYNC_MASK | RX_SYNC_SEL_MASK | TX_SYNC_SEL_MASK |452	    RX_FIFO_ENABLE_MASK | TX_FIFO_ENABLE_MASK | SRG_CLK_SEL_MASK |453	    LOOPBACK_MASK | TX_EXTRA_DELAY_MASK;454 455	new_reg = (config->tx_clk_sel | config->rx_clk_sel |456		config->rx_fsync_pol | config->tx_fsync_pol |457		config->rx_fsync_sel | config->tx_fsync_sel |458		config->rx_fifo_config | config->tx_fifo_config |459		config->srg_clk_sel | config->loopback_enable |460		config->tx_data_enable);461 462	old_reg = readl(msp->registers + MSP_GCR);463	old_reg &= ~mask;464	new_reg |= old_reg;465	writel(new_reg, msp->registers + MSP_GCR);466 467	res = enable_msp(msp, config);468	if (res < 0) {469		dev_err(msp->dev, "%s: ERROR: enable_msp failed (%d)!\n",470			__func__, res);471		return -EBUSY;472	}473	if (config->loopback_enable & 0x80)474		msp->loopback_enable = 1;475 476	/* Flush FIFOs */477	flush_fifo_tx(msp);478	flush_fifo_rx(msp);479 480	msp->msp_state = MSP_STATE_CONFIGURED;481	return 0;482}483 484static void disable_msp_rx(struct ux500_msp *msp)485{486	u32 reg_val_GCR, reg_val_DMACR, reg_val_IMSC;487 488	reg_val_GCR = readl(msp->registers + MSP_GCR);489	writel(reg_val_GCR & ~RX_ENABLE, msp->registers + MSP_GCR);490	reg_val_DMACR = readl(msp->registers + MSP_DMACR);491	writel(reg_val_DMACR & ~RX_DMA_ENABLE, msp->registers + MSP_DMACR);492	reg_val_IMSC = readl(msp->registers + MSP_IMSC);493	writel(reg_val_IMSC &494			~(RX_SERVICE_INT | RX_OVERRUN_ERROR_INT),495			msp->registers + MSP_IMSC);496 497	msp->dir_busy &= ~MSP_DIR_RX;498}499 500static void disable_msp_tx(struct ux500_msp *msp)501{502	u32 reg_val_GCR, reg_val_DMACR, reg_val_IMSC;503 504	reg_val_GCR = readl(msp->registers + MSP_GCR);505	writel(reg_val_GCR & ~TX_ENABLE, msp->registers + MSP_GCR);506	reg_val_DMACR = readl(msp->registers + MSP_DMACR);507	writel(reg_val_DMACR & ~TX_DMA_ENABLE, msp->registers + MSP_DMACR);508	reg_val_IMSC = readl(msp->registers + MSP_IMSC);509	writel(reg_val_IMSC &510			~(TX_SERVICE_INT | TX_UNDERRUN_ERR_INT),511			msp->registers + MSP_IMSC);512 513	msp->dir_busy &= ~MSP_DIR_TX;514}515 516static int disable_msp(struct ux500_msp *msp, unsigned int dir)517{518	u32 reg_val_GCR;519	unsigned int disable_tx, disable_rx;520 521	reg_val_GCR = readl(msp->registers + MSP_GCR);522	disable_tx = dir & MSP_DIR_TX;523	disable_rx = dir & MSP_DIR_TX;524	if (disable_tx && disable_rx) {525		reg_val_GCR = readl(msp->registers + MSP_GCR);526		writel(reg_val_GCR | LOOPBACK_MASK,527				msp->registers + MSP_GCR);528 529		/* Flush TX-FIFO */530		flush_fifo_tx(msp);531 532		/* Disable TX-channel */533		writel((readl(msp->registers + MSP_GCR) &534			       (~TX_ENABLE)), msp->registers + MSP_GCR);535 536		/* Flush RX-FIFO */537		flush_fifo_rx(msp);538 539		/* Disable Loopback and Receive channel */540		writel((readl(msp->registers + MSP_GCR) &541				(~(RX_ENABLE | LOOPBACK_MASK))),542				msp->registers + MSP_GCR);543 544		disable_msp_tx(msp);545		disable_msp_rx(msp);546	} else if (disable_tx)547		disable_msp_tx(msp);548	else if (disable_rx)549		disable_msp_rx(msp);550 551	return 0;552}553 554int ux500_msp_i2s_trigger(struct ux500_msp *msp, int cmd, int direction)555{556	u32 reg_val_GCR, enable_bit;557 558	if (msp->msp_state == MSP_STATE_IDLE) {559		dev_err(msp->dev, "%s: ERROR: MSP is not configured!\n",560			__func__);561		return -EINVAL;562	}563 564	switch (cmd) {565	case SNDRV_PCM_TRIGGER_START:566	case SNDRV_PCM_TRIGGER_RESUME:567	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:568		if (direction == SNDRV_PCM_STREAM_PLAYBACK)569			enable_bit = TX_ENABLE;570		else571			enable_bit = RX_ENABLE;572		reg_val_GCR = readl(msp->registers + MSP_GCR);573		writel(reg_val_GCR | enable_bit, msp->registers + MSP_GCR);574		break;575 576	case SNDRV_PCM_TRIGGER_STOP:577	case SNDRV_PCM_TRIGGER_SUSPEND:578	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:579		if (direction == SNDRV_PCM_STREAM_PLAYBACK)580			disable_msp_tx(msp);581		else582			disable_msp_rx(msp);583		break;584	default:585		return -EINVAL;586	}587 588	return 0;589}590 591int ux500_msp_i2s_close(struct ux500_msp *msp, unsigned int dir)592{593	int status = 0;594 595	dev_dbg(msp->dev, "%s: Enter (dir = 0x%01x).\n", __func__, dir);596 597	status = disable_msp(msp, dir);598	if (msp->dir_busy == 0) {599		/* disable sample rate and frame generators */600		msp->msp_state = MSP_STATE_IDLE;601		writel((readl(msp->registers + MSP_GCR) &602			       (~(FRAME_GEN_ENABLE | SRG_ENABLE))),603			      msp->registers + MSP_GCR);604 605		writel(0, msp->registers + MSP_GCR);606		writel(0, msp->registers + MSP_TCF);607		writel(0, msp->registers + MSP_RCF);608		writel(0, msp->registers + MSP_DMACR);609		writel(0, msp->registers + MSP_SRG);610		writel(0, msp->registers + MSP_MCR);611		writel(0, msp->registers + MSP_RCM);612		writel(0, msp->registers + MSP_RCV);613		writel(0, msp->registers + MSP_TCE0);614		writel(0, msp->registers + MSP_TCE1);615		writel(0, msp->registers + MSP_TCE2);616		writel(0, msp->registers + MSP_TCE3);617		writel(0, msp->registers + MSP_RCE0);618		writel(0, msp->registers + MSP_RCE1);619		writel(0, msp->registers + MSP_RCE2);620		writel(0, msp->registers + MSP_RCE3);621	}622 623	return status;624 625}626 627int ux500_msp_i2s_init_msp(struct platform_device *pdev,628			struct ux500_msp **msp_p)629{630	struct resource *res = NULL;631	struct ux500_msp *msp;632 633	*msp_p = devm_kzalloc(&pdev->dev, sizeof(struct ux500_msp), GFP_KERNEL);634	msp = *msp_p;635	if (!msp)636		return -ENOMEM;637 638	msp->dev = &pdev->dev;639 640	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);641	if (res == NULL) {642		dev_err(&pdev->dev, "%s: ERROR: Unable to get resource!\n",643			__func__);644		return -ENOMEM;645	}646 647	msp->tx_rx_addr = res->start + MSP_DR;648	msp->registers = devm_ioremap(&pdev->dev, res->start,649				      resource_size(res));650	if (msp->registers == NULL) {651		dev_err(&pdev->dev, "%s: ERROR: ioremap failed!\n", __func__);652		return -ENOMEM;653	}654 655	msp->msp_state = MSP_STATE_IDLE;656	msp->loopback_enable = 0;657 658	return 0;659}660 661void ux500_msp_i2s_cleanup_msp(struct platform_device *pdev,662			struct ux500_msp *msp)663{664	dev_dbg(msp->dev, "%s: Enter (id = %d).\n", __func__, msp->id);665}666 667MODULE_LICENSE("GPL v2");668