1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (c) 2025 Troy Mitchell <troy.mitchell@linux.spacemit.com> */ 3 4 #include <linux/bitfield.h> 5 #include <linux/clk.h> 6 #include <linux/reset.h> 7 #include <sound/dmaengine_pcm.h> 8 #include <sound/pcm.h> 9 #include <sound/pcm_params.h> 10 11 #define SSCR 0x00 /* SPI/I2S top control register */ 12 #define SSFCR 0x04 /* SPI/I2S FIFO control register */ 13 #define SSINTEN 0x08 /* SPI/I2S interrupt enable register */ 14 #define SSDATR 0x10 /* SPI/I2S data register */ 15 #define SSPSP 0x18 /* SPI/I2S programmable serial protocol control register */ 16 #define SSRWT 0x24 /* SPI/I2S root control register */ 17 18 /* SPI/I2S Work data size, register bits value 0~31 indicated data size 1~32 bits */ 19 #define SSCR_FIELD_DSS GENMASK(9, 5) 20 #define SSCR_DW_8BYTE FIELD_PREP(SSCR_FIELD_DSS, 0x7) 21 #define SSCR_DW_16BYTE FIELD_PREP(SSCR_FIELD_DSS, 0xf) 22 #define SSCR_DW_18BYTE FIELD_PREP(SSCR_FIELD_DSS, 0x11) 23 #define SSCR_DW_32BYTE FIELD_PREP(SSCR_FIELD_DSS, 0x1f) 24 25 #define SSCR_SSE BIT(0) /* SPI/I2S Enable */ 26 #define SSCR_FRF_PSP GENMASK(2, 1) /* Frame Format*/ 27 #define SSCR_TRAIL BIT(13) /* Trailing Byte */ 28 29 #define SSFCR_FIELD_TFT GENMASK(3, 0) /* TXFIFO Trigger Threshold */ 30 #define SSFCR_FIELD_RFT GENMASK(8, 5) /* RXFIFO Trigger Threshold */ 31 #define SSFCR_TSRE BIT(10) /* Transmit Service Request Enable */ 32 #define SSFCR_RSRE BIT(11) /* Receive Service Request Enable */ 33 34 #define SSPSP_FSRT BIT(3) /* Frame Sync Relative Timing Bit */ 35 #define SSPSP_SFRMP BIT(4) /* Serial Frame Polarity */ 36 #define SSPSP_FIELD_SFRMWDTH GENMASK(17, 12) /* Serial Frame Width field */ 37 38 #define SSRWT_RWOT BIT(0) /* Receive Without Transmit */ 39 40 #define SPACEMIT_PCM_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | \ 41 SNDRV_PCM_RATE_48000) 42 #define SPACEMIT_PCM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE) 43 44 #define SPACEMIT_I2S_PERIOD_SIZE 1024 45 46 struct spacemit_i2s_dev { 47 struct device *dev; 48 49 void __iomem *base; 50 51 struct reset_control *reset; 52 53 struct clk *sysclk; 54 struct clk *bclk; 55 struct clk *sspa_clk; 56 57 struct snd_dmaengine_dai_dma_data capture_dma_data; 58 struct snd_dmaengine_dai_dma_data playback_dma_data; 59 60 bool has_capture; 61 bool has_playback; 62 63 int dai_fmt; 64 65 int started_count; 66 }; 67 68 static const struct snd_pcm_hardware spacemit_pcm_hardware = { 69 .info = SNDRV_PCM_INFO_INTERLEAVED | 70 SNDRV_PCM_INFO_BATCH, 71 .formats = SPACEMIT_PCM_FORMATS, 72 .rates = SPACEMIT_PCM_RATES, 73 .rate_min = SNDRV_PCM_RATE_8000, 74 .rate_max = SNDRV_PCM_RATE_192000, 75 .channels_min = 1, 76 .channels_max = 2, 77 .buffer_bytes_max = SPACEMIT_I2S_PERIOD_SIZE * 4 * 4, 78 .period_bytes_min = SPACEMIT_I2S_PERIOD_SIZE * 2, 79 .period_bytes_max = SPACEMIT_I2S_PERIOD_SIZE * 4, 80 .periods_min = 2, 81 .periods_max = 4, 82 }; 83 84 static const struct snd_dmaengine_pcm_config spacemit_dmaengine_pcm_config = { 85 .pcm_hardware = &spacemit_pcm_hardware, 86 .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config, 87 .chan_names = {"tx", "rx"}, 88 .prealloc_buffer_size = 32 * 1024, 89 }; 90 91 static void spacemit_i2s_init(struct spacemit_i2s_dev *i2s) 92 { 93 u32 sscr_val, sspsp_val, ssfcr_val, ssrwt_val; 94 95 sscr_val = SSCR_TRAIL | SSCR_FRF_PSP; 96 ssfcr_val = FIELD_PREP(SSFCR_FIELD_TFT, 5) | 97 FIELD_PREP(SSFCR_FIELD_RFT, 5) | 98 SSFCR_RSRE | SSFCR_TSRE; 99 ssrwt_val = SSRWT_RWOT; 100 sspsp_val = SSPSP_SFRMP; 101 102 writel(sscr_val, i2s->base + SSCR); 103 writel(ssfcr_val, i2s->base + SSFCR); 104 writel(sspsp_val, i2s->base + SSPSP); 105 writel(ssrwt_val, i2s->base + SSRWT); 106 writel(0, i2s->base + SSINTEN); 107 } 108 109 static int spacemit_i2s_hw_params(struct snd_pcm_substream *substream, 110 struct snd_pcm_hw_params *params, 111 struct snd_soc_dai *dai) 112 { 113 struct spacemit_i2s_dev *i2s = snd_soc_dai_get_drvdata(dai); 114 struct snd_dmaengine_dai_dma_data *dma_data; 115 u32 data_width, data_bits; 116 unsigned long bclk_rate; 117 u32 val; 118 int ret; 119 120 val = readl(i2s->base + SSCR); 121 if (val & SSCR_SSE) 122 return 0; 123 124 dma_data = &i2s->playback_dma_data; 125 126 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) 127 dma_data = &i2s->capture_dma_data; 128 129 switch (params_format(params)) { 130 case SNDRV_PCM_FORMAT_S8: 131 data_bits = 8; 132 data_width = SSCR_DW_8BYTE; 133 dma_data->maxburst = 8; 134 dma_data->addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; 135 break; 136 case SNDRV_PCM_FORMAT_S16_LE: 137 data_bits = 16; 138 data_width = SSCR_DW_16BYTE; 139 dma_data->maxburst = 16; 140 dma_data->addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; 141 break; 142 case SNDRV_PCM_FORMAT_S32_LE: 143 data_bits = 32; 144 data_width = SSCR_DW_32BYTE; 145 dma_data->maxburst = 32; 146 dma_data->addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 147 break; 148 default: 149 dev_dbg(i2s->dev, "unexpected data width type"); 150 return -EINVAL; 151 } 152 153 switch (i2s->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 154 case SND_SOC_DAIFMT_I2S: 155 if (data_bits == 16) { 156 data_width = SSCR_DW_32BYTE; 157 dma_data->maxburst = 32; 158 dma_data->addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 159 } 160 161 snd_pcm_hw_constraint_minmax(substream->runtime, 162 SNDRV_PCM_HW_PARAM_CHANNELS, 163 1, 2); 164 snd_pcm_hw_constraint_mask64(substream->runtime, 165 SNDRV_PCM_HW_PARAM_FORMAT, 166 SNDRV_PCM_FMTBIT_S16_LE); 167 break; 168 case SND_SOC_DAIFMT_DSP_A: 169 case SND_SOC_DAIFMT_DSP_B: 170 snd_pcm_hw_constraint_minmax(substream->runtime, 171 SNDRV_PCM_HW_PARAM_CHANNELS, 172 1, 1); 173 snd_pcm_hw_constraint_mask64(substream->runtime, 174 SNDRV_PCM_HW_PARAM_FORMAT, 175 SNDRV_PCM_FMTBIT_S32_LE); 176 break; 177 default: 178 dev_dbg(i2s->dev, "unexpected format type"); 179 return -EINVAL; 180 181 } 182 183 val = readl(i2s->base + SSCR); 184 val &= ~SSCR_DW_32BYTE; 185 val |= data_width; 186 writel(val, i2s->base + SSCR); 187 188 bclk_rate = params_channels(params) * 189 params_rate(params) * 190 data_bits; 191 192 ret = clk_set_rate(i2s->bclk, bclk_rate); 193 if (ret) 194 return ret; 195 196 return clk_set_rate(i2s->sspa_clk, bclk_rate); 197 } 198 199 static int spacemit_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id, 200 unsigned int freq, int dir) 201 { 202 struct spacemit_i2s_dev *i2s = dev_get_drvdata(cpu_dai->dev); 203 204 if (freq == 0) 205 return 0; 206 207 return clk_set_rate(i2s->sysclk, freq); 208 } 209 210 static int spacemit_i2s_set_fmt(struct snd_soc_dai *cpu_dai, 211 unsigned int fmt) 212 { 213 struct spacemit_i2s_dev *i2s = dev_get_drvdata(cpu_dai->dev); 214 u32 sspsp_val; 215 216 sspsp_val = readl(i2s->base + SSPSP); 217 sspsp_val &= ~SSPSP_FIELD_SFRMWDTH; 218 sspsp_val |= SSPSP_FSRT; 219 220 i2s->dai_fmt = fmt; 221 222 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 223 case SND_SOC_DAIFMT_I2S: 224 sspsp_val |= FIELD_PREP(SSPSP_FIELD_SFRMWDTH, 0x10); 225 break; 226 case SND_SOC_DAIFMT_DSP_B: 227 /* DSP_B: next frame asserted after previous frame end, so clear FSRT */ 228 sspsp_val &= ~SSPSP_FSRT; 229 fallthrough; 230 case SND_SOC_DAIFMT_DSP_A: 231 sspsp_val |= FIELD_PREP(SSPSP_FIELD_SFRMWDTH, 0x1); 232 break; 233 default: 234 dev_dbg(i2s->dev, "unexpected format type"); 235 return -EINVAL; 236 } 237 238 writel(sspsp_val, i2s->base + SSPSP); 239 240 return 0; 241 } 242 243 static int spacemit_i2s_trigger(struct snd_pcm_substream *substream, 244 int cmd, struct snd_soc_dai *dai) 245 { 246 struct spacemit_i2s_dev *i2s = snd_soc_dai_get_drvdata(dai); 247 u32 val; 248 249 switch (cmd) { 250 case SNDRV_PCM_TRIGGER_START: 251 case SNDRV_PCM_TRIGGER_RESUME: 252 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 253 if (!i2s->started_count) { 254 val = readl(i2s->base + SSCR); 255 val |= SSCR_SSE; 256 writel(val, i2s->base + SSCR); 257 } 258 i2s->started_count++; 259 break; 260 case SNDRV_PCM_TRIGGER_STOP: 261 case SNDRV_PCM_TRIGGER_SUSPEND: 262 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 263 if (i2s->started_count) 264 i2s->started_count--; 265 266 if (!i2s->started_count) { 267 val = readl(i2s->base + SSCR); 268 val &= ~SSCR_SSE; 269 writel(val, i2s->base + SSCR); 270 } 271 break; 272 default: 273 return -EINVAL; 274 } 275 276 return 0; 277 } 278 279 static int spacemit_i2s_dai_probe(struct snd_soc_dai *dai) 280 { 281 struct spacemit_i2s_dev *i2s = snd_soc_dai_get_drvdata(dai); 282 283 snd_soc_dai_init_dma_data(dai, 284 i2s->has_playback ? &i2s->playback_dma_data : NULL, 285 i2s->has_capture ? &i2s->capture_dma_data : NULL); 286 287 reset_control_deassert(i2s->reset); 288 289 spacemit_i2s_init(i2s); 290 291 return 0; 292 } 293 294 static int spacemit_i2s_dai_remove(struct snd_soc_dai *dai) 295 { 296 struct spacemit_i2s_dev *i2s = snd_soc_dai_get_drvdata(dai); 297 298 reset_control_assert(i2s->reset); 299 300 return 0; 301 } 302 303 static const struct snd_soc_dai_ops spacemit_i2s_dai_ops = { 304 .probe = spacemit_i2s_dai_probe, 305 .remove = spacemit_i2s_dai_remove, 306 .hw_params = spacemit_i2s_hw_params, 307 .set_sysclk = spacemit_i2s_set_sysclk, 308 .set_fmt = spacemit_i2s_set_fmt, 309 .trigger = spacemit_i2s_trigger, 310 }; 311 312 static struct snd_soc_dai_driver spacemit_i2s_dai = { 313 .ops = &spacemit_i2s_dai_ops, 314 .playback = { 315 .channels_min = 1, 316 .channels_max = 2, 317 .rates = SPACEMIT_PCM_RATES, 318 .rate_min = SNDRV_PCM_RATE_8000, 319 .rate_max = SNDRV_PCM_RATE_48000, 320 .formats = SPACEMIT_PCM_FORMATS, 321 }, 322 .capture = { 323 .channels_min = 1, 324 .channels_max = 2, 325 .rates = SPACEMIT_PCM_RATES, 326 .rate_min = SNDRV_PCM_RATE_8000, 327 .rate_max = SNDRV_PCM_RATE_48000, 328 .formats = SPACEMIT_PCM_FORMATS, 329 }, 330 .symmetric_rate = 1, 331 }; 332 333 static int spacemit_i2s_init_dai(struct spacemit_i2s_dev *i2s, 334 struct snd_soc_dai_driver **dp, 335 dma_addr_t addr) 336 { 337 struct device_node *node = i2s->dev->of_node; 338 struct snd_soc_dai_driver *dai; 339 struct property *dma_names; 340 const char *dma_name; 341 342 of_property_for_each_string(node, "dma-names", dma_names, dma_name) { 343 if (!strcmp(dma_name, "tx")) 344 i2s->has_playback = true; 345 if (!strcmp(dma_name, "rx")) 346 i2s->has_capture = true; 347 } 348 349 dai = devm_kmemdup(i2s->dev, &spacemit_i2s_dai, 350 sizeof(*dai), GFP_KERNEL); 351 if (!dai) 352 return -ENOMEM; 353 354 if (i2s->has_playback) { 355 dai->playback.stream_name = "Playback"; 356 dai->playback.channels_min = 1; 357 dai->playback.channels_max = 2; 358 dai->playback.rates = SPACEMIT_PCM_RATES; 359 dai->playback.formats = SPACEMIT_PCM_FORMATS; 360 361 i2s->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; 362 i2s->playback_dma_data.maxburst = 32; 363 i2s->playback_dma_data.addr = addr; 364 } 365 366 if (i2s->has_capture) { 367 dai->capture.stream_name = "Capture"; 368 dai->capture.channels_min = 1; 369 dai->capture.channels_max = 2; 370 dai->capture.rates = SPACEMIT_PCM_RATES; 371 dai->capture.formats = SPACEMIT_PCM_FORMATS; 372 373 i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; 374 i2s->capture_dma_data.maxburst = 32; 375 i2s->capture_dma_data.addr = addr; 376 } 377 378 if (dp) 379 *dp = dai; 380 381 return 0; 382 } 383 384 static const struct snd_soc_component_driver spacemit_i2s_component = { 385 .name = "i2s-k1", 386 .legacy_dai_naming = 1, 387 }; 388 389 static int spacemit_i2s_probe(struct platform_device *pdev) 390 { 391 struct snd_soc_dai_driver *dai; 392 struct spacemit_i2s_dev *i2s; 393 struct resource *res; 394 struct clk *clk; 395 int ret; 396 397 i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL); 398 if (!i2s) 399 return -ENOMEM; 400 401 i2s->dev = &pdev->dev; 402 403 i2s->sysclk = devm_clk_get_enabled(i2s->dev, "sysclk"); 404 if (IS_ERR(i2s->sysclk)) 405 return dev_err_probe(i2s->dev, PTR_ERR(i2s->sysclk), 406 "failed to enable sysbase clock\n"); 407 408 i2s->bclk = devm_clk_get_enabled(i2s->dev, "bclk"); 409 if (IS_ERR(i2s->bclk)) 410 return dev_err_probe(i2s->dev, PTR_ERR(i2s->bclk), "failed to enable bit clock\n"); 411 412 clk = devm_clk_get_enabled(i2s->dev, "sspa_bus"); 413 if (IS_ERR(clk)) 414 return dev_err_probe(i2s->dev, PTR_ERR(clk), "failed to enable sspa_bus clock\n"); 415 416 i2s->sspa_clk = devm_clk_get_enabled(i2s->dev, "sspa"); 417 if (IS_ERR(i2s->sspa_clk)) 418 return dev_err_probe(i2s->dev, PTR_ERR(i2s->sspa_clk), 419 "failed to enable sspa clock\n"); 420 421 i2s->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); 422 if (IS_ERR(i2s->base)) 423 return dev_err_probe(i2s->dev, PTR_ERR(i2s->base), "failed to map registers\n"); 424 425 i2s->reset = devm_reset_control_get_exclusive(&pdev->dev, NULL); 426 if (IS_ERR(i2s->reset)) 427 return dev_err_probe(i2s->dev, PTR_ERR(i2s->reset), 428 "failed to get reset control"); 429 430 dev_set_drvdata(i2s->dev, i2s); 431 432 ret = spacemit_i2s_init_dai(i2s, &dai, res->start + SSDATR); 433 if (ret) 434 return ret; 435 436 ret = devm_snd_soc_register_component(i2s->dev, 437 &spacemit_i2s_component, 438 dai, 1); 439 if (ret) 440 return dev_err_probe(i2s->dev, ret, "failed to register component"); 441 442 return devm_snd_dmaengine_pcm_register(&pdev->dev, &spacemit_dmaengine_pcm_config, 0); 443 } 444 445 static const struct of_device_id spacemit_i2s_of_match[] = { 446 { .compatible = "spacemit,k1-i2s", }, 447 { /* sentinel */ } 448 }; 449 MODULE_DEVICE_TABLE(of, spacemit_i2s_of_match); 450 451 static struct platform_driver spacemit_i2s_driver = { 452 .probe = spacemit_i2s_probe, 453 .driver = { 454 .name = "i2s-k1", 455 .of_match_table = spacemit_i2s_of_match, 456 }, 457 }; 458 module_platform_driver(spacemit_i2s_driver); 459 460 MODULE_LICENSE("GPL"); 461 MODULE_DESCRIPTION("I2S bus driver for SpacemiT K1 SoC"); 462