diff --git a/asoc/qcs405.c b/asoc/qcs405.c index 1f62d66683c8..8989bf7b1541 100644 --- a/asoc/qcs405.c +++ b/asoc/qcs405.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -7527,6 +7528,119 @@ static void msm_i2s_auxpcm_deinit(void) } } +static int msm_scan_i2c_addr(struct platform_device *pdev, + uint32_t busnum, uint32_t addr) +{ + struct i2c_adapter *adap; + u8 rbuf; + struct i2c_msg msg; + int status = 0; + + adap = i2c_get_adapter(busnum); + if (!adap) { + dev_err(&pdev->dev, "%s: Cannot get I2C adapter %d\n", + __func__, busnum); + return -EBUSY; + } + + /* to test presence, read one byte from device */ + msg.addr = addr; + msg.flags = I2C_M_RD; + msg.len = 1; + msg.buf = &rbuf; + + status = i2c_transfer(adap, &msg, 1); + + i2c_put_adapter(adap); + + if (status != 1) { + dev_dbg(&pdev->dev, "%s: I2C read from addr 0x%02x failed\n", + __func__, addr); + return -ENODEV; + } + + dev_dbg(&pdev->dev, "%s: I2C read from addr 0x%02x successful\n", + __func__, addr); + + return 0; +} + +static int msm_detect_ep92_dev(struct platform_device *pdev, + struct snd_soc_card *card) +{ + int i; + uint32_t ep92_busnum = 0; + uint32_t ep92_reg = 0; + const char *ep92_name = NULL; + struct snd_soc_dai_link *dai; + int rc = 0; + + rc = of_property_read_u32(pdev->dev.of_node, "qcom,ep92-busnum", + &ep92_busnum); + if (rc) { + dev_info(&pdev->dev, "%s: No DT match ep92-reg\n", __func__); + return 0; + } + + rc = of_property_read_u32(pdev->dev.of_node, "qcom,ep92-reg", + &ep92_reg); + if (rc) { + dev_info(&pdev->dev, "%s: No DT match ep92-busnum\n", __func__); + return 0; + } + + rc = of_property_read_string(pdev->dev.of_node, "qcom,ep92-name", + &ep92_name); + if (rc) { + dev_info(&pdev->dev, "%s: No DT match ep92-name\n", __func__); + return 0; + } + + /* check I2C bus for connected ep92 chip */ + if (msm_scan_i2c_addr(pdev, ep92_busnum, ep92_reg) < 0) { + /* check a second time after a short delay */ + msleep(20); + if (msm_scan_i2c_addr(pdev, ep92_busnum, ep92_reg) < 0) { + dev_info(&pdev->dev, "%s: No ep92 device found\n", + __func__); + /* continue with snd_card registration without ep92 */ + return 0; + } + } + + dev_info(&pdev->dev, "%s: ep92 device found\n", __func__); + + /* update codec info in MI2S dai link */ + dai = &msm_mi2s_be_dai_links[0]; + for (i=0; iname, LPASS_BE_SEC_MI2S_TX) == 0) { + dev_dbg(&pdev->dev, + "%s: Set Sec MI2S dai to ep92 codec\n", + __func__); + dai->codec_name = ep92_name; + dai->codec_dai_name = "ep92-hdmi"; + break; + } + dai++; + } + + /* update codec info in SPDIF dai link */ + dai = &msm_spdif_be_dai_links[0]; + for (i=0; iname, LPASS_BE_SEC_SPDIF_TX) == 0) { + dev_dbg(&pdev->dev, + "%s: Set Sec SPDIF dai to ep92 codec\n", + __func__); + dai->codec_name = ep92_name; + dai->codec_dai_name = "ep92-arc"; + break; + } + dai++; + } + + return 0; +} + static int msm_asoc_machine_probe(struct platform_device *pdev) { struct snd_soc_card *card; @@ -7544,6 +7658,11 @@ static int msm_asoc_machine_probe(struct platform_device *pdev) if (!pdata) return -ENOMEM; + /* test for ep92 HDMI bridge and update dai links accordingly */ + ret = msm_detect_ep92_dev(pdev, card); + if (ret) + goto err; + card = populate_snd_card_dailinks(&pdev->dev); if (!card) { dev_err(&pdev->dev, "%s: Card uninitialized\n", __func__);