⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 omap-mcbsp.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  File: mcbsp.c * *  Defines for Multi-Channel Buffered Serial Port *  Multichannel mode not supported. * *  Copyright (C) 2002 RidgeRun, Inc. *  Author: Samuel Ortiz <samuel.ortiz@nokia.com> * *  This program is free software; you can redistribute	 it and/or modify it *  under  the terms of	 the GNU General  Public License as published by the *  Free Software Foundation;  either version 2 of the	License, or (at your *  option) any later version. * *  THIS  SOFTWARE  IS	PROVIDED  ``AS	IS''  AND   ANY	 EXPRESS  OR IMPLIED *  WARRANTIES,	  INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN *  NO	EVENT  SHALL   THE AUTHOR  BE	 LIABLE FOR ANY	  DIRECT,  INDIRECT, *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT *  NOT LIMITED	  TO, PROCUREMENT OF  SUBSTITUTE GOODS	OR SERVICES; LOSS OF *  USE, DATA,	OR PROFITS; OR	BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON *  ANY THEORY OF LIABILITY, WHETHER IN	 CONTRACT, STRICT LIABILITY, OR TORT *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *  You should have received a copy of the  GNU General Public License along *  with this program; if not, write  to the Free Software Foundation, Inc., *  675 Mass Ave, Cambridge, MA 02139, USA. * *  History *  ------- *  2004/08/12 Nishanth Menon Modified to integrate Audio requirements on 1610,1710 *                            and 2420 platforms. *//************************ INCLUDES *****************************************/#include <linux/module.h>#include <linux/init.h>#include <linux/device.h>#include <linux/wait.h>#include <linux/completion.h>#include <linux/interrupt.h>#include <asm/delay.h>#include <asm/io.h>#include <asm/irq.h>#include <asm/arch/dma.h>#include <asm/arch/mux.h>#include <asm/arch/irqs.h>#include "omap-mcbsp.h"#ifdef DPRINTK#undef DPRINTK#endif#undef DEBUG#define DEBUG#ifdef DEBUG#define DPRINTK(ARGS...)  printk(KERN_INFO "<%s>: ",__FUNCTION__);printk(ARGS)#define FN_IN printk(KERN_INFO "[%s]: start\n", __FUNCTION__)#define FN_OUT(n) printk(KERN_INFO "[%s]: end(%u)\n",__FUNCTION__, n)#else#define DPRINTK( x... )#define FN_IN#define FN_OUT(n)#endif#ifdef CONFIG_ARCH_OMAP16XX#include <asm/arch/dsp_common.h>extern int omap_mcbsp_request(unsigned int id);extern void omap_mcbsp_free(unsigned int id);extern void omap_mcbsp_start(unsigned int id);extern void omap_mcbsp_stop(unsigned int id);#endif/************************ MODULE DEFINES  **********************************//* Define this to enable IRQ functionality - This implementation Does not support this yet *///#define MCBSP_IRQ_MODE  1/* Define this to make McBSP Master mode - Not supported now. *///#define MCBSP_MASTER/* Define for dumping the registers *///#define MCBSP_DUMP_REGISTERS/* Enable the following for pcrm and muxing logic to be enabled for mcbsp2 24xx */#define MCBSP_PRCM#define MCBSP_PIN_MUXING/************************ MODULE DATA STRUCTURES ***************************//* Information about the mcbsp */struct omap_mcbsp {	u32 virt_base;		/* virtual base */	u32 phy_base;		/* physical base */	u8 free;		/* free or not */#ifdef MCBSP_IRQ_MODE	omap_mcbsp_word_length rx_word_length;	omap_mcbsp_word_length tx_word_length;	u8 id;	/* IRQ based TX/RX */	int rx_irq;	int tx_irq;	/* DMA stuff */	u8 dma_rx_sync;	short dma_rx_lch;	u8 dma_tx_sync;	short dma_tx_lch;	/* Completion queues */	struct completion tx_irq_completion;	struct completion rx_irq_completion;	struct completion tx_dma_completion;	struct completion rx_dma_completion;	spinlock_t lock;#endif				/* End of #ifdef MCBSP_IRQ_MODE */};/******************* McBSP definitions (START) */#ifdef CONFIG_ARCH_OMAP16XXstatic struct omap_mcbsp mcbsp_1610[OMAP_MAX_MCBSP_COUNT] = {	[0] = {.virt_base = OMAP1610_MCBSP1_BASE,	       .phy_base = OMAP1610_MCBSP1_BASE_PHY,#ifdef MCBSP_IRQ_MODE	       .dma_rx_sync = OMAP_DMA_MCBSP1_RX,	       .dma_tx_sync = OMAP_DMA_MCBSP1_TX,	       .rx_irq = INT_1610_McBSP1RX,	       .tx_irq = INT_1610_McBSP1TX#endif	       },	[1] = {.virt_base = OMAP1610_MCBSP2_BASE,	       .phy_base = OMAP1610_MCBSP2_BASE_PHY,#ifdef MCBSP_IRQ_MODE	       .dma_rx_sync = OMAP_DMA_MCBSP2_RX,	       .dma_tx_sync = OMAP_DMA_MCBSP2_TX,	       .rx_irq = INT_1610_McBSP2RX,	       .tx_irq = INT_1610_McBSP2TX#endif	       },	[2] = {.virt_base = OMAP1610_MCBSP3_BASE,	       .phy_base = OMAP1610_MCBSP3_BASE_PHY,#ifdef MCBSP_IRQ_MODE	       .dma_rx_sync = OMAP_DMA_MCBSP3_RX,	       .dma_tx_sync = OMAP_DMA_MCBSP3_TX,	       .rx_irq = INT_1610_McBSP3RX,	       .tx_irq = INT_1610_McBSP3TX#endif	       },};static struct omap_mcbsp mcbsp_1710[OMAP_MAX_MCBSP_COUNT] = {	[0] = {.virt_base = OMAP1710_MCBSP1_BASE,	       .phy_base = OMAP1710_MCBSP1_BASE_PHY,#ifdef MCBSP_IRQ_MODE	       .dma_rx_sync = OMAP_DMA_MCBSP1_RX,	       .dma_tx_sync = OMAP_DMA_MCBSP1_TX,	       .rx_irq = INT_1710_McBSP1RX,	       .tx_irq = INT_1710_McBSP1TX#endif	       },	[1] = {.virt_base = OMAP1710_MCBSP2_BASE,	       .phy_base = OMAP1710_MCBSP2_BASE_PHY,#ifdef MCBSP_IRQ_MODE	       .dma_rx_sync = OMAP_DMA_MCBSP2_RX,	       .dma_tx_sync = OMAP_DMA_MCBSP2_TX,	       .rx_irq = INT_1710_McBSP2RX,	       .tx_irq = INT_1710_McBSP2TX#endif	       },	[2] = {.virt_base = OMAP1710_MCBSP3_BASE,	       .phy_base = OMAP1710_MCBSP3_BASE_PHY,#ifdef MCBSP_IRQ_MODE	       .dma_rx_sync = OMAP_DMA_MCBSP3_RX,	       .dma_tx_sync = OMAP_DMA_MCBSP3_TX,	       .rx_irq = INT_1710_McBSP3RX,	       .tx_irq = INT_1710_McBSP3TX#endif	       },};#endif				/* CONFIG_ARCH_OMAP16XX */#ifdef CONFIG_ARCH_OMAP24XXstatic struct omap_mcbsp mcbsp_2420[OMAP_MAX_MCBSP_COUNT] = {	[0] = {.virt_base = OMAP2420_MCBSP1_BASE,	       .phy_base = OMAP2420_MCBSP1_BASE_PHY,#ifdef MCBSP_IRQ_MODE	       .dma_rx_sync = OMAP_DMA_MCBSP1_RX,	       .dma_tx_sync = OMAP_DMA_MCBSP1_TX,	       .rx_irq = INT_2420_McBSP1RX,	       .tx_irq = INT_2420_McBSP1TX#endif	       },	[1] = {.virt_base = OMAP2420_MCBSP2_BASE,	       .phy_base = OMAP2420_MCBSP2_BASE_PHY,#ifdef MCBSP_IRQ_MODE	       .dma_rx_sync = OMAP_DMA_MCBSP2_RX,	       .dma_tx_sync = OMAP_DMA_MCBSP2_TX,	       .rx_irq = INT_2420_McBSP2RX,	       .tx_irq = INT_2420_McBSP2TX#endif	       },};#endif				/* CONFIG_ARCH_OMAP24XX */static struct omap_mcbsp *mcbsp;/******************* McBSP definitions (END) */#ifdef CONFIG_ARCH_OMAP24XX#ifdef MCBSP_PRCMstatic __inline__ u32 mcbsp_prcm_andout(u32 offset, u32 val){	return writel(readl(PRCM_BASE_ADDRESS + offset) & val,		      PRCM_BASE_ADDRESS + offset);}static __inline__ u32 omap_mcbsp_prcm_orout(u32 offset, u32 val){	return writel(readl(PRCM_BASE_ADDRESS + offset) | val,		      PRCM_BASE_ADDRESS + offset);}#endif				/* MCBSP_PCRM */#ifdef MCBSP_PIN_MUXING#define CONTROL_REG_BASE_ADDR		OMAP24XX_VA_SYSTEM_CONTROL_BASE#define CONTROL_PADCONF_eac_ac_sclk 0x0124#define CONTROL_PADCONF_eac_ac_fs   0x0125#define CONTROL_PADCONF_eac_ac_din  0x0126#define CONTROL_PADCONF_eac_ac_dout 0x0127#define CONTROL_PADCONF_eac_ac_mclk 0x0128#define CONTROL_PADCONF_sys_clkout  0x0137static __inline__ u8 omap_mcbsp_pin_out(u32 offset, u8 val){	return writeb(val, CONTROL_REG_BASE_ADDR + offset);}#endif				/* End of pin mux reg read/write */#endif				/* End of #ifdef CONFIG_ARCH_OMAP24XX *//************************* MODULE SPECIFIC FUNCTIONS ***********************//* * This function does the required stuff to configure external interfaces to * get mcbsp working */#ifdef CONFIG_ARCH_OMAP24XXstatic void omap_mcbsp_ext_config(unsigned int id){	/* Platform specific inits - unfortunately, can handle only MCBSP2, 24xx */	/* Configure the clocks */#ifdef MCBSP_PRCM	omap_mcbsp_prcm_orout(CM_CLKEN_PLL, 0x000F);	/* enable APLL and DPLL  */	mcbsp_prcm_andout(CM_CLKSEL1_PLL, 0xFFFFFFF7);	/* 96 Mhz selected */	/* McBSP2 selected */	/* Done in core.c with ffffs */	omap_mcbsp_prcm_orout(CM_FCLKEN1_CORE, 0x00010000);	/* Done in core.c with ffffs */	omap_mcbsp_prcm_orout(CM_ICLKEN1_CORE, 0x00010000);	omap_mcbsp_prcm_orout(CM_AUTOIDLE1_CORE, 0x00010000);#endif				/* End of #ifdef MCBSP_PRCM */#ifdef MCBSP_PIN_MUXING	/* Pin Muxing  - TODO	 * These pins are used exclusively b/w mcbsp2 and eac. since eac is no longer	 * present, we can have this in mux.h. currently hacking in here.	 */	/* Enable Mode1 for McBSP2  */	omap_mcbsp_pin_out(CONTROL_PADCONF_eac_ac_sclk, 0x09);	omap_mcbsp_pin_out(CONTROL_PADCONF_eac_ac_fs, 0x09);	omap_mcbsp_pin_out(CONTROL_PADCONF_eac_ac_din, 0x09);	omap_mcbsp_pin_out(CONTROL_PADCONF_eac_ac_dout, 0x09);	omap_mcbsp_pin_out(CONTROL_PADCONF_eac_ac_mclk, 0x0B);	/* Enable Mode3 for GPIO117  */#endif				/* MCBSP_PIN_MUXING */}#endif				/* End of #ifdef CONFIG_ARCH_OMAP24XX *//* * omap_mcbsp_config simply write a config to the appropriate McBSP. * NOTE: Not exposing this interface to world until required. If required, this will * act as alternatvie to mcbsp_start. */static inline voidomap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg *config){	u32 io_base = mcbsp[id].virt_base;	/* We write the given config 	 * NOTE: The order is important - we would like to enable the 	 * tx and rx only after configuring everything	 */	OMAP_MCBSP_WRITE(io_base, RCR2, config->rcr2);	OMAP_MCBSP_WRITE(io_base, RCR1, config->rcr1);	OMAP_MCBSP_WRITE(io_base, XCR2, config->xcr2);	OMAP_MCBSP_WRITE(io_base, XCR1, config->xcr1);	OMAP_MCBSP_WRITE(io_base, SRGR2, config->srgr2);	OMAP_MCBSP_WRITE(io_base, SRGR1, config->srgr1);	OMAP_MCBSP_WRITE(io_base, PCR, config->pcr);	OMAP_MCBSP_WRITE(io_base, SPCR2, config->spcr2);	OMAP_MCBSP_WRITE(io_base, SPCR1, config->spcr1);	return;}/************************* GLOBAL FUNCTIONS ********************************//* * Here we start the McBSP, by enabling the sample * generator, both transmitter and receivers, * and the frame sync. */int omap_mcbsp_begin(unsigned int id){	u32 io_base;	const struct omap_mcbsp_reg_cfg initial_config = {		.spcr2 =		    SPCR2_FREE | SPCR2_FRST | SPCR2_GRST | SPCR2_XRST |		    SPCR2_XINTM(3),		.spcr1 = SPCR1_RINTM(3) | SPCR1_RRST,		.rcr2 =		    RCR2_RPHASE | RCR2_RFRLEN2(OMAP_MCBSP_WORD_8) |		    RCR2_RWDLEN2(OMAP_MCBSP_WORD_16) | RCR2_RDATDLY(1),		.rcr1 =		    RCR1_RFRLEN1(OMAP_MCBSP_WORD_8) |		    RCR1_RWDLEN1(OMAP_MCBSP_WORD_16),		.xcr2 =		    XCR2_XPHASE | XCR2_XFRLEN2(OMAP_MCBSP_WORD_8) |		    XCR2_XWDLEN2(OMAP_MCBSP_WORD_16) | XCR2_XDATDLY(1) |		    XCR2_XFIG,		.xcr1 =		    XCR1_XFRLEN1(OMAP_MCBSP_WORD_8) |		    XCR1_XWDLEN1(OMAP_MCBSP_WORD_16),		.srgr1 = SRGR1_FWID(15),		.srgr2 =		    SRGR2_GSYNC | SRGR2_CLKSP | SRGR2_FSGM | SRGR2_FPER(31),		/* platform specific initialization */#if CONFIG_MACH_OMAP_H2		.pcr =		    PCR_CLKXM | PCR_CLKRM | PCR_FSXP | PCR_FSRP | PCR_CLKXP |		    PCR_CLKRP,#elif CONFIG_MACH_OMAP_H3 || CONFIG_MACH_OMAP_H4 || CONFIG_ARCH_OMAP24XX#ifdef MCBSP_MASTER		.pcr =		    PCR_FSXM | PCR_FSRM | PCR_CLKXM | PCR_CLKRM | PCR_CLKXP |		    PCR_CLKRP,#else		.pcr =		    PCR_CLKRM | PCR_SCLKME | PCR_FSXP | PCR_FSRP | PCR_CLKXP |		    PCR_CLKRP,#endif				/* mcbsp Master defs */#endif				/* platform specific inits */	};	/* To prevent misuse */	if (!mcbsp[id].free) {		printk(KERN_ERR "mcbsp[%d] Already started\n", id);		return -EPERM;	}	io_base = mcbsp[id].virt_base;#ifdef CONFIG_ARCH_OMAP24XX	omap_mcbsp_ext_config(id);#endif				/* End of #ifdef CONFIG_ARCH_OMAP24XX */#ifdef CONFIG_ARCH_OMAP16XX	omap_mcbsp_request(id);	omap_dsp_request_idle();	omap_mcbsp_stop(id);#endif	/* Disable McBSP */	OMAP_MCBSP_WRITE(io_base, SPCR2, 0x0);	OMAP_MCBSP_WRITE(io_base, SPCR1, 0x0);	/* configure the registers */	omap_mcbsp_config(id, &initial_config);	/* no longer free */	mcbsp[id].free = 0;	/* Debug - Dump McBSP Regs */#ifdef MCBSP_DUMP_REGISTERS	printk("**** MCBSP%d regs ****\n", id + 1);	printk("SPCR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].virt_base, SPCR1));	printk("SPCR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].virt_base, SPCR2));	printk("RCR1 : 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].virt_base, RCR1));	printk("RCR2 : 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].virt_base, RCR2));	printk("XCR1 : 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].virt_base, XCR1));	printk("XCR2 : 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].virt_base, XCR2));	printk("SRGR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].virt_base, SRGR1));	printk("SRGR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].virt_base, SRGR2));	printk("PCR  : 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].virt_base, PCR));	printk("***********************\n");#endif				/* End of #ifdef MCBSP_DUMP_REGISTERS */	return 0;}/* * The function to stop the required mcBSP. To be called once all operations are completed. */int omap_mcbsp_end(unsigned int id){	u32 io_base;	/* To prevent misuse */	if (mcbsp[id].free) {		printk(KERN_ERR "mcbsp[%d] Already stopped \n", id);		return -EPERM;	}	io_base = mcbsp[id].virt_base;	// Disable the McBSP	OMAP_MCBSP_WRITE(io_base, DXR1, 0x0000);	// flush data	OMAP_MCBSP_WRITE(io_base, DXR1, 0x0000);	// flush data	OMAP_MCBSP_WRITE(io_base, SPCR1, 0x0000);	// disable SPCR1	OMAP_MCBSP_WRITE(io_base, SPCR2, 0x0000);	// disable SPCR2#if (defined(CONFIG_ARCH_OMAP24XX) && defined (MCBSP_PRCM))	mcbsp_prcm_andout(CM_AUTOIDLE1_CORE, ~0x00010000);#endif				/* #if CONFIG_ARCH_OMAP24XX */	mcbsp[id].free = 1;#ifdef CONFIG_ARCH_OMAP16XX	omap_mcbsp_stop(id);	omap_mcbsp_free(id);#endif	return (0);}/* * The function to set the clock rate generater for a certain sample rate. * sample rate is provided in hertz */int omap_mcbsp_set_rate(unsigned int id, u32 sample_rate, int bits_per_sample){	/*	 * CLKG = IP Clk/(CLKGDV)	 * SampleRateInhz = CLKG/(BitPerSample -1)	 * Assuming i/p clock of 96Mhz	 * CLKGDV = Input Clock/(SampleRateInhz * (BitsPerSample -1))	 */	int clkgdv = 0;	u32 io_base;	/* To prevent misuse */	if (mcbsp[id].free) {		printk(KERN_ERR		       "mcbsp[%d] Not started cannot set sample rate\n", id);		return -EPERM;	}	io_base = mcbsp[id].virt_base;#ifdef MCBSP_MASTER	clkgdv =	    DEFAULT_MCBSP_CLOCK / (sample_rate * (bits_per_sample * 2 - 1));	if (clkgdv)		OMAP_MCBSP_WRITE(io_base, SRGR1,				 SRGR1_FWID(bits_per_sample -					    1) | SRGR1_CLKGDV(clkgdv));	else		return (1);	/* Stereo Mode */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -