@@ -814,6 +814,43 @@ static int find_sdca_control_range(struct device *dev,
814814 return 0 ;
815815}
816816
817+ static int find_sdca_control_value (struct device * dev , struct sdca_entity * entity ,
818+ struct fwnode_handle * control_node ,
819+ struct sdca_control * control ,
820+ const char * const label )
821+ {
822+ char property [SDCA_PROPERTY_LENGTH ];
823+ bool global = true;
824+ int ret , cn , i ;
825+ u32 tmp ;
826+
827+ snprintf (property , sizeof (property ), "mipi-sdca-control-%s" , label );
828+
829+ ret = fwnode_property_read_u32 (control_node , property , & tmp );
830+ if (ret == - EINVAL )
831+ global = false;
832+ else if (ret )
833+ return ret ;
834+
835+ i = 0 ;
836+ for_each_set_bit (cn , (unsigned long * )& control -> cn_list ,
837+ BITS_PER_TYPE (control -> cn_list )) {
838+ if (!global ) {
839+ snprintf (property , sizeof (property ),
840+ "mipi-sdca-control-cn-%d-%s" , cn , label );
841+
842+ ret = fwnode_property_read_u32 (control_node , property , & tmp );
843+ if (ret )
844+ return ret ;
845+ }
846+
847+ control -> values [i ] = tmp ;
848+ i ++ ;
849+ }
850+
851+ return 0 ;
852+ }
853+
817854/*
818855 * TODO: Add support for -cn- properties, allowing different channels to have
819856 * different defaults etc.
@@ -843,44 +880,44 @@ static int find_sdca_entity_control(struct device *dev, struct sdca_entity *enti
843880
844881 control -> layers = tmp ;
845882
883+ ret = fwnode_property_read_u64 (control_node , "mipi-sdca-control-cn-list" ,
884+ & control -> cn_list );
885+ if (ret == - EINVAL ) {
886+ /* Spec allows not specifying cn-list if only the first number is used */
887+ control -> cn_list = 0x1 ;
888+ } else if (ret || !control -> cn_list ) {
889+ dev_err (dev , "%s: control %#x: cn list missing: %d\n" ,
890+ entity -> label , control -> sel , ret );
891+ return ret ;
892+ }
893+
894+ control -> values = devm_kzalloc (dev , hweight64 (control -> cn_list ), GFP_KERNEL );
895+ if (!control -> values )
896+ return - ENOMEM ;
897+
846898 switch (control -> mode ) {
847899 case SDCA_ACCESS_MODE_DC :
848- ret = fwnode_property_read_u32 (control_node ,
849- "mipi-sdca-control-dc-value" ,
850- & tmp );
900+ ret = find_sdca_control_value (dev , entity , control_node , control ,
901+ "dc-value" );
851902 if (ret ) {
852903 dev_err (dev , "%s: control %#x: dc value missing: %d\n" ,
853904 entity -> label , control -> sel , ret );
854905 return ret ;
855906 }
856907
857- control -> value = tmp ;
858908 control -> has_fixed = true;
859909 break ;
860910 case SDCA_ACCESS_MODE_RW :
861911 case SDCA_ACCESS_MODE_DUAL :
862- ret = fwnode_property_read_u32 (control_node ,
863- "mipi-sdca-control-default-value" ,
864- & tmp );
865- if (!ret ) {
866- control -> value = tmp ;
912+ ret = find_sdca_control_value (dev , entity , control_node , control ,
913+ "default-value" );
914+ if (!ret )
867915 control -> has_default = true;
868- }
869-
870- ret = fwnode_property_read_u32 (control_node ,
871- "mipi-sdca-control-fixed-value" ,
872- & tmp );
873- if (!ret ) {
874- if (control -> has_default && control -> value != tmp ) {
875- dev_err (dev ,
876- "%s: control %#x: default and fixed value don't match\n" ,
877- entity -> label , control -> sel );
878- return - EINVAL ;
879- }
880916
881- control -> value = tmp ;
917+ ret = find_sdca_control_value (dev , entity , control_node , control ,
918+ "fixed-value" );
919+ if (!ret )
882920 control -> has_fixed = true;
883- }
884921 fallthrough ;
885922 case SDCA_ACCESS_MODE_RO :
886923 control -> deferrable = fwnode_property_read_bool (control_node ,
@@ -897,17 +934,6 @@ static int find_sdca_entity_control(struct device *dev, struct sdca_entity *enti
897934 return ret ;
898935 }
899936
900- ret = fwnode_property_read_u64 (control_node , "mipi-sdca-control-cn-list" ,
901- & control -> cn_list );
902- if (ret == - EINVAL ) {
903- /* Spec allows not specifying cn-list if only the first number is used */
904- control -> cn_list = 0x1 ;
905- } else if (ret || !control -> cn_list ) {
906- dev_err (dev , "%s: control %#x: cn list missing: %d\n" ,
907- entity -> label , control -> sel , ret );
908- return ret ;
909- }
910-
911937 ret = fwnode_property_read_u32 (control_node ,
912938 "mipi-sdca-control-interrupt-position" ,
913939 & tmp );
@@ -923,11 +949,10 @@ static int find_sdca_entity_control(struct device *dev, struct sdca_entity *enti
923949 control -> type = find_sdca_control_datatype (entity , control );
924950 control -> nbits = find_sdca_control_bits (entity , control );
925951
926- dev_info (dev , "%s: %s: control %#x mode %#x layers %#x cn %#llx int %d value %#x %s\n" ,
952+ dev_info (dev , "%s: %s: control %#x mode %#x layers %#x cn %#llx int %d %s\n" ,
927953 entity -> label , control -> label , control -> sel ,
928954 control -> mode , control -> layers , control -> cn_list ,
929- control -> interrupt_position , control -> value ,
930- control -> deferrable ? "deferrable" : "" );
955+ control -> interrupt_position , control -> deferrable ? "deferrable" : "" );
931956
932957 return 0 ;
933958}
0 commit comments