@@ -461,9 +461,12 @@ static void cs35l41_remove_dsp(struct cs35l41_hda *cs35l41)
461
461
struct cs_dsp * dsp = & cs35l41 -> cs_dsp ;
462
462
463
463
cancel_work_sync (& cs35l41 -> fw_load_work );
464
+
465
+ mutex_lock (& cs35l41 -> fw_mutex );
464
466
cs35l41_shutdown_dsp (cs35l41 );
465
467
cs_dsp_remove (dsp );
466
468
cs35l41 -> halo_initialized = false;
469
+ mutex_unlock (& cs35l41 -> fw_mutex );
467
470
}
468
471
469
472
/* Protection release cycle to get the speaker out of Safe-Mode */
@@ -570,45 +573,148 @@ static int cs35l41_hda_channel_map(struct device *dev, unsigned int tx_num, unsi
570
573
rx_slot );
571
574
}
572
575
576
+ static void cs35l41_ready_for_reset (struct cs35l41_hda * cs35l41 )
577
+ {
578
+ mutex_lock (& cs35l41 -> fw_mutex );
579
+ if (cs35l41 -> firmware_running ) {
580
+
581
+ regcache_cache_only (cs35l41 -> regmap , false);
582
+
583
+ cs35l41_exit_hibernate (cs35l41 -> dev , cs35l41 -> regmap );
584
+ cs35l41_shutdown_dsp (cs35l41 );
585
+ cs35l41_safe_reset (cs35l41 -> regmap , cs35l41 -> hw_cfg .bst_type );
586
+
587
+ regcache_cache_only (cs35l41 -> regmap , true);
588
+ regcache_mark_dirty (cs35l41 -> regmap );
589
+ }
590
+ mutex_unlock (& cs35l41 -> fw_mutex );
591
+ }
592
+
593
+ static int cs35l41_system_suspend (struct device * dev )
594
+ {
595
+ struct cs35l41_hda * cs35l41 = dev_get_drvdata (dev );
596
+ int ret ;
597
+
598
+ dev_dbg (cs35l41 -> dev , "System Suspend\n" );
599
+
600
+ if (cs35l41 -> hw_cfg .bst_type == CS35L41_EXT_BOOST_NO_VSPK_SWITCH ) {
601
+ dev_err (cs35l41 -> dev , "System Suspend not supported\n" );
602
+ return - EINVAL ;
603
+ }
604
+
605
+ ret = pm_runtime_force_suspend (dev );
606
+ if (ret )
607
+ return ret ;
608
+
609
+ /* Shutdown DSP before system suspend */
610
+ cs35l41_ready_for_reset (cs35l41 );
611
+
612
+ /*
613
+ * Reset GPIO may be shared, so cannot reset here.
614
+ * However beyond this point, amps may be powered down.
615
+ */
616
+ return 0 ;
617
+ }
618
+
619
+ static int cs35l41_system_resume (struct device * dev )
620
+ {
621
+ struct cs35l41_hda * cs35l41 = dev_get_drvdata (dev );
622
+ int ret ;
623
+
624
+ dev_dbg (cs35l41 -> dev , "System Resume\n" );
625
+
626
+ if (cs35l41 -> hw_cfg .bst_type == CS35L41_EXT_BOOST_NO_VSPK_SWITCH ) {
627
+ dev_err (cs35l41 -> dev , "System Resume not supported\n" );
628
+ return - EINVAL ;
629
+ }
630
+
631
+ if (cs35l41 -> reset_gpio ) {
632
+ usleep_range (2000 , 2100 );
633
+ gpiod_set_value_cansleep (cs35l41 -> reset_gpio , 1 );
634
+ }
635
+
636
+ usleep_range (2000 , 2100 );
637
+
638
+ ret = pm_runtime_force_resume (dev );
639
+
640
+ mutex_lock (& cs35l41 -> fw_mutex );
641
+ if (!ret && cs35l41 -> request_fw_load && !cs35l41 -> fw_request_ongoing ) {
642
+ cs35l41 -> fw_request_ongoing = true;
643
+ schedule_work (& cs35l41 -> fw_load_work );
644
+ }
645
+ mutex_unlock (& cs35l41 -> fw_mutex );
646
+
647
+ return ret ;
648
+ }
649
+
573
650
static int cs35l41_runtime_suspend (struct device * dev )
574
651
{
575
652
struct cs35l41_hda * cs35l41 = dev_get_drvdata (dev );
653
+ int ret = 0 ;
576
654
577
- dev_dbg (cs35l41 -> dev , "Suspend\n" );
655
+ dev_dbg (cs35l41 -> dev , "Runtime Suspend\n" );
578
656
579
- if (!cs35l41 -> firmware_running )
657
+ if (cs35l41 -> hw_cfg .bst_type == CS35L41_EXT_BOOST_NO_VSPK_SWITCH ) {
658
+ dev_dbg (cs35l41 -> dev , "Runtime Suspend not supported\n" );
580
659
return 0 ;
660
+ }
581
661
582
- if (cs35l41_enter_hibernate (cs35l41 -> dev , cs35l41 -> regmap , cs35l41 -> hw_cfg .bst_type ) < 0 )
583
- return 0 ;
662
+ mutex_lock (& cs35l41 -> fw_mutex );
663
+
664
+ if (cs35l41 -> playback_started ) {
665
+ regmap_multi_reg_write (cs35l41 -> regmap , cs35l41_hda_mute ,
666
+ ARRAY_SIZE (cs35l41_hda_mute ));
667
+ cs35l41_global_enable (cs35l41 -> regmap , cs35l41 -> hw_cfg .bst_type , 0 );
668
+ regmap_update_bits (cs35l41 -> regmap , CS35L41_PWR_CTRL2 ,
669
+ CS35L41_AMP_EN_MASK , 0 << CS35L41_AMP_EN_SHIFT );
670
+ if (cs35l41 -> hw_cfg .bst_type == CS35L41_EXT_BOOST )
671
+ regmap_write (cs35l41 -> regmap , CS35L41_GPIO1_CTRL1 , 0x00000001 );
672
+ regmap_update_bits (cs35l41 -> regmap , CS35L41_PWR_CTRL2 ,
673
+ CS35L41_VMON_EN_MASK | CS35L41_IMON_EN_MASK ,
674
+ 0 << CS35L41_VMON_EN_SHIFT | 0 << CS35L41_IMON_EN_SHIFT );
675
+ cs35l41 -> playback_started = false;
676
+ }
677
+
678
+ if (cs35l41 -> firmware_running ) {
679
+ ret = cs35l41_enter_hibernate (cs35l41 -> dev , cs35l41 -> regmap ,
680
+ cs35l41 -> hw_cfg .bst_type );
681
+ if (ret )
682
+ goto err ;
683
+ } else {
684
+ cs35l41_safe_reset (cs35l41 -> regmap , cs35l41 -> hw_cfg .bst_type );
685
+ }
584
686
585
687
regcache_cache_only (cs35l41 -> regmap , true);
586
688
regcache_mark_dirty (cs35l41 -> regmap );
587
689
588
- return 0 ;
690
+ err :
691
+ mutex_unlock (& cs35l41 -> fw_mutex );
692
+
693
+ return ret ;
589
694
}
590
695
591
696
static int cs35l41_runtime_resume (struct device * dev )
592
697
{
593
698
struct cs35l41_hda * cs35l41 = dev_get_drvdata (dev );
594
- int ret ;
699
+ int ret = 0 ;
595
700
596
- dev_dbg (cs35l41 -> dev , "Resume. \n" );
701
+ dev_dbg (cs35l41 -> dev , "Runtime Resume\n" );
597
702
598
703
if (cs35l41 -> hw_cfg .bst_type == CS35L41_EXT_BOOST_NO_VSPK_SWITCH ) {
599
- dev_dbg (cs35l41 -> dev , "System does not support Resume \n" );
704
+ dev_dbg (cs35l41 -> dev , "Runtime Resume not supported \n" );
600
705
return 0 ;
601
706
}
602
707
603
- if (!cs35l41 -> firmware_running )
604
- return 0 ;
708
+ mutex_lock (& cs35l41 -> fw_mutex );
605
709
606
710
regcache_cache_only (cs35l41 -> regmap , false);
607
711
608
- ret = cs35l41_exit_hibernate (cs35l41 -> dev , cs35l41 -> regmap );
609
- if (ret ) {
610
- regcache_cache_only (cs35l41 -> regmap , true);
611
- return ret ;
712
+ if (cs35l41 -> firmware_running ) {
713
+ ret = cs35l41_exit_hibernate (cs35l41 -> dev , cs35l41 -> regmap );
714
+ if (ret ) {
715
+ dev_warn (cs35l41 -> dev , "Unable to exit Hibernate." );
716
+ goto err ;
717
+ }
612
718
}
613
719
614
720
/* Test key needs to be unlocked to allow the OTP settings to re-apply */
@@ -617,13 +723,16 @@ static int cs35l41_runtime_resume(struct device *dev)
617
723
cs35l41_test_key_lock (cs35l41 -> dev , cs35l41 -> regmap );
618
724
if (ret ) {
619
725
dev_err (cs35l41 -> dev , "Failed to restore register cache: %d\n" , ret );
620
- return ret ;
726
+ goto err ;
621
727
}
622
728
623
729
if (cs35l41 -> hw_cfg .bst_type == CS35L41_EXT_BOOST )
624
730
cs35l41_init_boost (cs35l41 -> dev , cs35l41 -> regmap , & cs35l41 -> hw_cfg );
625
731
626
- return 0 ;
732
+ err :
733
+ mutex_unlock (& cs35l41 -> fw_mutex );
734
+
735
+ return ret ;
627
736
}
628
737
629
738
static int cs35l41_smart_amp (struct cs35l41_hda * cs35l41 )
@@ -673,8 +782,6 @@ static int cs35l41_smart_amp(struct cs35l41_hda *cs35l41)
673
782
674
783
static void cs35l41_load_firmware (struct cs35l41_hda * cs35l41 , bool load )
675
784
{
676
- pm_runtime_get_sync (cs35l41 -> dev );
677
-
678
785
if (cs35l41 -> firmware_running && !load ) {
679
786
dev_dbg (cs35l41 -> dev , "Unloading Firmware\n" );
680
787
cs35l41_shutdown_dsp (cs35l41 );
@@ -684,9 +791,6 @@ static void cs35l41_load_firmware(struct cs35l41_hda *cs35l41, bool load)
684
791
} else {
685
792
dev_dbg (cs35l41 -> dev , "Unable to Load firmware.\n" );
686
793
}
687
-
688
- pm_runtime_mark_last_busy (cs35l41 -> dev );
689
- pm_runtime_put_autosuspend (cs35l41 -> dev );
690
794
}
691
795
692
796
static int cs35l41_fw_load_ctl_get (struct snd_kcontrol * kcontrol ,
@@ -702,16 +806,21 @@ static void cs35l41_fw_load_work(struct work_struct *work)
702
806
{
703
807
struct cs35l41_hda * cs35l41 = container_of (work , struct cs35l41_hda , fw_load_work );
704
808
809
+ pm_runtime_get_sync (cs35l41 -> dev );
810
+
705
811
mutex_lock (& cs35l41 -> fw_mutex );
706
812
707
813
/* Recheck if playback is ongoing, mutex will block playback during firmware loading */
708
814
if (cs35l41 -> playback_started )
709
- dev_err (cs35l41 -> dev , "Cannot Load/Unload firmware during Playback\n" );
815
+ dev_err (cs35l41 -> dev , "Cannot Load/Unload firmware during Playback. Retrying... \n" );
710
816
else
711
817
cs35l41_load_firmware (cs35l41 , cs35l41 -> request_fw_load );
712
818
713
819
cs35l41 -> fw_request_ongoing = false;
714
820
mutex_unlock (& cs35l41 -> fw_mutex );
821
+
822
+ pm_runtime_mark_last_busy (cs35l41 -> dev );
823
+ pm_runtime_put_autosuspend (cs35l41 -> dev );
715
824
}
716
825
717
826
static int cs35l41_fw_load_ctl_put (struct snd_kcontrol * kcontrol ,
@@ -835,6 +944,8 @@ static int cs35l41_hda_bind(struct device *dev, struct device *master, void *mas
835
944
836
945
pm_runtime_get_sync (dev );
837
946
947
+ mutex_lock (& cs35l41 -> fw_mutex );
948
+
838
949
comps -> dev = dev ;
839
950
if (!cs35l41 -> acpi_subsystem_id )
840
951
cs35l41 -> acpi_subsystem_id = kasprintf (GFP_KERNEL , "%.8x" ,
@@ -847,10 +958,8 @@ static int cs35l41_hda_bind(struct device *dev, struct device *master, void *mas
847
958
if (firmware_autostart ) {
848
959
dev_dbg (cs35l41 -> dev , "Firmware Autostart.\n" );
849
960
cs35l41 -> request_fw_load = true;
850
- mutex_lock (& cs35l41 -> fw_mutex );
851
961
if (cs35l41_smart_amp (cs35l41 ) < 0 )
852
962
dev_warn (cs35l41 -> dev , "Cannot Run Firmware, reverting to dsp bypass...\n" );
853
- mutex_unlock (& cs35l41 -> fw_mutex );
854
963
} else {
855
964
dev_dbg (cs35l41 -> dev , "Firmware Autostart is disabled.\n" );
856
965
}
@@ -859,6 +968,8 @@ static int cs35l41_hda_bind(struct device *dev, struct device *master, void *mas
859
968
860
969
comps -> playback_hook = cs35l41_hda_playback_hook ;
861
970
971
+ mutex_unlock (& cs35l41 -> fw_mutex );
972
+
862
973
pm_runtime_mark_last_busy (dev );
863
974
pm_runtime_put_autosuspend (dev );
864
975
@@ -1426,6 +1537,7 @@ EXPORT_SYMBOL_NS_GPL(cs35l41_hda_remove, SND_HDA_SCODEC_CS35L41);
1426
1537
1427
1538
const struct dev_pm_ops cs35l41_hda_pm_ops = {
1428
1539
RUNTIME_PM_OPS (cs35l41_runtime_suspend , cs35l41_runtime_resume , NULL )
1540
+ SYSTEM_SLEEP_PM_OPS (cs35l41_system_suspend , cs35l41_system_resume )
1429
1541
};
1430
1542
EXPORT_SYMBOL_NS_GPL (cs35l41_hda_pm_ops , SND_HDA_SCODEC_CS35L41 );
1431
1543
0 commit comments