Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6d96dd41 authored by Ralf Herz's avatar Ralf Herz
Browse files

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: default avatarRalf Herz <rherz@codeaurora.org>
parent ed30d2c2
Loading
Loading
Loading
Loading
+119 −0
Original line number Diff line number Diff line
@@ -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__);