1550 lines · c
1// SPDX-License-Identifier: GPL-2.02// Copyright 2019 NXP3 4#include <linux/bitrev.h>5#include <linux/clk.h>6#include <linux/firmware.h>7#include <linux/interrupt.h>8#include <linux/module.h>9#include <linux/of_platform.h>10#include <linux/pm_runtime.h>11#include <linux/regmap.h>12#include <linux/reset.h>13#include <sound/dmaengine_pcm.h>14#include <sound/pcm_iec958.h>15#include <sound/pcm_params.h>16 17#include "fsl_xcvr.h"18#include "fsl_utils.h"19#include "imx-pcm.h"20 21#define FSL_XCVR_CAPDS_SIZE 25622 23enum fsl_xcvr_pll_verison {24 PLL_MX8MP,25 PLL_MX95,26};27 28struct fsl_xcvr_soc_data {29 const char *fw_name;30 bool spdif_only;31 bool use_edma;32 bool use_phy;33 enum fsl_xcvr_pll_verison pll_ver;34};35 36struct fsl_xcvr {37 const struct fsl_xcvr_soc_data *soc_data;38 struct platform_device *pdev;39 struct regmap *regmap;40 struct clk *ipg_clk;41 struct clk *pll_ipg_clk;42 struct clk *phy_clk;43 struct clk *spba_clk;44 struct clk *pll8k_clk;45 struct clk *pll11k_clk;46 struct reset_control *reset;47 u8 streams;48 u32 mode;49 u32 arc_mode;50 void __iomem *ram_addr;51 struct snd_dmaengine_dai_dma_data dma_prms_rx;52 struct snd_dmaengine_dai_dma_data dma_prms_tx;53 struct snd_aes_iec958 rx_iec958;54 struct snd_aes_iec958 tx_iec958;55 u8 cap_ds[FSL_XCVR_CAPDS_SIZE];56};57 58static const struct fsl_xcvr_pll_conf {59 u8 mfi; /* min=0x18, max=0x38 */60 u32 mfn; /* signed int, 2's compl., min=0x3FFF0000, max=0x00010000 */61 u32 mfd; /* unsigned int */62 u32 fout; /* Fout = Fref*(MFI + MFN/MFD), Fref is 24MHz */63} fsl_xcvr_pll_cfg[] = {64 { .mfi = 54, .mfn = 1, .mfd = 6, .fout = 1300000000, }, /* 1.3 GHz */65 { .mfi = 32, .mfn = 96, .mfd = 125, .fout = 786432000, }, /* 8000 Hz */66 { .mfi = 30, .mfn = 66, .mfd = 625, .fout = 722534400, }, /* 11025 Hz */67 { .mfi = 29, .mfn = 1, .mfd = 6, .fout = 700000000, }, /* 700 MHz */68};69 70/*71 * HDMI2.1 spec defines 6- and 12-channels layout for one bit audio72 * stream. Todo: to check how this case can be considered below73 */74static const u32 fsl_xcvr_earc_channels[] = { 1, 2, 8, 16, 32, };75static const struct snd_pcm_hw_constraint_list fsl_xcvr_earc_channels_constr = {76 .count = ARRAY_SIZE(fsl_xcvr_earc_channels),77 .list = fsl_xcvr_earc_channels,78};79 80static const u32 fsl_xcvr_earc_rates[] = {81 32000, 44100, 48000, 64000, 88200, 96000,82 128000, 176400, 192000, 256000, 352800, 384000,83 512000, 705600, 768000, 1024000, 1411200, 1536000,84};85static const struct snd_pcm_hw_constraint_list fsl_xcvr_earc_rates_constr = {86 .count = ARRAY_SIZE(fsl_xcvr_earc_rates),87 .list = fsl_xcvr_earc_rates,88};89 90static const u32 fsl_xcvr_spdif_channels[] = { 2, };91static const struct snd_pcm_hw_constraint_list fsl_xcvr_spdif_channels_constr = {92 .count = ARRAY_SIZE(fsl_xcvr_spdif_channels),93 .list = fsl_xcvr_spdif_channels,94};95 96static const u32 fsl_xcvr_spdif_rates[] = {97 32000, 44100, 48000, 88200, 96000, 176400, 192000,98};99static const struct snd_pcm_hw_constraint_list fsl_xcvr_spdif_rates_constr = {100 .count = ARRAY_SIZE(fsl_xcvr_spdif_rates),101 .list = fsl_xcvr_spdif_rates,102};103 104static int fsl_xcvr_arc_mode_put(struct snd_kcontrol *kcontrol,105 struct snd_ctl_elem_value *ucontrol)106{107 struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol);108 struct fsl_xcvr *xcvr = snd_soc_dai_get_drvdata(dai);109 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;110 unsigned int *item = ucontrol->value.enumerated.item;111 112 xcvr->arc_mode = snd_soc_enum_item_to_val(e, item[0]);113 114 return 0;115}116 117static int fsl_xcvr_arc_mode_get(struct snd_kcontrol *kcontrol,118 struct snd_ctl_elem_value *ucontrol)119{120 struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol);121 struct fsl_xcvr *xcvr = snd_soc_dai_get_drvdata(dai);122 123 ucontrol->value.enumerated.item[0] = xcvr->arc_mode;124 125 return 0;126}127 128static const u32 fsl_xcvr_phy_arc_cfg[] = {129 FSL_XCVR_PHY_CTRL_ARC_MODE_SE_EN, FSL_XCVR_PHY_CTRL_ARC_MODE_CM_EN,130};131 132static const char * const fsl_xcvr_arc_mode[] = { "Single Ended", "Common", };133static const struct soc_enum fsl_xcvr_arc_mode_enum =134 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(fsl_xcvr_arc_mode), fsl_xcvr_arc_mode);135static struct snd_kcontrol_new fsl_xcvr_arc_mode_kctl =136 SOC_ENUM_EXT("ARC Mode", fsl_xcvr_arc_mode_enum,137 fsl_xcvr_arc_mode_get, fsl_xcvr_arc_mode_put);138 139/* Capabilities data structure, bytes */140static int fsl_xcvr_type_capds_bytes_info(struct snd_kcontrol *kcontrol,141 struct snd_ctl_elem_info *uinfo)142{143 uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;144 uinfo->count = FSL_XCVR_CAPDS_SIZE;145 146 return 0;147}148 149static int fsl_xcvr_capds_get(struct snd_kcontrol *kcontrol,150 struct snd_ctl_elem_value *ucontrol)151{152 struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol);153 struct fsl_xcvr *xcvr = snd_soc_dai_get_drvdata(dai);154 155 memcpy(ucontrol->value.bytes.data, xcvr->cap_ds, FSL_XCVR_CAPDS_SIZE);156 157 return 0;158}159 160static int fsl_xcvr_capds_put(struct snd_kcontrol *kcontrol,161 struct snd_ctl_elem_value *ucontrol)162{163 struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol);164 struct fsl_xcvr *xcvr = snd_soc_dai_get_drvdata(dai);165 166 memcpy(xcvr->cap_ds, ucontrol->value.bytes.data, FSL_XCVR_CAPDS_SIZE);167 168 return 0;169}170 171static struct snd_kcontrol_new fsl_xcvr_earc_capds_kctl = {172 .iface = SNDRV_CTL_ELEM_IFACE_PCM,173 .name = "Capabilities Data Structure",174 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,175 .info = fsl_xcvr_type_capds_bytes_info,176 .get = fsl_xcvr_capds_get,177 .put = fsl_xcvr_capds_put,178};179 180static int fsl_xcvr_activate_ctl(struct snd_soc_dai *dai, const char *name,181 bool active)182{183 struct snd_soc_card *card = dai->component->card;184 struct snd_kcontrol *kctl;185 bool enabled;186 187 lockdep_assert_held(&card->snd_card->controls_rwsem);188 189 kctl = snd_soc_card_get_kcontrol(card, name);190 if (kctl == NULL)191 return -ENOENT;192 193 enabled = ((kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_WRITE) != 0);194 if (active == enabled)195 return 0; /* nothing to do */196 197 if (active)198 kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_WRITE;199 else200 kctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_WRITE;201 202 snd_ctl_notify(card->snd_card, SNDRV_CTL_EVENT_MASK_INFO, &kctl->id);203 204 return 1;205}206 207static int fsl_xcvr_mode_put(struct snd_kcontrol *kcontrol,208 struct snd_ctl_elem_value *ucontrol)209{210 struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol);211 struct fsl_xcvr *xcvr = snd_soc_dai_get_drvdata(dai);212 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;213 unsigned int *item = ucontrol->value.enumerated.item;214 struct snd_soc_card *card = dai->component->card;215 struct snd_soc_pcm_runtime *rtd;216 217 xcvr->mode = snd_soc_enum_item_to_val(e, item[0]);218 219 fsl_xcvr_activate_ctl(dai, fsl_xcvr_arc_mode_kctl.name,220 (xcvr->mode == FSL_XCVR_MODE_ARC));221 fsl_xcvr_activate_ctl(dai, fsl_xcvr_earc_capds_kctl.name,222 (xcvr->mode == FSL_XCVR_MODE_EARC));223 /* Allow playback for SPDIF only */224 rtd = snd_soc_get_pcm_runtime(card, card->dai_link);225 rtd->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream_count =226 (xcvr->mode == FSL_XCVR_MODE_SPDIF ? 1 : 0);227 return 0;228}229 230static int fsl_xcvr_mode_get(struct snd_kcontrol *kcontrol,231 struct snd_ctl_elem_value *ucontrol)232{233 struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol);234 struct fsl_xcvr *xcvr = snd_soc_dai_get_drvdata(dai);235 236 ucontrol->value.enumerated.item[0] = xcvr->mode;237 238 return 0;239}240 241static const char * const fsl_xcvr_mode[] = { "SPDIF", "ARC RX", "eARC", };242static const struct soc_enum fsl_xcvr_mode_enum =243 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(fsl_xcvr_mode), fsl_xcvr_mode);244static struct snd_kcontrol_new fsl_xcvr_mode_kctl =245 SOC_ENUM_EXT("XCVR Mode", fsl_xcvr_mode_enum,246 fsl_xcvr_mode_get, fsl_xcvr_mode_put);247 248/** phy: true => phy, false => pll */249static int fsl_xcvr_ai_write(struct fsl_xcvr *xcvr, u8 reg, u32 data, bool phy)250{251 struct device *dev = &xcvr->pdev->dev;252 u32 val, idx, tidx;253 int ret;254 255 idx = BIT(phy ? 26 : 24);256 tidx = BIT(phy ? 27 : 25);257 258 regmap_write(xcvr->regmap, FSL_XCVR_PHY_AI_CTRL_CLR, 0xFF);259 regmap_write(xcvr->regmap, FSL_XCVR_PHY_AI_CTRL_SET, reg);260 regmap_write(xcvr->regmap, FSL_XCVR_PHY_AI_WDATA, data);261 regmap_write(xcvr->regmap, FSL_XCVR_PHY_AI_CTRL_TOG, idx);262 263 ret = regmap_read_poll_timeout(xcvr->regmap, FSL_XCVR_PHY_AI_CTRL, val,264 (val & idx) == ((val & tidx) >> 1),265 10, 10000);266 if (ret)267 dev_err(dev, "AI timeout: failed to set %s reg 0x%02x=0x%08x\n",268 phy ? "PHY" : "PLL", reg, data);269 return ret;270}271 272static int fsl_xcvr_en_phy_pll(struct fsl_xcvr *xcvr, u32 freq, bool tx)273{274 struct device *dev = &xcvr->pdev->dev;275 u32 i, div = 0, log2, val;276 int ret;277 278 if (!xcvr->soc_data->use_phy)279 return 0;280 281 for (i = 0; i < ARRAY_SIZE(fsl_xcvr_pll_cfg); i++) {282 if (fsl_xcvr_pll_cfg[i].fout % freq == 0) {283 div = fsl_xcvr_pll_cfg[i].fout / freq;284 break;285 }286 }287 288 if (!div || i >= ARRAY_SIZE(fsl_xcvr_pll_cfg))289 return -EINVAL;290 291 log2 = ilog2(div);292 293 /* Release AI interface from reset */294 ret = regmap_write(xcvr->regmap, FSL_XCVR_PHY_AI_CTRL_SET,295 FSL_XCVR_PHY_AI_CTRL_AI_RESETN);296 if (ret < 0) {297 dev_err(dev, "Error while setting IER0: %d\n", ret);298 return ret;299 }300 301 switch (xcvr->soc_data->pll_ver) {302 case PLL_MX8MP:303 /* PLL: BANDGAP_SET: EN_VBG (enable bandgap) */304 fsl_xcvr_ai_write(xcvr, FSL_XCVR_PLL_BANDGAP_SET,305 FSL_XCVR_PLL_BANDGAP_EN_VBG, 0);306 307 /* PLL: CTRL0: DIV_INTEGER */308 fsl_xcvr_ai_write(xcvr, FSL_XCVR_PLL_CTRL0, fsl_xcvr_pll_cfg[i].mfi, 0);309 /* PLL: NUMERATOR: MFN */310 fsl_xcvr_ai_write(xcvr, FSL_XCVR_PLL_NUM, fsl_xcvr_pll_cfg[i].mfn, 0);311 /* PLL: DENOMINATOR: MFD */312 fsl_xcvr_ai_write(xcvr, FSL_XCVR_PLL_DEN, fsl_xcvr_pll_cfg[i].mfd, 0);313 /* PLL: CTRL0_SET: HOLD_RING_OFF, POWER_UP */314 fsl_xcvr_ai_write(xcvr, FSL_XCVR_PLL_CTRL0_SET,315 FSL_XCVR_PLL_CTRL0_HROFF | FSL_XCVR_PLL_CTRL0_PWP, 0);316 udelay(25);317 /* PLL: CTRL0: Clear Hold Ring Off */318 fsl_xcvr_ai_write(xcvr, FSL_XCVR_PLL_CTRL0_CLR,319 FSL_XCVR_PLL_CTRL0_HROFF, 0);320 udelay(100);321 if (tx) { /* TX is enabled for SPDIF only */322 /* PLL: POSTDIV: PDIV0 */323 fsl_xcvr_ai_write(xcvr, FSL_XCVR_PLL_PDIV,324 FSL_XCVR_PLL_PDIVx(log2, 0), 0);325 /* PLL: CTRL_SET: CLKMUX0_EN */326 fsl_xcvr_ai_write(xcvr, FSL_XCVR_PLL_CTRL0_SET,327 FSL_XCVR_PLL_CTRL0_CM0_EN, 0);328 } else if (xcvr->mode == FSL_XCVR_MODE_EARC) { /* eARC RX */329 /* PLL: POSTDIV: PDIV1 */330 fsl_xcvr_ai_write(xcvr, FSL_XCVR_PLL_PDIV,331 FSL_XCVR_PLL_PDIVx(log2, 1), 0);332 /* PLL: CTRL_SET: CLKMUX1_EN */333 fsl_xcvr_ai_write(xcvr, FSL_XCVR_PLL_CTRL0_SET,334 FSL_XCVR_PLL_CTRL0_CM1_EN, 0);335 } else { /* SPDIF / ARC RX */336 /* PLL: POSTDIV: PDIV2 */337 fsl_xcvr_ai_write(xcvr, FSL_XCVR_PLL_PDIV,338 FSL_XCVR_PLL_PDIVx(log2, 2), 0);339 /* PLL: CTRL_SET: CLKMUX2_EN */340 fsl_xcvr_ai_write(xcvr, FSL_XCVR_PLL_CTRL0_SET,341 FSL_XCVR_PLL_CTRL0_CM2_EN, 0);342 }343 break;344 case PLL_MX95:345 val = fsl_xcvr_pll_cfg[i].mfi << FSL_XCVR_GP_PLL_DIV_MFI_SHIFT | div;346 fsl_xcvr_ai_write(xcvr, FSL_XCVR_GP_PLL_DIV, val, 0);347 val = fsl_xcvr_pll_cfg[i].mfn << FSL_XCVR_GP_PLL_NUMERATOR_MFN_SHIFT;348 fsl_xcvr_ai_write(xcvr, FSL_XCVR_GP_PLL_NUMERATOR, val, 0);349 fsl_xcvr_ai_write(xcvr, FSL_XCVR_GP_PLL_DENOMINATOR,350 fsl_xcvr_pll_cfg[i].mfd, 0);351 val = FSL_XCVR_GP_PLL_CTRL_POWERUP | FSL_XCVR_GP_PLL_CTRL_CLKMUX_EN;352 fsl_xcvr_ai_write(xcvr, FSL_XCVR_GP_PLL_CTRL, val, 0);353 break;354 default:355 dev_err(dev, "Error for PLL version %d\n", xcvr->soc_data->pll_ver);356 return -EINVAL;357 }358 359 if (xcvr->mode == FSL_XCVR_MODE_EARC) { /* eARC mode */360 /* PHY: CTRL_SET: TX_DIFF_OE, PHY_EN */361 fsl_xcvr_ai_write(xcvr, FSL_XCVR_PHY_CTRL_SET,362 FSL_XCVR_PHY_CTRL_TSDIFF_OE |363 FSL_XCVR_PHY_CTRL_PHY_EN, 1);364 /* PHY: CTRL2_SET: EARC_TX_MODE */365 fsl_xcvr_ai_write(xcvr, FSL_XCVR_PHY_CTRL2_SET,366 FSL_XCVR_PHY_CTRL2_EARC_TXMS, 1);367 } else if (!tx) { /* SPDIF / ARC RX mode */368 if (xcvr->mode == FSL_XCVR_MODE_SPDIF)369 /* PHY: CTRL_SET: SPDIF_EN */370 fsl_xcvr_ai_write(xcvr, FSL_XCVR_PHY_CTRL_SET,371 FSL_XCVR_PHY_CTRL_SPDIF_EN, 1);372 else /* PHY: CTRL_SET: ARC RX setup */373 fsl_xcvr_ai_write(xcvr, FSL_XCVR_PHY_CTRL_SET,374 FSL_XCVR_PHY_CTRL_PHY_EN |375 FSL_XCVR_PHY_CTRL_RX_CM_EN |376 fsl_xcvr_phy_arc_cfg[xcvr->arc_mode], 1);377 }378 379 dev_dbg(dev, "PLL Fexp: %u, Fout: %u, mfi: %u, mfn: %u, mfd: %d, div: %u, pdiv0: %u\n",380 freq, fsl_xcvr_pll_cfg[i].fout, fsl_xcvr_pll_cfg[i].mfi,381 fsl_xcvr_pll_cfg[i].mfn, fsl_xcvr_pll_cfg[i].mfd, div, log2);382 return 0;383}384 385static int fsl_xcvr_en_aud_pll(struct fsl_xcvr *xcvr, u32 freq)386{387 struct device *dev = &xcvr->pdev->dev;388 int ret;389 390 freq = xcvr->soc_data->spdif_only ? freq / 5 : freq;391 clk_disable_unprepare(xcvr->phy_clk);392 fsl_asoc_reparent_pll_clocks(dev, xcvr->phy_clk,393 xcvr->pll8k_clk, xcvr->pll11k_clk, freq);394 ret = clk_set_rate(xcvr->phy_clk, freq);395 if (ret < 0) {396 dev_err(dev, "Error while setting AUD PLL rate: %d\n", ret);397 return ret;398 }399 ret = clk_prepare_enable(xcvr->phy_clk);400 if (ret) {401 dev_err(dev, "failed to start PHY clock: %d\n", ret);402 return ret;403 }404 405 if (!xcvr->soc_data->use_phy)406 return 0;407 /* Release AI interface from reset */408 ret = regmap_write(xcvr->regmap, FSL_XCVR_PHY_AI_CTRL_SET,409 FSL_XCVR_PHY_AI_CTRL_AI_RESETN);410 if (ret < 0) {411 dev_err(dev, "Error while setting IER0: %d\n", ret);412 return ret;413 }414 415 if (xcvr->mode == FSL_XCVR_MODE_EARC) { /* eARC mode */416 /* PHY: CTRL_SET: TX_DIFF_OE, PHY_EN */417 fsl_xcvr_ai_write(xcvr, FSL_XCVR_PHY_CTRL_SET,418 FSL_XCVR_PHY_CTRL_TSDIFF_OE |419 FSL_XCVR_PHY_CTRL_PHY_EN, 1);420 /* PHY: CTRL2_SET: EARC_TX_MODE */421 fsl_xcvr_ai_write(xcvr, FSL_XCVR_PHY_CTRL2_SET,422 FSL_XCVR_PHY_CTRL2_EARC_TXMS, 1);423 } else { /* SPDIF mode */424 /* PHY: CTRL_SET: TX_CLK_AUD_SS | SPDIF_EN */425 fsl_xcvr_ai_write(xcvr, FSL_XCVR_PHY_CTRL_SET,426 FSL_XCVR_PHY_CTRL_TX_CLK_AUD_SS |427 FSL_XCVR_PHY_CTRL_SPDIF_EN, 1);428 }429 430 dev_dbg(dev, "PLL Fexp: %u\n", freq);431 432 return 0;433}434 435#define FSL_XCVR_SPDIF_RX_FREQ 175000000436static int fsl_xcvr_prepare(struct snd_pcm_substream *substream,437 struct snd_soc_dai *dai)438{439 struct fsl_xcvr *xcvr = snd_soc_dai_get_drvdata(dai);440 bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;441 u32 m_ctl = 0, v_ctl = 0;442 u32 r = substream->runtime->rate, ch = substream->runtime->channels;443 u32 fout = 32 * r * ch * 10;444 int ret = 0;445 446 switch (xcvr->mode) {447 case FSL_XCVR_MODE_SPDIF:448 if (xcvr->soc_data->spdif_only && tx) {449 ret = regmap_update_bits(xcvr->regmap, FSL_XCVR_TX_DPTH_CTRL_SET,450 FSL_XCVR_TX_DPTH_CTRL_BYPASS_FEM,451 FSL_XCVR_TX_DPTH_CTRL_BYPASS_FEM);452 if (ret < 0) {453 dev_err(dai->dev, "Failed to set bypass fem: %d\n", ret);454 return ret;455 }456 }457 fallthrough;458 case FSL_XCVR_MODE_ARC:459 if (tx) {460 ret = fsl_xcvr_en_aud_pll(xcvr, fout);461 if (ret < 0) {462 dev_err(dai->dev, "Failed to set TX freq %u: %d\n",463 fout, ret);464 return ret;465 }466 467 ret = regmap_write(xcvr->regmap, FSL_XCVR_TX_DPTH_CTRL_SET,468 FSL_XCVR_TX_DPTH_CTRL_FRM_FMT);469 if (ret < 0) {470 dev_err(dai->dev, "Failed to set TX_DPTH: %d\n", ret);471 return ret;472 }473 474 /**475 * set SPDIF MODE - this flag is used to gate476 * SPDIF output, useless for SPDIF RX477 */478 m_ctl |= FSL_XCVR_EXT_CTRL_SPDIF_MODE;479 v_ctl |= FSL_XCVR_EXT_CTRL_SPDIF_MODE;480 } else {481 /**482 * Clear RX FIFO, flip RX FIFO bits,483 * disable eARC related HW mode detects484 */485 ret = regmap_write(xcvr->regmap, FSL_XCVR_RX_DPTH_CTRL_SET,486 FSL_XCVR_RX_DPTH_CTRL_STORE_FMT |487 FSL_XCVR_RX_DPTH_CTRL_CLR_RX_FIFO |488 FSL_XCVR_RX_DPTH_CTRL_COMP |489 FSL_XCVR_RX_DPTH_CTRL_LAYB_CTRL);490 if (ret < 0) {491 dev_err(dai->dev, "Failed to set RX_DPTH: %d\n", ret);492 return ret;493 }494 495 ret = fsl_xcvr_en_phy_pll(xcvr, FSL_XCVR_SPDIF_RX_FREQ, tx);496 if (ret < 0) {497 dev_err(dai->dev, "Failed to set RX freq %u: %d\n",498 FSL_XCVR_SPDIF_RX_FREQ, ret);499 return ret;500 }501 }502 break;503 case FSL_XCVR_MODE_EARC:504 if (!tx) {505 /** Clear RX FIFO, flip RX FIFO bits */506 ret = regmap_write(xcvr->regmap, FSL_XCVR_RX_DPTH_CTRL_SET,507 FSL_XCVR_RX_DPTH_CTRL_STORE_FMT |508 FSL_XCVR_RX_DPTH_CTRL_CLR_RX_FIFO);509 if (ret < 0) {510 dev_err(dai->dev, "Failed to set RX_DPTH: %d\n", ret);511 return ret;512 }513 514 /** Enable eARC related HW mode detects */515 ret = regmap_write(xcvr->regmap, FSL_XCVR_RX_DPTH_CTRL_CLR,516 FSL_XCVR_RX_DPTH_CTRL_COMP |517 FSL_XCVR_RX_DPTH_CTRL_LAYB_CTRL);518 if (ret < 0) {519 dev_err(dai->dev, "Failed to clr TX_DPTH: %d\n", ret);520 return ret;521 }522 }523 524 /* clear CMDC RESET */525 m_ctl |= FSL_XCVR_EXT_CTRL_CMDC_RESET(tx);526 /* set TX_RX_MODE */527 m_ctl |= FSL_XCVR_EXT_CTRL_TX_RX_MODE;528 v_ctl |= (tx ? FSL_XCVR_EXT_CTRL_TX_RX_MODE : 0);529 break;530 }531 532 ret = regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_CTRL, m_ctl, v_ctl);533 if (ret < 0) {534 dev_err(dai->dev, "Error while setting EXT_CTRL: %d\n", ret);535 return ret;536 }537 538 return 0;539}540 541static int fsl_xcvr_constr(const struct snd_pcm_substream *substream,542 const struct snd_pcm_hw_constraint_list *channels,543 const struct snd_pcm_hw_constraint_list *rates)544{545 struct snd_pcm_runtime *rt = substream->runtime;546 int ret;547 548 ret = snd_pcm_hw_constraint_list(rt, 0, SNDRV_PCM_HW_PARAM_CHANNELS,549 channels);550 if (ret < 0)551 return ret;552 553 ret = snd_pcm_hw_constraint_list(rt, 0, SNDRV_PCM_HW_PARAM_RATE,554 rates);555 if (ret < 0)556 return ret;557 558 return 0;559}560 561static int fsl_xcvr_startup(struct snd_pcm_substream *substream,562 struct snd_soc_dai *dai)563{564 struct fsl_xcvr *xcvr = snd_soc_dai_get_drvdata(dai);565 bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;566 int ret = 0;567 568 if (xcvr->streams & BIT(substream->stream)) {569 dev_err(dai->dev, "%sX busy\n", tx ? "T" : "R");570 return -EBUSY;571 }572 573 /*574 * EDMA controller needs period size to be a multiple of575 * tx/rx maxburst576 */577 if (xcvr->soc_data->use_edma)578 snd_pcm_hw_constraint_step(substream->runtime, 0,579 SNDRV_PCM_HW_PARAM_PERIOD_SIZE,580 tx ? xcvr->dma_prms_tx.maxburst :581 xcvr->dma_prms_rx.maxburst);582 583 switch (xcvr->mode) {584 case FSL_XCVR_MODE_SPDIF:585 case FSL_XCVR_MODE_ARC:586 ret = fsl_xcvr_constr(substream, &fsl_xcvr_spdif_channels_constr,587 &fsl_xcvr_spdif_rates_constr);588 break;589 case FSL_XCVR_MODE_EARC:590 ret = fsl_xcvr_constr(substream, &fsl_xcvr_earc_channels_constr,591 &fsl_xcvr_earc_rates_constr);592 break;593 }594 if (ret < 0)595 return ret;596 597 xcvr->streams |= BIT(substream->stream);598 599 if (!xcvr->soc_data->spdif_only) {600 struct snd_soc_card *card = dai->component->card;601 602 /* Disable XCVR controls if there is stream started */603 down_read(&card->snd_card->controls_rwsem);604 fsl_xcvr_activate_ctl(dai, fsl_xcvr_mode_kctl.name, false);605 fsl_xcvr_activate_ctl(dai, fsl_xcvr_arc_mode_kctl.name, false);606 fsl_xcvr_activate_ctl(dai, fsl_xcvr_earc_capds_kctl.name, false);607 up_read(&card->snd_card->controls_rwsem);608 }609 610 return 0;611}612 613static void fsl_xcvr_shutdown(struct snd_pcm_substream *substream,614 struct snd_soc_dai *dai)615{616 struct fsl_xcvr *xcvr = snd_soc_dai_get_drvdata(dai);617 bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;618 u32 mask = 0, val = 0;619 int ret;620 621 xcvr->streams &= ~BIT(substream->stream);622 623 /* Enable XCVR controls if there is no stream started */624 if (!xcvr->streams) {625 if (!xcvr->soc_data->spdif_only) {626 struct snd_soc_card *card = dai->component->card;627 628 down_read(&card->snd_card->controls_rwsem);629 fsl_xcvr_activate_ctl(dai, fsl_xcvr_mode_kctl.name, true);630 fsl_xcvr_activate_ctl(dai, fsl_xcvr_arc_mode_kctl.name,631 (xcvr->mode == FSL_XCVR_MODE_ARC));632 fsl_xcvr_activate_ctl(dai, fsl_xcvr_earc_capds_kctl.name,633 (xcvr->mode == FSL_XCVR_MODE_EARC));634 up_read(&card->snd_card->controls_rwsem);635 }636 ret = regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_IER0,637 FSL_XCVR_IRQ_EARC_ALL, 0);638 if (ret < 0) {639 dev_err(dai->dev, "Failed to set IER0: %d\n", ret);640 return;641 }642 643 /* clear SPDIF MODE */644 if (xcvr->mode == FSL_XCVR_MODE_SPDIF)645 mask |= FSL_XCVR_EXT_CTRL_SPDIF_MODE;646 }647 648 if (xcvr->mode == FSL_XCVR_MODE_EARC) {649 /* set CMDC RESET */650 mask |= FSL_XCVR_EXT_CTRL_CMDC_RESET(tx);651 val |= FSL_XCVR_EXT_CTRL_CMDC_RESET(tx);652 }653 654 ret = regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_CTRL, mask, val);655 if (ret < 0) {656 dev_err(dai->dev, "Err setting DPATH RESET: %d\n", ret);657 return;658 }659}660 661static int fsl_xcvr_trigger(struct snd_pcm_substream *substream, int cmd,662 struct snd_soc_dai *dai)663{664 struct fsl_xcvr *xcvr = snd_soc_dai_get_drvdata(dai);665 bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;666 int ret;667 668 switch (cmd) {669 case SNDRV_PCM_TRIGGER_START:670 case SNDRV_PCM_TRIGGER_RESUME:671 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:672 /* set DPATH RESET */673 ret = regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_CTRL,674 FSL_XCVR_EXT_CTRL_DPTH_RESET(tx),675 FSL_XCVR_EXT_CTRL_DPTH_RESET(tx));676 if (ret < 0) {677 dev_err(dai->dev, "Failed to set DPATH RESET: %d\n", ret);678 return ret;679 }680 681 if (tx) {682 switch (xcvr->mode) {683 case FSL_XCVR_MODE_EARC:684 /* set isr_cmdc_tx_en, w1c */685 ret = regmap_write(xcvr->regmap,686 FSL_XCVR_ISR_SET,687 FSL_XCVR_ISR_CMDC_TX_EN);688 if (ret < 0) {689 dev_err(dai->dev, "err updating isr %d\n", ret);690 return ret;691 }692 fallthrough;693 case FSL_XCVR_MODE_SPDIF:694 ret = regmap_write(xcvr->regmap,695 FSL_XCVR_TX_DPTH_CTRL_SET,696 FSL_XCVR_TX_DPTH_CTRL_STRT_DATA_TX);697 if (ret < 0) {698 dev_err(dai->dev, "Failed to start DATA_TX: %d\n", ret);699 return ret;700 }701 break;702 }703 }704 705 /* enable DMA RD/WR */706 ret = regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_CTRL,707 FSL_XCVR_EXT_CTRL_DMA_DIS(tx), 0);708 if (ret < 0) {709 dev_err(dai->dev, "Failed to enable DMA: %d\n", ret);710 return ret;711 }712 713 ret = regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_IER0,714 FSL_XCVR_IRQ_EARC_ALL, FSL_XCVR_IRQ_EARC_ALL);715 if (ret < 0) {716 dev_err(dai->dev, "Error while setting IER0: %d\n", ret);717 return ret;718 }719 720 /* clear DPATH RESET */721 ret = regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_CTRL,722 FSL_XCVR_EXT_CTRL_DPTH_RESET(tx),723 0);724 if (ret < 0) {725 dev_err(dai->dev, "Failed to clear DPATH RESET: %d\n", ret);726 return ret;727 }728 729 break;730 case SNDRV_PCM_TRIGGER_STOP:731 case SNDRV_PCM_TRIGGER_SUSPEND:732 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:733 /* disable DMA RD/WR */734 ret = regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_CTRL,735 FSL_XCVR_EXT_CTRL_DMA_DIS(tx),736 FSL_XCVR_EXT_CTRL_DMA_DIS(tx));737 if (ret < 0) {738 dev_err(dai->dev, "Failed to disable DMA: %d\n", ret);739 return ret;740 }741 742 ret = regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_IER0,743 FSL_XCVR_IRQ_EARC_ALL, 0);744 if (ret < 0) {745 dev_err(dai->dev, "Failed to clear IER0: %d\n", ret);746 return ret;747 }748 749 if (tx) {750 switch (xcvr->mode) {751 case FSL_XCVR_MODE_SPDIF:752 ret = regmap_write(xcvr->regmap,753 FSL_XCVR_TX_DPTH_CTRL_CLR,754 FSL_XCVR_TX_DPTH_CTRL_STRT_DATA_TX);755 if (ret < 0) {756 dev_err(dai->dev, "Failed to stop DATA_TX: %d\n", ret);757 return ret;758 }759 if (xcvr->soc_data->spdif_only)760 break;761 else762 fallthrough;763 case FSL_XCVR_MODE_EARC:764 /* clear ISR_CMDC_TX_EN, W1C */765 ret = regmap_write(xcvr->regmap,766 FSL_XCVR_ISR_CLR,767 FSL_XCVR_ISR_CMDC_TX_EN);768 if (ret < 0) {769 dev_err(dai->dev,770 "Err updating ISR %d\n", ret);771 return ret;772 }773 break;774 }775 }776 break;777 default:778 return -EINVAL;779 }780 781 return 0;782}783 784static int fsl_xcvr_load_firmware(struct fsl_xcvr *xcvr)785{786 struct device *dev = &xcvr->pdev->dev;787 const struct firmware *fw;788 int ret = 0, rem, off, out, page = 0, size = FSL_XCVR_REG_OFFSET;789 u32 mask, val;790 791 ret = request_firmware(&fw, xcvr->soc_data->fw_name, dev);792 if (ret) {793 dev_err(dev, "failed to request firmware.\n");794 return ret;795 }796 797 rem = fw->size;798 799 /* RAM is 20KiB = 16KiB code + 4KiB data => max 10 pages 2KiB each */800 if (rem > 16384) {801 dev_err(dev, "FW size %d is bigger than 16KiB.\n", rem);802 release_firmware(fw);803 return -ENOMEM;804 }805 806 for (page = 0; page < 10; page++) {807 ret = regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_CTRL,808 FSL_XCVR_EXT_CTRL_PAGE_MASK,809 FSL_XCVR_EXT_CTRL_PAGE(page));810 if (ret < 0) {811 dev_err(dev, "FW: failed to set page %d, err=%d\n",812 page, ret);813 goto err_firmware;814 }815 816 off = page * size;817 out = min(rem, size);818 /* IPG clock is assumed to be running, otherwise it will hang */819 if (out > 0) {820 /* write firmware into code memory */821 memcpy_toio(xcvr->ram_addr, fw->data + off, out);822 rem -= out;823 if (rem == 0) {824 /* last part of firmware written */825 /* clean remaining part of code memory page */826 memset_io(xcvr->ram_addr + out, 0, size - out);827 }828 } else {829 /* clean current page, including data memory */830 memset_io(xcvr->ram_addr, 0, size);831 }832 }833 834err_firmware:835 release_firmware(fw);836 if (ret < 0)837 return ret;838 839 /* configure watermarks */840 mask = FSL_XCVR_EXT_CTRL_RX_FWM_MASK | FSL_XCVR_EXT_CTRL_TX_FWM_MASK;841 val = FSL_XCVR_EXT_CTRL_RX_FWM(FSL_XCVR_FIFO_WMK_RX);842 val |= FSL_XCVR_EXT_CTRL_TX_FWM(FSL_XCVR_FIFO_WMK_TX);843 /* disable DMA RD/WR */844 mask |= FSL_XCVR_EXT_CTRL_DMA_RD_DIS | FSL_XCVR_EXT_CTRL_DMA_WR_DIS;845 val |= FSL_XCVR_EXT_CTRL_DMA_RD_DIS | FSL_XCVR_EXT_CTRL_DMA_WR_DIS;846 /* Data RAM is 4KiB, last two pages: 8 and 9. Select page 8. */847 mask |= FSL_XCVR_EXT_CTRL_PAGE_MASK;848 val |= FSL_XCVR_EXT_CTRL_PAGE(8);849 850 ret = regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_CTRL, mask, val);851 if (ret < 0) {852 dev_err(dev, "Failed to set watermarks: %d\n", ret);853 return ret;854 }855 856 /* Store Capabilities Data Structure into Data RAM */857 memcpy_toio(xcvr->ram_addr + FSL_XCVR_CAP_DATA_STR, xcvr->cap_ds,858 FSL_XCVR_CAPDS_SIZE);859 return 0;860}861 862static int fsl_xcvr_type_iec958_info(struct snd_kcontrol *kcontrol,863 struct snd_ctl_elem_info *uinfo)864{865 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;866 uinfo->count = 1;867 868 return 0;869}870 871static int fsl_xcvr_type_iec958_bytes_info(struct snd_kcontrol *kcontrol,872 struct snd_ctl_elem_info *uinfo)873{874 uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;875 uinfo->count = sizeof_field(struct snd_aes_iec958, status);876 877 return 0;878}879 880static int fsl_xcvr_rx_cs_get(struct snd_kcontrol *kcontrol,881 struct snd_ctl_elem_value *ucontrol)882{883 struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol);884 struct fsl_xcvr *xcvr = snd_soc_dai_get_drvdata(dai);885 886 memcpy(ucontrol->value.iec958.status, xcvr->rx_iec958.status, 24);887 888 return 0;889}890 891static int fsl_xcvr_tx_cs_get(struct snd_kcontrol *kcontrol,892 struct snd_ctl_elem_value *ucontrol)893{894 struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol);895 struct fsl_xcvr *xcvr = snd_soc_dai_get_drvdata(dai);896 897 memcpy(ucontrol->value.iec958.status, xcvr->tx_iec958.status, 24);898 899 return 0;900}901 902static int fsl_xcvr_tx_cs_put(struct snd_kcontrol *kcontrol,903 struct snd_ctl_elem_value *ucontrol)904{905 struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol);906 struct fsl_xcvr *xcvr = snd_soc_dai_get_drvdata(dai);907 908 memcpy(xcvr->tx_iec958.status, ucontrol->value.iec958.status, 24);909 910 return 0;911}912 913static struct snd_kcontrol_new fsl_xcvr_rx_ctls[] = {914 /* Channel status controller */915 {916 .iface = SNDRV_CTL_ELEM_IFACE_PCM,917 .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT),918 .access = SNDRV_CTL_ELEM_ACCESS_READ,919 .info = fsl_xcvr_type_iec958_info,920 .get = fsl_xcvr_rx_cs_get,921 },922 /* Capture channel status, bytes */923 {924 .iface = SNDRV_CTL_ELEM_IFACE_PCM,925 .name = "Capture Channel Status",926 .access = SNDRV_CTL_ELEM_ACCESS_READ,927 .info = fsl_xcvr_type_iec958_bytes_info,928 .get = fsl_xcvr_rx_cs_get,929 },930};931 932static struct snd_kcontrol_new fsl_xcvr_tx_ctls[] = {933 /* Channel status controller */934 {935 .iface = SNDRV_CTL_ELEM_IFACE_PCM,936 .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),937 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,938 .info = fsl_xcvr_type_iec958_info,939 .get = fsl_xcvr_tx_cs_get,940 .put = fsl_xcvr_tx_cs_put,941 },942 /* Playback channel status, bytes */943 {944 .iface = SNDRV_CTL_ELEM_IFACE_PCM,945 .name = "Playback Channel Status",946 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,947 .info = fsl_xcvr_type_iec958_bytes_info,948 .get = fsl_xcvr_tx_cs_get,949 .put = fsl_xcvr_tx_cs_put,950 },951};952 953static int fsl_xcvr_dai_probe(struct snd_soc_dai *dai)954{955 struct fsl_xcvr *xcvr = snd_soc_dai_get_drvdata(dai);956 957 snd_soc_dai_init_dma_data(dai, &xcvr->dma_prms_tx, &xcvr->dma_prms_rx);958 959 if (xcvr->soc_data->spdif_only)960 xcvr->mode = FSL_XCVR_MODE_SPDIF;961 else {962 snd_soc_add_dai_controls(dai, &fsl_xcvr_mode_kctl, 1);963 snd_soc_add_dai_controls(dai, &fsl_xcvr_arc_mode_kctl, 1);964 snd_soc_add_dai_controls(dai, &fsl_xcvr_earc_capds_kctl, 1);965 }966 snd_soc_add_dai_controls(dai, fsl_xcvr_tx_ctls,967 ARRAY_SIZE(fsl_xcvr_tx_ctls));968 snd_soc_add_dai_controls(dai, fsl_xcvr_rx_ctls,969 ARRAY_SIZE(fsl_xcvr_rx_ctls));970 return 0;971}972 973static const struct snd_soc_dai_ops fsl_xcvr_dai_ops = {974 .probe = fsl_xcvr_dai_probe,975 .prepare = fsl_xcvr_prepare,976 .startup = fsl_xcvr_startup,977 .shutdown = fsl_xcvr_shutdown,978 .trigger = fsl_xcvr_trigger,979};980 981static struct snd_soc_dai_driver fsl_xcvr_dai = {982 .ops = &fsl_xcvr_dai_ops,983 .playback = {984 .stream_name = "CPU-Playback",985 .channels_min = 1,986 .channels_max = 32,987 .rate_min = 32000,988 .rate_max = 1536000,989 .rates = SNDRV_PCM_RATE_KNOT,990 .formats = SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE,991 },992 .capture = {993 .stream_name = "CPU-Capture",994 .channels_min = 1,995 .channels_max = 32,996 .rate_min = 32000,997 .rate_max = 1536000,998 .rates = SNDRV_PCM_RATE_KNOT,999 .formats = SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE,1000 },1001};1002 1003static const struct snd_soc_component_driver fsl_xcvr_comp = {1004 .name = "fsl-xcvr-dai",1005 .legacy_dai_naming = 1,1006};1007 1008static const struct reg_default fsl_xcvr_reg_defaults[] = {1009 { FSL_XCVR_VERSION, 0x00000000 },1010 { FSL_XCVR_EXT_CTRL, 0xF8204040 },1011 { FSL_XCVR_EXT_STATUS, 0x00000000 },1012 { FSL_XCVR_EXT_IER0, 0x00000000 },1013 { FSL_XCVR_EXT_IER1, 0x00000000 },1014 { FSL_XCVR_EXT_ISR, 0x00000000 },1015 { FSL_XCVR_EXT_ISR_SET, 0x00000000 },1016 { FSL_XCVR_EXT_ISR_CLR, 0x00000000 },1017 { FSL_XCVR_EXT_ISR_TOG, 0x00000000 },1018 { FSL_XCVR_IER, 0x00000000 },1019 { FSL_XCVR_ISR, 0x00000000 },1020 { FSL_XCVR_ISR_SET, 0x00000000 },1021 { FSL_XCVR_ISR_CLR, 0x00000000 },1022 { FSL_XCVR_ISR_TOG, 0x00000000 },1023 { FSL_XCVR_CLK_CTRL, 0x0000018F },1024 { FSL_XCVR_RX_DPTH_CTRL, 0x00040CC1 },1025 { FSL_XCVR_RX_DPTH_CTRL_SET, 0x00040CC1 },1026 { FSL_XCVR_RX_DPTH_CTRL_CLR, 0x00040CC1 },1027 { FSL_XCVR_RX_DPTH_CTRL_TOG, 0x00040CC1 },1028 { FSL_XCVR_RX_DPTH_CNTR_CTRL, 0x00000000 },1029 { FSL_XCVR_RX_DPTH_CNTR_CTRL_SET, 0x00000000 },1030 { FSL_XCVR_RX_DPTH_CNTR_CTRL_CLR, 0x00000000 },1031 { FSL_XCVR_RX_DPTH_CNTR_CTRL_TOG, 0x00000000 },1032 { FSL_XCVR_RX_DPTH_TSCR, 0x00000000 },1033 { FSL_XCVR_RX_DPTH_BCR, 0x00000000 },1034 { FSL_XCVR_RX_DPTH_BCTR, 0x00000000 },1035 { FSL_XCVR_RX_DPTH_BCRR, 0x00000000 },1036 { FSL_XCVR_TX_DPTH_CTRL, 0x00000000 },1037 { FSL_XCVR_TX_DPTH_CTRL_SET, 0x00000000 },1038 { FSL_XCVR_TX_DPTH_CTRL_CLR, 0x00000000 },1039 { FSL_XCVR_TX_DPTH_CTRL_TOG, 0x00000000 },1040 { FSL_XCVR_TX_CS_DATA_0, 0x00000000 },1041 { FSL_XCVR_TX_CS_DATA_1, 0x00000000 },1042 { FSL_XCVR_TX_CS_DATA_2, 0x00000000 },1043 { FSL_XCVR_TX_CS_DATA_3, 0x00000000 },1044 { FSL_XCVR_TX_CS_DATA_4, 0x00000000 },1045 { FSL_XCVR_TX_CS_DATA_5, 0x00000000 },1046 { FSL_XCVR_TX_DPTH_CNTR_CTRL, 0x00000000 },1047 { FSL_XCVR_TX_DPTH_CNTR_CTRL_SET, 0x00000000 },1048 { FSL_XCVR_TX_DPTH_CNTR_CTRL_CLR, 0x00000000 },1049 { FSL_XCVR_TX_DPTH_CNTR_CTRL_TOG, 0x00000000 },1050 { FSL_XCVR_TX_DPTH_TSCR, 0x00000000 },1051 { FSL_XCVR_TX_DPTH_BCR, 0x00000000 },1052 { FSL_XCVR_TX_DPTH_BCTR, 0x00000000 },1053 { FSL_XCVR_TX_DPTH_BCRR, 0x00000000 },1054 { FSL_XCVR_DEBUG_REG_0, 0x00000000 },1055 { FSL_XCVR_DEBUG_REG_1, 0x00000000 },1056};1057 1058static bool fsl_xcvr_readable_reg(struct device *dev, unsigned int reg)1059{1060 struct fsl_xcvr *xcvr = dev_get_drvdata(dev);1061 1062 if (!xcvr->soc_data->use_phy)1063 if ((reg >= FSL_XCVR_IER && reg <= FSL_XCVR_PHY_AI_RDATA) ||1064 reg > FSL_XCVR_TX_DPTH_BCRR)1065 return false;1066 switch (reg) {1067 case FSL_XCVR_VERSION:1068 case FSL_XCVR_EXT_CTRL:1069 case FSL_XCVR_EXT_STATUS:1070 case FSL_XCVR_EXT_IER0:1071 case FSL_XCVR_EXT_IER1:1072 case FSL_XCVR_EXT_ISR:1073 case FSL_XCVR_EXT_ISR_SET:1074 case FSL_XCVR_EXT_ISR_CLR:1075 case FSL_XCVR_EXT_ISR_TOG:1076 case FSL_XCVR_IER:1077 case FSL_XCVR_ISR:1078 case FSL_XCVR_ISR_SET:1079 case FSL_XCVR_ISR_CLR:1080 case FSL_XCVR_ISR_TOG:1081 case FSL_XCVR_PHY_AI_CTRL:1082 case FSL_XCVR_PHY_AI_CTRL_SET:1083 case FSL_XCVR_PHY_AI_CTRL_CLR:1084 case FSL_XCVR_PHY_AI_CTRL_TOG:1085 case FSL_XCVR_PHY_AI_RDATA:1086 case FSL_XCVR_CLK_CTRL:1087 case FSL_XCVR_RX_DPTH_CTRL:1088 case FSL_XCVR_RX_DPTH_CTRL_SET:1089 case FSL_XCVR_RX_DPTH_CTRL_CLR:1090 case FSL_XCVR_RX_DPTH_CTRL_TOG:1091 case FSL_XCVR_RX_CS_DATA_0:1092 case FSL_XCVR_RX_CS_DATA_1:1093 case FSL_XCVR_RX_CS_DATA_2:1094 case FSL_XCVR_RX_CS_DATA_3:1095 case FSL_XCVR_RX_CS_DATA_4:1096 case FSL_XCVR_RX_CS_DATA_5:1097 case FSL_XCVR_RX_DPTH_CNTR_CTRL:1098 case FSL_XCVR_RX_DPTH_CNTR_CTRL_SET:1099 case FSL_XCVR_RX_DPTH_CNTR_CTRL_CLR:1100 case FSL_XCVR_RX_DPTH_CNTR_CTRL_TOG:1101 case FSL_XCVR_RX_DPTH_TSCR:1102 case FSL_XCVR_RX_DPTH_BCR:1103 case FSL_XCVR_RX_DPTH_BCTR:1104 case FSL_XCVR_RX_DPTH_BCRR:1105 case FSL_XCVR_TX_DPTH_CTRL:1106 case FSL_XCVR_TX_DPTH_CTRL_SET:1107 case FSL_XCVR_TX_DPTH_CTRL_CLR:1108 case FSL_XCVR_TX_DPTH_CTRL_TOG:1109 case FSL_XCVR_TX_CS_DATA_0:1110 case FSL_XCVR_TX_CS_DATA_1:1111 case FSL_XCVR_TX_CS_DATA_2:1112 case FSL_XCVR_TX_CS_DATA_3:1113 case FSL_XCVR_TX_CS_DATA_4:1114 case FSL_XCVR_TX_CS_DATA_5:1115 case FSL_XCVR_TX_DPTH_CNTR_CTRL:1116 case FSL_XCVR_TX_DPTH_CNTR_CTRL_SET:1117 case FSL_XCVR_TX_DPTH_CNTR_CTRL_CLR:1118 case FSL_XCVR_TX_DPTH_CNTR_CTRL_TOG:1119 case FSL_XCVR_TX_DPTH_TSCR:1120 case FSL_XCVR_TX_DPTH_BCR:1121 case FSL_XCVR_TX_DPTH_BCTR:1122 case FSL_XCVR_TX_DPTH_BCRR:1123 case FSL_XCVR_DEBUG_REG_0:1124 case FSL_XCVR_DEBUG_REG_1:1125 return true;1126 default:1127 return false;1128 }1129}1130 1131static bool fsl_xcvr_writeable_reg(struct device *dev, unsigned int reg)1132{1133 struct fsl_xcvr *xcvr = dev_get_drvdata(dev);1134 1135 if (!xcvr->soc_data->use_phy)1136 if (reg >= FSL_XCVR_IER && reg <= FSL_XCVR_PHY_AI_RDATA)1137 return false;1138 switch (reg) {1139 case FSL_XCVR_EXT_CTRL:1140 case FSL_XCVR_EXT_IER0:1141 case FSL_XCVR_EXT_IER1:1142 case FSL_XCVR_EXT_ISR:1143 case FSL_XCVR_EXT_ISR_SET:1144 case FSL_XCVR_EXT_ISR_CLR:1145 case FSL_XCVR_EXT_ISR_TOG:1146 case FSL_XCVR_IER:1147 case FSL_XCVR_ISR_SET:1148 case FSL_XCVR_ISR_CLR:1149 case FSL_XCVR_ISR_TOG:1150 case FSL_XCVR_PHY_AI_CTRL:1151 case FSL_XCVR_PHY_AI_CTRL_SET:1152 case FSL_XCVR_PHY_AI_CTRL_CLR:1153 case FSL_XCVR_PHY_AI_CTRL_TOG:1154 case FSL_XCVR_PHY_AI_WDATA:1155 case FSL_XCVR_CLK_CTRL:1156 case FSL_XCVR_RX_DPTH_CTRL:1157 case FSL_XCVR_RX_DPTH_CTRL_SET:1158 case FSL_XCVR_RX_DPTH_CTRL_CLR:1159 case FSL_XCVR_RX_DPTH_CTRL_TOG:1160 case FSL_XCVR_RX_DPTH_CNTR_CTRL:1161 case FSL_XCVR_RX_DPTH_CNTR_CTRL_SET:1162 case FSL_XCVR_RX_DPTH_CNTR_CTRL_CLR:1163 case FSL_XCVR_RX_DPTH_CNTR_CTRL_TOG:1164 case FSL_XCVR_TX_DPTH_CTRL_SET:1165 case FSL_XCVR_TX_DPTH_CTRL_CLR:1166 case FSL_XCVR_TX_DPTH_CTRL_TOG:1167 case FSL_XCVR_TX_CS_DATA_0:1168 case FSL_XCVR_TX_CS_DATA_1:1169 case FSL_XCVR_TX_CS_DATA_2:1170 case FSL_XCVR_TX_CS_DATA_3:1171 case FSL_XCVR_TX_CS_DATA_4:1172 case FSL_XCVR_TX_CS_DATA_5:1173 case FSL_XCVR_TX_DPTH_CNTR_CTRL:1174 case FSL_XCVR_TX_DPTH_CNTR_CTRL_SET:1175 case FSL_XCVR_TX_DPTH_CNTR_CTRL_CLR:1176 case FSL_XCVR_TX_DPTH_CNTR_CTRL_TOG:1177 return true;1178 default:1179 return false;1180 }1181}1182 1183static bool fsl_xcvr_volatile_reg(struct device *dev, unsigned int reg)1184{1185 return fsl_xcvr_readable_reg(dev, reg);1186}1187 1188static const struct regmap_config fsl_xcvr_regmap_cfg = {1189 .reg_bits = 32,1190 .reg_stride = 4,1191 .val_bits = 32,1192 .max_register = FSL_XCVR_MAX_REG,1193 .reg_defaults = fsl_xcvr_reg_defaults,1194 .num_reg_defaults = ARRAY_SIZE(fsl_xcvr_reg_defaults),1195 .readable_reg = fsl_xcvr_readable_reg,1196 .volatile_reg = fsl_xcvr_volatile_reg,1197 .writeable_reg = fsl_xcvr_writeable_reg,1198 .cache_type = REGCACHE_FLAT,1199};1200 1201static irqreturn_t irq0_isr(int irq, void *devid)1202{1203 struct fsl_xcvr *xcvr = (struct fsl_xcvr *)devid;1204 struct device *dev = &xcvr->pdev->dev;1205 struct regmap *regmap = xcvr->regmap;1206 void __iomem *reg_ctrl, *reg_buff;1207 u32 isr, isr_clr = 0, val, i;1208 1209 regmap_read(regmap, FSL_XCVR_EXT_ISR, &isr);1210 1211 if (isr & FSL_XCVR_IRQ_NEW_CS) {1212 dev_dbg(dev, "Received new CS block\n");1213 isr_clr |= FSL_XCVR_IRQ_NEW_CS;1214 if (!xcvr->soc_data->spdif_only) {1215 /* Data RAM is 4KiB, last two pages: 8 and 9. Select page 8. */1216 regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_CTRL,1217 FSL_XCVR_EXT_CTRL_PAGE_MASK,1218 FSL_XCVR_EXT_CTRL_PAGE(8));1219 1220 /* Find updated CS buffer */1221 reg_ctrl = xcvr->ram_addr + FSL_XCVR_RX_CS_CTRL_0;1222 reg_buff = xcvr->ram_addr + FSL_XCVR_RX_CS_BUFF_0;1223 memcpy_fromio(&val, reg_ctrl, sizeof(val));1224 if (!val) {1225 reg_ctrl = xcvr->ram_addr + FSL_XCVR_RX_CS_CTRL_1;1226 reg_buff = xcvr->ram_addr + FSL_XCVR_RX_CS_BUFF_1;1227 memcpy_fromio(&val, reg_ctrl, sizeof(val));1228 }1229 1230 if (val) {1231 /* copy CS buffer */1232 memcpy_fromio(&xcvr->rx_iec958.status, reg_buff,1233 sizeof(xcvr->rx_iec958.status));1234 for (i = 0; i < 6; i++) {1235 val = *(u32 *)(xcvr->rx_iec958.status + i*4);1236 *(u32 *)(xcvr->rx_iec958.status + i*4) =1237 bitrev32(val);1238 }1239 /* clear CS control register */1240 memset_io(reg_ctrl, 0, sizeof(val));1241 }1242 }1243 }1244 if (isr & FSL_XCVR_IRQ_NEW_UD) {1245 dev_dbg(dev, "Received new UD block\n");1246 isr_clr |= FSL_XCVR_IRQ_NEW_UD;1247 }1248 if (isr & FSL_XCVR_IRQ_MUTE) {1249 dev_dbg(dev, "HW mute bit detected\n");1250 isr_clr |= FSL_XCVR_IRQ_MUTE;1251 }1252 if (isr & FSL_XCVR_IRQ_FIFO_UOFL_ERR) {1253 dev_dbg(dev, "RX/TX FIFO full/empty\n");1254 isr_clr |= FSL_XCVR_IRQ_FIFO_UOFL_ERR;1255 }1256 if (isr & FSL_XCVR_IRQ_ARC_MODE) {1257 dev_dbg(dev, "CMDC SM falls out of eARC mode\n");1258 isr_clr |= FSL_XCVR_IRQ_ARC_MODE;1259 }1260 if (isr & FSL_XCVR_IRQ_DMA_RD_REQ) {1261 dev_dbg(dev, "DMA read request\n");1262 isr_clr |= FSL_XCVR_IRQ_DMA_RD_REQ;1263 }1264 if (isr & FSL_XCVR_IRQ_DMA_WR_REQ) {1265 dev_dbg(dev, "DMA write request\n");1266 isr_clr |= FSL_XCVR_IRQ_DMA_WR_REQ;1267 }1268 1269 if (isr_clr) {1270 regmap_write(regmap, FSL_XCVR_EXT_ISR_CLR, isr_clr);1271 return IRQ_HANDLED;1272 }1273 1274 return IRQ_NONE;1275}1276 1277static const struct fsl_xcvr_soc_data fsl_xcvr_imx8mp_data = {1278 .fw_name = "imx/xcvr/xcvr-imx8mp.bin",1279 .use_phy = true,1280 .pll_ver = PLL_MX8MP,1281};1282 1283static const struct fsl_xcvr_soc_data fsl_xcvr_imx93_data = {1284 .spdif_only = true,1285 .use_edma = true,1286};1287 1288static const struct fsl_xcvr_soc_data fsl_xcvr_imx95_data = {1289 .spdif_only = true,1290 .use_phy = true,1291 .use_edma = true,1292 .pll_ver = PLL_MX95,1293};1294 1295static const struct of_device_id fsl_xcvr_dt_ids[] = {1296 { .compatible = "fsl,imx8mp-xcvr", .data = &fsl_xcvr_imx8mp_data },1297 { .compatible = "fsl,imx93-xcvr", .data = &fsl_xcvr_imx93_data},1298 { .compatible = "fsl,imx95-xcvr", .data = &fsl_xcvr_imx95_data},1299 { /* sentinel */ }1300};1301MODULE_DEVICE_TABLE(of, fsl_xcvr_dt_ids);1302 1303static int fsl_xcvr_probe(struct platform_device *pdev)1304{1305 struct device *dev = &pdev->dev;1306 struct fsl_xcvr *xcvr;1307 struct resource *rx_res, *tx_res;1308 void __iomem *regs;1309 int ret, irq;1310 1311 xcvr = devm_kzalloc(dev, sizeof(*xcvr), GFP_KERNEL);1312 if (!xcvr)1313 return -ENOMEM;1314 1315 xcvr->pdev = pdev;1316 xcvr->soc_data = of_device_get_match_data(&pdev->dev);1317 1318 xcvr->ipg_clk = devm_clk_get(dev, "ipg");1319 if (IS_ERR(xcvr->ipg_clk)) {1320 dev_err(dev, "failed to get ipg clock\n");1321 return PTR_ERR(xcvr->ipg_clk);1322 }1323 1324 xcvr->phy_clk = devm_clk_get(dev, "phy");1325 if (IS_ERR(xcvr->phy_clk)) {1326 dev_err(dev, "failed to get phy clock\n");1327 return PTR_ERR(xcvr->phy_clk);1328 }1329 1330 xcvr->spba_clk = devm_clk_get(dev, "spba");1331 if (IS_ERR(xcvr->spba_clk)) {1332 dev_err(dev, "failed to get spba clock\n");1333 return PTR_ERR(xcvr->spba_clk);1334 }1335 1336 xcvr->pll_ipg_clk = devm_clk_get(dev, "pll_ipg");1337 if (IS_ERR(xcvr->pll_ipg_clk)) {1338 dev_err(dev, "failed to get pll_ipg clock\n");1339 return PTR_ERR(xcvr->pll_ipg_clk);1340 }1341 1342 fsl_asoc_get_pll_clocks(dev, &xcvr->pll8k_clk,1343 &xcvr->pll11k_clk);1344 1345 xcvr->ram_addr = devm_platform_ioremap_resource_byname(pdev, "ram");1346 if (IS_ERR(xcvr->ram_addr))1347 return PTR_ERR(xcvr->ram_addr);1348 1349 regs = devm_platform_ioremap_resource_byname(pdev, "regs");1350 if (IS_ERR(regs))1351 return PTR_ERR(regs);1352 1353 xcvr->regmap = devm_regmap_init_mmio_clk(dev, NULL, regs,1354 &fsl_xcvr_regmap_cfg);1355 if (IS_ERR(xcvr->regmap)) {1356 dev_err(dev, "failed to init XCVR regmap: %ld\n",1357 PTR_ERR(xcvr->regmap));1358 return PTR_ERR(xcvr->regmap);1359 }1360 1361 xcvr->reset = devm_reset_control_get_optional_exclusive(dev, NULL);1362 if (IS_ERR(xcvr->reset)) {1363 dev_err(dev, "failed to get XCVR reset control\n");1364 return PTR_ERR(xcvr->reset);1365 }1366 1367 /* get IRQs */1368 irq = platform_get_irq(pdev, 0);1369 if (irq < 0)1370 return irq;1371 1372 ret = devm_request_irq(dev, irq, irq0_isr, 0, pdev->name, xcvr);1373 if (ret) {1374 dev_err(dev, "failed to claim IRQ0: %i\n", ret);1375 return ret;1376 }1377 1378 rx_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rxfifo");1379 tx_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "txfifo");1380 if (!rx_res || !tx_res) {1381 dev_err(dev, "could not find rxfifo or txfifo resource\n");1382 return -EINVAL;1383 }1384 xcvr->dma_prms_rx.chan_name = "rx";1385 xcvr->dma_prms_tx.chan_name = "tx";1386 xcvr->dma_prms_rx.addr = rx_res->start;1387 xcvr->dma_prms_tx.addr = tx_res->start;1388 xcvr->dma_prms_rx.maxburst = FSL_XCVR_MAXBURST_RX;1389 xcvr->dma_prms_tx.maxburst = FSL_XCVR_MAXBURST_TX;1390 1391 platform_set_drvdata(pdev, xcvr);1392 pm_runtime_enable(dev);1393 regcache_cache_only(xcvr->regmap, true);1394 1395 /*1396 * Register platform component before registering cpu dai for there1397 * is not defer probe for platform component in snd_soc_add_pcm_runtime().1398 */1399 ret = devm_snd_dmaengine_pcm_register(dev, NULL, 0);1400 if (ret) {1401 pm_runtime_disable(dev);1402 dev_err(dev, "failed to pcm register\n");1403 return ret;1404 }1405 1406 ret = devm_snd_soc_register_component(dev, &fsl_xcvr_comp,1407 &fsl_xcvr_dai, 1);1408 if (ret) {1409 pm_runtime_disable(dev);1410 dev_err(dev, "failed to register component %s\n",1411 fsl_xcvr_comp.name);1412 }1413 1414 return ret;1415}1416 1417static void fsl_xcvr_remove(struct platform_device *pdev)1418{1419 pm_runtime_disable(&pdev->dev);1420}1421 1422static int fsl_xcvr_runtime_suspend(struct device *dev)1423{1424 struct fsl_xcvr *xcvr = dev_get_drvdata(dev);1425 int ret;1426 1427 if (!xcvr->soc_data->spdif_only) {1428 /* Assert M0+ reset */1429 ret = regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_CTRL,1430 FSL_XCVR_EXT_CTRL_CORE_RESET,1431 FSL_XCVR_EXT_CTRL_CORE_RESET);1432 if (ret < 0)1433 dev_err(dev, "Failed to assert M0+ core: %d\n", ret);1434 }1435 1436 regcache_cache_only(xcvr->regmap, true);1437 1438 clk_disable_unprepare(xcvr->spba_clk);1439 clk_disable_unprepare(xcvr->phy_clk);1440 clk_disable_unprepare(xcvr->pll_ipg_clk);1441 clk_disable_unprepare(xcvr->ipg_clk);1442 1443 return 0;1444}1445 1446static int fsl_xcvr_runtime_resume(struct device *dev)1447{1448 struct fsl_xcvr *xcvr = dev_get_drvdata(dev);1449 int ret;1450 1451 ret = reset_control_assert(xcvr->reset);1452 if (ret < 0) {1453 dev_err(dev, "Failed to assert M0+ reset: %d\n", ret);1454 return ret;1455 }1456 1457 ret = clk_prepare_enable(xcvr->ipg_clk);1458 if (ret) {1459 dev_err(dev, "failed to start IPG clock.\n");1460 return ret;1461 }1462 1463 ret = clk_prepare_enable(xcvr->pll_ipg_clk);1464 if (ret) {1465 dev_err(dev, "failed to start PLL IPG clock.\n");1466 goto stop_ipg_clk;1467 }1468 1469 ret = clk_prepare_enable(xcvr->phy_clk);1470 if (ret) {1471 dev_err(dev, "failed to start PHY clock: %d\n", ret);1472 goto stop_pll_ipg_clk;1473 }1474 1475 ret = clk_prepare_enable(xcvr->spba_clk);1476 if (ret) {1477 dev_err(dev, "failed to start SPBA clock.\n");1478 goto stop_phy_clk;1479 }1480 1481 regcache_cache_only(xcvr->regmap, false);1482 regcache_mark_dirty(xcvr->regmap);1483 ret = regcache_sync(xcvr->regmap);1484 1485 if (ret) {1486 dev_err(dev, "failed to sync regcache.\n");1487 goto stop_spba_clk;1488 }1489 1490 if (xcvr->soc_data->spdif_only)1491 return 0;1492 1493 ret = reset_control_deassert(xcvr->reset);1494 if (ret) {1495 dev_err(dev, "failed to deassert M0+ reset.\n");1496 goto stop_spba_clk;1497 }1498 1499 ret = fsl_xcvr_load_firmware(xcvr);1500 if (ret) {1501 dev_err(dev, "failed to load firmware.\n");1502 goto stop_spba_clk;1503 }1504 1505 /* Release M0+ reset */1506 ret = regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_CTRL,1507 FSL_XCVR_EXT_CTRL_CORE_RESET, 0);1508 if (ret < 0) {1509 dev_err(dev, "M0+ core release failed: %d\n", ret);1510 goto stop_spba_clk;1511 }1512 1513 /* Let M0+ core complete firmware initialization */1514 msleep(50);1515 1516 return 0;1517 1518stop_spba_clk:1519 clk_disable_unprepare(xcvr->spba_clk);1520stop_phy_clk:1521 clk_disable_unprepare(xcvr->phy_clk);1522stop_pll_ipg_clk:1523 clk_disable_unprepare(xcvr->pll_ipg_clk);1524stop_ipg_clk:1525 clk_disable_unprepare(xcvr->ipg_clk);1526 1527 return ret;1528}1529 1530static const struct dev_pm_ops fsl_xcvr_pm_ops = {1531 RUNTIME_PM_OPS(fsl_xcvr_runtime_suspend, fsl_xcvr_runtime_resume, NULL)1532 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,1533 pm_runtime_force_resume)1534};1535 1536static struct platform_driver fsl_xcvr_driver = {1537 .probe = fsl_xcvr_probe,1538 .driver = {1539 .name = "fsl,imx8mp-audio-xcvr",1540 .pm = pm_ptr(&fsl_xcvr_pm_ops),1541 .of_match_table = fsl_xcvr_dt_ids,1542 },1543 .remove = fsl_xcvr_remove,1544};1545module_platform_driver(fsl_xcvr_driver);1546 1547MODULE_AUTHOR("Viorel Suman <viorel.suman@nxp.com>");1548MODULE_DESCRIPTION("NXP Audio Transceiver (XCVR) driver");1549MODULE_LICENSE("GPL v2");1550