4. hda设备中的pcm文件(第四部分)

4.3 Codec命令

之前介绍过,codec支持一定数量的命令,在每个帧周期中SDO中的前40bit都会保留下来作为发送给codec的命令,而SDI中也保留了36bit作为codec对命令的响应。

这一切都需要controller的参与,命令是由软件以DMA的方式传到controller。我们在之前也看到了帮hdac_bus中分配了DMA内存rb。这一小节,我们具体看看这一部分的内容。

4.3.1 CORB & RIRB

CORB(Command Outbound Ring Buffer)用来保存发送到codec的命令。CORB是分配在系统内存上(DMA类型的),当有命令要发送到codec的话,软件需要将命令写入CORB,而Controller可以通过DMA从CORB上读取命令然后放到AC Link上。DMA的好处不仅提高了效率,其实也方便了设备于系统的交互,比如这里的读取命令,就是由controller来主动完成的。

CORB也可以看成是一个数组,因为在分配之后,其实它就有固定的大小。软件往数组中添加数据,controller从中读取数据,就有了同步的问题。写数据会一直向前写,直到数组的末端,再有新数据的话,就会重新从开头写。这也就是称为环形缓冲的原因。

另外需要注意的是,controller需要知道这块内存区的位置,为了同步,软件和controller都需要知道当前的读写位置。后续分析的代码中,可以看到这些内容。

RIRB(Response Inbound Ring Buffer)用来保存从codec返回的响应结果。在CORB中,是Controller向内存读取数据,现在是写数据。其它内容是相似的。

HDA的标准说明书中,对这些内容都有详尽的描述,可以参考得到更多的信息。

4.3.2 CORB & RIRB 初始化

以上是一些基本的原理,现在看看具体的代码:

void snd_hdac_bus_init_cmd_io(struct hdac_bus *bus)
{
	WARN_ON_ONCE(!bus->rb.area);

	spin_lock_irq(&bus->reg_lock);
	/* CORB set up */
    // 设置corb相应的地址,为rb的开始地址
	bus->corb.addr = bus->rb.addr;
	bus->corb.buf = (__le32 *)bus->rb.area;
    // 将corb地址写入相应的寄存器
	snd_hdac_chip_writel(bus, CORBLBASE, (u32)bus->corb.addr);
	snd_hdac_chip_writel(bus, CORBUBASE, upper_32_bits(bus->corb.addr));

    // 将corb的大小以及当前写位置写入相应寄存器
	/* set the corb size to 256 entries (ULI requires explicitly) */
	snd_hdac_chip_writeb(bus, CORBSIZE, 0x02);
	/* set the corb write pointer to 0 */
	snd_hdac_chip_writew(bus, CORBWP, 0);

    // 重置读指针,也就将位置置为0,表示当前还没有读取
	/* reset the corb hw read pointer */
	snd_hdac_chip_writew(bus, CORBRP, AZX_CORBRP_RST);
	if (!bus->corbrp_self_clear)
		azx_clear_corbrp(bus);

    // 启动corb的dma
	/* enable corb dma */
	snd_hdac_chip_writeb(bus, CORBCTL, AZX_CORBCTL_RUN);

	/* RIRB set up */
	// 这是rirb的地址信息,它的地址是从rb的地址加2048来的
bus->rirb.addr = bus->rb.addr + 2048;
	bus->rirb.buf = (__le32 *)(bus->rb.area + 2048);
	bus->rirb.wp = bus->rirb.rp = 0;
	memset(bus->rirb.cmds, 0, sizeof(bus->rirb.cmds));
	snd_hdac_chip_writel(bus, RIRBLBASE, (u32)bus->rirb.addr);
	snd_hdac_chip_writel(bus, RIRBUBASE, upper_32_bits(bus->rirb.addr));

	/* set the r
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值