ASoC: wcd9xxx: Add fix to prevent same RX port added to same virtual port

There is big chance that application could add the same RX port
to same active virtual port. It can cause the linked list tracking
the RX ports to an AIF playback invalid. Add fix to prevent it happening.

Change-Id: I20661a51181d04233d75b964a50a0259dceb9f7d
Signed-off-by: Kuirong Wang <kuirongw@codeaurora.org>
diff --git a/drivers/mfd/wcd9xxx-slimslave.c b/drivers/mfd/wcd9xxx-slimslave.c
index 6e6de37..948cb6e 100644
--- a/drivers/mfd/wcd9xxx-slimslave.c
+++ b/drivers/mfd/wcd9xxx-slimslave.c
@@ -482,3 +482,56 @@
 	return ret;
 }
 EXPORT_SYMBOL_GPL(wcd9xxx_disconnect_port);
+
+/* This function is called with mutex acquired */
+int wcd9xxx_rx_vport_validation(u32 port_id,
+				struct list_head *codec_dai_list)
+{
+	struct wcd9xxx_ch *ch;
+	int ret = 0;
+
+	pr_debug("%s: port_id %u\n", __func__, port_id);
+
+	list_for_each_entry(ch,
+		codec_dai_list, list) {
+		pr_debug("%s: ch->port %u\n", __func__, ch->port);
+		if (ch->port == port_id) {
+			ret = -EINVAL;
+			break;
+		}
+	}
+	return ret;
+}
+EXPORT_SYMBOL_GPL(wcd9xxx_rx_vport_validation);
+
+
+/* This function is called with mutex acquired */
+int wcd9xxx_tx_vport_validation(u32 vtable, u32 port_id,
+				struct wcd9xxx_codec_dai_data *codec_dai)
+{
+	struct wcd9xxx_ch *ch;
+	int ret = 0;
+	u32 index;
+	u32 size = sizeof(vtable) * 8;
+	pr_debug("%s: vtable 0x%x port_id %u size %d\n", __func__,
+		 vtable, port_id, size);
+	for_each_set_bit(index, (unsigned long *)&vtable, size) {
+		list_for_each_entry(ch,
+				    &codec_dai[index].wcd9xxx_ch_list,
+				    list) {
+			pr_debug("%s: index %u ch->port %u vtable 0x%x\n",
+				 __func__, index, ch->port, vtable);
+			if (ch->port == port_id) {
+				pr_err("%s: TX%u is used by AIF%u_CAP Mixer\n",
+					__func__, port_id + 1,
+					(index + 1)/2);
+				ret = -EINVAL;
+				break;
+			}
+		}
+		if (ret)
+			break;
+	}
+	return ret;
+}
+EXPORT_SYMBOL_GPL(wcd9xxx_tx_vport_validation);