This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] Linux/AM3352:McASP 读取

Guru**** 2558810 points
Other Parts Discussed in Thread: AM3352

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/processors-group/processors/f/processors-forum/598195/linux-am3352-mcasp-read

器件型号:AM3352

工具/软件:Linux

你(们)好

我尝试读取 MCASP 轮询 RBUF。  但是、每次  RBUF 被读取为0。

我希望在 MCASP 接收数据时 、RDATA 位将被置位。 所以我对它进行了检查、但它从未设置。

我不知道问题是什么。 plz。 检查我的源代码。

是否有任何读取 MCASP 的示例。  

谢谢你

-块

-源代码

mcasp_open()-> audio_init()-> audio_run(); ->检查 Rx 状态或 RBUF

/*
BodyFriend kdj6724
McASP_audio.c
*/
#include 
#include 
#include 
#include /* kmalloc()*/
#include /*一切... */
#include /*错误代码*/
#include /* size_t */
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#include 
#include "mcasp_audio.h"

static int mcasp_major = 0;
module_param (mcasp_major、int、0);

#define SYS_INT_EDMA 20
#define SYS_INT_MCATXINT0 (80)
#define SYS_INT_MCARXINT0 (81)
#define SYS_INT_MCATXINT1 (82)
#define SYS_INT_MCARXINT1 (83)

struct McASP_EDMA_cc{
struct device *dev;
struct EDMA_SoC_info *信息;
void __iomem *底座;
内部 ID;
bool legacy_mode;

/* EDMA3资源信息*/
unsigned num_channels;
unsigned num_qchannels;
无符号 num_region;
unsigned num_slots;
unsigned num_tc;
bool chmap_exists;
//enum dma_event_q default_queue;

//
*每个参数插槽的 SLOW_INuse 位都是清除
的,除非该插槽*正在由 Linux 使用,或者该插槽被分配给 DSP 使用。
*/
unsigned long * slot_inuse;

struct dma_device dma_slave;
struct dma_device * dma_memcpy;
struct edma_chan * slave_chans;
struct edma_tc tc_list;
int 虚拟插槽;
};

/*********
** 内部宏定义
//*

**可配置的值
*/*
用于发送/接收数据的插槽大小*/
#define SLOT_SIZE 用于

发送/接收数据的32 /*字大小。 字大小<=插槽大小*/
#define WORD_SIZE 24

/*发送和接收段都将使用的采样率*/
#define SAMPLING_RATE (44100u)

/*通道数、L 和 R */
#define NUM_I2S_CHANNELS (2U)

/*每个音频缓冲器要使用的样本数*/
#define NUM_SAMESS_PER_AUDIO_BUF (2000u)

/*每个 TX/Rx 使用的缓冲器数量*/
#define NUM_BUF (3U)

/*每个 TX/Rx 使用的链接参数集数量*/
#define NUM_PAR (2U)

/*指定参数集起始位置是*/
#define PAR_ID_START (70U)

/*循环缓冲区中的样本数*/
#define NUM_SAMESS_LOOP_BUF (10U)

/* AIC3106编解码器地址*/
#define I2C_SLAVE_CODE_AIC31 (0x1Bu)

//
接收*的 McASP 串行器#define MCASP_XSER_RX (1U)

/*用于发送的 McASP 串行器*/
#define MCASP_XSER_TX (0U)

/*
**下面的宏是根据上述输入计算
的*/
#define NUM_TX_SERIALIZERS ((NUM_I2S_CHANNELS >> 1)\
+(NUM_I2S_CHANNELS 和0x01)
#define NUM_RX_SERIALIZERS ((NUM_I2S_CHANNELS >> 1)\
+(NUM_I2S_CHANNELS 和0x01)
#define I2S_SLOTS ((1 << NUM_I2S_CHANNELS)- 1)

#define Bytes_per_sample. ((word_size >> 3)\
* NUM_I2S_CHANNELS)

