Prechádzať zdrojové kódy

asoc: codecs: Enable custom WSA SWRS port settings

For PBR and CPS ports, need the ability to customized slave
SWR frame OFFSET1 settings. Add similar method to WCD TX where
offset1 and lane_ctrl parameters are parsed from WSA device tree
and configured in SWRM.

Change-Id: Ib973ed93d9daa5ba02461a156e5b0a8c816d371e
Signed-off-by: Matthew Rice <[email protected]>
Matthew Rice 3 rokov pred
rodič
commit
3a6ef472dd

+ 2 - 0
asoc/codecs/wsa884x/internal.h

@@ -376,6 +376,8 @@ struct wsa884x_priv {
 	u8 dev_index;
 	struct irq_domain *virq;
 	struct wcd_irq_info irq_info;
+	struct swr_port_params wsa_port_params[SWR_UC_MAX][WSA884X_MAX_SWR_PORTS];
+	struct swr_dev_frame_config swr_wsa_port_params[SWR_UC_MAX];
 #ifdef CONFIG_DEBUG_FS
 	struct dentry *debugfs_dent;
 	struct dentry *debugfs_peek;

+ 66 - 1
asoc/codecs/wsa884x/wsa884x.c

@@ -1779,6 +1779,65 @@ static int wsa884x_event_notify(struct notifier_block *nb,
 	return 0;
 }
 
+static int wsa884x_parse_port_params(struct device *dev, char *prop)
+{
+	u32 *dt_array, map_size, max_uc;
+	int ret = 0;
+	u32 cnt = 0;
+	u32 i, j;
+	struct swr_port_params (*map)[SWR_UC_MAX][WSA884X_MAX_SWR_PORTS];
+	struct swr_dev_frame_config (*map_uc)[SWR_UC_MAX];
+	struct wsa884x_priv *wsa884x = dev_get_drvdata(dev);
+
+	map = &wsa884x->wsa_port_params;
+	map_uc = &wsa884x->swr_wsa_port_params;
+
+	if (!of_find_property(dev->of_node, prop,
+				&map_size)) {
+		dev_err(dev, "missing port mapping prop %s\n", prop);
+		ret = -EINVAL;
+		goto err_port_map;
+	}
+
+	max_uc = map_size / (WSA884X_MAX_SWR_PORTS * SWR_PORT_PARAMS * sizeof(u32));
+
+	if (max_uc != SWR_UC_MAX) {
+		dev_err(dev, "%s: port params not provided for all usecases\n",
+			__func__);
+		ret = -EINVAL;
+		goto err_port_map;
+	}
+	dt_array = kzalloc(map_size, GFP_KERNEL);
+
+	if (!dt_array) {
+		ret = -ENOMEM;
+		goto err_port_map;
+	}
+	ret = of_property_read_u32_array(dev->of_node, prop, dt_array,
+				WSA884X_MAX_SWR_PORTS * SWR_PORT_PARAMS * max_uc);
+	if (ret) {
+		dev_err(dev, "%s: Failed to read port mapping from prop %s\n",
+					__func__, prop);
+		goto err_pdata_fail;
+	}
+
+	for (i = 0; i < max_uc; i++) {
+		for (j = 0; j < WSA884X_MAX_SWR_PORTS; j++) {
+			cnt = (i * WSA884X_MAX_SWR_PORTS + j) * SWR_PORT_PARAMS;
+			(*map)[i][j].offset1 = dt_array[cnt];
+			(*map)[i][j].lane_ctrl = dt_array[cnt + 1];
+		}
+		(*map_uc)[i].pp = &(*map)[i][0];
+	}
+	kfree(dt_array);
+	return 0;
+
+err_pdata_fail:
+	kfree(dt_array);
+err_port_map:
+	return ret;
+}
+
 static int wsa884x_enable_supplies(struct device *dev,
 				   struct wsa884x_priv *priv)
 {
@@ -2133,7 +2192,13 @@ static int wsa884x_swr_probe(struct swr_device *pdev)
 		snd_soc_component_update_bits(component,
 			REG_FIELD_VALUE(TOP_CTRL1,
 			OCP_LOWVBAT_ITH_SEL_EN, 0x00));
-
+	ret = wsa884x_parse_port_params(&pdev->dev, "qcom,swr-wsa-port-params");
+	swr_init_port_params(wsa884x->swr_slave, WSA884X_MAX_SWR_PORTS,
+		wsa884x->swr_wsa_port_params);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to read port params\n");
+		goto err;
+	}
 	mutex_init(&wsa884x->res_lock);
 
 #ifdef CONFIG_DEBUG_FS

+ 10 - 0
include/bindings/audio-codec-port-types.h

@@ -20,6 +20,16 @@
 #define OFFSET1_VAL13 13
 #define OFFSET1_VAL14 14
 #define OFFSET1_VAL15 15
+#define OFFSET1_VAL16 16
+#define OFFSET1_VAL17 17
+#define OFFSET1_VAL18 18
+#define OFFSET1_VAL19 19
+#define OFFSET1_VAL20 20
+#define OFFSET1_VAL21 21
+#define OFFSET1_VAL22 22
+#define OFFSET1_VAL23 23
+#define OFFSET1_VAL24 24
+#define OFFSET1_VAL25 25
 
 #define LANE0 0
 #define LANE1 1

+ 10 - 0
soc/swr-mstr-ctrl.c

@@ -1428,6 +1428,16 @@ static void swrm_get_device_frame_shape(struct swr_mstr_ctrl *swrm,
 		port_req->blk_grp_count = mport->blk_grp_count;
 		port_req->lane_ctrl = mport->lane_ctrl;
 	}
+	if (swrm->master_id == MASTER_ID_WSA) {
+		uc = swrm_get_uc(swrm->bus_clk);
+		port_id_offset = (port_req->dev_num - 1) *
+					SWR_MAX_DEV_PORT_NUM +
+					port_req->slave_port_id;
+		if (port_id_offset >= SWR_MAX_MSTR_PORT_NUM ||
+			!swrm->pp[uc][port_id_offset].offset1)
+			return;
+		port_req->offset1 = swrm->pp[uc][port_id_offset].offset1;
+	}
 }
 
 static void swrm_copy_data_port_config(struct swr_master *master, u8 bank)