^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * omap-mcbsp.c -- OMAP ALSA SoC DAI driver using McBSP port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2008 Nokia Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Contact: Jarkko Nikula <jarkko.nikula@bitmer.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Peter Ujfalusi <peter.ujfalusi@ti.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/pm_runtime.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/of_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <sound/core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <sound/pcm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <sound/pcm_params.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <sound/initval.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <sound/soc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <sound/dmaengine_pcm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include "omap-mcbsp-priv.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include "omap-mcbsp.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include "sdma-pcm.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define OMAP_MCBSP_RATES (SNDRV_PCM_RATE_8000_96000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) OMAP_MCBSP_WORD_8 = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) OMAP_MCBSP_WORD_12,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) OMAP_MCBSP_WORD_16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) OMAP_MCBSP_WORD_20,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) OMAP_MCBSP_WORD_24,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) OMAP_MCBSP_WORD_32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) static void omap_mcbsp_dump_reg(struct omap_mcbsp *mcbsp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) dev_dbg(mcbsp->dev, "**** McBSP%d regs ****\n", mcbsp->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) dev_dbg(mcbsp->dev, "DRR2: 0x%04x\n", MCBSP_READ(mcbsp, DRR2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) dev_dbg(mcbsp->dev, "DRR1: 0x%04x\n", MCBSP_READ(mcbsp, DRR1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) dev_dbg(mcbsp->dev, "DXR2: 0x%04x\n", MCBSP_READ(mcbsp, DXR2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) dev_dbg(mcbsp->dev, "DXR1: 0x%04x\n", MCBSP_READ(mcbsp, DXR1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) dev_dbg(mcbsp->dev, "SPCR2: 0x%04x\n", MCBSP_READ(mcbsp, SPCR2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) dev_dbg(mcbsp->dev, "SPCR1: 0x%04x\n", MCBSP_READ(mcbsp, SPCR1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) dev_dbg(mcbsp->dev, "RCR2: 0x%04x\n", MCBSP_READ(mcbsp, RCR2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) dev_dbg(mcbsp->dev, "RCR1: 0x%04x\n", MCBSP_READ(mcbsp, RCR1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) dev_dbg(mcbsp->dev, "XCR2: 0x%04x\n", MCBSP_READ(mcbsp, XCR2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) dev_dbg(mcbsp->dev, "XCR1: 0x%04x\n", MCBSP_READ(mcbsp, XCR1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) dev_dbg(mcbsp->dev, "SRGR2: 0x%04x\n", MCBSP_READ(mcbsp, SRGR2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) dev_dbg(mcbsp->dev, "SRGR1: 0x%04x\n", MCBSP_READ(mcbsp, SRGR1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) dev_dbg(mcbsp->dev, "PCR0: 0x%04x\n", MCBSP_READ(mcbsp, PCR0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) dev_dbg(mcbsp->dev, "***********************\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) static int omap2_mcbsp_set_clks_src(struct omap_mcbsp *mcbsp, u8 fck_src_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) struct clk *fck_src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) const char *src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) int r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) if (fck_src_id == MCBSP_CLKS_PAD_SRC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) src = "pad_fck";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) else if (fck_src_id == MCBSP_CLKS_PRCM_SRC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) src = "prcm_fck";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) fck_src = clk_get(mcbsp->dev, src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) if (IS_ERR(fck_src)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) dev_err(mcbsp->dev, "CLKS: could not clk_get() %s\n", src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) pm_runtime_put_sync(mcbsp->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) r = clk_set_parent(mcbsp->fclk, fck_src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) if (r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) dev_err(mcbsp->dev, "CLKS: could not clk_set_parent() to %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) pm_runtime_get_sync(mcbsp->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) clk_put(fck_src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) return r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) static irqreturn_t omap_mcbsp_irq_handler(int irq, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) struct omap_mcbsp *mcbsp = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) u16 irqst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) irqst = MCBSP_READ(mcbsp, IRQST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) dev_dbg(mcbsp->dev, "IRQ callback : 0x%x\n", irqst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) if (irqst & RSYNCERREN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) dev_err(mcbsp->dev, "RX Frame Sync Error!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) if (irqst & RFSREN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) dev_dbg(mcbsp->dev, "RX Frame Sync\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) if (irqst & REOFEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) dev_dbg(mcbsp->dev, "RX End Of Frame\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) if (irqst & RRDYEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) dev_dbg(mcbsp->dev, "RX Buffer Threshold Reached\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) if (irqst & RUNDFLEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) dev_err(mcbsp->dev, "RX Buffer Underflow!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) if (irqst & ROVFLEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) dev_err(mcbsp->dev, "RX Buffer Overflow!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) if (irqst & XSYNCERREN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) dev_err(mcbsp->dev, "TX Frame Sync Error!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) if (irqst & XFSXEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) dev_dbg(mcbsp->dev, "TX Frame Sync\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) if (irqst & XEOFEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) dev_dbg(mcbsp->dev, "TX End Of Frame\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) if (irqst & XRDYEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) dev_dbg(mcbsp->dev, "TX Buffer threshold Reached\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) if (irqst & XUNDFLEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) dev_err(mcbsp->dev, "TX Buffer Underflow!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) if (irqst & XOVFLEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) dev_err(mcbsp->dev, "TX Buffer Overflow!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) if (irqst & XEMPTYEOFEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) dev_dbg(mcbsp->dev, "TX Buffer empty at end of frame\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) MCBSP_WRITE(mcbsp, IRQST, irqst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) static irqreturn_t omap_mcbsp_tx_irq_handler(int irq, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) struct omap_mcbsp *mcbsp = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) u16 irqst_spcr2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) irqst_spcr2 = MCBSP_READ(mcbsp, SPCR2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) dev_dbg(mcbsp->dev, "TX IRQ callback : 0x%x\n", irqst_spcr2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) if (irqst_spcr2 & XSYNC_ERR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) dev_err(mcbsp->dev, "TX Frame Sync Error! : 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) irqst_spcr2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) /* Writing zero to XSYNC_ERR clears the IRQ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) MCBSP_WRITE(mcbsp, SPCR2, MCBSP_READ_CACHE(mcbsp, SPCR2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) static irqreturn_t omap_mcbsp_rx_irq_handler(int irq, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) struct omap_mcbsp *mcbsp = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) u16 irqst_spcr1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) irqst_spcr1 = MCBSP_READ(mcbsp, SPCR1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) dev_dbg(mcbsp->dev, "RX IRQ callback : 0x%x\n", irqst_spcr1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) if (irqst_spcr1 & RSYNC_ERR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) dev_err(mcbsp->dev, "RX Frame Sync Error! : 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) irqst_spcr1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) /* Writing zero to RSYNC_ERR clears the IRQ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) MCBSP_WRITE(mcbsp, SPCR1, MCBSP_READ_CACHE(mcbsp, SPCR1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) * omap_mcbsp_config simply write a config to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) * appropriate McBSP.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) * You either call this function or set the McBSP registers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) * by yourself before calling omap_mcbsp_start().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) static void omap_mcbsp_config(struct omap_mcbsp *mcbsp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) const struct omap_mcbsp_reg_cfg *config)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) dev_dbg(mcbsp->dev, "Configuring McBSP%d phys_base: 0x%08lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) mcbsp->id, mcbsp->phys_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) /* We write the given config */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) MCBSP_WRITE(mcbsp, SPCR2, config->spcr2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) MCBSP_WRITE(mcbsp, SPCR1, config->spcr1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) MCBSP_WRITE(mcbsp, RCR2, config->rcr2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) MCBSP_WRITE(mcbsp, RCR1, config->rcr1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) MCBSP_WRITE(mcbsp, XCR2, config->xcr2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) MCBSP_WRITE(mcbsp, XCR1, config->xcr1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) MCBSP_WRITE(mcbsp, SRGR2, config->srgr2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) MCBSP_WRITE(mcbsp, SRGR1, config->srgr1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) MCBSP_WRITE(mcbsp, MCR2, config->mcr2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) MCBSP_WRITE(mcbsp, MCR1, config->mcr1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) MCBSP_WRITE(mcbsp, PCR0, config->pcr0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) if (mcbsp->pdata->has_ccr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) MCBSP_WRITE(mcbsp, XCCR, config->xccr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) MCBSP_WRITE(mcbsp, RCCR, config->rccr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) /* Enable wakeup behavior */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) if (mcbsp->pdata->has_wakeup)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) MCBSP_WRITE(mcbsp, WAKEUPEN, XRDYEN | RRDYEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) /* Enable TX/RX sync error interrupts by default */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) if (mcbsp->irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) MCBSP_WRITE(mcbsp, IRQEN, RSYNCERREN | XSYNCERREN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) RUNDFLEN | ROVFLEN | XUNDFLEN | XOVFLEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) * omap_mcbsp_dma_reg_params - returns the address of mcbsp data register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) * @mcbsp: omap_mcbsp struct for the McBSP instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) * @stream: Stream direction (playback/capture)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) * Returns the address of mcbsp data transmit register or data receive register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) * to be used by DMA for transferring/receiving data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) static int omap_mcbsp_dma_reg_params(struct omap_mcbsp *mcbsp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) unsigned int stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) int data_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) if (mcbsp->pdata->reg_size == 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) data_reg = OMAP_MCBSP_REG_DXR1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) data_reg = OMAP_MCBSP_REG_DXR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) if (mcbsp->pdata->reg_size == 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) data_reg = OMAP_MCBSP_REG_DRR1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) data_reg = OMAP_MCBSP_REG_DRR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) return mcbsp->phys_dma_base + data_reg * mcbsp->pdata->reg_step;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) * omap_mcbsp_set_rx_threshold configures the transmit threshold in words.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) * The threshold parameter is 1 based, and it is converted (threshold - 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) * for the THRSH2 register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) static void omap_mcbsp_set_tx_threshold(struct omap_mcbsp *mcbsp, u16 threshold)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) if (threshold && threshold <= mcbsp->max_tx_thres)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) MCBSP_WRITE(mcbsp, THRSH2, threshold - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) * omap_mcbsp_set_rx_threshold configures the receive threshold in words.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) * The threshold parameter is 1 based, and it is converted (threshold - 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) * for the THRSH1 register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) static void omap_mcbsp_set_rx_threshold(struct omap_mcbsp *mcbsp, u16 threshold)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) if (threshold && threshold <= mcbsp->max_rx_thres)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) MCBSP_WRITE(mcbsp, THRSH1, threshold - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) * omap_mcbsp_get_tx_delay returns the number of used slots in the McBSP FIFO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) static u16 omap_mcbsp_get_tx_delay(struct omap_mcbsp *mcbsp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) u16 buffstat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) /* Returns the number of free locations in the buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) buffstat = MCBSP_READ(mcbsp, XBUFFSTAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) /* Number of slots are different in McBSP ports */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) return mcbsp->pdata->buffer_size - buffstat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) * omap_mcbsp_get_rx_delay returns the number of free slots in the McBSP FIFO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) * to reach the threshold value (when the DMA will be triggered to read it)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) static u16 omap_mcbsp_get_rx_delay(struct omap_mcbsp *mcbsp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) u16 buffstat, threshold;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) /* Returns the number of used locations in the buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) buffstat = MCBSP_READ(mcbsp, RBUFFSTAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) /* RX threshold */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) threshold = MCBSP_READ(mcbsp, THRSH1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) /* Return the number of location till we reach the threshold limit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) if (threshold <= buffstat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) return threshold - buffstat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) static int omap_mcbsp_request(struct omap_mcbsp *mcbsp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) void *reg_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) reg_cache = kzalloc(mcbsp->reg_cache_size, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) if (!reg_cache)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) spin_lock(&mcbsp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) if (!mcbsp->free) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) dev_err(mcbsp->dev, "McBSP%d is currently in use\n", mcbsp->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) err = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) goto err_kfree;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) mcbsp->free = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) mcbsp->reg_cache = reg_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) spin_unlock(&mcbsp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) if(mcbsp->pdata->ops && mcbsp->pdata->ops->request)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) mcbsp->pdata->ops->request(mcbsp->id - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) * Make sure that transmitter, receiver and sample-rate generator are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) * not running before activating IRQs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) MCBSP_WRITE(mcbsp, SPCR1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) MCBSP_WRITE(mcbsp, SPCR2, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) if (mcbsp->irq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) err = request_irq(mcbsp->irq, omap_mcbsp_irq_handler, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) "McBSP", (void *)mcbsp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) if (err != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) dev_err(mcbsp->dev, "Unable to request IRQ\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) goto err_clk_disable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) err = request_irq(mcbsp->tx_irq, omap_mcbsp_tx_irq_handler, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) "McBSP TX", (void *)mcbsp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) if (err != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) dev_err(mcbsp->dev, "Unable to request TX IRQ\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) goto err_clk_disable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) err = request_irq(mcbsp->rx_irq, omap_mcbsp_rx_irq_handler, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) "McBSP RX", (void *)mcbsp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) if (err != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) dev_err(mcbsp->dev, "Unable to request RX IRQ\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) goto err_free_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) err_free_irq:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) free_irq(mcbsp->tx_irq, (void *)mcbsp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) err_clk_disable:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) if(mcbsp->pdata->ops && mcbsp->pdata->ops->free)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) mcbsp->pdata->ops->free(mcbsp->id - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) /* Disable wakeup behavior */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) if (mcbsp->pdata->has_wakeup)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) MCBSP_WRITE(mcbsp, WAKEUPEN, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) spin_lock(&mcbsp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) mcbsp->free = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) mcbsp->reg_cache = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) err_kfree:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) spin_unlock(&mcbsp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) kfree(reg_cache);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) static void omap_mcbsp_free(struct omap_mcbsp *mcbsp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) void *reg_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) if(mcbsp->pdata->ops && mcbsp->pdata->ops->free)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) mcbsp->pdata->ops->free(mcbsp->id - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) /* Disable wakeup behavior */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) if (mcbsp->pdata->has_wakeup)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) MCBSP_WRITE(mcbsp, WAKEUPEN, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) /* Disable interrupt requests */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) if (mcbsp->irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) MCBSP_WRITE(mcbsp, IRQEN, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) if (mcbsp->irq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) free_irq(mcbsp->irq, (void *)mcbsp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) free_irq(mcbsp->rx_irq, (void *)mcbsp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) free_irq(mcbsp->tx_irq, (void *)mcbsp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) reg_cache = mcbsp->reg_cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) * Select CLKS source from internal source unconditionally before
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) * marking the McBSP port as free.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) * If the external clock source via MCBSP_CLKS pin has been selected the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) * system will refuse to enter idle if the CLKS pin source is not reset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) * back to internal source.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) if (!mcbsp_omap1())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) omap2_mcbsp_set_clks_src(mcbsp, MCBSP_CLKS_PRCM_SRC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) spin_lock(&mcbsp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) if (mcbsp->free)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) dev_err(mcbsp->dev, "McBSP%d was not reserved\n", mcbsp->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) mcbsp->free = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) mcbsp->reg_cache = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) spin_unlock(&mcbsp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) kfree(reg_cache);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) * Here we start the McBSP, by enabling transmitter, receiver or both.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) * If no transmitter or receiver is active prior calling, then sample-rate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) * generator and frame sync are started.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) static void omap_mcbsp_start(struct omap_mcbsp *mcbsp, int stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) int tx = (stream == SNDRV_PCM_STREAM_PLAYBACK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) int rx = !tx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) int enable_srg = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) u16 w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) if (mcbsp->st_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) omap_mcbsp_st_start(mcbsp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) /* Only enable SRG, if McBSP is master */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) w = MCBSP_READ_CACHE(mcbsp, PCR0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) if (w & (FSXM | FSRM | CLKXM | CLKRM))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) enable_srg = !((MCBSP_READ_CACHE(mcbsp, SPCR2) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) MCBSP_READ_CACHE(mcbsp, SPCR1)) & 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) if (enable_srg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) /* Start the sample generator */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) w = MCBSP_READ_CACHE(mcbsp, SPCR2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) MCBSP_WRITE(mcbsp, SPCR2, w | (1 << 6));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) /* Enable transmitter and receiver */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) tx &= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) w = MCBSP_READ_CACHE(mcbsp, SPCR2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) MCBSP_WRITE(mcbsp, SPCR2, w | tx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) rx &= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) w = MCBSP_READ_CACHE(mcbsp, SPCR1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) MCBSP_WRITE(mcbsp, SPCR1, w | rx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) * Worst case: CLKSRG*2 = 8000khz: (1/8000) * 2 * 2 usec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) * REVISIT: 100us may give enough time for two CLKSRG, however
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) * due to some unknown PM related, clock gating etc. reason it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) * is now at 500us.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) udelay(500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) if (enable_srg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) /* Start frame sync */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) w = MCBSP_READ_CACHE(mcbsp, SPCR2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) MCBSP_WRITE(mcbsp, SPCR2, w | (1 << 7));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) if (mcbsp->pdata->has_ccr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) /* Release the transmitter and receiver */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) w = MCBSP_READ_CACHE(mcbsp, XCCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) w &= ~(tx ? XDISABLE : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) MCBSP_WRITE(mcbsp, XCCR, w);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) w = MCBSP_READ_CACHE(mcbsp, RCCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) w &= ~(rx ? RDISABLE : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) MCBSP_WRITE(mcbsp, RCCR, w);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) /* Dump McBSP Regs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) omap_mcbsp_dump_reg(mcbsp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) static void omap_mcbsp_stop(struct omap_mcbsp *mcbsp, int stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) int tx = (stream == SNDRV_PCM_STREAM_PLAYBACK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) int rx = !tx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) int idle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) u16 w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) /* Reset transmitter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) tx &= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) if (mcbsp->pdata->has_ccr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) w = MCBSP_READ_CACHE(mcbsp, XCCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) w |= (tx ? XDISABLE : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) MCBSP_WRITE(mcbsp, XCCR, w);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) w = MCBSP_READ_CACHE(mcbsp, SPCR2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) MCBSP_WRITE(mcbsp, SPCR2, w & ~tx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) /* Reset receiver */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) rx &= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) if (mcbsp->pdata->has_ccr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) w = MCBSP_READ_CACHE(mcbsp, RCCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) w |= (rx ? RDISABLE : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) MCBSP_WRITE(mcbsp, RCCR, w);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) w = MCBSP_READ_CACHE(mcbsp, SPCR1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) MCBSP_WRITE(mcbsp, SPCR1, w & ~rx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) idle = !((MCBSP_READ_CACHE(mcbsp, SPCR2) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) MCBSP_READ_CACHE(mcbsp, SPCR1)) & 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) if (idle) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) /* Reset the sample rate generator */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) w = MCBSP_READ_CACHE(mcbsp, SPCR2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) MCBSP_WRITE(mcbsp, SPCR2, w & ~(1 << 6));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) if (mcbsp->st_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) omap_mcbsp_st_stop(mcbsp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) #define max_thres(m) (mcbsp->pdata->buffer_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) #define valid_threshold(m, val) ((val) <= max_thres(m))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) #define THRESHOLD_PROP_BUILDER(prop) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) static ssize_t prop##_show(struct device *dev, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) struct device_attribute *attr, char *buf) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) struct omap_mcbsp *mcbsp = dev_get_drvdata(dev); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) return sprintf(buf, "%u\n", mcbsp->prop); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) static ssize_t prop##_store(struct device *dev, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) struct device_attribute *attr, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) const char *buf, size_t size) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) struct omap_mcbsp *mcbsp = dev_get_drvdata(dev); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) unsigned long val; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) int status; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) status = kstrtoul(buf, 0, &val); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) if (status) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) return status; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) if (!valid_threshold(mcbsp, val)) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) return -EDOM; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) mcbsp->prop = val; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) return size; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) static DEVICE_ATTR(prop, 0644, prop##_show, prop##_store)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) THRESHOLD_PROP_BUILDER(max_tx_thres);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) THRESHOLD_PROP_BUILDER(max_rx_thres);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) static const char * const dma_op_modes[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) "element", "threshold",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) static ssize_t dma_op_mode_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) struct omap_mcbsp *mcbsp = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) int dma_op_mode, i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) ssize_t len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) const char * const *s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) dma_op_mode = mcbsp->dma_op_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) for (s = &dma_op_modes[i]; i < ARRAY_SIZE(dma_op_modes); s++, i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) if (dma_op_mode == i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) len += sprintf(buf + len, "[%s] ", *s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) len += sprintf(buf + len, "%s ", *s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) len += sprintf(buf + len, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) static ssize_t dma_op_mode_store(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) struct device_attribute *attr, const char *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) struct omap_mcbsp *mcbsp = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) i = sysfs_match_string(dma_op_modes, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) if (i < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) return i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) spin_lock_irq(&mcbsp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) if (!mcbsp->free) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) size = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) goto unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) mcbsp->dma_op_mode = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) spin_unlock_irq(&mcbsp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) return size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) static DEVICE_ATTR_RW(dma_op_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) static const struct attribute *additional_attrs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) &dev_attr_max_tx_thres.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) &dev_attr_max_rx_thres.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) &dev_attr_dma_op_mode.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) static const struct attribute_group additional_attr_group = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) .attrs = (struct attribute **)additional_attrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) * McBSP1 and McBSP3 are directly mapped on 1610 and 1510.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) * 730 has only 2 McBSP, and both of them are MPU peripherals.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) static int omap_mcbsp_init(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) struct omap_mcbsp *mcbsp = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) spin_lock_init(&mcbsp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) mcbsp->free = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) if (!res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) mcbsp->io_base = devm_ioremap_resource(&pdev->dev, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) if (IS_ERR(mcbsp->io_base))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) return PTR_ERR(mcbsp->io_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) mcbsp->phys_base = res->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) mcbsp->reg_cache_size = resource_size(res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dma");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) if (!res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) mcbsp->phys_dma_base = mcbsp->phys_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) mcbsp->phys_dma_base = res->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) * OMAP1, 2 uses two interrupt lines: TX, RX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) * OMAP2430, OMAP3 SoC have combined IRQ line as well.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) * OMAP4 and newer SoC only have the combined IRQ line.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) * Use the combined IRQ if available since it gives better debugging
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) * possibilities.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) mcbsp->irq = platform_get_irq_byname(pdev, "common");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) if (mcbsp->irq == -ENXIO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) mcbsp->tx_irq = platform_get_irq_byname(pdev, "tx");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) if (mcbsp->tx_irq == -ENXIO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) mcbsp->irq = platform_get_irq(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) mcbsp->tx_irq = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) mcbsp->rx_irq = platform_get_irq_byname(pdev, "rx");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) mcbsp->irq = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) if (!pdev->dev.of_node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) if (!res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) dev_err(&pdev->dev, "invalid tx DMA channel\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) mcbsp->dma_req[0] = res->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) mcbsp->dma_data[0].filter_data = &mcbsp->dma_req[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) if (!res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) dev_err(&pdev->dev, "invalid rx DMA channel\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) mcbsp->dma_req[1] = res->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) mcbsp->dma_data[1].filter_data = &mcbsp->dma_req[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) mcbsp->dma_data[0].filter_data = "tx";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) mcbsp->dma_data[1].filter_data = "rx";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) mcbsp->dma_data[0].addr = omap_mcbsp_dma_reg_params(mcbsp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) SNDRV_PCM_STREAM_PLAYBACK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) mcbsp->dma_data[1].addr = omap_mcbsp_dma_reg_params(mcbsp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) SNDRV_PCM_STREAM_CAPTURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) mcbsp->fclk = devm_clk_get(&pdev->dev, "fck");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) if (IS_ERR(mcbsp->fclk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) ret = PTR_ERR(mcbsp->fclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) dev_err(mcbsp->dev, "unable to get fck: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) mcbsp->dma_op_mode = MCBSP_DMA_MODE_ELEMENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) if (mcbsp->pdata->buffer_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) * Initially configure the maximum thresholds to a safe value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) * The McBSP FIFO usage with these values should not go under
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) * 16 locations.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) * If the whole FIFO without safety buffer is used, than there
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) * is a possibility that the DMA will be not able to push the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) * new data on time, causing channel shifts in runtime.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) mcbsp->max_tx_thres = max_thres(mcbsp) - 0x10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) mcbsp->max_rx_thres = max_thres(mcbsp) - 0x10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) ret = sysfs_create_group(&mcbsp->dev->kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) &additional_attr_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) dev_err(mcbsp->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) "Unable to create additional controls\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) ret = omap_mcbsp_st_init(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) goto err_st;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) err_st:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) if (mcbsp->pdata->buffer_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) sysfs_remove_group(&mcbsp->dev->kobj, &additional_attr_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) * Stream DMA parameters. DMA request line and port address are set runtime
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) * since they are different between OMAP1 and later OMAPs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) static void omap_mcbsp_set_threshold(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) unsigned int packet_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) int words;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) /* No need to proceed further if McBSP does not have FIFO */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) if (mcbsp->pdata->buffer_size == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) * Configure McBSP threshold based on either:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) * packet_size, when the sDMA is in packet mode, or based on the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) * period size in THRESHOLD mode, otherwise use McBSP threshold = 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) * for mono streams.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) if (packet_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) words = packet_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) words = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) /* Configure McBSP internal buffer usage */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) omap_mcbsp_set_tx_threshold(mcbsp, words);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) omap_mcbsp_set_rx_threshold(mcbsp, words);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) static int omap_mcbsp_hwrule_min_buffersize(struct snd_pcm_hw_params *params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) struct snd_pcm_hw_rule *rule)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) struct snd_interval *buffer_size = hw_param_interval(params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) SNDRV_PCM_HW_PARAM_BUFFER_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) struct snd_interval *channels = hw_param_interval(params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) SNDRV_PCM_HW_PARAM_CHANNELS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) struct omap_mcbsp *mcbsp = rule->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) struct snd_interval frames;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) int size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) snd_interval_any(&frames);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) size = mcbsp->pdata->buffer_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) frames.min = size / channels->min;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) frames.integer = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) return snd_interval_refine(buffer_size, &frames);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) struct snd_soc_dai *cpu_dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) if (!snd_soc_dai_active(cpu_dai))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) err = omap_mcbsp_request(mcbsp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) * OMAP3 McBSP FIFO is word structured.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) * McBSP2 has 1024 + 256 = 1280 word long buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) * McBSP1,3,4,5 has 128 word long buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) * This means that the size of the FIFO depends on the sample format.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) * For example on McBSP3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) * 16bit samples: size is 128 * 2 = 256 bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) * 32bit samples: size is 128 * 4 = 512 bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) * It is simpler to place constraint for buffer and period based on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) * channels.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) * McBSP3 as example again (16 or 32 bit samples):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) * 1 channel (mono): size is 128 frames (128 words)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) * 2 channels (stereo): size is 128 / 2 = 64 frames (2 * 64 words)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) * 4 channels: size is 128 / 4 = 32 frames (4 * 32 words)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) if (mcbsp->pdata->buffer_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) * Rule for the buffer size. We should not allow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) * smaller buffer than the FIFO size to avoid underruns.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) * This applies only for the playback stream.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) snd_pcm_hw_rule_add(substream->runtime, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) omap_mcbsp_hwrule_min_buffersize,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) mcbsp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) SNDRV_PCM_HW_PARAM_CHANNELS, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) /* Make sure, that the period size is always even */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) snd_pcm_hw_constraint_step(substream->runtime, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) static void omap_mcbsp_dai_shutdown(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) struct snd_soc_dai *cpu_dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) int tx = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) int stream1 = tx ? SNDRV_PCM_STREAM_PLAYBACK : SNDRV_PCM_STREAM_CAPTURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) int stream2 = tx ? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) if (mcbsp->latency[stream2])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) cpu_latency_qos_update_request(&mcbsp->pm_qos_req,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) mcbsp->latency[stream2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) else if (mcbsp->latency[stream1])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) cpu_latency_qos_remove_request(&mcbsp->pm_qos_req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) mcbsp->latency[stream1] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) if (!snd_soc_dai_active(cpu_dai)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) omap_mcbsp_free(mcbsp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) mcbsp->configured = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) static int omap_mcbsp_dai_prepare(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) struct snd_soc_dai *cpu_dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) struct pm_qos_request *pm_qos_req = &mcbsp->pm_qos_req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) int tx = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) int stream1 = tx ? SNDRV_PCM_STREAM_PLAYBACK : SNDRV_PCM_STREAM_CAPTURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) int stream2 = tx ? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) int latency = mcbsp->latency[stream2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) /* Prevent omap hardware from hitting off between FIFO fills */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) if (!latency || mcbsp->latency[stream1] < latency)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) latency = mcbsp->latency[stream1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) if (cpu_latency_qos_request_active(pm_qos_req))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) cpu_latency_qos_update_request(pm_qos_req, latency);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) else if (latency)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) cpu_latency_qos_add_request(pm_qos_req, latency);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) static int omap_mcbsp_dai_trigger(struct snd_pcm_substream *substream, int cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) struct snd_soc_dai *cpu_dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) case SNDRV_PCM_TRIGGER_START:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) case SNDRV_PCM_TRIGGER_RESUME:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) mcbsp->active++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) omap_mcbsp_start(mcbsp, substream->stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) case SNDRV_PCM_TRIGGER_STOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) case SNDRV_PCM_TRIGGER_SUSPEND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) omap_mcbsp_stop(mcbsp, substream->stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) mcbsp->active--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) static snd_pcm_sframes_t omap_mcbsp_dai_delay(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) struct snd_soc_dai *dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) u16 fifo_use;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) snd_pcm_sframes_t delay;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) /* No need to proceed further if McBSP does not have FIFO */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) if (mcbsp->pdata->buffer_size == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) fifo_use = omap_mcbsp_get_tx_delay(mcbsp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) fifo_use = omap_mcbsp_get_rx_delay(mcbsp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) * Divide the used locations with the channel count to get the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) * FIFO usage in samples (don't care about partial samples in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) * buffer).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) delay = fifo_use / substream->runtime->channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) return delay;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) struct snd_pcm_hw_params *params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) struct snd_soc_dai *cpu_dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) struct omap_mcbsp_reg_cfg *regs = &mcbsp->cfg_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) struct snd_dmaengine_dai_dma_data *dma_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) int wlen, channels, wpf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) int pkt_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) unsigned int format, div, framesize, master;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) unsigned int buffer_size = mcbsp->pdata->buffer_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) dma_data = snd_soc_dai_get_dma_data(cpu_dai, substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) channels = params_channels(params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) switch (params_format(params)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) case SNDRV_PCM_FORMAT_S16_LE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) wlen = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) case SNDRV_PCM_FORMAT_S32_LE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) wlen = 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) if (buffer_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) int latency;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) if (mcbsp->dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) int period_words, max_thrsh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) int divider = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) period_words = params_period_bytes(params) / (wlen / 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) max_thrsh = mcbsp->max_tx_thres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) max_thrsh = mcbsp->max_rx_thres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) * Use sDMA packet mode if McBSP is in threshold mode:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) * If period words less than the FIFO size the packet
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) * size is set to the number of period words, otherwise
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) * Look for the biggest threshold value which divides
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) * the period size evenly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) divider = period_words / max_thrsh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) if (period_words % max_thrsh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) divider++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) while (period_words % divider &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) divider < period_words)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) divider++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) if (divider == period_words)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) pkt_size = period_words / divider;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) } else if (channels > 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) /* Use packet mode for non mono streams */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) pkt_size = channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) latency = (buffer_size - pkt_size) / channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) latency = latency * USEC_PER_SEC /
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) (params->rate_num / params->rate_den);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) mcbsp->latency[substream->stream] = latency;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) omap_mcbsp_set_threshold(substream, pkt_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) dma_data->maxburst = pkt_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) if (mcbsp->configured) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) /* McBSP already configured by another stream */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) regs->rcr2 &= ~(RPHASE | RFRLEN2(0x7f) | RWDLEN2(7));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) regs->xcr2 &= ~(RPHASE | XFRLEN2(0x7f) | XWDLEN2(7));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) regs->rcr1 &= ~(RFRLEN1(0x7f) | RWDLEN1(7));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) regs->xcr1 &= ~(XFRLEN1(0x7f) | XWDLEN1(7));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) format = mcbsp->fmt & SND_SOC_DAIFMT_FORMAT_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) wpf = channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) if (channels == 2 && (format == SND_SOC_DAIFMT_I2S ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) format == SND_SOC_DAIFMT_LEFT_J)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) /* Use dual-phase frames */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) regs->rcr2 |= RPHASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) regs->xcr2 |= XPHASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) /* Set 1 word per (McBSP) frame for phase1 and phase2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) wpf--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) regs->rcr2 |= RFRLEN2(wpf - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) regs->xcr2 |= XFRLEN2(wpf - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) regs->rcr1 |= RFRLEN1(wpf - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) regs->xcr1 |= XFRLEN1(wpf - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) switch (params_format(params)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) case SNDRV_PCM_FORMAT_S16_LE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) /* Set word lengths */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) regs->rcr2 |= RWDLEN2(OMAP_MCBSP_WORD_16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) regs->rcr1 |= RWDLEN1(OMAP_MCBSP_WORD_16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) regs->xcr2 |= XWDLEN2(OMAP_MCBSP_WORD_16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) regs->xcr1 |= XWDLEN1(OMAP_MCBSP_WORD_16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) case SNDRV_PCM_FORMAT_S32_LE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) /* Set word lengths */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) regs->rcr2 |= RWDLEN2(OMAP_MCBSP_WORD_32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) regs->rcr1 |= RWDLEN1(OMAP_MCBSP_WORD_32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) regs->xcr2 |= XWDLEN2(OMAP_MCBSP_WORD_32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) regs->xcr1 |= XWDLEN1(OMAP_MCBSP_WORD_32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) /* Unsupported PCM format */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) /* In McBSP master modes, FRAME (i.e. sample rate) is generated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) * by _counting_ BCLKs. Calculate frame size in BCLKs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) master = mcbsp->fmt & SND_SOC_DAIFMT_MASTER_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) if (master == SND_SOC_DAIFMT_CBS_CFS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) div = mcbsp->clk_div ? mcbsp->clk_div : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) framesize = (mcbsp->in_freq / div) / params_rate(params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) if (framesize < wlen * channels) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) printk(KERN_ERR "%s: not enough bandwidth for desired rate and "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) "channels\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) framesize = wlen * channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) /* Set FS period and length in terms of bit clock periods */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) regs->srgr2 &= ~FPER(0xfff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) regs->srgr1 &= ~FWID(0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) switch (format) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) case SND_SOC_DAIFMT_I2S:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) case SND_SOC_DAIFMT_LEFT_J:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) regs->srgr2 |= FPER(framesize - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) regs->srgr1 |= FWID((framesize >> 1) - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) case SND_SOC_DAIFMT_DSP_A:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) case SND_SOC_DAIFMT_DSP_B:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) regs->srgr2 |= FPER(framesize - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) regs->srgr1 |= FWID(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) omap_mcbsp_config(mcbsp, &mcbsp->cfg_regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) mcbsp->wlen = wlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) mcbsp->configured = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) * This must be called before _set_clkdiv and _set_sysclk since McBSP register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) * cache is initialized here
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) unsigned int fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) struct omap_mcbsp_reg_cfg *regs = &mcbsp->cfg_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) bool inv_fs = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) if (mcbsp->configured)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) mcbsp->fmt = fmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) memset(regs, 0, sizeof(*regs));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) /* Generic McBSP register settings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) regs->spcr2 |= XINTM(3) | FREE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) regs->spcr1 |= RINTM(3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) /* RFIG and XFIG are not defined in 2430 and on OMAP3+ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) if (!mcbsp->pdata->has_ccr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) regs->rcr2 |= RFIG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) regs->xcr2 |= XFIG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) /* Configure XCCR/RCCR only for revisions which have ccr registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) if (mcbsp->pdata->has_ccr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) regs->xccr = DXENDLY(1) | XDMAEN | XDISABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) regs->rccr = RFULL_CYCLE | RDMAEN | RDISABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) case SND_SOC_DAIFMT_I2S:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) /* 1-bit data delay */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) regs->rcr2 |= RDATDLY(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) regs->xcr2 |= XDATDLY(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) case SND_SOC_DAIFMT_LEFT_J:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) /* 0-bit data delay */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) regs->rcr2 |= RDATDLY(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) regs->xcr2 |= XDATDLY(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) regs->spcr1 |= RJUST(2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) /* Invert FS polarity configuration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) inv_fs = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) case SND_SOC_DAIFMT_DSP_A:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) /* 1-bit data delay */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) regs->rcr2 |= RDATDLY(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) regs->xcr2 |= XDATDLY(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) /* Invert FS polarity configuration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) inv_fs = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) case SND_SOC_DAIFMT_DSP_B:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) /* 0-bit data delay */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) regs->rcr2 |= RDATDLY(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) regs->xcr2 |= XDATDLY(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) /* Invert FS polarity configuration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) inv_fs = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) /* Unsupported data format */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) case SND_SOC_DAIFMT_CBS_CFS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) /* McBSP master. Set FS and bit clocks as outputs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) regs->pcr0 |= FSXM | FSRM |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) CLKXM | CLKRM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) /* Sample rate generator drives the FS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) regs->srgr2 |= FSGM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) case SND_SOC_DAIFMT_CBM_CFS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) /* McBSP slave. FS clock as output */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) regs->srgr2 |= FSGM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) regs->pcr0 |= FSXM | FSRM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) case SND_SOC_DAIFMT_CBM_CFM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) /* McBSP slave */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) /* Unsupported master/slave configuration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) /* Set bit clock (CLKX/CLKR) and FS polarities */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) case SND_SOC_DAIFMT_NB_NF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) * Normal BCLK + FS.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) * FS active low. TX data driven on falling edge of bit clock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) * and RX data sampled on rising edge of bit clock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) regs->pcr0 |= FSXP | FSRP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) CLKXP | CLKRP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) case SND_SOC_DAIFMT_NB_IF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) regs->pcr0 |= CLKXP | CLKRP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) case SND_SOC_DAIFMT_IB_NF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) regs->pcr0 |= FSXP | FSRP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) case SND_SOC_DAIFMT_IB_IF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) if (inv_fs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) regs->pcr0 ^= FSXP | FSRP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) static int omap_mcbsp_dai_set_clkdiv(struct snd_soc_dai *cpu_dai,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) int div_id, int div)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) struct omap_mcbsp_reg_cfg *regs = &mcbsp->cfg_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) if (div_id != OMAP_MCBSP_CLKGDV)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) mcbsp->clk_div = div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) regs->srgr1 &= ~CLKGDV(0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) regs->srgr1 |= CLKGDV(div - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) int clk_id, unsigned int freq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) int dir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) struct omap_mcbsp_reg_cfg *regs = &mcbsp->cfg_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) if (mcbsp->active) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) if (freq == mcbsp->in_freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) mcbsp->in_freq = freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) regs->srgr2 &= ~CLKSM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) regs->pcr0 &= ~SCLKME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) switch (clk_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) case OMAP_MCBSP_SYSCLK_CLK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) regs->srgr2 |= CLKSM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) case OMAP_MCBSP_SYSCLK_CLKS_FCLK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) if (mcbsp_omap1()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) err = omap2_mcbsp_set_clks_src(mcbsp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) MCBSP_CLKS_PRCM_SRC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) case OMAP_MCBSP_SYSCLK_CLKS_EXT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) if (mcbsp_omap1()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) err = omap2_mcbsp_set_clks_src(mcbsp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) MCBSP_CLKS_PAD_SRC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) case OMAP_MCBSP_SYSCLK_CLKX_EXT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) regs->srgr2 |= CLKSM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) regs->pcr0 |= SCLKME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) * If McBSP is master but yet the CLKX/CLKR pin drives the SRG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) * disable output on those pins. This enables to inject the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) * reference clock through CLKX/CLKR. For this to work
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) * set_dai_sysclk() _needs_ to be called after set_dai_fmt().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) regs->pcr0 &= ~CLKXM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) case OMAP_MCBSP_SYSCLK_CLKR_EXT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) regs->pcr0 |= SCLKME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) /* Disable ouput on CLKR pin in master mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) regs->pcr0 &= ~CLKRM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) err = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) static const struct snd_soc_dai_ops mcbsp_dai_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) .startup = omap_mcbsp_dai_startup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) .shutdown = omap_mcbsp_dai_shutdown,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) .prepare = omap_mcbsp_dai_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) .trigger = omap_mcbsp_dai_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) .delay = omap_mcbsp_dai_delay,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) .hw_params = omap_mcbsp_dai_hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) .set_fmt = omap_mcbsp_dai_set_dai_fmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) .set_clkdiv = omap_mcbsp_dai_set_clkdiv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) .set_sysclk = omap_mcbsp_dai_set_dai_sysclk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) static int omap_mcbsp_probe(struct snd_soc_dai *dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) pm_runtime_enable(mcbsp->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) snd_soc_dai_init_dma_data(dai,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) &mcbsp->dma_data[SNDRV_PCM_STREAM_PLAYBACK],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) &mcbsp->dma_data[SNDRV_PCM_STREAM_CAPTURE]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) static int omap_mcbsp_remove(struct snd_soc_dai *dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) pm_runtime_disable(mcbsp->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) static struct snd_soc_dai_driver omap_mcbsp_dai = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) .probe = omap_mcbsp_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) .remove = omap_mcbsp_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) .playback = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) .channels_min = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) .channels_max = 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) .rates = OMAP_MCBSP_RATES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) .capture = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) .channels_min = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) .channels_max = 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) .rates = OMAP_MCBSP_RATES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) .ops = &mcbsp_dai_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) static const struct snd_soc_component_driver omap_mcbsp_component = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) .name = "omap-mcbsp",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) static struct omap_mcbsp_platform_data omap2420_pdata = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) .reg_step = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) .reg_size = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) static struct omap_mcbsp_platform_data omap2430_pdata = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) .reg_step = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) .reg_size = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) .has_ccr = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) static struct omap_mcbsp_platform_data omap3_pdata = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) .reg_step = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) .reg_size = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) .has_ccr = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) .has_wakeup = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) static struct omap_mcbsp_platform_data omap4_pdata = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) .reg_step = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) .reg_size = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) .has_ccr = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) .has_wakeup = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) static const struct of_device_id omap_mcbsp_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) .compatible = "ti,omap2420-mcbsp",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) .data = &omap2420_pdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) .compatible = "ti,omap2430-mcbsp",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) .data = &omap2430_pdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) .compatible = "ti,omap3-mcbsp",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) .data = &omap3_pdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) .compatible = "ti,omap4-mcbsp",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) .data = &omap4_pdata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) { },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) MODULE_DEVICE_TABLE(of, omap_mcbsp_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) static int asoc_mcbsp_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) struct omap_mcbsp_platform_data *pdata = dev_get_platdata(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) struct omap_mcbsp *mcbsp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) const struct of_device_id *match;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) match = of_match_device(omap_mcbsp_of_match, &pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) if (match) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) struct device_node *node = pdev->dev.of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) struct omap_mcbsp_platform_data *pdata_quirk = pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) int buffer_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) pdata = devm_kzalloc(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) sizeof(struct omap_mcbsp_platform_data),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) if (!pdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) memcpy(pdata, match->data, sizeof(*pdata));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) if (!of_property_read_u32(node, "ti,buffer-size", &buffer_size))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) pdata->buffer_size = buffer_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) if (pdata_quirk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) pdata->force_ick_on = pdata_quirk->force_ick_on;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) } else if (!pdata) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) dev_err(&pdev->dev, "missing platform data.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) mcbsp = devm_kzalloc(&pdev->dev, sizeof(struct omap_mcbsp), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) if (!mcbsp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) mcbsp->id = pdev->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) mcbsp->pdata = pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) mcbsp->dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) platform_set_drvdata(pdev, mcbsp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) ret = omap_mcbsp_init(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) if (mcbsp->pdata->reg_size == 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) omap_mcbsp_dai.playback.formats = SNDRV_PCM_FMTBIT_S16_LE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) omap_mcbsp_dai.capture.formats = SNDRV_PCM_FMTBIT_S16_LE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) ret = devm_snd_soc_register_component(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) &omap_mcbsp_component,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) &omap_mcbsp_dai, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) return sdma_pcm_platform_register(&pdev->dev, "tx", "rx");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) static int asoc_mcbsp_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) struct omap_mcbsp *mcbsp = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) if (mcbsp->pdata->ops && mcbsp->pdata->ops->free)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) mcbsp->pdata->ops->free(mcbsp->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) if (cpu_latency_qos_request_active(&mcbsp->pm_qos_req))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) cpu_latency_qos_remove_request(&mcbsp->pm_qos_req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) if (mcbsp->pdata->buffer_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) sysfs_remove_group(&mcbsp->dev->kobj, &additional_attr_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) omap_mcbsp_st_cleanup(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) static struct platform_driver asoc_mcbsp_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) .name = "omap-mcbsp",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) .of_match_table = omap_mcbsp_of_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) .probe = asoc_mcbsp_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) .remove = asoc_mcbsp_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) module_platform_driver(asoc_mcbsp_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@bitmer.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) MODULE_DESCRIPTION("OMAP I2S SoC Interface");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) MODULE_ALIAS("platform:omap-mcbsp");