#define AUDIO_BUF_SIZE (num_samples_per_audio_BUF \
* bytes_per_sample)

#define TX_DMA_INT_ENABLE (EDMA3CC_OPT_TCC_SET \
(EDMA3_CHA_McASP1_TX)|(1 \
<<EDMA3CC_OPT_TCINTEN 位移))
#define RX_DMA_INT_ENABLE (EDMA3CC_OPT_TCC_SET \
(EDMA3_CHA_McASP1_RX)|(1 \
<< EDMA3CC_OPT_TCINTEN 移位))

#define PAR_RX_START (PAR_ID_START)
#define PAR_TX_START (PAR_RX_START + NUM_PAR)

/*
**不可配置的定义
*/
#define SIZE_PARAMETERS (32U)
#define OPT_FIFO_WIDTH (0x02 <<8u)

void __iomem * McASP0_BASE;
void __iomem * McASP1_base;
void __iomem * ctrl_BASE;
void __iomem * cmper_BASE;
void __iomem * edma3ch_BASE; // EDMA3通道控制
器 void __iomem *edma3ch0_BASE;// EDMA3通道1控制
器 void __iomem *edma3ch1_base;// EDMA3通道2控制
器 void __iomem *edma3ch2_base;// EDMA3通道3控制器/*********通道3控制器


** 内部变量定义
/
静态无符号 char loopBuf[NUM_SAMPS_LOOP_BUF * bytes_per_sample]={0};


/*
**发送缓冲区。 如果要添加任何新的缓冲区,请在此处进行定义,
并**更新 NUM_BUF。
//
静态无符号 char txBuf0[AUDIO_BUF_SIZE];
静态无符号 char txBuf1[AUDIO_BUF_SIZE];
静态无符号 char txBuf2[AUDIO_BUF_SIZE];

/*
**接收缓冲器。 如果要添加任何新的缓冲区,请在此处进行定义,
并**更新 NUM_BUF。
//
静态 unsigned char rxBuf0[AUDIO_BUF_SIZE];
静态 unsigned char rxBuf1[AUDIO_BUF_SIZE];
静态 unsigned char rxBuf2[AUDIO_BUF_SIZE];

/***
接收数据的下一个缓冲区。 数据将在此缓冲区中接收。
*/
静态易失性 unsigned int nxtBufToRcv = 0;

/*
**填充最新版本的 RX 缓冲区。
*/
静态易失性 unsigned int lastFullRxBuf = 0;

/*
**参数 ID 的偏移量,从参数集开始。
*/
静态易失性无符号短整型 parOffRcvd = 0;

/*
**从参数集开始发送的参数 ID 偏移量。
*/
静态易失性无符号短整型 parOffSent = 0;

/*
**最后发送的发送缓冲区。
//
静态易失性 unsigned int lastSentTxBuf = NUM_BUF - 1;

//
**从参数集开始,接下来要发送的参数 ID 的偏移量。
*/
静态易失性无符号短整型 parOffTxToSend = 0;

/*********
** 内部 CONSTATNT 定义
//
//接收缓冲区指针数组*/
静态无符号 int const rxBufPtr[NUM_BUF]=
{
(unsigned int) rxBuf0、
(unsigned int) rxBuf1、
(unsigned int) rxBuf2
};

//发送缓冲区指针数组*/
静态无符号 int const txBufPtR[NUM_BUF]=
{
(unsigned int) txBuf0、
(unsigned int) txBuf1、
(unsigned int) txBuf2
};

