Loading Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt +1 −1 Original line number Diff line number Diff line Loading @@ -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 Loading sound/soc/davinci/davinci-mcasp.c +236 −26 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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 Loading Loading @@ -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); Loading @@ -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); Loading @@ -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 Loading @@ -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. Loading Loading @@ -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) { Loading Loading @@ -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); Loading @@ -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; } Loading Loading @@ -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; Loading Loading @@ -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; } Loading Loading @@ -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, Loading Loading @@ -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) { Loading Loading @@ -1247,7 +1413,21 @@ static int davinci_mcasp_probe(struct platform_device *pdev) } mcasp->op_mode = pdata->op_mode; /* 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, Loading @@ -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; Loading sound/soc/davinci/davinci-mcasp.h +11 −0 Original line number Diff line number Diff line Loading @@ -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 */ /* Loading Loading @@ -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 */ Loading sound/soc/dwc/designware_i2s.c +19 −27 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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, Loading sound/soc/sh/fsi.c +3 −6 Original line number Diff line number Diff line Loading @@ -842,11 +842,8 @@ 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); } Loading Loading
Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt +1 −1 Original line number Diff line number Diff line Loading @@ -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 Loading
sound/soc/davinci/davinci-mcasp.c +236 −26 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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 Loading Loading @@ -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); Loading @@ -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); Loading @@ -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 Loading @@ -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. Loading Loading @@ -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) { Loading Loading @@ -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); Loading @@ -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; } Loading Loading @@ -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; Loading Loading @@ -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; } Loading Loading @@ -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, Loading Loading @@ -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) { Loading Loading @@ -1247,7 +1413,21 @@ static int davinci_mcasp_probe(struct platform_device *pdev) } mcasp->op_mode = pdata->op_mode; /* 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, Loading @@ -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; Loading
sound/soc/davinci/davinci-mcasp.h +11 −0 Original line number Diff line number Diff line Loading @@ -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 */ /* Loading Loading @@ -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 */ Loading
sound/soc/dwc/designware_i2s.c +19 −27 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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, Loading
sound/soc/sh/fsi.c +3 −6 Original line number Diff line number Diff line Loading @@ -842,11 +842,8 @@ 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); } Loading