소스 검색

soc: swr-mstr: Add support for platform specific port configuration

Different platforms have different configuration for soundwire
ports. Add support to get the port configuration information
from the machine driver.

Change-Id: If2c006c4d4a43e2a8dc67c076f6d1c0f36eae16b
Signed-off-by: Sudheer Papothi <[email protected]>
Sudheer Papothi 6 년 전
부모
커밋
3d1596e2c6
4개의 변경된 파일120개의 추가작업 그리고 13개의 파일을 삭제
  1. 45 0
      include/soc/swr-common.h
  2. 1 0
      include/soc/swr-wcd.h
  3. 71 1
      soc/swr-mstr-ctrl.c
  4. 3 12
      soc/swr-mstr-ctrl.h

+ 45 - 0
include/soc/swr-common.h

@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2015, 2017-2018 The Linux Foundation. All rights reserved.
+ */
+
+#ifndef _LINUX_SWR_COMMON_H
+#define _LINUX_SWR_COMMON_H
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/device.h>
+#include <linux/bitops.h>
+
+enum {
+	SWR_UC0 = 0,
+	SWR_UC1,
+	SWR_UC_MAX,
+};
+
+struct port_params {
+	u8 si;
+	u8 off1;
+	u8 off2;
+	u8 hstart;/* head start */
+	u8 hstop; /* head stop */
+	u8 wd_len;/* word length */
+	u8 bp_mode; /* block pack mode */
+	u8 bgp_ctrl;/* block group control */
+	u8 lane_ctrl;/* lane to be used */
+};
+
+struct swrm_port_config {
+	u32 size;
+	u32 uc;
+	void *params;
+};
+
+struct swr_mstr_port_map {
+	u32 id;
+	u32 uc;
+	struct port_params *swr_port_params;
+};
+
+#define SWR_MSTR_PORT_LEN      8 /* Number of master ports */
+
+#endif /* _LINUX_SWR_COMMON_H */

+ 1 - 0
include/soc/swr-wcd.h

@@ -20,6 +20,7 @@ enum {
 	SWR_DEVICE_SSR_DOWN,
 	SWR_DEVICE_SSR_UP,
 	SWR_REGISTER_WAKE_IRQ,
+	SWR_SET_PORT_MAP,
 };
 
 struct swr_mstr_port {

+ 71 - 1
soc/swr-mstr-ctrl.c

@@ -19,7 +19,7 @@
 #include <linux/debugfs.h>
 #include <linux/uaccess.h>
 #include <soc/soundwire.h>
-#include <soc/swr-wcd.h>
+#include <soc/swr-common.h>
 #include <linux/regmap.h>
 #include <dsp/msm-audio-event-notify.h>
 #include "swrm_registers.h"
@@ -28,6 +28,7 @@
 
 #define SWRM_SYSTEM_RESUME_TIMEOUT_MS 700
 #define SWRM_SYS_SUSPEND_WAIT 1
+
 #define SWR_BROADCAST_CMD_ID            0x0F
 #define SWR_AUTO_SUSPEND_DELAY          3 /* delay in sec */
 #define SWR_DEV_ID_MASK			0xFFFFFFFFFFFF
@@ -2187,6 +2188,53 @@ int swrm_register_wake_irq(struct swr_mstr_ctrl *swrm)
 	return ret;
 }
 
+static int swrm_alloc_port_mem(struct device *dev, struct swr_mstr_ctrl *swrm,
+				u32 uc, u32 size)
+{
+	if (!swrm->port_param) {
+		swrm->port_param = devm_kzalloc(dev,
+					sizeof(swrm->port_param) * SWR_UC_MAX,
+					GFP_KERNEL);
+		if (!swrm->port_param)
+			return -ENOMEM;
+	}
+	if (!swrm->port_param[uc]) {
+		swrm->port_param[uc] = devm_kcalloc(dev, size,
+					sizeof(struct port_params),
+					GFP_KERNEL);
+		if (!swrm->port_param[uc])
+			return -ENOMEM;
+	} else {
+		dev_err_ratelimited(swrm->dev, "%s: called more than once\n",
+				    __func__);
+	}
+
+	return 0;
+}
+
+static int swrm_copy_port_config(struct swr_mstr_ctrl *swrm,
+				struct swrm_port_config *port_cfg,
+				u32 size)
+{
+	int idx;
+	struct port_params *params;
+	int uc = port_cfg->uc;
+	int ret = 0;
+
+	for (idx = 0; idx < size; idx++) {
+		params = &((struct port_params *)port_cfg->params)[idx];
+		if (!params) {
+			dev_err(swrm->dev, "%s: Invalid params\n", __func__);
+			ret = -EINVAL;
+			break;
+		}
+		memcpy(&swrm->port_param[uc][idx], params,
+					sizeof(struct port_params));
+	}
+
+	return ret;
+}
+
 /**
  * swrm_wcd_notify - parent device can notify to soundwire master through
  * this function
@@ -2200,6 +2248,7 @@ int swrm_wcd_notify(struct platform_device *pdev, u32 id, void *data)
 	int ret = 0;
 	struct swr_master *mstr;
 	struct swr_device *swr_dev;
+	struct swrm_port_config *port_cfg;
 
 	if (!pdev) {
 		pr_err("%s: pdev is NULL\n", __func__);
@@ -2327,6 +2376,27 @@ int swrm_wcd_notify(struct platform_device *pdev, u32 id, void *data)
 			mutex_unlock(&swrm->mlock);
 		}
 		break;
+	case SWR_SET_PORT_MAP:
+		if (!data) {
+			dev_err(swrm->dev, "%s: data is NULL for id=%d\n",
+				__func__, id);
+			ret = -EINVAL;
+		} else {
+			mutex_lock(&swrm->mlock);
+			port_cfg = (struct swrm_port_config *)data;
+			if (!port_cfg->size) {
+				ret = -EINVAL;
+				goto done;
+			}
+			ret = swrm_alloc_port_mem(&pdev->dev, swrm,
+						port_cfg->uc, port_cfg->size);
+			if (!ret)
+				swrm_copy_port_config(swrm, port_cfg,
+						      port_cfg->size);
+done:
+			mutex_unlock(&swrm->mlock);
+		}
+		break;
 	default:
 		dev_err(swrm->dev, "%s: swr master unknown id %d\n",
 			__func__, id);

+ 3 - 12
soc/swr-mstr-ctrl.h

@@ -9,6 +9,7 @@
 #include <soc/swr-wcd.h>
 #include <linux/pm_qos.h>
 #include <soc/qcom/pm.h>
+#include <soc/swr-common.h>
 
 #define SWR_ROW_48		0
 #define SWR_ROW_50		1
@@ -61,18 +62,6 @@ struct usecase {
 	u32 chrate;
 };
 
-struct port_params {
-	u8 si;
-	u8 off1;
-	u8 off2;
-	u8 hstart;/* head start */
-	u8 hstop; /* head stop */
-	u8 wd_len;/* word length */
-	u8 bp_mode; /* block pack mode */
-	u8 bgp_ctrl;/* block group control */
-	u8 lane_ctrl;/* lane to be used */
-};
-
 struct swrm_mports {
 	struct list_head port_req_list;
 	bool port_en;
@@ -163,6 +152,8 @@ struct swr_mstr_ctrl {
 	wait_queue_head_t pm_wq;
 	int wlock_holders;
 	u32 intr_mask;
+	struct port_params **port_param;
+	u8 num_usecase;
 };
 
 #endif /* _SWR_WCD_CTRL_H */