brintos

brintos / linux-shallow public Read only

0
0
Text · 41.7 KiB · 8f6deb0 Raw
1759 lines · c
1// SPDX-License-Identifier: GPL-2.02//3// ALSA SoC Audio Layer - Samsung I2S Controller driver4//5// Copyright (c) 2010 Samsung Electronics Co. Ltd.6//	Jaswinder Singh <jassisinghbrar@gmail.com>7 8#include <dt-bindings/sound/samsung-i2s.h>9#include <linux/delay.h>10#include <linux/slab.h>11#include <linux/clk.h>12#include <linux/clk-provider.h>13#include <linux/io.h>14#include <linux/module.h>15#include <linux/of.h>16#include <linux/pm_runtime.h>17 18#include <sound/soc.h>19#include <sound/pcm_params.h>20 21#include <linux/platform_data/asoc-s3c.h>22 23#include "dma.h"24#include "idma.h"25#include "i2s.h"26#include "i2s-regs.h"27 28#define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t)29 30#define SAMSUNG_I2S_ID_PRIMARY		131#define SAMSUNG_I2S_ID_SECONDARY	232 33struct samsung_i2s_variant_regs {34	unsigned int	bfs_off;35	unsigned int	rfs_off;36	unsigned int	sdf_off;37	unsigned int	txr_off;38	unsigned int	rclksrc_off;39	unsigned int	mss_off;40	unsigned int	cdclkcon_off;41	unsigned int	lrp_off;42	unsigned int	bfs_mask;43	unsigned int	rfs_mask;44	unsigned int	ftx0cnt_off;45};46 47struct samsung_i2s_dai_data {48	u32 quirks;49	unsigned int pcm_rates;50	const struct samsung_i2s_variant_regs *i2s_variant_regs;51	void (*fixup_early)(struct snd_pcm_substream *substream,52					struct snd_soc_dai *dai);53	void (*fixup_late)(struct snd_pcm_substream *substream,54					struct snd_soc_dai *dai);55};56 57struct i2s_dai {58	/* Platform device for this DAI */59	struct platform_device *pdev;60 61	/* Frame clock */62	unsigned frmclk;63	/*64	 * Specifically requested RCLK, BCLK by machine driver.65	 * 0 indicates CPU driver is free to choose any value.66	 */67	unsigned rfs, bfs;68	/* Pointer to the Primary_Fifo if this is Sec_Fifo, NULL otherwise */69	struct i2s_dai *pri_dai;70	/* Pointer to the Secondary_Fifo if it has one, NULL otherwise */71	struct i2s_dai *sec_dai;72 73#define DAI_OPENED	(1 << 0) /* DAI is opened */74#define DAI_MANAGER	(1 << 1) /* DAI is the manager */75	unsigned mode;76 77	/* Driver for this DAI */78	struct snd_soc_dai_driver *drv;79 80	/* DMA parameters */81	struct snd_dmaengine_dai_dma_data dma_playback;82	struct snd_dmaengine_dai_dma_data dma_capture;83	struct snd_dmaengine_dai_dma_data idma_playback;84	dma_filter_fn filter;85 86	struct samsung_i2s_priv *priv;87};88 89struct samsung_i2s_priv {90	struct platform_device *pdev;91	struct platform_device *pdev_sec;92 93	/* Lock for cross interface checks */94	spinlock_t pcm_lock;95 96	/* CPU DAIs and their corresponding drivers */97	struct i2s_dai *dai;98	struct snd_soc_dai_driver *dai_drv;99	int num_dais;100 101	/* The I2S controller's core clock */102	struct clk *clk;103 104	/* Clock for generating I2S signals */105	struct clk *op_clk;106 107	/* Rate of RCLK source clock */108	unsigned long rclk_srcrate;109 110	/* Cache of selected I2S registers for system suspend */111	u32 suspend_i2smod;112	u32 suspend_i2scon;113	u32 suspend_i2spsr;114 115	const struct samsung_i2s_variant_regs *variant_regs;116	void (*fixup_early)(struct snd_pcm_substream *substream,117						struct snd_soc_dai *dai);118	void (*fixup_late)(struct snd_pcm_substream *substream,119						struct snd_soc_dai *dai);120	u32 quirks;121 122	/* The clock provider's data */123	struct clk *clk_table[3];124	struct clk_onecell_data clk_data;125 126	/* Spinlock protecting member fields below */127	spinlock_t lock;128 129	/* Memory mapped SFR region */130	void __iomem *addr;131 132	/* A flag indicating the I2S slave mode operation */133	bool slave_mode;134};135 136/* Returns true if this is the 'overlay' stereo DAI */137static inline bool is_secondary(struct i2s_dai *i2s)138{139	return i2s->drv->id == SAMSUNG_I2S_ID_SECONDARY;140}141 142/* If this interface of the controller is transmitting data */143static inline bool tx_active(struct i2s_dai *i2s)144{145	u32 active;146 147	if (!i2s)148		return false;149 150	active = readl(i2s->priv->addr + I2SCON);151 152	if (is_secondary(i2s))153		active &= CON_TXSDMA_ACTIVE;154	else155		active &= CON_TXDMA_ACTIVE;156 157	return active ? true : false;158}159 160/* Return pointer to the other DAI */161static inline struct i2s_dai *get_other_dai(struct i2s_dai *i2s)162{163	return i2s->pri_dai ? : i2s->sec_dai;164}165 166/* If the other interface of the controller is transmitting data */167static inline bool other_tx_active(struct i2s_dai *i2s)168{169	struct i2s_dai *other = get_other_dai(i2s);170 171	return tx_active(other);172}173 174/* If any interface of the controller is transmitting data */175static inline bool any_tx_active(struct i2s_dai *i2s)176{177	return tx_active(i2s) || other_tx_active(i2s);178}179 180/* If this interface of the controller is receiving data */181static inline bool rx_active(struct i2s_dai *i2s)182{183	u32 active;184 185	if (!i2s)186		return false;187 188	active = readl(i2s->priv->addr + I2SCON) & CON_RXDMA_ACTIVE;189 190	return active ? true : false;191}192 193/* If the other interface of the controller is receiving data */194static inline bool other_rx_active(struct i2s_dai *i2s)195{196	struct i2s_dai *other = get_other_dai(i2s);197 198	return rx_active(other);199}200 201/* If any interface of the controller is receiving data */202static inline bool any_rx_active(struct i2s_dai *i2s)203{204	return rx_active(i2s) || other_rx_active(i2s);205}206 207/* If the other DAI is transmitting or receiving data */208static inline bool other_active(struct i2s_dai *i2s)209{210	return other_rx_active(i2s) || other_tx_active(i2s);211}212 213/* If this DAI is transmitting or receiving data */214static inline bool this_active(struct i2s_dai *i2s)215{216	return tx_active(i2s) || rx_active(i2s);217}218 219/* If the controller is active anyway */220static inline bool any_active(struct i2s_dai *i2s)221{222	return this_active(i2s) || other_active(i2s);223}224 225static inline struct i2s_dai *to_info(struct snd_soc_dai *dai)226{227	struct samsung_i2s_priv *priv = snd_soc_dai_get_drvdata(dai);228 229	return &priv->dai[dai->id - 1];230}231 232static inline bool is_opened(struct i2s_dai *i2s)233{234	if (i2s && (i2s->mode & DAI_OPENED))235		return true;236	else237		return false;238}239 240static inline bool is_manager(struct i2s_dai *i2s)241{242	if (is_opened(i2s) && (i2s->mode & DAI_MANAGER))243		return true;244	else245		return false;246}247 248/* Read RCLK of I2S (in multiples of LRCLK) */249static inline unsigned get_rfs(struct i2s_dai *i2s)250{251	struct samsung_i2s_priv *priv = i2s->priv;252	u32 rfs;253 254	rfs = readl(priv->addr + I2SMOD) >> priv->variant_regs->rfs_off;255	rfs &= priv->variant_regs->rfs_mask;256 257	switch (rfs) {258	case 7: return 192;259	case 6: return 96;260	case 5: return 128;261	case 4: return 64;262	case 3:	return 768;263	case 2: return 384;264	case 1:	return 512;265	default: return 256;266	}267}268 269/* Write RCLK of I2S (in multiples of LRCLK) */270static inline void set_rfs(struct i2s_dai *i2s, unsigned rfs)271{272	struct samsung_i2s_priv *priv = i2s->priv;273	u32 mod = readl(priv->addr + I2SMOD);274	int rfs_shift = priv->variant_regs->rfs_off;275 276	mod &= ~(priv->variant_regs->rfs_mask << rfs_shift);277 278	switch (rfs) {279	case 192:280		mod |= (EXYNOS7_MOD_RCLK_192FS << rfs_shift);281		break;282	case 96:283		mod |= (EXYNOS7_MOD_RCLK_96FS << rfs_shift);284		break;285	case 128:286		mod |= (EXYNOS7_MOD_RCLK_128FS << rfs_shift);287		break;288	case 64:289		mod |= (EXYNOS7_MOD_RCLK_64FS << rfs_shift);290		break;291	case 768:292		mod |= (MOD_RCLK_768FS << rfs_shift);293		break;294	case 512:295		mod |= (MOD_RCLK_512FS << rfs_shift);296		break;297	case 384:298		mod |= (MOD_RCLK_384FS << rfs_shift);299		break;300	default:301		mod |= (MOD_RCLK_256FS << rfs_shift);302		break;303	}304 305	writel(mod, priv->addr + I2SMOD);306}307 308/* Read bit-clock of I2S (in multiples of LRCLK) */309static inline unsigned get_bfs(struct i2s_dai *i2s)310{311	struct samsung_i2s_priv *priv = i2s->priv;312	u32 bfs;313 314	bfs = readl(priv->addr + I2SMOD) >> priv->variant_regs->bfs_off;315	bfs &= priv->variant_regs->bfs_mask;316 317	switch (bfs) {318	case 8: return 256;319	case 7: return 192;320	case 6: return 128;321	case 5: return 96;322	case 4: return 64;323	case 3: return 24;324	case 2: return 16;325	case 1:	return 48;326	default: return 32;327	}328}329 330/* Write bit-clock of I2S (in multiples of LRCLK) */331static inline void set_bfs(struct i2s_dai *i2s, unsigned bfs)332{333	struct samsung_i2s_priv *priv = i2s->priv;334	u32 mod = readl(priv->addr + I2SMOD);335	int tdm = priv->quirks & QUIRK_SUPPORTS_TDM;336	int bfs_shift = priv->variant_regs->bfs_off;337 338	/* Non-TDM I2S controllers do not support BCLK > 48 * FS */339	if (!tdm && bfs > 48) {340		dev_err(&i2s->pdev->dev, "Unsupported BCLK divider\n");341		return;342	}343 344	mod &= ~(priv->variant_regs->bfs_mask << bfs_shift);345 346	switch (bfs) {347	case 48:348		mod |= (MOD_BCLK_48FS << bfs_shift);349		break;350	case 32:351		mod |= (MOD_BCLK_32FS << bfs_shift);352		break;353	case 24:354		mod |= (MOD_BCLK_24FS << bfs_shift);355		break;356	case 16:357		mod |= (MOD_BCLK_16FS << bfs_shift);358		break;359	case 64:360		mod |= (EXYNOS5420_MOD_BCLK_64FS << bfs_shift);361		break;362	case 96:363		mod |= (EXYNOS5420_MOD_BCLK_96FS << bfs_shift);364		break;365	case 128:366		mod |= (EXYNOS5420_MOD_BCLK_128FS << bfs_shift);367		break;368	case 192:369		mod |= (EXYNOS5420_MOD_BCLK_192FS << bfs_shift);370		break;371	case 256:372		mod |= (EXYNOS5420_MOD_BCLK_256FS << bfs_shift);373		break;374	default:375		dev_err(&i2s->pdev->dev, "Wrong BCLK Divider!\n");376		return;377	}378 379	writel(mod, priv->addr + I2SMOD);380}381 382/* Sample size */383static inline int get_blc(struct i2s_dai *i2s)384{385	int blc = readl(i2s->priv->addr + I2SMOD);386 387	blc = (blc >> 13) & 0x3;388 389	switch (blc) {390	case 2: return 24;391	case 1:	return 8;392	default: return 16;393	}394}395 396/* TX channel control */397static void i2s_txctrl(struct i2s_dai *i2s, int on)398{399	struct samsung_i2s_priv *priv = i2s->priv;400	void __iomem *addr = priv->addr;401	int txr_off = priv->variant_regs->txr_off;402	u32 con = readl(addr + I2SCON);403	u32 mod = readl(addr + I2SMOD) & ~(3 << txr_off);404 405	if (on) {406		con |= CON_ACTIVE;407		con &= ~CON_TXCH_PAUSE;408 409		if (is_secondary(i2s)) {410			con |= CON_TXSDMA_ACTIVE;411			con &= ~CON_TXSDMA_PAUSE;412		} else {413			con |= CON_TXDMA_ACTIVE;414			con &= ~CON_TXDMA_PAUSE;415		}416 417		if (any_rx_active(i2s))418			mod |= 2 << txr_off;419		else420			mod |= 0 << txr_off;421	} else {422		if (is_secondary(i2s)) {423			con |=  CON_TXSDMA_PAUSE;424			con &= ~CON_TXSDMA_ACTIVE;425		} else {426			con |=  CON_TXDMA_PAUSE;427			con &= ~CON_TXDMA_ACTIVE;428		}429 430		if (other_tx_active(i2s)) {431			writel(con, addr + I2SCON);432			return;433		}434 435		con |=  CON_TXCH_PAUSE;436 437		if (any_rx_active(i2s))438			mod |= 1 << txr_off;439		else440			con &= ~CON_ACTIVE;441	}442 443	writel(mod, addr + I2SMOD);444	writel(con, addr + I2SCON);445}446 447/* RX Channel Control */448static void i2s_rxctrl(struct i2s_dai *i2s, int on)449{450	struct samsung_i2s_priv *priv = i2s->priv;451	void __iomem *addr = priv->addr;452	int txr_off = priv->variant_regs->txr_off;453	u32 con = readl(addr + I2SCON);454	u32 mod = readl(addr + I2SMOD) & ~(3 << txr_off);455 456	if (on) {457		con |= CON_RXDMA_ACTIVE | CON_ACTIVE;458		con &= ~(CON_RXDMA_PAUSE | CON_RXCH_PAUSE);459 460		if (any_tx_active(i2s))461			mod |= 2 << txr_off;462		else463			mod |= 1 << txr_off;464	} else {465		con |=  CON_RXDMA_PAUSE | CON_RXCH_PAUSE;466		con &= ~CON_RXDMA_ACTIVE;467 468		if (any_tx_active(i2s))469			mod |= 0 << txr_off;470		else471			con &= ~CON_ACTIVE;472	}473 474	writel(mod, addr + I2SMOD);475	writel(con, addr + I2SCON);476}477 478/* Flush FIFO of an interface */479static inline void i2s_fifo(struct i2s_dai *i2s, u32 flush)480{481	void __iomem *fic;482	u32 val;483 484	if (!i2s)485		return;486 487	if (is_secondary(i2s))488		fic = i2s->priv->addr + I2SFICS;489	else490		fic = i2s->priv->addr + I2SFIC;491 492	/* Flush the FIFO */493	writel(readl(fic) | flush, fic);494 495	/* Be patient */496	val = msecs_to_loops(1) / 1000; /* 1 usec */497	while (--val)498		cpu_relax();499 500	writel(readl(fic) & ~flush, fic);501}502 503static int i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id, unsigned int rfs,504			  int dir)505{506	struct samsung_i2s_priv *priv = snd_soc_dai_get_drvdata(dai);507	struct i2s_dai *i2s = to_info(dai);508	struct i2s_dai *other = get_other_dai(i2s);509	const struct samsung_i2s_variant_regs *i2s_regs = priv->variant_regs;510	unsigned int cdcon_mask = 1 << i2s_regs->cdclkcon_off;511	unsigned int rsrc_mask = 1 << i2s_regs->rclksrc_off;512	u32 mod, mask, val = 0;513	unsigned long flags;514	int ret = 0;515 516	pm_runtime_get_sync(dai->dev);517 518	spin_lock_irqsave(&priv->lock, flags);519	mod = readl(priv->addr + I2SMOD);520	spin_unlock_irqrestore(&priv->lock, flags);521 522	switch (clk_id) {523	case SAMSUNG_I2S_OPCLK:524		mask = MOD_OPCLK_MASK;525		val = (dir << MOD_OPCLK_SHIFT) & MOD_OPCLK_MASK;526		break;527	case SAMSUNG_I2S_CDCLK:528		mask = 1 << i2s_regs->cdclkcon_off;529		/* Shouldn't matter in GATING(CLOCK_IN) mode */530		if (dir == SND_SOC_CLOCK_IN)531			rfs = 0;532 533		if ((rfs && other && other->rfs && (other->rfs != rfs)) ||534				(any_active(i2s) &&535				(((dir == SND_SOC_CLOCK_IN)536					&& !(mod & cdcon_mask)) ||537				((dir == SND_SOC_CLOCK_OUT)538					&& (mod & cdcon_mask))))) {539			dev_err(&i2s->pdev->dev,540				"%s:%d Other DAI busy\n", __func__, __LINE__);541			ret = -EAGAIN;542			goto err;543		}544 545		if (dir == SND_SOC_CLOCK_IN)546			val = 1 << i2s_regs->cdclkcon_off;547 548		i2s->rfs = rfs;549		break;550 551	case SAMSUNG_I2S_RCLKSRC_0: /* clock corrsponding to IISMOD[10] := 0 */552	case SAMSUNG_I2S_RCLKSRC_1: /* clock corrsponding to IISMOD[10] := 1 */553		mask = 1 << i2s_regs->rclksrc_off;554 555		if ((priv->quirks & QUIRK_NO_MUXPSR)556				|| (clk_id == SAMSUNG_I2S_RCLKSRC_0))557			clk_id = 0;558		else559			clk_id = 1;560 561		if (!any_active(i2s)) {562			if (priv->op_clk && !IS_ERR(priv->op_clk)) {563				if ((clk_id && !(mod & rsrc_mask)) ||564					(!clk_id && (mod & rsrc_mask))) {565					clk_disable_unprepare(priv->op_clk);566					clk_put(priv->op_clk);567				} else {568					priv->rclk_srcrate =569						clk_get_rate(priv->op_clk);570					goto done;571				}572			}573 574			if (clk_id)575				priv->op_clk = clk_get(&i2s->pdev->dev,576						"i2s_opclk1");577			else578				priv->op_clk = clk_get(&i2s->pdev->dev,579						"i2s_opclk0");580 581			if (WARN_ON(IS_ERR(priv->op_clk))) {582				ret = PTR_ERR(priv->op_clk);583				priv->op_clk = NULL;584				goto err;585			}586 587			ret = clk_prepare_enable(priv->op_clk);588			if (ret) {589				clk_put(priv->op_clk);590				priv->op_clk = NULL;591				goto err;592			}593			priv->rclk_srcrate = clk_get_rate(priv->op_clk);594 595		} else if ((!clk_id && (mod & rsrc_mask))596				|| (clk_id && !(mod & rsrc_mask))) {597			dev_err(&i2s->pdev->dev,598				"%s:%d Other DAI busy\n", __func__, __LINE__);599			ret = -EAGAIN;600			goto err;601		} else {602			/* Call can't be on the active DAI */603			goto done;604		}605 606		if (clk_id == 1)607			val = 1 << i2s_regs->rclksrc_off;608		break;609	default:610		dev_err(&i2s->pdev->dev, "We don't serve that!\n");611		ret = -EINVAL;612		goto err;613	}614 615	spin_lock_irqsave(&priv->lock, flags);616	mod = readl(priv->addr + I2SMOD);617	mod = (mod & ~mask) | val;618	writel(mod, priv->addr + I2SMOD);619	spin_unlock_irqrestore(&priv->lock, flags);620done:621	pm_runtime_put(dai->dev);622 623	return 0;624err:625	pm_runtime_put(dai->dev);626	return ret;627}628 629static int i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)630{631	struct samsung_i2s_priv *priv = snd_soc_dai_get_drvdata(dai);632	struct i2s_dai *i2s = to_info(dai);633	int lrp_shift, sdf_shift, sdf_mask, lrp_rlow, mod_slave;634	u32 mod, tmp = 0;635	unsigned long flags;636 637	lrp_shift = priv->variant_regs->lrp_off;638	sdf_shift = priv->variant_regs->sdf_off;639	mod_slave = 1 << priv->variant_regs->mss_off;640 641	sdf_mask = MOD_SDF_MASK << sdf_shift;642	lrp_rlow = MOD_LR_RLOW << lrp_shift;643 644	/* Format is priority */645	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {646	case SND_SOC_DAIFMT_RIGHT_J:647		tmp |= lrp_rlow;648		tmp |= (MOD_SDF_MSB << sdf_shift);649		break;650	case SND_SOC_DAIFMT_LEFT_J:651		tmp |= lrp_rlow;652		tmp |= (MOD_SDF_LSB << sdf_shift);653		break;654	case SND_SOC_DAIFMT_I2S:655		tmp |= (MOD_SDF_IIS << sdf_shift);656		break;657	default:658		dev_err(&i2s->pdev->dev, "Format not supported\n");659		return -EINVAL;660	}661 662	/*663	 * INV flag is relative to the FORMAT flag - if set it simply664	 * flips the polarity specified by the Standard665	 */666	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {667	case SND_SOC_DAIFMT_NB_NF:668		break;669	case SND_SOC_DAIFMT_NB_IF:670		if (tmp & lrp_rlow)671			tmp &= ~lrp_rlow;672		else673			tmp |= lrp_rlow;674		break;675	default:676		dev_err(&i2s->pdev->dev, "Polarity not supported\n");677		return -EINVAL;678	}679 680	switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {681	case SND_SOC_DAIFMT_BC_FC:682		tmp |= mod_slave;683		break;684	case SND_SOC_DAIFMT_BP_FP:685		/*686		 * Set default source clock in Master mode, only when the687		 * CLK_I2S_RCLK_SRC clock is not exposed so we ensure any688		 * clock configuration assigned in DT is not overwritten.689		 */690		if (priv->rclk_srcrate == 0 && priv->clk_data.clks == NULL)691			i2s_set_sysclk(dai, SAMSUNG_I2S_RCLKSRC_0,692							0, SND_SOC_CLOCK_IN);693		break;694	default:695		dev_err(&i2s->pdev->dev, "master/slave format not supported\n");696		return -EINVAL;697	}698 699	pm_runtime_get_sync(dai->dev);700	spin_lock_irqsave(&priv->lock, flags);701	mod = readl(priv->addr + I2SMOD);702	/*703	 * Don't change the I2S mode if any controller is active on this704	 * channel.705	 */706	if (any_active(i2s) &&707		((mod & (sdf_mask | lrp_rlow | mod_slave)) != tmp)) {708		spin_unlock_irqrestore(&priv->lock, flags);709		pm_runtime_put(dai->dev);710		dev_err(&i2s->pdev->dev,711				"%s:%d Other DAI busy\n", __func__, __LINE__);712		return -EAGAIN;713	}714 715	mod &= ~(sdf_mask | lrp_rlow | mod_slave);716	mod |= tmp;717	writel(mod, priv->addr + I2SMOD);718	priv->slave_mode = (mod & mod_slave);719	spin_unlock_irqrestore(&priv->lock, flags);720	pm_runtime_put(dai->dev);721 722	return 0;723}724 725static int i2s_hw_params(struct snd_pcm_substream *substream,726	struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)727{728	struct samsung_i2s_priv *priv = snd_soc_dai_get_drvdata(dai);729	struct i2s_dai *i2s = to_info(dai);730	u32 mod, mask = 0, val = 0;731	struct clk *rclksrc;732	unsigned long flags;733 734	WARN_ON(!pm_runtime_active(dai->dev));735 736	if (!is_secondary(i2s))737		mask |= (MOD_DC2_EN | MOD_DC1_EN);738 739	switch (params_channels(params)) {740	case 6:741		val |= MOD_DC2_EN;742		fallthrough;743	case 4:744		val |= MOD_DC1_EN;745		break;746	case 2:747		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)748			i2s->dma_playback.addr_width = 4;749		else750			i2s->dma_capture.addr_width = 4;751		break;752	case 1:753		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)754			i2s->dma_playback.addr_width = 2;755		else756			i2s->dma_capture.addr_width = 2;757 758		break;759	default:760		dev_err(&i2s->pdev->dev, "%d channels not supported\n",761				params_channels(params));762		return -EINVAL;763	}764 765	if (is_secondary(i2s))766		mask |= MOD_BLCS_MASK;767	else768		mask |= MOD_BLCP_MASK;769 770	if (is_manager(i2s))771		mask |= MOD_BLC_MASK;772 773	switch (params_width(params)) {774	case 8:775		if (is_secondary(i2s))776			val |= MOD_BLCS_8BIT;777		else778			val |= MOD_BLCP_8BIT;779		if (is_manager(i2s))780			val |= MOD_BLC_8BIT;781		break;782	case 16:783		if (is_secondary(i2s))784			val |= MOD_BLCS_16BIT;785		else786			val |= MOD_BLCP_16BIT;787		if (is_manager(i2s))788			val |= MOD_BLC_16BIT;789		break;790	case 24:791		if (is_secondary(i2s))792			val |= MOD_BLCS_24BIT;793		else794			val |= MOD_BLCP_24BIT;795		if (is_manager(i2s))796			val |= MOD_BLC_24BIT;797		break;798	default:799		dev_err(&i2s->pdev->dev, "Format(%d) not supported\n",800				params_format(params));801		return -EINVAL;802	}803 804	spin_lock_irqsave(&priv->lock, flags);805	mod = readl(priv->addr + I2SMOD);806	mod = (mod & ~mask) | val;807	writel(mod, priv->addr + I2SMOD);808	spin_unlock_irqrestore(&priv->lock, flags);809 810	snd_soc_dai_init_dma_data(dai, &i2s->dma_playback, &i2s->dma_capture);811 812	i2s->frmclk = params_rate(params);813 814	rclksrc = priv->clk_table[CLK_I2S_RCLK_SRC];815	if (rclksrc && !IS_ERR(rclksrc))816		priv->rclk_srcrate = clk_get_rate(rclksrc);817 818	return 0;819}820 821/* We set constraints on the substream according to the version of I2S */822static int i2s_startup(struct snd_pcm_substream *substream,823	  struct snd_soc_dai *dai)824{825	struct samsung_i2s_priv *priv = snd_soc_dai_get_drvdata(dai);826	struct i2s_dai *i2s = to_info(dai);827	struct i2s_dai *other = get_other_dai(i2s);828	unsigned long flags;829 830	pm_runtime_get_sync(dai->dev);831 832	spin_lock_irqsave(&priv->pcm_lock, flags);833 834	i2s->mode |= DAI_OPENED;835 836	if (is_manager(other))837		i2s->mode &= ~DAI_MANAGER;838	else839		i2s->mode |= DAI_MANAGER;840 841	if (!any_active(i2s) && (priv->quirks & QUIRK_NEED_RSTCLR))842		writel(CON_RSTCLR, i2s->priv->addr + I2SCON);843 844	spin_unlock_irqrestore(&priv->pcm_lock, flags);845 846	return 0;847}848 849static void i2s_shutdown(struct snd_pcm_substream *substream,850	struct snd_soc_dai *dai)851{852	struct samsung_i2s_priv *priv = snd_soc_dai_get_drvdata(dai);853	struct i2s_dai *i2s = to_info(dai);854	struct i2s_dai *other = get_other_dai(i2s);855	unsigned long flags;856 857	spin_lock_irqsave(&priv->pcm_lock, flags);858 859	i2s->mode &= ~DAI_OPENED;860	i2s->mode &= ~DAI_MANAGER;861 862	if (is_opened(other))863		other->mode |= DAI_MANAGER;864 865	/* Reset any constraint on RFS and BFS */866	i2s->rfs = 0;867	i2s->bfs = 0;868 869	spin_unlock_irqrestore(&priv->pcm_lock, flags);870 871	pm_runtime_put(dai->dev);872}873 874static int config_setup(struct i2s_dai *i2s)875{876	struct samsung_i2s_priv *priv = i2s->priv;877	struct i2s_dai *other = get_other_dai(i2s);878	unsigned rfs, bfs, blc;879	u32 psr;880 881	blc = get_blc(i2s);882 883	bfs = i2s->bfs;884 885	if (!bfs && other)886		bfs = other->bfs;887 888	/* Select least possible multiple(2) if no constraint set */889	if (!bfs)890		bfs = blc * 2;891 892	rfs = i2s->rfs;893 894	if (!rfs && other)895		rfs = other->rfs;896 897	if ((rfs == 256 || rfs == 512) && (blc == 24)) {898		dev_err(&i2s->pdev->dev,899			"%d-RFS not supported for 24-blc\n", rfs);900		return -EINVAL;901	}902 903	if (!rfs) {904		if (bfs == 16 || bfs == 32)905			rfs = 256;906		else907			rfs = 384;908	}909 910	/* If already setup and running */911	if (any_active(i2s) && (get_rfs(i2s) != rfs || get_bfs(i2s) != bfs)) {912		dev_err(&i2s->pdev->dev,913				"%s:%d Other DAI busy\n", __func__, __LINE__);914		return -EAGAIN;915	}916 917	set_bfs(i2s, bfs);918	set_rfs(i2s, rfs);919 920	/* Don't bother with PSR in Slave mode */921	if (priv->slave_mode)922		return 0;923 924	if (!(priv->quirks & QUIRK_NO_MUXPSR)) {925		psr = priv->rclk_srcrate / i2s->frmclk / rfs;926		writel(((psr - 1) << 8) | PSR_PSREN, priv->addr + I2SPSR);927		dev_dbg(&i2s->pdev->dev,928			"RCLK_SRC=%luHz PSR=%u, RCLK=%dfs, BCLK=%dfs\n",929				priv->rclk_srcrate, psr, rfs, bfs);930	}931 932	return 0;933}934 935static int i2s_trigger(struct snd_pcm_substream *substream,936	int cmd, struct snd_soc_dai *dai)937{938	struct samsung_i2s_priv *priv = snd_soc_dai_get_drvdata(dai);939	int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE);940	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);941	struct i2s_dai *i2s = to_info(snd_soc_rtd_to_cpu(rtd, 0));942	unsigned long flags;943 944	switch (cmd) {945	case SNDRV_PCM_TRIGGER_START:946	case SNDRV_PCM_TRIGGER_RESUME:947	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:948		pm_runtime_get_sync(dai->dev);949 950		if (priv->fixup_early)951			priv->fixup_early(substream, dai);952 953		spin_lock_irqsave(&priv->lock, flags);954 955		if (config_setup(i2s)) {956			spin_unlock_irqrestore(&priv->lock, flags);957			return -EINVAL;958		}959 960		if (priv->fixup_late)961			priv->fixup_late(substream, dai);962 963		if (capture)964			i2s_rxctrl(i2s, 1);965		else966			i2s_txctrl(i2s, 1);967 968		spin_unlock_irqrestore(&priv->lock, flags);969		break;970	case SNDRV_PCM_TRIGGER_STOP:971	case SNDRV_PCM_TRIGGER_SUSPEND:972	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:973		spin_lock_irqsave(&priv->lock, flags);974 975		if (capture) {976			i2s_rxctrl(i2s, 0);977			i2s_fifo(i2s, FIC_RXFLUSH);978		} else {979			i2s_txctrl(i2s, 0);980			i2s_fifo(i2s, FIC_TXFLUSH);981		}982 983		spin_unlock_irqrestore(&priv->lock, flags);984		pm_runtime_put(dai->dev);985		break;986	}987 988	return 0;989}990 991static int i2s_set_clkdiv(struct snd_soc_dai *dai,992	int div_id, int div)993{994	struct i2s_dai *i2s = to_info(dai);995	struct i2s_dai *other = get_other_dai(i2s);996 997	switch (div_id) {998	case SAMSUNG_I2S_DIV_BCLK:999		pm_runtime_get_sync(dai->dev);1000		if ((any_active(i2s) && div && (get_bfs(i2s) != div))1001			|| (other && other->bfs && (other->bfs != div))) {1002			pm_runtime_put(dai->dev);1003			dev_err(&i2s->pdev->dev,1004				"%s:%d Other DAI busy\n", __func__, __LINE__);1005			return -EAGAIN;1006		}1007		i2s->bfs = div;1008		pm_runtime_put(dai->dev);1009		break;1010	default:1011		dev_err(&i2s->pdev->dev,1012			"Invalid clock divider(%d)\n", div_id);1013		return -EINVAL;1014	}1015 1016	return 0;1017}1018 1019static snd_pcm_sframes_t1020i2s_delay(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)1021{1022	struct samsung_i2s_priv *priv = snd_soc_dai_get_drvdata(dai);1023	struct i2s_dai *i2s = to_info(dai);1024	u32 reg = readl(priv->addr + I2SFIC);1025	snd_pcm_sframes_t delay;1026 1027	WARN_ON(!pm_runtime_active(dai->dev));1028 1029	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)1030		delay = FIC_RXCOUNT(reg);1031	else if (is_secondary(i2s))1032		delay = FICS_TXCOUNT(readl(priv->addr + I2SFICS));1033	else1034		delay = (reg >> priv->variant_regs->ftx0cnt_off) & 0x7f;1035 1036	return delay;1037}1038 1039#ifdef CONFIG_PM1040static int i2s_suspend(struct snd_soc_component *component)1041{1042	return pm_runtime_force_suspend(component->dev);1043}1044 1045static int i2s_resume(struct snd_soc_component *component)1046{1047	return pm_runtime_force_resume(component->dev);1048}1049#else1050#define i2s_suspend NULL1051#define i2s_resume  NULL1052#endif1053 1054static int samsung_i2s_dai_probe(struct snd_soc_dai *dai)1055{1056	struct samsung_i2s_priv *priv = snd_soc_dai_get_drvdata(dai);1057	struct i2s_dai *i2s = to_info(dai);1058	struct i2s_dai *other = get_other_dai(i2s);1059	unsigned long flags;1060 1061	pm_runtime_get_sync(dai->dev);1062 1063	if (is_secondary(i2s)) {1064		/* If this is probe on the secondary DAI */1065		snd_soc_dai_init_dma_data(dai, &i2s->dma_playback, NULL);1066	} else {1067		snd_soc_dai_init_dma_data(dai, &i2s->dma_playback,1068					  &i2s->dma_capture);1069 1070		if (priv->quirks & QUIRK_NEED_RSTCLR)1071			writel(CON_RSTCLR, priv->addr + I2SCON);1072 1073		if (priv->quirks & QUIRK_SUPPORTS_IDMA)1074			idma_reg_addr_init(priv->addr,1075					   other->idma_playback.addr);1076	}1077 1078	/* Reset any constraint on RFS and BFS */1079	i2s->rfs = 0;1080	i2s->bfs = 0;1081 1082	spin_lock_irqsave(&priv->lock, flags);1083	i2s_txctrl(i2s, 0);1084	i2s_rxctrl(i2s, 0);1085	i2s_fifo(i2s, FIC_TXFLUSH);1086	i2s_fifo(other, FIC_TXFLUSH);1087	i2s_fifo(i2s, FIC_RXFLUSH);1088	spin_unlock_irqrestore(&priv->lock, flags);1089 1090	/* Gate CDCLK by default */1091	if (!is_opened(other))1092		i2s_set_sysclk(dai, SAMSUNG_I2S_CDCLK,1093				0, SND_SOC_CLOCK_IN);1094	pm_runtime_put(dai->dev);1095 1096	return 0;1097}1098 1099static int samsung_i2s_dai_remove(struct snd_soc_dai *dai)1100{1101	struct samsung_i2s_priv *priv = snd_soc_dai_get_drvdata(dai);1102	struct i2s_dai *i2s = to_info(dai);1103	unsigned long flags;1104 1105	pm_runtime_get_sync(dai->dev);1106 1107	if (!is_secondary(i2s)) {1108		if (priv->quirks & QUIRK_NEED_RSTCLR) {1109			spin_lock_irqsave(&priv->lock, flags);1110			writel(0, priv->addr + I2SCON);1111			spin_unlock_irqrestore(&priv->lock, flags);1112		}1113	}1114 1115	pm_runtime_put(dai->dev);1116 1117	return 0;1118}1119 1120static const struct snd_soc_dai_ops samsung_i2s_dai_ops = {1121	.probe = samsung_i2s_dai_probe,1122	.remove = samsung_i2s_dai_remove,1123	.trigger = i2s_trigger,1124	.hw_params = i2s_hw_params,1125	.set_fmt = i2s_set_fmt,1126	.set_clkdiv = i2s_set_clkdiv,1127	.set_sysclk = i2s_set_sysclk,1128	.startup = i2s_startup,1129	.shutdown = i2s_shutdown,1130	.delay = i2s_delay,1131};1132 1133static const struct snd_soc_dapm_widget samsung_i2s_widgets[] = {1134	/* Backend DAI  */1135	SND_SOC_DAPM_AIF_OUT("Mixer DAI TX", NULL, 0, SND_SOC_NOPM, 0, 0),1136	SND_SOC_DAPM_AIF_IN("Mixer DAI RX", NULL, 0, SND_SOC_NOPM, 0, 0),1137 1138	/* Playback Mixer */1139	SND_SOC_DAPM_MIXER("Playback Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),1140};1141 1142static const struct snd_soc_dapm_route samsung_i2s_dapm_routes[] = {1143	{ "Playback Mixer", NULL, "Primary Playback" },1144	{ "Playback Mixer", NULL, "Secondary Playback" },1145 1146	{ "Mixer DAI TX", NULL, "Playback Mixer" },1147	{ "Primary Capture", NULL, "Mixer DAI RX" },1148};1149 1150static const struct snd_soc_component_driver samsung_i2s_component = {1151	.name = "samsung-i2s",1152 1153	.dapm_widgets = samsung_i2s_widgets,1154	.num_dapm_widgets = ARRAY_SIZE(samsung_i2s_widgets),1155 1156	.dapm_routes = samsung_i2s_dapm_routes,1157	.num_dapm_routes = ARRAY_SIZE(samsung_i2s_dapm_routes),1158 1159	.suspend = i2s_suspend,1160	.resume = i2s_resume,1161 1162	.legacy_dai_naming = 1,1163};1164 1165#define SAMSUNG_I2S_FMTS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | \1166			  SNDRV_PCM_FMTBIT_S24_LE)1167 1168static int i2s_alloc_dais(struct samsung_i2s_priv *priv,1169			  const struct samsung_i2s_dai_data *i2s_dai_data,1170			  int num_dais)1171{1172	static const char *dai_names[] = { "samsung-i2s", "samsung-i2s-sec" };1173	static const char *stream_names[] = { "Primary Playback",1174					      "Secondary Playback" };1175	struct snd_soc_dai_driver *dai_drv;1176	int i;1177 1178	priv->dai = devm_kcalloc(&priv->pdev->dev, num_dais,1179				     sizeof(struct i2s_dai), GFP_KERNEL);1180	if (!priv->dai)1181		return -ENOMEM;1182 1183	priv->dai_drv = devm_kcalloc(&priv->pdev->dev, num_dais,1184				     sizeof(*dai_drv), GFP_KERNEL);1185	if (!priv->dai_drv)1186		return -ENOMEM;1187 1188	for (i = 0; i < num_dais; i++) {1189		dai_drv = &priv->dai_drv[i];1190 1191		dai_drv->symmetric_rate = 1;1192		dai_drv->ops = &samsung_i2s_dai_ops;1193 1194		dai_drv->playback.channels_min = 1;1195		dai_drv->playback.channels_max = 2;1196		dai_drv->playback.rates = i2s_dai_data->pcm_rates;1197		dai_drv->playback.formats = SAMSUNG_I2S_FMTS;1198		dai_drv->playback.stream_name = stream_names[i];1199 1200		dai_drv->id = i + 1;1201		dai_drv->name = dai_names[i];1202 1203		priv->dai[i].drv = &priv->dai_drv[i];1204		priv->dai[i].pdev = priv->pdev;1205	}1206 1207	/* Initialize capture only for the primary DAI */1208	dai_drv = &priv->dai_drv[SAMSUNG_I2S_ID_PRIMARY - 1];1209 1210	dai_drv->capture.channels_min = 1;1211	dai_drv->capture.channels_max = 2;1212	dai_drv->capture.rates = i2s_dai_data->pcm_rates;1213	dai_drv->capture.formats = SAMSUNG_I2S_FMTS;1214	dai_drv->capture.stream_name = "Primary Capture";1215 1216	return 0;1217}1218 1219#ifdef CONFIG_PM1220static int i2s_runtime_suspend(struct device *dev)1221{1222	struct samsung_i2s_priv *priv = dev_get_drvdata(dev);1223 1224	priv->suspend_i2smod = readl(priv->addr + I2SMOD);1225	priv->suspend_i2scon = readl(priv->addr + I2SCON);1226	priv->suspend_i2spsr = readl(priv->addr + I2SPSR);1227 1228	clk_disable_unprepare(priv->op_clk);1229	clk_disable_unprepare(priv->clk);1230 1231	return 0;1232}1233 1234static int i2s_runtime_resume(struct device *dev)1235{1236	struct samsung_i2s_priv *priv = dev_get_drvdata(dev);1237	int ret;1238 1239	ret = clk_prepare_enable(priv->clk);1240	if (ret)1241		return ret;1242 1243	if (priv->op_clk) {1244		ret = clk_prepare_enable(priv->op_clk);1245		if (ret) {1246			clk_disable_unprepare(priv->clk);1247			return ret;1248		}1249	}1250 1251	writel(priv->suspend_i2scon, priv->addr + I2SCON);1252	writel(priv->suspend_i2smod, priv->addr + I2SMOD);1253	writel(priv->suspend_i2spsr, priv->addr + I2SPSR);1254 1255	return 0;1256}1257#endif /* CONFIG_PM */1258 1259static void i2s_unregister_clocks(struct samsung_i2s_priv *priv)1260{1261	int i;1262 1263	for (i = 0; i < priv->clk_data.clk_num; i++) {1264		if (!IS_ERR(priv->clk_table[i]))1265			clk_unregister(priv->clk_table[i]);1266	}1267}1268 1269static void i2s_unregister_clock_provider(struct samsung_i2s_priv *priv)1270{1271	of_clk_del_provider(priv->pdev->dev.of_node);1272	i2s_unregister_clocks(priv);1273}1274 1275 1276static int i2s_register_clock_provider(struct samsung_i2s_priv *priv)1277{1278 1279	const char * const i2s_clk_desc[] = { "cdclk", "rclk_src", "prescaler" };1280	const char *clk_name[2] = { "i2s_opclk0", "i2s_opclk1" };1281	const char *p_names[2] = { NULL };1282	struct device *dev = &priv->pdev->dev;1283	const struct samsung_i2s_variant_regs *reg_info = priv->variant_regs;1284	const char *i2s_clk_name[ARRAY_SIZE(i2s_clk_desc)];1285	struct clk *rclksrc;1286	int ret, i;1287 1288	/* Register the clock provider only if it's expected in the DTB */1289	if (!of_property_present(dev->of_node, "#clock-cells"))1290		return 0;1291 1292	/* Get the RCLKSRC mux clock parent clock names */1293	for (i = 0; i < ARRAY_SIZE(p_names); i++) {1294		rclksrc = clk_get(dev, clk_name[i]);1295		if (IS_ERR(rclksrc))1296			continue;1297		p_names[i] = __clk_get_name(rclksrc);1298		clk_put(rclksrc);1299	}1300 1301	for (i = 0; i < ARRAY_SIZE(i2s_clk_desc); i++) {1302		i2s_clk_name[i] = devm_kasprintf(dev, GFP_KERNEL, "%s_%s",1303						dev_name(dev), i2s_clk_desc[i]);1304		if (!i2s_clk_name[i])1305			return -ENOMEM;1306	}1307 1308	if (!(priv->quirks & QUIRK_NO_MUXPSR)) {1309		/* Activate the prescaler */1310		u32 val = readl(priv->addr + I2SPSR);1311		writel(val | PSR_PSREN, priv->addr + I2SPSR);1312 1313		priv->clk_table[CLK_I2S_RCLK_SRC] = clk_register_mux(dev,1314				i2s_clk_name[CLK_I2S_RCLK_SRC], p_names,1315				ARRAY_SIZE(p_names),1316				CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT,1317				priv->addr + I2SMOD, reg_info->rclksrc_off,1318				1, 0, &priv->lock);1319 1320		priv->clk_table[CLK_I2S_RCLK_PSR] = clk_register_divider(dev,1321				i2s_clk_name[CLK_I2S_RCLK_PSR],1322				i2s_clk_name[CLK_I2S_RCLK_SRC],1323				CLK_SET_RATE_PARENT,1324				priv->addr + I2SPSR, 8, 6, 0, &priv->lock);1325 1326		p_names[0] = i2s_clk_name[CLK_I2S_RCLK_PSR];1327		priv->clk_data.clk_num = 2;1328	}1329 1330	priv->clk_table[CLK_I2S_CDCLK] = clk_register_gate(dev,1331				i2s_clk_name[CLK_I2S_CDCLK], p_names[0],1332				CLK_SET_RATE_PARENT,1333				priv->addr + I2SMOD, reg_info->cdclkcon_off,1334				CLK_GATE_SET_TO_DISABLE, &priv->lock);1335 1336	priv->clk_data.clk_num += 1;1337	priv->clk_data.clks = priv->clk_table;1338 1339	ret = of_clk_add_provider(dev->of_node, of_clk_src_onecell_get,1340				  &priv->clk_data);1341	if (ret < 0) {1342		dev_err(dev, "failed to add clock provider: %d\n", ret);1343		i2s_unregister_clocks(priv);1344	}1345 1346	return ret;1347}1348 1349/* Create platform device for the secondary PCM */1350static int i2s_create_secondary_device(struct samsung_i2s_priv *priv)1351{1352	struct platform_device *pdev_sec;1353	const char *devname;1354	int ret;1355 1356	devname = devm_kasprintf(&priv->pdev->dev, GFP_KERNEL, "%s-sec",1357				 dev_name(&priv->pdev->dev));1358	if (!devname)1359		return -ENOMEM;1360 1361	pdev_sec = platform_device_alloc(devname, -1);1362	if (!pdev_sec)1363		return -ENOMEM;1364 1365	pdev_sec->driver_override = kstrdup("samsung-i2s", GFP_KERNEL);1366	if (!pdev_sec->driver_override) {1367		platform_device_put(pdev_sec);1368		return -ENOMEM;1369	}1370 1371	ret = platform_device_add(pdev_sec);1372	if (ret < 0) {1373		platform_device_put(pdev_sec);1374		return ret;1375	}1376 1377	ret = device_attach(&pdev_sec->dev);1378	if (ret <= 0) {1379		platform_device_unregister(priv->pdev_sec);1380		dev_info(&pdev_sec->dev, "device_attach() failed\n");1381		return ret;1382	}1383 1384	priv->pdev_sec = pdev_sec;1385 1386	return 0;1387}1388 1389static void i2s_delete_secondary_device(struct samsung_i2s_priv *priv)1390{1391	platform_device_unregister(priv->pdev_sec);1392	priv->pdev_sec = NULL;1393}1394 1395static int samsung_i2s_probe(struct platform_device *pdev)1396{1397	struct i2s_dai *pri_dai, *sec_dai = NULL;1398	struct s3c_audio_pdata *i2s_pdata = pdev->dev.platform_data;1399	u32 regs_base, idma_addr = 0;1400	struct device_node *np = pdev->dev.of_node;1401	const struct samsung_i2s_dai_data *i2s_dai_data;1402	const struct platform_device_id *id;1403	struct samsung_i2s_priv *priv;1404	struct resource *res;1405	int num_dais, ret;1406 1407	if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) {1408		i2s_dai_data = of_device_get_match_data(&pdev->dev);1409	} else {1410		id = platform_get_device_id(pdev);1411 1412		/* Nothing to do if it is the secondary device probe */1413		if (!id)1414			return 0;1415 1416		i2s_dai_data = (struct samsung_i2s_dai_data *)id->driver_data;1417	}1418 1419	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);1420	if (!priv)1421		return -ENOMEM;1422 1423	if (np) {1424		priv->quirks = i2s_dai_data->quirks;1425		priv->fixup_early = i2s_dai_data->fixup_early;1426		priv->fixup_late = i2s_dai_data->fixup_late;1427	} else {1428		if (!i2s_pdata) {1429			dev_err(&pdev->dev, "Missing platform data\n");1430			return -EINVAL;1431		}1432		priv->quirks = i2s_pdata->type.quirks;1433	}1434 1435	num_dais = (priv->quirks & QUIRK_SEC_DAI) ? 2 : 1;1436	priv->pdev = pdev;1437	priv->variant_regs = i2s_dai_data->i2s_variant_regs;1438 1439	ret = i2s_alloc_dais(priv, i2s_dai_data, num_dais);1440	if (ret < 0)1441		return ret;1442 1443	pri_dai = &priv->dai[SAMSUNG_I2S_ID_PRIMARY - 1];1444 1445	spin_lock_init(&priv->lock);1446	spin_lock_init(&priv->pcm_lock);1447 1448	if (!np) {1449		pri_dai->dma_playback.filter_data = i2s_pdata->dma_playback;1450		pri_dai->dma_capture.filter_data = i2s_pdata->dma_capture;1451		pri_dai->filter = i2s_pdata->dma_filter;1452 1453		idma_addr = i2s_pdata->type.idma_addr;1454	} else {1455		if (of_property_read_u32(np, "samsung,idma-addr",1456					 &idma_addr)) {1457			if (priv->quirks & QUIRK_SUPPORTS_IDMA) {1458				dev_info(&pdev->dev, "idma address is not"\1459						"specified");1460			}1461		}1462	}1463 1464	priv->addr = devm_platform_get_and_ioremap_resource(pdev, 0, &res);1465	if (IS_ERR(priv->addr))1466		return PTR_ERR(priv->addr);1467 1468	regs_base = res->start;1469 1470	priv->clk = devm_clk_get(&pdev->dev, "iis");1471	if (IS_ERR(priv->clk)) {1472		dev_err(&pdev->dev, "Failed to get iis clock\n");1473		return PTR_ERR(priv->clk);1474	}1475 1476	ret = clk_prepare_enable(priv->clk);1477	if (ret != 0) {1478		dev_err(&pdev->dev, "failed to enable clock: %d\n", ret);1479		return ret;1480	}1481	pri_dai->dma_playback.addr = regs_base + I2STXD;1482	pri_dai->dma_capture.addr = regs_base + I2SRXD;1483	pri_dai->dma_playback.chan_name = "tx";1484	pri_dai->dma_capture.chan_name = "rx";1485	pri_dai->dma_playback.addr_width = 4;1486	pri_dai->dma_capture.addr_width = 4;1487	pri_dai->priv = priv;1488 1489	if (priv->quirks & QUIRK_PRI_6CHAN)1490		pri_dai->drv->playback.channels_max = 6;1491 1492	ret = samsung_asoc_dma_platform_register(&pdev->dev, pri_dai->filter,1493						 "tx", "rx", NULL);1494	if (ret < 0)1495		goto err_disable_clk;1496 1497	if (priv->quirks & QUIRK_SEC_DAI) {1498		sec_dai = &priv->dai[SAMSUNG_I2S_ID_SECONDARY - 1];1499 1500		sec_dai->dma_playback.addr = regs_base + I2STXDS;1501		sec_dai->dma_playback.chan_name = "tx-sec";1502 1503		if (!np) {1504			sec_dai->dma_playback.filter_data = i2s_pdata->dma_play_sec;1505			sec_dai->filter = i2s_pdata->dma_filter;1506		}1507 1508		sec_dai->dma_playback.addr_width = 4;1509		sec_dai->idma_playback.addr = idma_addr;1510		sec_dai->pri_dai = pri_dai;1511		sec_dai->priv = priv;1512		pri_dai->sec_dai = sec_dai;1513 1514		ret = i2s_create_secondary_device(priv);1515		if (ret < 0)1516			goto err_disable_clk;1517 1518		ret = samsung_asoc_dma_platform_register(&priv->pdev_sec->dev,1519						sec_dai->filter, "tx-sec", NULL,1520						&pdev->dev);1521		if (ret < 0)1522			goto err_del_sec;1523 1524	}1525 1526	if (i2s_pdata && i2s_pdata->cfg_gpio && i2s_pdata->cfg_gpio(pdev)) {1527		dev_err(&pdev->dev, "Unable to configure gpio\n");1528		ret = -EINVAL;1529		goto err_del_sec;1530	}1531 1532	dev_set_drvdata(&pdev->dev, priv);1533 1534	ret = devm_snd_soc_register_component(&pdev->dev,1535					&samsung_i2s_component,1536					priv->dai_drv, num_dais);1537	if (ret < 0)1538		goto err_del_sec;1539 1540	pm_runtime_set_active(&pdev->dev);1541	pm_runtime_enable(&pdev->dev);1542 1543	ret = i2s_register_clock_provider(priv);1544	if (ret < 0)1545		goto err_disable_pm;1546 1547	priv->op_clk = clk_get_parent(priv->clk_table[CLK_I2S_RCLK_SRC]);1548 1549	return 0;1550 1551err_disable_pm:1552	pm_runtime_disable(&pdev->dev);1553err_del_sec:1554	i2s_delete_secondary_device(priv);1555err_disable_clk:1556	clk_disable_unprepare(priv->clk);1557	return ret;1558}1559 1560static void samsung_i2s_remove(struct platform_device *pdev)1561{1562	struct samsung_i2s_priv *priv = dev_get_drvdata(&pdev->dev);1563 1564	/* The secondary device has no driver data assigned */1565	if (!priv)1566		return;1567 1568	pm_runtime_get_sync(&pdev->dev);1569	pm_runtime_disable(&pdev->dev);1570 1571	i2s_unregister_clock_provider(priv);1572	i2s_delete_secondary_device(priv);1573	clk_disable_unprepare(priv->clk);1574 1575	pm_runtime_put_noidle(&pdev->dev);1576}1577 1578static void fsd_i2s_fixup_early(struct snd_pcm_substream *substream,1579		struct snd_soc_dai *dai)1580{1581	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);1582	struct i2s_dai *i2s = to_info(snd_soc_rtd_to_cpu(rtd, 0));1583	struct i2s_dai *other = get_other_dai(i2s);1584 1585	if (!is_opened(other)) {1586		i2s_set_sysclk(dai, SAMSUNG_I2S_CDCLK, 0, SND_SOC_CLOCK_OUT);1587		i2s_set_sysclk(dai, SAMSUNG_I2S_OPCLK, 0, MOD_OPCLK_PCLK);1588	}1589}1590 1591static void fsd_i2s_fixup_late(struct snd_pcm_substream *substream,1592		struct snd_soc_dai *dai)1593{1594	struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);1595	struct samsung_i2s_priv *priv = snd_soc_dai_get_drvdata(dai);1596	struct i2s_dai *i2s = to_info(snd_soc_rtd_to_cpu(rtd, 0));1597	struct i2s_dai *other = get_other_dai(i2s);1598 1599	if (!is_opened(other))1600		writel(PSR_PSVAL(2) | PSR_PSREN, priv->addr + I2SPSR);1601}1602 1603static const struct samsung_i2s_variant_regs i2sv3_regs = {1604	.bfs_off = 1,1605	.rfs_off = 3,1606	.sdf_off = 5,1607	.txr_off = 8,1608	.rclksrc_off = 10,1609	.mss_off = 11,1610	.cdclkcon_off = 12,1611	.lrp_off = 7,1612	.bfs_mask = 0x3,1613	.rfs_mask = 0x3,1614	.ftx0cnt_off = 8,1615};1616 1617static const struct samsung_i2s_variant_regs i2sv6_regs = {1618	.bfs_off = 0,1619	.rfs_off = 4,1620	.sdf_off = 6,1621	.txr_off = 8,1622	.rclksrc_off = 10,1623	.mss_off = 11,1624	.cdclkcon_off = 12,1625	.lrp_off = 15,1626	.bfs_mask = 0xf,1627	.rfs_mask = 0x3,1628	.ftx0cnt_off = 8,1629};1630 1631static const struct samsung_i2s_variant_regs i2sv7_regs = {1632	.bfs_off = 0,1633	.rfs_off = 4,1634	.sdf_off = 7,1635	.txr_off = 9,1636	.rclksrc_off = 11,1637	.mss_off = 12,1638	.cdclkcon_off = 22,1639	.lrp_off = 15,1640	.bfs_mask = 0xf,1641	.rfs_mask = 0x7,1642	.ftx0cnt_off = 0,1643};1644 1645static const struct samsung_i2s_variant_regs i2sv5_i2s1_regs = {1646	.bfs_off = 0,1647	.rfs_off = 3,1648	.sdf_off = 6,1649	.txr_off = 8,1650	.rclksrc_off = 10,1651	.mss_off = 11,1652	.cdclkcon_off = 12,1653	.lrp_off = 15,1654	.bfs_mask = 0x7,1655	.rfs_mask = 0x7,1656	.ftx0cnt_off = 8,1657};1658 1659static const struct samsung_i2s_dai_data i2sv3_dai_type = {1660	.quirks = QUIRK_NO_MUXPSR,1661	.pcm_rates = SNDRV_PCM_RATE_8000_96000,1662	.i2s_variant_regs = &i2sv3_regs,1663};1664 1665static const struct samsung_i2s_dai_data i2sv5_dai_type __maybe_unused = {1666	.quirks = QUIRK_PRI_6CHAN | QUIRK_SEC_DAI | QUIRK_NEED_RSTCLR |1667			QUIRK_SUPPORTS_IDMA,1668	.pcm_rates = SNDRV_PCM_RATE_8000_96000,1669	.i2s_variant_regs = &i2sv3_regs,1670};1671 1672static const struct samsung_i2s_dai_data i2sv6_dai_type __maybe_unused = {1673	.quirks = QUIRK_PRI_6CHAN | QUIRK_SEC_DAI | QUIRK_NEED_RSTCLR |1674			QUIRK_SUPPORTS_TDM | QUIRK_SUPPORTS_IDMA,1675	.pcm_rates = SNDRV_PCM_RATE_8000_96000,1676	.i2s_variant_regs = &i2sv6_regs,1677};1678 1679static const struct samsung_i2s_dai_data i2sv7_dai_type __maybe_unused = {1680	.quirks = QUIRK_PRI_6CHAN | QUIRK_SEC_DAI | QUIRK_NEED_RSTCLR |1681			QUIRK_SUPPORTS_TDM,1682	.pcm_rates = SNDRV_PCM_RATE_8000_192000,1683	.i2s_variant_regs = &i2sv7_regs,1684};1685 1686static const struct samsung_i2s_dai_data i2sv5_dai_type_i2s1 __maybe_unused = {1687	.quirks = QUIRK_PRI_6CHAN | QUIRK_NEED_RSTCLR,1688	.pcm_rates = SNDRV_PCM_RATE_8000_96000,1689	.i2s_variant_regs = &i2sv5_i2s1_regs,1690};1691 1692static const struct samsung_i2s_dai_data fsd_dai_type __maybe_unused = {1693	.quirks = QUIRK_SEC_DAI | QUIRK_NEED_RSTCLR | QUIRK_SUPPORTS_TDM,1694	.pcm_rates = SNDRV_PCM_RATE_8000_192000,1695	.i2s_variant_regs = &i2sv7_regs,1696	.fixup_early = fsd_i2s_fixup_early,1697	.fixup_late = fsd_i2s_fixup_late,1698};1699 1700static const struct platform_device_id samsung_i2s_driver_ids[] = {1701	{1702		.name           = "samsung-i2s",1703		.driver_data	= (kernel_ulong_t)&i2sv3_dai_type,1704	},1705	{},1706};1707MODULE_DEVICE_TABLE(platform, samsung_i2s_driver_ids);1708 1709#ifdef CONFIG_OF1710static const struct of_device_id exynos_i2s_match[] = {1711	{1712		.compatible = "samsung,s3c6410-i2s",1713		.data = &i2sv3_dai_type,1714	}, {1715		.compatible = "samsung,s5pv210-i2s",1716		.data = &i2sv5_dai_type,1717	}, {1718		.compatible = "samsung,exynos5420-i2s",1719		.data = &i2sv6_dai_type,1720	}, {1721		.compatible = "samsung,exynos7-i2s",1722		.data = &i2sv7_dai_type,1723	}, {1724		.compatible = "samsung,exynos7-i2s1",1725		.data = &i2sv5_dai_type_i2s1,1726	}, {1727		.compatible = "tesla,fsd-i2s",1728		.data = &fsd_dai_type,1729	},1730	{},1731};1732MODULE_DEVICE_TABLE(of, exynos_i2s_match);1733#endif1734 1735static const struct dev_pm_ops samsung_i2s_pm = {1736	SET_RUNTIME_PM_OPS(i2s_runtime_suspend,1737				i2s_runtime_resume, NULL)1738	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,1739				     pm_runtime_force_resume)1740};1741 1742static struct platform_driver samsung_i2s_driver = {1743	.probe  = samsung_i2s_probe,1744	.remove = samsung_i2s_remove,1745	.id_table = samsung_i2s_driver_ids,1746	.driver = {1747		.name = "samsung-i2s",1748		.of_match_table = of_match_ptr(exynos_i2s_match),1749		.pm = &samsung_i2s_pm,1750	},1751};1752 1753module_platform_driver(samsung_i2s_driver);1754 1755/* Module information */1756MODULE_AUTHOR("Jaswinder Singh, <jassisinghbrar@gmail.com>");1757MODULE_DESCRIPTION("Samsung I2S Interface");1758MODULE_LICENSE("GPL");1759