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:
parent
8a3699b9ac
commit
fbcaf32428
4 changed files with 60 additions and 26 deletions
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
#define SWR_MAX_CH_PER_PORT 8
|
||||
|
||||
#define SWR_MAX_SLAVE_DEVICES 11
|
||||
|
||||
enum {
|
||||
SWR_MSTR_PAUSE,
|
||||
|
|
Loading…
Add table
Reference in a new issue