1 /* sound/soc/rockchip/rk_spdif.c 2 * 3 * ALSA SoC Audio Layer - Rockchip I2S Controller driver 4 * 5 * Copyright (c) 2014 Rockchip Electronics Co. Ltd. 6 * Author: Jianqun <jay.xu@rock-chips.com> 7 * Copyright (c) 2015 Collabora Ltd. 8 * 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 */ 14 15 #include <linux/module.h> 16 #include <linux/delay.h> 17 #include <linux/of_gpio.h> 18 #include <linux/clk.h> 19 #include <linux/pm_runtime.h> 20 #include <linux/mfd/syscon.h> 21 #include <linux/regmap.h> 22 #include <sound/pcm_params.h> 23 #include <sound/dmaengine_pcm.h> 24 25 #include "rockchip_spdif.h" 26 27 enum rk_spdif_type { 28 RK_SPDIF_RK3066, 29 RK_SPDIF_RK3188, 30 RK_SPDIF_RK3288, 31 }; 32 33 #define RK3288_GRF_SOC_CON2 0x24c 34 35 struct rk_spdif_dev { 36 struct device *dev; 37 38 struct clk *mclk; 39 struct clk *hclk; 40 41 struct snd_dmaengine_dai_dma_data playback_dma_data; 42 43 struct regmap *regmap; 44 }; 45 46 static const struct of_device_id rk_spdif_match[] = { 47 { .compatible = "rockchip,rk3066-spdif", 48 .data = (void *) RK_SPDIF_RK3066 }, 49 { .compatible = "rockchip,rk3188-spdif", 50 .data = (void *) RK_SPDIF_RK3188 }, 51 { .compatible = "rockchip,rk3288-spdif", 52 .data = (void *) RK_SPDIF_RK3288 }, 53 {}, 54 }; 55 MODULE_DEVICE_TABLE(of, rk_spdif_match); 56 57 static int rk_spdif_runtime_suspend(struct device *dev) 58 { 59 struct rk_spdif_dev *spdif = dev_get_drvdata(dev); 60 61 clk_disable_unprepare(spdif->mclk); 62 clk_disable_unprepare(spdif->hclk); 63 64 return 0; 65 } 66 67 static int rk_spdif_runtime_resume(struct device *dev) 68 { 69 struct rk_spdif_dev *spdif = dev_get_drvdata(dev); 70 int ret; 71 72 ret = clk_prepare_enable(spdif->mclk); 73 if (ret) { 74 dev_err(spdif->dev, "mclk clock enable failed %d\n", ret); 75 return ret; 76 } 77 78 ret = clk_prepare_enable(spdif->hclk); 79 if (ret) { 80 dev_err(spdif->dev, "hclk clock enable failed %d\n", ret); 81 return ret; 82 } 83 84 return 0; 85 } 86 87 static int rk_spdif_hw_params(struct snd_pcm_substream *substream, 88 struct snd_pcm_hw_params *params, 89 struct snd_soc_dai *dai) 90 { 91 struct rk_spdif_dev *spdif = snd_soc_dai_get_drvdata(dai); 92 unsigned int val = SPDIF_CFGR_HALFWORD_ENABLE; 93 int srate, mclk; 94 int ret; 95 96 srate = params_rate(params); 97 switch (srate) { 98 case 32000: 99 case 48000: 100 case 96000: 101 mclk = 96000 * 128; /* 12288000 hz */ 102 break; 103 case 44100: 104 mclk = 44100 * 256; /* 11289600 hz */ 105 break; 106 case 192000: 107 mclk = 192000 * 128; /* 24576000 hz */ 108 break; 109 default: 110 return -EINVAL; 111 } 112 113 switch (params_format(params)) { 114 case SNDRV_PCM_FORMAT_S16_LE: 115 val |= SPDIF_CFGR_VDW_16; 116 break; 117 case SNDRV_PCM_FORMAT_S20_3LE: 118 val |= SPDIF_CFGR_VDW_20; 119 break; 120 case SNDRV_PCM_FORMAT_S24_LE: 121 val |= SPDIF_CFGR_VDW_24; 122 break; 123 default: 124 return -EINVAL; 125 } 126 127 /* Set clock and calculate divider */ 128 ret = clk_set_rate(spdif->mclk, mclk); 129 if (ret != 0) { 130 dev_err(spdif->dev, "Failed to set module clock rate: %d\n", 131 ret); 132 return ret; 133 } 134 135 val |= SPDIF_CFGR_CLK_DIV(mclk/(srate * 256)); 136 ret = regmap_update_bits(spdif->regmap, SPDIF_CFGR, 137 SPDIF_CFGR_CLK_DIV_MASK | SPDIF_CFGR_HALFWORD_ENABLE | 138 SDPIF_CFGR_VDW_MASK, 139 val); 140 141 return ret; 142 } 143 144 static int rk_spdif_trigger(struct snd_pcm_substream *substream, 145 int cmd, struct snd_soc_dai *dai) 146 { 147 struct rk_spdif_dev *spdif = snd_soc_dai_get_drvdata(dai); 148 int ret; 149 150 switch (cmd) { 151 case SNDRV_PCM_TRIGGER_START: 152 case SNDRV_PCM_TRIGGER_RESUME: 153 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 154 ret = regmap_update_bits(spdif->regmap, SPDIF_DMACR, 155 SPDIF_DMACR_TDE_ENABLE, 156 SPDIF_DMACR_TDE_ENABLE); 157 158 if (ret != 0) 159 return ret; 160 161 ret = regmap_update_bits(spdif->regmap, SPDIF_XFER, 162 SPDIF_XFER_TXS_START, 163 SPDIF_XFER_TXS_START); 164 break; 165 case SNDRV_PCM_TRIGGER_SUSPEND: 166 case SNDRV_PCM_TRIGGER_STOP: 167 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 168 ret = regmap_update_bits(spdif->regmap, SPDIF_DMACR, 169 SPDIF_DMACR_TDE_ENABLE, 170 SPDIF_DMACR_TDE_DISABLE); 171 172 if (ret != 0) 173 return ret; 174 175 ret = regmap_update_bits(spdif->regmap, SPDIF_XFER, 176 SPDIF_XFER_TXS_START, 177 SPDIF_XFER_TXS_STOP); 178 break; 179 default: 180 ret = -EINVAL; 181 break; 182 } 183 184 return ret; 185 } 186 187 static int rk_spdif_dai_probe(struct snd_soc_dai *dai) 188 { 189 struct rk_spdif_dev *spdif = snd_soc_dai_get_drvdata(dai); 190 191 dai->playback_dma_data = &spdif->playback_dma_data; 192 193 return 0; 194 } 195 196 static const struct snd_soc_dai_ops rk_spdif_dai_ops = { 197 .hw_params = rk_spdif_hw_params, 198 .trigger = rk_spdif_trigger, 199 }; 200 201 static struct snd_soc_dai_driver rk_spdif_dai = { 202 .probe = rk_spdif_dai_probe, 203 .playback = { 204 .stream_name = "Playback", 205 .channels_min = 2, 206 .channels_max = 2, 207 .rates = (SNDRV_PCM_RATE_32000 | 208 SNDRV_PCM_RATE_44100 | 209 SNDRV_PCM_RATE_48000 | 210 SNDRV_PCM_RATE_96000 | 211 SNDRV_PCM_RATE_192000), 212 .formats = (SNDRV_PCM_FMTBIT_S16_LE | 213 SNDRV_PCM_FMTBIT_S20_3LE | 214 SNDRV_PCM_FMTBIT_S24_LE), 215 }, 216 .ops = &rk_spdif_dai_ops, 217 }; 218 219 static const struct snd_soc_component_driver rk_spdif_component = { 220 .name = "rockchip-spdif", 221 }; 222 223 static bool rk_spdif_wr_reg(struct device *dev, unsigned int reg) 224 { 225 switch (reg) { 226 case SPDIF_CFGR: 227 case SPDIF_DMACR: 228 case SPDIF_INTCR: 229 case SPDIF_XFER: 230 case SPDIF_SMPDR: 231 return true; 232 default: 233 return false; 234 } 235 } 236 237 static bool rk_spdif_rd_reg(struct device *dev, unsigned int reg) 238 { 239 switch (reg) { 240 case SPDIF_CFGR: 241 case SPDIF_SDBLR: 242 case SPDIF_INTCR: 243 case SPDIF_INTSR: 244 case SPDIF_XFER: 245 return true; 246 default: 247 return false; 248 } 249 } 250 251 static bool rk_spdif_volatile_reg(struct device *dev, unsigned int reg) 252 { 253 switch (reg) { 254 case SPDIF_INTSR: 255 case SPDIF_SDBLR: 256 return true; 257 default: 258 return false; 259 } 260 } 261 262 static const struct regmap_config rk_spdif_regmap_config = { 263 .reg_bits = 32, 264 .reg_stride = 4, 265 .val_bits = 32, 266 .max_register = SPDIF_SMPDR, 267 .writeable_reg = rk_spdif_wr_reg, 268 .readable_reg = rk_spdif_rd_reg, 269 .volatile_reg = rk_spdif_volatile_reg, 270 .cache_type = REGCACHE_FLAT, 271 }; 272 273 static int rk_spdif_probe(struct platform_device *pdev) 274 { 275 struct device_node *np = pdev->dev.of_node; 276 struct rk_spdif_dev *spdif; 277 const struct of_device_id *match; 278 struct resource *res; 279 void __iomem *regs; 280 int ret; 281 282 match = of_match_node(rk_spdif_match, np); 283 if ((int) match->data == RK_SPDIF_RK3288) { 284 struct regmap *grf; 285 286 grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf"); 287 if (IS_ERR(grf)) { 288 dev_err(&pdev->dev, 289 "rockchip_spdif missing 'rockchip,grf' \n"); 290 return PTR_ERR(grf); 291 } 292 293 /* Select the 8 channel SPDIF solution on RK3288 as 294 * the 2 channel one does not appear to work 295 */ 296 regmap_write(grf, RK3288_GRF_SOC_CON2, BIT(1) << 16); 297 } 298 299 spdif = devm_kzalloc(&pdev->dev, sizeof(*spdif), GFP_KERNEL); 300 if (!spdif) 301 return -ENOMEM; 302 303 spdif->hclk = devm_clk_get(&pdev->dev, "hclk"); 304 if (IS_ERR(spdif->hclk)) { 305 dev_err(&pdev->dev, "Can't retrieve rk_spdif bus clock\n"); 306 return PTR_ERR(spdif->hclk); 307 } 308 ret = clk_prepare_enable(spdif->hclk); 309 if (ret) { 310 dev_err(spdif->dev, "hclock enable failed %d\n", ret); 311 return ret; 312 } 313 314 spdif->mclk = devm_clk_get(&pdev->dev, "mclk"); 315 if (IS_ERR(spdif->mclk)) { 316 dev_err(&pdev->dev, "Can't retrieve rk_spdif master clock\n"); 317 return PTR_ERR(spdif->mclk); 318 } 319 320 ret = clk_prepare_enable(spdif->mclk); 321 if (ret) { 322 dev_err(spdif->dev, "clock enable failed %d\n", ret); 323 return ret; 324 } 325 326 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 327 regs = devm_ioremap_resource(&pdev->dev, res); 328 if (IS_ERR(regs)) 329 return PTR_ERR(regs); 330 331 spdif->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "hclk", regs, 332 &rk_spdif_regmap_config); 333 if (IS_ERR(spdif->regmap)) { 334 dev_err(&pdev->dev, 335 "Failed to initialise managed register map\n"); 336 return PTR_ERR(spdif->regmap); 337 } 338 339 spdif->playback_dma_data.addr = res->start + SPDIF_SMPDR; 340 spdif->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 341 spdif->playback_dma_data.maxburst = 4; 342 343 spdif->dev = &pdev->dev; 344 dev_set_drvdata(&pdev->dev, spdif); 345 346 pm_runtime_set_active(&pdev->dev); 347 pm_runtime_enable(&pdev->dev); 348 pm_request_idle(&pdev->dev); 349 350 ret = devm_snd_soc_register_component(&pdev->dev, 351 &rk_spdif_component, 352 &rk_spdif_dai, 1); 353 if (ret) { 354 dev_err(&pdev->dev, "Could not register DAI\n"); 355 goto err_pm_runtime; 356 } 357 358 ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); 359 if (ret) { 360 dev_err(&pdev->dev, "Could not register PCM\n"); 361 goto err_pm_runtime; 362 } 363 364 return 0; 365 366 err_pm_runtime: 367 pm_runtime_disable(&pdev->dev); 368 369 return ret; 370 } 371 372 static int rk_spdif_remove(struct platform_device *pdev) 373 { 374 struct rk_spdif_dev *spdif = dev_get_drvdata(&pdev->dev); 375 376 pm_runtime_disable(&pdev->dev); 377 if (!pm_runtime_status_suspended(&pdev->dev)) 378 rk_spdif_runtime_suspend(&pdev->dev); 379 380 clk_disable_unprepare(spdif->mclk); 381 clk_disable_unprepare(spdif->hclk); 382 383 return 0; 384 } 385 386 static const struct dev_pm_ops rk_spdif_pm_ops = { 387 SET_RUNTIME_PM_OPS(rk_spdif_runtime_suspend, rk_spdif_runtime_resume, 388 NULL) 389 }; 390 391 static struct platform_driver rk_spdif_driver = { 392 .probe = rk_spdif_probe, 393 .remove = rk_spdif_remove, 394 .driver = { 395 .name = "rockchip-spdif", 396 .of_match_table = of_match_ptr(rk_spdif_match), 397 .pm = &rk_spdif_pm_ops, 398 }, 399 }; 400 module_platform_driver(rk_spdif_driver); 401 402 MODULE_ALIAS("platform:rockchip-spdif"); 403 MODULE_DESCRIPTION("ROCKCHIP SPDIF transceiver Interface"); 404 MODULE_AUTHOR("Sjoerd Simons <sjoerd.simons@collabora.co.uk>"); 405 MODULE_LICENSE("GPL v2"); 406