.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de> |
---|
3 | | - * |
---|
4 | | - * This program is free software; you can redistribute it and/or modify it |
---|
5 | | - * under the terms of the GNU General Public License as published by the |
---|
6 | | - * Free Software Foundation; either version 2 of the License, or (at your |
---|
7 | | - * option) any later version. |
---|
8 | | - * |
---|
9 | | - * You should have received a copy of the GNU General Public License along |
---|
10 | | - * with this program; if not, write to the Free Software Foundation, Inc., |
---|
11 | | - * 675 Mass Ave, Cambridge, MA 02139, USA. |
---|
12 | | - * |
---|
13 | 4 | */ |
---|
14 | 5 | |
---|
15 | 6 | #include <linux/init.h> |
---|
.. | .. |
---|
58 | 49 | |
---|
59 | 50 | #define JZ_AIC_CONF_FIFO_RX_THRESHOLD_OFFSET 12 |
---|
60 | 51 | #define JZ_AIC_CONF_FIFO_TX_THRESHOLD_OFFSET 8 |
---|
61 | | -#define JZ4780_AIC_CONF_FIFO_RX_THRESHOLD_OFFSET 24 |
---|
62 | | -#define JZ4780_AIC_CONF_FIFO_TX_THRESHOLD_OFFSET 16 |
---|
63 | | -#define JZ4780_AIC_CONF_FIFO_RX_THRESHOLD_MASK \ |
---|
64 | | - (0xf << JZ4780_AIC_CONF_FIFO_RX_THRESHOLD_OFFSET) |
---|
65 | | -#define JZ4780_AIC_CONF_FIFO_TX_THRESHOLD_MASK \ |
---|
66 | | - (0x1f << JZ4780_AIC_CONF_FIFO_TX_THRESHOLD_OFFSET) |
---|
| 52 | +#define JZ4760_AIC_CONF_FIFO_RX_THRESHOLD_OFFSET 24 |
---|
| 53 | +#define JZ4760_AIC_CONF_FIFO_TX_THRESHOLD_OFFSET 16 |
---|
67 | 54 | |
---|
68 | 55 | #define JZ_AIC_CTRL_OUTPUT_SAMPLE_SIZE_MASK (0x7 << 19) |
---|
69 | 56 | #define JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_MASK (0x7 << 16) |
---|
.. | .. |
---|
99 | 86 | |
---|
100 | 87 | enum jz47xx_i2s_version { |
---|
101 | 88 | JZ_I2S_JZ4740, |
---|
| 89 | + JZ_I2S_JZ4760, |
---|
| 90 | + JZ_I2S_JZ4770, |
---|
102 | 91 | JZ_I2S_JZ4780, |
---|
| 92 | +}; |
---|
| 93 | + |
---|
| 94 | +struct i2s_soc_info { |
---|
| 95 | + enum jz47xx_i2s_version version; |
---|
| 96 | + struct snd_soc_dai_driver *dai; |
---|
103 | 97 | }; |
---|
104 | 98 | |
---|
105 | 99 | struct jz4740_i2s { |
---|
.. | .. |
---|
113 | 107 | struct snd_dmaengine_dai_dma_data playback_dma_data; |
---|
114 | 108 | struct snd_dmaengine_dai_dma_data capture_dma_data; |
---|
115 | 109 | |
---|
116 | | - enum jz47xx_i2s_version version; |
---|
| 110 | + const struct i2s_soc_info *soc_info; |
---|
117 | 111 | }; |
---|
118 | 112 | |
---|
119 | 113 | static inline uint32_t jz4740_i2s_read(const struct jz4740_i2s *i2s, |
---|
.. | .. |
---|
135 | 129 | uint32_t conf, ctrl; |
---|
136 | 130 | int ret; |
---|
137 | 131 | |
---|
138 | | - if (dai->active) |
---|
| 132 | + if (snd_soc_dai_active(dai)) |
---|
139 | 133 | return 0; |
---|
140 | 134 | |
---|
141 | 135 | ctrl = jz4740_i2s_read(i2s, JZ_REG_AIC_CTRL); |
---|
.. | .. |
---|
159 | 153 | struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); |
---|
160 | 154 | uint32_t conf; |
---|
161 | 155 | |
---|
162 | | - if (dai->active) |
---|
| 156 | + if (snd_soc_dai_active(dai)) |
---|
163 | 157 | return; |
---|
164 | 158 | |
---|
165 | 159 | conf = jz4740_i2s_read(i2s, JZ_REG_AIC_CONF); |
---|
.. | .. |
---|
293 | 287 | ctrl &= ~JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_MASK; |
---|
294 | 288 | ctrl |= sample_size << JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_OFFSET; |
---|
295 | 289 | |
---|
296 | | - if (i2s->version >= JZ_I2S_JZ4780) { |
---|
| 290 | + if (i2s->soc_info->version >= JZ_I2S_JZ4770) { |
---|
297 | 291 | div_reg &= ~I2SDIV_IDV_MASK; |
---|
298 | 292 | div_reg |= (div - 1) << I2SDIV_IDV_SHIFT; |
---|
299 | 293 | } else { |
---|
.. | .. |
---|
337 | 331 | return ret; |
---|
338 | 332 | } |
---|
339 | 333 | |
---|
340 | | -static int jz4740_i2s_suspend(struct snd_soc_dai *dai) |
---|
| 334 | +static int jz4740_i2s_suspend(struct snd_soc_component *component) |
---|
341 | 335 | { |
---|
342 | | - struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); |
---|
| 336 | + struct jz4740_i2s *i2s = snd_soc_component_get_drvdata(component); |
---|
343 | 337 | uint32_t conf; |
---|
344 | 338 | |
---|
345 | | - if (dai->active) { |
---|
| 339 | + if (snd_soc_component_active(component)) { |
---|
346 | 340 | conf = jz4740_i2s_read(i2s, JZ_REG_AIC_CONF); |
---|
347 | 341 | conf &= ~JZ_AIC_CONF_ENABLE; |
---|
348 | 342 | jz4740_i2s_write(i2s, JZ_REG_AIC_CONF, conf); |
---|
.. | .. |
---|
355 | 349 | return 0; |
---|
356 | 350 | } |
---|
357 | 351 | |
---|
358 | | -static int jz4740_i2s_resume(struct snd_soc_dai *dai) |
---|
| 352 | +static int jz4740_i2s_resume(struct snd_soc_component *component) |
---|
359 | 353 | { |
---|
360 | | - struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); |
---|
| 354 | + struct jz4740_i2s *i2s = snd_soc_component_get_drvdata(component); |
---|
361 | 355 | uint32_t conf; |
---|
362 | 356 | int ret; |
---|
363 | 357 | |
---|
.. | .. |
---|
365 | 359 | if (ret) |
---|
366 | 360 | return ret; |
---|
367 | 361 | |
---|
368 | | - if (dai->active) { |
---|
| 362 | + if (snd_soc_component_active(component)) { |
---|
369 | 363 | ret = clk_prepare_enable(i2s->clk_i2s); |
---|
370 | 364 | if (ret) { |
---|
371 | 365 | clk_disable_unprepare(i2s->clk_aic); |
---|
.. | .. |
---|
411 | 405 | snd_soc_dai_init_dma_data(dai, &i2s->playback_dma_data, |
---|
412 | 406 | &i2s->capture_dma_data); |
---|
413 | 407 | |
---|
414 | | - if (i2s->version >= JZ_I2S_JZ4780) { |
---|
415 | | - conf = (7 << JZ4780_AIC_CONF_FIFO_RX_THRESHOLD_OFFSET) | |
---|
416 | | - (8 << JZ4780_AIC_CONF_FIFO_TX_THRESHOLD_OFFSET) | |
---|
| 408 | + if (i2s->soc_info->version >= JZ_I2S_JZ4760) { |
---|
| 409 | + conf = (7 << JZ4760_AIC_CONF_FIFO_RX_THRESHOLD_OFFSET) | |
---|
| 410 | + (8 << JZ4760_AIC_CONF_FIFO_TX_THRESHOLD_OFFSET) | |
---|
417 | 411 | JZ_AIC_CONF_OVERFLOW_PLAY_LAST | |
---|
418 | 412 | JZ_AIC_CONF_I2S | |
---|
419 | 413 | JZ_AIC_CONF_INTERNAL_CODEC; |
---|
.. | .. |
---|
468 | 462 | }, |
---|
469 | 463 | .symmetric_rates = 1, |
---|
470 | 464 | .ops = &jz4740_i2s_dai_ops, |
---|
471 | | - .suspend = jz4740_i2s_suspend, |
---|
472 | | - .resume = jz4740_i2s_resume, |
---|
473 | 465 | }; |
---|
474 | 466 | |
---|
475 | | -static struct snd_soc_dai_driver jz4780_i2s_dai = { |
---|
| 467 | +static const struct i2s_soc_info jz4740_i2s_soc_info = { |
---|
| 468 | + .version = JZ_I2S_JZ4740, |
---|
| 469 | + .dai = &jz4740_i2s_dai, |
---|
| 470 | +}; |
---|
| 471 | + |
---|
| 472 | +static const struct i2s_soc_info jz4760_i2s_soc_info = { |
---|
| 473 | + .version = JZ_I2S_JZ4760, |
---|
| 474 | + .dai = &jz4740_i2s_dai, |
---|
| 475 | +}; |
---|
| 476 | + |
---|
| 477 | +static struct snd_soc_dai_driver jz4770_i2s_dai = { |
---|
476 | 478 | .probe = jz4740_i2s_dai_probe, |
---|
477 | 479 | .remove = jz4740_i2s_dai_remove, |
---|
478 | 480 | .playback = { |
---|
.. | .. |
---|
488 | 490 | .formats = JZ4740_I2S_FMTS, |
---|
489 | 491 | }, |
---|
490 | 492 | .ops = &jz4740_i2s_dai_ops, |
---|
491 | | - .suspend = jz4740_i2s_suspend, |
---|
492 | | - .resume = jz4740_i2s_resume, |
---|
| 493 | +}; |
---|
| 494 | + |
---|
| 495 | +static const struct i2s_soc_info jz4770_i2s_soc_info = { |
---|
| 496 | + .version = JZ_I2S_JZ4770, |
---|
| 497 | + .dai = &jz4770_i2s_dai, |
---|
| 498 | +}; |
---|
| 499 | + |
---|
| 500 | +static const struct i2s_soc_info jz4780_i2s_soc_info = { |
---|
| 501 | + .version = JZ_I2S_JZ4780, |
---|
| 502 | + .dai = &jz4770_i2s_dai, |
---|
493 | 503 | }; |
---|
494 | 504 | |
---|
495 | 505 | static const struct snd_soc_component_driver jz4740_i2s_component = { |
---|
496 | 506 | .name = "jz4740-i2s", |
---|
| 507 | + .suspend = jz4740_i2s_suspend, |
---|
| 508 | + .resume = jz4740_i2s_resume, |
---|
497 | 509 | }; |
---|
498 | 510 | |
---|
499 | | -#ifdef CONFIG_OF |
---|
500 | 511 | static const struct of_device_id jz4740_of_matches[] = { |
---|
501 | | - { .compatible = "ingenic,jz4740-i2s", .data = (void *)JZ_I2S_JZ4740 }, |
---|
502 | | - { .compatible = "ingenic,jz4780-i2s", .data = (void *)JZ_I2S_JZ4780 }, |
---|
| 512 | + { .compatible = "ingenic,jz4740-i2s", .data = &jz4740_i2s_soc_info }, |
---|
| 513 | + { .compatible = "ingenic,jz4760-i2s", .data = &jz4760_i2s_soc_info }, |
---|
| 514 | + { .compatible = "ingenic,jz4770-i2s", .data = &jz4770_i2s_soc_info }, |
---|
| 515 | + { .compatible = "ingenic,jz4780-i2s", .data = &jz4780_i2s_soc_info }, |
---|
503 | 516 | { /* sentinel */ } |
---|
504 | 517 | }; |
---|
505 | 518 | MODULE_DEVICE_TABLE(of, jz4740_of_matches); |
---|
506 | | -#endif |
---|
507 | 519 | |
---|
508 | 520 | static int jz4740_i2s_dev_probe(struct platform_device *pdev) |
---|
509 | 521 | { |
---|
| 522 | + struct device *dev = &pdev->dev; |
---|
510 | 523 | struct jz4740_i2s *i2s; |
---|
511 | 524 | struct resource *mem; |
---|
512 | 525 | int ret; |
---|
513 | | - const struct of_device_id *match; |
---|
514 | 526 | |
---|
515 | | - i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL); |
---|
| 527 | + i2s = devm_kzalloc(dev, sizeof(*i2s), GFP_KERNEL); |
---|
516 | 528 | if (!i2s) |
---|
517 | 529 | return -ENOMEM; |
---|
518 | 530 | |
---|
519 | | - match = of_match_device(jz4740_of_matches, &pdev->dev); |
---|
520 | | - if (match) |
---|
521 | | - i2s->version = (enum jz47xx_i2s_version)match->data; |
---|
| 531 | + i2s->soc_info = device_get_match_data(dev); |
---|
522 | 532 | |
---|
523 | 533 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
---|
524 | | - i2s->base = devm_ioremap_resource(&pdev->dev, mem); |
---|
| 534 | + i2s->base = devm_ioremap_resource(dev, mem); |
---|
525 | 535 | if (IS_ERR(i2s->base)) |
---|
526 | 536 | return PTR_ERR(i2s->base); |
---|
527 | 537 | |
---|
528 | 538 | i2s->phys_base = mem->start; |
---|
529 | 539 | |
---|
530 | | - i2s->clk_aic = devm_clk_get(&pdev->dev, "aic"); |
---|
| 540 | + i2s->clk_aic = devm_clk_get(dev, "aic"); |
---|
531 | 541 | if (IS_ERR(i2s->clk_aic)) |
---|
532 | 542 | return PTR_ERR(i2s->clk_aic); |
---|
533 | 543 | |
---|
534 | | - i2s->clk_i2s = devm_clk_get(&pdev->dev, "i2s"); |
---|
| 544 | + i2s->clk_i2s = devm_clk_get(dev, "i2s"); |
---|
535 | 545 | if (IS_ERR(i2s->clk_i2s)) |
---|
536 | 546 | return PTR_ERR(i2s->clk_i2s); |
---|
537 | 547 | |
---|
538 | 548 | platform_set_drvdata(pdev, i2s); |
---|
539 | 549 | |
---|
540 | | - if (i2s->version == JZ_I2S_JZ4780) |
---|
541 | | - ret = devm_snd_soc_register_component(&pdev->dev, |
---|
542 | | - &jz4740_i2s_component, &jz4780_i2s_dai, 1); |
---|
543 | | - else |
---|
544 | | - ret = devm_snd_soc_register_component(&pdev->dev, |
---|
545 | | - &jz4740_i2s_component, &jz4740_i2s_dai, 1); |
---|
546 | | - |
---|
| 550 | + ret = devm_snd_soc_register_component(dev, &jz4740_i2s_component, |
---|
| 551 | + i2s->soc_info->dai, 1); |
---|
547 | 552 | if (ret) |
---|
548 | 553 | return ret; |
---|
549 | 554 | |
---|
550 | | - return devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, |
---|
| 555 | + return devm_snd_dmaengine_pcm_register(dev, NULL, |
---|
551 | 556 | SND_DMAENGINE_PCM_FLAG_COMPAT); |
---|
552 | 557 | } |
---|
553 | 558 | |
---|
.. | .. |
---|
555 | 560 | .probe = jz4740_i2s_dev_probe, |
---|
556 | 561 | .driver = { |
---|
557 | 562 | .name = "jz4740-i2s", |
---|
558 | | - .of_match_table = of_match_ptr(jz4740_of_matches) |
---|
| 563 | + .of_match_table = jz4740_of_matches, |
---|
559 | 564 | }, |
---|
560 | 565 | }; |
---|
561 | 566 | |
---|