AnsweredAssumed Answered

Route Bluetooth pcm through audmux

Question asked by Philippe De Swert on Aug 23, 2016
Latest reply on Aug 26, 2016 by igorpadykov

Hi all,

 

We're trying to get some PCM audio routed from a BT chip through the audmux. We have checked that the bt chip indeed sends out PCM data. However despite having configured the audmux and a fake audio card we still don't seem to be getting any audio.

 

We have the BT connected with a 4 wire interface as master to port6 of the audmux, we would like to connect this to ssi2 on port2. The BT chip is master, so we put ssi2 in slave mode (devicetree) Currently the audmux ports are configured as follows:

 

port2:

PDCR: 0000a000
PTCR: ad400800
TxFS output from SSI6, TxClk output from SSI6

Port is symmetric

Data recieved from SSI6

 

port6:

PDCR: 00002000
PTCR: 00000800
TxFS input, TxClk input
Port is symmetric
Data received from imx-ssi.1

 

However we do not get any action on our dummy audio driver.

 

The extra driver we have is a simple platform driver, which registers one instance of an audio card, which also does the aumux setting (read from devicetree) and the ssi (also read from devicetree).

 

We have set the pads as inputs (device tree 0x0130b0 and in imx6-pinfunc.h

 

Relevant parts of the driver

audmux setting

 

static int imx_audmux_config(int slave, int master)

{

    unsigned int ptcr, pdcr;

    /*

     * The port numbering in the hardware manual starts at 1, while

     * the audmux API expects it starts at 0.

     */

     slave = slave - 1;

     master = master - 1;

 

     ptcr = IMX_AUDMUX_V2_PTCR_SYN |

            IMX_AUDMUX_V2_PTCR_TFSDIR |

            IMX_AUDMUX_V2_PTCR_TFSEL(master) |

            IMX_AUDMUX_V2_PTCR_TCLKDIR |

            IMX_AUDMUX_V2_PTCR_TCSEL(master);

     pdcr = IMX_AUDMUX_V2_PDCR_RXDSEL(master);

     imx_audmux_v2_configure_port(slave, ptcr, pdcr);

 

     ptcr = IMX_AUDMUX_V2_PTCR_SYN;

     pdcr = IMX_AUDMUX_V2_PDCR_RXDSEL(slave);

     imx_audmux_v2_configure_port(master, ptcr, pdcr);

 

     return 0;

}

 

Reading of port numbers and setting ssi and sound card

static int bt_imx_fake_audio_probe(struct platform_device *pdev)

{

    struct device_node *ssi_np, *np = pdev->dev.of_node;

    struct bt_imx_fake_audio_data *data;

    struct platform_device *ssi_pdev;

    int ret = 0, int_port, ext_port;

 

    dev_info(&pdev->dev, "Probing bt_imx_fake_audio\n");

 

    ret = of_property_read_u32(np, "mux-int-port", &int_port);

    if (ret) {

        dev_err(&pdev->dev,  "mux-int-port missing or invalid\n");

        return ret;

    }

 

    ret = of_property_read_u32(np, "mux-ext-port", &ext_port);

    if (ret) {

        dev_err(&pdev->dev,  "mux-ext-port missing or invalid\n");

        return ret;

    }

    dev_info(&pdev->dev, "Using audmux ports %d and %d \n", int_port, ext_port);

    imx_audmux_config(int_port, ext_port);

 

    ssi_np = of_parse_phandle(pdev->dev.of_node, "ssi-controller", 0);

    if (!ssi_np) {

        dev_err(&pdev->dev,  "phandle missing or invalid\n");

        ret = -EINVAL;

        goto fail;

    }

 

    ssi_pdev = of_find_device_by_node(ssi_np);

    if (!ssi_pdev) {

        dev_err(&pdev->dev,  "failed to find SSI platform device\n");

        ret = -EINVAL;

        goto fail;

    }

 

    data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);

    if (!data) {

        dev_err(&pdev->dev,  "failed to allocate memory\n");

        ret = -ENOMEM;

       goto fail;

    }

   data->dai.name = "BT HFP";

    data->dai.stream_name = "Bluetooth HFP";

    data->dai.codec_dai_name = "snd-soc-dummy-dai";

    data->dai.codec_name = "snd-soc-dummy";

    data->dai.cpu_of_node = ssi_np;

    data->dai.platform_of_node = ssi_np;

    data->dai.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |

                        SND_SOC_DAIFMT_CBM_CFM;

 

    data->card.dev = &pdev->dev;

    data->card.num_links = 1;

    data->card.dai_link = &data->dai;

    data->pdev = platform_device_register_simple("bluetooth", -1, NULL, 0);

    if (IS_ERR(data->pdev)) {

        ret = PTR_ERR(data->pdev);

        dev_err(&pdev->dev,  "register failed: %d\n", ret);

        goto fail;

    }

 

 

    //Fill in the card details

    ret = snd_soc_of_parse_card_name(&data->card, "model");

    if (ret)

        goto fail;

 

    data->card.num_links = 1;

    data->card.owner = THIS_MODULE;

    data->card.dai_link = &data->dai;

    platform_set_drvdata(pdev, &data->card);

    snd_soc_card_set_drvdata(&data->card, data);

    ret = snd_soc_register_card(&data->card);

    if (ret) {

        dev_err(&pdev->dev,  "snd_soc_register_card failed: %d\n", ret);

        goto fail;

    }

 

    // Done, set the driver data.

    platform_set_drvdata(pdev, data);

    printk(KERN_INFO "Imx fake bluetooth audio driver version 0.1 loaded\n");

 

fail:

 

    if (ssi_np)

        of_node_put(ssi_np);

 

    return ret;

}

 

The sound card is there, Alsa lists it nicely. Now when we start bluetooth audio, we can see with the scope we have traffic but no sound comes out. Anybody having any idea what we're missing?

 

Thanks!

Outcomes