/*
**发送段的默认参数。 这将从
**一个环路缓冲器传输。
*/
静态结构 EDMA3CCPaRAMEntry const txDefaultPar =
{
(unsigned int)(opt_FIFO_width)、/* Opt 字段*/
(unsigned int) loopBuf、//源地址*/
(unsigned short)(bytes_per_sample")、/* aCnt */
(无符号短整型)(NUM_SAMESS_LOOP_BUF)、/* bCnt */
(unsigned int) SOC_MCASP_1_DATA_regs、/* dest 地址*/
(short)(bytes_per_sample")、/* source bIdx *
(短整型)(0)、/* dest bIdx */
(无符号短整型)(PAR_TX_START * SIZE _ParamSet)、/*链接地址*/
(无符号短整型)(0)、/* bcnt reload 值*/
(short)(0)、/*源 cIdx */
(短整型)(0)、/* dest cIdx */
(无符号短整型) 1 /* ccnt */
};

/*
**接收部分的默认参数。
*/
静态结构 EDMA3CCPaRAMEntry const rxDefaultPar =
{
(unsigned int)(opt_FIFO_width)、/* Opt 字段*/
(unsigned int) SOC_MCASP_1_DATA_regs、/*源地址*/
(unsigned short)(bytes_per_sample")、/* aCnt */
(无符号短整型)(1)、/* bcnt */
(unsigned int) rxBuf0、/* dest 地址*/
(短整型)(0)、/*源 bIdx *
(short)(bytes_per_sample)、/* dest bIdx */
(无符号短整型)(PAR_RX_START * SIZE _ParamSet)、/*链接地址*/
(无符号短整型)(0)、/* bcnt reload 值*/
(short)(0)、/*源 cIdx */
(短整型)(0)、/* dest cIdx */
(无符号短整型) 1 /* ccnt */
};

/
** 功能定义
//
//*
**为参数集指派循环作业
*/
static void ParamTxLoopJobSet (volatile void __iomem *dmaAddr,unsigned short parId)
{
EDMA3CCPaRAMEntry 参数集;

memcpy (&ParamSet、&txDefaultPar、Size_ParamSet - 2);

/*将参数链接到自身*/
ParamSet.linkAddr = parId * size_ParamSet;

EDMA3SetPaRAM (dmaAddr、parId、&ParamSet);
}/*


**初始化 DMA 参数。
** RX 基本参数集(通道)为0,TX 基本参数集(通道)为1。
**
** RX 参数集0将被初始化,以在 Rx 缓冲区0中接收数据。
**传输完成中断将不会为参数集0启用;
**参数集0将链接到 RX 的链接参数集启动(PAR_RX_START)。
**并且只能通过链接参数集进行进一步的接收。
**例如,如果 PAR_RX_START 值为40,且参数数为2,
**接收参数集链接将初始化为0->40->41->40**

TX 参数集将初始化为从循环缓冲区传输。
**可以配置循环缓冲区的大小。
**传输完成中断将不会为参数集1启用;
**参数集1将链接到 TX 的链接参数集启动(PAR_TX_START)。
**所有其它参数集将链接到自身。
**且仅通过链接参数集进行进一步传输。
**例如,如果 PAR_RX_START 值为42,且参数数为2,
**因此传输参数集链接将初始化为1->42->42,43->43。
*/

static void I2SDMAParamInit (volatile void __iomem *dmaAddr)
{
EDMA3CCPaRAMEntry 参数集;
int idx;

/*初始化接收的第0个参数集*/
memcpy (&ParamSet、&rxDefaultPar、Size_ParamSet - 2);

EDMA3SetPaRAM (dmaAddr、EDMA3_CHA_McASP1_RX、&ParamSet);

/*进一步的参数集,启用中断*/
ParamSet.op= RX_DMA_INT_ENABLE;

for (idx = 0;idx < NUM_PAR;idx++)
{
paramSet.destAddr = rxBufPtr[idx];

ParamSet.linkAddr =(PAR_RX_START +((IDx + 1)% NUM_PAR)
*(size_ParamSet);

ParamSet.bCnt = NUM_SAMESS_PER_AUDIO_BUF;

/*
**对于第一个链接参数集,开始接收第二个参数集
**仅限样本,因为中已接收到第一个样本
** Rx 缓冲器0本身。
*
if (0 = idx)
{
paramSet.destAddr += bytes_per_sample_sample_;
ParamSet.bcnt = bytes_per_sample_sample_sample_}


EDMA3SetPaRAM (dmaAddr、(PAR_RX_START + IDx)、&ParamSet);
}

/*初始化接收所需的变量*/
nxtBufToRcv = idx % NUM_BUF;
lastFullRxBuf = NUM_BUF - 1;
parOffRcvd = 0;

/*初始化传输的第一个参数集*/
memcpy (&ParamSet、&txDefaultPar、Size_ParamSet - 2);

EDMA3SetPaRAM (dmaAddr、EDMA3_CHA_McASP1_TX、&ParamSet);

/*参数的其余部分,启用循环作业*/
for (idx = 0;idx < NUM_PAR;idx++)
{
ParamTxLoopJobSet (dmaAddr、PAR_TX_START + IDx);
}

/*初始化要传输的变量*/
parOffSent = 0;
lastSentTxBuf = NUM_BUF - 1;
}

/*
**将 McASP 发送部分配置为 I2S 模式。
//
静态空 McASPI2STxConfigure (volatile void __iomem *baseAddr)
{
McASPTxReset (baseAddr);

/*为 DMA 传输启用 FIFO */
McASPWriteFifoEnable (baseAddr + 0x1000、1、1);

/*以发送器/接收器格式单位设置 I2S 格式*/
McASPTxFmtI2SSet (baseAddr、word_size、slot_size、
McASP_TX_MODE_DMA);

/*配置帧同步。 I2S 应采用 TDM 格式、具有2个插槽*/
McASPTxFrameSyncCfg (baseAddr、2、MCASP_TX_FS_WIDTH_WORD、
McASP_TX_FS_INT_BEGIN_ON_FALL_EDGE);

/*配置发送器的时钟*/
McASPTxClkCfg (baseAddr、MCASP_TX_CLK_INTERNAL、0、0);
McASPTxClkPolaritySet (baseAddr、MCASP_TX_CLK_POL_FALL_EDGE);
McASPTxClkCheckConfig (baseAddr、MCBSP_TX_CLKCHCK_DIV32、
0x00、0xFF);

/*启用 RX 和 TX 部分的同步*/
McASPTxRxClkSyncEnable (baseAddr);

/*启用发送器/接收器插槽。 I2S 使用2个插槽*/
McASPTxTimeSlotSet (baseAddr、I2S_SLOTS);

/*
**设置串行器,当前只有一个串行器设置为
**发送器和一个串行器作为接收器。
*
McASPSerializerTxSet (baseAddr、MCASP_XSER_TX);

/*
**配置 McASP 引脚
**输入-帧同步、时钟和串行器 Rx
**输出-串行器 Tx 连接到编解码器的输入
*
McASPPinMcASPSet (baseAddr、0xFFFFFFFF);
McASPPinDirOutputSet (baseAddr、MCASP_PIN_AXR (MCASP_XSER_TX)
| MCASP_PIN_ACLKX | MCASP_PIN_AFSX);
}

静态空 McASPI2SRxConfigure (易失性空__iomem *baseAddr)
{
McASPRxReset (baseAddr);

/*为 DMA 传输启用 FIFO */
McASPReadFifoEnable (baseAddr + 0x1000、1、1);

/*以发送器/接收器格式单位设置 I2S 格式*/
McASPRxFmtI2SSet (baseAddr、word_size、slot_size、
McASP_RX_MODE_DMA);

/*配置帧同步。 I2S 应采用 TDM 格式、具有2个插槽*/
McASPRxFrameSyncCfg (baseAddr、2、MCASP_RX_FS_WIDTH_WORD、
McASP_RX_FS_INT_BEGIN_ON_FALL_EDGE);

/*为接收器配置时钟*/
McASPRxClkCfg (baseAddr、MCASP_RX_CLK_EXTERNAL、0、0);
McASPRxClkPolaritySet (baseAddr、MCASP_RX_CLK_POL_FALL_EDGE);
McASPRxClkCheckConfig (baseAddr、MCBSP_RX_CLKCHCK_DIV32、
0x00、0xFF);

/*启用 RX 和 TX 部分的同步*/
McASPTxRxClkSyncEnable (baseAddr);

/*启用发送器/接收器插槽。 I2S 使用2个插槽*/
McASPRxTimeSlotSet (baseAddr、I2S_SLOTS);

/*
**设置串行器,当前只有一个串行器设置为
**发送器和一个串行器作为接收器。
*
McASPSerialerRxSet (baseAddr、MCASP_XSER_RX);

/*
**配置 McASP 引脚
**输入-帧同步、时钟和串行器 Rx
**输出-串行器 Tx 连接到编解码器的输入
*
McASPPinMcASPSet (baseAddr、0xFFFFFFFF);
McASPPinDirInputSet (baseAddr、MCASP_PIN_AFSR
| MCASP_PIN_ACLKR
| MCASP_PIN_AXR (MCASP_XSER_RX);
}/*


**激活数据传输/接收
**调用此函数之前,DMA 参数应准备就绪。
*/
static void I2SDataTxActivate (volatile void __iomem *mcaspAddr、
volatile void __iomem *dmaAddr)
{
/*启动时钟*/
McASPTxClkStart (mcaspAddr、MCBSP_TX_CLK_external);

/*为传输启用 EDMA */
EDMA3 EnableTransfer (dmaAddr、EDMA3_CHA_McASP1_TX、
EDMA3_TRIG_MODE_EVENT);

/*激活串行器*/
//McASPRxSerActivate (mcaspAddr);
McASPTxSerActivate (mcaspAddr);

/*确保 XDATA 位清零*/
while (McASPTxStatusGet (mcaspAddr)和 MCASP_TX_STAT_DATAREADY);

/*激活状态机*/
McASPTxEnable (mcaspAddr);
}/*


**激活数据传输/接收
**调用此函数之前,DMA 参数应准备就绪。
*/
static void I2SDataRxActivate (volatile void __iomem *mcaspAddr、
volatile void __iomem *dmaAddr)
{
/*启动时钟*/
McASPRxClkStart (mcaspAddr、MCBSP_RX_CLK_external);

/*为传输启用 EDMA */
EDMA3 EnableTransfer (dmaAddr、EDMA3_CHA_McASP1_RX、
EDMA3_TRIG_MODE_EVENT);

/*激活串行器*/
McASPRxSerActivate (mcaspAddr);

/*激活状态机*/
McASPRxEnable (mcaspAddr);
}/*


**激活给定缓冲区参数集的 DMA 传输。
静态
空 BufferTxDMAActivate (volatile void __iomem *dmaAddr、unsigned int txBuf、
无符号短整型数值采样、无符号短整型参数 ID、无符号短整型链接参数)
{
EDMA3CCPaRAMEntry 参数集;

/*复制默认参数集*/
memcpy (&ParamSet、&txDefaultPar、Size_ParamSet - 2);

/*启用完成中断*/
ParamSet.op= TX_DMA_INT_ENABLE;
ParamSet.srcAddr = txBufPtr[txBuf];
ParamSet.linkAddr = linkPar * size_ParamSet;
ParamSet.bCnt = numSamples;

EDMA3SetPaRAM (dmaAddr、parId、&ParamSet);
}/*



**激活给定缓冲区参数集的 DMA 传输。
*/
static void BufferRxDMAActivate (volatile void __iomem *dmaAddr、unsigned int rxBuf、unsigned short parId、
unsigned short parLink)
{
EDMA3CCPaRAMEntry 参数集;

/*复制默认参数集*/
memcpy (&ParamSet、&rxDefaultPar、Size_ParamSet - 2);

/*启用完成中断*/
ParamSet.op= RX_DMA_INT_ENABLE;
paramSet.destAddr = rxBufPtr[rxBuf];
ParamSet.bCnt = NUM_SAMESS_PER_AUDIO_BUF;
ParamSet.linkAddr = parLink * Size_ParamSet;

EDMA3SetPaRAM (dmaAddr、parId、&ParamSet);
}

//***
一旦接收 DMA 完成
,将调用此函数*/
静态空 McASPRxDMAComplHandler (void)
{
unsigned short nxtParToUpdate;

/*
**更新 lastFullRxBuf 以指示新的缓冲区接收
**已完成。
*
lastFullRxBuf =(lastFullRxBuf + 1)% NUM_BUF;
nxtParToUpdate = PAR_RX_START + parOffRcvd;
parOffRcvd =(parOffRcvd + 1)% NUM_PAR;

/*
**更新要接收的缓冲区的 DMA 参数
**在适当的缓冲区中进一步的数据
*
BufferRxDMAActivate (edma3ch_BASE、nxtBufToRcv、nxtParToUpdate、
PAR_RX_START + parOffRcvd);

/*更新下一个缓冲区以接收数据*/
nxtBufToRcv =(nxtBufToRcv + 1)% NUM_BUF;
}

//
***此函数将在传输 DMA 完成后调用*/

静态空 McASPTxDMAComplHandler (void)
{
ParamTxLoopJobSet (edma3ch_BASE、(无符号短整型)(PAR_TX_START + parOffSent));

parret Sent =(parOffSent + 1)% NUM_PAR;
}

static irqreturn_t McASP_IRQ_handler (int IRQ、void * data){
printk ("[kdj6724]%s (%d)\n"、__function__、__line_handler;
return IRQ_handled;
}

//t.eq_inq

= static t.int eq.int;


//prtd = kzalloc (sizeof (struct EDMA_info)、GFP_kernel);

printk ("[kdj6724]%s (%d)\n"、__function__、__line__);
//ret = request_IRQ (SYS_INT_EDMA、McASP_IRQ_handler、 IRQF_shared、"BD-EDMA"、prtd);
printk ("[kdj6724]%s (%d) ret:%d\n"、__function__、 __LINE__,RET);
返回0;
}

static int audio_init (void)
{
ctrl_base = ioremap (SOC_control_regs、SOC_control_size);
McASP1PinMuxSetup (ctrl_BASE);

McASP0_BASE = ioremap (SOC_MCASP_0_CFG、McASP0_ADDR_SIZE);
McASP1_base = ioremap (SOC_MCASP_1_CFG、McASP1_ADDR_SIZE);
cmper_BASE = ioremap (SOC_CM_PER、CMPER_ADDR_SIZE);
edma3ch_BASE = ioremap (SOC_EDMA30CC_0_regs、 SoC_EDMA30CC_0_SIZE);
edma3ch0_BASE = ioremap (SOC_EDMA3CH_0_REG、SOC_EDMA3CH_SIZE);
edma3ch1_base = ioremap (SOC_EDMA3CH_1_REG、SOC_EDMA3CH_SIZE);
edma3ch2_base = ioremap (SOC_EDMA3ch_2_REG、SOC_EDMA3 CH_SIZE);

McASPModuleClkConfig (cmper_BASE、CM_PER_McASP1_CLKCTRL);
McASPModuleClkConfig (cmper_BASE、 CM_PER_McASP0_CLKCTRL);
EDMA 模块 ClkConfig (cmper_BASE、edma3ch0_BASE、edma3ch1_base、edma3ch2_base);
EDMA3Init (edma3ch_BASE、0);

/*请求 EDMA 通道*/
EDMA3RequestChannel (edma3ch_BASE、EDMA3_CHANNEL_TYPE_DMA、
EDMA3_CHA_McASP1_TX、EDMA3_CHA_McASP1_TX、0);
EDMA3RequestChannel (edma3ch_BASE、EDMA3_CHANNEL TYPE_DMA、
EDMA3_CHA_McASP1_RX、EDMA3_CHA_McASP1_RX、0);

//初始化 DMA 参数*/
I2SDMAParamInit (edma3ch_BASE);

//为 I2S 配置 McASP */
McASPI2SRxConfigure (McASP0_BASE);
McASPI2STxSP1 (edSIBASE);DataSPI2MCASTxSPI (McADS0_BASE);DataActivate McADISTxSPI (McADISTxSP1

)
edma3ch_BASE);

返回0;
}

void hex_dump (unsigned int * buf、size_t len){
size_t index=0;
if (buf = NULL || len <= 0){
printk ("[kdj6724] hex_dump 错误\n");
return;
}

printk ("\n");
for (index=0;index "\n");="" else="" printk("0x%04x="" ",="" buf[index]);="" }="" int="" audio_run(void)="" unsigned="" short="" partosend;="" partolink;="" index="0;" printk("rx="" \n");="" mcaspregdump(mcasp0_base);="" printk("tx\n");="" mcaspregdump(mcasp1_base);="" #if="" 0="" read="" while(1)="" mcasprxdmacomplhandler();="" while(mcasprxstatusget(mcasp0_base)="" &="" mcasp_rx_stat_dataready);="" hex_dump((void="" *)rxbufptr[0],="" 32);="" *)rxbufptr[1],="" *)rxbufptr[2],="" #endif="" 1="" rdata="" reg.="" printk("state:="" 0x%08x\n",="" mcasprxstatusget(mcasp0_base));="" return="" 0;="" *="" open="" the="" device;="" in="" fact,="" there's="" nothing="" to="" do="" here.="" static="" mcasp_open(struct="" inode="" *inode,="" struct="" file="" *filp)="" printk("[kdj6724]="" %s(%d)\n",="" __function__,="" __line__);="" mcasp_irq_enable();="" audio_init();="" audio_run();="" closing="" is="" just="" as="" simpler.="" mcasp_release(struct="" void="" mcasp_setup_cdev(struct="" cdev="" *dev,="" minor,="" file_operations="" *fops)="" err,="" devno="MKDEV(mcasp_major," minor);="" cdev_init(dev,="" fops);="" dev-="">所有者=此模块;
dev->ops = FOPS;
err = cdev_add (dev、devno、1);
//如果需要,会缓慢地失败*/
if (err)
printk (kern_notice "添加 simple_d"时出错%d "、错误、次要);
}

静态结构 file_operations McASP_ops ={
.owner = this 模块、
.open = McASP_open、
.release = McASP_release、
};

#define MAX_MCASP_dev 2
static 结构 concmcasps[MAX_MCA_open、.define = tcc_dev_clind_1[#define


0
= tid_device_define dCC_define #define d_define d_time_time_clinding];#define dCCEST_d_dev_dev_

.compatible ="ti、EDMA3"、
.data =(void *) EDMA_binding_legacy
、}、
{
.compatible ="ti、edma3-tpcc"、
.data =(void *) edma_binding_tPCC
、}、
{}
};

static int mcasp_audio_probe (struct platform_device *pdev){
struct edma_soc_info *信息= pdev->dev.platform_data;
struct mcasp_edma_cc_ccc;
struct device_node *节点= pdev->device_struct_docl
;&l *
节点= pdev->device_dev->struct;设备节点= pstruct_decc *IRQ_NAME;
struct resource *mem;
bool legacy_mode = true;
int ret =-1;
int IRQ;

if (node){
const struct of _device_id *匹配;

匹配= of _match_node (EDMA_of _ID、node);
if (匹配&&(u32) match->data =EDMA_binding_TPCC)
legacy_mode = false;
}

if (!pdev->dev.platform_data &&!pdev->dev.for_node){
DEV_ERR(&pdev->DEV,“未提供平台数据\n");
return -EINVAL;
}

ecc = devm_kzalloc (dev、sizeof (* ecc)、gfp_kernel);
if (!ecc){
DEV_ERR (DEV、"无法分配控制器\n");
return -ENOMEM;
}

ecc->dev = dev;
ecc->id = pdev->id;
mem = platform_get_resource_byname (pdev、IORESOURCE_MEM、"EDMA3_cc");
如果(!mem){
DEV_dbg (dev、"找不到内存资源、使用索引0\n");
MEM = platform_get_resource (pdev、IORESOURCE_MEM、0);
如果(!mem){
DEV_ERR (DEV、"无内存资源?\n");
return -ENODEV;
}
}

//IRQ = platform_get_IRQ_Byname (pdev、"EDMA3_ccint");
//IRQ_name = devm_kasprintf (dev、GFP_kernel、"BD-EDMA");
//ret = devm_request_IRQ (dev、SYS_INT_EDMA、McASP_IRQ_handler、0、IRQ_name、 ECC);

返回0;
}

静态 int McASP_AUDIO_REMOVE (struct platform_device *pdev){
printk ("[kdj6724]%s (%d)\n"、__function__、__line__);
返回0;
}

静态结构 platform_driver McASP_EDMA_driver ={
.probe = McASP_remove_audio_probe
=
{.asp、_audio_remove .asp =.asp、.asp =.audio_remove .asp
.name ="McASP-音频"、
//.pm =&EDMA_PM_ops、
.f_match_table = edma_for_IDs、
}、
};

int __init init_mcasp_audio (void)
{
int 结果= 0;
printk ([kdj6724]%s (%d)\n"、__function__、__line___);
dev_t dev = mkdev (McASP_MAJOR、DEV_REALLOC0
)、DEV_REALLOR、DEV_REALLOR (DEV_0)、DEV_REALLOR、DEV_REALLOR = 0、DEV_RECO "McASP-AUDIBLE");
McASP_MAJOR = MAJOR (DEV);

IF (结果< 0){
printk (Kern_warning "无法获取主要%d\n"、McASP_MAJOR);
返回结果;
}
如果(McASP_MAJOR =0)
McASP_MAJOR =结果;

McASP_setup_cdev (mcaspDev、0、&McASP_ops);
platform_driver_register (&McASP_EDMA_driver);

返回结果;
}

void __exit exit_mcasp_audio (void)
{
iounmap (McASP0_BASE);
iounmap (McASP1_base);
iounmap (ctrl_BASE);
iounmap (cmper_BASE);
iounmap (edma3ch_BASE);
iounmap (edma3ch0_BASE);
iounmap (edma3ch1_base);
iounmap (edma3ch2_base);
//free_IRQ (SYS_INT_EDMA、prtd);
platform_driver_unregister (&McASP_EDMA_driver);
}

module_init (init_McASP_audio);
module_exit (exit_McASP_audio);

module_Author ("kdj6724");
module_description ("Bodyfriend MCASP Audio driver");
module_license ("GPL");

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好!

    McASP 驱动程序包含在 TI 提供的 Linux SDK 中: software-dl.ti.com/.../index_FDS.html 您可以在此处找到更多信息: processors.wiki.ti.com/.../Linux_Core_Audio_User's_Guide
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    感谢您的快速回答。

    我正在尝试执行以下操作。
    将 I2S 数据从 McASP0传递到 McASP1。
    McASP0_AXR1为 RX、McASP1_AXR0~AXR2为 TX (三个 TX 数据)
    3. RX 数据的修改方式不同,将发送每个数据(McASP1_AXR0~AXR2)。

    有很多困难,我不敢肯定,这种结构是可以支持的。
    最后、我修改了 RTOS MCASP 源代码并尝试直接写入 MCASP。

    我有任何意见。 请告诉我。

    谢谢你
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    器件型号:AM3352

    工具/软件:Linux

    你(们)好  

    感谢您的回答。  我在帖子下面附加了额外的问题、请检查一下

    https://e2e.ti.com/support/arm/sitara_arm/f/791/t/598195

    谢谢你