Sending VS commands to Wilink from kernel driver

I’m trying to set up an audio codec driver for the TI Wilink that is able to send the proper command to the Wilink to set up its PCM according to the sample rate being requested.

Here is the function I’ve written for it;

static int bt_sco_hw_params(struct snd_pcm_substream *substream,
			    struct snd_pcm_hw_params *params,
			    struct snd_soc_dai *cpu_dai)
{
	u8 rate8k = 1;
	u8 pcm8k[34] = {0x00, 0x02, 0x01, 0x40, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x01, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x21, 0x00, 0x01, 0x10, 0x00, 0x21, 0x00, 0x00, 0x00};
	u8 pcm16k[34] = {0x00, 0x04, 0x01, 0x80, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x01, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x21, 0x00, 0x01, 0x10, 0x00, 0x21, 0x00, 0x00, 0x00};
	u8 *pcm;
	struct hci_dev *hdev;

	switch (params_rate(params)) {
	case 8000:
		pcm = pcm8k;
		break;
	case 16000:
		pcm = pcm16k;
		break;
	default:
		dev_err(cpu_dai->dev, "Bad rate: %d\n", params_rate(params));
		return -EINVAL;
	}
	if ((hdev = hci_dev_get(0))){
		hci_send_cmd(hdev, 0xfd06, 34, pcm);
	}

	return 0;
}

Now here is the thing… it “kind of” works.
What I mean by that is this; if I enable dut mode via modified mcap_tool, then it works and I get clear audio. If I don’t enable dut mode, then it does not work.

I’ve tried enabling dut mode via debugfs (echo “Y” > dut_mode), but that has no effect at all on the hardware.

Anyone have any ideas?

Nevermind that question. Turns out it actually is working.
I just ran into a bit of… unexpected behavior during testing.

Up to this point, it has always established an 8k connection during testing. But it turns out that it was something about DUT mode that was causing it to fall back to 8k. After I implemented that kernel driver, the bluetooth started negotiating a 16k link, which I didn’t notice, but there was still a request for the 8k mode for the alsa driver, which means that it was setting up the BT PCM for 8k when the stream was running at 16k.

With a quick hack from SCO between iPhone and hikey960 - #6 by Loic I have it now working at 8k on boot without any manual intervention.

Great, did you integrate this to the TI BT driver itself (drivers/bluetooth/hci_ll.c) ? This could allow to potentially configure BT sco/audio via device-tree.

No. I forked the bt-sco alsa driver into a new driver for wilink8, and implemented the bluetooth VS commands from there. In this way, it is the parameters you send to alsa that triggers setting up the bluetooth PCM appropriately. I’m not aware of any sensible way to do it from the bluetooth driver without something coming from alsa.

This is the driver here;

There is some room for improvement, of course.

  • its hard coded to the first hci device (/dev/hci0), the proper association should probably be made through the device tree.
  • It has two sample rates hard coded rather than being generated from data set in the device tree.
  • Its set up for 2 channels, mainly because I’m stumped when it comes to getting the hisi-i2s working in 1 channel mode. I’ve implemented some channel manipulations in the HAL to work around this.