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