1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Copyright (C) 2015 Linaro 4 * 5 * Author: Jun Nie <jun.nie@linaro.org> 6 */ 7 8#include <linux/clk.h> 9#include <linux/device.h> 10#include <linux/dmaengine.h> 11#include <linux/init.h> 12#include <linux/io.h> 13#include <linux/kernel.h> 14#include <linux/module.h> 15#include <linux/of_address.h> 16#include <sound/asoundef.h> 17#include <sound/core.h> 18#include <sound/dmaengine_pcm.h> 19#include <sound/initval.h> 20#include <sound/pcm.h> 21#include <sound/pcm_params.h> 22#include <sound/soc.h> 23#include <sound/soc-dai.h> 24 25#define ZX_CTRL 0x04 26#define ZX_FIFOCTRL 0x08 27#define ZX_INT_STATUS 0x10 28#define ZX_INT_MASK 0x14 29#define ZX_DATA 0x18 30#define ZX_VALID_BIT 0x1c 31#define ZX_CH_STA_1 0x20 32#define ZX_CH_STA_2 0x24 33#define ZX_CH_STA_3 0x28 34#define ZX_CH_STA_4 0x2c 35#define ZX_CH_STA_5 0x30 36#define ZX_CH_STA_6 0x34 37 38#define ZX_CTRL_MODA_16 (0 << 6) 39#define ZX_CTRL_MODA_18 BIT(6) 40#define ZX_CTRL_MODA_20 (2 << 6) 41#define ZX_CTRL_MODA_24 (3 << 6) 42#define ZX_CTRL_MODA_MASK (3 << 6) 43 44#define ZX_CTRL_ENB BIT(4) 45#define ZX_CTRL_DNB (0 << 4) 46#define ZX_CTRL_ENB_MASK BIT(4) 47 48#define ZX_CTRL_TX_OPEN BIT(0) 49#define ZX_CTRL_TX_CLOSE (0 << 0) 50#define ZX_CTRL_TX_MASK BIT(0) 51 52#define ZX_CTRL_OPEN (ZX_CTRL_TX_OPEN | ZX_CTRL_ENB) 53#define ZX_CTRL_CLOSE (ZX_CTRL_TX_CLOSE | ZX_CTRL_DNB) 54 55#define ZX_CTRL_DOUBLE_TRACK (0 << 8) 56#define ZX_CTRL_LEFT_TRACK BIT(8) 57#define ZX_CTRL_RIGHT_TRACK (2 << 8) 58#define ZX_CTRL_TRACK_MASK (3 << 8) 59 60#define ZX_FIFOCTRL_TXTH_MASK (0x1f << 8) 61#define ZX_FIFOCTRL_TXTH(x) (x << 8) 62#define ZX_FIFOCTRL_TX_DMA_EN BIT(2) 63#define ZX_FIFOCTRL_TX_DMA_DIS (0 << 2) 64#define ZX_FIFOCTRL_TX_DMA_EN_MASK BIT(2) 65#define ZX_FIFOCTRL_TX_FIFO_RST BIT(0) 66#define ZX_FIFOCTRL_TX_FIFO_RST_MASK BIT(0) 67 68#define ZX_VALID_DOUBLE_TRACK (0 << 0) 69#define ZX_VALID_LEFT_TRACK BIT(1) 70#define ZX_VALID_RIGHT_TRACK (2 << 0) 71#define ZX_VALID_TRACK_MASK (3 << 0) 72 73#define ZX_SPDIF_CLK_RAT (2 * 32) 74 75struct zx_spdif_info { 76 struct snd_dmaengine_dai_dma_data dma_data; 77 struct clk *dai_clk; 78 void __iomem *reg_base; 79 resource_size_t mapbase; 80}; 81 82static int zx_spdif_dai_probe(struct snd_soc_dai *dai) 83{ 84 struct zx_spdif_info *zx_spdif = dev_get_drvdata(dai->dev); 85 86 snd_soc_dai_set_drvdata(dai, zx_spdif); 87 zx_spdif->dma_data.addr = zx_spdif->mapbase + ZX_DATA; 88 zx_spdif->dma_data.maxburst = 8; 89 snd_soc_dai_init_dma_data(dai, &zx_spdif->dma_data, NULL); 90 return 0; 91} 92 93static int zx_spdif_chanstats(void __iomem *base, unsigned int rate) 94{ 95 u32 cstas1; 96 97 switch (rate) { 98 case 22050: 99 cstas1 = IEC958_AES3_CON_FS_22050; 100 break; 101 case 24000: 102 cstas1 = IEC958_AES3_CON_FS_24000; 103 break; 104 case 32000: 105 cstas1 = IEC958_AES3_CON_FS_32000; 106 break; 107 case 44100: 108 cstas1 = IEC958_AES3_CON_FS_44100; 109 break; 110 case 48000: 111 cstas1 = IEC958_AES3_CON_FS_48000; 112 break; 113 case 88200: 114 cstas1 = IEC958_AES3_CON_FS_88200; 115 break; 116 case 96000: 117 cstas1 = IEC958_AES3_CON_FS_96000; 118 break; 119 case 176400: 120 cstas1 = IEC958_AES3_CON_FS_176400; 121 break; 122 case 192000: 123 cstas1 = IEC958_AES3_CON_FS_192000; 124 break; 125 default: 126 return -EINVAL; 127 } 128 cstas1 = cstas1 << 24; 129 cstas1 |= IEC958_AES0_CON_NOT_COPYRIGHT; 130 131 writel_relaxed(cstas1, base + ZX_CH_STA_1); 132 return 0; 133} 134 135static int zx_spdif_hw_params(struct snd_pcm_substream *substream, 136 struct snd_pcm_hw_params *params, 137 struct snd_soc_dai *socdai) 138{ 139 struct zx_spdif_info *zx_spdif = dev_get_drvdata(socdai->dev); 140 struct zx_spdif_info *spdif = snd_soc_dai_get_drvdata(socdai); 141 struct snd_dmaengine_dai_dma_data *dma_data = 142 snd_soc_dai_get_dma_data(socdai, substream); 143 u32 val, ch_num, rate; 144 int ret; 145 146 dma_data->addr_width = params_width(params) >> 3; 147 148 val = readl_relaxed(zx_spdif->reg_base + ZX_CTRL); 149 val &= ~ZX_CTRL_MODA_MASK; 150 switch (params_format(params)) { 151 case SNDRV_PCM_FORMAT_S16_LE: 152 val |= ZX_CTRL_MODA_16; 153 break; 154 155 case SNDRV_PCM_FORMAT_S18_3LE: 156 val |= ZX_CTRL_MODA_18; 157 break; 158 159 case SNDRV_PCM_FORMAT_S20_3LE: 160 val |= ZX_CTRL_MODA_20; 161 break; 162 163 case SNDRV_PCM_FORMAT_S24_LE: 164 val |= ZX_CTRL_MODA_24; 165 break; 166 default: 167 dev_err(socdai->dev, "Format not support!\n"); 168 return -EINVAL; 169 } 170 171 ch_num = params_channels(params); 172 if (ch_num == 2) 173 val |= ZX_CTRL_DOUBLE_TRACK; 174 else 175 val |= ZX_CTRL_LEFT_TRACK; 176 writel_relaxed(val, zx_spdif->reg_base + ZX_CTRL); 177 178 val = readl_relaxed(zx_spdif->reg_base + ZX_VALID_BIT); 179 val &= ~ZX_VALID_TRACK_MASK; 180 if (ch_num == 2) 181 val |= ZX_VALID_DOUBLE_TRACK; 182 else 183 val |= ZX_VALID_RIGHT_TRACK; 184 writel_relaxed(val, zx_spdif->reg_base + ZX_VALID_BIT); 185 186 rate = params_rate(params); 187 ret = zx_spdif_chanstats(zx_spdif->reg_base, rate); 188 if (ret) 189 return ret; 190 return clk_set_rate(spdif->dai_clk, rate * ch_num * ZX_SPDIF_CLK_RAT); 191} 192 193static void zx_spdif_cfg_tx(void __iomem *base, int on) 194{ 195 u32 val; 196 197 val = readl_relaxed(base + ZX_CTRL); 198 val &= ~(ZX_CTRL_ENB_MASK | ZX_CTRL_TX_MASK); 199 val |= on ? ZX_CTRL_OPEN : ZX_CTRL_CLOSE; 200 writel_relaxed(val, base + ZX_CTRL); 201 202 val = readl_relaxed(base + ZX_FIFOCTRL); 203 val &= ~ZX_FIFOCTRL_TX_DMA_EN_MASK; 204 if (on) 205 val |= ZX_FIFOCTRL_TX_DMA_EN; 206 writel_relaxed(val, base + ZX_FIFOCTRL); 207} 208 209static int zx_spdif_trigger(struct snd_pcm_substream *substream, int cmd, 210 struct snd_soc_dai *dai) 211{ 212 u32 val; 213 struct zx_spdif_info *zx_spdif = dev_get_drvdata(dai->dev); 214 int ret = 0; 215 216 switch (cmd) { 217 case SNDRV_PCM_TRIGGER_START: 218 val = readl_relaxed(zx_spdif->reg_base + ZX_FIFOCTRL); 219 val |= ZX_FIFOCTRL_TX_FIFO_RST; 220 writel_relaxed(val, zx_spdif->reg_base + ZX_FIFOCTRL); 221 fallthrough; 222 case SNDRV_PCM_TRIGGER_RESUME: 223 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 224 zx_spdif_cfg_tx(zx_spdif->reg_base, true); 225 break; 226 227 case SNDRV_PCM_TRIGGER_STOP: 228 case SNDRV_PCM_TRIGGER_SUSPEND: 229 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 230 zx_spdif_cfg_tx(zx_spdif->reg_base, false); 231 break; 232 233 default: 234 ret = -EINVAL; 235 break; 236 } 237 238 return ret; 239} 240 241static int zx_spdif_startup(struct snd_pcm_substream *substream, 242 struct snd_soc_dai *dai) 243{ 244 struct zx_spdif_info *zx_spdif = dev_get_drvdata(dai->dev); 245 246 return clk_prepare_enable(zx_spdif->dai_clk); 247} 248 249static void zx_spdif_shutdown(struct snd_pcm_substream *substream, 250 struct snd_soc_dai *dai) 251{ 252 struct zx_spdif_info *zx_spdif = dev_get_drvdata(dai->dev); 253 254 clk_disable_unprepare(zx_spdif->dai_clk); 255} 256 257#define ZX_RATES \ 258 (SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ 259 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |\ 260 SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000) 261 262#define ZX_FORMAT \ 263 (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE \ 264 | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE) 265 266static const struct snd_soc_dai_ops zx_spdif_dai_ops = { 267 .trigger = zx_spdif_trigger, 268 .startup = zx_spdif_startup, 269 .shutdown = zx_spdif_shutdown, 270 .hw_params = zx_spdif_hw_params, 271}; 272 273static struct snd_soc_dai_driver zx_spdif_dai = { 274 .name = "spdif", 275 .id = 0, 276 .probe = zx_spdif_dai_probe, 277 .playback = { 278 .channels_min = 1, 279 .channels_max = 2, 280 .rates = ZX_RATES, 281 .formats = ZX_FORMAT, 282 }, 283 .ops = &zx_spdif_dai_ops, 284}; 285 286static const struct snd_soc_component_driver zx_spdif_component = { 287 .name = "spdif", 288}; 289 290static void zx_spdif_dev_init(void __iomem *base) 291{ 292 u32 val; 293 294 writel_relaxed(0, base + ZX_CTRL); 295 writel_relaxed(0, base + ZX_INT_MASK); 296 writel_relaxed(0xf, base + ZX_INT_STATUS); 297 writel_relaxed(0x1, base + ZX_FIFOCTRL); 298 299 val = readl_relaxed(base + ZX_FIFOCTRL); 300 val &= ~(ZX_FIFOCTRL_TXTH_MASK | ZX_FIFOCTRL_TX_FIFO_RST_MASK); 301 val |= ZX_FIFOCTRL_TXTH(8); 302 writel_relaxed(val, base + ZX_FIFOCTRL); 303} 304 305static int zx_spdif_probe(struct platform_device *pdev) 306{ 307 struct resource *res; 308 struct zx_spdif_info *zx_spdif; 309 int ret; 310 311 zx_spdif = devm_kzalloc(&pdev->dev, sizeof(*zx_spdif), GFP_KERNEL); 312 if (!zx_spdif) 313 return -ENOMEM; 314 315 zx_spdif->dai_clk = devm_clk_get(&pdev->dev, "tx"); 316 if (IS_ERR(zx_spdif->dai_clk)) { 317 dev_err(&pdev->dev, "Fail to get clk\n"); 318 return PTR_ERR(zx_spdif->dai_clk); 319 } 320 321 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 322 zx_spdif->mapbase = res->start; 323 zx_spdif->reg_base = devm_ioremap_resource(&pdev->dev, res); 324 if (IS_ERR(zx_spdif->reg_base)) { 325 return PTR_ERR(zx_spdif->reg_base); 326 } 327 328 zx_spdif_dev_init(zx_spdif->reg_base); 329 platform_set_drvdata(pdev, zx_spdif); 330 331 ret = devm_snd_soc_register_component(&pdev->dev, &zx_spdif_component, 332 &zx_spdif_dai, 1); 333 if (ret) { 334 dev_err(&pdev->dev, "Register DAI failed: %d\n", ret); 335 return ret; 336 } 337 338 ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); 339 if (ret) 340 dev_err(&pdev->dev, "Register platform PCM failed: %d\n", ret); 341 342 return ret; 343} 344 345static const struct of_device_id zx_spdif_dt_ids[] = { 346 { .compatible = "zte,zx296702-spdif", }, 347 {} 348}; 349MODULE_DEVICE_TABLE(of, zx_spdif_dt_ids); 350 351static struct platform_driver spdif_driver = { 352 .probe = zx_spdif_probe, 353 .driver = { 354 .name = "zx-spdif", 355 .of_match_table = zx_spdif_dt_ids, 356 }, 357}; 358 359module_platform_driver(spdif_driver); 360 361MODULE_AUTHOR("Jun Nie <jun.nie@linaro.org>"); 362MODULE_DESCRIPTION("ZTE SPDIF SoC DAI"); 363MODULE_LICENSE("GPL"); 364