openwrt pcm driver on mt7620 or rt5350

查看datasheet可以知道,mt7620和rt5350有相通的Audio组件
从openwrt14.07的kernel源码中,我们可以找到mt7620 i2s的驱动
我们的pcm驱动,可以基于i2s驱动进行改动。pcm驱动已传至github,相关代码可以看这里
主要改动了以下几点:

driver source code
This code is based on the mt7620 i2s driver in openwrt 14.07, beacause the mt7620 and rt5350 has
the same Audio Component, we can just do some modifications to make the pcm driver:

1.寄存器相关 (About the registers)

参考datasheet,定义PCM相关的寄存器,把i2s驱动里对应的寄存器操作换成对PCM部分寄存器的操作
Just refer to the datasheet and repace I2S registers with PCM registers.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#define PCM_GLB_CFG 0x00
#define PCM_GLB_CFG_EN BIT(31)
#define PCM_GLB_CFG_DMA_EN BIT(30)
#define PCM_GLB_CFG_CH0_TX_EN BIT(8)
#define PCM_GLB_CFG_CH0_RX_EN BIT(0)

#define PCM_GLB_CFG_RFF_THRES 20
#define PCM_GLB_CFG_TFF_THRES 16

#define PCM_GLB_CFG_DFT_THRES (4 << PCM_GLB_CFG_RFF_THRES) | \
(4 << PCM_GLB_CFG_TFF_THRES)


#define PCM_PCM_CFG 0x04
#define PCM_PCM_CFG_CLKOUT_EN BIT(30)
#define PCM_PCM_CFG_EXT_FSYNC BIT(27)
#define PCM_PCM_CFG_LONG_FSYNC BIT(26)
#define PCM_PCM_CFG_FSYNC_POL BIT(25)



#define PCM_INT_STATUS 0x08
#define PCM_INT_EN 0x0C
#define PCM_FF_STATUS 0x10
#define PCM_CH0_CFG 0x20
#define PCM_CH1_CFG 0x24
#define PCM_FSYNC_CFG 0x30
#define PCM_CH_CFG2 0x34

#define PCM_DIVCOMP_CFG 0x50
#define PCM_DIVCOMP_CFG_CLK_EN BIT(31)

#define PCM_DIVINT_CFG 0x54
#define PCM_DIGDELAY_CFG 0x60
#define PCM_CH0_FIFO 0x80
#define PCM_CH1_FIFO 0x84

2.PCM Config相关 (About PCM config)

参考RT5350 Preliminary Datasheet.pdf第3.12.3节
Peripheral Channel Connection部分可知,
PCM Channel0 对应的GDMA Slot为4(RX)、6(TX),
在配置dma channel的时候做对应的改动即可

From RT5350 Preliminary Datasheet.pdf 3.12.3,
we can see the PCM use channel 4 and channel 6 for DMA.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
static void rt5350_init_pcm_config(struct rt5350_pcm *pcm)
{
struct snd_dmaengine_dai_dma_data *dma_data;

/* Playback */
dma_data = &pcm->playback_dma_data;
dma_data->maxburst = 16;
dma_data->slave_id = 6;
dma_data->addr = pcm->phys_base + PCM_CH0_FIFO; //only use channel 0

/* Capture */
dma_data = &pcm->capture_dma_data;
dma_data->maxburst = 16;
dma_data->slave_id = 4;
dma_data->addr = pcm->phys_base + PCM_CH0_FIFO;
}
3.PCM时序相关 (About PCM timming)

以rt5350做pcm slave,sim800模块做master为例
sim800模块的pcm参数如下:

a) PCM clock 为256kHz

b) PCM sync 为 short sync,极性为高有效

于是参考datasheet对PCM_CFG寄存器的描述,可以得到下面改动

suppose we use rt5350 as PCM Slave, and Sim800 as master,

PCM parameters of Sim800:

a) PCM clock: 256kHz
b) PCM sync: short sync, high active

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
rt5350_pcm_dai_probe
/ pcm general config
cfg = rt5350_pcm_read(pcm, PCM_FSYNC_CFG);
cfg &= ~PCM_PCM_CFG_LONG_FSYNC; //short sync mode
cfg |= PCM_PCM_CFG_FSYNC_POL; // sync high active

//slot mode, pcm clock = 256KHz
cfg &= ~(0x07);
cfg = 0; // 4 slots

rt5350_pcm_write(pcm, PCM_PCM_CFG, cfg);

/ pcm sync config
cfg = rt5350_pcm_read(pcm, PCM_FSYNC_CFG);
// pol, etc.

rt5350_pcm_write(pcm, PCM_FSYNC_CFG, cfg);

//When using the external clock, the frequency clock
//should be equal to the PCM_clock out. Otherwise, the
//PCM_CLKin should be 8.192 MHz.
rt5350_pcm_write(pcm, PCM_DIVINT_CFG, i2sMaster_inclk_int[PCMCLOCK_OUT]);
rt5350_pcm_write(pcm, PCM_DIVCOMP_CFG, i2sMaster_inclk_comp[PCMCLOCK_OUT] | PCM_DIVCOMP_CFG_CLK_EN);
----------------------------
rt5350_pcm_set_fmt
cfg = rt5350_pcm_read(pcm, PCM_PCM_CFG);

switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBS_CFS:
cfg &= ~PCM_PCM_CFG_CLKOUT_EN; // pcm clock from external
cfg |= PCM_PCM_CFG_EXT_FSYNC; // pcm sync from external
break;
case SND_SOC_DAIFMT_CBM_CFM:
cfg |= PCM_PCM_CFG_CLKOUT_EN; // pcm clock from internal
cfg &= ~PCM_PCM_CFG_EXT_FSYNC; // pcm sync from internal
break;
case SND_SOC_DAIFMT_CBM_CFS:
default:
return -EINVAL;
}

rt5350_pcm_write(pcm, PCM_PCM_CFG, cfg);
4.管脚定义 (About Pinmux)

因为rt5350/mt7620上PCM是复用脚,所以需要配置成PCM功能,
这部分通过修改dts文件即可,
另外,PCM驱动设备节点的声明,codec machine层、codec层驱动设备节点的声明
也都是在dts文件里完成,
具体如下

rt5350.dtsi

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
      pcm: pcm@2000 {
compatible = "ralink,rt5350-pcm";
reg = <0x2000 0x800>;

resets = <&rstctrl 11>;
reset-names = "pcm";

interrupt-parent = <&intc>;
interrupts = <4>;

dmas = <&gdma 4>,
<&gdma 5>;
dma-names = "tx", "rx";

status = "disabled";
};

SXX.dts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
   //使能pcm驱动
palmbus@10000000 {
pcm@2000 {
status = "okay";
};
}

//管脚功能初始化
pinctrl {
state_default: pinctrl0 {
gpio {
ralink,group = "i2c", "jtag";
ralink,function = "gpio";
};
uartf {
ralink,group = "uartf";
ralink,function = "pcm uartf";
};
};
};

//声明codec设备节点
codec: sxx-pcm-codec {
compatible = "ralink,sxx-pcm-codec";
};

//声明codec machine层设备节点
sound: sxx-pcm-machine {
compatible = "ralink,sxx-pcm-machine";
model = "sxx-pcm-machine";
cpu-dai = <&pcm>;
codec-dai = <&codec>;
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值