diff options
| -rw-r--r-- | include/sound/sh_fsi.h | 6 | ||||
| -rw-r--r-- | sound/soc/sh/fsi.c | 378 |
2 files changed, 378 insertions, 6 deletions
diff --git a/include/sound/sh_fsi.h b/include/sound/sh_fsi.h index 906010344dd7..27ee1dcc3e2e 100644 --- a/include/sound/sh_fsi.h +++ b/include/sound/sh_fsi.h | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | * A: inversion | 26 | * A: inversion |
| 27 | * B: format mode | 27 | * B: format mode |
| 28 | * C: chip specific | 28 | * C: chip specific |
| 29 | * D: clock selecter if master mode | ||
| 29 | */ | 30 | */ |
| 30 | 31 | ||
| 31 | /* A: clock inversion */ | 32 | /* A: clock inversion */ |
| @@ -44,6 +45,11 @@ | |||
| 44 | #define SH_FSI_OPTION_MASK 0x00000F00 | 45 | #define SH_FSI_OPTION_MASK 0x00000F00 |
| 45 | #define SH_FSI_ENABLE_STREAM_MODE (1 << 8) /* for 16bit data */ | 46 | #define SH_FSI_ENABLE_STREAM_MODE (1 << 8) /* for 16bit data */ |
| 46 | 47 | ||
| 48 | /* D: clock selecter if master mode */ | ||
| 49 | #define SH_FSI_CLK_MASK 0x0000F000 | ||
| 50 | #define SH_FSI_CLK_EXTERNAL (1 << 12) | ||
| 51 | #define SH_FSI_CLK_CPG (2 << 12) /* FSIxCK + FSI-DIV */ | ||
| 52 | |||
| 47 | /* | 53 | /* |
| 48 | * set_rate return value | 54 | * set_rate return value |
| 49 | * | 55 | * |
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index ef257bcb5341..bdaca356aaad 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
| 22 | #include <linux/module.h> | 22 | #include <linux/module.h> |
| 23 | #include <sound/soc.h> | 23 | #include <sound/soc.h> |
| 24 | #include <sound/pcm_params.h> | ||
| 24 | #include <sound/sh_fsi.h> | 25 | #include <sound/sh_fsi.h> |
| 25 | 26 | ||
| 26 | /* PortA/PortB register */ | 27 | /* PortA/PortB register */ |
| @@ -188,6 +189,14 @@ typedef int (*set_rate_func)(struct device *dev, int rate, int enable); | |||
| 188 | */ | 189 | */ |
| 189 | 190 | ||
| 190 | /* | 191 | /* |
| 192 | * FSI clock | ||
| 193 | * | ||
| 194 | * FSIxCLK [CPG] (ick) -------> | | ||
| 195 | * |-> FSI_DIV (div)-> FSI2 | ||
| 196 | * FSIxCK [external] (xck) ---> | | ||
| 197 | */ | ||
| 198 | |||
| 199 | /* | ||
| 191 | * struct | 200 | * struct |
| 192 | */ | 201 | */ |
| 193 | 202 | ||
| @@ -227,6 +236,20 @@ struct fsi_stream { | |||
| 227 | dma_addr_t dma; | 236 | dma_addr_t dma; |
| 228 | }; | 237 | }; |
| 229 | 238 | ||
| 239 | struct fsi_clk { | ||
| 240 | /* see [FSI clock] */ | ||
| 241 | struct clk *own; | ||
| 242 | struct clk *xck; | ||
| 243 | struct clk *ick; | ||
| 244 | struct clk *div; | ||
| 245 | int (*set_rate)(struct device *dev, | ||
| 246 | struct fsi_priv *fsi, | ||
| 247 | unsigned long rate); | ||
| 248 | |||
| 249 | unsigned long rate; | ||
| 250 | unsigned int count; | ||
| 251 | }; | ||
| 252 | |||
| 230 | struct fsi_priv { | 253 | struct fsi_priv { |
| 231 | void __iomem *base; | 254 | void __iomem *base; |
| 232 | struct fsi_master *master; | 255 | struct fsi_master *master; |
| @@ -235,6 +258,8 @@ struct fsi_priv { | |||
| 235 | struct fsi_stream playback; | 258 | struct fsi_stream playback; |
| 236 | struct fsi_stream capture; | 259 | struct fsi_stream capture; |
| 237 | 260 | ||
| 261 | struct fsi_clk clock; | ||
| 262 | |||
| 238 | u32 fmt; | 263 | u32 fmt; |
| 239 | 264 | ||
| 240 | int chan_num:16; | 265 | int chan_num:16; |
| @@ -716,14 +741,335 @@ static void fsi_spdif_clk_ctrl(struct fsi_priv *fsi, int enable) | |||
| 716 | /* | 741 | /* |
| 717 | * clock function | 742 | * clock function |
| 718 | */ | 743 | */ |
| 744 | static int fsi_clk_init(struct device *dev, | ||
| 745 | struct fsi_priv *fsi, | ||
| 746 | int xck, | ||
| 747 | int ick, | ||
| 748 | int div, | ||
| 749 | int (*set_rate)(struct device *dev, | ||
| 750 | struct fsi_priv *fsi, | ||
| 751 | unsigned long rate)) | ||
| 752 | { | ||
| 753 | struct fsi_clk *clock = &fsi->clock; | ||
| 754 | int is_porta = fsi_is_port_a(fsi); | ||
| 755 | |||
| 756 | clock->xck = NULL; | ||
| 757 | clock->ick = NULL; | ||
| 758 | clock->div = NULL; | ||
| 759 | clock->rate = 0; | ||
| 760 | clock->count = 0; | ||
| 761 | clock->set_rate = set_rate; | ||
| 762 | |||
| 763 | clock->own = devm_clk_get(dev, NULL); | ||
| 764 | if (IS_ERR(clock->own)) | ||
| 765 | return -EINVAL; | ||
| 766 | |||
| 767 | /* external clock */ | ||
| 768 | if (xck) { | ||
| 769 | clock->xck = devm_clk_get(dev, is_porta ? "xcka" : "xckb"); | ||
| 770 | if (IS_ERR(clock->xck)) { | ||
| 771 | dev_err(dev, "can't get xck clock\n"); | ||
| 772 | return -EINVAL; | ||
| 773 | } | ||
| 774 | if (clock->xck == clock->own) { | ||
| 775 | dev_err(dev, "cpu doesn't support xck clock\n"); | ||
| 776 | return -EINVAL; | ||
| 777 | } | ||
| 778 | } | ||
| 779 | |||
| 780 | /* FSIACLK/FSIBCLK */ | ||
| 781 | if (ick) { | ||
| 782 | clock->ick = devm_clk_get(dev, is_porta ? "icka" : "ickb"); | ||
| 783 | if (IS_ERR(clock->ick)) { | ||
| 784 | dev_err(dev, "can't get ick clock\n"); | ||
| 785 | return -EINVAL; | ||
| 786 | } | ||
| 787 | if (clock->ick == clock->own) { | ||
| 788 | dev_err(dev, "cpu doesn't support ick clock\n"); | ||
| 789 | return -EINVAL; | ||
| 790 | } | ||
| 791 | } | ||
| 792 | |||
| 793 | /* FSI-DIV */ | ||
| 794 | if (div) { | ||
| 795 | clock->div = devm_clk_get(dev, is_porta ? "diva" : "divb"); | ||
| 796 | if (IS_ERR(clock->div)) { | ||
| 797 | dev_err(dev, "can't get div clock\n"); | ||
| 798 | return -EINVAL; | ||
| 799 | } | ||
| 800 | if (clock->div == clock->own) { | ||
| 801 | dev_err(dev, "cpu doens't support div clock\n"); | ||
| 802 | return -EINVAL; | ||
| 803 | } | ||
| 804 | } | ||
| 805 | |||
| 806 | return 0; | ||
| 807 | } | ||
| 808 | |||
| 809 | #define fsi_clk_invalid(fsi) fsi_clk_valid(fsi, 0) | ||
| 810 | static void fsi_clk_valid(struct fsi_priv *fsi, unsigned long rate) | ||
| 811 | { | ||
| 812 | fsi->clock.rate = rate; | ||
| 813 | } | ||
| 814 | |||
| 815 | static int fsi_clk_is_valid(struct fsi_priv *fsi) | ||
| 816 | { | ||
| 817 | return fsi->clock.set_rate && | ||
| 818 | fsi->clock.rate; | ||
| 819 | } | ||
| 820 | |||
| 821 | static int fsi_clk_enable(struct device *dev, | ||
| 822 | struct fsi_priv *fsi, | ||
| 823 | unsigned long rate) | ||
| 824 | { | ||
| 825 | struct fsi_clk *clock = &fsi->clock; | ||
| 826 | int ret = -EINVAL; | ||
| 827 | |||
| 828 | if (!fsi_clk_is_valid(fsi)) | ||
| 829 | return ret; | ||
| 830 | |||
| 831 | if (0 == clock->count) { | ||
| 832 | ret = clock->set_rate(dev, fsi, rate); | ||
| 833 | if (ret < 0) { | ||
| 834 | fsi_clk_invalid(fsi); | ||
| 835 | return ret; | ||
| 836 | } | ||
| 837 | |||
| 838 | if (clock->xck) | ||
| 839 | clk_enable(clock->xck); | ||
| 840 | if (clock->ick) | ||
| 841 | clk_enable(clock->ick); | ||
| 842 | if (clock->div) | ||
| 843 | clk_enable(clock->div); | ||
| 844 | |||
| 845 | clock->count++; | ||
| 846 | } | ||
| 847 | |||
| 848 | return ret; | ||
| 849 | } | ||
| 850 | |||
| 851 | static int fsi_clk_disable(struct device *dev, | ||
| 852 | struct fsi_priv *fsi) | ||
| 853 | { | ||
| 854 | struct fsi_clk *clock = &fsi->clock; | ||
| 855 | |||
| 856 | if (!fsi_clk_is_valid(fsi)) | ||
| 857 | return -EINVAL; | ||
| 858 | |||
| 859 | if (1 == clock->count--) { | ||
| 860 | if (clock->xck) | ||
| 861 | clk_disable(clock->xck); | ||
| 862 | if (clock->ick) | ||
| 863 | clk_disable(clock->ick); | ||
| 864 | if (clock->div) | ||
| 865 | clk_disable(clock->div); | ||
| 866 | } | ||
| 867 | |||
| 868 | return 0; | ||
| 869 | } | ||
| 870 | |||
| 871 | static int fsi_clk_set_ackbpf(struct device *dev, | ||
| 872 | struct fsi_priv *fsi, | ||
| 873 | int ackmd, int bpfmd) | ||
| 874 | { | ||
| 875 | u32 data = 0; | ||
| 876 | |||
| 877 | /* check ackmd/bpfmd relationship */ | ||
| 878 | if (bpfmd > ackmd) { | ||
| 879 | dev_err(dev, "unsupported rate (%d/%d)\n", ackmd, bpfmd); | ||
| 880 | return -EINVAL; | ||
| 881 | } | ||
| 882 | |||
| 883 | /* ACKMD */ | ||
| 884 | switch (ackmd) { | ||
| 885 | case 512: | ||
| 886 | data |= (0x0 << 12); | ||
| 887 | break; | ||
| 888 | case 256: | ||
| 889 | data |= (0x1 << 12); | ||
| 890 | break; | ||
| 891 | case 128: | ||
| 892 | data |= (0x2 << 12); | ||
| 893 | break; | ||
| 894 | case 64: | ||
| 895 | data |= (0x3 << 12); | ||
| 896 | break; | ||
| 897 | case 32: | ||
| 898 | data |= (0x4 << 12); | ||
| 899 | break; | ||
| 900 | default: | ||
| 901 | dev_err(dev, "unsupported ackmd (%d)\n", ackmd); | ||
| 902 | return -EINVAL; | ||
| 903 | } | ||
| 904 | |||
| 905 | /* BPFMD */ | ||
| 906 | switch (bpfmd) { | ||
| 907 | case 32: | ||
| 908 | data |= (0x0 << 8); | ||
| 909 | break; | ||
| 910 | case 64: | ||
| 911 | data |= (0x1 << 8); | ||
| 912 | break; | ||
| 913 | case 128: | ||
| 914 | data |= (0x2 << 8); | ||
| 915 | break; | ||
| 916 | case 256: | ||
| 917 | data |= (0x3 << 8); | ||
| 918 | break; | ||
| 919 | case 512: | ||
| 920 | data |= (0x4 << 8); | ||
| 921 | break; | ||
| 922 | case 16: | ||
| 923 | data |= (0x7 << 8); | ||
| 924 | break; | ||
| 925 | default: | ||
| 926 | dev_err(dev, "unsupported bpfmd (%d)\n", bpfmd); | ||
| 927 | return -EINVAL; | ||
| 928 | } | ||
| 929 | |||
| 930 | dev_dbg(dev, "ACKMD/BPFMD = %d/%d\n", ackmd, bpfmd); | ||
| 931 | |||
| 932 | fsi_reg_mask_set(fsi, CKG1, (ACKMD_MASK | BPFMD_MASK) , data); | ||
| 933 | udelay(10); | ||
| 934 | |||
| 935 | return 0; | ||
| 936 | } | ||
| 937 | |||
| 938 | static int fsi_clk_set_rate_external(struct device *dev, | ||
| 939 | struct fsi_priv *fsi, | ||
| 940 | unsigned long rate) | ||
| 941 | { | ||
| 942 | struct clk *xck = fsi->clock.xck; | ||
| 943 | struct clk *ick = fsi->clock.ick; | ||
| 944 | unsigned long xrate; | ||
| 945 | int ackmd, bpfmd; | ||
| 946 | int ret = 0; | ||
| 947 | |||
| 948 | /* check clock rate */ | ||
| 949 | xrate = clk_get_rate(xck); | ||
| 950 | if (xrate % rate) { | ||
| 951 | dev_err(dev, "unsupported clock rate\n"); | ||
| 952 | return -EINVAL; | ||
| 953 | } | ||
| 954 | |||
| 955 | clk_set_parent(ick, xck); | ||
| 956 | clk_set_rate(ick, xrate); | ||
| 957 | |||
| 958 | bpfmd = fsi->chan_num * 32; | ||
| 959 | ackmd = xrate / rate; | ||
| 960 | |||
| 961 | dev_dbg(dev, "external/rate = %ld/%ld\n", xrate, rate); | ||
| 962 | |||
| 963 | ret = fsi_clk_set_ackbpf(dev, fsi, ackmd, bpfmd); | ||
| 964 | if (ret < 0) | ||
| 965 | dev_err(dev, "%s failed", __func__); | ||
| 966 | |||
| 967 | return ret; | ||
| 968 | } | ||
| 969 | |||
| 970 | static int fsi_clk_set_rate_cpg(struct device *dev, | ||
| 971 | struct fsi_priv *fsi, | ||
| 972 | unsigned long rate) | ||
| 973 | { | ||
| 974 | struct clk *ick = fsi->clock.ick; | ||
| 975 | struct clk *div = fsi->clock.div; | ||
| 976 | unsigned long target = 0; /* 12288000 or 11289600 */ | ||
| 977 | unsigned long actual, cout; | ||
| 978 | unsigned long diff, min; | ||
| 979 | unsigned long best_cout, best_act; | ||
| 980 | int adj; | ||
| 981 | int ackmd, bpfmd; | ||
| 982 | int ret = -EINVAL; | ||
| 983 | |||
| 984 | if (!(12288000 % rate)) | ||
| 985 | target = 12288000; | ||
| 986 | if (!(11289600 % rate)) | ||
| 987 | target = 11289600; | ||
| 988 | if (!target) { | ||
| 989 | dev_err(dev, "unsupported rate\n"); | ||
| 990 | return ret; | ||
| 991 | } | ||
| 992 | |||
| 993 | bpfmd = fsi->chan_num * 32; | ||
| 994 | ackmd = target / rate; | ||
| 995 | ret = fsi_clk_set_ackbpf(dev, fsi, ackmd, bpfmd); | ||
| 996 | if (ret < 0) { | ||
| 997 | dev_err(dev, "%s failed", __func__); | ||
| 998 | return ret; | ||
| 999 | } | ||
| 1000 | |||
| 1001 | /* | ||
| 1002 | * The clock flow is | ||
| 1003 | * | ||
| 1004 | * [CPG] = cout => [FSI_DIV] = audio => [FSI] => [codec] | ||
| 1005 | * | ||
| 1006 | * But, it needs to find best match of CPG and FSI_DIV | ||
| 1007 | * combination, since it is difficult to generate correct | ||
| 1008 | * frequency of audio clock from ick clock only. | ||
| 1009 | * Because ick is created from its parent clock. | ||
| 1010 | * | ||
| 1011 | * target = rate x [512/256/128/64]fs | ||
| 1012 | * cout = round(target x adjustment) | ||
| 1013 | * actual = cout / adjustment (by FSI-DIV) ~= target | ||
| 1014 | * audio = actual | ||
| 1015 | */ | ||
| 1016 | min = ~0; | ||
| 1017 | best_cout = 0; | ||
| 1018 | best_act = 0; | ||
| 1019 | for (adj = 1; adj < 0xffff; adj++) { | ||
| 1020 | |||
| 1021 | cout = target * adj; | ||
| 1022 | if (cout > 100000000) /* max clock = 100MHz */ | ||
| 1023 | break; | ||
| 1024 | |||
| 1025 | /* cout/actual audio clock */ | ||
| 1026 | cout = clk_round_rate(ick, cout); | ||
| 1027 | actual = cout / adj; | ||
| 1028 | |||
| 1029 | /* find best frequency */ | ||
| 1030 | diff = abs(actual - target); | ||
| 1031 | if (diff < min) { | ||
| 1032 | min = diff; | ||
| 1033 | best_cout = cout; | ||
| 1034 | best_act = actual; | ||
| 1035 | } | ||
| 1036 | } | ||
| 1037 | |||
| 1038 | ret = clk_set_rate(ick, best_cout); | ||
| 1039 | if (ret < 0) { | ||
| 1040 | dev_err(dev, "ick clock failed\n"); | ||
| 1041 | return -EIO; | ||
| 1042 | } | ||
| 1043 | |||
| 1044 | ret = clk_set_rate(div, clk_round_rate(div, best_act)); | ||
| 1045 | if (ret < 0) { | ||
| 1046 | dev_err(dev, "div clock failed\n"); | ||
| 1047 | return -EIO; | ||
| 1048 | } | ||
| 1049 | |||
| 1050 | dev_dbg(dev, "ick/div = %ld/%ld\n", | ||
| 1051 | clk_get_rate(ick), clk_get_rate(div)); | ||
| 1052 | |||
| 1053 | return ret; | ||
| 1054 | } | ||
| 1055 | |||
| 719 | static int fsi_set_master_clk(struct device *dev, struct fsi_priv *fsi, | 1056 | static int fsi_set_master_clk(struct device *dev, struct fsi_priv *fsi, |
| 720 | long rate, int enable) | 1057 | long rate, int enable) |
| 721 | { | 1058 | { |
| 722 | set_rate_func set_rate = fsi_get_info_set_rate(fsi); | 1059 | set_rate_func set_rate = fsi_get_info_set_rate(fsi); |
| 723 | int ret; | 1060 | int ret; |
| 724 | 1061 | ||
| 725 | if (!set_rate) | 1062 | /* |
| 726 | return 0; | 1063 | * CAUTION |
| 1064 | * | ||
| 1065 | * set_rate will be deleted | ||
| 1066 | */ | ||
| 1067 | if (!set_rate) { | ||
| 1068 | if (enable) | ||
| 1069 | return fsi_clk_enable(dev, fsi, rate); | ||
| 1070 | else | ||
| 1071 | return fsi_clk_disable(dev, fsi); | ||
| 1072 | } | ||
| 727 | 1073 | ||
| 728 | ret = set_rate(dev, rate, enable); | 1074 | ret = set_rate(dev, rate, enable); |
| 729 | if (ret < 0) /* error */ | 1075 | if (ret < 0) /* error */ |
| @@ -1355,6 +1701,7 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream, | |||
| 1355 | { | 1701 | { |
| 1356 | struct fsi_priv *fsi = fsi_get_priv(substream); | 1702 | struct fsi_priv *fsi = fsi_get_priv(substream); |
| 1357 | 1703 | ||
| 1704 | fsi_clk_invalid(fsi); | ||
| 1358 | fsi->rate = 0; | 1705 | fsi->rate = 0; |
| 1359 | 1706 | ||
| 1360 | return 0; | 1707 | return 0; |
| @@ -1365,6 +1712,7 @@ static void fsi_dai_shutdown(struct snd_pcm_substream *substream, | |||
| 1365 | { | 1712 | { |
| 1366 | struct fsi_priv *fsi = fsi_get_priv(substream); | 1713 | struct fsi_priv *fsi = fsi_get_priv(substream); |
| 1367 | 1714 | ||
| 1715 | fsi_clk_invalid(fsi); | ||
| 1368 | fsi->rate = 0; | 1716 | fsi->rate = 0; |
| 1369 | } | 1717 | } |
| 1370 | 1718 | ||
| @@ -1446,9 +1794,25 @@ static int fsi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | |||
| 1446 | return -EINVAL; | 1794 | return -EINVAL; |
| 1447 | } | 1795 | } |
| 1448 | 1796 | ||
| 1449 | if (fsi_is_clk_master(fsi) && !set_rate) { | 1797 | if (fsi_is_clk_master(fsi)) { |
| 1450 | dev_err(dai->dev, "platform doesn't have set_rate\n"); | 1798 | /* |
| 1451 | return -EINVAL; | 1799 | * CAUTION |
| 1800 | * | ||
| 1801 | * set_rate will be deleted | ||
| 1802 | */ | ||
| 1803 | if (set_rate) | ||
| 1804 | dev_warn(dai->dev, "set_rate will be removed soon\n"); | ||
| 1805 | |||
| 1806 | switch (flags & SH_FSI_CLK_MASK) { | ||
| 1807 | case SH_FSI_CLK_EXTERNAL: | ||
| 1808 | fsi_clk_init(dai->dev, fsi, 1, 1, 0, | ||
| 1809 | fsi_clk_set_rate_external); | ||
| 1810 | break; | ||
| 1811 | case SH_FSI_CLK_CPG: | ||
| 1812 | fsi_clk_init(dai->dev, fsi, 0, 1, 1, | ||
| 1813 | fsi_clk_set_rate_cpg); | ||
| 1814 | break; | ||
| 1815 | } | ||
| 1452 | } | 1816 | } |
| 1453 | 1817 | ||
| 1454 | /* set format */ | 1818 | /* set format */ |
| @@ -1472,8 +1836,10 @@ static int fsi_dai_hw_params(struct snd_pcm_substream *substream, | |||
| 1472 | { | 1836 | { |
| 1473 | struct fsi_priv *fsi = fsi_get_priv(substream); | 1837 | struct fsi_priv *fsi = fsi_get_priv(substream); |
| 1474 | 1838 | ||
| 1475 | if (fsi_is_clk_master(fsi)) | 1839 | if (fsi_is_clk_master(fsi)) { |
| 1476 | fsi->rate = params_rate(params); | 1840 | fsi->rate = params_rate(params); |
| 1841 | fsi_clk_valid(fsi, fsi->rate); | ||
| 1842 | } | ||
| 1477 | 1843 | ||
| 1478 | return 0; | 1844 | return 0; |
| 1479 | } | 1845 | } |
