xref: /linux/sound/soc/sdca/sdca_functions.c (revision cdd30ebb1b9f36159d66f088b61aee264e649d7a)
1 // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
2 // Copyright(c) 2024 Intel Corporation
3 
4 /*
5  * The MIPI SDCA specification is available for public downloads at
6  * https://www.mipi.org/mipi-sdca-v1-0-download
7  */
8 
9 #include <linux/acpi.h>
10 #include <linux/soundwire/sdw.h>
11 #include <sound/sdca.h>
12 #include <sound/sdca_function.h>
13 
patch_sdca_function_type(struct device * dev,u32 interface_revision,u32 * function_type,const char ** function_name)14 static int patch_sdca_function_type(struct device *dev,
15 				    u32 interface_revision,
16 				    u32 *function_type,
17 				    const char **function_name)
18 {
19 	unsigned long function_type_patch = 0;
20 
21 	/*
22 	 * Unfortunately early SDCA specifications used different indices for Functions,
23 	 * for backwards compatibility we have to reorder the values found
24 	 */
25 	if (interface_revision >= 0x0801)
26 		goto skip_early_draft_order;
27 
28 	switch (*function_type) {
29 	case 1:
30 		function_type_patch = SDCA_FUNCTION_TYPE_SMART_AMP;
31 		break;
32 	case 2:
33 		function_type_patch = SDCA_FUNCTION_TYPE_SMART_MIC;
34 		break;
35 	case 3:
36 		function_type_patch = SDCA_FUNCTION_TYPE_SPEAKER_MIC;
37 		break;
38 	case 4:
39 		function_type_patch = SDCA_FUNCTION_TYPE_UAJ;
40 		break;
41 	case 5:
42 		function_type_patch = SDCA_FUNCTION_TYPE_RJ;
43 		break;
44 	case 6:
45 		function_type_patch = SDCA_FUNCTION_TYPE_HID;
46 		break;
47 	default:
48 		dev_warn(dev, "%s: SDCA version %#x unsupported function type %d, skipped\n",
49 			 __func__, interface_revision, *function_type);
50 		return -EINVAL;
51 	}
52 
53 skip_early_draft_order:
54 	if (function_type_patch)
55 		*function_type = function_type_patch;
56 
57 	/* now double-check the values */
58 	switch (*function_type) {
59 	case SDCA_FUNCTION_TYPE_SMART_AMP:
60 		*function_name = SDCA_FUNCTION_TYPE_SMART_AMP_NAME;
61 		break;
62 	case SDCA_FUNCTION_TYPE_SMART_MIC:
63 		*function_name = SDCA_FUNCTION_TYPE_SMART_MIC_NAME;
64 		break;
65 	case SDCA_FUNCTION_TYPE_UAJ:
66 		*function_name = SDCA_FUNCTION_TYPE_UAJ_NAME;
67 		break;
68 	case SDCA_FUNCTION_TYPE_HID:
69 		*function_name = SDCA_FUNCTION_TYPE_HID_NAME;
70 		break;
71 	case SDCA_FUNCTION_TYPE_SIMPLE_AMP:
72 	case SDCA_FUNCTION_TYPE_SIMPLE_MIC:
73 	case SDCA_FUNCTION_TYPE_SPEAKER_MIC:
74 	case SDCA_FUNCTION_TYPE_RJ:
75 	case SDCA_FUNCTION_TYPE_IMP_DEF:
76 		dev_warn(dev, "%s: found unsupported SDCA function type %d, skipped\n",
77 			 __func__, *function_type);
78 		return -EINVAL;
79 	default:
80 		dev_err(dev, "%s: found invalid SDCA function type %d, skipped\n",
81 			__func__, *function_type);
82 		return -EINVAL;
83 	}
84 
85 	dev_info(dev, "%s: found SDCA function %s (type %d)\n",
86 		 __func__, *function_name, *function_type);
87 
88 	return 0;
89 }
90 
find_sdca_function(struct acpi_device * adev,void * data)91 static int find_sdca_function(struct acpi_device *adev, void *data)
92 {
93 	struct fwnode_handle *function_node = acpi_fwnode_handle(adev);
94 	struct sdca_device_data *sdca_data = data;
95 	struct device *dev = &adev->dev;
96 	struct fwnode_handle *control5; /* used to identify function type */
97 	const char *function_name;
98 	u32 function_type;
99 	int func_index;
100 	u64 addr;
101 	int ret;
102 
103 	if (sdca_data->num_functions >= SDCA_MAX_FUNCTION_COUNT) {
104 		dev_err(dev, "%s: maximum number of functions exceeded\n", __func__);
105 		return -EINVAL;
106 	}
107 
108 	/*
109 	 * The number of functions cannot exceed 8, we could use
110 	 * acpi_get_local_address() but the value is stored as u64 so
111 	 * we might as well avoid casts and intermediate levels
112 	 */
113 	ret = acpi_get_local_u64_address(adev->handle, &addr);
114 	if (ret < 0)
115 		return ret;
116 
117 	if (!addr) {
118 		dev_err(dev, "%s: no addr\n", __func__);
119 		return -ENODEV;
120 	}
121 
122 	/*
123 	 * Extracting the topology type for an SDCA function is a
124 	 * convoluted process.
125 	 * The Function type is only visible as a result of a read
126 	 * from a control. In theory this would mean reading from the hardware,
127 	 * but the SDCA/DisCo specs defined the notion of "DC value" - a constant
128 	 * represented with a DSD subproperty.
129 	 * Drivers have to query the properties for the control
130 	 * SDCA_CONTROL_ENTITY_0_FUNCTION_TOPOLOGY (0x05)
131 	 */
132 	control5 = fwnode_get_named_child_node(function_node,
133 					       "mipi-sdca-control-0x5-subproperties");
134 	if (!control5)
135 		return -ENODEV;
136 
137 	ret = fwnode_property_read_u32(control5, "mipi-sdca-control-dc-value",
138 				       &function_type);
139 
140 	fwnode_handle_put(control5);
141 
142 	if (ret < 0) {
143 		dev_err(dev, "%s: the function type can only be determined from ACPI information\n",
144 			__func__);
145 		return ret;
146 	}
147 
148 	ret = patch_sdca_function_type(dev, sdca_data->interface_revision,
149 				       &function_type, &function_name);
150 	if (ret < 0)
151 		return ret;
152 
153 	/* store results */
154 	func_index = sdca_data->num_functions;
155 	sdca_data->sdca_func[func_index].adr = addr;
156 	sdca_data->sdca_func[func_index].type = function_type;
157 	sdca_data->sdca_func[func_index].name = function_name;
158 	sdca_data->num_functions++;
159 
160 	return 0;
161 }
162 
sdca_lookup_functions(struct sdw_slave * slave)163 void sdca_lookup_functions(struct sdw_slave *slave)
164 {
165 	struct device *dev = &slave->dev;
166 	struct acpi_device *adev = to_acpi_device_node(dev->fwnode);
167 
168 	if (!adev) {
169 		dev_info(dev, "No matching ACPI device found, ignoring peripheral\n");
170 		return;
171 	}
172 	acpi_dev_for_each_child(adev, find_sdca_function, &slave->sdca_data);
173 }
174 EXPORT_SYMBOL_NS(sdca_lookup_functions, "SND_SOC_SDCA");
175 
176 MODULE_LICENSE("Dual BSD/GPL");
177 MODULE_DESCRIPTION("SDCA library");
178