soc: swr-mstr: Fix headset detection during sva clk switch

Headset insertion/removal is not detected sometime due to
fifo read failure due to swr underflow. This is because if
headset sva is enabled, during clk switch swr force stop
happens and if mbhc has already taken pm vote for 3sec
further mbhc reads/writes will fail. If swr is in clk switch
mode then call swrm runtime_resume during reads/writes
to resolve issue.

Change-Id: I0d65869bd1c645bbf7ded9c0265f8d7de0dc624b
Signed-off-by: Vatsal Bucha <vbucha@codeaurora.org>
This commit is contained in:
Vatsal Bucha 2020-06-08 10:41:56 +05:30
parent 6015c2a3b4
commit bd68a7c023
2 changed files with 25 additions and 8 deletions

View file

@ -96,7 +96,7 @@ static bool swrm_lock_sleep(struct swr_mstr_ctrl *swrm);
static void swrm_unlock_sleep(struct swr_mstr_ctrl *swrm);
static u32 swr_master_read(struct swr_mstr_ctrl *swrm, unsigned int reg_addr);
static void swr_master_write(struct swr_mstr_ctrl *swrm, u16 reg_addr, u32 val);
static int swrm_runtime_resume(struct device *dev);
static u8 swrm_get_clk_div(int mclk_freq, int bus_clk_freq)
{
@ -853,6 +853,8 @@ static int swrm_read(struct swr_master *master, u8 dev_num, u16 reg_addr,
mutex_unlock(&swrm->devlock);
pm_runtime_get_sync(swrm->dev);
if (swrm->req_clk_switch)
swrm_runtime_resume(swrm->dev);
ret = swrm_cmd_fifo_rd_cmd(swrm, &val, dev_num, 0, reg_addr, len);
if (!ret)
@ -886,6 +888,8 @@ static int swrm_write(struct swr_master *master, u8 dev_num, u16 reg_addr,
mutex_unlock(&swrm->devlock);
pm_runtime_get_sync(swrm->dev);
if (swrm->req_clk_switch)
swrm_runtime_resume(swrm->dev);
ret = swrm_cmd_fifo_wr_cmd(swrm, reg_val, dev_num, 0, reg_addr);
pm_runtime_put_autosuspend(swrm->dev);
@ -2032,16 +2036,22 @@ static irqreturn_t swr_mstr_interrupt_v2(int irq, void *dev)
swrm->intr_mask);
break;
case SWRM_INTERRUPT_STATUS_RD_FIFO_OVERFLOW:
dev_dbg(swrm->dev, "%s: SWR read FIFO overflow\n",
__func__);
value = swr_master_read(swrm, SWRM_CMD_FIFO_STATUS);
dev_err(swrm->dev,
"%s: SWR read FIFO overflow fifo status 0x%x\n",
__func__, value);
break;
case SWRM_INTERRUPT_STATUS_RD_FIFO_UNDERFLOW:
dev_dbg(swrm->dev, "%s: SWR read FIFO underflow\n",
__func__);
value = swr_master_read(swrm, SWRM_CMD_FIFO_STATUS);
dev_err(swrm->dev,
"%s: SWR read FIFO underflow fifo status 0x%x\n",
__func__, value);
break;
case SWRM_INTERRUPT_STATUS_WR_CMD_FIFO_OVERFLOW:
dev_dbg(swrm->dev, "%s: SWR write FIFO overflow\n",
__func__);
value = swr_master_read(swrm, SWRM_CMD_FIFO_STATUS);
dev_err(swrm->dev,
"%s: SWR write FIFO overflow fifo status %x\n",
__func__, value);
swr_master_write(swrm, SWRM_CMD_FIFO_CMD, 0x1);
break;
case SWRM_INTERRUPT_STATUS_CMD_ERROR:
@ -2991,6 +3001,8 @@ static int swrm_runtime_resume(struct device *dev)
else
pm_runtime_set_autosuspend_delay(&pdev->dev,
auto_suspend_timer);
if (swrm->req_clk_switch)
swrm->req_clk_switch = false;
mutex_unlock(&swrm->reslock);
trace_printk("%s: pm_runtime: resume done, state:%d\n",
@ -3296,8 +3308,12 @@ int swrm_wcd_notify(struct platform_device *pdev, u32 id, void *data)
}
mutex_lock(&swrm->mlock);
if (swrm->clk_src != *(int *)data) {
if (swrm->state == SWR_MSTR_UP)
if (swrm->state == SWR_MSTR_UP) {
swrm->req_clk_switch = true;
swrm_device_suspend(&pdev->dev);
if (swrm->state == SWR_MSTR_UP)
swrm->req_clk_switch = false;
}
swrm->clk_src = *(int *)data;
}
mutex_unlock(&swrm->mlock);

View file

@ -171,6 +171,7 @@ struct swr_mstr_ctrl {
bool dev_up;
bool ipc_wakeup_triggered;
bool aud_core_err;
bool req_clk_switch;
struct pm_qos_request pm_qos_req;
enum swrm_pm_state pm_state;
wait_queue_head_t pm_wq;