Merge remote-tracking branches 'asoc/topic/davinci', 'asoc/topic/doc', 'asoc/topic/dpcm', 'asoc/topic/dwc' and 'asoc/topic/fsi' into asoc-next
This commit is contained in:
Коммит
fed25395ff
|
@ -32,7 +32,7 @@ Optional properties:
|
|||
- rx-num-evt : FIFO levels.
|
||||
- sram-size-playback : size of sram to be allocated during playback
|
||||
- sram-size-capture : size of sram to be allocated during capture
|
||||
- interrupts : Interrupt numbers for McASP, currently not used by the driver
|
||||
- interrupts : Interrupt numbers for McASP
|
||||
- interrupt-names : Known interrupt names are "tx" and "rx"
|
||||
- pinctrl-0: Should specify pin control group used for this controller.
|
||||
- pinctrl-names: Should contain only one value - "default", for more details
|
||||
|
|
|
@ -70,6 +70,7 @@ struct davinci_mcasp {
|
|||
void __iomem *base;
|
||||
u32 fifo_base;
|
||||
struct device *dev;
|
||||
struct snd_pcm_substream *substreams[2];
|
||||
|
||||
/* McASP specific data */
|
||||
int tdm_slots;
|
||||
|
@ -80,6 +81,7 @@ struct davinci_mcasp {
|
|||
u8 bclk_div;
|
||||
u16 bclk_lrclk_ratio;
|
||||
int streams;
|
||||
u32 irq_request[2];
|
||||
|
||||
int sysclk_freq;
|
||||
bool bclk_master;
|
||||
|
@ -90,6 +92,9 @@ struct davinci_mcasp {
|
|||
|
||||
bool dat_port;
|
||||
|
||||
/* Used for comstraint setting on the second stream */
|
||||
u32 channels;
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
struct davinci_mcasp_context context;
|
||||
#endif
|
||||
|
@ -154,6 +159,13 @@ static bool mcasp_is_synchronous(struct davinci_mcasp *mcasp)
|
|||
|
||||
static void mcasp_start_rx(struct davinci_mcasp *mcasp)
|
||||
{
|
||||
if (mcasp->rxnumevt) { /* enable FIFO */
|
||||
u32 reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET;
|
||||
|
||||
mcasp_clr_bits(mcasp, reg, FIFO_ENABLE);
|
||||
mcasp_set_bits(mcasp, reg, FIFO_ENABLE);
|
||||
}
|
||||
|
||||
/* Start clocks */
|
||||
mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXHCLKRST);
|
||||
mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXCLKRST);
|
||||
|
@ -175,12 +187,23 @@ static void mcasp_start_rx(struct davinci_mcasp *mcasp)
|
|||
mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLR_REG, RXFSRST);
|
||||
if (mcasp_is_synchronous(mcasp))
|
||||
mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXFSRST);
|
||||
|
||||
/* enable receive IRQs */
|
||||
mcasp_set_bits(mcasp, DAVINCI_MCASP_EVTCTLR_REG,
|
||||
mcasp->irq_request[SNDRV_PCM_STREAM_CAPTURE]);
|
||||
}
|
||||
|
||||
static void mcasp_start_tx(struct davinci_mcasp *mcasp)
|
||||
{
|
||||
u32 cnt;
|
||||
|
||||
if (mcasp->txnumevt) { /* enable FIFO */
|
||||
u32 reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET;
|
||||
|
||||
mcasp_clr_bits(mcasp, reg, FIFO_ENABLE);
|
||||
mcasp_set_bits(mcasp, reg, FIFO_ENABLE);
|
||||
}
|
||||
|
||||
/* Start clocks */
|
||||
mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST);
|
||||
mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST);
|
||||
|
@ -197,33 +220,28 @@ static void mcasp_start_tx(struct davinci_mcasp *mcasp)
|
|||
mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXSMRST);
|
||||
/* Release Frame Sync generator */
|
||||
mcasp_set_ctl_reg(mcasp, DAVINCI_MCASP_GBLCTLX_REG, TXFSRST);
|
||||
|
||||
/* enable transmit IRQs */
|
||||
mcasp_set_bits(mcasp, DAVINCI_MCASP_EVTCTLX_REG,
|
||||
mcasp->irq_request[SNDRV_PCM_STREAM_PLAYBACK]);
|
||||
}
|
||||
|
||||
static void davinci_mcasp_start(struct davinci_mcasp *mcasp, int stream)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
mcasp->streams++;
|
||||
|
||||
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
if (mcasp->txnumevt) { /* enable FIFO */
|
||||
reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET;
|
||||
mcasp_clr_bits(mcasp, reg, FIFO_ENABLE);
|
||||
mcasp_set_bits(mcasp, reg, FIFO_ENABLE);
|
||||
}
|
||||
if (stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||
mcasp_start_tx(mcasp);
|
||||
} else {
|
||||
if (mcasp->rxnumevt) { /* enable FIFO */
|
||||
reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET;
|
||||
mcasp_clr_bits(mcasp, reg, FIFO_ENABLE);
|
||||
mcasp_set_bits(mcasp, reg, FIFO_ENABLE);
|
||||
}
|
||||
else
|
||||
mcasp_start_rx(mcasp);
|
||||
}
|
||||
}
|
||||
|
||||
static void mcasp_stop_rx(struct davinci_mcasp *mcasp)
|
||||
{
|
||||
/* disable IRQ sources */
|
||||
mcasp_clr_bits(mcasp, DAVINCI_MCASP_EVTCTLR_REG,
|
||||
mcasp->irq_request[SNDRV_PCM_STREAM_CAPTURE]);
|
||||
|
||||
/*
|
||||
* In synchronous mode stop the TX clocks if no other stream is
|
||||
* running
|
||||
|
@ -245,6 +263,10 @@ static void mcasp_stop_tx(struct davinci_mcasp *mcasp)
|
|||
{
|
||||
u32 val = 0;
|
||||
|
||||
/* disable IRQ sources */
|
||||
mcasp_clr_bits(mcasp, DAVINCI_MCASP_EVTCTLX_REG,
|
||||
mcasp->irq_request[SNDRV_PCM_STREAM_PLAYBACK]);
|
||||
|
||||
/*
|
||||
* In synchronous mode keep TX clocks running if the capture stream is
|
||||
* still running.
|
||||
|
@ -272,6 +294,76 @@ static void davinci_mcasp_stop(struct davinci_mcasp *mcasp, int stream)
|
|||
mcasp_stop_rx(mcasp);
|
||||
}
|
||||
|
||||
static irqreturn_t davinci_mcasp_tx_irq_handler(int irq, void *data)
|
||||
{
|
||||
struct davinci_mcasp *mcasp = (struct davinci_mcasp *)data;
|
||||
struct snd_pcm_substream *substream;
|
||||
u32 irq_mask = mcasp->irq_request[SNDRV_PCM_STREAM_PLAYBACK];
|
||||
u32 handled_mask = 0;
|
||||
u32 stat;
|
||||
|
||||
stat = mcasp_get_reg(mcasp, DAVINCI_MCASP_TXSTAT_REG);
|
||||
if (stat & XUNDRN & irq_mask) {
|
||||
dev_warn(mcasp->dev, "Transmit buffer underflow\n");
|
||||
handled_mask |= XUNDRN;
|
||||
|
||||
substream = mcasp->substreams[SNDRV_PCM_STREAM_PLAYBACK];
|
||||
if (substream) {
|
||||
snd_pcm_stream_lock_irq(substream);
|
||||
if (snd_pcm_running(substream))
|
||||
snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
|
||||
snd_pcm_stream_unlock_irq(substream);
|
||||
}
|
||||
}
|
||||
|
||||
if (!handled_mask)
|
||||
dev_warn(mcasp->dev, "unhandled tx event. txstat: 0x%08x\n",
|
||||
stat);
|
||||
|
||||
if (stat & XRERR)
|
||||
handled_mask |= XRERR;
|
||||
|
||||
/* Ack the handled event only */
|
||||
mcasp_set_reg(mcasp, DAVINCI_MCASP_TXSTAT_REG, handled_mask);
|
||||
|
||||
return IRQ_RETVAL(handled_mask);
|
||||
}
|
||||
|
||||
static irqreturn_t davinci_mcasp_rx_irq_handler(int irq, void *data)
|
||||
{
|
||||
struct davinci_mcasp *mcasp = (struct davinci_mcasp *)data;
|
||||
struct snd_pcm_substream *substream;
|
||||
u32 irq_mask = mcasp->irq_request[SNDRV_PCM_STREAM_CAPTURE];
|
||||
u32 handled_mask = 0;
|
||||
u32 stat;
|
||||
|
||||
stat = mcasp_get_reg(mcasp, DAVINCI_MCASP_RXSTAT_REG);
|
||||
if (stat & ROVRN & irq_mask) {
|
||||
dev_warn(mcasp->dev, "Receive buffer overflow\n");
|
||||
handled_mask |= ROVRN;
|
||||
|
||||
substream = mcasp->substreams[SNDRV_PCM_STREAM_CAPTURE];
|
||||
if (substream) {
|
||||
snd_pcm_stream_lock_irq(substream);
|
||||
if (snd_pcm_running(substream))
|
||||
snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
|
||||
snd_pcm_stream_unlock_irq(substream);
|
||||
}
|
||||
}
|
||||
|
||||
if (!handled_mask)
|
||||
dev_warn(mcasp->dev, "unhandled rx event. rxstat: 0x%08x\n",
|
||||
stat);
|
||||
|
||||
if (stat & XRERR)
|
||||
handled_mask |= XRERR;
|
||||
|
||||
/* Ack the handled event only */
|
||||
mcasp_set_reg(mcasp, DAVINCI_MCASP_RXSTAT_REG, handled_mask);
|
||||
|
||||
return IRQ_RETVAL(handled_mask);
|
||||
}
|
||||
|
||||
static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
|
||||
unsigned int fmt)
|
||||
{
|
||||
|
@ -634,19 +726,29 @@ static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int mcasp_i2s_hw_param(struct davinci_mcasp *mcasp, int stream)
|
||||
static int mcasp_i2s_hw_param(struct davinci_mcasp *mcasp, int stream,
|
||||
int channels)
|
||||
{
|
||||
int i, active_slots;
|
||||
int total_slots;
|
||||
int active_serializers;
|
||||
u32 mask = 0;
|
||||
u32 busel = 0;
|
||||
|
||||
if ((mcasp->tdm_slots < 2) || (mcasp->tdm_slots > 32)) {
|
||||
dev_err(mcasp->dev, "tdm slot %d not supported\n",
|
||||
mcasp->tdm_slots);
|
||||
return -EINVAL;
|
||||
}
|
||||
total_slots = mcasp->tdm_slots;
|
||||
|
||||
/*
|
||||
* If more than one serializer is needed, then use them with
|
||||
* their specified tdm_slots count. Otherwise, one serializer
|
||||
* can cope with the transaction using as many slots as channels
|
||||
* in the stream, requires channels symmetry
|
||||
*/
|
||||
active_serializers = (channels + total_slots - 1) / total_slots;
|
||||
if (active_serializers == 1)
|
||||
active_slots = channels;
|
||||
else
|
||||
active_slots = total_slots;
|
||||
|
||||
active_slots = (mcasp->tdm_slots > 31) ? 32 : mcasp->tdm_slots;
|
||||
for (i = 0; i < active_slots; i++)
|
||||
mask |= (1 << i);
|
||||
|
||||
|
@ -658,12 +760,12 @@ static int mcasp_i2s_hw_param(struct davinci_mcasp *mcasp, int stream)
|
|||
mcasp_set_reg(mcasp, DAVINCI_MCASP_TXTDM_REG, mask);
|
||||
mcasp_set_bits(mcasp, DAVINCI_MCASP_TXFMT_REG, busel | TXORD);
|
||||
mcasp_mod_bits(mcasp, DAVINCI_MCASP_TXFMCTL_REG,
|
||||
FSXMOD(mcasp->tdm_slots), FSXMOD(0x1FF));
|
||||
FSXMOD(total_slots), FSXMOD(0x1FF));
|
||||
|
||||
mcasp_set_reg(mcasp, DAVINCI_MCASP_RXTDM_REG, mask);
|
||||
mcasp_set_bits(mcasp, DAVINCI_MCASP_RXFMT_REG, busel | RXORD);
|
||||
mcasp_mod_bits(mcasp, DAVINCI_MCASP_RXFMCTL_REG,
|
||||
FSRMOD(mcasp->tdm_slots), FSRMOD(0x1FF));
|
||||
FSRMOD(total_slots), FSRMOD(0x1FF));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -777,7 +879,8 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
|
|||
if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE)
|
||||
ret = mcasp_dit_hw_param(mcasp, params_rate(params));
|
||||
else
|
||||
ret = mcasp_i2s_hw_param(mcasp, substream->stream);
|
||||
ret = mcasp_i2s_hw_param(mcasp, substream->stream,
|
||||
channels);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
@ -825,6 +928,9 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
|
|||
|
||||
davinci_config_channel_size(mcasp, word_length);
|
||||
|
||||
if (mcasp->op_mode == DAVINCI_MCASP_IIS_MODE)
|
||||
mcasp->channels = channels;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -853,7 +959,65 @@ static int davinci_mcasp_trigger(struct snd_pcm_substream *substream,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int davinci_mcasp_startup(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_dai *cpu_dai)
|
||||
{
|
||||
struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai);
|
||||
u32 max_channels = 0;
|
||||
int i, dir;
|
||||
|
||||
mcasp->substreams[substream->stream] = substream;
|
||||
|
||||
if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Limit the maximum allowed channels for the first stream:
|
||||
* number of serializers for the direction * tdm slots per serializer
|
||||
*/
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||
dir = TX_MODE;
|
||||
else
|
||||
dir = RX_MODE;
|
||||
|
||||
for (i = 0; i < mcasp->num_serializer; i++) {
|
||||
if (mcasp->serial_dir[i] == dir)
|
||||
max_channels++;
|
||||
}
|
||||
max_channels *= mcasp->tdm_slots;
|
||||
/*
|
||||
* If the already active stream has less channels than the calculated
|
||||
* limnit based on the seirializers * tdm_slots, we need to use that as
|
||||
* a constraint for the second stream.
|
||||
* Otherwise (first stream or less allowed channels) we use the
|
||||
* calculated constraint.
|
||||
*/
|
||||
if (mcasp->channels && mcasp->channels < max_channels)
|
||||
max_channels = mcasp->channels;
|
||||
|
||||
snd_pcm_hw_constraint_minmax(substream->runtime,
|
||||
SNDRV_PCM_HW_PARAM_CHANNELS,
|
||||
2, max_channels);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void davinci_mcasp_shutdown(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_dai *cpu_dai)
|
||||
{
|
||||
struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(cpu_dai);
|
||||
|
||||
mcasp->substreams[substream->stream] = NULL;
|
||||
|
||||
if (mcasp->op_mode == DAVINCI_MCASP_DIT_MODE)
|
||||
return;
|
||||
|
||||
if (!cpu_dai->active)
|
||||
mcasp->channels = 0;
|
||||
}
|
||||
|
||||
static const struct snd_soc_dai_ops davinci_mcasp_dai_ops = {
|
||||
.startup = davinci_mcasp_startup,
|
||||
.shutdown = davinci_mcasp_shutdown,
|
||||
.trigger = davinci_mcasp_trigger,
|
||||
.hw_params = davinci_mcasp_hw_params,
|
||||
.set_fmt = davinci_mcasp_set_dai_fmt,
|
||||
|
@ -1194,6 +1358,8 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
|
|||
struct resource *mem, *ioarea, *res, *dat;
|
||||
struct davinci_mcasp_pdata *pdata;
|
||||
struct davinci_mcasp *mcasp;
|
||||
char *irq_name;
|
||||
int irq;
|
||||
int ret;
|
||||
|
||||
if (!pdev->dev.platform_data && !pdev->dev.of_node) {
|
||||
|
@ -1247,7 +1413,21 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
mcasp->op_mode = pdata->op_mode;
|
||||
mcasp->tdm_slots = pdata->tdm_slots;
|
||||
/* sanity check for tdm slots parameter */
|
||||
if (mcasp->op_mode == DAVINCI_MCASP_IIS_MODE) {
|
||||
if (pdata->tdm_slots < 2) {
|
||||
dev_err(&pdev->dev, "invalid tdm slots: %d\n",
|
||||
pdata->tdm_slots);
|
||||
mcasp->tdm_slots = 2;
|
||||
} else if (pdata->tdm_slots > 32) {
|
||||
dev_err(&pdev->dev, "invalid tdm slots: %d\n",
|
||||
pdata->tdm_slots);
|
||||
mcasp->tdm_slots = 32;
|
||||
} else {
|
||||
mcasp->tdm_slots = pdata->tdm_slots;
|
||||
}
|
||||
}
|
||||
|
||||
mcasp->num_serializer = pdata->num_serializer;
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
mcasp->context.xrsr_regs = devm_kzalloc(&pdev->dev,
|
||||
|
@ -1261,6 +1441,36 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
|
|||
|
||||
mcasp->dev = &pdev->dev;
|
||||
|
||||
irq = platform_get_irq_byname(pdev, "rx");
|
||||
if (irq >= 0) {
|
||||
irq_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s_rx\n",
|
||||
dev_name(&pdev->dev));
|
||||
ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
|
||||
davinci_mcasp_rx_irq_handler,
|
||||
IRQF_ONESHOT, irq_name, mcasp);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "RX IRQ request failed\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
mcasp->irq_request[SNDRV_PCM_STREAM_CAPTURE] = ROVRN;
|
||||
}
|
||||
|
||||
irq = platform_get_irq_byname(pdev, "tx");
|
||||
if (irq >= 0) {
|
||||
irq_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s_tx\n",
|
||||
dev_name(&pdev->dev));
|
||||
ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
|
||||
davinci_mcasp_tx_irq_handler,
|
||||
IRQF_ONESHOT, irq_name, mcasp);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "TX IRQ request failed\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
mcasp->irq_request[SNDRV_PCM_STREAM_PLAYBACK] = XUNDRN;
|
||||
}
|
||||
|
||||
dat = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dat");
|
||||
if (dat)
|
||||
mcasp->dat_port = true;
|
||||
|
|
|
@ -256,6 +256,7 @@
|
|||
* DAVINCI_MCASP_TXSTAT_REG - Transmitter Status Register Bits
|
||||
* DAVINCI_MCASP_RXSTAT_REG - Receiver Status Register Bits
|
||||
*/
|
||||
#define XRERR BIT(8) /* Transmit/Receive error */
|
||||
#define XRDATA BIT(5) /* Transmit/Receive data ready */
|
||||
|
||||
/*
|
||||
|
@ -284,6 +285,16 @@
|
|||
*/
|
||||
#define TXDATADMADIS BIT(0)
|
||||
|
||||
/*
|
||||
* DAVINCI_MCASP_EVTCTLR_REG - Receiver Interrupt Control Register Bits
|
||||
*/
|
||||
#define ROVRN BIT(0)
|
||||
|
||||
/*
|
||||
* DAVINCI_MCASP_EVTCTLX_REG - Transmitter Interrupt Control Register Bits
|
||||
*/
|
||||
#define XUNDRN BIT(0)
|
||||
|
||||
/*
|
||||
* DAVINCI_MCASP_W[R]FIFOCTL - Write/Read FIFO Control Register bits
|
||||
*/
|
||||
|
|
|
@ -338,31 +338,34 @@ static int dw_i2s_probe(struct platform_device *pdev)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
dev_err(&pdev->dev, "no i2s resource defined\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (!devm_request_mem_region(&pdev->dev, res->start,
|
||||
resource_size(res), pdev->name)) {
|
||||
dev_err(&pdev->dev, "i2s region already claimed\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
|
||||
if (!dev) {
|
||||
dev_warn(&pdev->dev, "kzalloc fail\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
dev->i2s_base = devm_ioremap(&pdev->dev, res->start,
|
||||
resource_size(res));
|
||||
if (!dev->i2s_base) {
|
||||
dev_err(&pdev->dev, "ioremap fail for i2s_region\n");
|
||||
dw_i2s_dai = devm_kzalloc(&pdev->dev, sizeof(*dw_i2s_dai), GFP_KERNEL);
|
||||
if (!dw_i2s_dai) {
|
||||
dev_err(&pdev->dev, "mem allocation failed for dai driver\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
dw_i2s_dai->ops = &dw_i2s_dai_ops;
|
||||
dw_i2s_dai->suspend = dw_i2s_suspend;
|
||||
dw_i2s_dai->resume = dw_i2s_resume;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
dev_err(&pdev->dev, "no i2s resource defined\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
dev->i2s_base = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(dev->i2s_base)) {
|
||||
dev_err(&pdev->dev, "ioremap fail for i2s_region\n");
|
||||
return PTR_ERR(dev->i2s_base);
|
||||
}
|
||||
|
||||
cap = pdata->cap;
|
||||
dev->capability = cap;
|
||||
dev->i2s_clk_cfg = pdata->i2s_clk_cfg;
|
||||
|
@ -388,13 +391,6 @@ static int dw_i2s_probe(struct platform_device *pdev)
|
|||
if (ret < 0)
|
||||
goto err_clk_put;
|
||||
|
||||
dw_i2s_dai = devm_kzalloc(&pdev->dev, sizeof(*dw_i2s_dai), GFP_KERNEL);
|
||||
if (!dw_i2s_dai) {
|
||||
dev_err(&pdev->dev, "mem allocation failed for dai driver\n");
|
||||
ret = -ENOMEM;
|
||||
goto err_clk_disable;
|
||||
}
|
||||
|
||||
if (cap & DWC_I2S_PLAY) {
|
||||
dev_dbg(&pdev->dev, " designware: play supported\n");
|
||||
dw_i2s_dai->playback.channels_min = MIN_CHANNEL_NUM;
|
||||
|
@ -411,10 +407,6 @@ static int dw_i2s_probe(struct platform_device *pdev)
|
|||
dw_i2s_dai->capture.rates = pdata->snd_rates;
|
||||
}
|
||||
|
||||
dw_i2s_dai->ops = &dw_i2s_dai_ops;
|
||||
dw_i2s_dai->suspend = dw_i2s_suspend;
|
||||
dw_i2s_dai->resume = dw_i2s_resume;
|
||||
|
||||
dev->dev = &pdev->dev;
|
||||
dev_set_drvdata(&pdev->dev, dev);
|
||||
ret = snd_soc_register_component(&pdev->dev, &dw_i2s_component,
|
||||
|
|
|
@ -842,12 +842,9 @@ static int fsi_clk_disable(struct device *dev,
|
|||
return -EINVAL;
|
||||
|
||||
if (1 == clock->count--) {
|
||||
if (clock->xck)
|
||||
clk_disable(clock->xck);
|
||||
if (clock->ick)
|
||||
clk_disable(clock->ick);
|
||||
if (clock->div)
|
||||
clk_disable(clock->div);
|
||||
clk_disable(clock->xck);
|
||||
clk_disable(clock->ick);
|
||||
clk_disable(clock->div);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -116,7 +116,7 @@ EXPORT_SYMBOL_GPL(snd_soc_jack_report);
|
|||
*
|
||||
* @jack: ASoC jack
|
||||
* @count: Number of zones
|
||||
* @zone: Array of zones
|
||||
* @zones: Array of zones
|
||||
*
|
||||
* After this function has been called the zones specified in the
|
||||
* array will be associated with the jack.
|
||||
|
|
|
@ -2295,7 +2295,13 @@ int soc_dpcm_runtime_update(struct snd_soc_card *card)
|
|||
fe->dai_link->name);
|
||||
|
||||
/* skip if FE doesn't have playback capability */
|
||||
if (!fe->cpu_dai->driver->playback.channels_min)
|
||||
if (!fe->cpu_dai->driver->playback.channels_min
|
||||
|| !fe->codec_dai->driver->playback.channels_min)
|
||||
goto capture;
|
||||
|
||||
/* skip if FE isn't currently playing */
|
||||
if (!fe->cpu_dai->playback_active
|
||||
|| !fe->codec_dai->playback_active)
|
||||
goto capture;
|
||||
|
||||
paths = dpcm_path_get(fe, SNDRV_PCM_STREAM_PLAYBACK, &list);
|
||||
|
@ -2325,7 +2331,13 @@ int soc_dpcm_runtime_update(struct snd_soc_card *card)
|
|||
dpcm_path_put(&list);
|
||||
capture:
|
||||
/* skip if FE doesn't have capture capability */
|
||||
if (!fe->cpu_dai->driver->capture.channels_min)
|
||||
if (!fe->cpu_dai->driver->capture.channels_min
|
||||
|| !fe->codec_dai->driver->capture.channels_min)
|
||||
continue;
|
||||
|
||||
/* skip if FE isn't currently capturing */
|
||||
if (!fe->cpu_dai->capture_active
|
||||
|| !fe->codec_dai->capture_active)
|
||||
continue;
|
||||
|
||||
paths = dpcm_path_get(fe, SNDRV_PCM_STREAM_CAPTURE, &list);
|
||||
|
|
Загрузка…
Ссылка в новой задаче