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