Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ASoC: sh: fsi: modify selection method of I2S/PCM/SPDIF format

Current format selection of FSI-codecs depended on platform information for FSI,
and chip default settings for codecs. It is not understandable/formal method.
This patch modify FSI and FSI-codecs to use snd_soc_dai_set_fmt.

But FSI can use I2S/PCM and SPDIF format today.
It can be selected to I2S/PCM by snd_soc_dai_set_fmt, but can not select SPDIF.
So, this patch change FSI platform information to have DAI/SPDIF mode.

If platform selects DAI mode (default),
FSI-codecs can select I2S/PCM by snd_soc_dai_set_fmt,
and if it is SPDIF mode, FSI become SPDIF format.

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Acked-by: Paul Mundt <lethal@linux-sh.org>
Acked-by: Liam Girdwood <lrg@slimlogic.co.uk>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>

authored by

Kuninori Morimoto and committed by
Mark Brown
f17c13ca d7c5762b

+83 -125
-8
arch/arm/mach-shmobile/board-ag5evm.c
··· 118 118 }; 119 119 120 120 /* FSI A */ 121 - static struct sh_fsi_platform_info fsi_info = { 122 - .porta_flags = SH_FSI_OFMT(I2S) | 123 - SH_FSI_IFMT(I2S), 124 - }; 125 - 126 121 static struct resource fsi_resources[] = { 127 122 [0] = { 128 123 .name = "FSI", ··· 136 141 .id = -1, 137 142 .num_resources = ARRAY_SIZE(fsi_resources), 138 143 .resource = fsi_resources, 139 - .dev = { 140 - .platform_data = &fsi_info, 141 - }, 142 144 }; 143 145 144 146 static struct resource sh_mmcif_resources[] = {
+2 -4
arch/arm/mach-shmobile/board-ap4evb.c
··· 673 673 } 674 674 675 675 static struct sh_fsi_platform_info fsi_info = { 676 - .porta_flags = SH_FSI_BRS_INV | 677 - SH_FSI_OFMT(PCM) | 678 - SH_FSI_IFMT(PCM), 676 + .porta_flags = SH_FSI_BRS_INV, 679 677 680 678 .portb_flags = SH_FSI_BRS_INV | 681 679 SH_FSI_BRM_INV | 682 680 SH_FSI_LRS_INV | 683 - SH_FSI_OFMT(SPDIF), 681 + SH_FSI_FMT_SPDIF, 684 682 .set_rate = fsi_set_rate, 685 683 }; 686 684
+2 -4
arch/arm/mach-shmobile/board-mackerel.c
··· 614 614 } 615 615 616 616 static struct sh_fsi_platform_info fsi_info = { 617 - .porta_flags = SH_FSI_BRS_INV | 618 - SH_FSI_OFMT(PCM) | 619 - SH_FSI_IFMT(PCM), 617 + .porta_flags = SH_FSI_BRS_INV, 620 618 621 619 .portb_flags = SH_FSI_BRS_INV | 622 620 SH_FSI_BRM_INV | 623 621 SH_FSI_LRS_INV | 624 - SH_FSI_OFMT(SPDIF), 622 + SH_FSI_FMT_SPDIF, 625 623 626 624 .set_rate = fsi_set_rate, 627 625 };
+1 -3
arch/sh/boards/mach-ecovec24/setup.c
··· 723 723 724 724 /* FSI */ 725 725 static struct sh_fsi_platform_info fsi_info = { 726 - .portb_flags = SH_FSI_BRS_INV | 727 - SH_FSI_OFMT(I2S) | 728 - SH_FSI_IFMT(I2S), 726 + .portb_flags = SH_FSI_BRS_INV, 729 727 }; 730 728 731 729 static struct resource fsi_resources[] = {
+1 -3
arch/sh/boards/mach-se/7724/setup.c
··· 286 286 /* FSI */ 287 287 /* change J20, J21, J22 pin to 1-2 connection to use slave mode */ 288 288 static struct sh_fsi_platform_info fsi_info = { 289 - .porta_flags = SH_FSI_BRS_INV | 290 - SH_FSI_OFMT(PCM) | 291 - SH_FSI_IFMT(PCM), 289 + .porta_flags = SH_FSI_BRS_INV, 292 290 }; 293 291 294 292 static struct resource fsi_resources[] = {
+18 -50
include/sound/sh_fsi.h
··· 15 15 #define FSI_PORT_A 0 16 16 #define FSI_PORT_B 1 17 17 18 - /* flags format 19 - 20 - * 0xABC0EEFF 21 - * 22 - * A: channel size for TDM (input) 23 - * B: channel size for TDM (ooutput) 24 - * C: inversion 25 - * E: input format 26 - * F: output format 27 - */ 28 - 29 18 #include <linux/clk.h> 30 19 #include <sound/soc.h> 31 20 32 - /* TDM channel */ 33 - #define SH_FSI_SET_CH_I(x) ((x & 0xF) << 28) 34 - #define SH_FSI_SET_CH_O(x) ((x & 0xF) << 24) 21 + /* 22 + * flags format 23 + * 24 + * 0x000000BA 25 + * 26 + * A: inversion 27 + * B: format mode 28 + */ 35 29 36 - #define SH_FSI_CH_IMASK 0xF0000000 37 - #define SH_FSI_CH_OMASK 0x0F000000 38 - #define SH_FSI_GET_CH_I(x) ((x & SH_FSI_CH_IMASK) >> 28) 39 - #define SH_FSI_GET_CH_O(x) ((x & SH_FSI_CH_OMASK) >> 24) 30 + /* A: clock inversion */ 31 + #define SH_FSI_INVERSION_MASK 0x0000000F 32 + #define SH_FSI_LRM_INV (1 << 0) 33 + #define SH_FSI_BRM_INV (1 << 1) 34 + #define SH_FSI_LRS_INV (1 << 2) 35 + #define SH_FSI_BRS_INV (1 << 3) 40 36 41 - /* clock inversion */ 42 - #define SH_FSI_INVERSION_MASK 0x00F00000 43 - #define SH_FSI_LRM_INV (1 << 20) 44 - #define SH_FSI_BRM_INV (1 << 21) 45 - #define SH_FSI_LRS_INV (1 << 22) 46 - #define SH_FSI_BRS_INV (1 << 23) 47 - 48 - /* DI format */ 49 - #define SH_FSI_FMT_MASK 0x000000FF 50 - #define SH_FSI_IFMT(x) (((SH_FSI_FMT_ ## x) & SH_FSI_FMT_MASK) << 8) 51 - #define SH_FSI_OFMT(x) (((SH_FSI_FMT_ ## x) & SH_FSI_FMT_MASK) << 0) 52 - #define SH_FSI_GET_IFMT(x) ((x >> 8) & SH_FSI_FMT_MASK) 53 - #define SH_FSI_GET_OFMT(x) ((x >> 0) & SH_FSI_FMT_MASK) 54 - 55 - #define SH_FSI_FMT_MONO 0 56 - #define SH_FSI_FMT_MONO_DELAY 1 57 - #define SH_FSI_FMT_PCM 2 58 - #define SH_FSI_FMT_I2S 3 59 - #define SH_FSI_FMT_TDM 4 60 - #define SH_FSI_FMT_TDM_DELAY 5 61 - #define SH_FSI_FMT_SPDIF 6 62 - 63 - 64 - #define SH_FSI_IFMT_TDM_CH(x) \ 65 - (SH_FSI_IFMT(TDM) | SH_FSI_SET_CH_I(x)) 66 - #define SH_FSI_IFMT_TDM_DELAY_CH(x) \ 67 - (SH_FSI_IFMT(TDM_DELAY) | SH_FSI_SET_CH_I(x)) 68 - 69 - #define SH_FSI_OFMT_TDM_CH(x) \ 70 - (SH_FSI_OFMT(TDM) | SH_FSI_SET_CH_O(x)) 71 - #define SH_FSI_OFMT_TDM_DELAY_CH(x) \ 72 - (SH_FSI_OFMT(TDM_DELAY) | SH_FSI_SET_CH_O(x)) 37 + /* B: format mode */ 38 + #define SH_FSI_FMT_MASK 0x000000F0 39 + #define SH_FSI_FMT_DAI (0 << 4) 40 + #define SH_FSI_FMT_SPDIF (1 << 4) 73 41 74 42 75 43 /*
+2 -1
sound/soc/sh/fsi-ak4642.c
··· 36 36 if (ret < 0) 37 37 return ret; 38 38 39 - ret = snd_soc_dai_set_fmt(cpu, SND_SOC_DAIFMT_CBS_CFS); 39 + ret = snd_soc_dai_set_fmt(cpu, SND_SOC_DAIFMT_LEFT_J | 40 + SND_SOC_DAIFMT_CBS_CFS); 40 41 41 42 return ret; 42 43 }
+2 -1
sound/soc/sh/fsi-da7210.c
··· 25 25 if (ret < 0) 26 26 return ret; 27 27 28 - ret = snd_soc_dai_set_fmt(cpu, SND_SOC_DAIFMT_CBS_CFS); 28 + ret = snd_soc_dai_set_fmt(cpu, SND_SOC_DAIFMT_I2S | 29 + SND_SOC_DAIFMT_CBS_CFS); 29 30 30 31 return ret; 31 32 }
+55 -51
sound/soc/sh/fsi.c
··· 757 757 struct snd_soc_dai *dai) 758 758 { 759 759 struct fsi_priv *fsi = fsi_get_priv(substream); 760 - struct fsi_master *master = fsi_get_master(fsi); 761 760 u32 flags = fsi_get_info_flags(fsi); 762 - u32 fmt; 763 761 u32 data; 764 762 int is_play = fsi_is_play(substream); 765 763 ··· 776 778 data |= 1 << 0; 777 779 778 780 fsi_reg_write(fsi, CKG2, data); 779 - 780 - /* do fmt, di fmt */ 781 - data = 0; 782 - fmt = is_play ? SH_FSI_GET_OFMT(flags) : SH_FSI_GET_IFMT(flags); 783 - switch (fmt) { 784 - case SH_FSI_FMT_MONO: 785 - data = CR_MONO; 786 - fsi->chan_num = 1; 787 - break; 788 - case SH_FSI_FMT_MONO_DELAY: 789 - data = CR_MONO_D; 790 - fsi->chan_num = 1; 791 - break; 792 - case SH_FSI_FMT_PCM: 793 - data = CR_PCM; 794 - fsi->chan_num = 2; 795 - break; 796 - case SH_FSI_FMT_I2S: 797 - data = CR_I2S; 798 - fsi->chan_num = 2; 799 - break; 800 - case SH_FSI_FMT_TDM: 801 - fsi->chan_num = is_play ? 802 - SH_FSI_GET_CH_O(flags) : SH_FSI_GET_CH_I(flags); 803 - data = CR_TDM | (fsi->chan_num - 1); 804 - break; 805 - case SH_FSI_FMT_TDM_DELAY: 806 - fsi->chan_num = is_play ? 807 - SH_FSI_GET_CH_O(flags) : SH_FSI_GET_CH_I(flags); 808 - data = CR_TDM_D | (fsi->chan_num - 1); 809 - break; 810 - case SH_FSI_FMT_SPDIF: 811 - if (master->core->ver < 2) { 812 - dev_err(dai->dev, "This FSI can not use SPDIF\n"); 813 - return -EINVAL; 814 - } 815 - data = CR_BWS_16 | CR_DTMD_SPDIF_PCM | CR_PCM; 816 - fsi->chan_num = 2; 817 - fsi_spdif_clk_ctrl(fsi, 1); 818 - fsi_reg_mask_set(fsi, OUT_SEL, DMMD, DMMD); 819 - break; 820 - default: 821 - dev_err(dai->dev, "unknown format.\n"); 822 - return -EINVAL; 823 - } 824 - is_play ? 825 - fsi_reg_write(fsi, DO_FMT, data) : 826 - fsi_reg_write(fsi, DI_FMT, data); 827 781 828 782 /* irq clear */ 829 783 fsi_irq_disable(fsi, is_play); ··· 831 881 return ret; 832 882 } 833 883 884 + static int fsi_set_fmt_dai(struct fsi_priv *fsi, unsigned int fmt) 885 + { 886 + u32 data = 0; 887 + 888 + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 889 + case SND_SOC_DAIFMT_I2S: 890 + data = CR_I2S; 891 + fsi->chan_num = 2; 892 + break; 893 + case SND_SOC_DAIFMT_LEFT_J: 894 + data = CR_PCM; 895 + fsi->chan_num = 2; 896 + break; 897 + default: 898 + return -EINVAL; 899 + } 900 + 901 + fsi_reg_write(fsi, DO_FMT, data); 902 + fsi_reg_write(fsi, DI_FMT, data); 903 + 904 + return 0; 905 + } 906 + 907 + static int fsi_set_fmt_spdif(struct fsi_priv *fsi) 908 + { 909 + struct fsi_master *master = fsi_get_master(fsi); 910 + u32 data = 0; 911 + 912 + if (master->core->ver < 2) 913 + return -EINVAL; 914 + 915 + data = CR_BWS_16 | CR_DTMD_SPDIF_PCM | CR_PCM; 916 + fsi->chan_num = 2; 917 + fsi_spdif_clk_ctrl(fsi, 1); 918 + fsi_reg_mask_set(fsi, OUT_SEL, DMMD, DMMD); 919 + 920 + fsi_reg_write(fsi, DO_FMT, data); 921 + fsi_reg_write(fsi, DI_FMT, data); 922 + 923 + return 0; 924 + } 925 + 834 926 static int fsi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) 835 927 { 836 928 struct fsi_priv *fsi = fsi_get_priv_frm_dai(dai); 929 + u32 flags = fsi_get_info_flags(fsi); 837 930 u32 data = 0; 838 931 int ret; 839 932 ··· 894 901 goto set_fmt_exit; 895 902 } 896 903 fsi_reg_mask_set(fsi, CKG1, (DIMD | DOMD), data); 897 - ret = 0; 904 + 905 + /* set format */ 906 + switch (flags & SH_FSI_FMT_MASK) { 907 + case SH_FSI_FMT_DAI: 908 + ret = fsi_set_fmt_dai(fsi, fmt & SND_SOC_DAIFMT_FORMAT_MASK); 909 + break; 910 + case SH_FSI_FMT_SPDIF: 911 + ret = fsi_set_fmt_spdif(fsi); 912 + break; 913 + default: 914 + ret = -EINVAL; 915 + } 898 916 899 917 set_fmt_exit: 900 918 pm_runtime_put_sync(dai->dev);