Skip to content

Commit

Permalink
ASoC: fsi: Fixup for master mode
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Kuninori Morimoto authored and Mark Brown committed Jul 13, 2010
1 parent d785414 commit ccad7b4
Show file tree
Hide file tree
Showing 2 changed files with 124 additions and 6 deletions.
32 changes: 32 additions & 0 deletions include/sound/sh_fsi.h
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand Down
98 changes: 92 additions & 6 deletions sound/soc/sh/fsi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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,
};

/************************************************************************
Expand Down

0 comments on commit ccad7b4

Please sign in to comment.