Loading include/soc/swr-wcd.h +1 −0 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ enum { SWR_CLK_FREQ, SWR_DEVICE_SSR_DOWN, SWR_DEVICE_SSR_UP, SWR_REGISTER_WAKE_IRQ, }; struct swr_mstr_port { Loading soc/swr-mstr-ctrl.c +89 −14 Original line number Diff line number Diff line Loading @@ -1421,6 +1421,32 @@ static irqreturn_t swr_mstr_interrupt(int irq, void *dev) return ret; } static irqreturn_t swrm_wakeup_interrupt(int irq, void *dev) { struct swr_mstr_ctrl *swrm = dev; int ret = IRQ_HANDLED; if (!swrm || !(swrm->dev)) { pr_err("%s: swrm or dev is null\n", __func__); return IRQ_NONE; } mutex_lock(&swrm->devlock); if (!swrm->dev_up) { if (swrm->wake_irq > 0) disable_irq_nosync(swrm->wake_irq); mutex_unlock(&swrm->devlock); return ret; } mutex_unlock(&swrm->devlock); if (swrm->wake_irq > 0) disable_irq_nosync(swrm->wake_irq); pm_runtime_get_sync(swrm->dev); pm_runtime_mark_last_busy(swrm->dev); pm_runtime_put_autosuspend(swrm->dev); return ret; } static void swrm_wakeup_work(struct work_struct *work) { struct swr_mstr_ctrl *swrm; Loading Loading @@ -1592,8 +1618,8 @@ static int swrm_event_notify(struct notifier_block *self, schedule_work(&(swrm->dc_presence_work)); break; case SWR_WAKE_IRQ_EVENT: if (swrm->wakeup_req && !swrm->wakeup_triggered) { swrm->wakeup_triggered = true; if (swrm->ipc_wakeup && !swrm->ipc_wakeup_triggered) { swrm->ipc_wakeup_triggered = true; schedule_work(&swrm->wakeup_work); } break; Loading Loading @@ -1769,6 +1795,8 @@ static int swrm_probe(struct platform_device *pdev) swrm->mclk_freq = MCLK_FREQ; swrm->dev_up = true; swrm->state = SWR_MSTR_UP; swrm->ipc_wakeup = false; swrm->ipc_wakeup_triggered = false; init_completion(&swrm->reset); init_completion(&swrm->broadcast); init_completion(&swrm->clk_off_complete); Loading Loading @@ -1796,11 +1824,6 @@ static int swrm_probe(struct platform_device *pdev) } } if (of_property_read_u32(swrm->dev->of_node, "qcom,swr-wakeup-required", &swrm->wakeup_req)) { swrm->wakeup_req = false; } if (swrm->reg_irq) { ret = swrm->reg_irq(swrm->handle, swr_mstr_interrupt, swrm, SWR_IRQ_REGISTER); Loading Loading @@ -1910,6 +1933,9 @@ static int swrm_remove(struct platform_device *pdev) swrm, SWR_IRQ_FREE); else if (swrm->irq) free_irq(swrm->irq, swrm); else if (swrm->wake_irq > 0) free_irq(swrm->wake_irq, swrm); pm_runtime_disable(&pdev->dev); pm_runtime_set_suspended(&pdev->dev); swr_unregister_master(&swrm->master); Loading Loading @@ -1951,7 +1977,8 @@ static int swrm_runtime_resume(struct device *dev) if ((swrm->state == SWR_MSTR_DOWN) || (swrm->state == SWR_MSTR_SSR && swrm->dev_up)) { if (swrm->clk_stop_mode0_supp && swrm->wakeup_req) { if (swrm->clk_stop_mode0_supp) { if (swrm->ipc_wakeup) msm_aud_evt_blocking_notifier_call_chain( SWR_WAKE_IRQ_DEREGISTER, (void *)swrm); } Loading Loading @@ -2032,10 +2059,14 @@ static int swrm_runtime_suspend(struct device *dev) } swrm_clk_request(swrm, false); if (swrm->clk_stop_mode0_supp && swrm->wakeup_req) { if (swrm->clk_stop_mode0_supp) { if (swrm->wake_irq > 0) { enable_irq(swrm->wake_irq); } else if (swrm->ipc_wakeup) { msm_aud_evt_blocking_notifier_call_chain( SWR_WAKE_IRQ_REGISTER, (void *)swrm); swrm->wakeup_triggered = false; swrm->ipc_wakeup_triggered = false; } } } Loading Loading @@ -2071,6 +2102,35 @@ static int swrm_device_down(struct device *dev) return 0; } int swrm_register_wake_irq(struct swr_mstr_ctrl *swrm) { int ret = 0; if (!swrm->ipc_wakeup) { swrm->wake_irq = platform_get_irq_byname(swrm->pdev, "swr_wake_irq"); if (swrm->wake_irq < 0) { dev_err(swrm->dev, "%s() error getting wake irq handle: %d\n", __func__, swrm->wake_irq); return -EINVAL; } ret = request_threaded_irq(swrm->wake_irq, NULL, swrm_wakeup_interrupt, IRQF_TRIGGER_HIGH | IRQF_ONESHOT, "swr_wake_irq", swrm); if (ret) { dev_err(swrm->dev, "%s: Failed to request irq %d\n", __func__, ret); return -EINVAL; } /* Disable wake irq - enable it after clock stop */ disable_irq(swrm->wake_irq); } return ret; } /** * swrm_wcd_notify - parent device can notify to soundwire master through * this function Loading Loading @@ -2196,6 +2256,21 @@ int swrm_wcd_notify(struct platform_device *pdev, u32 id, void *data) mutex_unlock(&swrm->mlock); } break; case SWR_REGISTER_WAKE_IRQ: if (!data) { dev_err(swrm->dev, "%s: reg wake irq data is NULL\n", __func__); ret = -EINVAL; } else { mutex_lock(&swrm->mlock); swrm->ipc_wakeup = *(u32 *)data; ret = swrm_register_wake_irq(swrm); if (ret) dev_err(swrm->dev, "%s: register wake_irq failed\n", __func__); mutex_unlock(&swrm->mlock); } break; default: dev_err(swrm->dev, "%s: swr master unknown id %d\n", __func__, id); Loading soc/swr-mstr-ctrl.h +3 −2 Original line number Diff line number Diff line Loading @@ -131,6 +131,7 @@ struct swr_mstr_ctrl { int (*reg_irq)(void *handle, irqreturn_t(*irq_handler)(int irq, void *data), void *swr_handle, int type); int irq; int wake_irq; int version; int mclk_freq; u32 num_dev; Loading @@ -152,9 +153,9 @@ struct swr_mstr_ctrl { int swr_irq; u32 clk_stop_mode0_supp; struct work_struct wakeup_work; u32 wakeup_req; u32 ipc_wakeup; bool dev_up; bool wakeup_triggered; bool ipc_wakeup_triggered; }; #endif /* _SWR_WCD_CTRL_H */ Loading
include/soc/swr-wcd.h +1 −0 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ enum { SWR_CLK_FREQ, SWR_DEVICE_SSR_DOWN, SWR_DEVICE_SSR_UP, SWR_REGISTER_WAKE_IRQ, }; struct swr_mstr_port { Loading
soc/swr-mstr-ctrl.c +89 −14 Original line number Diff line number Diff line Loading @@ -1421,6 +1421,32 @@ static irqreturn_t swr_mstr_interrupt(int irq, void *dev) return ret; } static irqreturn_t swrm_wakeup_interrupt(int irq, void *dev) { struct swr_mstr_ctrl *swrm = dev; int ret = IRQ_HANDLED; if (!swrm || !(swrm->dev)) { pr_err("%s: swrm or dev is null\n", __func__); return IRQ_NONE; } mutex_lock(&swrm->devlock); if (!swrm->dev_up) { if (swrm->wake_irq > 0) disable_irq_nosync(swrm->wake_irq); mutex_unlock(&swrm->devlock); return ret; } mutex_unlock(&swrm->devlock); if (swrm->wake_irq > 0) disable_irq_nosync(swrm->wake_irq); pm_runtime_get_sync(swrm->dev); pm_runtime_mark_last_busy(swrm->dev); pm_runtime_put_autosuspend(swrm->dev); return ret; } static void swrm_wakeup_work(struct work_struct *work) { struct swr_mstr_ctrl *swrm; Loading Loading @@ -1592,8 +1618,8 @@ static int swrm_event_notify(struct notifier_block *self, schedule_work(&(swrm->dc_presence_work)); break; case SWR_WAKE_IRQ_EVENT: if (swrm->wakeup_req && !swrm->wakeup_triggered) { swrm->wakeup_triggered = true; if (swrm->ipc_wakeup && !swrm->ipc_wakeup_triggered) { swrm->ipc_wakeup_triggered = true; schedule_work(&swrm->wakeup_work); } break; Loading Loading @@ -1769,6 +1795,8 @@ static int swrm_probe(struct platform_device *pdev) swrm->mclk_freq = MCLK_FREQ; swrm->dev_up = true; swrm->state = SWR_MSTR_UP; swrm->ipc_wakeup = false; swrm->ipc_wakeup_triggered = false; init_completion(&swrm->reset); init_completion(&swrm->broadcast); init_completion(&swrm->clk_off_complete); Loading Loading @@ -1796,11 +1824,6 @@ static int swrm_probe(struct platform_device *pdev) } } if (of_property_read_u32(swrm->dev->of_node, "qcom,swr-wakeup-required", &swrm->wakeup_req)) { swrm->wakeup_req = false; } if (swrm->reg_irq) { ret = swrm->reg_irq(swrm->handle, swr_mstr_interrupt, swrm, SWR_IRQ_REGISTER); Loading Loading @@ -1910,6 +1933,9 @@ static int swrm_remove(struct platform_device *pdev) swrm, SWR_IRQ_FREE); else if (swrm->irq) free_irq(swrm->irq, swrm); else if (swrm->wake_irq > 0) free_irq(swrm->wake_irq, swrm); pm_runtime_disable(&pdev->dev); pm_runtime_set_suspended(&pdev->dev); swr_unregister_master(&swrm->master); Loading Loading @@ -1951,7 +1977,8 @@ static int swrm_runtime_resume(struct device *dev) if ((swrm->state == SWR_MSTR_DOWN) || (swrm->state == SWR_MSTR_SSR && swrm->dev_up)) { if (swrm->clk_stop_mode0_supp && swrm->wakeup_req) { if (swrm->clk_stop_mode0_supp) { if (swrm->ipc_wakeup) msm_aud_evt_blocking_notifier_call_chain( SWR_WAKE_IRQ_DEREGISTER, (void *)swrm); } Loading Loading @@ -2032,10 +2059,14 @@ static int swrm_runtime_suspend(struct device *dev) } swrm_clk_request(swrm, false); if (swrm->clk_stop_mode0_supp && swrm->wakeup_req) { if (swrm->clk_stop_mode0_supp) { if (swrm->wake_irq > 0) { enable_irq(swrm->wake_irq); } else if (swrm->ipc_wakeup) { msm_aud_evt_blocking_notifier_call_chain( SWR_WAKE_IRQ_REGISTER, (void *)swrm); swrm->wakeup_triggered = false; swrm->ipc_wakeup_triggered = false; } } } Loading Loading @@ -2071,6 +2102,35 @@ static int swrm_device_down(struct device *dev) return 0; } int swrm_register_wake_irq(struct swr_mstr_ctrl *swrm) { int ret = 0; if (!swrm->ipc_wakeup) { swrm->wake_irq = platform_get_irq_byname(swrm->pdev, "swr_wake_irq"); if (swrm->wake_irq < 0) { dev_err(swrm->dev, "%s() error getting wake irq handle: %d\n", __func__, swrm->wake_irq); return -EINVAL; } ret = request_threaded_irq(swrm->wake_irq, NULL, swrm_wakeup_interrupt, IRQF_TRIGGER_HIGH | IRQF_ONESHOT, "swr_wake_irq", swrm); if (ret) { dev_err(swrm->dev, "%s: Failed to request irq %d\n", __func__, ret); return -EINVAL; } /* Disable wake irq - enable it after clock stop */ disable_irq(swrm->wake_irq); } return ret; } /** * swrm_wcd_notify - parent device can notify to soundwire master through * this function Loading Loading @@ -2196,6 +2256,21 @@ int swrm_wcd_notify(struct platform_device *pdev, u32 id, void *data) mutex_unlock(&swrm->mlock); } break; case SWR_REGISTER_WAKE_IRQ: if (!data) { dev_err(swrm->dev, "%s: reg wake irq data is NULL\n", __func__); ret = -EINVAL; } else { mutex_lock(&swrm->mlock); swrm->ipc_wakeup = *(u32 *)data; ret = swrm_register_wake_irq(swrm); if (ret) dev_err(swrm->dev, "%s: register wake_irq failed\n", __func__); mutex_unlock(&swrm->mlock); } break; default: dev_err(swrm->dev, "%s: swr master unknown id %d\n", __func__, id); Loading
soc/swr-mstr-ctrl.h +3 −2 Original line number Diff line number Diff line Loading @@ -131,6 +131,7 @@ struct swr_mstr_ctrl { int (*reg_irq)(void *handle, irqreturn_t(*irq_handler)(int irq, void *data), void *swr_handle, int type); int irq; int wake_irq; int version; int mclk_freq; u32 num_dev; Loading @@ -152,9 +153,9 @@ struct swr_mstr_ctrl { int swr_irq; u32 clk_stop_mode0_supp; struct work_struct wakeup_work; u32 wakeup_req; u32 ipc_wakeup; bool dev_up; bool wakeup_triggered; bool ipc_wakeup_triggered; }; #endif /* _SWR_WCD_CTRL_H */