Prechádzať zdrojové kódy

Merge "soc: swr-ctrl: Update master controller for WSA mute issue"

Linux Build Service Account 6 rokov pred
rodič
commit
1f7a9de956
4 zmenil súbory, kde vykonal 60 pridanie a 26 odobranie
  1. 3 2
      include/soc/swr-wcd.h
  2. 1 0
      soc/Kbuild
  3. 55 24
      soc/swr-mstr-ctrl.c
  4. 1 0
      soc/swr-mstr-ctrl.h

+ 3 - 2
include/soc/swr-wcd.h

@@ -1,4 +1,4 @@
-/* Copyright (c) 2015, 2017 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015, 2017-2018 The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -30,7 +30,8 @@ struct swr_mstr_port {
 	u8 *port;
 };
 
-#if IS_ENABLED(CONFIG_SOUNDWIRE_WCD_CTRL)
+#if (IS_ENABLED(CONFIG_SOUNDWIRE_WCD_CTRL) || \
+	IS_ENABLED(CONFIG_SOUNDWIRE_MSTR_CTRL))
 extern int swrm_wcd_notify(struct platform_device *pdev, u32 id, void *data);
 #else /* CONFIG_SOUNDWIRE_WCD_CTRL */
 static inline int swrm_wcd_notify(struct platform_device *pdev, u32 id,

+ 1 - 0
soc/Kbuild

@@ -150,6 +150,7 @@ obj-$(CONFIG_SOUNDWIRE) += swr_dlkm.o
 swr_dlkm-y := $(SWR_OBJS)
 
 obj-$(CONFIG_SOUNDWIRE_WCD_CTRL) += swr_ctrl_dlkm.o
+obj-$(CONFIG_SOUNDWIRE_MSTR_CTRL) += swr_ctrl_dlkm.o
 swr_ctrl_dlkm-y := $(SWR_CTRL_OBJS)
 
 # inject some build related information

+ 55 - 24
soc/swr-mstr-ctrl.c

@@ -69,6 +69,8 @@ enum {
 #define SWR_MSTR_RD_BUF_LEN      8
 #define SWR_MSTR_WR_BUF_LEN      32
 
+#define MAX_FIFO_RD_FAIL_RETRY 3
+
 static struct swr_mstr_ctrl *dbgswrm;
 static struct dentry *debugfs_swrm_dent;
 static struct dentry *debugfs_peek;
@@ -243,7 +245,7 @@ static int swrm_clk_request(struct swr_mstr_ctrl *swrm, bool enable)
 static int swrm_ahb_write(struct swr_mstr_ctrl *swrm,
 					u16 reg, u32 *value)
 {
-	u32 temp = (u32)(*value) & 0x000000FF;
+	u32 temp = (u32)(*value);
 	int ret;
 
 	ret = swrm_clk_request(swrm, TRUE);
@@ -253,7 +255,7 @@ static int swrm_ahb_write(struct swr_mstr_ctrl *swrm,
 
 	iowrite32(temp, swrm->swrm_dig_base + reg);
 
-	swrm_clk_request(swrm, TRUE);
+	swrm_clk_request(swrm, FALSE);
 
 	return 0;
 }
@@ -261,7 +263,7 @@ static int swrm_ahb_write(struct swr_mstr_ctrl *swrm,
 static int swrm_ahb_read(struct swr_mstr_ctrl *swrm,
 					u16 reg, u32 *value)
 {
-	u32 temp;
+	u32 temp = 0;
 	int ret;
 
 	ret = swrm_clk_request(swrm, TRUE);
@@ -270,7 +272,7 @@ static int swrm_ahb_read(struct swr_mstr_ctrl *swrm,
 		return -EINVAL;
 
 	temp = ioread32(swrm->swrm_dig_base + reg);
-	*value = (u8)temp;
+	*value = temp;
 	swrm_clk_request(swrm, FALSE);
 	return 0;
 }
@@ -302,8 +304,11 @@ static int swr_master_bulk_write(struct swr_mstr_ctrl *swrm, u32 *reg_addr,
 	if (swrm->bulk_write)
 		swrm->bulk_write(swrm->handle, reg_addr, val, length);
 	else {
-		for (i = 0; i < length; i++)
+		for (i = 0; i < length; i++) {
+		/* wait for FIFO WR command to complete to avoid overflow */
+			usleep_range(100, 105);
 			swr_master_write(swrm, reg_addr[i], val[i]);
+		}
 	}
 	return 0;
 }
@@ -318,10 +323,8 @@ static int swrm_get_port_config(struct swr_mstr_ctrl *swrm)
 	u8 master_device_id;
 	int i;
 
-	if (swrm->version == SWRM_VERSION_1_5)
-		master_device_id = swr_master_read(swrm, SWRM_COMP_MASTER_ID);
-	else
-		master_device_id = MASTER_ID_WSA;
+	/* update device_id for tx/rx */
+	master_device_id = MASTER_ID_WSA;
 
 	switch (master_device_id & MASTER_ID_MASK) {
 	case MASTER_ID_WSA:
@@ -398,15 +401,30 @@ static int swrm_cmd_fifo_rd_cmd(struct swr_mstr_ctrl *swrm, int *cmd_data,
 				 u32 len)
 {
 	u32 val;
+	u32 retry_attempt = 0;
 
 	val = swrm_get_packed_reg_val(&swrm->rcmd_id, len, dev_addr, reg_addr);
+	/* wait for FIFO RD to complete to avoid overflow */
+	usleep_range(100, 105);
 	swr_master_write(swrm, SWRM_CMD_FIFO_RD_CMD, val);
-
+	/* wait for FIFO RD CMD complete to avoid overflow */
+	usleep_range(250, 255);
+retry_read:
 	*cmd_data = swr_master_read(swrm, SWRM_CMD_FIFO_RD_FIFO_ADDR);
 	dev_dbg(swrm->dev,
 		"%s: reg: 0x%x, cmd_id: 0x%x, dev_num: 0x%x, cmd_data: 0x%x\n",
 		__func__, reg_addr, cmd_id, dev_addr, *cmd_data);
-
+	if ((((*cmd_data) & 0xF00) >> 8) != swrm->rcmd_id) {
+		if (retry_attempt < MAX_FIFO_RD_FAIL_RETRY) {
+			/* wait 500 us before retry on fifo read failure */
+			usleep_range(500, 505);
+			retry_attempt++;
+			goto retry_read;
+		} else {
+			dev_err_ratelimited(swrm->dev,
+				"%s: failed to read fifo\n", __func__);
+		}
+	}
 	return 0;
 }
 
@@ -422,12 +440,12 @@ static int swrm_cmd_fifo_wr_cmd(struct swr_mstr_ctrl *swrm, u8 cmd_data,
 	else
 		val = swrm_get_packed_reg_val(&cmd_id, cmd_data,
 					      dev_addr, reg_addr);
-
 	dev_dbg(swrm->dev,
-		"%s: reg: 0x%x, cmd_id: 0x%x, dev_num: 0x%x, cmd_data: 0x%x\n",
-		__func__, reg_addr, cmd_id, dev_addr, cmd_data);
+		"%s: reg: 0x%x, cmd_id: 0x%x, val:0x%x, dev_num: 0x%x, cmd_data: 0x%x\n",
+		__func__, reg_addr, cmd_id, val, dev_addr, cmd_data);
+	/* wait for FIFO WR command to complete to avoid overflow */
+	usleep_range(250, 255);
 	swr_master_write(swrm, SWRM_CMD_FIFO_WR_CMD, val);
-
 	if (cmd_id == 0xF) {
 		/*
 		 * sleep for 10ms for MSM soundwire variant to allow broadcast
@@ -806,9 +824,8 @@ static int swrm_slvdev_datapath_control(struct swr_master *master, bool enable)
 	}
 	mutex_lock(&swrm->mlock);
 
-	/* wakeup soundwire master if in sleep */
-	pm_runtime_get_sync(swrm->dev);
-
+	if (enable)
+		pm_runtime_get_sync(swrm->dev);
 	bank = get_inactive_bank_num(swrm);
 
 	if (enable) {
@@ -816,6 +833,8 @@ static int swrm_slvdev_datapath_control(struct swr_master *master, bool enable)
 		if (ret) {
 			/* cannot accommodate ports */
 			swrm_cleanup_disabled_port_reqs(master);
+			pm_runtime_mark_last_busy(swrm->dev);
+			pm_runtime_put_autosuspend(swrm->dev);
 			mutex_unlock(&swrm->mlock);
 			return -EINVAL;
 		}
@@ -858,8 +877,6 @@ static int swrm_slvdev_datapath_control(struct swr_master *master, bool enable)
 	else {
 		swrm_disable_ports(master, inactive_bank);
 		swrm_cleanup_disabled_port_reqs(master);
-	}
-	if (!swrm_is_port_en(master)) {
 		dev_dbg(&master->dev, "%s: pm_runtime auto suspend triggered\n",
 			__func__);
 		pm_runtime_mark_last_busy(swrm->dev);
@@ -1300,8 +1317,9 @@ static int swrm_probe(struct platform_device *pdev)
 		ret = -EINVAL;
 		goto err_pdata_fail;
 	}
-	if (!(of_property_read_u32(pdev->dev.of_node, "swrm-io-base", NULL)))
-		swrm->swrm_base_reg = of_property_read_u32(pdev->dev.of_node,
+	if (!(of_property_read_u32(pdev->dev.of_node,
+			"swrm-io-base", &swrm->swrm_base_reg)))
+		ret = of_property_read_u32(pdev->dev.of_node,
 			"swrm-io-base", &swrm->swrm_base_reg);
 	if (!swrm->swrm_base_reg) {
 		swrm->read = pdata->read;
@@ -1414,6 +1432,19 @@ static int swrm_probe(struct platform_device *pdev)
 	for (i = 0 ; i < SWR_MSTR_PORT_LEN; i++)
 		INIT_LIST_HEAD(&swrm->mport_cfg[i].port_req_list);
 
+	ret = of_property_read_u32(swrm->dev->of_node, "qcom,swr-num-dev",
+				   &swrm->num_dev);
+	if (ret) {
+		dev_dbg(&pdev->dev, "%s: Looking up %s property failed\n",
+			__func__, "qcom,swr-num-dev");
+	} else {
+		if (swrm->num_dev > SWR_MAX_SLAVE_DEVICES) {
+			dev_err(&pdev->dev, "%s: num_dev %d > max limit %d\n",
+				__func__, swrm->num_dev, SWR_MAX_SLAVE_DEVICES);
+			ret = -EINVAL;
+			goto err_pdata_fail;
+		}
+	}
 	if (swrm->reg_irq) {
 		ret = swrm->reg_irq(swrm->handle, swr_mstr_interrupt, swrm,
 			    SWR_IRQ_REGISTER);
@@ -1427,12 +1458,12 @@ static int swrm_probe(struct platform_device *pdev)
 		if (swrm->irq < 0) {
 			dev_err(swrm->dev, "%s() error getting irq hdle: %d\n",
 					__func__, swrm->irq);
-			goto err_pdata_fail;
+			goto err_irq_fail;
 		}
 
 		ret = request_threaded_irq(swrm->irq, NULL,
 					   swr_mstr_interrupt,
-					   IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+					   IRQF_TRIGGER_RISING | IRQF_ONESHOT,
 					   "swr_master_irq", swrm);
 		if (ret) {
 			dev_err(swrm->dev, "%s: Failed to request irq %d\n",

+ 1 - 0
soc/swr-mstr-ctrl.h

@@ -30,6 +30,7 @@
 
 #define SWR_MAX_CH_PER_PORT 8
 
+#define SWR_MAX_SLAVE_DEVICES 11
 
 enum {
 	SWR_MSTR_PAUSE,