@@ -872,6 +872,52 @@ static int cs35l56_hda_system_resume(struct device *dev)
872
872
return 0 ;
873
873
}
874
874
875
+ static int cs35l56_hda_fixup_yoga9 (struct cs35l56_hda * cs35l56 , int * bus_addr )
876
+ {
877
+ /* The cirrus,dev-index property has the wrong values */
878
+ switch (* bus_addr ) {
879
+ case 0x30 :
880
+ cs35l56 -> index = 1 ;
881
+ return 0 ;
882
+ case 0x31 :
883
+ cs35l56 -> index = 0 ;
884
+ return 0 ;
885
+ default :
886
+ /* There is a pseudo-address for broadcast to both amps - ignore it */
887
+ dev_dbg (cs35l56 -> base .dev , "Ignoring I2C address %#x\n" , * bus_addr );
888
+ return 0 ;
889
+ }
890
+ }
891
+
892
+ static const struct {
893
+ const char * sub ;
894
+ int (* fixup_fn )(struct cs35l56_hda * cs35l56 , int * bus_addr );
895
+ } cs35l56_hda_fixups [] = {
896
+ {
897
+ .sub = "17AA390B" , /* Lenovo Yoga Book 9i GenX */
898
+ .fixup_fn = cs35l56_hda_fixup_yoga9 ,
899
+ },
900
+ };
901
+
902
+ static int cs35l56_hda_apply_platform_fixups (struct cs35l56_hda * cs35l56 , const char * sub ,
903
+ int * bus_addr )
904
+ {
905
+ int i ;
906
+
907
+ if (IS_ERR (sub ))
908
+ return 0 ;
909
+
910
+ for (i = 0 ; i < ARRAY_SIZE (cs35l56_hda_fixups ); i ++ ) {
911
+ if (strcasecmp (cs35l56_hda_fixups [i ].sub , sub ) == 0 ) {
912
+ dev_dbg (cs35l56 -> base .dev , "Applying fixup for %s\n" ,
913
+ cs35l56_hda_fixups [i ].sub );
914
+ return (cs35l56_hda_fixups [i ].fixup_fn )(cs35l56 , bus_addr );
915
+ }
916
+ }
917
+
918
+ return 0 ;
919
+ }
920
+
875
921
static int cs35l56_hda_read_acpi (struct cs35l56_hda * cs35l56 , int hid , int id )
876
922
{
877
923
u32 values [HDA_MAX_COMPONENTS ];
@@ -896,39 +942,47 @@ static int cs35l56_hda_read_acpi(struct cs35l56_hda *cs35l56, int hid, int id)
896
942
ACPI_COMPANION_SET (cs35l56 -> base .dev , adev );
897
943
}
898
944
899
- property = "cirrus,dev-index" ;
900
- ret = device_property_count_u32 (cs35l56 -> base .dev , property );
901
- if (ret <= 0 )
902
- goto err ;
903
-
904
- if (ret > ARRAY_SIZE (values )) {
905
- ret = - EINVAL ;
906
- goto err ;
907
- }
908
- nval = ret ;
945
+ /* Initialize things that could be overwritten by a fixup */
946
+ cs35l56 -> index = -1 ;
909
947
910
- ret = device_property_read_u32_array (cs35l56 -> base .dev , property , values , nval );
948
+ sub = acpi_get_subsystem_id (ACPI_HANDLE (cs35l56 -> base .dev ));
949
+ ret = cs35l56_hda_apply_platform_fixups (cs35l56 , sub , & id );
911
950
if (ret )
912
- goto err ;
951
+ return ret ;
913
952
914
- cs35l56 -> index = -1 ;
915
- for (i = 0 ; i < nval ; i ++ ) {
916
- if (values [i ] == id ) {
917
- cs35l56 -> index = i ;
918
- break ;
919
- }
920
- }
921
- /*
922
- * It's not an error for the ID to be missing: for I2C there can be
923
- * an alias address that is not a real device. So reject silently.
924
- */
925
953
if (cs35l56 -> index == -1 ) {
926
- dev_dbg ( cs35l56 -> base . dev , "No index found in %s\n" , property ) ;
927
- ret = - ENODEV ;
928
- goto err ;
929
- }
954
+ property = "cirrus,dev-index" ;
955
+ ret = device_property_count_u32 ( cs35l56 -> base . dev , property ) ;
956
+ if ( ret <= 0 )
957
+ goto err ;
930
958
931
- sub = acpi_get_subsystem_id (ACPI_HANDLE (cs35l56 -> base .dev ));
959
+ if (ret > ARRAY_SIZE (values )) {
960
+ ret = - EINVAL ;
961
+ goto err ;
962
+ }
963
+ nval = ret ;
964
+
965
+ ret = device_property_read_u32_array (cs35l56 -> base .dev , property , values , nval );
966
+ if (ret )
967
+ goto err ;
968
+
969
+ for (i = 0 ; i < nval ; i ++ ) {
970
+ if (values [i ] == id ) {
971
+ cs35l56 -> index = i ;
972
+ break ;
973
+ }
974
+ }
975
+
976
+ /*
977
+ * It's not an error for the ID to be missing: for I2C there can be
978
+ * an alias address that is not a real device. So reject silently.
979
+ */
980
+ if (cs35l56 -> index == -1 ) {
981
+ dev_dbg (cs35l56 -> base .dev , "No index found in %s\n" , property );
982
+ ret = - ENODEV ;
983
+ goto err ;
984
+ }
985
+ }
932
986
933
987
if (IS_ERR (sub )) {
934
988
dev_info (cs35l56 -> base .dev ,
0 commit comments