@@ -872,6 +872,52 @@ static int cs35l56_hda_system_resume(struct device *dev)
872872 return 0 ;
873873}
874874
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+
875921static int cs35l56_hda_read_acpi (struct cs35l56_hda * cs35l56 , int hid , int id )
876922{
877923 u32 values [HDA_MAX_COMPONENTS ];
@@ -896,39 +942,47 @@ static int cs35l56_hda_read_acpi(struct cs35l56_hda *cs35l56, int hid, int id)
896942 ACPI_COMPANION_SET (cs35l56 -> base .dev , adev );
897943 }
898944
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 ;
909947
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 );
911950 if (ret )
912- goto err ;
951+ return ret ;
913952
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- */
925953 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 ;
930958
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+ }
932986
933987 if (IS_ERR (sub )) {
934988 dev_info (cs35l56 -> base .dev ,
0 commit comments