[alsa-devel] [PATCH 0/6] ASoC: fsi: modify patch
Dear Mark
These are v2 patches for FSI driver almost all are same as v1
Kuninori Morimoto (6): ASoC: fsi: modify format area definition on flags ASoC: fsi: remove un-used variable on fsi_dai_startup ASoC: fsi: remove noisy CR_FMT macro ASoC: fsi: Change struct fsi_regs to fsi_core ASoC: fsi: Add pr_err for noticing unsupported access ASoC: fsi: Fixup for master mode
v1 -> v2
o modiry straight start number as 0 o based on bug fix patches
Best regards -- Kuninori Morimoto
There is no necessity that each bit in this area has the meaning. This patch modify it to sequence number
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- v1 -> v2
o modiry straight start number as 0
include/sound/sh_fsi.h | 12 ++++++------ 1 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/include/sound/sh_fsi.h b/include/sound/sh_fsi.h index c022736..d025e54 100644 --- a/include/sound/sh_fsi.h +++ b/include/sound/sh_fsi.h @@ -55,12 +55,12 @@ #define SH_FSI_GET_IFMT(x) ((x >> 8) & SH_FSI_FMT_MASK) #define SH_FSI_GET_OFMT(x) ((x >> 0) & SH_FSI_FMT_MASK)
-#define SH_FSI_FMT_MONO (1 << 0) -#define SH_FSI_FMT_MONO_DELAY (1 << 1) -#define SH_FSI_FMT_PCM (1 << 2) -#define SH_FSI_FMT_I2S (1 << 3) -#define SH_FSI_FMT_TDM (1 << 4) -#define SH_FSI_FMT_TDM_DELAY (1 << 5) +#define SH_FSI_FMT_MONO (0 << 0) +#define SH_FSI_FMT_MONO_DELAY (1 << 0) +#define SH_FSI_FMT_PCM (2 << 0) +#define SH_FSI_FMT_I2S (3 << 0) +#define SH_FSI_FMT_TDM (4 << 0) +#define SH_FSI_FMT_TDM_DELAY (5 << 0)
#define SH_FSI_IFMT_TDM_CH(x) \ (SH_FSI_IFMT(TDM) | SH_FSI_SET_CH_I(x))
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- sound/soc/sh/fsi.c | 7 ------- 1 files changed, 0 insertions(+), 7 deletions(-)
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index ec4acac..33a56dc 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c @@ -662,7 +662,6 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct fsi_priv *fsi = fsi_get_priv(substream); - const char *msg; u32 flags = fsi_get_info_flags(fsi); u32 fmt; u32 reg; @@ -700,33 +699,27 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream, fmt = is_play ? SH_FSI_GET_OFMT(flags) : SH_FSI_GET_IFMT(flags); switch (fmt) { case SH_FSI_FMT_MONO: - msg = "MONO"; data = CR_FMT(CR_MONO); fsi->chan = 1; break; case SH_FSI_FMT_MONO_DELAY: - msg = "MONO Delay"; data = CR_FMT(CR_MONO_D); fsi->chan = 1; break; case SH_FSI_FMT_PCM: - msg = "PCM"; data = CR_FMT(CR_PCM); fsi->chan = 2; break; case SH_FSI_FMT_I2S: - msg = "I2S"; data = CR_FMT(CR_I2S); fsi->chan = 2; break; case SH_FSI_FMT_TDM: - msg = "TDM"; fsi->chan = is_play ? SH_FSI_GET_CH_O(flags) : SH_FSI_GET_CH_I(flags); data = CR_FMT(CR_TDM) | (fsi->chan - 1); break; case SH_FSI_FMT_TDM_DELAY: - msg = "TDM Delay"; fsi->chan = is_play ? SH_FSI_GET_CH_O(flags) : SH_FSI_GET_CH_I(flags); data = CR_FMT(CR_TDM_D) | (fsi->chan - 1);
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- sound/soc/sh/fsi.c | 25 ++++++++++++------------- 1 files changed, 12 insertions(+), 13 deletions(-)
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index 33a56dc..1843e10 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c @@ -57,13 +57,12 @@
/* DO_FMT */ /* DI_FMT */ -#define CR_FMT(param) ((param) << 4) -# define CR_MONO 0x0 -# define CR_MONO_D 0x1 -# define CR_PCM 0x2 -# define CR_I2S 0x3 -# define CR_TDM 0x4 -# define CR_TDM_D 0x5 +#define CR_MONO (0x0 << 4) +#define CR_MONO_D (0x1 << 4) +#define CR_PCM (0x2 << 4) +#define CR_I2S (0x3 << 4) +#define CR_TDM (0x4 << 4) +#define CR_TDM_D (0x5 << 4)
/* DOFF_CTL */ /* DIFF_CTL */ @@ -699,30 +698,30 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream, fmt = is_play ? SH_FSI_GET_OFMT(flags) : SH_FSI_GET_IFMT(flags); switch (fmt) { case SH_FSI_FMT_MONO: - data = CR_FMT(CR_MONO); + data = CR_MONO; fsi->chan = 1; break; case SH_FSI_FMT_MONO_DELAY: - data = CR_FMT(CR_MONO_D); + data = CR_MONO_D; fsi->chan = 1; break; case SH_FSI_FMT_PCM: - data = CR_FMT(CR_PCM); + data = CR_PCM; fsi->chan = 2; break; case SH_FSI_FMT_I2S: - data = CR_FMT(CR_I2S); + data = CR_I2S; fsi->chan = 2; break; case SH_FSI_FMT_TDM: fsi->chan = is_play ? SH_FSI_GET_CH_O(flags) : SH_FSI_GET_CH_I(flags); - data = CR_FMT(CR_TDM) | (fsi->chan - 1); + data = CR_TDM | (fsi->chan - 1); break; case SH_FSI_FMT_TDM_DELAY: fsi->chan = is_play ? SH_FSI_GET_CH_O(flags) : SH_FSI_GET_CH_I(flags); - data = CR_FMT(CR_TDM_D) | (fsi->chan - 1); + data = CR_TDM_D | (fsi->chan - 1); break; default: dev_err(dai->dev, "unknown format.\n");
Many registers which were grouped by category were added in FSI2. To make easy to switch FSI/FSI2, fsi_core was added instead of fsi_regs.
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- sound/soc/sh/fsi.c | 36 ++++++++++++++++++++++-------------- 1 files changed, 22 insertions(+), 14 deletions(-)
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index 1843e10..8bc80b5 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c @@ -120,7 +120,9 @@ struct fsi_priv { int periods; };
-struct fsi_regs { +struct fsi_core { + int ver; + u32 int_st; u32 iemsk; u32 imsk; @@ -131,7 +133,7 @@ struct fsi_master { int irq; struct fsi_priv fsia; struct fsi_priv fsib; - struct fsi_regs *regs; + struct fsi_core *core; struct sh_fsi_platform_info *info; spinlock_t lock; }; @@ -348,8 +350,8 @@ static void fsi_irq_enable(struct fsi_priv *fsi, int is_play) u32 data = fsi_port_ab_io_bit(fsi, is_play); struct fsi_master *master = fsi_get_master(fsi);
- fsi_master_mask_set(master, master->regs->imsk, data, data); - fsi_master_mask_set(master, master->regs->iemsk, data, data); + fsi_master_mask_set(master, master->core->imsk, data, data); + fsi_master_mask_set(master, master->core->iemsk, data, data); }
static void fsi_irq_disable(struct fsi_priv *fsi, int is_play) @@ -357,18 +359,18 @@ static void fsi_irq_disable(struct fsi_priv *fsi, int is_play) u32 data = fsi_port_ab_io_bit(fsi, is_play); struct fsi_master *master = fsi_get_master(fsi);
- fsi_master_mask_set(master, master->regs->imsk, data, 0); - fsi_master_mask_set(master, master->regs->iemsk, data, 0); + fsi_master_mask_set(master, master->core->imsk, data, 0); + fsi_master_mask_set(master, master->core->iemsk, data, 0); }
static u32 fsi_irq_get_status(struct fsi_master *master) { - return fsi_master_read(master, master->regs->int_st); + return fsi_master_read(master, master->core->int_st); }
static void fsi_irq_clear_all_status(struct fsi_master *master) { - fsi_master_write(master, master->regs->int_st, 0x0000000); + fsi_master_write(master, master->core->int_st, 0); }
static void fsi_irq_clear_status(struct fsi_priv *fsi) @@ -380,7 +382,7 @@ static void fsi_irq_clear_status(struct fsi_priv *fsi) data |= fsi_port_ab_io_bit(fsi, 1);
/* clear interrupt factor */ - fsi_master_mask_set(master, master->regs->int_st, data, 0); + fsi_master_mask_set(master, master->core->int_st, data, 0); }
/************************************************************************ @@ -996,7 +998,7 @@ static int fsi_probe(struct platform_device *pdev) master->fsia.master = master; master->fsib.base = master->base + 0x40; master->fsib.master = master; - master->regs = (struct fsi_regs *)id_entry->driver_data; + master->core = (struct fsi_core *)id_entry->driver_data; spin_lock_init(&master->lock);
pm_runtime_enable(&pdev->dev); @@ -1077,21 +1079,27 @@ static struct dev_pm_ops fsi_pm_ops = { .runtime_resume = fsi_runtime_nop, };
-static struct fsi_regs fsi_regs = { +static struct fsi_core fsi1_core = { + .ver = 1, + + /* Interrupt */ .int_st = INT_ST, .iemsk = IEMSK, .imsk = IMSK, };
-static struct fsi_regs fsi2_regs = { +static struct fsi_core fsi2_core = { + .ver = 2, + + /* Interrupt */ .int_st = CPU_INT_ST, .iemsk = CPU_IEMSK, .imsk = CPU_IMSK, };
static struct platform_device_id fsi_id_table[] = { - { "sh_fsi", (kernel_ulong_t)&fsi_regs }, - { "sh_fsi2", (kernel_ulong_t)&fsi2_regs }, + { "sh_fsi", (kernel_ulong_t)&fsi1_core }, + { "sh_fsi2", (kernel_ulong_t)&fsi2_core }, };
static struct platform_driver fsi_driver = {
This patch didn't use dev_err, because it is difficult to get struct device here.
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- sound/soc/sh/fsi.c | 24 ++++++++++++++++++------ 1 files changed, 18 insertions(+), 6 deletions(-)
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index 8bc80b5..2377307 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c @@ -170,24 +170,30 @@ static void __fsi_reg_mask_set(u32 reg, u32 mask, u32 data)
static void fsi_reg_write(struct fsi_priv *fsi, u32 reg, u32 data) { - if (reg > REG_END) + if (reg > REG_END) { + pr_err("fsi: register access err (%s)\n", __func__); return; + }
__fsi_reg_write((u32)(fsi->base + reg), data); }
static u32 fsi_reg_read(struct fsi_priv *fsi, u32 reg) { - if (reg > REG_END) + if (reg > REG_END) { + pr_err("fsi: register access err (%s)\n", __func__); return 0; + }
return __fsi_reg_read((u32)(fsi->base + reg)); }
static void fsi_reg_mask_set(struct fsi_priv *fsi, u32 reg, u32 mask, u32 data) { - if (reg > REG_END) + if (reg > REG_END) { + pr_err("fsi: register access err (%s)\n", __func__); return; + }
__fsi_reg_mask_set((u32)(fsi->base + reg), mask, data); } @@ -197,8 +203,10 @@ static void fsi_master_write(struct fsi_master *master, u32 reg, u32 data) unsigned long flags;
if ((reg < MREG_START) || - (reg > MREG_END)) + (reg > MREG_END)) { + pr_err("fsi: register access err (%s)\n", __func__); return; + }
spin_lock_irqsave(&master->lock, flags); __fsi_reg_write((u32)(master->base + reg), data); @@ -211,8 +219,10 @@ static u32 fsi_master_read(struct fsi_master *master, u32 reg) unsigned long flags;
if ((reg < MREG_START) || - (reg > MREG_END)) + (reg > MREG_END)) { + pr_err("fsi: register access err (%s)\n", __func__); return 0; + }
spin_lock_irqsave(&master->lock, flags); ret = __fsi_reg_read((u32)(master->base + reg)); @@ -227,8 +237,10 @@ static void fsi_master_mask_set(struct fsi_master *master, unsigned long flags;
if ((reg < MREG_START) || - (reg > MREG_END)) + (reg > MREG_END)) { + pr_err("fsi: register access err (%s)\n", __func__); return; + }
spin_lock_irqsave(&master->lock, flags); __fsi_reg_mask_set((u32)(master->base + reg), mask, data);
This patch add hw_params to snd_soc_dai_ops, because board specific set_rate is needed when FSI was used as master mode.
This patch remove fsi_clk_ctrl from fsi_dai_startup, because clock should be disabled before set_rate.
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- include/sound/sh_fsi.h | 32 ++++++++++++++++ sound/soc/sh/fsi.c | 98 +++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 124 insertions(+), 6 deletions(-)
diff --git a/include/sound/sh_fsi.h b/include/sound/sh_fsi.h index d025e54..b63fe76 100644 --- a/include/sound/sh_fsi.h +++ b/include/sound/sh_fsi.h @@ -72,9 +72,41 @@ #define SH_FSI_OFMT_TDM_DELAY_CH(x) \ (SH_FSI_OFMT(TDM_DELAY) | SH_FSI_SET_CH_O(x))
+ +/* + * set_rate return value + * + * see ACKMD/BPFMD on + * ACK_MD (FSI2) + * CKG1 (FSI) + * + * err: return value < 0 + * + * 0x-00000AB + * + * A: ACKMD value + * B: BPFMD value + */ + +#define SH_FSI_ACKMD_MASK (0xF << 0) +#define SH_FSI_ACKMD_512 (1 << 0) +#define SH_FSI_ACKMD_256 (2 << 0) +#define SH_FSI_ACKMD_128 (3 << 0) +#define SH_FSI_ACKMD_64 (4 << 0) +#define SH_FSI_ACKMD_32 (5 << 0) + +#define SH_FSI_BPFMD_MASK (0xF << 4) +#define SH_FSI_BPFMD_512 (1 << 4) +#define SH_FSI_BPFMD_256 (2 << 4) +#define SH_FSI_BPFMD_128 (3 << 4) +#define SH_FSI_BPFMD_64 (4 << 4) +#define SH_FSI_BPFMD_32 (5 << 4) +#define SH_FSI_BPFMD_16 (6 << 4) + struct sh_fsi_platform_info { unsigned long porta_flags; unsigned long portb_flags; + int (*set_rate)(int is_porta, int rate); /* for master mode */ };
extern struct snd_soc_dai fsi_soc_dai[2]; diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index 2377307..aab0d87 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c @@ -74,6 +74,10 @@ #define ERR_UNDER 0x00000001 #define ST_ERR (ERR_OVER | ERR_UNDER)
+/* CKG1 */ +#define ACKMD_MASK 0x00007000 +#define BPFMD_MASK 0x00000700 + /* CLK_RST */ #define B_CLK 0x00000010 #define A_CLK 0x00000001 @@ -743,12 +747,6 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream, } fsi_reg_write(fsi, reg, data);
- /* - * clear clk reset if master mode - */ - if (is_master) - fsi_clk_ctrl(fsi, 1); - /* irq clear */ fsi_irq_disable(fsi, is_play); fsi_irq_clear_status(fsi); @@ -795,10 +793,98 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd, return ret; }
+static int fsi_dai_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct fsi_priv *fsi = fsi_get_priv(substream); + struct fsi_master *master = fsi_get_master(fsi); + int (*set_rate)(int is_porta, int rate) = master->info->set_rate; + int fsi_ver = master->core->ver; + int is_play = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); + int ret; + + /* if slave mode, set_rate is not needed */ + if (!fsi_is_master_mode(fsi, is_play)) + return 0; + + /* it is error if no set_rate */ + if (!set_rate) + return -EIO; + + /* clock stop */ + pm_runtime_put_sync(dai->dev); + fsi_clk_ctrl(fsi, 0); + + ret = set_rate(fsi_is_port_a(fsi), params_rate(params)); + if (ret > 0) { + u32 data = 0; + + switch (ret & SH_FSI_ACKMD_MASK) { + default: + /* FALL THROUGH */ + case SH_FSI_ACKMD_512: + data |= (0x0 << 12); + break; + case SH_FSI_ACKMD_256: + data |= (0x1 << 12); + break; + case SH_FSI_ACKMD_128: + data |= (0x2 << 12); + break; + case SH_FSI_ACKMD_64: + data |= (0x3 << 12); + break; + case SH_FSI_ACKMD_32: + if (fsi_ver < 2) + dev_err(dai->dev, "unsupported ACKMD\n"); + else + data |= (0x4 << 12); + break; + } + + switch (ret & SH_FSI_BPFMD_MASK) { + default: + /* FALL THROUGH */ + case SH_FSI_BPFMD_32: + data |= (0x0 << 8); + break; + case SH_FSI_BPFMD_64: + data |= (0x1 << 8); + break; + case SH_FSI_BPFMD_128: + data |= (0x2 << 8); + break; + case SH_FSI_BPFMD_256: + data |= (0x3 << 8); + break; + case SH_FSI_BPFMD_512: + data |= (0x4 << 8); + break; + case SH_FSI_BPFMD_16: + if (fsi_ver < 2) + dev_err(dai->dev, "unsupported ACKMD\n"); + else + data |= (0x7 << 8); + break; + } + + fsi_reg_mask_set(fsi, CKG1, (ACKMD_MASK | BPFMD_MASK) , data); + udelay(10); + fsi_clk_ctrl(fsi, 1); + ret = 0; + } + pm_runtime_get_sync(dai->dev); + + return ret; + +} + static struct snd_soc_dai_ops fsi_dai_ops = { .startup = fsi_dai_startup, .shutdown = fsi_dai_shutdown, .trigger = fsi_dai_trigger, + .hw_params = fsi_dai_hw_params, };
/************************************************************************
participants (1)
-
Kuninori Morimoto