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_TDL_MASK, 157 SPDIF_DMACR_TDE_ENABLE | 158 SPDIF_DMACR_TDL(16)); 159 160 if (ret != 0) 161 return ret; 162 163 ret = regmap_update_bits(spdif->regmap, SPDIF_XFER, 164 SPDIF_XFER_TXS_START, 165 SPDIF_XFER_TXS_START); 166 break; 167 case SNDRV_PCM_TRIGGER_SUSPEND: 168 case SNDRV_PCM_TRIGGER_STOP: 169 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 170 ret = regmap_update_bits(spdif->regmap, SPDIF_DMACR, 171 SPDIF_DMACR_TDE_ENABLE, 172 SPDIF_DMACR_TDE_DISABLE); 173 174 if (ret != 0) 175 return ret; 176 177 ret = regmap_update_bits(spdif->regmap, SPDIF_XFER, 178 SPDIF_XFER_TXS_START, 179 SPDIF_XFER_TXS_STOP); 180 break; 181 default: 182 ret = -EINVAL; 183 break; 184 } 185 186 return ret; 187 } 188 189 static int rk_spdif_dai_probe(struct snd_soc_dai *dai) 190 { 191 struct rk_spdif_dev *spdif = snd_soc_dai_get_drvdata(dai); 192 193 dai->playback_dma_data = &spdif->playback_dma_data; 194 195 return 0; 196 } 197 198 static const struct snd_soc_dai_ops rk_spdif_dai_ops = { 199 .hw_params = rk_spdif_hw_params, 200 .trigger = rk_spdif_trigger, 201 }; 202 203 static struct snd_soc_dai_driver rk_spdif_dai = { 204 .probe = rk_spdif_dai_probe, 205 .playback = { 206 .stream_name = "Playback", 207 .channels_min = 2, 208 .channels_max = 2, 209 .rates = (SNDRV_PCM_RATE_32000 | 210 SNDRV_PCM_RATE_44100 | 211 SNDRV_PCM_RATE_48000 | 212 SNDRV_PCM_RATE_96000 | 213 SNDRV_PCM_RATE_192000), 214 .formats = (SNDRV_PCM_FMTBIT_S16_LE | 215 SNDRV_PCM_FMTBIT_S20_3LE | 216 SNDRV_PCM_FMTBIT_S24_LE), 217 }, 218 .ops = &rk_spdif_dai_ops, 219 }; 220 221 static const struct snd_soc_component_driver rk_spdif_component = { 222 .name = "rockchip-spdif", 223 }; 224 225 static bool rk_spdif_wr_reg(struct device *dev, unsigned int reg) 226 { 227 switch (reg) { 228 case SPDIF_CFGR: 229 case SPDIF_DMACR: 230 case SPDIF_INTCR: 231 case SPDIF_XFER: 232 case SPDIF_SMPDR: 233 return true; 234 default: 235 return false; 236 } 237 } 238 239 static bool rk_spdif_rd_reg(struct device *dev, unsigned int reg) 240 { 241 switch (reg) { 242 case SPDIF_CFGR: 243 case SPDIF_SDBLR: 244 case SPDIF_INTCR: 245 case SPDIF_INTSR: 246 case SPDIF_XFER: 247 return true; 248 default: 249 return false; 250 } 251 } 252 253 static bool rk_spdif_volatile_reg(struct device *dev, unsigned int reg) 254 { 255 switch (reg) { 256 case SPDIF_INTSR: 257 case SPDIF_SDBLR: 258 return true; 259 default: 260 return false; 261 } 262 } 263 264 static const struct regmap_config rk_spdif_regmap_config = { 265 .reg_bits = 32, 266 .reg_stride = 4, 267 .val_bits = 32, 268 .max_register = SPDIF_SMPDR, 269 .writeable_reg = rk_spdif_wr_reg, 270 .readable_reg = rk_spdif_rd_reg, 271 .volatile_reg = rk_spdif_volatile_reg, 272 .cache_type = REGCACHE_FLAT, 273 }; 274 275 static int rk_spdif_probe(struct platform_device *pdev) 276 { 277 struct device_node *np = pdev->dev.of_node; 278 struct rk_spdif_dev *spdif; 279 const struct of_device_id *match; 280 struct resource *res; 281 void __iomem *regs; 282 int ret; 283 284 match = of_match_node(rk_spdif_match, np); 285 if (match->data == (void *)RK_SPDIF_RK3288) { 286 struct regmap *grf; 287 288 grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf"); 289 if (IS_ERR(grf)) { 290 dev_err(&pdev->dev, 291 "rockchip_spdif missing 'rockchip,grf' \n"); 292 return PTR_ERR(grf); 293 } 294 295 /* Select the 8 channel SPDIF solution on RK3288 as 296 * the 2 channel one does not appear to work 297 */ 298 regmap_write(grf, RK3288_GRF_SOC_CON2, BIT(1) << 16); 299 } 300 301 spdif = devm_kzalloc(&pdev->dev, sizeof(*spdif), GFP_KERNEL); 302 if (!spdif) 303 return -ENOMEM; 304 305 spdif->hclk = devm_clk_get(&pdev->dev, "hclk"); 306 if (IS_ERR(spdif->hclk)) { 307 dev_err(&pdev->dev, "Can't retrieve rk_spdif bus clock\n"); 308 return PTR_ERR(spdif->hclk); 309 } 310 ret = clk_prepare_enable(spdif->hclk); 311 if (ret) { 312 dev_err(spdif->dev, "hclock enable failed %d\n", ret); 313 return ret; 314 } 315 316 spdif->mclk = devm_clk_get(&pdev->dev, "mclk"); 317 if (IS_ERR(spdif->mclk)) { 318 dev_err(&pdev->dev, "Can't retrieve rk_spdif master clock\n"); 319 return PTR_ERR(spdif->mclk); 320 } 321 322 ret = clk_prepare_enable(spdif->mclk); 323 if (ret) { 324 dev_err(spdif->dev, "clock enable failed %d\n", ret); 325 return ret; 326 } 327 328 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 329 regs = devm_ioremap_resource(&pdev->dev, res); 330 if (IS_ERR(regs)) 331 return PTR_ERR(regs); 332 333 spdif->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "hclk", regs, 334 &rk_spdif_regmap_config); 335 if (IS_ERR(spdif->regmap)) { 336 dev_err(&pdev->dev, 337 "Failed to initialise managed register map\n"); 338 return PTR_ERR(spdif->regmap); 339 } 340 341 spdif->playback_dma_data.addr = res->start + SPDIF_SMPDR; 342 spdif->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 343 spdif->playback_dma_data.maxburst = 4; 344 345 spdif->dev = &pdev->dev; 346 dev_set_drvdata(&pdev->dev, spdif); 347 348 pm_runtime_set_active(&pdev->dev); 349 pm_runtime_enable(&pdev->dev); 350 pm_request_idle(&pdev->dev); 351 352 ret = devm_snd_soc_register_component(&pdev->dev, 353 &rk_spdif_component, 354 &rk_spdif_dai, 1); 355 if (ret) { 356 dev_err(&pdev->dev, "Could not register DAI\n"); 357 goto err_pm_runtime; 358 } 359 360 ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); 361 if (ret) { 362 dev_err(&pdev->dev, "Could not register PCM\n"); 363 goto err_pm_runtime; 364 } 365 366 return 0; 367 368 err_pm_runtime: 369 pm_runtime_disable(&pdev->dev); 370 371 return ret; 372 } 373 374 static int rk_spdif_remove(struct platform_device *pdev) 375 { 376 struct rk_spdif_dev *spdif = dev_get_drvdata(&pdev->dev); 377 378 pm_runtime_disable(&pdev->dev); 379 if (!pm_runtime_status_suspended(&pdev->dev)) 380 rk_spdif_runtime_suspend(&pdev->dev); 381 382 clk_disable_unprepare(spdif->mclk); 383 clk_disable_unprepare(spdif->hclk); 384 385 return 0; 386 } 387 388 static const struct dev_pm_ops rk_spdif_pm_ops = { 389 SET_RUNTIME_PM_OPS(rk_spdif_runtime_suspend, rk_spdif_runtime_resume, 390 NULL) 391 }; 392 393 static struct platform_driver rk_spdif_driver = { 394 .probe = rk_spdif_probe, 395 .remove = rk_spdif_remove, 396 .driver = { 397 .name = "rockchip-spdif", 398 .of_match_table = of_match_ptr(rk_spdif_match), 399 .pm = &rk_spdif_pm_ops, 400 }, 401 }; 402 module_platform_driver(rk_spdif_driver); 403 404 MODULE_ALIAS("platform:rockchip-spdif"); 405 MODULE_DESCRIPTION("ROCKCHIP SPDIF transceiver Interface"); 406 MODULE_AUTHOR("Sjoerd Simons <sjoerd.simons@collabora.co.uk>"); 407 MODULE_LICENSE("GPL v2"); 408