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