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 <spapothi@codeaurora.org>
This commit is contained in:
Sudheer Papothi 2018-10-27 06:19:18 +05:30 committed by Karthikeyan Mani
parent d0dd6a6284
commit 3d1596e2c6
4 changed files with 120 additions and 13 deletions

45
include/soc/swr-common.h Normal file
View file

@ -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 */

View file

@ -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 {

View file

@ -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);

View file

@ -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 */