| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* sound/soc/rockchip/rk_spdif.c |
|---|
| 2 | 3 | * |
|---|
| 3 | 4 | * ALSA SoC Audio Layer - Rockchip I2S Controller driver |
|---|
| .. | .. |
|---|
| 6 | 7 | * Author: Jianqun <jay.xu@rock-chips.com> |
|---|
| 7 | 8 | * Copyright (c) 2015 Collabora Ltd. |
|---|
| 8 | 9 | * Author: Sjoerd Simons <sjoerd.simons@collabora.co.uk> |
|---|
| 9 | | - * |
|---|
| 10 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 11 | | - * it under the terms of the GNU General Public License version 2 as |
|---|
| 12 | | - * published by the Free Software Foundation. |
|---|
| 13 | 10 | */ |
|---|
| 14 | 11 | |
|---|
| 15 | 12 | #include <linux/module.h> |
|---|
| .. | .. |
|---|
| 20 | 17 | #include <linux/mfd/syscon.h> |
|---|
| 21 | 18 | #include <linux/regmap.h> |
|---|
| 22 | 19 | #include <sound/pcm_params.h> |
|---|
| 20 | +#include <sound/pcm_iec958.h> |
|---|
| 23 | 21 | #include <sound/dmaengine_pcm.h> |
|---|
| 24 | 22 | |
|---|
| 25 | 23 | #include "rockchip_spdif.h" |
|---|
| .. | .. |
|---|
| 31 | 29 | RK_SPDIF_RK3366, |
|---|
| 32 | 30 | }; |
|---|
| 33 | 31 | |
|---|
| 34 | | -#define RK3288_GRF_SOC_CON2 0x24c |
|---|
| 32 | +/* |
|---|
| 33 | + * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
|---|
| 34 | + * CS0: | Mode | d | c | b | a | |
|---|
| 35 | + * CS1: | Category Code | |
|---|
| 36 | + * CS2: | Channel Number | Source Number | |
|---|
| 37 | + * CS3: | Clock Accuracy | Sample Freq | |
|---|
| 38 | + * CS4: | Ori Sample Freq | Word Length | |
|---|
| 39 | + * CS5: | | CGMS-A | |
|---|
| 40 | + * CS6~CS23: Reserved |
|---|
| 41 | + * |
|---|
| 42 | + * a: use of channel status block |
|---|
| 43 | + * b: linear PCM identification: 0 for lpcm, 1 for nlpcm |
|---|
| 44 | + * c: copyright information |
|---|
| 45 | + * d: additional format information |
|---|
| 46 | + */ |
|---|
| 47 | +#define CS_BYTE 6 |
|---|
| 48 | +#define CS_FRAME(c) ((c) << 16 | (c)) |
|---|
| 49 | + |
|---|
| 50 | +#define RK3288_GRF_SOC_CON2 0x24c |
|---|
| 35 | 51 | |
|---|
| 36 | 52 | struct rk_spdif_dev { |
|---|
| 37 | 53 | struct device *dev; |
|---|
| .. | .. |
|---|
| 44 | 60 | struct regmap *regmap; |
|---|
| 45 | 61 | }; |
|---|
| 46 | 62 | |
|---|
| 47 | | -static const struct of_device_id rk_spdif_match[] = { |
|---|
| 63 | +static const struct of_device_id rk_spdif_match[] __maybe_unused = { |
|---|
| 48 | 64 | { .compatible = "rockchip,rk3066-spdif", |
|---|
| 49 | 65 | .data = (void *)RK_SPDIF_RK3066 }, |
|---|
| 50 | 66 | { .compatible = "rockchip,rk3188-spdif", |
|---|
| .. | .. |
|---|
| 62 | 78 | { .compatible = "rockchip,rk3399-spdif", |
|---|
| 63 | 79 | .data = (void *)RK_SPDIF_RK3366 }, |
|---|
| 64 | 80 | { .compatible = "rockchip,rk3568-spdif", |
|---|
| 81 | + .data = (void *)RK_SPDIF_RK3366 }, |
|---|
| 82 | + { .compatible = "rockchip,rk3588-spdif", |
|---|
| 65 | 83 | .data = (void *)RK_SPDIF_RK3366 }, |
|---|
| 66 | 84 | {}, |
|---|
| 67 | 85 | }; |
|---|
| .. | .. |
|---|
| 113 | 131 | { |
|---|
| 114 | 132 | struct rk_spdif_dev *spdif = snd_soc_dai_get_drvdata(dai); |
|---|
| 115 | 133 | unsigned int val = SPDIF_CFGR_HALFWORD_ENABLE; |
|---|
| 116 | | - int srate, mclk; |
|---|
| 117 | | - int ret; |
|---|
| 134 | + unsigned int mclk_rate = clk_get_rate(spdif->mclk); |
|---|
| 135 | + int bmc, div, ret, i; |
|---|
| 136 | + u8 cs[CS_BYTE]; |
|---|
| 137 | + u16 *fc = (u16 *)cs; |
|---|
| 118 | 138 | |
|---|
| 119 | | - srate = params_rate(params); |
|---|
| 120 | | - mclk = srate * 128; |
|---|
| 139 | + ret = snd_pcm_create_iec958_consumer_hw_params(params, cs, sizeof(cs)); |
|---|
| 140 | + if (ret < 0) |
|---|
| 141 | + return ret; |
|---|
| 142 | + |
|---|
| 143 | + for (i = 0; i < CS_BYTE / 2; i++) |
|---|
| 144 | + regmap_write(spdif->regmap, SPDIF_CHNSRn(i), CS_FRAME(fc[i])); |
|---|
| 145 | + |
|---|
| 146 | + regmap_update_bits(spdif->regmap, SPDIF_CFGR, SPDIF_CFGR_CSE_MASK, |
|---|
| 147 | + SPDIF_CFGR_CSE_EN); |
|---|
| 148 | + |
|---|
| 149 | + /* bmc = 128fs */ |
|---|
| 150 | + bmc = 128 * params_rate(params); |
|---|
| 151 | + div = DIV_ROUND_CLOSEST(mclk_rate, bmc); |
|---|
| 152 | + val |= SPDIF_CFGR_CLK_DIV(div); |
|---|
| 121 | 153 | |
|---|
| 122 | 154 | switch (params_format(params)) { |
|---|
| 123 | 155 | case SNDRV_PCM_FORMAT_S16_LE: |
|---|
| .. | .. |
|---|
| 128 | 160 | break; |
|---|
| 129 | 161 | case SNDRV_PCM_FORMAT_S24_LE: |
|---|
| 130 | 162 | val |= SPDIF_CFGR_VDW_24; |
|---|
| 163 | + val |= SPDIF_CFGR_ADJ_RIGHT_J; |
|---|
| 164 | + break; |
|---|
| 165 | + case SNDRV_PCM_FORMAT_S32_LE: |
|---|
| 166 | + val |= SPDIF_CFGR_VDW_24; |
|---|
| 167 | + val |= SPDIF_CFGR_ADJ_LEFT_J; |
|---|
| 131 | 168 | break; |
|---|
| 132 | 169 | default: |
|---|
| 133 | 170 | return -EINVAL; |
|---|
| 134 | 171 | } |
|---|
| 135 | 172 | |
|---|
| 136 | | - /* Set clock and calculate divider */ |
|---|
| 137 | | - ret = clk_set_rate(spdif->mclk, mclk); |
|---|
| 138 | | - if (ret != 0) { |
|---|
| 139 | | - dev_err(spdif->dev, "Failed to set module clock rate: %d\n", |
|---|
| 140 | | - ret); |
|---|
| 141 | | - return ret; |
|---|
| 142 | | - } |
|---|
| 173 | + regmap_update_bits(spdif->regmap, SPDIF_CFGR, SPDIF_CFGR_CLR_MASK, |
|---|
| 174 | + SPDIF_CFGR_CLR_EN); |
|---|
| 143 | 175 | |
|---|
| 176 | + udelay(1); |
|---|
| 144 | 177 | ret = regmap_update_bits(spdif->regmap, SPDIF_CFGR, |
|---|
| 145 | 178 | SPDIF_CFGR_CLK_DIV_MASK | |
|---|
| 146 | 179 | SPDIF_CFGR_HALFWORD_ENABLE | |
|---|
| 147 | | - SDPIF_CFGR_VDW_MASK, val); |
|---|
| 180 | + SDPIF_CFGR_VDW_MASK | |
|---|
| 181 | + SPDIF_CFGR_ADJ_MASK, val); |
|---|
| 148 | 182 | |
|---|
| 149 | 183 | return ret; |
|---|
| 150 | 184 | } |
|---|
| .. | .. |
|---|
| 203 | 237 | return 0; |
|---|
| 204 | 238 | } |
|---|
| 205 | 239 | |
|---|
| 240 | +static int rk_spdif_set_sysclk(struct snd_soc_dai *dai, |
|---|
| 241 | + int clk_id, unsigned int freq, int dir) |
|---|
| 242 | +{ |
|---|
| 243 | + struct rk_spdif_dev *spdif = snd_soc_dai_get_drvdata(dai); |
|---|
| 244 | + int ret = 0; |
|---|
| 245 | + |
|---|
| 246 | + if (!freq) |
|---|
| 247 | + return 0; |
|---|
| 248 | + |
|---|
| 249 | + ret = clk_set_rate(spdif->mclk, freq); |
|---|
| 250 | + if (ret) |
|---|
| 251 | + dev_err(spdif->dev, "Failed to set mclk: %d\n", ret); |
|---|
| 252 | + |
|---|
| 253 | + return ret; |
|---|
| 254 | +} |
|---|
| 255 | + |
|---|
| 206 | 256 | static const struct snd_soc_dai_ops rk_spdif_dai_ops = { |
|---|
| 257 | + .set_sysclk = rk_spdif_set_sysclk, |
|---|
| 207 | 258 | .hw_params = rk_spdif_hw_params, |
|---|
| 208 | 259 | .trigger = rk_spdif_trigger, |
|---|
| 209 | 260 | }; |
|---|
| .. | .. |
|---|
| 214 | 265 | .stream_name = "Playback", |
|---|
| 215 | 266 | .channels_min = 2, |
|---|
| 216 | 267 | .channels_max = 2, |
|---|
| 217 | | - .rates = (SNDRV_PCM_RATE_32000 | |
|---|
| 218 | | - SNDRV_PCM_RATE_44100 | |
|---|
| 219 | | - SNDRV_PCM_RATE_48000 | |
|---|
| 220 | | - SNDRV_PCM_RATE_96000 | |
|---|
| 221 | | - SNDRV_PCM_RATE_192000), |
|---|
| 268 | + .rates = SNDRV_PCM_RATE_8000_192000, |
|---|
| 222 | 269 | .formats = (SNDRV_PCM_FMTBIT_S16_LE | |
|---|
| 223 | 270 | SNDRV_PCM_FMTBIT_S20_3LE | |
|---|
| 224 | | - SNDRV_PCM_FMTBIT_S24_LE), |
|---|
| 271 | + SNDRV_PCM_FMTBIT_S24_LE | |
|---|
| 272 | + SNDRV_PCM_FMTBIT_S32_LE), |
|---|
| 225 | 273 | }, |
|---|
| 226 | 274 | .ops = &rk_spdif_dai_ops, |
|---|
| 227 | 275 | }; |
|---|
| .. | .. |
|---|
| 238 | 286 | case SPDIF_INTCR: |
|---|
| 239 | 287 | case SPDIF_XFER: |
|---|
| 240 | 288 | case SPDIF_SMPDR: |
|---|
| 289 | + case SPDIF_VLDFRn(0) ... SPDIF_VLDFRn(11): |
|---|
| 290 | + case SPDIF_USRDRn(0) ... SPDIF_USRDRn(11): |
|---|
| 291 | + case SPDIF_CHNSRn(0) ... SPDIF_CHNSRn(11): |
|---|
| 241 | 292 | return true; |
|---|
| 242 | 293 | default: |
|---|
| 243 | 294 | return false; |
|---|
| .. | .. |
|---|
| 253 | 304 | case SPDIF_INTSR: |
|---|
| 254 | 305 | case SPDIF_XFER: |
|---|
| 255 | 306 | case SPDIF_SMPDR: |
|---|
| 307 | + case SPDIF_VLDFRn(0) ... SPDIF_VLDFRn(11): |
|---|
| 308 | + case SPDIF_USRDRn(0) ... SPDIF_USRDRn(11): |
|---|
| 309 | + case SPDIF_CHNSRn(0) ... SPDIF_CHNSRn(11): |
|---|
| 256 | 310 | return true; |
|---|
| 257 | 311 | default: |
|---|
| 258 | 312 | return false; |
|---|
| .. | .. |
|---|
| 275 | 329 | .reg_bits = 32, |
|---|
| 276 | 330 | .reg_stride = 4, |
|---|
| 277 | 331 | .val_bits = 32, |
|---|
| 278 | | - .max_register = SPDIF_SMPDR, |
|---|
| 332 | + .max_register = SPDIF_VERSION, |
|---|
| 279 | 333 | .writeable_reg = rk_spdif_wr_reg, |
|---|
| 280 | 334 | .readable_reg = rk_spdif_rd_reg, |
|---|
| 281 | 335 | .volatile_reg = rk_spdif_volatile_reg, |
|---|
| .. | .. |
|---|
| 320 | 374 | if (IS_ERR(spdif->mclk)) |
|---|
| 321 | 375 | return PTR_ERR(spdif->mclk); |
|---|
| 322 | 376 | |
|---|
| 323 | | - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
|---|
| 324 | | - regs = devm_ioremap_resource(&pdev->dev, res); |
|---|
| 377 | + regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res); |
|---|
| 325 | 378 | if (IS_ERR(regs)) |
|---|
| 326 | 379 | return PTR_ERR(regs); |
|---|
| 327 | 380 | |
|---|