From 3d1596e2c60f1bc1be2e7719e437451262b48f12 Mon Sep 17 00:00:00 2001 From: Sudheer Papothi Date: Sat, 27 Oct 2018 06:19:18 +0530 Subject: [PATCH] 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 --- include/soc/swr-common.h | 45 +++++++++++++++++++++++++ include/soc/swr-wcd.h | 1 + soc/swr-mstr-ctrl.c | 72 +++++++++++++++++++++++++++++++++++++++- soc/swr-mstr-ctrl.h | 15 ++------- 4 files changed, 120 insertions(+), 13 deletions(-) create mode 100644 include/soc/swr-common.h diff --git a/include/soc/swr-common.h b/include/soc/swr-common.h new file mode 100644 index 0000000000..92b79c79a9 --- /dev/null +++ b/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 +#include +#include +#include + +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 */ diff --git a/include/soc/swr-wcd.h b/include/soc/swr-wcd.h index 0f1762545e..ad129c8327 100644 --- a/include/soc/swr-wcd.h +++ b/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 { diff --git a/soc/swr-mstr-ctrl.c b/soc/swr-mstr-ctrl.c index 26433539ea..2379df88b8 100644 --- a/soc/swr-mstr-ctrl.c +++ b/soc/swr-mstr-ctrl.c @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include #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); diff --git a/soc/swr-mstr-ctrl.h b/soc/swr-mstr-ctrl.h index 8582c51ea9..afbbe46829 100644 --- a/soc/swr-mstr-ctrl.h +++ b/soc/swr-mstr-ctrl.h @@ -9,6 +9,7 @@ #include #include #include +#include #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 */