Browse Source

asoc: qcs405: Add support for ep92 HDMI bridge chip

Add support for ep92 HDMI bridge chip for QCS405 platform

Change-Id: Ifa8a6e60cee69c88276b50d5f61b3e13fac82b60
Signed-off-by: Ralf Herz <[email protected]>
Ralf Herz 6 years ago
parent
commit
6d96dd41d3
1 changed files with 119 additions and 0 deletions
  1. 119 0
      asoc/qcs405.c

+ 119 - 0
asoc/qcs405.c

@@ -16,6 +16,7 @@
 #include <linux/of_gpio.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
+#include <linux/i2c.h>
 #include <linux/io.h>
 #include <linux/module.h>
 #include <linux/input.h>
@@ -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; i<ARRAY_SIZE(msm_mi2s_be_dai_links); i++) {
+		if (strcmp(dai->name, 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; i<ARRAY_SIZE(msm_spdif_be_dai_links); i++) {
+		if (strcmp(dai->name, 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__);