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:
parent
d0dd6a6284
commit
3d1596e2c6
4 changed files with 120 additions and 13 deletions
45
include/soc/swr-common.h
Normal file
45
include/soc/swr-common.h
Normal 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 */
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in a new issue