| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * STM32 ALSA SoC Digital Audio Interface (SPDIF-rx) driver. |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * Copyright (C) 2017, STMicroelectronics - All Rights Reserved |
|---|
| 5 | 6 | * Author(s): Olivier Moysan <olivier.moysan@st.com> for STMicroelectronics. |
|---|
| 6 | | - * |
|---|
| 7 | | - * License terms: GPL V2.0. |
|---|
| 8 | | - * |
|---|
| 9 | | - * This program is free software; you can redistribute it and/or modify it |
|---|
| 10 | | - * under the terms of the GNU General Public License version 2 as published by |
|---|
| 11 | | - * the Free Software Foundation. |
|---|
| 12 | | - * |
|---|
| 13 | | - * This program is distributed in the hope that it will be useful, but |
|---|
| 14 | | - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|---|
| 15 | | - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more |
|---|
| 16 | | - * details. |
|---|
| 17 | 7 | */ |
|---|
| 18 | 8 | |
|---|
| 9 | +#include <linux/bitfield.h> |
|---|
| 19 | 10 | #include <linux/clk.h> |
|---|
| 20 | 11 | #include <linux/completion.h> |
|---|
| 21 | 12 | #include <linux/delay.h> |
|---|
| .. | .. |
|---|
| 35 | 26 | #define STM32_SPDIFRX_DR 0x10 |
|---|
| 36 | 27 | #define STM32_SPDIFRX_CSR 0x14 |
|---|
| 37 | 28 | #define STM32_SPDIFRX_DIR 0x18 |
|---|
| 29 | +#define STM32_SPDIFRX_VERR 0x3F4 |
|---|
| 30 | +#define STM32_SPDIFRX_IDR 0x3F8 |
|---|
| 31 | +#define STM32_SPDIFRX_SIDR 0x3FC |
|---|
| 38 | 32 | |
|---|
| 39 | 33 | /* Bit definition for SPDIF_CR register */ |
|---|
| 40 | 34 | #define SPDIFRX_CR_SPDIFEN_SHIFT 0 |
|---|
| .. | .. |
|---|
| 167 | 161 | #define SPDIFRX_SPDIFEN_DISABLE 0x0 |
|---|
| 168 | 162 | #define SPDIFRX_SPDIFEN_SYNC 0x1 |
|---|
| 169 | 163 | #define SPDIFRX_SPDIFEN_ENABLE 0x3 |
|---|
| 164 | + |
|---|
| 165 | +/* Bit definition for SPDIFRX_VERR register */ |
|---|
| 166 | +#define SPDIFRX_VERR_MIN_MASK GENMASK(3, 0) |
|---|
| 167 | +#define SPDIFRX_VERR_MAJ_MASK GENMASK(7, 4) |
|---|
| 168 | + |
|---|
| 169 | +/* Bit definition for SPDIFRX_IDR register */ |
|---|
| 170 | +#define SPDIFRX_IDR_ID_MASK GENMASK(31, 0) |
|---|
| 171 | + |
|---|
| 172 | +/* Bit definition for SPDIFRX_SIDR register */ |
|---|
| 173 | +#define SPDIFRX_SIDR_SID_MASK GENMASK(31, 0) |
|---|
| 174 | + |
|---|
| 175 | +#define SPDIFRX_IPIDR_NUMBER 0x00130041 |
|---|
| 170 | 176 | |
|---|
| 171 | 177 | #define SPDIFRX_IN1 0x1 |
|---|
| 172 | 178 | #define SPDIFRX_IN2 0x2 |
|---|
| .. | .. |
|---|
| 347 | 353 | SPDIFRX_CR_CUMSK | SPDIFRX_CR_PTMSK | SPDIFRX_CR_RXSTEO; |
|---|
| 348 | 354 | cr_mask = cr; |
|---|
| 349 | 355 | |
|---|
| 356 | + cr |= SPDIFRX_CR_NBTRSET(SPDIFRX_NBTR_63); |
|---|
| 357 | + cr_mask |= SPDIFRX_CR_NBTR_MASK; |
|---|
| 350 | 358 | cr |= SPDIFRX_CR_SPDIFENSET(SPDIFRX_SPDIFEN_SYNC); |
|---|
| 351 | 359 | cr_mask |= SPDIFRX_CR_SPDIFEN_MASK; |
|---|
| 352 | 360 | ret = regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_CR, |
|---|
| .. | .. |
|---|
| 398 | 406 | |
|---|
| 399 | 407 | spdifrx->ctrl_chan = dma_request_chan(dev, "rx-ctrl"); |
|---|
| 400 | 408 | if (IS_ERR(spdifrx->ctrl_chan)) { |
|---|
| 401 | | - dev_err(dev, "dma_request_slave_channel failed\n"); |
|---|
| 409 | + if (PTR_ERR(spdifrx->ctrl_chan) != -EPROBE_DEFER) |
|---|
| 410 | + dev_err(dev, "dma_request_slave_channel error %ld\n", |
|---|
| 411 | + PTR_ERR(spdifrx->ctrl_chan)); |
|---|
| 402 | 412 | return PTR_ERR(spdifrx->ctrl_chan); |
|---|
| 403 | 413 | } |
|---|
| 404 | 414 | |
|---|
| .. | .. |
|---|
| 497 | 507 | if (wait_for_completion_interruptible_timeout(&spdifrx->cs_completion, |
|---|
| 498 | 508 | msecs_to_jiffies(100)) |
|---|
| 499 | 509 | <= 0) { |
|---|
| 500 | | - dev_err(&spdifrx->pdev->dev, "Failed to get control data\n"); |
|---|
| 510 | + dev_dbg(&spdifrx->pdev->dev, "Failed to get control data\n"); |
|---|
| 501 | 511 | ret = -EAGAIN; |
|---|
| 502 | 512 | } |
|---|
| 503 | 513 | |
|---|
| .. | .. |
|---|
| 607 | 617 | case STM32_SPDIFRX_DR: |
|---|
| 608 | 618 | case STM32_SPDIFRX_CSR: |
|---|
| 609 | 619 | case STM32_SPDIFRX_DIR: |
|---|
| 620 | + case STM32_SPDIFRX_VERR: |
|---|
| 621 | + case STM32_SPDIFRX_IDR: |
|---|
| 622 | + case STM32_SPDIFRX_SIDR: |
|---|
| 610 | 623 | return true; |
|---|
| 611 | 624 | default: |
|---|
| 612 | 625 | return false; |
|---|
| .. | .. |
|---|
| 615 | 628 | |
|---|
| 616 | 629 | static bool stm32_spdifrx_volatile_reg(struct device *dev, unsigned int reg) |
|---|
| 617 | 630 | { |
|---|
| 618 | | - if (reg == STM32_SPDIFRX_DR) |
|---|
| 631 | + switch (reg) { |
|---|
| 632 | + case STM32_SPDIFRX_DR: |
|---|
| 633 | + case STM32_SPDIFRX_CSR: |
|---|
| 634 | + case STM32_SPDIFRX_SR: |
|---|
| 635 | + case STM32_SPDIFRX_DIR: |
|---|
| 619 | 636 | return true; |
|---|
| 620 | | - |
|---|
| 621 | | - return false; |
|---|
| 637 | + default: |
|---|
| 638 | + return false; |
|---|
| 639 | + } |
|---|
| 622 | 640 | } |
|---|
| 623 | 641 | |
|---|
| 624 | 642 | static bool stm32_spdifrx_writeable_reg(struct device *dev, unsigned int reg) |
|---|
| .. | .. |
|---|
| 637 | 655 | .reg_bits = 32, |
|---|
| 638 | 656 | .reg_stride = 4, |
|---|
| 639 | 657 | .val_bits = 32, |
|---|
| 640 | | - .max_register = STM32_SPDIFRX_DIR, |
|---|
| 658 | + .max_register = STM32_SPDIFRX_SIDR, |
|---|
| 641 | 659 | .readable_reg = stm32_spdifrx_readable_reg, |
|---|
| 642 | 660 | .volatile_reg = stm32_spdifrx_volatile_reg, |
|---|
| 643 | 661 | .writeable_reg = stm32_spdifrx_writeable_reg, |
|---|
| 662 | + .num_reg_defaults_raw = STM32_SPDIFRX_SIDR / sizeof(u32) + 1, |
|---|
| 644 | 663 | .fast_io = true, |
|---|
| 664 | + .cache_type = REGCACHE_FLAT, |
|---|
| 645 | 665 | }; |
|---|
| 646 | 666 | |
|---|
| 647 | 667 | static irqreturn_t stm32_spdifrx_isr(int irq, void *devid) |
|---|
| .. | .. |
|---|
| 649 | 669 | struct stm32_spdifrx_data *spdifrx = (struct stm32_spdifrx_data *)devid; |
|---|
| 650 | 670 | struct platform_device *pdev = spdifrx->pdev; |
|---|
| 651 | 671 | unsigned int cr, mask, sr, imr; |
|---|
| 652 | | - unsigned int flags; |
|---|
| 672 | + unsigned int flags, sync_state; |
|---|
| 653 | 673 | int err = 0, err_xrun = 0; |
|---|
| 654 | 674 | |
|---|
| 655 | 675 | regmap_read(spdifrx->regmap, STM32_SPDIFRX_SR, &sr); |
|---|
| .. | .. |
|---|
| 709 | 729 | } |
|---|
| 710 | 730 | |
|---|
| 711 | 731 | if (err) { |
|---|
| 712 | | - /* SPDIFRX in STATE_STOP. Disable SPDIFRX to clear errors */ |
|---|
| 732 | + regmap_read(spdifrx->regmap, STM32_SPDIFRX_CR, &cr); |
|---|
| 733 | + sync_state = FIELD_GET(SPDIFRX_CR_SPDIFEN_MASK, cr) && |
|---|
| 734 | + SPDIFRX_SPDIFEN_SYNC; |
|---|
| 735 | + |
|---|
| 736 | + /* SPDIFRX is in STATE_STOP. Disable SPDIFRX to clear errors */ |
|---|
| 713 | 737 | cr = SPDIFRX_CR_SPDIFENSET(SPDIFRX_SPDIFEN_DISABLE); |
|---|
| 714 | 738 | regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_CR, |
|---|
| 715 | 739 | SPDIFRX_CR_SPDIFEN_MASK, cr); |
|---|
| 740 | + |
|---|
| 741 | + /* If SPDIFRX was in STATE_SYNC, retry synchro */ |
|---|
| 742 | + if (sync_state) { |
|---|
| 743 | + cr = SPDIFRX_CR_SPDIFENSET(SPDIFRX_SPDIFEN_SYNC); |
|---|
| 744 | + regmap_update_bits(spdifrx->regmap, STM32_SPDIFRX_CR, |
|---|
| 745 | + SPDIFRX_CR_SPDIFEN_MASK, cr); |
|---|
| 746 | + return IRQ_HANDLED; |
|---|
| 747 | + } |
|---|
| 716 | 748 | |
|---|
| 717 | 749 | spin_lock(&spdifrx->irq_lock); |
|---|
| 718 | 750 | if (spdifrx->substream) |
|---|
| .. | .. |
|---|
| 850 | 882 | static const struct snd_pcm_hardware stm32_spdifrx_pcm_hw = { |
|---|
| 851 | 883 | .info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_MMAP, |
|---|
| 852 | 884 | .buffer_bytes_max = 8 * PAGE_SIZE, |
|---|
| 853 | | - .period_bytes_max = 2048, /* MDMA constraint */ |
|---|
| 885 | + .period_bytes_min = 1024, |
|---|
| 886 | + .period_bytes_max = 4 * PAGE_SIZE, |
|---|
| 854 | 887 | .periods_min = 2, |
|---|
| 855 | 888 | .periods_max = 8, |
|---|
| 856 | 889 | }; |
|---|
| .. | .. |
|---|
| 898 | 931 | |
|---|
| 899 | 932 | spdifrx->kclk = devm_clk_get(&pdev->dev, "kclk"); |
|---|
| 900 | 933 | if (IS_ERR(spdifrx->kclk)) { |
|---|
| 901 | | - dev_err(&pdev->dev, "Could not get kclk\n"); |
|---|
| 934 | + if (PTR_ERR(spdifrx->kclk) != -EPROBE_DEFER) |
|---|
| 935 | + dev_err(&pdev->dev, "Could not get kclk: %ld\n", |
|---|
| 936 | + PTR_ERR(spdifrx->kclk)); |
|---|
| 902 | 937 | return PTR_ERR(spdifrx->kclk); |
|---|
| 903 | 938 | } |
|---|
| 904 | 939 | |
|---|
| 905 | 940 | spdifrx->irq = platform_get_irq(pdev, 0); |
|---|
| 906 | | - if (spdifrx->irq < 0) { |
|---|
| 907 | | - dev_err(&pdev->dev, "No irq for node %s\n", pdev->name); |
|---|
| 941 | + if (spdifrx->irq < 0) |
|---|
| 908 | 942 | return spdifrx->irq; |
|---|
| 909 | | - } |
|---|
| 943 | + |
|---|
| 944 | + return 0; |
|---|
| 945 | +} |
|---|
| 946 | + |
|---|
| 947 | +static int stm32_spdifrx_remove(struct platform_device *pdev) |
|---|
| 948 | +{ |
|---|
| 949 | + struct stm32_spdifrx_data *spdifrx = platform_get_drvdata(pdev); |
|---|
| 950 | + |
|---|
| 951 | + if (spdifrx->ctrl_chan) |
|---|
| 952 | + dma_release_channel(spdifrx->ctrl_chan); |
|---|
| 953 | + |
|---|
| 954 | + if (spdifrx->dmab) |
|---|
| 955 | + snd_dma_free_pages(spdifrx->dmab); |
|---|
| 956 | + |
|---|
| 957 | + snd_dmaengine_pcm_unregister(&pdev->dev); |
|---|
| 958 | + snd_soc_unregister_component(&pdev->dev); |
|---|
| 910 | 959 | |
|---|
| 911 | 960 | return 0; |
|---|
| 912 | 961 | } |
|---|
| .. | .. |
|---|
| 916 | 965 | struct stm32_spdifrx_data *spdifrx; |
|---|
| 917 | 966 | struct reset_control *rst; |
|---|
| 918 | 967 | const struct snd_dmaengine_pcm_config *pcm_config = NULL; |
|---|
| 968 | + u32 ver, idr; |
|---|
| 919 | 969 | int ret; |
|---|
| 920 | 970 | |
|---|
| 921 | 971 | spdifrx = devm_kzalloc(&pdev->dev, sizeof(*spdifrx), GFP_KERNEL); |
|---|
| .. | .. |
|---|
| 937 | 987 | spdifrx->base, |
|---|
| 938 | 988 | spdifrx->regmap_conf); |
|---|
| 939 | 989 | if (IS_ERR(spdifrx->regmap)) { |
|---|
| 940 | | - dev_err(&pdev->dev, "Regmap init failed\n"); |
|---|
| 990 | + if (PTR_ERR(spdifrx->regmap) != -EPROBE_DEFER) |
|---|
| 991 | + dev_err(&pdev->dev, "Regmap init error %ld\n", |
|---|
| 992 | + PTR_ERR(spdifrx->regmap)); |
|---|
| 941 | 993 | return PTR_ERR(spdifrx->regmap); |
|---|
| 942 | 994 | } |
|---|
| 943 | 995 | |
|---|
| .. | .. |
|---|
| 948 | 1000 | return ret; |
|---|
| 949 | 1001 | } |
|---|
| 950 | 1002 | |
|---|
| 951 | | - rst = devm_reset_control_get_exclusive(&pdev->dev, NULL); |
|---|
| 952 | | - if (!IS_ERR(rst)) { |
|---|
| 953 | | - reset_control_assert(rst); |
|---|
| 954 | | - udelay(2); |
|---|
| 955 | | - reset_control_deassert(rst); |
|---|
| 1003 | + rst = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL); |
|---|
| 1004 | + if (IS_ERR(rst)) { |
|---|
| 1005 | + if (PTR_ERR(rst) != -EPROBE_DEFER) |
|---|
| 1006 | + dev_err(&pdev->dev, "Reset controller error %ld\n", |
|---|
| 1007 | + PTR_ERR(rst)); |
|---|
| 1008 | + return PTR_ERR(rst); |
|---|
| 1009 | + } |
|---|
| 1010 | + reset_control_assert(rst); |
|---|
| 1011 | + udelay(2); |
|---|
| 1012 | + reset_control_deassert(rst); |
|---|
| 1013 | + |
|---|
| 1014 | + pcm_config = &stm32_spdifrx_pcm_config; |
|---|
| 1015 | + ret = snd_dmaengine_pcm_register(&pdev->dev, pcm_config, 0); |
|---|
| 1016 | + if (ret) { |
|---|
| 1017 | + if (ret != -EPROBE_DEFER) |
|---|
| 1018 | + dev_err(&pdev->dev, "PCM DMA register error %d\n", ret); |
|---|
| 1019 | + return ret; |
|---|
| 956 | 1020 | } |
|---|
| 957 | 1021 | |
|---|
| 958 | | - ret = devm_snd_soc_register_component(&pdev->dev, |
|---|
| 959 | | - &stm32_spdifrx_component, |
|---|
| 960 | | - stm32_spdifrx_dai, |
|---|
| 961 | | - ARRAY_SIZE(stm32_spdifrx_dai)); |
|---|
| 962 | | - if (ret) |
|---|
| 1022 | + ret = snd_soc_register_component(&pdev->dev, |
|---|
| 1023 | + &stm32_spdifrx_component, |
|---|
| 1024 | + stm32_spdifrx_dai, |
|---|
| 1025 | + ARRAY_SIZE(stm32_spdifrx_dai)); |
|---|
| 1026 | + if (ret) { |
|---|
| 1027 | + snd_dmaengine_pcm_unregister(&pdev->dev); |
|---|
| 963 | 1028 | return ret; |
|---|
| 1029 | + } |
|---|
| 964 | 1030 | |
|---|
| 965 | 1031 | ret = stm32_spdifrx_dma_ctrl_register(&pdev->dev, spdifrx); |
|---|
| 966 | 1032 | if (ret) |
|---|
| 967 | 1033 | goto error; |
|---|
| 968 | 1034 | |
|---|
| 969 | | - pcm_config = &stm32_spdifrx_pcm_config; |
|---|
| 970 | | - ret = devm_snd_dmaengine_pcm_register(&pdev->dev, pcm_config, 0); |
|---|
| 971 | | - if (ret) { |
|---|
| 972 | | - dev_err(&pdev->dev, "PCM DMA register returned %d\n", ret); |
|---|
| 1035 | + ret = regmap_read(spdifrx->regmap, STM32_SPDIFRX_IDR, &idr); |
|---|
| 1036 | + if (ret) |
|---|
| 973 | 1037 | goto error; |
|---|
| 1038 | + |
|---|
| 1039 | + if (idr == SPDIFRX_IPIDR_NUMBER) { |
|---|
| 1040 | + ret = regmap_read(spdifrx->regmap, STM32_SPDIFRX_VERR, &ver); |
|---|
| 1041 | + if (ret) |
|---|
| 1042 | + goto error; |
|---|
| 1043 | + |
|---|
| 1044 | + dev_dbg(&pdev->dev, "SPDIFRX version: %lu.%lu registered\n", |
|---|
| 1045 | + FIELD_GET(SPDIFRX_VERR_MAJ_MASK, ver), |
|---|
| 1046 | + FIELD_GET(SPDIFRX_VERR_MIN_MASK, ver)); |
|---|
| 974 | 1047 | } |
|---|
| 975 | 1048 | |
|---|
| 976 | | - return 0; |
|---|
| 1049 | + return ret; |
|---|
| 977 | 1050 | |
|---|
| 978 | 1051 | error: |
|---|
| 979 | | - if (!IS_ERR(spdifrx->ctrl_chan)) |
|---|
| 980 | | - dma_release_channel(spdifrx->ctrl_chan); |
|---|
| 981 | | - if (spdifrx->dmab) |
|---|
| 982 | | - snd_dma_free_pages(spdifrx->dmab); |
|---|
| 1052 | + stm32_spdifrx_remove(pdev); |
|---|
| 983 | 1053 | |
|---|
| 984 | 1054 | return ret; |
|---|
| 985 | 1055 | } |
|---|
| 986 | 1056 | |
|---|
| 987 | | -static int stm32_spdifrx_remove(struct platform_device *pdev) |
|---|
| 1057 | +MODULE_DEVICE_TABLE(of, stm32_spdifrx_ids); |
|---|
| 1058 | + |
|---|
| 1059 | +#ifdef CONFIG_PM_SLEEP |
|---|
| 1060 | +static int stm32_spdifrx_suspend(struct device *dev) |
|---|
| 988 | 1061 | { |
|---|
| 989 | | - struct stm32_spdifrx_data *spdifrx = platform_get_drvdata(pdev); |
|---|
| 1062 | + struct stm32_spdifrx_data *spdifrx = dev_get_drvdata(dev); |
|---|
| 990 | 1063 | |
|---|
| 991 | | - if (spdifrx->ctrl_chan) |
|---|
| 992 | | - dma_release_channel(spdifrx->ctrl_chan); |
|---|
| 993 | | - |
|---|
| 994 | | - if (spdifrx->dmab) |
|---|
| 995 | | - snd_dma_free_pages(spdifrx->dmab); |
|---|
| 1064 | + regcache_cache_only(spdifrx->regmap, true); |
|---|
| 1065 | + regcache_mark_dirty(spdifrx->regmap); |
|---|
| 996 | 1066 | |
|---|
| 997 | 1067 | return 0; |
|---|
| 998 | 1068 | } |
|---|
| 999 | 1069 | |
|---|
| 1000 | | -MODULE_DEVICE_TABLE(of, stm32_spdifrx_ids); |
|---|
| 1070 | +static int stm32_spdifrx_resume(struct device *dev) |
|---|
| 1071 | +{ |
|---|
| 1072 | + struct stm32_spdifrx_data *spdifrx = dev_get_drvdata(dev); |
|---|
| 1073 | + |
|---|
| 1074 | + regcache_cache_only(spdifrx->regmap, false); |
|---|
| 1075 | + |
|---|
| 1076 | + return regcache_sync(spdifrx->regmap); |
|---|
| 1077 | +} |
|---|
| 1078 | +#endif /* CONFIG_PM_SLEEP */ |
|---|
| 1079 | + |
|---|
| 1080 | +static const struct dev_pm_ops stm32_spdifrx_pm_ops = { |
|---|
| 1081 | + SET_SYSTEM_SLEEP_PM_OPS(stm32_spdifrx_suspend, stm32_spdifrx_resume) |
|---|
| 1082 | +}; |
|---|
| 1001 | 1083 | |
|---|
| 1002 | 1084 | static struct platform_driver stm32_spdifrx_driver = { |
|---|
| 1003 | 1085 | .driver = { |
|---|
| 1004 | 1086 | .name = "st,stm32-spdifrx", |
|---|
| 1005 | 1087 | .of_match_table = stm32_spdifrx_ids, |
|---|
| 1088 | + .pm = &stm32_spdifrx_pm_ops, |
|---|
| 1006 | 1089 | }, |
|---|
| 1007 | 1090 | .probe = stm32_spdifrx_probe, |
|---|
| 1008 | 1091 | .remove = stm32_spdifrx_remove, |
|---|