soc: swr-ctrl: Update master controller for WSA mute issue

Add delay in master read/write fifo for slave register update.
Handle pm runtime for clock disable to happen after usecase.

Change-Id: Ia1abc4ee3db500cbc8f42b9f08760463fb77acef
Signed-off-by: Laxminath Kasam <lkasam@codeaurora.org>
This commit is contained in:
Laxminath Kasam 2018-07-18 00:38:14 +05:30
parent 8a3699b9ac
commit fbcaf32428
4 changed files with 60 additions and 26 deletions

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2015, 2017 The Linux Foundation. All rights reserved.
/* Copyright (c) 2015, 2017-2018 The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@ -30,7 +30,8 @@ struct swr_mstr_port {
u8 *port;
};
#if IS_ENABLED(CONFIG_SOUNDWIRE_WCD_CTRL)
#if (IS_ENABLED(CONFIG_SOUNDWIRE_WCD_CTRL) || \
IS_ENABLED(CONFIG_SOUNDWIRE_MSTR_CTRL))
extern int swrm_wcd_notify(struct platform_device *pdev, u32 id, void *data);
#else /* CONFIG_SOUNDWIRE_WCD_CTRL */
static inline int swrm_wcd_notify(struct platform_device *pdev, u32 id,

View file

@ -150,6 +150,7 @@ obj-$(CONFIG_SOUNDWIRE) += swr_dlkm.o
swr_dlkm-y := $(SWR_OBJS)
obj-$(CONFIG_SOUNDWIRE_WCD_CTRL) += swr_ctrl_dlkm.o
obj-$(CONFIG_SOUNDWIRE_MSTR_CTRL) += swr_ctrl_dlkm.o
swr_ctrl_dlkm-y := $(SWR_CTRL_OBJS)
# inject some build related information

View file

@ -69,6 +69,8 @@ enum {
#define SWR_MSTR_RD_BUF_LEN 8
#define SWR_MSTR_WR_BUF_LEN 32
#define MAX_FIFO_RD_FAIL_RETRY 3
static struct swr_mstr_ctrl *dbgswrm;
static struct dentry *debugfs_swrm_dent;
static struct dentry *debugfs_peek;
@ -243,7 +245,7 @@ static int swrm_clk_request(struct swr_mstr_ctrl *swrm, bool enable)
static int swrm_ahb_write(struct swr_mstr_ctrl *swrm,
u16 reg, u32 *value)
{
u32 temp = (u32)(*value) & 0x000000FF;
u32 temp = (u32)(*value);
int ret;
ret = swrm_clk_request(swrm, TRUE);
@ -253,7 +255,7 @@ static int swrm_ahb_write(struct swr_mstr_ctrl *swrm,
iowrite32(temp, swrm->swrm_dig_base + reg);
swrm_clk_request(swrm, TRUE);
swrm_clk_request(swrm, FALSE);
return 0;
}
@ -261,7 +263,7 @@ static int swrm_ahb_write(struct swr_mstr_ctrl *swrm,
static int swrm_ahb_read(struct swr_mstr_ctrl *swrm,
u16 reg, u32 *value)
{
u32 temp;
u32 temp = 0;
int ret;
ret = swrm_clk_request(swrm, TRUE);
@ -270,7 +272,7 @@ static int swrm_ahb_read(struct swr_mstr_ctrl *swrm,
return -EINVAL;
temp = ioread32(swrm->swrm_dig_base + reg);
*value = (u8)temp;
*value = temp;
swrm_clk_request(swrm, FALSE);
return 0;
}
@ -302,8 +304,11 @@ static int swr_master_bulk_write(struct swr_mstr_ctrl *swrm, u32 *reg_addr,
if (swrm->bulk_write)
swrm->bulk_write(swrm->handle, reg_addr, val, length);
else {
for (i = 0; i < length; i++)
for (i = 0; i < length; i++) {
/* wait for FIFO WR command to complete to avoid overflow */
usleep_range(100, 105);
swr_master_write(swrm, reg_addr[i], val[i]);
}
}
return 0;
}
@ -318,10 +323,8 @@ static int swrm_get_port_config(struct swr_mstr_ctrl *swrm)
u8 master_device_id;
int i;
if (swrm->version == SWRM_VERSION_1_5)
master_device_id = swr_master_read(swrm, SWRM_COMP_MASTER_ID);
else
master_device_id = MASTER_ID_WSA;
/* update device_id for tx/rx */
master_device_id = MASTER_ID_WSA;
switch (master_device_id & MASTER_ID_MASK) {
case MASTER_ID_WSA:
@ -398,15 +401,30 @@ static int swrm_cmd_fifo_rd_cmd(struct swr_mstr_ctrl *swrm, int *cmd_data,
u32 len)
{
u32 val;
u32 retry_attempt = 0;
val = swrm_get_packed_reg_val(&swrm->rcmd_id, len, dev_addr, reg_addr);
/* wait for FIFO RD to complete to avoid overflow */
usleep_range(100, 105);
swr_master_write(swrm, SWRM_CMD_FIFO_RD_CMD, val);
/* wait for FIFO RD CMD complete to avoid overflow */
usleep_range(250, 255);
retry_read:
*cmd_data = swr_master_read(swrm, SWRM_CMD_FIFO_RD_FIFO_ADDR);
dev_dbg(swrm->dev,
"%s: reg: 0x%x, cmd_id: 0x%x, dev_num: 0x%x, cmd_data: 0x%x\n",
__func__, reg_addr, cmd_id, dev_addr, *cmd_data);
if ((((*cmd_data) & 0xF00) >> 8) != swrm->rcmd_id) {
if (retry_attempt < MAX_FIFO_RD_FAIL_RETRY) {
/* wait 500 us before retry on fifo read failure */
usleep_range(500, 505);
retry_attempt++;
goto retry_read;
} else {
dev_err_ratelimited(swrm->dev,
"%s: failed to read fifo\n", __func__);
}
}
return 0;
}
@ -422,12 +440,12 @@ static int swrm_cmd_fifo_wr_cmd(struct swr_mstr_ctrl *swrm, u8 cmd_data,
else
val = swrm_get_packed_reg_val(&cmd_id, cmd_data,
dev_addr, reg_addr);
dev_dbg(swrm->dev,
"%s: reg: 0x%x, cmd_id: 0x%x, dev_num: 0x%x, cmd_data: 0x%x\n",
__func__, reg_addr, cmd_id, dev_addr, cmd_data);
"%s: reg: 0x%x, cmd_id: 0x%x, val:0x%x, dev_num: 0x%x, cmd_data: 0x%x\n",
__func__, reg_addr, cmd_id, val, dev_addr, cmd_data);
/* wait for FIFO WR command to complete to avoid overflow */
usleep_range(250, 255);
swr_master_write(swrm, SWRM_CMD_FIFO_WR_CMD, val);
if (cmd_id == 0xF) {
/*
* sleep for 10ms for MSM soundwire variant to allow broadcast
@ -806,9 +824,8 @@ static int swrm_slvdev_datapath_control(struct swr_master *master, bool enable)
}
mutex_lock(&swrm->mlock);
/* wakeup soundwire master if in sleep */
pm_runtime_get_sync(swrm->dev);
if (enable)
pm_runtime_get_sync(swrm->dev);
bank = get_inactive_bank_num(swrm);
if (enable) {
@ -816,6 +833,8 @@ static int swrm_slvdev_datapath_control(struct swr_master *master, bool enable)
if (ret) {
/* cannot accommodate ports */
swrm_cleanup_disabled_port_reqs(master);
pm_runtime_mark_last_busy(swrm->dev);
pm_runtime_put_autosuspend(swrm->dev);
mutex_unlock(&swrm->mlock);
return -EINVAL;
}
@ -858,8 +877,6 @@ static int swrm_slvdev_datapath_control(struct swr_master *master, bool enable)
else {
swrm_disable_ports(master, inactive_bank);
swrm_cleanup_disabled_port_reqs(master);
}
if (!swrm_is_port_en(master)) {
dev_dbg(&master->dev, "%s: pm_runtime auto suspend triggered\n",
__func__);
pm_runtime_mark_last_busy(swrm->dev);
@ -1300,8 +1317,9 @@ static int swrm_probe(struct platform_device *pdev)
ret = -EINVAL;
goto err_pdata_fail;
}
if (!(of_property_read_u32(pdev->dev.of_node, "swrm-io-base", NULL)))
swrm->swrm_base_reg = of_property_read_u32(pdev->dev.of_node,
if (!(of_property_read_u32(pdev->dev.of_node,
"swrm-io-base", &swrm->swrm_base_reg)))
ret = of_property_read_u32(pdev->dev.of_node,
"swrm-io-base", &swrm->swrm_base_reg);
if (!swrm->swrm_base_reg) {
swrm->read = pdata->read;
@ -1414,6 +1432,19 @@ static int swrm_probe(struct platform_device *pdev)
for (i = 0 ; i < SWR_MSTR_PORT_LEN; i++)
INIT_LIST_HEAD(&swrm->mport_cfg[i].port_req_list);
ret = of_property_read_u32(swrm->dev->of_node, "qcom,swr-num-dev",
&swrm->num_dev);
if (ret) {
dev_dbg(&pdev->dev, "%s: Looking up %s property failed\n",
__func__, "qcom,swr-num-dev");
} else {
if (swrm->num_dev > SWR_MAX_SLAVE_DEVICES) {
dev_err(&pdev->dev, "%s: num_dev %d > max limit %d\n",
__func__, swrm->num_dev, SWR_MAX_SLAVE_DEVICES);
ret = -EINVAL;
goto err_pdata_fail;
}
}
if (swrm->reg_irq) {
ret = swrm->reg_irq(swrm->handle, swr_mstr_interrupt, swrm,
SWR_IRQ_REGISTER);
@ -1427,12 +1458,12 @@ static int swrm_probe(struct platform_device *pdev)
if (swrm->irq < 0) {
dev_err(swrm->dev, "%s() error getting irq hdle: %d\n",
__func__, swrm->irq);
goto err_pdata_fail;
goto err_irq_fail;
}
ret = request_threaded_irq(swrm->irq, NULL,
swr_mstr_interrupt,
IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
"swr_master_irq", swrm);
if (ret) {
dev_err(swrm->dev, "%s: Failed to request irq %d\n",

View file

@ -30,6 +30,7 @@
#define SWR_MAX_CH_PER_PORT 8
#define SWR_MAX_SLAVE_DEVICES 11
enum {
SWR_MSTR_PAUSE,