.. | .. |
---|
27 | 27 | #define CLK_PPM_MIN (-1000) |
---|
28 | 28 | #define CLK_PPM_MAX (1000) |
---|
29 | 29 | |
---|
| 30 | +#define DEFAULT_MCLK_FS 256 |
---|
| 31 | +#define DEFAULT_FS 48000 |
---|
| 32 | + |
---|
| 33 | +#define WAIT_TIME_MS_MAX 10000 |
---|
| 34 | + |
---|
| 35 | +#define QUIRK_ALWAYS_ON BIT(0) |
---|
| 36 | + |
---|
30 | 37 | struct rk_i2s_pins { |
---|
31 | 38 | u32 reg_offset; |
---|
32 | 39 | u32 shift; |
---|
.. | .. |
---|
44 | 51 | |
---|
45 | 52 | struct regmap *regmap; |
---|
46 | 53 | struct regmap *grf; |
---|
| 54 | + |
---|
| 55 | + struct snd_pcm_substream *substreams[SNDRV_PCM_STREAM_LAST + 1]; |
---|
| 56 | + unsigned int wait_time[SNDRV_PCM_STREAM_LAST + 1]; |
---|
47 | 57 | |
---|
48 | 58 | bool has_capture; |
---|
49 | 59 | bool has_playback; |
---|
.. | .. |
---|
66 | 76 | int clk_ppm; |
---|
67 | 77 | bool mclk_calibrate; |
---|
68 | 78 | |
---|
| 79 | + unsigned int quirks; |
---|
| 80 | +}; |
---|
| 81 | + |
---|
| 82 | +static struct i2s_of_quirks { |
---|
| 83 | + char *quirk; |
---|
| 84 | + int id; |
---|
| 85 | +} of_quirks[] = { |
---|
| 86 | + { |
---|
| 87 | + .quirk = "rockchip,always-on", |
---|
| 88 | + .id = QUIRK_ALWAYS_ON, |
---|
| 89 | + }, |
---|
69 | 90 | }; |
---|
70 | 91 | |
---|
71 | 92 | static int i2s_runtime_suspend(struct device *dev) |
---|
.. | .. |
---|
157 | 178 | regmap_update_bits(i2s->regmap, I2S_DMACR, |
---|
158 | 179 | I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_DISABLE); |
---|
159 | 180 | |
---|
160 | | - if (!i2s->rx_start) { |
---|
| 181 | + if (!i2s->rx_start && !(i2s->quirks & QUIRK_ALWAYS_ON)) { |
---|
161 | 182 | regmap_update_bits(i2s->regmap, I2S_XFER, |
---|
162 | 183 | I2S_XFER_TXS_START | |
---|
163 | 184 | I2S_XFER_RXS_START, |
---|
.. | .. |
---|
189 | 210 | regmap_update_bits(i2s->regmap, I2S_DMACR, |
---|
190 | 211 | I2S_DMACR_RDE_ENABLE, I2S_DMACR_RDE_DISABLE); |
---|
191 | 212 | |
---|
192 | | - if (!i2s->tx_start) { |
---|
| 213 | + if (!i2s->tx_start && !(i2s->quirks & QUIRK_ALWAYS_ON)) { |
---|
193 | 214 | regmap_update_bits(i2s->regmap, I2S_XFER, |
---|
194 | 215 | I2S_XFER_TXS_START | |
---|
195 | 216 | I2S_XFER_RXS_START, |
---|
.. | .. |
---|
353 | 374 | val |= I2S_TXCR_VDW(24); |
---|
354 | 375 | break; |
---|
355 | 376 | case SNDRV_PCM_FORMAT_S32_LE: |
---|
| 377 | + case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE: |
---|
356 | 378 | val |= I2S_TXCR_VDW(32); |
---|
357 | 379 | break; |
---|
358 | 380 | default: |
---|
.. | .. |
---|
588 | 610 | i2s->has_capture ? &i2s->capture_dma_data : NULL); |
---|
589 | 611 | |
---|
590 | 612 | if (i2s->mclk_calibrate) |
---|
591 | | - snd_soc_add_dai_controls(dai, &rockchip_i2s_compensation_control, 1); |
---|
| 613 | + snd_soc_add_component_controls(dai->component, |
---|
| 614 | + &rockchip_i2s_compensation_control, |
---|
| 615 | + 1); |
---|
592 | 616 | |
---|
593 | 617 | return 0; |
---|
594 | 618 | } |
---|
595 | 619 | |
---|
| 620 | +static int rockchip_i2s_startup(struct snd_pcm_substream *substream, |
---|
| 621 | + struct snd_soc_dai *dai) |
---|
| 622 | +{ |
---|
| 623 | + struct rk_i2s_dev *i2s = snd_soc_dai_get_drvdata(dai); |
---|
| 624 | + int stream = substream->stream; |
---|
| 625 | + |
---|
| 626 | + if (i2s->substreams[stream]) |
---|
| 627 | + return -EBUSY; |
---|
| 628 | + |
---|
| 629 | + if (i2s->wait_time[stream]) |
---|
| 630 | + substream->wait_time = msecs_to_jiffies(i2s->wait_time[stream]); |
---|
| 631 | + |
---|
| 632 | + i2s->substreams[stream] = substream; |
---|
| 633 | + |
---|
| 634 | + return 0; |
---|
| 635 | +} |
---|
| 636 | + |
---|
| 637 | +static void rockchip_i2s_shutdown(struct snd_pcm_substream *substream, |
---|
| 638 | + struct snd_soc_dai *dai) |
---|
| 639 | +{ |
---|
| 640 | + struct rk_i2s_dev *i2s = snd_soc_dai_get_drvdata(dai); |
---|
| 641 | + |
---|
| 642 | + i2s->substreams[substream->stream] = NULL; |
---|
| 643 | +} |
---|
| 644 | + |
---|
596 | 645 | static const struct snd_soc_dai_ops rockchip_i2s_dai_ops = { |
---|
| 646 | + .startup = rockchip_i2s_startup, |
---|
| 647 | + .shutdown = rockchip_i2s_shutdown, |
---|
597 | 648 | .hw_params = rockchip_i2s_hw_params, |
---|
598 | 649 | .set_bclk_ratio = rockchip_i2s_set_bclk_ratio, |
---|
599 | 650 | .set_sysclk = rockchip_i2s_set_sysclk, |
---|
.. | .. |
---|
606 | 657 | .ops = &rockchip_i2s_dai_ops, |
---|
607 | 658 | }; |
---|
608 | 659 | |
---|
| 660 | +static int rockchip_i2s_get_bclk_ratio(struct snd_kcontrol *kcontrol, |
---|
| 661 | + struct snd_ctl_elem_value *ucontrol) |
---|
| 662 | +{ |
---|
| 663 | + struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol); |
---|
| 664 | + struct rk_i2s_dev *i2s = snd_soc_component_get_drvdata(compnt); |
---|
| 665 | + |
---|
| 666 | + ucontrol->value.integer.value[0] = i2s->bclk_ratio; |
---|
| 667 | + |
---|
| 668 | + return 0; |
---|
| 669 | +} |
---|
| 670 | + |
---|
| 671 | +static int rockchip_i2s_put_bclk_ratio(struct snd_kcontrol *kcontrol, |
---|
| 672 | + struct snd_ctl_elem_value *ucontrol) |
---|
| 673 | +{ |
---|
| 674 | + struct snd_soc_component *compnt = snd_soc_kcontrol_component(kcontrol); |
---|
| 675 | + struct rk_i2s_dev *i2s = snd_soc_component_get_drvdata(compnt); |
---|
| 676 | + int value = ucontrol->value.integer.value[0]; |
---|
| 677 | + |
---|
| 678 | + if (value == i2s->bclk_ratio) |
---|
| 679 | + return 0; |
---|
| 680 | + |
---|
| 681 | + i2s->bclk_ratio = value; |
---|
| 682 | + |
---|
| 683 | + return 1; |
---|
| 684 | +} |
---|
| 685 | + |
---|
| 686 | +static int rockchip_i2s_wait_time_info(struct snd_kcontrol *kcontrol, |
---|
| 687 | + struct snd_ctl_elem_info *uinfo) |
---|
| 688 | +{ |
---|
| 689 | + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; |
---|
| 690 | + uinfo->count = 1; |
---|
| 691 | + uinfo->value.integer.min = 0; |
---|
| 692 | + uinfo->value.integer.max = WAIT_TIME_MS_MAX; |
---|
| 693 | + uinfo->value.integer.step = 1; |
---|
| 694 | + |
---|
| 695 | + return 0; |
---|
| 696 | +} |
---|
| 697 | + |
---|
| 698 | +static int rockchip_i2s_rd_wait_time_get(struct snd_kcontrol *kcontrol, |
---|
| 699 | + struct snd_ctl_elem_value *ucontrol) |
---|
| 700 | +{ |
---|
| 701 | + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); |
---|
| 702 | + struct rk_i2s_dev *i2s = snd_soc_component_get_drvdata(component); |
---|
| 703 | + |
---|
| 704 | + ucontrol->value.integer.value[0] = i2s->wait_time[SNDRV_PCM_STREAM_CAPTURE]; |
---|
| 705 | + |
---|
| 706 | + return 0; |
---|
| 707 | +} |
---|
| 708 | + |
---|
| 709 | +static int rockchip_i2s_rd_wait_time_put(struct snd_kcontrol *kcontrol, |
---|
| 710 | + struct snd_ctl_elem_value *ucontrol) |
---|
| 711 | +{ |
---|
| 712 | + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); |
---|
| 713 | + struct rk_i2s_dev *i2s = snd_soc_component_get_drvdata(component); |
---|
| 714 | + |
---|
| 715 | + if (ucontrol->value.integer.value[0] > WAIT_TIME_MS_MAX) |
---|
| 716 | + return -EINVAL; |
---|
| 717 | + |
---|
| 718 | + i2s->wait_time[SNDRV_PCM_STREAM_CAPTURE] = ucontrol->value.integer.value[0]; |
---|
| 719 | + |
---|
| 720 | + return 1; |
---|
| 721 | +} |
---|
| 722 | + |
---|
| 723 | +static int rockchip_i2s_wr_wait_time_get(struct snd_kcontrol *kcontrol, |
---|
| 724 | + struct snd_ctl_elem_value *ucontrol) |
---|
| 725 | +{ |
---|
| 726 | + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); |
---|
| 727 | + struct rk_i2s_dev *i2s = snd_soc_component_get_drvdata(component); |
---|
| 728 | + |
---|
| 729 | + ucontrol->value.integer.value[0] = i2s->wait_time[SNDRV_PCM_STREAM_PLAYBACK]; |
---|
| 730 | + |
---|
| 731 | + return 0; |
---|
| 732 | +} |
---|
| 733 | + |
---|
| 734 | +static int rockchip_i2s_wr_wait_time_put(struct snd_kcontrol *kcontrol, |
---|
| 735 | + struct snd_ctl_elem_value *ucontrol) |
---|
| 736 | +{ |
---|
| 737 | + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); |
---|
| 738 | + struct rk_i2s_dev *i2s = snd_soc_component_get_drvdata(component); |
---|
| 739 | + |
---|
| 740 | + if (ucontrol->value.integer.value[0] > WAIT_TIME_MS_MAX) |
---|
| 741 | + return -EINVAL; |
---|
| 742 | + |
---|
| 743 | + i2s->wait_time[SNDRV_PCM_STREAM_PLAYBACK] = ucontrol->value.integer.value[0]; |
---|
| 744 | + |
---|
| 745 | + return 1; |
---|
| 746 | +} |
---|
| 747 | + |
---|
| 748 | +#define SAI_PCM_WAIT_TIME(xname, xhandler_get, xhandler_put) \ |
---|
| 749 | +{ .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = xname, \ |
---|
| 750 | + .info = rockchip_i2s_wait_time_info, \ |
---|
| 751 | + .get = xhandler_get, .put = xhandler_put } |
---|
| 752 | + |
---|
| 753 | +static const struct snd_kcontrol_new rockchip_i2s_snd_controls[] = { |
---|
| 754 | + SOC_SINGLE_EXT("BCLK Ratio", 0, 0, INT_MAX, 0, |
---|
| 755 | + rockchip_i2s_get_bclk_ratio, |
---|
| 756 | + rockchip_i2s_put_bclk_ratio), |
---|
| 757 | + |
---|
| 758 | + SAI_PCM_WAIT_TIME("PCM Read Wait Time MS", |
---|
| 759 | + rockchip_i2s_rd_wait_time_get, |
---|
| 760 | + rockchip_i2s_rd_wait_time_put), |
---|
| 761 | + SAI_PCM_WAIT_TIME("PCM Write Wait Time MS", |
---|
| 762 | + rockchip_i2s_wr_wait_time_get, |
---|
| 763 | + rockchip_i2s_wr_wait_time_put), |
---|
| 764 | +}; |
---|
| 765 | + |
---|
609 | 766 | static const struct snd_soc_component_driver rockchip_i2s_component = { |
---|
610 | 767 | .name = DRV_NAME, |
---|
| 768 | + .controls = rockchip_i2s_snd_controls, |
---|
| 769 | + .num_controls = ARRAY_SIZE(rockchip_i2s_snd_controls), |
---|
611 | 770 | }; |
---|
612 | 771 | |
---|
613 | 772 | static bool rockchip_i2s_wr_reg(struct device *dev, unsigned int reg) |
---|
.. | .. |
---|
772 | 931 | SNDRV_PCM_FMTBIT_S16_LE | |
---|
773 | 932 | SNDRV_PCM_FMTBIT_S20_3LE | |
---|
774 | 933 | SNDRV_PCM_FMTBIT_S24_LE | |
---|
775 | | - SNDRV_PCM_FMTBIT_S32_LE; |
---|
| 934 | + SNDRV_PCM_FMTBIT_S32_LE | |
---|
| 935 | + SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE; |
---|
776 | 936 | |
---|
777 | 937 | i2s->playback_dma_data.addr = res->start + I2S_TXDR; |
---|
778 | 938 | i2s->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; |
---|
.. | .. |
---|
793 | 953 | SNDRV_PCM_FMTBIT_S16_LE | |
---|
794 | 954 | SNDRV_PCM_FMTBIT_S20_3LE | |
---|
795 | 955 | SNDRV_PCM_FMTBIT_S24_LE | |
---|
796 | | - SNDRV_PCM_FMTBIT_S32_LE; |
---|
| 956 | + SNDRV_PCM_FMTBIT_S32_LE | |
---|
| 957 | + SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE; |
---|
797 | 958 | |
---|
798 | 959 | i2s->capture_dma_data.addr = res->start + I2S_RXDR; |
---|
799 | 960 | i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; |
---|
.. | .. |
---|
823 | 984 | return 0; |
---|
824 | 985 | } |
---|
825 | 986 | |
---|
| 987 | +static int rockchip_i2s_keep_clk_always_on(struct rk_i2s_dev *i2s) |
---|
| 988 | +{ |
---|
| 989 | + unsigned int mclk_rate = DEFAULT_FS * DEFAULT_MCLK_FS; |
---|
| 990 | + unsigned int bclk_rate = i2s->bclk_ratio * DEFAULT_FS; |
---|
| 991 | + unsigned int div_lrck = i2s->bclk_ratio; |
---|
| 992 | + unsigned int div_bclk; |
---|
| 993 | + |
---|
| 994 | + div_bclk = DIV_ROUND_CLOSEST(mclk_rate, bclk_rate); |
---|
| 995 | + |
---|
| 996 | + /* assign generic freq */ |
---|
| 997 | + clk_set_rate(i2s->mclk, mclk_rate); |
---|
| 998 | + |
---|
| 999 | + regmap_update_bits(i2s->regmap, I2S_CKR, |
---|
| 1000 | + I2S_CKR_MDIV_MASK, |
---|
| 1001 | + I2S_CKR_MDIV(div_bclk)); |
---|
| 1002 | + regmap_update_bits(i2s->regmap, I2S_CKR, |
---|
| 1003 | + I2S_CKR_TSD_MASK | |
---|
| 1004 | + I2S_CKR_RSD_MASK, |
---|
| 1005 | + I2S_CKR_TSD(div_lrck) | |
---|
| 1006 | + I2S_CKR_RSD(div_lrck)); |
---|
| 1007 | + regmap_update_bits(i2s->regmap, I2S_XFER, |
---|
| 1008 | + I2S_XFER_TXS_START | I2S_XFER_RXS_START, |
---|
| 1009 | + I2S_XFER_TXS_START | I2S_XFER_RXS_START); |
---|
| 1010 | + |
---|
| 1011 | + pm_runtime_forbid(i2s->dev); |
---|
| 1012 | + |
---|
| 1013 | + dev_info(i2s->dev, "CLK-ALWAYS-ON: mclk: %d, bclk: %d, fsync: %d\n", |
---|
| 1014 | + mclk_rate, bclk_rate, DEFAULT_FS); |
---|
| 1015 | + |
---|
| 1016 | + return 0; |
---|
| 1017 | +} |
---|
| 1018 | + |
---|
826 | 1019 | static int rockchip_i2s_probe(struct platform_device *pdev) |
---|
827 | 1020 | { |
---|
828 | 1021 | struct device_node *node = pdev->dev.of_node; |
---|
.. | .. |
---|
831 | 1024 | struct snd_soc_dai_driver *dai; |
---|
832 | 1025 | struct resource *res; |
---|
833 | 1026 | void __iomem *regs; |
---|
834 | | - int ret; |
---|
| 1027 | + int ret, i, val; |
---|
835 | 1028 | |
---|
836 | 1029 | i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL); |
---|
837 | 1030 | if (!i2s) |
---|
.. | .. |
---|
849 | 1042 | i2s->pins = of_id->data; |
---|
850 | 1043 | } |
---|
851 | 1044 | |
---|
| 1045 | + for (i = 0; i < ARRAY_SIZE(of_quirks); i++) |
---|
| 1046 | + if (device_property_read_bool(i2s->dev, of_quirks[i].quirk)) |
---|
| 1047 | + i2s->quirks |= of_quirks[i].id; |
---|
| 1048 | + |
---|
852 | 1049 | regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res); |
---|
853 | 1050 | if (IS_ERR(regs)) |
---|
854 | 1051 | return PTR_ERR(regs); |
---|
.. | .. |
---|
862 | 1059 | } |
---|
863 | 1060 | |
---|
864 | 1061 | i2s->bclk_ratio = 64; |
---|
| 1062 | + if (!device_property_read_u32(&pdev->dev, "rockchip,bclk-fs", &val)) { |
---|
| 1063 | + if ((val >= 32) && (val % 2 == 0)) |
---|
| 1064 | + i2s->bclk_ratio = val; |
---|
| 1065 | + } |
---|
865 | 1066 | |
---|
866 | 1067 | dev_set_drvdata(&pdev->dev, i2s); |
---|
867 | 1068 | |
---|
.. | .. |
---|
894 | 1095 | return ret; |
---|
895 | 1096 | } |
---|
896 | 1097 | |
---|
| 1098 | + ret = rockchip_i2s_init_dai(i2s, res, &dai); |
---|
| 1099 | + if (ret) |
---|
| 1100 | + goto err_clk; |
---|
| 1101 | + |
---|
| 1102 | + /* |
---|
| 1103 | + * CLK_ALWAYS_ON should be placed after all registers write done, |
---|
| 1104 | + * because this situation will enable XFER bit which will make |
---|
| 1105 | + * some registers(depend on XFER) write failed. |
---|
| 1106 | + */ |
---|
| 1107 | + if (i2s->quirks & QUIRK_ALWAYS_ON) { |
---|
| 1108 | + ret = rockchip_i2s_keep_clk_always_on(i2s); |
---|
| 1109 | + if (ret) |
---|
| 1110 | + goto err_clk; |
---|
| 1111 | + } |
---|
| 1112 | + |
---|
| 1113 | + /* |
---|
| 1114 | + * MUST: after pm_runtime_enable step, any register R/W |
---|
| 1115 | + * should be wrapped with pm_runtime_get_sync/put. |
---|
| 1116 | + * |
---|
| 1117 | + * Another approach is to enable the regcache true to |
---|
| 1118 | + * avoid access HW registers. |
---|
| 1119 | + * |
---|
| 1120 | + * Alternatively, performing the registers R/W before |
---|
| 1121 | + * pm_runtime_enable is also a good option. |
---|
| 1122 | + */ |
---|
897 | 1123 | pm_runtime_enable(&pdev->dev); |
---|
898 | 1124 | if (!pm_runtime_enabled(&pdev->dev)) { |
---|
899 | 1125 | ret = i2s_runtime_resume(&pdev->dev); |
---|
900 | 1126 | if (ret) |
---|
901 | 1127 | goto err_pm_disable; |
---|
902 | 1128 | } |
---|
903 | | - |
---|
904 | | - ret = rockchip_i2s_init_dai(i2s, res, &dai); |
---|
905 | | - if (ret) |
---|
906 | | - goto err_pm_disable; |
---|
907 | 1129 | |
---|
908 | 1130 | ret = devm_snd_soc_register_component(&pdev->dev, |
---|
909 | 1131 | &rockchip_i2s_component, |
---|
.. | .. |
---|
932 | 1154 | i2s_runtime_suspend(&pdev->dev); |
---|
933 | 1155 | err_pm_disable: |
---|
934 | 1156 | pm_runtime_disable(&pdev->dev); |
---|
935 | | - |
---|
| 1157 | +err_clk: |
---|
936 | 1158 | clk_disable_unprepare(i2s->hclk); |
---|
937 | 1159 | |
---|
938 | 1160 | return ret; |
---|