Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 305814
b: refs/heads/master
c: 766812e
h: refs/heads/master
v: v3
  • Loading branch information
Kuninori Morimoto authored and Mark Brown committed May 19, 2012
1 parent 4b2c2e0 commit bacca49
Show file tree
Hide file tree
Showing 3 changed files with 149 additions and 36 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: f33238e96f619d9888713c07dcd92e4518879282
refs/heads/master: 766812e6d5e2e23be1e212cf84902d5e834dd865
6 changes: 5 additions & 1 deletion trunk/include/sound/sh_fsi.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,11 @@
/*
* flags format
*
* 0x000000BA
* 0x00000CBA
*
* A: inversion
* B: format mode
* C: chip specific
*/

/* A: clock inversion */
Expand All @@ -39,6 +40,9 @@
#define SH_FSI_FMT_DAI (0 << 4)
#define SH_FSI_FMT_SPDIF (1 << 4)

/* C: chip specific */
#define SH_FSI_OPTION_MASK 0x00000F00
#define SH_FSI_ENABLE_STREAM_MODE (1 << 8) /* for 16bit data */

/*
* set_rate return value
Expand Down
177 changes: 143 additions & 34 deletions trunk/sound/soc/sh/fsi.c
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,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
*
Expand Down Expand Up @@ -188,6 +207,11 @@ struct fsi_stream {
int uerr_num;
int oerr_num;

/*
* bus options
*/
u32 bus_option;

/*
* thse are initialized by fsi_handler_init()
*/
Expand Down Expand Up @@ -498,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);
Expand Down Expand Up @@ -525,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);
Expand Down Expand Up @@ -583,6 +609,53 @@ static int fsi_stream_remove(struct fsi_priv *fsi)
return 0;
}

/*
* 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
*/
Expand Down Expand Up @@ -718,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)
Expand Down Expand Up @@ -862,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,
};
Expand Down Expand Up @@ -909,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;
Expand Down Expand Up @@ -1045,25 +1172,9 @@ 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;
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, DO_FMT, CR_BWS_MASK, bws);
fsi_reg_write(fsi, OUT_DMAC, dma);
fsi_reg_mask_set(fsi, OUT_DMAC, DMA_ON, enable);
}

static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io)
Expand Down Expand Up @@ -1166,7 +1277,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);
u32 flags = fsi_get_info_flags(fsi);
u32 data = 0;

Expand All @@ -1189,26 +1299,25 @@ static int fsi_hw_startup(struct fsi_priv *fsi,

fsi_reg_write(fsi, CKG2, data);

/* set format */
fsi_reg_write(fsi, DO_FMT, fsi->fmt);
fsi_reg_write(fsi, DI_FMT, fsi->fmt);

/* spdif ? */
if (fsi_is_spdif(fsi)) {
fsi_spdif_clk_ctrl(fsi, 1);
fsi_reg_mask_set(fsi, OUT_SEL, DMMD, DMMD);
}

/*
* FIXME
*
* FSI driver assumed that data package is in-back.
* FSI2 chip can select it.
* get bus settings
*/
if (fsi_version(master) >= 2) {
fsi_reg_write(fsi, OUT_DMAC, VDMD_BACK);
fsi_reg_write(fsi, IN_DMAC, VDMD_BACK);
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);
Expand Down Expand Up @@ -1295,7 +1404,7 @@ static int fsi_set_fmt_spdif(struct fsi_priv *fsi)
if (fsi_version(master) < 2)
return -EINVAL;

fsi->fmt = CR_BWS_16 | CR_DTMD_SPDIF_PCM | CR_PCM;
fsi->fmt = CR_DTMD_SPDIF_PCM | CR_PCM;
fsi->chan_num = 2;
fsi->spdif = 1;

Expand Down

0 comments on commit bacca49

Please sign in to comment.