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: rockchip: spdif: Cleanups and port features

Merge series from Sebastian Reichel <sebastian.reichel@collabora.com>:

I'm currently working on DisplayPort audio support for the Rockchip
RK3588/RK3576 SoCs, which preferrably use S/PDIF as DAI source.

Apparently the upstream Rockchip S/PDIF driver is lacking a couple of
features right now, which are necessary to get things going (i.e.
setting the sysclk from the machine driver). I found the missing bits
in Rockchip's 6.1 BSP kernel and ported them over. This series effectly
brings the mainline kernel on-par with the BSP driver, but also contains
a couple of cleanup patches of my own to bring the driver to the modern
age.

+176 -107
+1
sound/soc/rockchip/Kconfig
··· 41 41 42 42 config SND_SOC_ROCKCHIP_SPDIF 43 43 tristate "Rockchip SPDIF Device Driver" 44 + select SND_PCM_IEC958 44 45 select SND_SOC_GENERIC_DMAENGINE_PCM 45 46 help 46 47 Say Y or M if you want to add support for SPDIF driver for
+140 -85
sound/soc/rockchip/rockchip_spdif.c
··· 5 5 * 6 6 * Copyright (c) 2014 Rockchip Electronics Co. Ltd. 7 7 * Author: Jianqun <jay.xu@rock-chips.com> 8 - * Copyright (c) 2015 Collabora Ltd. 8 + * Copyright (c) 2015-2026 Collabora Ltd. 9 9 * Author: Sjoerd Simons <sjoerd.simons@collabora.co.uk> 10 10 */ 11 11 12 + #include <linux/bitfield.h> 12 13 #include <linux/module.h> 13 14 #include <linux/delay.h> 14 15 #include <linux/clk.h> ··· 17 16 #include <linux/mfd/syscon.h> 18 17 #include <linux/regmap.h> 19 18 #include <sound/pcm_params.h> 19 + #include <sound/pcm_iec958.h> 20 20 #include <sound/dmaengine_pcm.h> 21 21 22 22 #include "rockchip_spdif.h" ··· 29 27 RK_SPDIF_RK3366, 30 28 }; 31 29 32 - #define RK3288_GRF_SOC_CON2 0x24c 30 + /* 31 + * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | 32 + * CS0: | Mode | d | c | b | a | 33 + * CS1: | Category Code | 34 + * CS2: | Channel Number | Source Number | 35 + * CS3: | Clock Accuracy | Sample Freq | 36 + * CS4: | Ori Sample Freq | Word Length | 37 + * CS5: | | CGMS-A | 38 + * CS6~CS23: Reserved 39 + * 40 + * a: use of channel status block 41 + * b: linear PCM identification: 0 for lpcm, 1 for nlpcm 42 + * c: copyright information 43 + * d: additional format information 44 + */ 45 + #define CS_BYTE 6 46 + #define CS_FRAME(c) ((c) << 16 | (c)) 47 + 48 + #define RK3288_GRF_SOC_CON2 0x24c 33 49 34 50 struct rk_spdif_dev { 35 51 struct device *dev; ··· 59 39 60 40 struct regmap *regmap; 61 41 }; 62 - 63 - static const struct of_device_id rk_spdif_match[] __maybe_unused = { 64 - { .compatible = "rockchip,rk3066-spdif", 65 - .data = (void *)RK_SPDIF_RK3066 }, 66 - { .compatible = "rockchip,rk3188-spdif", 67 - .data = (void *)RK_SPDIF_RK3188 }, 68 - { .compatible = "rockchip,rk3228-spdif", 69 - .data = (void *)RK_SPDIF_RK3366 }, 70 - { .compatible = "rockchip,rk3288-spdif", 71 - .data = (void *)RK_SPDIF_RK3288 }, 72 - { .compatible = "rockchip,rk3328-spdif", 73 - .data = (void *)RK_SPDIF_RK3366 }, 74 - { .compatible = "rockchip,rk3366-spdif", 75 - .data = (void *)RK_SPDIF_RK3366 }, 76 - { .compatible = "rockchip,rk3368-spdif", 77 - .data = (void *)RK_SPDIF_RK3366 }, 78 - { .compatible = "rockchip,rk3399-spdif", 79 - .data = (void *)RK_SPDIF_RK3366 }, 80 - { .compatible = "rockchip,rk3568-spdif", 81 - .data = (void *)RK_SPDIF_RK3366 }, 82 - {}, 83 - }; 84 - MODULE_DEVICE_TABLE(of, rk_spdif_match); 85 42 86 43 static int rk_spdif_runtime_suspend(struct device *dev) 87 44 { ··· 106 109 struct snd_soc_dai *dai) 107 110 { 108 111 struct rk_spdif_dev *spdif = snd_soc_dai_get_drvdata(dai); 112 + unsigned int mclk_rate = clk_get_rate(spdif->mclk); 109 113 unsigned int val = SPDIF_CFGR_HALFWORD_ENABLE; 110 - int srate, mclk; 111 - int ret; 114 + int bmc, div, ret, i; 115 + u16 *fc; 116 + u8 cs[CS_BYTE]; 112 117 113 - srate = params_rate(params); 114 - mclk = srate * 128; 118 + ret = snd_pcm_create_iec958_consumer_hw_params(params, cs, sizeof(cs)); 119 + if (ret < 0) 120 + return ret; 121 + 122 + fc = (u16 *)cs; 123 + for (i = 0; i < CS_BYTE / 2; i++) 124 + regmap_write(spdif->regmap, SPDIF_CHNSRn(i), CS_FRAME(fc[i])); 125 + 126 + regmap_update_bits(spdif->regmap, SPDIF_CFGR, SPDIF_CFGR_CSE_MASK, 127 + SPDIF_CFGR_CSE_EN); 128 + 129 + /* bmc = 128fs */ 130 + bmc = 128 * params_rate(params); 131 + div = DIV_ROUND_CLOSEST(mclk_rate, bmc); 132 + val |= SPDIF_CFGR_CLK_DIV(div); 115 133 116 134 switch (params_format(params)) { 117 135 case SNDRV_PCM_FORMAT_S16_LE: 118 136 val |= SPDIF_CFGR_VDW_16; 137 + val |= SPDIF_CFGR_ADJ_RIGHT_J; 119 138 break; 120 139 case SNDRV_PCM_FORMAT_S20_3LE: 121 140 val |= SPDIF_CFGR_VDW_20; 141 + val |= SPDIF_CFGR_ADJ_RIGHT_J; 122 142 break; 123 143 case SNDRV_PCM_FORMAT_S24_LE: 124 144 val |= SPDIF_CFGR_VDW_24; 145 + val |= SPDIF_CFGR_ADJ_RIGHT_J; 146 + break; 147 + case SNDRV_PCM_FORMAT_S32_LE: 148 + val |= SPDIF_CFGR_VDW_24; 149 + val |= SPDIF_CFGR_ADJ_LEFT_J; 125 150 break; 126 151 default: 127 152 return -EINVAL; 128 153 } 129 154 130 - /* Set clock and calculate divider */ 131 - ret = clk_set_rate(spdif->mclk, mclk); 132 - if (ret != 0) { 133 - dev_err(spdif->dev, "Failed to set module clock rate: %d\n", 134 - ret); 135 - return ret; 136 - } 155 + /* 156 + * clear MCLK domain logic before setting Fmclk and Fsdo to ensure 157 + * that switching between S16_LE and S32_LE audio does not result 158 + * in accidential channels swap. 159 + */ 160 + regmap_update_bits(spdif->regmap, SPDIF_CFGR, SPDIF_CFGR_CLR_MASK, 161 + SPDIF_CFGR_CLR_EN); 162 + udelay(1); 137 163 138 164 ret = regmap_update_bits(spdif->regmap, SPDIF_CFGR, 139 165 SPDIF_CFGR_CLK_DIV_MASK | 140 - SPDIF_CFGR_HALFWORD_ENABLE | 141 - SDPIF_CFGR_VDW_MASK, val); 166 + SPDIF_CFGR_HALFWORD_MASK | 167 + SDPIF_CFGR_VDW_MASK | 168 + SPDIF_CFGR_ADJ_MASK, val); 142 169 143 170 return ret; 144 171 } ··· 178 157 case SNDRV_PCM_TRIGGER_RESUME: 179 158 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 180 159 ret = regmap_update_bits(spdif->regmap, SPDIF_DMACR, 181 - SPDIF_DMACR_TDE_ENABLE | 160 + SPDIF_DMACR_TDE_MASK | 182 161 SPDIF_DMACR_TDL_MASK, 183 162 SPDIF_DMACR_TDE_ENABLE | 184 163 SPDIF_DMACR_TDL(16)); ··· 187 166 return ret; 188 167 189 168 ret = regmap_update_bits(spdif->regmap, SPDIF_XFER, 190 - SPDIF_XFER_TXS_START, 169 + SPDIF_XFER_TXS_MASK, 191 170 SPDIF_XFER_TXS_START); 192 171 break; 193 172 case SNDRV_PCM_TRIGGER_SUSPEND: 194 173 case SNDRV_PCM_TRIGGER_STOP: 195 174 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 196 175 ret = regmap_update_bits(spdif->regmap, SPDIF_DMACR, 197 - SPDIF_DMACR_TDE_ENABLE, 176 + SPDIF_DMACR_TDE_MASK, 198 177 SPDIF_DMACR_TDE_DISABLE); 199 178 200 179 if (ret != 0) 201 180 return ret; 202 181 203 182 ret = regmap_update_bits(spdif->regmap, SPDIF_XFER, 204 - SPDIF_XFER_TXS_START, 183 + SPDIF_XFER_TXS_MASK, 205 184 SPDIF_XFER_TXS_STOP); 206 185 break; 207 186 default: ··· 221 200 return 0; 222 201 } 223 202 203 + static int rk_spdif_set_sysclk(struct snd_soc_dai *dai, 204 + int clk_id, unsigned int freq, int dir) 205 + { 206 + struct rk_spdif_dev *spdif = snd_soc_dai_get_drvdata(dai); 207 + int ret; 208 + 209 + if (!freq) 210 + return 0; 211 + 212 + ret = clk_set_rate(spdif->mclk, freq); 213 + if (ret) 214 + dev_err(spdif->dev, "Failed to set mclk: %d\n", ret); 215 + 216 + return ret; 217 + } 218 + 224 219 static const struct snd_soc_dai_ops rk_spdif_dai_ops = { 220 + .set_sysclk = rk_spdif_set_sysclk, 225 221 .probe = rk_spdif_dai_probe, 226 222 .hw_params = rk_spdif_hw_params, 227 223 .trigger = rk_spdif_trigger, ··· 249 211 .stream_name = "Playback", 250 212 .channels_min = 2, 251 213 .channels_max = 2, 252 - .rates = (SNDRV_PCM_RATE_32000 | 253 - SNDRV_PCM_RATE_44100 | 254 - SNDRV_PCM_RATE_48000 | 255 - SNDRV_PCM_RATE_96000 | 256 - SNDRV_PCM_RATE_192000), 214 + .rates = SNDRV_PCM_RATE_8000_192000, 257 215 .formats = (SNDRV_PCM_FMTBIT_S16_LE | 258 216 SNDRV_PCM_FMTBIT_S20_3LE | 259 - SNDRV_PCM_FMTBIT_S24_LE), 217 + SNDRV_PCM_FMTBIT_S24_LE | 218 + SNDRV_PCM_FMTBIT_S32_LE), 260 219 }, 261 220 .ops = &rk_spdif_dai_ops, 262 221 }; ··· 271 236 case SPDIF_INTCR: 272 237 case SPDIF_XFER: 273 238 case SPDIF_SMPDR: 239 + case SPDIF_VLDFRn(0) ... SPDIF_VLDFRn(11): 240 + case SPDIF_USRDRn(0) ... SPDIF_USRDRn(11): 241 + case SPDIF_CHNSRn(0) ... SPDIF_CHNSRn(11): 274 242 return true; 275 243 default: 276 244 return false; ··· 289 251 case SPDIF_INTSR: 290 252 case SPDIF_XFER: 291 253 case SPDIF_SMPDR: 254 + case SPDIF_VLDFRn(0) ... SPDIF_VLDFRn(11): 255 + case SPDIF_USRDRn(0) ... SPDIF_USRDRn(11): 256 + case SPDIF_CHNSRn(0) ... SPDIF_CHNSRn(11): 292 257 return true; 293 258 default: 294 259 return false; ··· 314 273 .reg_bits = 32, 315 274 .reg_stride = 4, 316 275 .val_bits = 32, 317 - .max_register = SPDIF_SMPDR, 276 + .max_register = SPDIF_VERSION, 318 277 .writeable_reg = rk_spdif_wr_reg, 319 278 .readable_reg = rk_spdif_rd_reg, 320 279 .volatile_reg = rk_spdif_volatile_reg, 321 280 .cache_type = REGCACHE_FLAT, 322 281 }; 323 282 283 + static void rk_spdif_suspend(void *data) 284 + { 285 + struct device *dev = data; 286 + 287 + if (!pm_runtime_status_suspended(dev)) 288 + rk_spdif_runtime_suspend(dev); 289 + } 290 + 324 291 static int rk_spdif_probe(struct platform_device *pdev) 325 292 { 326 293 struct device_node *np = pdev->dev.of_node; 294 + enum rk_spdif_type spdif_type; 327 295 struct rk_spdif_dev *spdif; 328 - const struct of_device_id *match; 329 296 struct resource *res; 330 297 void __iomem *regs; 331 298 int ret; 332 299 333 - match = of_match_node(rk_spdif_match, np); 334 - if (match->data == (void *)RK_SPDIF_RK3288) { 300 + spdif_type = (uintptr_t) device_get_match_data(&pdev->dev); 301 + if (spdif_type == RK_SPDIF_RK3288) { 335 302 struct regmap *grf; 336 303 337 304 grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf"); 338 - if (IS_ERR(grf)) { 339 - dev_err(&pdev->dev, 305 + if (IS_ERR(grf)) 306 + return dev_err_probe(&pdev->dev, PTR_ERR(grf), 340 307 "rockchip_spdif missing 'rockchip,grf'\n"); 341 - return PTR_ERR(grf); 342 - } 343 308 344 309 /* Select the 8 channel SPDIF solution on RK3288 as 345 310 * the 2 channel one does not appear to work ··· 381 334 spdif->dev = &pdev->dev; 382 335 dev_set_drvdata(&pdev->dev, spdif); 383 336 384 - pm_runtime_enable(&pdev->dev); 337 + ret = devm_add_action_or_reset(&pdev->dev, rk_spdif_suspend, &pdev->dev); 338 + if (ret) 339 + return ret; 340 + 341 + devm_pm_runtime_enable(&pdev->dev); 342 + 385 343 if (!pm_runtime_enabled(&pdev->dev)) { 386 344 ret = rk_spdif_runtime_resume(&pdev->dev); 387 345 if (ret) 388 - goto err_pm_runtime; 346 + return ret; 389 347 } 348 + 349 + ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); 350 + if (ret) 351 + return dev_err_probe(&pdev->dev, ret, "Could not register PCM\n"); 390 352 391 353 ret = devm_snd_soc_register_component(&pdev->dev, 392 354 &rk_spdif_component, 393 355 &rk_spdif_dai, 1); 394 - if (ret) { 395 - dev_err(&pdev->dev, "Could not register DAI\n"); 396 - goto err_pm_suspend; 397 - } 398 - 399 - ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); 400 - if (ret) { 401 - dev_err(&pdev->dev, "Could not register PCM\n"); 402 - goto err_pm_suspend; 403 - } 356 + if (ret) 357 + return dev_err_probe(&pdev->dev, ret, "Could not register DAI\n"); 404 358 405 359 return 0; 406 - 407 - err_pm_suspend: 408 - if (!pm_runtime_status_suspended(&pdev->dev)) 409 - rk_spdif_runtime_suspend(&pdev->dev); 410 - err_pm_runtime: 411 - pm_runtime_disable(&pdev->dev); 412 - 413 - return ret; 414 - } 415 - 416 - static void rk_spdif_remove(struct platform_device *pdev) 417 - { 418 - pm_runtime_disable(&pdev->dev); 419 - if (!pm_runtime_status_suspended(&pdev->dev)) 420 - rk_spdif_runtime_suspend(&pdev->dev); 421 360 } 422 361 423 362 static const struct dev_pm_ops rk_spdif_pm_ops = { 424 363 RUNTIME_PM_OPS(rk_spdif_runtime_suspend, rk_spdif_runtime_resume, NULL) 425 364 }; 426 365 366 + static const struct of_device_id rk_spdif_match[] = { 367 + { .compatible = "rockchip,rk3066-spdif", 368 + .data = (void *)RK_SPDIF_RK3066 }, 369 + { .compatible = "rockchip,rk3188-spdif", 370 + .data = (void *)RK_SPDIF_RK3188 }, 371 + { .compatible = "rockchip,rk3228-spdif", 372 + .data = (void *)RK_SPDIF_RK3366 }, 373 + { .compatible = "rockchip,rk3288-spdif", 374 + .data = (void *)RK_SPDIF_RK3288 }, 375 + { .compatible = "rockchip,rk3328-spdif", 376 + .data = (void *)RK_SPDIF_RK3366 }, 377 + { .compatible = "rockchip,rk3366-spdif", 378 + .data = (void *)RK_SPDIF_RK3366 }, 379 + { .compatible = "rockchip,rk3368-spdif", 380 + .data = (void *)RK_SPDIF_RK3366 }, 381 + { .compatible = "rockchip,rk3399-spdif", 382 + .data = (void *)RK_SPDIF_RK3366 }, 383 + { .compatible = "rockchip,rk3568-spdif", 384 + .data = (void *)RK_SPDIF_RK3366 }, 385 + {}, 386 + }; 387 + MODULE_DEVICE_TABLE(of, rk_spdif_match); 388 + 427 389 static struct platform_driver rk_spdif_driver = { 428 390 .probe = rk_spdif_probe, 429 - .remove = rk_spdif_remove, 430 391 .driver = { 431 392 .name = "rockchip-spdif", 432 - .of_match_table = of_match_ptr(rk_spdif_match), 393 + .of_match_table = rk_spdif_match, 433 394 .pm = pm_ptr(&rk_spdif_pm_ops), 434 395 }, 435 396 };
+35 -22
sound/soc/rockchip/rockchip_spdif.h
··· 2 2 /* 3 3 * ALSA SoC Audio Layer - Rockchip SPDIF transceiver driver 4 4 * 5 - * Copyright (c) 2015 Collabora Ltd. 5 + * Copyright (c) 2015-2026 Collabora Ltd. 6 6 * Author: Sjoerd Simons <sjoerd.simons@collabora.co.uk> 7 7 */ 8 8 ··· 13 13 * CFGR 14 14 * transfer configuration register 15 15 */ 16 - #define SPDIF_CFGR_CLK_DIV_SHIFT (16) 17 - #define SPDIF_CFGR_CLK_DIV_MASK (0xff << SPDIF_CFGR_CLK_DIV_SHIFT) 18 - #define SPDIF_CFGR_CLK_DIV(x) (x << SPDIF_CFGR_CLK_DIV_SHIFT) 16 + #define SPDIF_CFGR_CLK_DIV_MASK GENMASK(23, 16) 17 + #define SPDIF_CFGR_CLK_DIV(x) FIELD_PREP(SPDIF_CFGR_CLK_DIV_MASK, x-1) 19 18 20 - #define SPDIF_CFGR_HALFWORD_SHIFT 2 21 - #define SPDIF_CFGR_HALFWORD_DISABLE (0 << SPDIF_CFGR_HALFWORD_SHIFT) 22 - #define SPDIF_CFGR_HALFWORD_ENABLE (1 << SPDIF_CFGR_HALFWORD_SHIFT) 19 + #define SPDIF_CFGR_CLR_MASK BIT(7) 20 + #define SPDIF_CFGR_CLR_EN FIELD_PREP(SPDIF_CFGR_CLR_MASK, 1) 21 + #define SPDIF_CFGR_CLR_DIS FIELD_PREP(SPDIF_CFGR_CLR_MASK, 0) 23 22 24 - #define SPDIF_CFGR_VDW_SHIFT 0 25 - #define SPDIF_CFGR_VDW(x) (x << SPDIF_CFGR_VDW_SHIFT) 26 - #define SDPIF_CFGR_VDW_MASK (0xf << SPDIF_CFGR_VDW_SHIFT) 23 + #define SPDIF_CFGR_CSE_MASK BIT(6) 24 + #define SPDIF_CFGR_CSE_EN FIELD_PREP(SPDIF_CFGR_CSE_MASK, 1) 25 + #define SPDIF_CFGR_CSE_DIS FIELD_PREP(SPDIF_CFGR_CSE_MASK, 0) 27 26 28 - #define SPDIF_CFGR_VDW_16 SPDIF_CFGR_VDW(0x0) 29 - #define SPDIF_CFGR_VDW_20 SPDIF_CFGR_VDW(0x1) 30 - #define SPDIF_CFGR_VDW_24 SPDIF_CFGR_VDW(0x2) 27 + #define SPDIF_CFGR_ADJ_MASK BIT(3) 28 + #define SPDIF_CFGR_ADJ_LEFT_J FIELD_PREP(SPDIF_CFGR_ADJ_MASK, 1) 29 + #define SPDIF_CFGR_ADJ_RIGHT_J FIELD_PREP(SPDIF_CFGR_ADJ_MASK, 0) 30 + 31 + #define SPDIF_CFGR_HALFWORD_MASK BIT(2) 32 + #define SPDIF_CFGR_HALFWORD_DISABLE FIELD_PREP(SPDIF_CFGR_HALFWORD_MASK, 0) 33 + #define SPDIF_CFGR_HALFWORD_ENABLE FIELD_PREP(SPDIF_CFGR_HALFWORD_MASK, 1) 34 + 35 + #define SDPIF_CFGR_VDW_MASK GENMASK(1, 0) 36 + #define SPDIF_CFGR_VDW(x) FIELD_PREP(SDPIF_CFGR_VDW_MASK, x) 37 + 38 + #define SPDIF_CFGR_VDW_16 SPDIF_CFGR_VDW(0x0) 39 + #define SPDIF_CFGR_VDW_20 SPDIF_CFGR_VDW(0x1) 40 + #define SPDIF_CFGR_VDW_24 SPDIF_CFGR_VDW(0x2) 31 41 32 42 /* 33 43 * DMACR 34 44 * DMA control register 35 45 */ 36 - #define SPDIF_DMACR_TDE_SHIFT 5 37 - #define SPDIF_DMACR_TDE_DISABLE (0 << SPDIF_DMACR_TDE_SHIFT) 38 - #define SPDIF_DMACR_TDE_ENABLE (1 << SPDIF_DMACR_TDE_SHIFT) 46 + #define SPDIF_DMACR_TDE_MASK BIT(5) 47 + #define SPDIF_DMACR_TDE_DISABLE FIELD_PREP(SPDIF_DMACR_TDE_MASK, 0) 48 + #define SPDIF_DMACR_TDE_ENABLE FIELD_PREP(SPDIF_DMACR_TDE_MASK, 1) 39 49 40 - #define SPDIF_DMACR_TDL_SHIFT 0 41 - #define SPDIF_DMACR_TDL(x) ((x) << SPDIF_DMACR_TDL_SHIFT) 42 - #define SPDIF_DMACR_TDL_MASK (0x1f << SPDIF_DMACR_TDL_SHIFT) 50 + #define SPDIF_DMACR_TDL_MASK GENMASK(4, 0) 51 + #define SPDIF_DMACR_TDL(x) FIELD_PREP(SPDIF_DMACR_TDL_MASK, x) 43 52 44 53 /* 45 54 * XFER 46 55 * Transfer control register 47 56 */ 48 - #define SPDIF_XFER_TXS_SHIFT 0 49 - #define SPDIF_XFER_TXS_STOP (0 << SPDIF_XFER_TXS_SHIFT) 50 - #define SPDIF_XFER_TXS_START (1 << SPDIF_XFER_TXS_SHIFT) 57 + #define SPDIF_XFER_TXS_MASK BIT(0) 58 + #define SPDIF_XFER_TXS_STOP FIELD_PREP(SPDIF_XFER_TXS_MASK, 0) 59 + #define SPDIF_XFER_TXS_START FIELD_PREP(SPDIF_XFER_TXS_MASK, 1) 51 60 52 61 #define SPDIF_CFGR (0x0000) 53 62 #define SPDIF_SDBLR (0x0004) ··· 65 56 #define SPDIF_INTSR (0x0010) 66 57 #define SPDIF_XFER (0x0018) 67 58 #define SPDIF_SMPDR (0x0020) 59 + #define SPDIF_VLDFRn(x) (0x0060 + (x) * 4) 60 + #define SPDIF_USRDRn(x) (0x0090 + (x) * 4) 61 + #define SPDIF_CHNSRn(x) (0x00c0 + (x) * 4) 62 + #define SPDIF_VERSION (0x01c0) 68 63 69 64 #endif /* _ROCKCHIP_SPDIF_H */