ASoC: fsi: Fixup for master mode
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> Acked-by: Liam Girdwood <lrg@slimlogic.co.uk> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
This commit is contained in:
parent
d78541473d
commit
ccad7b44cc
@ -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];
|
||||
|
@ -65,6 +65,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
|
||||
@ -734,12 +738,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);
|
||||
@ -786,10 +784,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,
|
||||
};
|
||||
|
||||
/************************************************************************
|
||||
|
Loading…
Reference in New Issue
Block a user