| .. | .. |
|---|
| 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 | |
|---|