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