Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 150
Enable ipc4 d0i3 setting#3928
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Uh oh!
There was an error while loading. Please reload this page.
Enable ipc4 d0i3 setting #3928
Changes from all commits
ed62ae42f3d78ecf0258d073343a30189abFile filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -280,6 +280,8 @@ int cnl_ipc4_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) | ||
| snd_sof_dsp_write(sdev, HDA_DSP_BAR, CNL_DSP_REG_HIPCIDR, | ||
| msg_data->primary | CNL_DSP_REG_HIPCIDR_BUSY); | ||
| hda_dsp_ipc4_schedule_d0i3_work(hdev, msg); | ||
RanderWang marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| return 0; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -364,19 +364,12 @@ static int hda_dsp_wait_d0i3c_done(struct snd_sof_dev *sdev) | ||
| static int hda_dsp_send_pm_gate_ipc(struct snd_sof_dev *sdev, u32 flags) | ||
| { | ||
| struct sof_ipc_pm_gate pm_gate; | ||
| struct sof_ipc_reply reply; | ||
| const struct sof_ipc_pm_ops *pm_ops = sof_ipc_get_ops(sdev, pm); | ||
| memset(&pm_gate, 0, sizeof(pm_gate)); | ||
| if (pm_ops && pm_ops->set_pm_gate) | ||
| return pm_ops->set_pm_gate(sdev, flags); | ||
| /* configure pm_gate ipc message */ | ||
| pm_gate.hdr.size = sizeof(pm_gate); | ||
| pm_gate.hdr.cmd = SOF_IPC_GLB_PM_MSG | SOF_IPC_PM_GATE; | ||
| pm_gate.flags = flags; | ||
| /* send pm_gate ipc to dsp */ | ||
| return sof_ipc_tx_message_no_pm(sdev->ipc, &pm_gate, sizeof(pm_gate), | ||
| &reply, sizeof(reply)); | ||
| return 0; | ||
RanderWang marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. RanderWang marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| } | ||
| static int hda_dsp_update_d0i3c_register(struct snd_sof_dev *sdev, u8 value) | ||
| @@ -412,6 +405,34 @@ static int hda_dsp_update_d0i3c_register(struct snd_sof_dev *sdev, u8 value) | ||
| return 0; | ||
| } | ||
| /* | ||
| * d0i3 streaming is enabled if all the active streams can | ||
| * work in d0i3 state and playback is enabled | ||
| */ | ||
| static bool hda_dsp_d0i3_streaming_applicable(struct snd_sof_dev *sdev) | ||
| { | ||
| struct snd_pcm_substream *substream; | ||
| struct snd_sof_pcm *spcm; | ||
| bool playback_active = false; | ||
| int dir; | ||
| list_for_each_entry(spcm, &sdev->pcm_list, list) { | ||
| for_each_pcm_streams(dir) { | ||
RanderWang marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| substream = spcm->stream[dir].substream; | ||
| if (!substream || !substream->runtime) | ||
| continue; | ||
| if (!spcm->stream[dir].d0i3_compatible) | ||
| return false; | ||
| if (dir == SNDRV_PCM_STREAM_PLAYBACK) | ||
| playback_active = true; | ||
plbossart marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| } | ||
| } | ||
| return playback_active; | ||
| } | ||
| static int hda_dsp_set_D0_state(struct snd_sof_dev *sdev, | ||
| const struct sof_dsp_power_state *target_state) | ||
| { | ||
| @@ -453,6 +474,9 @@ static int hda_dsp_set_D0_state(struct snd_sof_dev *sdev, | ||
| !hda_enable_trace_D0I3_S0 || | ||
| sdev->system_suspend_target != SOF_SUSPEND_NONE) | ||
| flags = HDA_PM_NO_DMA_TRACE; | ||
| if (hda_dsp_d0i3_streaming_applicable(sdev)) | ||
| flags |= HDA_PM_PG_STREAMING; | ||
RanderWang marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. RanderWang marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| } else { | ||
| /* prevent power gating in D0I0 */ | ||
| flags = HDA_PM_PPG; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -67,6 +67,32 @@ int hda_dsp_ipc_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) | ||
| return 0; | ||
| } | ||
| static inline bool hda_dsp_ipc4_pm_msg(u32 primary) | ||
| { | ||
| /* pm setting is only supported by module msg */ | ||
| if (SOF_IPC4_MSG_IS_MODULE_MSG(primary) != SOF_IPC4_MODULE_MSG) | ||
| return false; | ||
| if (SOF_IPC4_MSG_TYPE_GET(primary) == SOF_IPC4_MOD_SET_DX || | ||
| SOF_IPC4_MSG_TYPE_GET(primary) == SOF_IPC4_MOD_SET_D0IX) | ||
| return true; | ||
| return false; | ||
| } | ||
| void hda_dsp_ipc4_schedule_d0i3_work(struct sof_intel_hda_dev *hdev, | ||
| struct snd_sof_ipc_msg *msg) | ||
| { | ||
| struct sof_ipc4_msg *msg_data = msg->msg_data; | ||
| /* Schedule a delayed work for d0i3 entry after sending non-pm ipc msg */ | ||
| if (hda_dsp_ipc4_pm_msg(msg_data->primary)) | ||
| return; | ||
| mod_delayed_work(system_wq, &hdev->d0i3_work, | ||
| msecs_to_jiffies(SOF_HDA_D0I3_WORK_DELAY_MS)); | ||
| } | ||
| int hda_dsp_ipc4_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) | ||
| { | ||
| struct sof_intel_hda_dev *hdev = sdev->pdata->hw_pdata; | ||
| @@ -88,6 +114,8 @@ int hda_dsp_ipc4_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) | ||
| snd_sof_dsp_write(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCI, | ||
| msg_data->primary | HDA_DSP_REG_HIPCI_BUSY); | ||
| hda_dsp_ipc4_schedule_d0i3_work(hdev, msg); | ||
RanderWang marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. RanderWang marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. plbossart marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| return 0; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -110,6 +110,8 @@ static int mtl_ipc_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *ms | ||
| snd_sof_dsp_write(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFIPCXIDR, | ||
| msg_data->primary | MTL_DSP_REG_HFIPCXIDR_BUSY); | ||
| hda_dsp_ipc4_schedule_d0i3_work(hdev, msg); | ||
RanderWang marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| return 0; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1077,10 +1077,28 @@ static int sof_ipc3_ctx_restore(struct snd_sof_dev *sdev) | ||
| return sof_ipc3_ctx_ipc(sdev, SOF_IPC_PM_CTX_RESTORE); | ||
| } | ||
| static int sof_ipc3_set_pm_gate(struct snd_sof_dev *sdev, u32 flags) | ||
Member There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe rename to 'set_pm_gate_flags' - which seems to be a better definition of what the functions actually do. Collaborator There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It does a bit more than setting flags, it sends the message to firmware to set the 'pm_gate' and the state is described by the 'flags' parameter. | ||
| { | ||
| struct sof_ipc_pm_gate pm_gate; | ||
| struct sof_ipc_reply reply; | ||
| memset(&pm_gate, 0, sizeof(pm_gate)); | ||
| /* configure pm_gate ipc message */ | ||
| pm_gate.hdr.size = sizeof(pm_gate); | ||
| pm_gate.hdr.cmd = SOF_IPC_GLB_PM_MSG | SOF_IPC_PM_GATE; | ||
| pm_gate.flags = flags; | ||
| /* send pm_gate ipc to dsp */ | ||
| return sof_ipc_tx_message_no_pm(sdev->ipc, &pm_gate, sizeof(pm_gate), | ||
| &reply, sizeof(reply)); | ||
| } | ||
RanderWang marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| static const struct sof_ipc_pm_ops ipc3_pm_ops = { | ||
| .ctx_save = sof_ipc3_ctx_save, | ||
| .ctx_restore = sof_ipc3_ctx_restore, | ||
| .set_core_state = sof_ipc3_set_core_state, | ||
| .set_pm_gate = sof_ipc3_set_pm_gate, | ||
| }; | ||
| const struct sof_ipc_ops ipc3_ops = { | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -369,6 +369,17 @@ static int sof_ipc4_tx_msg(struct snd_sof_dev *sdev, void *msg_data, size_t msg_ | ||
| if (!msg_data) | ||
| return -EINVAL; | ||
| if (!no_pm) { | ||
RanderWang marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| const struct sof_dsp_power_state target_state = { | ||
| .state = SOF_DSP_PM_D0, | ||
| }; | ||
| /* ensure the DSP is in D0i0 before sending a new IPC */ | ||
| ret = snd_sof_dsp_set_power_state(sdev, &target_state); | ||
| if (ret < 0) | ||
| return ret; | ||
| } | ||
RanderWang marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| /* Serialise IPC TX */ | ||
| mutex_lock(&ipc->tx_mutex); | ||
| @@ -653,9 +664,22 @@ static int sof_ipc4_ctx_save(struct snd_sof_dev *sdev) | ||
| return sof_ipc4_set_core_state(sdev, SOF_DSP_PRIMARY_CORE, false); | ||
| } | ||
| static int sof_ipc4_set_pm_gate(struct snd_sof_dev *sdev, u32 flags) | ||
| { | ||
| struct sof_ipc4_msg msg = {{0}}; | ||
| msg.primary = SOF_IPC4_MSG_TYPE_SET(SOF_IPC4_MOD_SET_D0IX); | ||
| msg.primary |= SOF_IPC4_MSG_DIR(SOF_IPC4_MSG_REQUEST); | ||
| msg.primary |= SOF_IPC4_MSG_TARGET(SOF_IPC4_MODULE_MSG); | ||
| msg.extension = flags; | ||
| return sof_ipc4_tx_msg(sdev, &msg, 0, NULL, 0, true); | ||
| } | ||
| static const struct sof_ipc_pm_ops ipc4_pm_ops = { | ||
| .ctx_save = sof_ipc4_ctx_save, | ||
| .set_core_state = sof_ipc4_set_core_state, | ||
| .set_pm_gate = sof_ipc4_set_pm_gate, | ||
| }; | ||
| static int sof_ipc4_init(struct snd_sof_dev *sdev) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -413,11 +413,13 @@ struct sof_ipc_fw_tracing_ops { | ||
| * @ctx_save: Optional function pointer for context save | ||
| * @ctx_restore: Optional function pointer for context restore | ||
| * @set_core_state: Optional function pointer for turning on/off a DSP core | ||
| * @set_pm_gate: Optional function pointer for pm gate settings | ||
| */ | ||
| struct sof_ipc_pm_ops { | ||
| int (*ctx_save)(struct snd_sof_dev *sdev); | ||
| int (*ctx_restore)(struct snd_sof_dev *sdev); | ||
| int (*set_core_state)(struct snd_sof_dev *sdev, int core_idx, bool on); | ||
| int (*set_pm_gate)(struct snd_sof_dev *sdev, u32 flags); | ||
RanderWang marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| }; | ||
| /** | ||
Uh oh!
There was an error while loading. Please reload this page.