mirror of https://gitee.com/openkylin/linux.git
Merge remote-tracking branch 'asoc/topic/davinci' into asoc-next
This commit is contained in:
commit
d66e065c5b
|
@ -235,6 +235,8 @@
|
||||||
#define DISMOD (val)(val<<2)
|
#define DISMOD (val)(val<<2)
|
||||||
#define TXSTATE BIT(4)
|
#define TXSTATE BIT(4)
|
||||||
#define RXSTATE BIT(5)
|
#define RXSTATE BIT(5)
|
||||||
|
#define SRMOD_MASK 3
|
||||||
|
#define SRMOD_INACTIVE 0
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* DAVINCI_MCASP_LBCTL_REG - Loop Back Control Register Bits
|
* DAVINCI_MCASP_LBCTL_REG - Loop Back Control Register Bits
|
||||||
|
@ -643,26 +645,33 @@ static int davinci_config_channel_size(struct davinci_audio_dev *dev,
|
||||||
/* mapping of the XSSZ bit-field as described in the datasheet */
|
/* mapping of the XSSZ bit-field as described in the datasheet */
|
||||||
fmt = (word_length >> 1) - 1;
|
fmt = (word_length >> 1) - 1;
|
||||||
|
|
||||||
mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMT_REG,
|
if (dev->op_mode != DAVINCI_MCASP_DIT_MODE) {
|
||||||
RXSSZ(fmt), RXSSZ(0x0F));
|
mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMT_REG,
|
||||||
mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMT_REG,
|
RXSSZ(fmt), RXSSZ(0x0F));
|
||||||
TXSSZ(fmt), TXSSZ(0x0F));
|
mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMT_REG,
|
||||||
mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, TXROT(rotate),
|
TXSSZ(fmt), TXSSZ(0x0F));
|
||||||
TXROT(7));
|
mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMT_REG,
|
||||||
mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, RXROT(rotate),
|
TXROT(rotate), TXROT(7));
|
||||||
RXROT(7));
|
mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMT_REG,
|
||||||
|
RXROT(rotate), RXROT(7));
|
||||||
|
mcasp_set_reg(dev->base + DAVINCI_MCASP_RXMASK_REG,
|
||||||
|
mask);
|
||||||
|
}
|
||||||
|
|
||||||
mcasp_set_reg(dev->base + DAVINCI_MCASP_TXMASK_REG, mask);
|
mcasp_set_reg(dev->base + DAVINCI_MCASP_TXMASK_REG, mask);
|
||||||
mcasp_set_reg(dev->base + DAVINCI_MCASP_RXMASK_REG, mask);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void davinci_hw_common_param(struct davinci_audio_dev *dev, int stream)
|
static int davinci_hw_common_param(struct davinci_audio_dev *dev, int stream,
|
||||||
|
int channels)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
u8 tx_ser = 0;
|
u8 tx_ser = 0;
|
||||||
u8 rx_ser = 0;
|
u8 rx_ser = 0;
|
||||||
|
u8 ser;
|
||||||
|
u8 slots = dev->tdm_slots;
|
||||||
|
u8 max_active_serializers = (channels + slots - 1) / slots;
|
||||||
/* Default configuration */
|
/* Default configuration */
|
||||||
mcasp_set_bits(dev->base + DAVINCI_MCASP_PWREMUMGT_REG, MCASP_SOFT);
|
mcasp_set_bits(dev->base + DAVINCI_MCASP_PWREMUMGT_REG, MCASP_SOFT);
|
||||||
|
|
||||||
|
@ -682,17 +691,33 @@ static void davinci_hw_common_param(struct davinci_audio_dev *dev, int stream)
|
||||||
for (i = 0; i < dev->num_serializer; i++) {
|
for (i = 0; i < dev->num_serializer; i++) {
|
||||||
mcasp_set_bits(dev->base + DAVINCI_MCASP_XRSRCTL_REG(i),
|
mcasp_set_bits(dev->base + DAVINCI_MCASP_XRSRCTL_REG(i),
|
||||||
dev->serial_dir[i]);
|
dev->serial_dir[i]);
|
||||||
if (dev->serial_dir[i] == TX_MODE) {
|
if (dev->serial_dir[i] == TX_MODE &&
|
||||||
|
tx_ser < max_active_serializers) {
|
||||||
mcasp_set_bits(dev->base + DAVINCI_MCASP_PDIR_REG,
|
mcasp_set_bits(dev->base + DAVINCI_MCASP_PDIR_REG,
|
||||||
AXR(i));
|
AXR(i));
|
||||||
tx_ser++;
|
tx_ser++;
|
||||||
} else if (dev->serial_dir[i] == RX_MODE) {
|
} else if (dev->serial_dir[i] == RX_MODE &&
|
||||||
|
rx_ser < max_active_serializers) {
|
||||||
mcasp_clr_bits(dev->base + DAVINCI_MCASP_PDIR_REG,
|
mcasp_clr_bits(dev->base + DAVINCI_MCASP_PDIR_REG,
|
||||||
AXR(i));
|
AXR(i));
|
||||||
rx_ser++;
|
rx_ser++;
|
||||||
|
} else {
|
||||||
|
mcasp_mod_bits(dev->base + DAVINCI_MCASP_XRSRCTL_REG(i),
|
||||||
|
SRMOD_INACTIVE, SRMOD_MASK);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||||
|
ser = tx_ser;
|
||||||
|
else
|
||||||
|
ser = rx_ser;
|
||||||
|
|
||||||
|
if (ser < max_active_serializers) {
|
||||||
|
dev_warn(dev->dev, "stream has more channels (%d) than are "
|
||||||
|
"enabled in mcasp (%d)\n", channels, ser * slots);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
if (dev->txnumevt && stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
if (dev->txnumevt && stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||||
if (dev->txnumevt * tx_ser > 64)
|
if (dev->txnumevt * tx_ser > 64)
|
||||||
dev->txnumevt = 1;
|
dev->txnumevt = 1;
|
||||||
|
@ -729,6 +754,8 @@ static void davinci_hw_common_param(struct davinci_audio_dev *dev, int stream)
|
||||||
((dev->rxnumevt * rx_ser) << 8), NUMEVT_MASK);
|
((dev->rxnumevt * rx_ser) << 8), NUMEVT_MASK);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void davinci_hw_param(struct davinci_audio_dev *dev, int stream)
|
static void davinci_hw_param(struct davinci_audio_dev *dev, int stream)
|
||||||
|
@ -772,12 +799,6 @@ static void davinci_hw_param(struct davinci_audio_dev *dev, int stream)
|
||||||
/* S/PDIF */
|
/* S/PDIF */
|
||||||
static void davinci_hw_dit_param(struct davinci_audio_dev *dev)
|
static void davinci_hw_dit_param(struct davinci_audio_dev *dev)
|
||||||
{
|
{
|
||||||
/* Set the PDIR for Serialiser as output */
|
|
||||||
mcasp_set_bits(dev->base + DAVINCI_MCASP_PDIR_REG, AFSX);
|
|
||||||
|
|
||||||
/* TXMASK for 24 bits */
|
|
||||||
mcasp_set_reg(dev->base + DAVINCI_MCASP_TXMASK_REG, 0x00FFFFFF);
|
|
||||||
|
|
||||||
/* Set the TX format : 24 bit right rotation, 32 bit slot, Pad 0
|
/* Set the TX format : 24 bit right rotation, 32 bit slot, Pad 0
|
||||||
and LSB first */
|
and LSB first */
|
||||||
mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG,
|
mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG,
|
||||||
|
@ -812,8 +833,14 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
|
||||||
&dev->dma_params[substream->stream];
|
&dev->dma_params[substream->stream];
|
||||||
int word_length;
|
int word_length;
|
||||||
u8 fifo_level;
|
u8 fifo_level;
|
||||||
|
u8 slots = dev->tdm_slots;
|
||||||
|
int channels;
|
||||||
|
struct snd_interval *pcm_channels = hw_param_interval(params,
|
||||||
|
SNDRV_PCM_HW_PARAM_CHANNELS);
|
||||||
|
channels = pcm_channels->min;
|
||||||
|
|
||||||
davinci_hw_common_param(dev, substream->stream);
|
if (davinci_hw_common_param(dev, substream->stream, channels) == -EINVAL)
|
||||||
|
return -EINVAL;
|
||||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||||
fifo_level = dev->txnumevt;
|
fifo_level = dev->txnumevt;
|
||||||
else
|
else
|
||||||
|
@ -862,6 +889,7 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
|
||||||
dma_params->acnt = dma_params->data_type;
|
dma_params->acnt = dma_params->data_type;
|
||||||
|
|
||||||
dma_params->fifo_level = fifo_level;
|
dma_params->fifo_level = fifo_level;
|
||||||
|
dma_params->active_serializers = (channels + slots - 1) / slots;
|
||||||
davinci_config_channel_size(dev, word_length);
|
davinci_config_channel_size(dev, word_length);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -936,13 +964,13 @@ static struct snd_soc_dai_driver davinci_mcasp_dai[] = {
|
||||||
.name = "davinci-mcasp.0",
|
.name = "davinci-mcasp.0",
|
||||||
.playback = {
|
.playback = {
|
||||||
.channels_min = 2,
|
.channels_min = 2,
|
||||||
.channels_max = 2,
|
.channels_max = 32 * 16,
|
||||||
.rates = DAVINCI_MCASP_RATES,
|
.rates = DAVINCI_MCASP_RATES,
|
||||||
.formats = DAVINCI_MCASP_PCM_FMTS,
|
.formats = DAVINCI_MCASP_PCM_FMTS,
|
||||||
},
|
},
|
||||||
.capture = {
|
.capture = {
|
||||||
.channels_min = 2,
|
.channels_min = 2,
|
||||||
.channels_max = 2,
|
.channels_max = 32 * 16,
|
||||||
.rates = DAVINCI_MCASP_RATES,
|
.rates = DAVINCI_MCASP_RATES,
|
||||||
.formats = DAVINCI_MCASP_PCM_FMTS,
|
.formats = DAVINCI_MCASP_PCM_FMTS,
|
||||||
},
|
},
|
||||||
|
@ -1019,8 +1047,16 @@ static struct snd_platform_data *davinci_mcasp_set_pdata_from_of(
|
||||||
pdata->op_mode = val;
|
pdata->op_mode = val;
|
||||||
|
|
||||||
ret = of_property_read_u32(np, "tdm-slots", &val);
|
ret = of_property_read_u32(np, "tdm-slots", &val);
|
||||||
if (ret >= 0)
|
if (ret >= 0) {
|
||||||
|
if (val < 2 || val > 32) {
|
||||||
|
dev_err(&pdev->dev,
|
||||||
|
"tdm-slots must be in rage [2-32]\n");
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto nodata;
|
||||||
|
}
|
||||||
|
|
||||||
pdata->tdm_slots = val;
|
pdata->tdm_slots = val;
|
||||||
|
}
|
||||||
|
|
||||||
ret = of_property_read_u32(np, "num-serializer", &val);
|
ret = of_property_read_u32(np, "num-serializer", &val);
|
||||||
if (ret >= 0)
|
if (ret >= 0)
|
||||||
|
|
|
@ -181,6 +181,7 @@ static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream)
|
||||||
unsigned short acnt;
|
unsigned short acnt;
|
||||||
unsigned int count;
|
unsigned int count;
|
||||||
unsigned int fifo_level;
|
unsigned int fifo_level;
|
||||||
|
unsigned char serializers = prtd->params->active_serializers;
|
||||||
|
|
||||||
period_size = snd_pcm_lib_period_bytes(substream);
|
period_size = snd_pcm_lib_period_bytes(substream);
|
||||||
dma_offset = prtd->period * period_size;
|
dma_offset = prtd->period * period_size;
|
||||||
|
@ -194,14 +195,14 @@ static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream)
|
||||||
data_type = prtd->params->data_type;
|
data_type = prtd->params->data_type;
|
||||||
count = period_size / data_type;
|
count = period_size / data_type;
|
||||||
if (fifo_level)
|
if (fifo_level)
|
||||||
count /= fifo_level;
|
count /= fifo_level * serializers;
|
||||||
|
|
||||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||||
src = dma_pos;
|
src = dma_pos;
|
||||||
dst = prtd->params->dma_addr;
|
dst = prtd->params->dma_addr;
|
||||||
src_bidx = data_type;
|
src_bidx = data_type;
|
||||||
dst_bidx = 0;
|
dst_bidx = 4;
|
||||||
src_cidx = data_type * fifo_level;
|
src_cidx = data_type * fifo_level * serializers;
|
||||||
dst_cidx = 0;
|
dst_cidx = 0;
|
||||||
} else {
|
} else {
|
||||||
src = prtd->params->dma_addr;
|
src = prtd->params->dma_addr;
|
||||||
|
@ -209,7 +210,7 @@ static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream)
|
||||||
src_bidx = 0;
|
src_bidx = 0;
|
||||||
dst_bidx = data_type;
|
dst_bidx = data_type;
|
||||||
src_cidx = 0;
|
src_cidx = 0;
|
||||||
dst_cidx = data_type * fifo_level;
|
dst_cidx = data_type * fifo_level * serializers;
|
||||||
}
|
}
|
||||||
|
|
||||||
acnt = prtd->params->acnt;
|
acnt = prtd->params->acnt;
|
||||||
|
@ -223,9 +224,10 @@ static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream)
|
||||||
edma_set_transfer_params(prtd->asp_link[0], acnt, count, 1, 0,
|
edma_set_transfer_params(prtd->asp_link[0], acnt, count, 1, 0,
|
||||||
ASYNC);
|
ASYNC);
|
||||||
else
|
else
|
||||||
edma_set_transfer_params(prtd->asp_link[0], acnt, fifo_level,
|
edma_set_transfer_params(prtd->asp_link[0], acnt,
|
||||||
count, fifo_level,
|
fifo_level * serializers,
|
||||||
ABSYNC);
|
count, fifo_level * serializers,
|
||||||
|
ABSYNC);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void davinci_pcm_dma_irq(unsigned link, u16 ch_status, void *data)
|
static void davinci_pcm_dma_irq(unsigned link, u16 ch_status, void *data)
|
||||||
|
|
|
@ -27,6 +27,7 @@ struct davinci_pcm_dma_params {
|
||||||
unsigned char data_type; /* xfer data type */
|
unsigned char data_type; /* xfer data type */
|
||||||
unsigned char convert_mono_stereo;
|
unsigned char convert_mono_stereo;
|
||||||
unsigned int fifo_level;
|
unsigned int fifo_level;
|
||||||
|
unsigned char active_serializers; /* num. of active audio serializers */
|
||||||
};
|
};
|
||||||
|
|
||||||
int davinci_soc_platform_register(struct device *dev);
|
int davinci_soc_platform_register(struct device *dev);
|
||||||
|
|
Loading…
Reference in New Issue