diff options
-rw-r--r-- | include/sound/sh_fsi.h | 6 | ||||
-rw-r--r-- | sound/soc/sh/fsi.c | 177 |
2 files changed, 148 insertions, 35 deletions
diff --git a/include/sound/sh_fsi.h b/include/sound/sh_fsi.h index 956e30e89ea8..906010344dd7 100644 --- a/include/sound/sh_fsi.h +++ b/include/sound/sh_fsi.h | |||
@@ -21,10 +21,11 @@ | |||
21 | /* | 21 | /* |
22 | * flags format | 22 | * flags format |
23 | * | 23 | * |
24 | * 0x000000BA | 24 | * 0x00000CBA |
25 | * | 25 | * |
26 | * A: inversion | 26 | * A: inversion |
27 | * B: format mode | 27 | * B: format mode |
28 | * C: chip specific | ||
28 | */ | 29 | */ |
29 | 30 | ||
30 | /* A: clock inversion */ | 31 | /* A: clock inversion */ |
@@ -39,6 +40,9 @@ | |||
39 | #define SH_FSI_FMT_DAI (0 << 4) | 40 | #define SH_FSI_FMT_DAI (0 << 4) |
40 | #define SH_FSI_FMT_SPDIF (1 << 4) | 41 | #define SH_FSI_FMT_SPDIF (1 << 4) |
41 | 42 | ||
43 | /* C: chip specific */ | ||
44 | #define SH_FSI_OPTION_MASK 0x00000F00 | ||
45 | #define SH_FSI_ENABLE_STREAM_MODE (1 << 8) /* for 16bit data */ | ||
42 | 46 | ||
43 | /* | 47 | /* |
44 | * set_rate return value | 48 | * set_rate return value |
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index e52a95d44a6b..7cee22515d9d 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c | |||
@@ -132,6 +132,25 @@ | |||
132 | typedef int (*set_rate_func)(struct device *dev, int rate, int enable); | 132 | typedef int (*set_rate_func)(struct device *dev, int rate, int enable); |
133 | 133 | ||
134 | /* | 134 | /* |
135 | * bus options | ||
136 | * | ||
137 | * 0x000000BA | ||
138 | * | ||
139 | * A : sample widtht 16bit setting | ||
140 | * B : sample widtht 24bit setting | ||
141 | */ | ||
142 | |||
143 | #define SHIFT_16DATA 0 | ||
144 | #define SHIFT_24DATA 4 | ||
145 | |||
146 | #define PACKAGE_24BITBUS_BACK 0 | ||
147 | #define PACKAGE_24BITBUS_FRONT 1 | ||
148 | #define PACKAGE_16BITBUS_STREAM 2 | ||
149 | |||
150 | #define BUSOP_SET(s, a) ((a) << SHIFT_ ## s ## DATA) | ||
151 | #define BUSOP_GET(s, a) (((a) >> SHIFT_ ## s ## DATA) & 0xF) | ||
152 | |||
153 | /* | ||
135 | * FSI driver use below type name for variable | 154 | * FSI driver use below type name for variable |
136 | * | 155 | * |
137 | * xxx_num : number of data | 156 | * xxx_num : number of data |
@@ -189,6 +208,11 @@ struct fsi_stream { | |||
189 | int oerr_num; | 208 | int oerr_num; |
190 | 209 | ||
191 | /* | 210 | /* |
211 | * bus options | ||
212 | */ | ||
213 | u32 bus_option; | ||
214 | |||
215 | /* | ||
192 | * thse are initialized by fsi_handler_init() | 216 | * thse are initialized by fsi_handler_init() |
193 | */ | 217 | */ |
194 | struct fsi_stream_handler *handler; | 218 | struct fsi_stream_handler *handler; |
@@ -498,6 +522,7 @@ static void fsi_stream_init(struct fsi_priv *fsi, | |||
498 | io->period_samples = fsi_frame2sample(fsi, runtime->period_size); | 522 | io->period_samples = fsi_frame2sample(fsi, runtime->period_size); |
499 | io->period_pos = 0; | 523 | io->period_pos = 0; |
500 | io->sample_width = samples_to_bytes(runtime, 1); | 524 | io->sample_width = samples_to_bytes(runtime, 1); |
525 | io->bus_option = 0; | ||
501 | io->oerr_num = -1; /* ignore 1st err */ | 526 | io->oerr_num = -1; /* ignore 1st err */ |
502 | io->uerr_num = -1; /* ignore 1st err */ | 527 | io->uerr_num = -1; /* ignore 1st err */ |
503 | fsi_stream_handler_call(io, init, fsi, io); | 528 | fsi_stream_handler_call(io, init, fsi, io); |
@@ -525,6 +550,7 @@ static void fsi_stream_quit(struct fsi_priv *fsi, struct fsi_stream *io) | |||
525 | io->period_samples = 0; | 550 | io->period_samples = 0; |
526 | io->period_pos = 0; | 551 | io->period_pos = 0; |
527 | io->sample_width = 0; | 552 | io->sample_width = 0; |
553 | io->bus_option = 0; | ||
528 | io->oerr_num = 0; | 554 | io->oerr_num = 0; |
529 | io->uerr_num = 0; | 555 | io->uerr_num = 0; |
530 | spin_unlock_irqrestore(&master->lock, flags); | 556 | spin_unlock_irqrestore(&master->lock, flags); |
@@ -584,6 +610,53 @@ static int fsi_stream_remove(struct fsi_priv *fsi) | |||
584 | } | 610 | } |
585 | 611 | ||
586 | /* | 612 | /* |
613 | * format/bus/dma setting | ||
614 | */ | ||
615 | static void fsi_format_bus_setup(struct fsi_priv *fsi, struct fsi_stream *io, | ||
616 | u32 bus, struct device *dev) | ||
617 | { | ||
618 | struct fsi_master *master = fsi_get_master(fsi); | ||
619 | int is_play = fsi_stream_is_play(fsi, io); | ||
620 | u32 fmt = fsi->fmt; | ||
621 | |||
622 | if (fsi_version(master) >= 2) { | ||
623 | u32 dma = 0; | ||
624 | |||
625 | /* | ||
626 | * FSI2 needs DMA/Bus setting | ||
627 | */ | ||
628 | switch (bus) { | ||
629 | case PACKAGE_24BITBUS_FRONT: | ||
630 | fmt |= CR_BWS_24; | ||
631 | dma |= VDMD_FRONT; | ||
632 | dev_dbg(dev, "24bit bus / package in front\n"); | ||
633 | break; | ||
634 | case PACKAGE_16BITBUS_STREAM: | ||
635 | fmt |= CR_BWS_16; | ||
636 | dma |= VDMD_STREAM; | ||
637 | dev_dbg(dev, "16bit bus / stream mode\n"); | ||
638 | break; | ||
639 | case PACKAGE_24BITBUS_BACK: | ||
640 | default: | ||
641 | fmt |= CR_BWS_24; | ||
642 | dma |= VDMD_BACK; | ||
643 | dev_dbg(dev, "24bit bus / package in back\n"); | ||
644 | break; | ||
645 | } | ||
646 | |||
647 | if (is_play) | ||
648 | fsi_reg_write(fsi, OUT_DMAC, dma); | ||
649 | else | ||
650 | fsi_reg_write(fsi, IN_DMAC, dma); | ||
651 | } | ||
652 | |||
653 | if (is_play) | ||
654 | fsi_reg_write(fsi, DO_FMT, fmt); | ||
655 | else | ||
656 | fsi_reg_write(fsi, DI_FMT, fmt); | ||
657 | } | ||
658 | |||
659 | /* | ||
587 | * irq function | 660 | * irq function |
588 | */ | 661 | */ |
589 | 662 | ||
@@ -718,11 +791,26 @@ static int fsi_set_master_clk(struct device *dev, struct fsi_priv *fsi, | |||
718 | */ | 791 | */ |
719 | static void fsi_pio_push16(struct fsi_priv *fsi, u8 *_buf, int samples) | 792 | static void fsi_pio_push16(struct fsi_priv *fsi, u8 *_buf, int samples) |
720 | { | 793 | { |
721 | u16 *buf = (u16 *)_buf; | 794 | u32 enable_stream = fsi_get_info_flags(fsi) & SH_FSI_ENABLE_STREAM_MODE; |
722 | int i; | 795 | int i; |
723 | 796 | ||
724 | for (i = 0; i < samples; i++) | 797 | if (enable_stream) { |
725 | fsi_reg_write(fsi, DODT, ((u32)*(buf + i) << 8)); | 798 | /* |
799 | * stream mode | ||
800 | * see | ||
801 | * fsi_pio_push_init() | ||
802 | */ | ||
803 | u32 *buf = (u32 *)_buf; | ||
804 | |||
805 | for (i = 0; i < samples / 2; i++) | ||
806 | fsi_reg_write(fsi, DODT, buf[i]); | ||
807 | } else { | ||
808 | /* normal mode */ | ||
809 | u16 *buf = (u16 *)_buf; | ||
810 | |||
811 | for (i = 0; i < samples; i++) | ||
812 | fsi_reg_write(fsi, DODT, ((u32)*(buf + i) << 8)); | ||
813 | } | ||
726 | } | 814 | } |
727 | 815 | ||
728 | static void fsi_pio_pop16(struct fsi_priv *fsi, u8 *_buf, int samples) | 816 | static void fsi_pio_pop16(struct fsi_priv *fsi, u8 *_buf, int samples) |
@@ -862,12 +950,44 @@ static void fsi_pio_start_stop(struct fsi_priv *fsi, struct fsi_stream *io, | |||
862 | fsi_master_mask_set(master, CLK_RST, clk, (enable) ? clk : 0); | 950 | fsi_master_mask_set(master, CLK_RST, clk, (enable) ? clk : 0); |
863 | } | 951 | } |
864 | 952 | ||
953 | static int fsi_pio_push_init(struct fsi_priv *fsi, struct fsi_stream *io) | ||
954 | { | ||
955 | u32 enable_stream = fsi_get_info_flags(fsi) & SH_FSI_ENABLE_STREAM_MODE; | ||
956 | |||
957 | /* | ||
958 | * we can use 16bit stream mode | ||
959 | * when "playback" and "16bit data" | ||
960 | * and platform allows "stream mode" | ||
961 | * see | ||
962 | * fsi_pio_push16() | ||
963 | */ | ||
964 | if (enable_stream) | ||
965 | io->bus_option = BUSOP_SET(24, PACKAGE_24BITBUS_BACK) | | ||
966 | BUSOP_SET(16, PACKAGE_16BITBUS_STREAM); | ||
967 | else | ||
968 | io->bus_option = BUSOP_SET(24, PACKAGE_24BITBUS_BACK) | | ||
969 | BUSOP_SET(16, PACKAGE_24BITBUS_BACK); | ||
970 | return 0; | ||
971 | } | ||
972 | |||
973 | static int fsi_pio_pop_init(struct fsi_priv *fsi, struct fsi_stream *io) | ||
974 | { | ||
975 | /* | ||
976 | * always 24bit bus, package back when "capture" | ||
977 | */ | ||
978 | io->bus_option = BUSOP_SET(24, PACKAGE_24BITBUS_BACK) | | ||
979 | BUSOP_SET(16, PACKAGE_24BITBUS_BACK); | ||
980 | return 0; | ||
981 | } | ||
982 | |||
865 | static struct fsi_stream_handler fsi_pio_push_handler = { | 983 | static struct fsi_stream_handler fsi_pio_push_handler = { |
984 | .init = fsi_pio_push_init, | ||
866 | .transfer = fsi_pio_push, | 985 | .transfer = fsi_pio_push, |
867 | .start_stop = fsi_pio_start_stop, | 986 | .start_stop = fsi_pio_start_stop, |
868 | }; | 987 | }; |
869 | 988 | ||
870 | static struct fsi_stream_handler fsi_pio_pop_handler = { | 989 | static struct fsi_stream_handler fsi_pio_pop_handler = { |
990 | .init = fsi_pio_pop_init, | ||
871 | .transfer = fsi_pio_pop, | 991 | .transfer = fsi_pio_pop, |
872 | .start_stop = fsi_pio_start_stop, | 992 | .start_stop = fsi_pio_start_stop, |
873 | }; | 993 | }; |
@@ -909,6 +1029,13 @@ static int fsi_dma_init(struct fsi_priv *fsi, struct fsi_stream *io) | |||
909 | enum dma_data_direction dir = fsi_stream_is_play(fsi, io) ? | 1029 | enum dma_data_direction dir = fsi_stream_is_play(fsi, io) ? |
910 | DMA_TO_DEVICE : DMA_FROM_DEVICE; | 1030 | DMA_TO_DEVICE : DMA_FROM_DEVICE; |
911 | 1031 | ||
1032 | /* | ||
1033 | * 24bit data : 24bit bus / package in back | ||
1034 | * 16bit data : 16bit bus / stream mode | ||
1035 | */ | ||
1036 | io->bus_option = BUSOP_SET(24, PACKAGE_24BITBUS_BACK) | | ||
1037 | BUSOP_SET(16, PACKAGE_16BITBUS_STREAM); | ||
1038 | |||
912 | io->dma = dma_map_single(dai->dev, runtime->dma_area, | 1039 | io->dma = dma_map_single(dai->dev, runtime->dma_area, |
913 | snd_pcm_lib_buffer_bytes(io->substream), dir); | 1040 | snd_pcm_lib_buffer_bytes(io->substream), dir); |
914 | return 0; | 1041 | return 0; |
@@ -1045,25 +1172,9 @@ static int fsi_dma_transfer(struct fsi_priv *fsi, struct fsi_stream *io) | |||
1045 | static void fsi_dma_push_start_stop(struct fsi_priv *fsi, struct fsi_stream *io, | 1172 | static void fsi_dma_push_start_stop(struct fsi_priv *fsi, struct fsi_stream *io, |
1046 | int start) | 1173 | int start) |
1047 | { | 1174 | { |
1048 | u32 bws; | 1175 | u32 enable = start ? DMA_ON : 0; |
1049 | u32 dma; | ||
1050 | 1176 | ||
1051 | switch (io->sample_width * start) { | 1177 | fsi_reg_mask_set(fsi, OUT_DMAC, DMA_ON, enable); |
1052 | case 2: | ||
1053 | bws = CR_BWS_16; | ||
1054 | dma = VDMD_STREAM | DMA_ON; | ||
1055 | break; | ||
1056 | case 4: | ||
1057 | bws = CR_BWS_24; | ||
1058 | dma = VDMD_BACK | DMA_ON; | ||
1059 | break; | ||
1060 | default: | ||
1061 | bws = 0; | ||
1062 | dma = 0; | ||
1063 | } | ||
1064 | |||
1065 | fsi_reg_mask_set(fsi, DO_FMT, CR_BWS_MASK, bws); | ||
1066 | fsi_reg_write(fsi, OUT_DMAC, dma); | ||
1067 | } | 1178 | } |
1068 | 1179 | ||
1069 | static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io) | 1180 | static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io) |
@@ -1166,7 +1277,6 @@ static int fsi_hw_startup(struct fsi_priv *fsi, | |||
1166 | struct fsi_stream *io, | 1277 | struct fsi_stream *io, |
1167 | struct device *dev) | 1278 | struct device *dev) |
1168 | { | 1279 | { |
1169 | struct fsi_master *master = fsi_get_master(fsi); | ||
1170 | u32 flags = fsi_get_info_flags(fsi); | 1280 | u32 flags = fsi_get_info_flags(fsi); |
1171 | u32 data = 0; | 1281 | u32 data = 0; |
1172 | 1282 | ||
@@ -1189,10 +1299,6 @@ static int fsi_hw_startup(struct fsi_priv *fsi, | |||
1189 | 1299 | ||
1190 | fsi_reg_write(fsi, CKG2, data); | 1300 | fsi_reg_write(fsi, CKG2, data); |
1191 | 1301 | ||
1192 | /* set format */ | ||
1193 | fsi_reg_write(fsi, DO_FMT, fsi->fmt); | ||
1194 | fsi_reg_write(fsi, DI_FMT, fsi->fmt); | ||
1195 | |||
1196 | /* spdif ? */ | 1302 | /* spdif ? */ |
1197 | if (fsi_is_spdif(fsi)) { | 1303 | if (fsi_is_spdif(fsi)) { |
1198 | fsi_spdif_clk_ctrl(fsi, 1); | 1304 | fsi_spdif_clk_ctrl(fsi, 1); |
@@ -1200,15 +1306,18 @@ static int fsi_hw_startup(struct fsi_priv *fsi, | |||
1200 | } | 1306 | } |
1201 | 1307 | ||
1202 | /* | 1308 | /* |
1203 | * FIXME | 1309 | * get bus settings |
1204 | * | ||
1205 | * FSI driver assumed that data package is in-back. | ||
1206 | * FSI2 chip can select it. | ||
1207 | */ | 1310 | */ |
1208 | if (fsi_version(master) >= 2) { | 1311 | data = 0; |
1209 | fsi_reg_write(fsi, OUT_DMAC, VDMD_BACK); | 1312 | switch (io->sample_width) { |
1210 | fsi_reg_write(fsi, IN_DMAC, VDMD_BACK); | 1313 | case 2: |
1314 | data = BUSOP_GET(16, io->bus_option); | ||
1315 | break; | ||
1316 | case 4: | ||
1317 | data = BUSOP_GET(24, io->bus_option); | ||
1318 | break; | ||
1211 | } | 1319 | } |
1320 | fsi_format_bus_setup(fsi, io, data, dev); | ||
1212 | 1321 | ||
1213 | /* irq clear */ | 1322 | /* irq clear */ |
1214 | fsi_irq_disable(fsi, io); | 1323 | fsi_irq_disable(fsi, io); |
@@ -1295,7 +1404,7 @@ static int fsi_set_fmt_spdif(struct fsi_priv *fsi) | |||
1295 | if (fsi_version(master) < 2) | 1404 | if (fsi_version(master) < 2) |
1296 | return -EINVAL; | 1405 | return -EINVAL; |
1297 | 1406 | ||
1298 | fsi->fmt = CR_BWS_16 | CR_DTMD_SPDIF_PCM | CR_PCM; | 1407 | fsi->fmt = CR_DTMD_SPDIF_PCM | CR_PCM; |
1299 | fsi->chan_num = 2; | 1408 | fsi->chan_num = 2; |
1300 | fsi->spdif = 1; | 1409 | fsi->spdif = 1; |
1301 | 1410 | ||