Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ASoC: fsl_xcvr: Support i.MX95 platform

Merge series from Shengjiu Wang <shengjiu.wang@nxp.com>:

On i.MX95 wakeup domain, there is one instance of Audio XCVR
supporting SPDIF mode with a connection to the Audio XCVR physical
interface.

+207 -43
+31 -1
Documentation/devicetree/bindings/sound/fsl,xcvr.yaml
··· 22 22 enum: 23 23 - fsl,imx8mp-xcvr 24 24 - fsl,imx93-xcvr 25 + - fsl,imx95-xcvr 25 26 26 27 reg: 27 28 items: ··· 50 49 - description: PHY clock 51 50 - description: SPBA clock 52 51 - description: PLL clock 52 + - description: PLL clock source for 8kHz series 53 + - description: PLL clock source for 11kHz series 54 + minItems: 4 53 55 54 56 clock-names: 55 57 items: ··· 60 56 - const: phy 61 57 - const: spba 62 58 - const: pll_ipg 59 + - const: pll8k 60 + - const: pll11k 61 + minItems: 4 63 62 64 63 dmas: 65 64 items: ··· 86 79 - clock-names 87 80 - dmas 88 81 - dma-names 89 - - resets 90 82 91 83 allOf: 92 84 - if: 93 85 properties: 94 86 compatible: 95 87 contains: 88 + const: fsl,imx8mp-xcvr 89 + then: 90 + required: 91 + - resets 92 + 93 + - if: 94 + properties: 95 + compatible: 96 + contains: 96 97 enum: 97 98 - fsl,imx93-xcvr 99 + - fsl,imx95-xcvr 98 100 then: 99 101 properties: 100 102 interrupts: ··· 113 97 properties: 114 98 interrupts: 115 99 maxItems: 1 100 + 101 + - if: 102 + properties: 103 + compatible: 104 + contains: 105 + enum: 106 + - fsl,imx8mp-xcvr 107 + - fsl,imx93-xcvr 108 + then: 109 + properties: 110 + clocks: 111 + maxItems: 4 112 + clock-names: 113 + maxItems: 4 116 114 117 115 additionalProperties: false 118 116
+1
sound/soc/fsl/Kconfig
··· 103 103 select REGMAP_MMIO 104 104 select SND_SOC_IMX_PCM_DMA if SND_IMX_SOC != n 105 105 select SND_SOC_GENERIC_DMAENGINE_PCM 106 + select SND_SOC_FSL_UTILS 106 107 help 107 108 Say Y if you want to add Audio Transceiver (XCVR) support for NXP 108 109 iMX CPUs. XCVR is a digital module that supports HDMI2.1 eARC,
+84 -42
sound/soc/fsl/fsl_xcvr.c
··· 15 15 #include <sound/pcm_params.h> 16 16 17 17 #include "fsl_xcvr.h" 18 + #include "fsl_utils.h" 18 19 #include "imx-pcm.h" 19 20 20 21 #define FSL_XCVR_CAPDS_SIZE 256 22 + 23 + enum fsl_xcvr_pll_verison { 24 + PLL_MX8MP, 25 + PLL_MX95, 26 + }; 21 27 22 28 struct fsl_xcvr_soc_data { 23 29 const char *fw_name; 24 30 bool spdif_only; 25 31 bool use_edma; 32 + bool use_phy; 33 + enum fsl_xcvr_pll_verison pll_ver; 26 34 }; 27 35 28 36 struct fsl_xcvr { ··· 41 33 struct clk *pll_ipg_clk; 42 34 struct clk *phy_clk; 43 35 struct clk *spba_clk; 36 + struct clk *pll8k_clk; 37 + struct clk *pll11k_clk; 44 38 struct reset_control *reset; 45 39 u8 streams; 46 40 u32 mode; ··· 272 262 static int fsl_xcvr_en_phy_pll(struct fsl_xcvr *xcvr, u32 freq, bool tx) 273 263 { 274 264 struct device *dev = &xcvr->pdev->dev; 275 - u32 i, div = 0, log2; 265 + u32 i, div = 0, log2, val; 276 266 int ret; 277 267 278 - if (xcvr->soc_data->spdif_only) 268 + if (!xcvr->soc_data->use_phy) 279 269 return 0; 280 270 281 271 for (i = 0; i < ARRAY_SIZE(fsl_xcvr_pll_cfg); i++) { ··· 298 288 return ret; 299 289 } 300 290 301 - /* PLL: BANDGAP_SET: EN_VBG (enable bandgap) */ 302 - fsl_xcvr_ai_write(xcvr, FSL_XCVR_PLL_BANDGAP_SET, 303 - FSL_XCVR_PLL_BANDGAP_EN_VBG, 0); 291 + switch (xcvr->soc_data->pll_ver) { 292 + case PLL_MX8MP: 293 + /* PLL: BANDGAP_SET: EN_VBG (enable bandgap) */ 294 + fsl_xcvr_ai_write(xcvr, FSL_XCVR_PLL_BANDGAP_SET, 295 + FSL_XCVR_PLL_BANDGAP_EN_VBG, 0); 304 296 305 - /* PLL: CTRL0: DIV_INTEGER */ 306 - fsl_xcvr_ai_write(xcvr, FSL_XCVR_PLL_CTRL0, fsl_xcvr_pll_cfg[i].mfi, 0); 307 - /* PLL: NUMERATOR: MFN */ 308 - fsl_xcvr_ai_write(xcvr, FSL_XCVR_PLL_NUM, fsl_xcvr_pll_cfg[i].mfn, 0); 309 - /* PLL: DENOMINATOR: MFD */ 310 - fsl_xcvr_ai_write(xcvr, FSL_XCVR_PLL_DEN, fsl_xcvr_pll_cfg[i].mfd, 0); 311 - /* PLL: CTRL0_SET: HOLD_RING_OFF, POWER_UP */ 312 - fsl_xcvr_ai_write(xcvr, FSL_XCVR_PLL_CTRL0_SET, 313 - FSL_XCVR_PLL_CTRL0_HROFF | FSL_XCVR_PLL_CTRL0_PWP, 0); 314 - udelay(25); 315 - /* PLL: CTRL0: Clear Hold Ring Off */ 316 - fsl_xcvr_ai_write(xcvr, FSL_XCVR_PLL_CTRL0_CLR, 317 - FSL_XCVR_PLL_CTRL0_HROFF, 0); 318 - udelay(100); 319 - if (tx) { /* TX is enabled for SPDIF only */ 320 - /* PLL: POSTDIV: PDIV0 */ 321 - fsl_xcvr_ai_write(xcvr, FSL_XCVR_PLL_PDIV, 322 - FSL_XCVR_PLL_PDIVx(log2, 0), 0); 323 - /* PLL: CTRL_SET: CLKMUX0_EN */ 297 + /* PLL: CTRL0: DIV_INTEGER */ 298 + fsl_xcvr_ai_write(xcvr, FSL_XCVR_PLL_CTRL0, fsl_xcvr_pll_cfg[i].mfi, 0); 299 + /* PLL: NUMERATOR: MFN */ 300 + fsl_xcvr_ai_write(xcvr, FSL_XCVR_PLL_NUM, fsl_xcvr_pll_cfg[i].mfn, 0); 301 + /* PLL: DENOMINATOR: MFD */ 302 + fsl_xcvr_ai_write(xcvr, FSL_XCVR_PLL_DEN, fsl_xcvr_pll_cfg[i].mfd, 0); 303 + /* PLL: CTRL0_SET: HOLD_RING_OFF, POWER_UP */ 324 304 fsl_xcvr_ai_write(xcvr, FSL_XCVR_PLL_CTRL0_SET, 325 - FSL_XCVR_PLL_CTRL0_CM0_EN, 0); 326 - } else if (xcvr->mode == FSL_XCVR_MODE_EARC) { /* eARC RX */ 327 - /* PLL: POSTDIV: PDIV1 */ 328 - fsl_xcvr_ai_write(xcvr, FSL_XCVR_PLL_PDIV, 329 - FSL_XCVR_PLL_PDIVx(log2, 1), 0); 330 - /* PLL: CTRL_SET: CLKMUX1_EN */ 331 - fsl_xcvr_ai_write(xcvr, FSL_XCVR_PLL_CTRL0_SET, 332 - FSL_XCVR_PLL_CTRL0_CM1_EN, 0); 333 - } else { /* SPDIF / ARC RX */ 334 - /* PLL: POSTDIV: PDIV2 */ 335 - fsl_xcvr_ai_write(xcvr, FSL_XCVR_PLL_PDIV, 336 - FSL_XCVR_PLL_PDIVx(log2, 2), 0); 337 - /* PLL: CTRL_SET: CLKMUX2_EN */ 338 - fsl_xcvr_ai_write(xcvr, FSL_XCVR_PLL_CTRL0_SET, 339 - FSL_XCVR_PLL_CTRL0_CM2_EN, 0); 305 + FSL_XCVR_PLL_CTRL0_HROFF | FSL_XCVR_PLL_CTRL0_PWP, 0); 306 + udelay(25); 307 + /* PLL: CTRL0: Clear Hold Ring Off */ 308 + fsl_xcvr_ai_write(xcvr, FSL_XCVR_PLL_CTRL0_CLR, 309 + FSL_XCVR_PLL_CTRL0_HROFF, 0); 310 + udelay(100); 311 + if (tx) { /* TX is enabled for SPDIF only */ 312 + /* PLL: POSTDIV: PDIV0 */ 313 + fsl_xcvr_ai_write(xcvr, FSL_XCVR_PLL_PDIV, 314 + FSL_XCVR_PLL_PDIVx(log2, 0), 0); 315 + /* PLL: CTRL_SET: CLKMUX0_EN */ 316 + fsl_xcvr_ai_write(xcvr, FSL_XCVR_PLL_CTRL0_SET, 317 + FSL_XCVR_PLL_CTRL0_CM0_EN, 0); 318 + } else if (xcvr->mode == FSL_XCVR_MODE_EARC) { /* eARC RX */ 319 + /* PLL: POSTDIV: PDIV1 */ 320 + fsl_xcvr_ai_write(xcvr, FSL_XCVR_PLL_PDIV, 321 + FSL_XCVR_PLL_PDIVx(log2, 1), 0); 322 + /* PLL: CTRL_SET: CLKMUX1_EN */ 323 + fsl_xcvr_ai_write(xcvr, FSL_XCVR_PLL_CTRL0_SET, 324 + FSL_XCVR_PLL_CTRL0_CM1_EN, 0); 325 + } else { /* SPDIF / ARC RX */ 326 + /* PLL: POSTDIV: PDIV2 */ 327 + fsl_xcvr_ai_write(xcvr, FSL_XCVR_PLL_PDIV, 328 + FSL_XCVR_PLL_PDIVx(log2, 2), 0); 329 + /* PLL: CTRL_SET: CLKMUX2_EN */ 330 + fsl_xcvr_ai_write(xcvr, FSL_XCVR_PLL_CTRL0_SET, 331 + FSL_XCVR_PLL_CTRL0_CM2_EN, 0); 332 + } 333 + break; 334 + case PLL_MX95: 335 + val = fsl_xcvr_pll_cfg[i].mfi << FSL_XCVR_GP_PLL_DIV_MFI_SHIFT | div; 336 + fsl_xcvr_ai_write(xcvr, FSL_XCVR_GP_PLL_DIV, val, 0); 337 + val = fsl_xcvr_pll_cfg[i].mfn << FSL_XCVR_GP_PLL_NUMERATOR_MFN_SHIFT; 338 + fsl_xcvr_ai_write(xcvr, FSL_XCVR_GP_PLL_NUMERATOR, val, 0); 339 + fsl_xcvr_ai_write(xcvr, FSL_XCVR_GP_PLL_DENOMINATOR, 340 + fsl_xcvr_pll_cfg[i].mfd, 0); 341 + val = FSL_XCVR_GP_PLL_CTRL_POWERUP | FSL_XCVR_GP_PLL_CTRL_CLKMUX_EN; 342 + fsl_xcvr_ai_write(xcvr, FSL_XCVR_GP_PLL_CTRL, val, 0); 343 + break; 344 + default: 345 + dev_err(dev, "Error for PLL version %d\n", xcvr->soc_data->pll_ver); 346 + return -EINVAL; 340 347 } 341 348 342 349 if (xcvr->mode == FSL_XCVR_MODE_EARC) { /* eARC mode */ ··· 389 362 390 363 freq = xcvr->soc_data->spdif_only ? freq / 5 : freq; 391 364 clk_disable_unprepare(xcvr->phy_clk); 365 + fsl_asoc_reparent_pll_clocks(dev, xcvr->phy_clk, 366 + xcvr->pll8k_clk, xcvr->pll11k_clk, freq); 392 367 ret = clk_set_rate(xcvr->phy_clk, freq); 393 368 if (ret < 0) { 394 369 dev_err(dev, "Error while setting AUD PLL rate: %d\n", ret); ··· 402 373 return ret; 403 374 } 404 375 405 - if (xcvr->soc_data->spdif_only) 376 + if (!xcvr->soc_data->use_phy) 406 377 return 0; 407 378 /* Release AI interface from reset */ 408 379 ret = regmap_write(xcvr->regmap, FSL_XCVR_PHY_AI_CTRL_SET, ··· 1046 1017 { 1047 1018 struct fsl_xcvr *xcvr = dev_get_drvdata(dev); 1048 1019 1049 - if (xcvr->soc_data->spdif_only) 1020 + if (!xcvr->soc_data->use_phy) 1050 1021 if ((reg >= FSL_XCVR_IER && reg <= FSL_XCVR_PHY_AI_RDATA) || 1051 1022 reg > FSL_XCVR_TX_DPTH_BCRR) 1052 1023 return false; ··· 1119 1090 { 1120 1091 struct fsl_xcvr *xcvr = dev_get_drvdata(dev); 1121 1092 1122 - if (xcvr->soc_data->spdif_only) 1093 + if (!xcvr->soc_data->use_phy) 1123 1094 if (reg >= FSL_XCVR_IER && reg <= FSL_XCVR_PHY_AI_RDATA) 1124 1095 return false; 1125 1096 switch (reg) { ··· 1263 1234 1264 1235 static const struct fsl_xcvr_soc_data fsl_xcvr_imx8mp_data = { 1265 1236 .fw_name = "imx/xcvr/xcvr-imx8mp.bin", 1237 + .use_phy = true, 1238 + .pll_ver = PLL_MX8MP, 1266 1239 }; 1267 1240 1268 1241 static const struct fsl_xcvr_soc_data fsl_xcvr_imx93_data = { ··· 1272 1241 .use_edma = true, 1273 1242 }; 1274 1243 1244 + static const struct fsl_xcvr_soc_data fsl_xcvr_imx95_data = { 1245 + .spdif_only = true, 1246 + .use_phy = true, 1247 + .use_edma = true, 1248 + .pll_ver = PLL_MX95, 1249 + }; 1250 + 1275 1251 static const struct of_device_id fsl_xcvr_dt_ids[] = { 1276 1252 { .compatible = "fsl,imx8mp-xcvr", .data = &fsl_xcvr_imx8mp_data }, 1277 1253 { .compatible = "fsl,imx93-xcvr", .data = &fsl_xcvr_imx93_data}, 1254 + { .compatible = "fsl,imx95-xcvr", .data = &fsl_xcvr_imx95_data}, 1278 1255 { /* sentinel */ } 1279 1256 }; 1280 1257 MODULE_DEVICE_TABLE(of, fsl_xcvr_dt_ids); ··· 1325 1286 dev_err(dev, "failed to get pll_ipg clock\n"); 1326 1287 return PTR_ERR(xcvr->pll_ipg_clk); 1327 1288 } 1289 + 1290 + fsl_asoc_get_pll_clocks(dev, &xcvr->pll8k_clk, 1291 + &xcvr->pll11k_clk); 1328 1292 1329 1293 xcvr->ram_addr = devm_platform_ioremap_resource_byname(pdev, "ram"); 1330 1294 if (IS_ERR(xcvr->ram_addr))
+91
sound/soc/fsl/fsl_xcvr.h
··· 291 291 #define FSL_XCVR_RX_CS_BUFF_1 0xA0 /* Second RX CS buffer */ 292 292 #define FSL_XCVR_CAP_DATA_STR 0x300 /* Capabilities data structure */ 293 293 294 + /* GP PLL Registers */ 295 + #define FSL_XCVR_GP_PLL_CTRL 0x00 296 + #define FSL_XCVR_GP_PLL_CTRL_SET 0x04 297 + #define FSL_XCVR_GP_PLL_CTRL_CLR 0x08 298 + #define FSL_XCVR_GP_PLL_CTRL_TOG 0x0C 299 + #define FSL_XCVR_GP_PLL_ANA_PRG 0x10 300 + #define FSL_XCVR_GP_PLL_ANA_PRG_SET 0x14 301 + #define FSL_XCVR_GP_PLL_ANA_PRG_CLR 0x18 302 + #define FSL_XCVR_GP_PLL_ANA_PRG_TOG 0x1C 303 + #define FSL_XCVR_GP_PLL_TEST 0x20 304 + #define FSL_XCVR_GP_PLL_TEST_SET 0x24 305 + #define FSL_XCVR_GP_PLL_TEST_CLR 0x28 306 + #define FSL_XCVR_GP_PLL_TEST_TOG 0x2C 307 + #define FSL_XCVR_GP_PLL_SPREAD_SPECTRUM 0x30 308 + #define FSL_XCVR_GP_PLL_SPREAD_SPECTRUM_SET 0x34 309 + #define FSL_XCVR_GP_PLL_SPREAD_SPECTRUM_CLR 0x38 310 + #define FSL_XCVR_GP_PLL_SPREAD_SPECTRUM_TOG 0x3C 311 + #define FSL_XCVR_GP_PLL_NUMERATOR 0x40 312 + #define FSL_XCVR_GP_PLL_NUMERATOR_SET 0x44 313 + #define FSL_XCVR_GP_PLL_NUMERATOR_CLR 0x48 314 + #define FSL_XCVR_GP_PLL_NUMERATOR_TOG 0x4C 315 + #define FSL_XCVR_GP_PLL_DENOMINATOR 0x50 316 + #define FSL_XCVR_GP_PLL_DENOMINATOR_SET 0x54 317 + #define FSL_XCVR_GP_PLL_DENOMINATOR_CLR 0x58 318 + #define FSL_XCVR_GP_PLL_DENOMINATOR_TOG 0x5C 319 + #define FSL_XCVR_GP_PLL_DIV 0x60 320 + #define FSL_XCVR_GP_PLL_DIV_SET 0x64 321 + #define FSL_XCVR_GP_PLL_DIV_CLR 0x68 322 + #define FSL_XCVR_GP_PLL_DIV_TOG 0x6C 323 + #define FSL_XCVR_GP_PLL_DFS_CTRL0 0x70 324 + #define FSL_XCVR_GP_PLL_DFS_CTRL0_SET 0x74 325 + #define FSL_XCVR_GP_PLL_DFS_CTRL0_CLR 0x78 326 + #define FSL_XCVR_GP_PLL_DFS_CTRL0_TOG 0x7C 327 + #define FSL_XCVR_GP_PLL_DFS_DIV0 0x80 328 + #define FSL_XCVR_GP_PLL_DFS_DIV0_SET 0x84 329 + #define FSL_XCVR_GP_PLL_DFS_DIV0_CLR 0x88 330 + #define FSL_XCVR_GP_PLL_DFS_DIV0_TOG 0x8C 331 + #define FSL_XCVR_GP_PLL_DFS_CTRL1 0x90 332 + #define FSL_XCVR_GP_PLL_DFS_CTRL1_SET 0x94 333 + #define FSL_XCVR_GP_PLL_DFS_CTRL1_CLR 0x98 334 + #define FSL_XCVR_GP_PLL_DFS_CTRL1_TOG 0x9C 335 + #define FSL_XCVR_GP_PLL_DFS_DIV1 0xA0 336 + #define FSL_XCVR_GP_PLL_DFS_DIV1_SET 0xA4 337 + #define FSL_XCVR_GP_PLL_DFS_DIV1_CLR 0xA8 338 + #define FSL_XCVR_GP_PLL_DFS_DIV1_TOG 0xAC 339 + #define FSL_XCVR_GP_PLL_DFS_CTRL2 0xB0 340 + #define FSL_XCVR_GP_PLL_DFS_CTRL2_SET 0xB4 341 + #define FSL_XCVR_GP_PLL_DFS_CTRL2_CLR 0xB8 342 + #define FSL_XCVR_GP_PLL_DFS_CTRL2_TOG 0xBC 343 + #define FSL_XCVR_GP_PLL_DFS_DIV2 0xC0 344 + #define FSL_XCVR_GP_PLL_DFS_DIV2_SET 0xC4 345 + #define FSL_XCVR_GP_PLL_DFS_DIV2_CLR 0xC8 346 + #define FSL_XCVR_GP_PLL_DFS_DIV2_TOG 0xCC 347 + #define FSL_XCVR_GP_PLL_DFS_CTRL3 0xD0 348 + #define FSL_XCVR_GP_PLL_DFS_CTRL3_SET 0xD4 349 + #define FSL_XCVR_GP_PLL_DFS_CTRL3_CLR 0xD8 350 + #define FSL_XCVR_GP_PLL_DFS_CTRL3_TOG 0xDC 351 + #define FSL_XCVR_GP_PLL_DFS_DIV3 0xE0 352 + #define FSL_XCVR_GP_PLL_DFS_DIV3_SET 0xE4 353 + #define FSL_XCVR_GP_PLL_DFS_DIV3_CLR 0xE8 354 + #define FSL_XCVR_GP_PLL_DFS_DIV3_TOG 0xEC 355 + #define FSL_XCVR_GP_PLL_STATUS 0xF0 356 + #define FSL_XCVR_GP_PLL_STATUS_SET 0xF4 357 + #define FSL_XCVR_GP_PLL_STATUS_CLR 0xF8 358 + #define FSL_XCVR_GP_PLL_STATUS_TOG 0xFC 359 + 360 + /* GP PLL Control Register */ 361 + #define FSL_XCVR_GP_PLL_CTRL_LBYPASS BIT(31) 362 + #define FSL_XCVR_GP_PLL_CTRL_HCS BIT(16) 363 + #define FSL_XCVR_GP_PLL_CTRL_MSD BIT(12) 364 + #define FSL_XCVR_GP_PLL_CTRL_DITHER_EN3 BIT(11) 365 + #define FSL_XCVR_GP_PLL_CTRL_DITHER_EN2 BIT(10) 366 + #define FSL_XCVR_GP_PLL_CTRL_DITHER_EN1 BIT(9) 367 + #define FSL_XCVR_GP_PLL_CTRL_SPREADCTL BIT(8) 368 + #define FSL_XCVR_GP_PLL_CTRL_CLKMUX_BYPASS BIT(2) 369 + #define FSL_XCVR_GP_PLL_CTRL_CLKMUX_EN BIT(1) 370 + #define FSL_XCVR_GP_PLL_CTRL_POWERUP BIT(0) 371 + 372 + /* GP PLL Numerator Register */ 373 + #define FSL_XCVR_GP_PLL_NUMERATOR_MFN_SHIFT 2 374 + #define FSL_XCVR_GP_PLL_NUMERATOR_MFN GENMASK(31, 2) 375 + 376 + /* GP PLL Denominator Register */ 377 + #define FSL_XCVR_GP_PLL_DENOMINATOR_MFD GENMASK(29, 0) 378 + 379 + /* GP PLL Dividers Register */ 380 + #define FSL_XCVR_GP_PLL_DIV_MFI_SHIFT 16 381 + #define FSL_XCVR_GP_PLL_DIV_MFI GENMASK(24, 16) 382 + #define FSL_XCVR_GP_PLL_DIV_RDIV GENMASK(15, 13) 383 + #define FSL_XCVR_GP_PLL_DIV_ODIV GENMASK(7, 0) 384 + 294 385 #endif /* __FSL_XCVR_H */