summaryrefslogtreecommitdiff
path: root/sound/soc/sh
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/sh')
-rw-r--r--sound/soc/sh/Kconfig24
-rw-r--r--sound/soc/sh/Makefile6
-rw-r--r--sound/soc/sh/fsi-ak4642.c108
-rw-r--r--sound/soc/sh/fsi-da7210.c81
-rw-r--r--sound/soc/sh/fsi-hdmi.c118
-rw-r--r--sound/soc/sh/fsi.c247
6 files changed, 174 insertions, 410 deletions
diff --git a/sound/soc/sh/Kconfig b/sound/soc/sh/Kconfig
index d8e06a607a22..6bcb1164d599 100644
--- a/sound/soc/sh/Kconfig
+++ b/sound/soc/sh/Kconfig
@@ -22,6 +22,7 @@ config SND_SOC_SH4_SSI
config SND_SOC_SH4_FSI
tristate "SH4 FSI support"
+ select SND_SIMPLE_CARD
help
This option enables FSI sound support
@@ -46,29 +47,6 @@ config SND_SH7760_AC97
This option enables generic sound support for the first
AC97 unit of the SH7760.
-config SND_FSI_AK4642
- tristate "FSI-AK4642 sound support"
- depends on SND_SOC_SH4_FSI && I2C
- select SND_SOC_AK4642
- help
- This option enables generic sound support for the
- FSI - AK4642 unit
-
-config SND_FSI_DA7210
- tristate "FSI-DA7210 sound support"
- depends on SND_SOC_SH4_FSI && I2C
- select SND_SOC_DA7210
- help
- This option enables generic sound support for the
- FSI - DA7210 unit
-
-config SND_FSI_HDMI
- tristate "FSI-HDMI sound support"
- depends on SND_SOC_SH4_FSI && FB_SH_MOBILE_HDMI
- help
- This option enables generic sound support for the
- FSI - HDMI unit
-
config SND_SIU_MIGOR
tristate "SIU sound support on Migo-R"
depends on SH_MIGOR
diff --git a/sound/soc/sh/Makefile b/sound/soc/sh/Makefile
index 94476d4c0fd5..849b387d17d9 100644
--- a/sound/soc/sh/Makefile
+++ b/sound/soc/sh/Makefile
@@ -14,13 +14,7 @@ obj-$(CONFIG_SND_SOC_SH4_SIU) += snd-soc-siu.o
## boards
snd-soc-sh7760-ac97-objs := sh7760-ac97.o
-snd-soc-fsi-ak4642-objs := fsi-ak4642.o
-snd-soc-fsi-da7210-objs := fsi-da7210.o
-snd-soc-fsi-hdmi-objs := fsi-hdmi.o
snd-soc-migor-objs := migor.o
obj-$(CONFIG_SND_SH7760_AC97) += snd-soc-sh7760-ac97.o
-obj-$(CONFIG_SND_FSI_AK4642) += snd-soc-fsi-ak4642.o
-obj-$(CONFIG_SND_FSI_DA7210) += snd-soc-fsi-da7210.o
-obj-$(CONFIG_SND_FSI_HDMI) += snd-soc-fsi-hdmi.o
obj-$(CONFIG_SND_SIU_MIGOR) += snd-soc-migor.o
diff --git a/sound/soc/sh/fsi-ak4642.c b/sound/soc/sh/fsi-ak4642.c
deleted file mode 100644
index 97f540aabbdd..000000000000
--- a/sound/soc/sh/fsi-ak4642.c
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * FSI-AK464x sound support for ms7724se
- *
- * Copyright (C) 2009 Renesas Solutions Corp.
- * Kuninori Morimoto <morimoto.kuninori@renesas.com>
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-
-#include <linux/platform_device.h>
-#include <linux/module.h>
-#include <sound/sh_fsi.h>
-
-struct fsi_ak4642_data {
- const char *name;
- const char *card;
- const char *cpu_dai;
- const char *codec;
- const char *platform;
- int id;
-};
-
-static int fsi_ak4642_dai_init(struct snd_soc_pcm_runtime *rtd)
-{
- struct snd_soc_dai *codec = rtd->codec_dai;
- struct snd_soc_dai *cpu = rtd->cpu_dai;
- int ret;
-
- ret = snd_soc_dai_set_fmt(codec, SND_SOC_DAIFMT_LEFT_J |
- SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0)
- return ret;
-
- ret = snd_soc_dai_set_sysclk(codec, 0, 11289600, 0);
- if (ret < 0)
- return ret;
-
- ret = snd_soc_dai_set_fmt(cpu, SND_SOC_DAIFMT_LEFT_J |
- SND_SOC_DAIFMT_CBS_CFS);
-
- return ret;
-}
-
-static struct snd_soc_dai_link fsi_dai_link = {
- .codec_dai_name = "ak4642-hifi",
- .init = fsi_ak4642_dai_init,
-};
-
-static struct snd_soc_card fsi_soc_card = {
- .owner = THIS_MODULE,
- .dai_link = &fsi_dai_link,
- .num_links = 1,
-};
-
-static struct platform_device *fsi_snd_device;
-
-static int fsi_ak4642_probe(struct platform_device *pdev)
-{
- int ret = -ENOMEM;
- struct fsi_ak4642_info *pinfo = pdev->dev.platform_data;
-
- if (!pinfo) {
- dev_err(&pdev->dev, "no info for fsi ak4642\n");
- goto out;
- }
-
- fsi_snd_device = platform_device_alloc("soc-audio", pinfo->id);
- if (!fsi_snd_device)
- goto out;
-
- fsi_dai_link.name = pinfo->name;
- fsi_dai_link.stream_name = pinfo->name;
- fsi_dai_link.cpu_dai_name = pinfo->cpu_dai;
- fsi_dai_link.platform_name = pinfo->platform;
- fsi_dai_link.codec_name = pinfo->codec;
- fsi_soc_card.name = pinfo->card;
-
- platform_set_drvdata(fsi_snd_device, &fsi_soc_card);
- ret = platform_device_add(fsi_snd_device);
-
- if (ret)
- platform_device_put(fsi_snd_device);
-
-out:
- return ret;
-}
-
-static int fsi_ak4642_remove(struct platform_device *pdev)
-{
- platform_device_unregister(fsi_snd_device);
- return 0;
-}
-
-static struct platform_driver fsi_ak4642 = {
- .driver = {
- .name = "fsi-ak4642-audio",
- },
- .probe = fsi_ak4642_probe,
- .remove = fsi_ak4642_remove,
-};
-
-module_platform_driver(fsi_ak4642);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Generic SH4 FSI-AK4642 sound card");
-MODULE_AUTHOR("Kuninori Morimoto <morimoto.kuninori@renesas.com>");
diff --git a/sound/soc/sh/fsi-da7210.c b/sound/soc/sh/fsi-da7210.c
deleted file mode 100644
index 1dd3354c7411..000000000000
--- a/sound/soc/sh/fsi-da7210.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * fsi-da7210.c
- *
- * Copyright (C) 2009 Renesas Solutions Corp.
- * Kuninori Morimoto <morimoto.kuninori@renesas.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-
-#include <linux/platform_device.h>
-#include <linux/module.h>
-#include <sound/sh_fsi.h>
-
-static int fsi_da7210_init(struct snd_soc_pcm_runtime *rtd)
-{
- struct snd_soc_dai *codec = rtd->codec_dai;
- struct snd_soc_dai *cpu = rtd->cpu_dai;
- int ret;
-
- ret = snd_soc_dai_set_fmt(codec,
- SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0)
- return ret;
-
- ret = snd_soc_dai_set_fmt(cpu, SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_CBS_CFS);
-
- return ret;
-}
-
-static struct snd_soc_dai_link fsi_da7210_dai = {
- .name = "DA7210",
- .stream_name = "DA7210",
- .cpu_dai_name = "fsib-dai", /* FSI B */
- .codec_dai_name = "da7210-hifi",
- .platform_name = "sh_fsi.0",
- .codec_name = "da7210-codec.0-001a",
- .init = fsi_da7210_init,
-};
-
-static struct snd_soc_card fsi_soc_card = {
- .name = "FSI-DA7210",
- .owner = THIS_MODULE,
- .dai_link = &fsi_da7210_dai,
- .num_links = 1,
-};
-
-static struct platform_device *fsi_da7210_snd_device;
-
-static int __init fsi_da7210_sound_init(void)
-{
- int ret;
-
- fsi_da7210_snd_device = platform_device_alloc("soc-audio", FSI_PORT_B);
- if (!fsi_da7210_snd_device)
- return -ENOMEM;
-
- platform_set_drvdata(fsi_da7210_snd_device, &fsi_soc_card);
- ret = platform_device_add(fsi_da7210_snd_device);
- if (ret)
- platform_device_put(fsi_da7210_snd_device);
-
- return ret;
-}
-
-static void __exit fsi_da7210_sound_exit(void)
-{
- platform_device_unregister(fsi_da7210_snd_device);
-}
-
-module_init(fsi_da7210_sound_init);
-module_exit(fsi_da7210_sound_exit);
-
-/* Module information */
-MODULE_DESCRIPTION("ALSA SoC FSI DA2710");
-MODULE_AUTHOR("Kuninori Morimoto <morimoto.kuninori@renesas.com>");
-MODULE_LICENSE("GPL");
diff --git a/sound/soc/sh/fsi-hdmi.c b/sound/soc/sh/fsi-hdmi.c
deleted file mode 100644
index 6e41908323e8..000000000000
--- a/sound/soc/sh/fsi-hdmi.c
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * FSI - HDMI sound support
- *
- * Copyright (C) 2010 Renesas Solutions Corp.
- * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-
-#include <linux/platform_device.h>
-#include <linux/module.h>
-#include <sound/sh_fsi.h>
-
-struct fsi_hdmi_data {
- const char *cpu_dai;
- const char *card;
- int id;
-};
-
-static int fsi_hdmi_dai_init(struct snd_soc_pcm_runtime *rtd)
-{
- struct snd_soc_dai *cpu = rtd->cpu_dai;
- int ret;
-
- ret = snd_soc_dai_set_fmt(cpu, SND_SOC_DAIFMT_CBM_CFM);
-
- return ret;
-}
-
-static struct snd_soc_dai_link fsi_dai_link = {
- .name = "HDMI",
- .stream_name = "HDMI",
- .codec_dai_name = "sh_mobile_hdmi-hifi",
- .platform_name = "sh_fsi2",
- .codec_name = "sh-mobile-hdmi",
- .init = fsi_hdmi_dai_init,
-};
-
-static struct snd_soc_card fsi_soc_card = {
- .owner = THIS_MODULE,
- .dai_link = &fsi_dai_link,
- .num_links = 1,
-};
-
-static struct platform_device *fsi_snd_device;
-
-static int fsi_hdmi_probe(struct platform_device *pdev)
-{
- int ret = -ENOMEM;
- const struct platform_device_id *id_entry;
- struct fsi_hdmi_data *pdata;
-
- id_entry = pdev->id_entry;
- if (!id_entry) {
- dev_err(&pdev->dev, "unknown fsi hdmi\n");
- return -ENODEV;
- }
-
- pdata = (struct fsi_hdmi_data *)id_entry->driver_data;
-
- fsi_snd_device = platform_device_alloc("soc-audio", pdata->id);
- if (!fsi_snd_device)
- goto out;
-
- fsi_dai_link.cpu_dai_name = pdata->cpu_dai;
- fsi_soc_card.name = pdata->card;
-
- platform_set_drvdata(fsi_snd_device, &fsi_soc_card);
- ret = platform_device_add(fsi_snd_device);
-
- if (ret)
- platform_device_put(fsi_snd_device);
-
-out:
- return ret;
-}
-
-static int fsi_hdmi_remove(struct platform_device *pdev)
-{
- platform_device_unregister(fsi_snd_device);
- return 0;
-}
-
-static struct fsi_hdmi_data fsi2_a_hdmi = {
- .cpu_dai = "fsia-dai",
- .card = "FSI2A-HDMI",
- .id = FSI_PORT_A,
-};
-
-static struct fsi_hdmi_data fsi2_b_hdmi = {
- .cpu_dai = "fsib-dai",
- .card = "FSI2B-HDMI",
- .id = FSI_PORT_B,
-};
-
-static struct platform_device_id fsi_id_table[] = {
- /* FSI 2 */
- { "sh_fsi2_a_hdmi", (kernel_ulong_t)&fsi2_a_hdmi },
- { "sh_fsi2_b_hdmi", (kernel_ulong_t)&fsi2_b_hdmi },
- {},
-};
-
-static struct platform_driver fsi_hdmi = {
- .driver = {
- .name = "fsi-hdmi-audio",
- },
- .probe = fsi_hdmi_probe,
- .remove = fsi_hdmi_remove,
- .id_table = fsi_id_table,
-};
-
-module_platform_driver(fsi_hdmi);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Generic SH4 FSI-HDMI sound card");
-MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c
index 74ed2dffbffd..2ef98536f1da 100644
--- a/sound/soc/sh/fsi.c
+++ b/sound/soc/sh/fsi.c
@@ -132,6 +132,25 @@
typedef int (*set_rate_func)(struct device *dev, int rate, int enable);
/*
+ * bus options
+ *
+ * 0x000000BA
+ *
+ * A : sample widtht 16bit setting
+ * B : sample widtht 24bit setting
+ */
+
+#define SHIFT_16DATA 0
+#define SHIFT_24DATA 4
+
+#define PACKAGE_24BITBUS_BACK 0
+#define PACKAGE_24BITBUS_FRONT 1
+#define PACKAGE_16BITBUS_STREAM 2
+
+#define BUSOP_SET(s, a) ((a) << SHIFT_ ## s ## DATA)
+#define BUSOP_GET(s, a) (((a) >> SHIFT_ ## s ## DATA) & 0xF)
+
+/*
* FSI driver use below type name for variable
*
* xxx_num : number of data
@@ -189,6 +208,11 @@ struct fsi_stream {
int oerr_num;
/*
+ * bus options
+ */
+ u32 bus_option;
+
+ /*
* thse are initialized by fsi_handler_init()
*/
struct fsi_stream_handler *handler;
@@ -211,8 +235,7 @@ struct fsi_priv {
struct fsi_stream playback;
struct fsi_stream capture;
- u32 do_fmt;
- u32 di_fmt;
+ u32 fmt;
int chan_num:16;
int clk_master:1;
@@ -321,6 +344,10 @@ static void _fsi_master_mask_set(struct fsi_master *master,
/*
* basic function
*/
+static int fsi_version(struct fsi_master *master)
+{
+ return master->core->ver;
+}
static struct fsi_master *fsi_get_master(struct fsi_priv *fsi)
{
@@ -495,6 +522,7 @@ static void fsi_stream_init(struct fsi_priv *fsi,
io->period_samples = fsi_frame2sample(fsi, runtime->period_size);
io->period_pos = 0;
io->sample_width = samples_to_bytes(runtime, 1);
+ io->bus_option = 0;
io->oerr_num = -1; /* ignore 1st err */
io->uerr_num = -1; /* ignore 1st err */
fsi_stream_handler_call(io, init, fsi, io);
@@ -522,6 +550,7 @@ static void fsi_stream_quit(struct fsi_priv *fsi, struct fsi_stream *io)
io->period_samples = 0;
io->period_pos = 0;
io->sample_width = 0;
+ io->bus_option = 0;
io->oerr_num = 0;
io->uerr_num = 0;
spin_unlock_irqrestore(&master->lock, flags);
@@ -581,6 +610,53 @@ static int fsi_stream_remove(struct fsi_priv *fsi)
}
/*
+ * format/bus/dma setting
+ */
+static void fsi_format_bus_setup(struct fsi_priv *fsi, struct fsi_stream *io,
+ u32 bus, struct device *dev)
+{
+ struct fsi_master *master = fsi_get_master(fsi);
+ int is_play = fsi_stream_is_play(fsi, io);
+ u32 fmt = fsi->fmt;
+
+ if (fsi_version(master) >= 2) {
+ u32 dma = 0;
+
+ /*
+ * FSI2 needs DMA/Bus setting
+ */
+ switch (bus) {
+ case PACKAGE_24BITBUS_FRONT:
+ fmt |= CR_BWS_24;
+ dma |= VDMD_FRONT;
+ dev_dbg(dev, "24bit bus / package in front\n");
+ break;
+ case PACKAGE_16BITBUS_STREAM:
+ fmt |= CR_BWS_16;
+ dma |= VDMD_STREAM;
+ dev_dbg(dev, "16bit bus / stream mode\n");
+ break;
+ case PACKAGE_24BITBUS_BACK:
+ default:
+ fmt |= CR_BWS_24;
+ dma |= VDMD_BACK;
+ dev_dbg(dev, "24bit bus / package in back\n");
+ break;
+ }
+
+ if (is_play)
+ fsi_reg_write(fsi, OUT_DMAC, dma);
+ else
+ fsi_reg_write(fsi, IN_DMAC, dma);
+ }
+
+ if (is_play)
+ fsi_reg_write(fsi, DO_FMT, fmt);
+ else
+ fsi_reg_write(fsi, DI_FMT, fmt);
+}
+
+/*
* irq function
*/
@@ -629,11 +705,6 @@ static void fsi_spdif_clk_ctrl(struct fsi_priv *fsi, int enable)
struct fsi_master *master = fsi_get_master(fsi);
u32 mask, val;
- if (master->core->ver < 2) {
- pr_err("fsi: register access err (%s)\n", __func__);
- return;
- }
-
mask = BP | SE;
val = enable ? mask : 0;
@@ -648,9 +719,7 @@ static void fsi_spdif_clk_ctrl(struct fsi_priv *fsi, int enable)
static int fsi_set_master_clk(struct device *dev, struct fsi_priv *fsi,
long rate, int enable)
{
- struct fsi_master *master = fsi_get_master(fsi);
set_rate_func set_rate = fsi_get_info_set_rate(fsi);
- int fsi_ver = master->core->ver;
int ret;
if (!set_rate)
@@ -682,10 +751,7 @@ static int fsi_set_master_clk(struct device *dev, struct fsi_priv *fsi,
data |= (0x3 << 12);
break;
case SH_FSI_ACKMD_32:
- if (fsi_ver < 2)
- dev_err(dev, "unsupported ACKMD\n");
- else
- data |= (0x4 << 12);
+ data |= (0x4 << 12);
break;
}
@@ -708,10 +774,7 @@ static int fsi_set_master_clk(struct device *dev, struct fsi_priv *fsi,
data |= (0x4 << 8);
break;
case SH_FSI_BPFMD_16:
- if (fsi_ver < 2)
- dev_err(dev, "unsupported ACKMD\n");
- else
- data |= (0x7 << 8);
+ data |= (0x7 << 8);
break;
}
@@ -728,11 +791,26 @@ static int fsi_set_master_clk(struct device *dev, struct fsi_priv *fsi,
*/
static void fsi_pio_push16(struct fsi_priv *fsi, u8 *_buf, int samples)
{
- u16 *buf = (u16 *)_buf;
+ u32 enable_stream = fsi_get_info_flags(fsi) & SH_FSI_ENABLE_STREAM_MODE;
int i;
- for (i = 0; i < samples; i++)
- fsi_reg_write(fsi, DODT, ((u32)*(buf + i) << 8));
+ if (enable_stream) {
+ /*
+ * stream mode
+ * see
+ * fsi_pio_push_init()
+ */
+ u32 *buf = (u32 *)_buf;
+
+ for (i = 0; i < samples / 2; i++)
+ fsi_reg_write(fsi, DODT, buf[i]);
+ } else {
+ /* normal mode */
+ u16 *buf = (u16 *)_buf;
+
+ for (i = 0; i < samples; i++)
+ fsi_reg_write(fsi, DODT, ((u32)*(buf + i) << 8));
+ }
}
static void fsi_pio_pop16(struct fsi_priv *fsi, u8 *_buf, int samples)
@@ -872,12 +950,44 @@ static void fsi_pio_start_stop(struct fsi_priv *fsi, struct fsi_stream *io,
fsi_master_mask_set(master, CLK_RST, clk, (enable) ? clk : 0);
}
+static int fsi_pio_push_init(struct fsi_priv *fsi, struct fsi_stream *io)
+{
+ u32 enable_stream = fsi_get_info_flags(fsi) & SH_FSI_ENABLE_STREAM_MODE;
+
+ /*
+ * we can use 16bit stream mode
+ * when "playback" and "16bit data"
+ * and platform allows "stream mode"
+ * see
+ * fsi_pio_push16()
+ */
+ if (enable_stream)
+ io->bus_option = BUSOP_SET(24, PACKAGE_24BITBUS_BACK) |
+ BUSOP_SET(16, PACKAGE_16BITBUS_STREAM);
+ else
+ io->bus_option = BUSOP_SET(24, PACKAGE_24BITBUS_BACK) |
+ BUSOP_SET(16, PACKAGE_24BITBUS_BACK);
+ return 0;
+}
+
+static int fsi_pio_pop_init(struct fsi_priv *fsi, struct fsi_stream *io)
+{
+ /*
+ * always 24bit bus, package back when "capture"
+ */
+ io->bus_option = BUSOP_SET(24, PACKAGE_24BITBUS_BACK) |
+ BUSOP_SET(16, PACKAGE_24BITBUS_BACK);
+ return 0;
+}
+
static struct fsi_stream_handler fsi_pio_push_handler = {
+ .init = fsi_pio_push_init,
.transfer = fsi_pio_push,
.start_stop = fsi_pio_start_stop,
};
static struct fsi_stream_handler fsi_pio_pop_handler = {
+ .init = fsi_pio_pop_init,
.transfer = fsi_pio_pop,
.start_stop = fsi_pio_start_stop,
};
@@ -919,6 +1029,13 @@ static int fsi_dma_init(struct fsi_priv *fsi, struct fsi_stream *io)
enum dma_data_direction dir = fsi_stream_is_play(fsi, io) ?
DMA_TO_DEVICE : DMA_FROM_DEVICE;
+ /*
+ * 24bit data : 24bit bus / package in back
+ * 16bit data : 16bit bus / stream mode
+ */
+ io->bus_option = BUSOP_SET(24, PACKAGE_24BITBUS_BACK) |
+ BUSOP_SET(16, PACKAGE_16BITBUS_STREAM);
+
io->dma = dma_map_single(dai->dev, runtime->dma_area,
snd_pcm_lib_buffer_bytes(io->substream), dir);
return 0;
@@ -935,6 +1052,13 @@ static int fsi_dma_quit(struct fsi_priv *fsi, struct fsi_stream *io)
return 0;
}
+static dma_addr_t fsi_dma_get_area(struct fsi_stream *io)
+{
+ struct snd_pcm_runtime *runtime = io->substream->runtime;
+
+ return io->dma + samples_to_bytes(runtime, io->buff_sample_pos);
+}
+
static void fsi_dma_complete(void *data)
{
struct fsi_stream *io = (struct fsi_stream *)data;
@@ -944,7 +1068,7 @@ static void fsi_dma_complete(void *data)
enum dma_data_direction dir = fsi_stream_is_play(fsi, io) ?
DMA_TO_DEVICE : DMA_FROM_DEVICE;
- dma_sync_single_for_cpu(dai->dev, io->dma,
+ dma_sync_single_for_cpu(dai->dev, fsi_dma_get_area(io),
samples_to_bytes(runtime, io->period_samples), dir);
io->buff_sample_pos += io->period_samples;
@@ -961,13 +1085,6 @@ static void fsi_dma_complete(void *data)
snd_pcm_period_elapsed(io->substream);
}
-static dma_addr_t fsi_dma_get_area(struct fsi_stream *io)
-{
- struct snd_pcm_runtime *runtime = io->substream->runtime;
-
- return io->dma + samples_to_bytes(runtime, io->buff_sample_pos);
-}
-
static void fsi_dma_do_tasklet(unsigned long data)
{
struct fsi_stream *io = (struct fsi_stream *)data;
@@ -993,7 +1110,7 @@ static void fsi_dma_do_tasklet(unsigned long data)
len = samples_to_bytes(runtime, io->period_samples);
buf = fsi_dma_get_area(io);
- dma_sync_single_for_device(dai->dev, io->dma, len, dir);
+ dma_sync_single_for_device(dai->dev, buf, len, dir);
sg_init_table(&sg, 1);
sg_set_page(&sg, pfn_to_page(PFN_DOWN(buf)),
@@ -1055,25 +1172,16 @@ static int fsi_dma_transfer(struct fsi_priv *fsi, struct fsi_stream *io)
static void fsi_dma_push_start_stop(struct fsi_priv *fsi, struct fsi_stream *io,
int start)
{
- u32 bws;
- u32 dma;
+ struct fsi_master *master = fsi_get_master(fsi);
+ u32 clk = fsi_is_port_a(fsi) ? CRA : CRB;
+ u32 enable = start ? DMA_ON : 0;
- switch (io->sample_width * start) {
- case 2:
- bws = CR_BWS_16;
- dma = VDMD_STREAM | DMA_ON;
- break;
- case 4:
- bws = CR_BWS_24;
- dma = VDMD_BACK | DMA_ON;
- break;
- default:
- bws = 0;
- dma = 0;
- }
+ fsi_reg_mask_set(fsi, OUT_DMAC, DMA_ON, enable);
+
+ dmaengine_terminate_all(io->chan);
- fsi_reg_mask_set(fsi, DO_FMT, CR_BWS_MASK, bws);
- fsi_reg_write(fsi, OUT_DMAC, dma);
+ if (fsi_is_clk_master(fsi))
+ fsi_master_mask_set(master, CLK_RST, clk, (enable) ? clk : 0);
}
static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io)
@@ -1176,8 +1284,6 @@ static int fsi_hw_startup(struct fsi_priv *fsi,
struct fsi_stream *io,
struct device *dev)
{
- struct fsi_master *master = fsi_get_master(fsi);
- int fsi_ver = master->core->ver;
u32 flags = fsi_get_info_flags(fsi);
u32 data = 0;
@@ -1200,10 +1306,6 @@ static int fsi_hw_startup(struct fsi_priv *fsi,
fsi_reg_write(fsi, CKG2, data);
- /* set format */
- fsi_reg_write(fsi, DO_FMT, fsi->do_fmt);
- fsi_reg_write(fsi, DI_FMT, fsi->di_fmt);
-
/* spdif ? */
if (fsi_is_spdif(fsi)) {
fsi_spdif_clk_ctrl(fsi, 1);
@@ -1211,15 +1313,18 @@ static int fsi_hw_startup(struct fsi_priv *fsi,
}
/*
- * FIXME
- *
- * FSI driver assumed that data package is in-back.
- * FSI2 chip can select it.
+ * get bus settings
*/
- if (fsi_ver >= 2) {
- fsi_reg_write(fsi, OUT_DMAC, (1 << 4));
- fsi_reg_write(fsi, IN_DMAC, (1 << 4));
+ data = 0;
+ switch (io->sample_width) {
+ case 2:
+ data = BUSOP_GET(16, io->bus_option);
+ break;
+ case 4:
+ data = BUSOP_GET(24, io->bus_option);
+ break;
}
+ fsi_format_bus_setup(fsi, io, data, dev);
/* irq clear */
fsi_irq_disable(fsi, io);
@@ -1243,7 +1348,9 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream,
{
struct fsi_priv *fsi = fsi_get_priv(substream);
- return fsi_hw_startup(fsi, fsi_stream_get(fsi, substream), dai->dev);
+ fsi->rate = 0;
+
+ return 0;
}
static void fsi_dai_shutdown(struct snd_pcm_substream *substream,
@@ -1251,7 +1358,6 @@ static void fsi_dai_shutdown(struct snd_pcm_substream *substream,
{
struct fsi_priv *fsi = fsi_get_priv(substream);
- fsi_hw_shutdown(fsi, dai->dev);
fsi->rate = 0;
}
@@ -1265,11 +1371,13 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
fsi_stream_init(fsi, io, substream);
+ fsi_hw_startup(fsi, io, dai->dev);
ret = fsi_stream_transfer(io);
if (0 == ret)
fsi_stream_start(fsi, io);
break;
case SNDRV_PCM_TRIGGER_STOP:
+ fsi_hw_shutdown(fsi, dai->dev);
fsi_stream_stop(fsi, io);
fsi_stream_quit(fsi, io);
break;
@@ -1280,42 +1388,33 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
static int fsi_set_fmt_dai(struct fsi_priv *fsi, unsigned int fmt)
{
- u32 data = 0;
-
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_I2S:
- data = CR_I2S;
+ fsi->fmt = CR_I2S;
fsi->chan_num = 2;
break;
case SND_SOC_DAIFMT_LEFT_J:
- data = CR_PCM;
+ fsi->fmt = CR_PCM;
fsi->chan_num = 2;
break;
default:
return -EINVAL;
}
- fsi->do_fmt = data;
- fsi->di_fmt = data;
-
return 0;
}
static int fsi_set_fmt_spdif(struct fsi_priv *fsi)
{
struct fsi_master *master = fsi_get_master(fsi);
- u32 data = 0;
- if (master->core->ver < 2)
+ if (fsi_version(master) < 2)
return -EINVAL;
- data = CR_BWS_16 | CR_DTMD_SPDIF_PCM | CR_PCM;
+ fsi->fmt = CR_DTMD_SPDIF_PCM | CR_PCM;
fsi->chan_num = 2;
fsi->spdif = 1;
- fsi->do_fmt = data;
- fsi->di_fmt = data;
-
return 0;
}