1818#include <linux/of_graph.h>
1919#include <linux/of_platform.h>
2020#include <linux/platform_device.h>
21+ #include <linux/pm_runtime.h>
2122#include <sound/dmaengine_pcm.h>
2223#include <sound/pcm.h>
2324#include <sound/pcm_params.h>
@@ -377,6 +378,7 @@ static int dcp_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
377378 if (!dcpaud_connection_up (dcpaud ))
378379 return - ENXIO ;
379380
381+ WARN_ON (pm_runtime_get_sync (dcpaud -> dev ) < 0 );
380382 ret = dcp_audiosrv_startlink (dcpaud -> dcp_dev ,
381383 & dcpaud -> selected_cookie );
382384 if (ret < 0 )
@@ -403,6 +405,8 @@ static int dcp_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
403405 case SNDRV_PCM_TRIGGER_STOP :
404406 case SNDRV_PCM_TRIGGER_SUSPEND :
405407 ret = dcp_audiosrv_stoplink (dcpaud -> dcp_dev );
408+ pm_runtime_mark_last_busy (dcpaud -> dev );
409+ __pm_runtime_put_autosuspend (dcpaud -> dev );
406410 if (ret < 0 )
407411 return ret ;
408412 break ;
@@ -605,6 +609,13 @@ static int dcpaud_comp_bind(struct device *dev, struct device *main, void *data)
605609 int index ;
606610 int ret ;
607611
612+ pm_runtime_get_noresume (dev );
613+ pm_runtime_set_active (dev );
614+
615+ ret = devm_pm_runtime_enable (dev );
616+ if (ret )
617+ return dev_err_probe (dev , ret , "Failed to enable runtime PM: %d\n" , ret );
618+
608619 /* find linked DCP instance */
609620 endpoint = of_graph_get_endpoint_by_regs (dev -> of_node , 0 , 0 );
610621 if (endpoint ) {
@@ -614,35 +625,34 @@ static int dcpaud_comp_bind(struct device *dev, struct device *main, void *data)
614625 if (!dcp_node || !of_device_is_available (dcp_node )) {
615626 of_node_put (dcp_node );
616627 dev_info (dev , "No audio support\n" );
617- return 0 ;
628+ goto rpm_put ;
618629 }
619630
620631 index = of_property_match_string (dev -> of_node , "dma-names" , "tx" );
621632 if (index < 0 ) {
622633 dev_err (dev , "No dma-names property\n" );
623- return 0 ;
634+ goto rpm_put ;
624635 }
625636
626637 if (of_parse_phandle_with_args (dev -> of_node , "dmas" , "#dma-cells" , index ,
627638 & dma_spec ) || !dma_spec .np ) {
628639 dev_err (dev , "Failed to parse dmas property\n" );
629- return 0 ;
640+ goto rpm_put ;
630641 }
631642
632643 dcp_pdev = of_find_device_by_node (dcp_node );
633644 of_node_put (dcp_node );
634645 if (!dcp_pdev ) {
635646 dev_info (dev , "No DP/HDMI audio device, dcp not ready\n" );
636- return 0 ;
647+ goto rpm_put ;
637648 }
638649 dcpaud -> dcp_dev = & dcp_pdev -> dev ;
639650
640-
641651 dma_pdev = of_find_device_by_node (dma_spec .np );
642652 of_node_put (dma_spec .np );
643653 if (!dma_pdev ) {
644654 dev_info (dev , "No DMA device\n" );
645- return 0 ;
655+ goto rpm_put ;
646656 }
647657 dcpaud -> dma_dev = & dma_pdev -> dev ;
648658
@@ -663,6 +673,9 @@ static int dcpaud_comp_bind(struct device *dev, struct device *main, void *data)
663673 DCPAUD_PRODUCTATTRS_MAXSIZE );
664674 }
665675
676+ rpm_put :
677+ pm_runtime_put (dev );
678+
666679 return 0 ;
667680}
668681
@@ -718,7 +731,22 @@ static void dcpaud_shutdown(struct platform_device *pdev)
718731 component_del (& pdev -> dev , & dcpaud_comp_ops );
719732}
720733
721- // static DEFINE_SIMPLE_DEV_PM_OPS(dcpaud_pm_ops, dcpaud_suspend, dcpaud_resume);
734+ static __maybe_unused int dcpaud_suspend (struct device * dev )
735+ {
736+ /*
737+ * Using snd_power_change_state() does not work since the sound card
738+ * is what resumes runtime PM.
739+ */
740+
741+ return 0 ;
742+ }
743+
744+ static __maybe_unused int dcpaud_resume (struct device * dev )
745+ {
746+ return 0 ;
747+ }
748+
749+ static DEFINE_RUNTIME_DEV_PM_OPS (dcpaud_pm_ops , dcpaud_suspend , dcpaud_resume , NULL) ;
722750
723751static const struct of_device_id dcpaud_of_match [] = {
724752 { .compatible = "apple,dpaudio" },
@@ -728,7 +756,8 @@ static const struct of_device_id dcpaud_of_match[] = {
728756static struct platform_driver dcpaud_driver = {
729757 .driver = {
730758 .name = "dcp-dp-audio" ,
731- .of_match_table = dcpaud_of_match ,
759+ .of_match_table = dcpaud_of_match ,
760+ .pm = pm_ptr (& dcpaud_pm_ops ),
732761 },
733762 .probe = dcpaud_probe ,
734763 .remove = dcpaud_remove ,
0 commit comments