Blame view
drivers/soundwire/mipi_disco.c
10.7 KB
56d4fe31a soundwire: Add MI... |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) // Copyright(c) 2015-17 Intel Corporation. /* * MIPI Discovery And Configuration (DisCo) Specification for SoundWire * specifies properties to be implemented for SoundWire Masters and Slaves. * The DisCo spec doesn't mandate these properties. However, SDW bus cannot * work without knowing these values. * * The helper functions read the Master and Slave properties. Implementers * of Master or Slave drivers can use any of the below three mechanisms: * a) Use these APIs here as .read_prop() callback for Master and Slave * b) Implement own methods and set those as .read_prop(), but invoke * APIs in this file for generic read and override the values with * platform specific data * c) Implement ones own methods which do not use anything provided * here */ #include <linux/device.h> #include <linux/property.h> #include <linux/mod_devicetable.h> #include <linux/soundwire/sdw.h> #include "bus.h" /** * sdw_master_read_prop() - Read Master properties * @bus: SDW bus instance */ int sdw_master_read_prop(struct sdw_bus *bus) { struct sdw_master_prop *prop = &bus->prop; struct fwnode_handle *link; char name[32]; int nval, i; device_property_read_u32(bus->dev, |
31dba3129 soundwire: mipi_d... |
38 39 |
"mipi-sdw-sw-interface-revision", &prop->revision); |
56d4fe31a soundwire: Add MI... |
40 41 42 |
/* Find master handle */ snprintf(name, sizeof(name), |
eadc0049e soundwire: mipi_d... |
43 |
"mipi-sdw-link-%d-subproperties", bus->link_id); |
56d4fe31a soundwire: Add MI... |
44 45 46 47 48 49 50 51 52 |
link = device_get_named_child_node(bus->dev, name); if (!link) { dev_err(bus->dev, "Master node %s not found ", name); return -EIO; } if (fwnode_property_read_bool(link, |
00910f3cb soundwire: mipi_d... |
53 |
"mipi-sdw-clock-stop-mode0-supported")) |
53d2e9c37 soundwire: mipi-d... |
54 |
prop->clk_stop_modes |= BIT(SDW_CLK_STOP_MODE0); |
56d4fe31a soundwire: Add MI... |
55 56 |
if (fwnode_property_read_bool(link, |
00910f3cb soundwire: mipi_d... |
57 |
"mipi-sdw-clock-stop-mode1-supported")) |
53d2e9c37 soundwire: mipi-d... |
58 |
prop->clk_stop_modes |= BIT(SDW_CLK_STOP_MODE1); |
56d4fe31a soundwire: Add MI... |
59 60 |
fwnode_property_read_u32(link, |
31dba3129 soundwire: mipi_d... |
61 |
"mipi-sdw-max-clock-frequency", |
3424305b8 soundwire: rename... |
62 |
&prop->max_clk_freq); |
56d4fe31a soundwire: Add MI... |
63 |
|
be46cfba5 soundwire: mipi_d... |
64 |
nval = fwnode_property_count_u32(link, "mipi-sdw-clock-frequencies-supported"); |
56d4fe31a soundwire: Add MI... |
65 |
if (nval > 0) { |
3424305b8 soundwire: rename... |
66 67 68 69 70 |
prop->num_clk_freq = nval; prop->clk_freq = devm_kcalloc(bus->dev, prop->num_clk_freq, sizeof(*prop->clk_freq), GFP_KERNEL); if (!prop->clk_freq) |
56d4fe31a soundwire: Add MI... |
71 72 73 74 |
return -ENOMEM; fwnode_property_read_u32_array(link, "mipi-sdw-clock-frequencies-supported", |
3424305b8 soundwire: rename... |
75 |
prop->clk_freq, prop->num_clk_freq); |
56d4fe31a soundwire: Add MI... |
76 77 78 79 80 81 |
} /* * Check the frequencies supported. If FW doesn't provide max * freq, then populate here by checking values. */ |
3424305b8 soundwire: rename... |
82 83 84 85 86 |
if (!prop->max_clk_freq && prop->clk_freq) { prop->max_clk_freq = prop->clk_freq[0]; for (i = 1; i < prop->num_clk_freq; i++) { if (prop->clk_freq[i] > prop->max_clk_freq) prop->max_clk_freq = prop->clk_freq[i]; |
56d4fe31a soundwire: Add MI... |
87 88 |
} } |
be46cfba5 soundwire: mipi_d... |
89 |
nval = fwnode_property_count_u32(link, "mipi-sdw-supported-clock-gears"); |
56d4fe31a soundwire: Add MI... |
90 |
if (nval > 0) { |
56d4fe31a soundwire: Add MI... |
91 92 |
prop->num_clk_gears = nval; prop->clk_gears = devm_kcalloc(bus->dev, prop->num_clk_gears, |
31dba3129 soundwire: mipi_d... |
93 94 |
sizeof(*prop->clk_gears), GFP_KERNEL); |
56d4fe31a soundwire: Add MI... |
95 96 97 98 |
if (!prop->clk_gears) return -ENOMEM; fwnode_property_read_u32_array(link, |
31dba3129 soundwire: mipi_d... |
99 100 101 |
"mipi-sdw-supported-clock-gears", prop->clk_gears, prop->num_clk_gears); |
56d4fe31a soundwire: Add MI... |
102 103 104 |
} fwnode_property_read_u32(link, "mipi-sdw-default-frame-rate", |
31dba3129 soundwire: mipi_d... |
105 |
&prop->default_frame_rate); |
56d4fe31a soundwire: Add MI... |
106 107 |
fwnode_property_read_u32(link, "mipi-sdw-default-frame-row-size", |
31dba3129 soundwire: mipi_d... |
108 |
&prop->default_row); |
56d4fe31a soundwire: Add MI... |
109 110 |
fwnode_property_read_u32(link, "mipi-sdw-default-frame-col-size", |
31dba3129 soundwire: mipi_d... |
111 |
&prop->default_col); |
56d4fe31a soundwire: Add MI... |
112 113 114 115 116 |
prop->dynamic_frame = fwnode_property_read_bool(link, "mipi-sdw-dynamic-frame-shape"); fwnode_property_read_u32(link, "mipi-sdw-command-error-threshold", |
31dba3129 soundwire: mipi_d... |
117 |
&prop->err_threshold); |
56d4fe31a soundwire: Add MI... |
118 119 120 121 122 123 |
return 0; } EXPORT_SYMBOL(sdw_master_read_prop); static int sdw_slave_read_dp0(struct sdw_slave *slave, |
31dba3129 soundwire: mipi_d... |
124 125 |
struct fwnode_handle *port, struct sdw_dp0_prop *dp0) |
56d4fe31a soundwire: Add MI... |
126 127 128 129 |
{ int nval; fwnode_property_read_u32(port, "mipi-sdw-port-max-wordlength", |
31dba3129 soundwire: mipi_d... |
130 |
&dp0->max_word); |
56d4fe31a soundwire: Add MI... |
131 132 |
fwnode_property_read_u32(port, "mipi-sdw-port-min-wordlength", |
31dba3129 soundwire: mipi_d... |
133 |
&dp0->min_word); |
56d4fe31a soundwire: Add MI... |
134 |
|
be46cfba5 soundwire: mipi_d... |
135 |
nval = fwnode_property_count_u32(port, "mipi-sdw-port-wordlength-configs"); |
56d4fe31a soundwire: Add MI... |
136 137 138 139 |
if (nval > 0) { dp0->num_words = nval; dp0->words = devm_kcalloc(&slave->dev, |
31dba3129 soundwire: mipi_d... |
140 141 |
dp0->num_words, sizeof(*dp0->words), GFP_KERNEL); |
56d4fe31a soundwire: Add MI... |
142 143 144 145 146 147 148 |
if (!dp0->words) return -ENOMEM; fwnode_property_read_u32_array(port, "mipi-sdw-port-wordlength-configs", dp0->words, dp0->num_words); } |
8acbbfec2 soundwire: rename... |
149 |
dp0->BRA_flow_controlled = fwnode_property_read_bool(port, |
31dba3129 soundwire: mipi_d... |
150 |
"mipi-sdw-bra-flow-controlled"); |
56d4fe31a soundwire: Add MI... |
151 |
|
31dba3129 soundwire: mipi_d... |
152 153 |
dp0->simple_ch_prep_sm = fwnode_property_read_bool(port, "mipi-sdw-simplified-channel-prepare-sm"); |
56d4fe31a soundwire: Add MI... |
154 |
|
8acbbfec2 soundwire: rename... |
155 |
dp0->imp_def_interrupts = fwnode_property_read_bool(port, |
31dba3129 soundwire: mipi_d... |
156 |
"mipi-sdw-imp-def-dp0-interrupts-supported"); |
56d4fe31a soundwire: Add MI... |
157 158 159 160 161 |
return 0; } static int sdw_slave_read_dpn(struct sdw_slave *slave, |
31dba3129 soundwire: mipi_d... |
162 163 |
struct sdw_dpn_prop *dpn, int count, int ports, char *type) |
56d4fe31a soundwire: Add MI... |
164 165 166 167 168 169 170 171 172 173 174 175 176 |
{ struct fwnode_handle *node; u32 bit, i = 0; int nval; unsigned long addr; char name[40]; addr = ports; /* valid ports are 1 to 14 so apply mask */ addr &= GENMASK(14, 1); for_each_set_bit(bit, &addr, 32) { snprintf(name, sizeof(name), |
31dba3129 soundwire: mipi_d... |
177 |
"mipi-sdw-dp-%d-%s-subproperties", bit, type); |
56d4fe31a soundwire: Add MI... |
178 179 180 181 182 183 184 185 186 187 188 |
dpn[i].num = bit; node = device_get_named_child_node(&slave->dev, name); if (!node) { dev_err(&slave->dev, "%s dpN not found ", name); return -EIO; } fwnode_property_read_u32(node, "mipi-sdw-port-max-wordlength", |
31dba3129 soundwire: mipi_d... |
189 |
&dpn[i].max_word); |
56d4fe31a soundwire: Add MI... |
190 |
fwnode_property_read_u32(node, "mipi-sdw-port-min-wordlength", |
31dba3129 soundwire: mipi_d... |
191 |
&dpn[i].min_word); |
56d4fe31a soundwire: Add MI... |
192 |
|
be46cfba5 soundwire: mipi_d... |
193 |
nval = fwnode_property_count_u32(node, "mipi-sdw-port-wordlength-configs"); |
56d4fe31a soundwire: Add MI... |
194 |
if (nval > 0) { |
56d4fe31a soundwire: Add MI... |
195 196 |
dpn[i].num_words = nval; dpn[i].words = devm_kcalloc(&slave->dev, |
31dba3129 soundwire: mipi_d... |
197 198 199 |
dpn[i].num_words, sizeof(*dpn[i].words), GFP_KERNEL); |
56d4fe31a soundwire: Add MI... |
200 201 202 203 204 205 206 207 208 |
if (!dpn[i].words) return -ENOMEM; fwnode_property_read_u32_array(node, "mipi-sdw-port-wordlength-configs", dpn[i].words, dpn[i].num_words); } fwnode_property_read_u32(node, "mipi-sdw-data-port-type", |
31dba3129 soundwire: mipi_d... |
209 |
&dpn[i].type); |
56d4fe31a soundwire: Add MI... |
210 211 |
fwnode_property_read_u32(node, |
31dba3129 soundwire: mipi_d... |
212 213 |
"mipi-sdw-max-grouping-supported", &dpn[i].max_grouping); |
56d4fe31a soundwire: Add MI... |
214 215 216 217 218 |
dpn[i].simple_ch_prep_sm = fwnode_property_read_bool(node, "mipi-sdw-simplified-channelprepare-sm"); fwnode_property_read_u32(node, |
31dba3129 soundwire: mipi_d... |
219 220 |
"mipi-sdw-port-channelprepare-timeout", &dpn[i].ch_prep_timeout); |
56d4fe31a soundwire: Add MI... |
221 222 223 |
fwnode_property_read_u32(node, "mipi-sdw-imp-def-dpn-interrupts-supported", |
8acbbfec2 soundwire: rename... |
224 |
&dpn[i].imp_def_interrupts); |
56d4fe31a soundwire: Add MI... |
225 226 |
fwnode_property_read_u32(node, "mipi-sdw-min-channel-number", |
31dba3129 soundwire: mipi_d... |
227 |
&dpn[i].min_ch); |
56d4fe31a soundwire: Add MI... |
228 229 |
fwnode_property_read_u32(node, "mipi-sdw-max-channel-number", |
31dba3129 soundwire: mipi_d... |
230 |
&dpn[i].max_ch); |
56d4fe31a soundwire: Add MI... |
231 |
|
be46cfba5 soundwire: mipi_d... |
232 |
nval = fwnode_property_count_u32(node, "mipi-sdw-channel-number-list"); |
56d4fe31a soundwire: Add MI... |
233 |
if (nval > 0) { |
6bf393c57 soundwire: disco:... |
234 235 236 237 |
dpn[i].num_channels = nval; dpn[i].channels = devm_kcalloc(&slave->dev, dpn[i].num_channels, sizeof(*dpn[i].channels), |
31dba3129 soundwire: mipi_d... |
238 |
GFP_KERNEL); |
6bf393c57 soundwire: disco:... |
239 |
if (!dpn[i].channels) |
56d4fe31a soundwire: Add MI... |
240 241 242 243 |
return -ENOMEM; fwnode_property_read_u32_array(node, "mipi-sdw-channel-number-list", |
6bf393c57 soundwire: disco:... |
244 |
dpn[i].channels, dpn[i].num_channels); |
56d4fe31a soundwire: Add MI... |
245 |
} |
be46cfba5 soundwire: mipi_d... |
246 |
nval = fwnode_property_count_u32(node, "mipi-sdw-channel-combination-list"); |
56d4fe31a soundwire: Add MI... |
247 |
if (nval > 0) { |
56d4fe31a soundwire: Add MI... |
248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 |
dpn[i].num_ch_combinations = nval; dpn[i].ch_combinations = devm_kcalloc(&slave->dev, dpn[i].num_ch_combinations, sizeof(*dpn[i].ch_combinations), GFP_KERNEL); if (!dpn[i].ch_combinations) return -ENOMEM; fwnode_property_read_u32_array(node, "mipi-sdw-channel-combination-list", dpn[i].ch_combinations, dpn[i].num_ch_combinations); } fwnode_property_read_u32(node, "mipi-sdw-modes-supported", &dpn[i].modes); fwnode_property_read_u32(node, "mipi-sdw-max-async-buffer", |
31dba3129 soundwire: mipi_d... |
266 |
&dpn[i].max_async_buffer); |
56d4fe31a soundwire: Add MI... |
267 268 269 270 271 |
dpn[i].block_pack_mode = fwnode_property_read_bool(node, "mipi-sdw-block-packing-mode"); fwnode_property_read_u32(node, "mipi-sdw-port-encoding-type", |
31dba3129 soundwire: mipi_d... |
272 |
&dpn[i].port_encoding); |
56d4fe31a soundwire: Add MI... |
273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 |
/* TODO: Read audio mode */ i++; } return 0; } /** * sdw_slave_read_prop() - Read Slave properties * @slave: SDW Slave */ int sdw_slave_read_prop(struct sdw_slave *slave) { struct sdw_slave_prop *prop = &slave->prop; struct device *dev = &slave->dev; struct fwnode_handle *port; |
607375588 soundwire: fix po... |
291 |
int nval; |
56d4fe31a soundwire: Add MI... |
292 293 |
device_property_read_u32(dev, "mipi-sdw-sw-interface-revision", |
31dba3129 soundwire: mipi_d... |
294 |
&prop->mipi_revision); |
56d4fe31a soundwire: Add MI... |
295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 |
prop->wake_capable = device_property_read_bool(dev, "mipi-sdw-wake-up-unavailable"); prop->wake_capable = !prop->wake_capable; prop->test_mode_capable = device_property_read_bool(dev, "mipi-sdw-test-mode-supported"); prop->clk_stop_mode1 = false; if (device_property_read_bool(dev, "mipi-sdw-clock-stop-mode1-supported")) prop->clk_stop_mode1 = true; prop->simple_clk_stop_capable = device_property_read_bool(dev, "mipi-sdw-simplified-clockstopprepare-sm-supported"); device_property_read_u32(dev, "mipi-sdw-clockstopprepare-timeout", |
31dba3129 soundwire: mipi_d... |
312 |
&prop->clk_stop_timeout); |
56d4fe31a soundwire: Add MI... |
313 314 |
device_property_read_u32(dev, "mipi-sdw-slave-channelprepare-timeout", |
31dba3129 soundwire: mipi_d... |
315 |
&prop->ch_prep_timeout); |
56d4fe31a soundwire: Add MI... |
316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 |
device_property_read_u32(dev, "mipi-sdw-clockstopprepare-hard-reset-behavior", &prop->reset_behave); prop->high_PHY_capable = device_property_read_bool(dev, "mipi-sdw-highPHY-capable"); prop->paging_support = device_property_read_bool(dev, "mipi-sdw-paging-support"); prop->bank_delay_support = device_property_read_bool(dev, "mipi-sdw-bank-delay-support"); device_property_read_u32(dev, "mipi-sdw-port15-read-behavior", &prop->p15_behave); device_property_read_u32(dev, "mipi-sdw-master-count", |
31dba3129 soundwire: mipi_d... |
334 |
&prop->master_count); |
56d4fe31a soundwire: Add MI... |
335 336 |
device_property_read_u32(dev, "mipi-sdw-source-port-list", |
31dba3129 soundwire: mipi_d... |
337 |
&prop->source_ports); |
56d4fe31a soundwire: Add MI... |
338 339 |
device_property_read_u32(dev, "mipi-sdw-sink-port-list", |
31dba3129 soundwire: mipi_d... |
340 |
&prop->sink_ports); |
56d4fe31a soundwire: Add MI... |
341 342 343 344 345 346 347 |
/* Read dp0 properties */ port = device_get_named_child_node(dev, "mipi-sdw-dp-0-subproperties"); if (!port) { dev_dbg(dev, "DP0 node not found!! "); } else { |
56d4fe31a soundwire: Add MI... |
348 |
prop->dp0_prop = devm_kzalloc(&slave->dev, |
31dba3129 soundwire: mipi_d... |
349 350 |
sizeof(*prop->dp0_prop), GFP_KERNEL); |
56d4fe31a soundwire: Add MI... |
351 352 353 354 |
if (!prop->dp0_prop) return -ENOMEM; sdw_slave_read_dp0(slave, port, prop->dp0_prop); |
56d4fe31a soundwire: Add MI... |
355 356 357 358 359 360 361 362 363 364 |
} /* * Based on each DPn port, get source and sink dpn properties. * Also, some ports can operate as both source or sink. */ /* Allocate memory for set bits in port lists */ nval = hweight32(prop->source_ports); prop->src_dpn_prop = devm_kcalloc(&slave->dev, nval, |
31dba3129 soundwire: mipi_d... |
365 366 |
sizeof(*prop->src_dpn_prop), GFP_KERNEL); |
56d4fe31a soundwire: Add MI... |
367 368 369 370 371 |
if (!prop->src_dpn_prop) return -ENOMEM; /* Read dpn properties for source port(s) */ sdw_slave_read_dpn(slave, prop->src_dpn_prop, nval, |
31dba3129 soundwire: mipi_d... |
372 |
prop->source_ports, "source"); |
56d4fe31a soundwire: Add MI... |
373 374 375 |
nval = hweight32(prop->sink_ports); prop->sink_dpn_prop = devm_kcalloc(&slave->dev, nval, |
31dba3129 soundwire: mipi_d... |
376 377 |
sizeof(*prop->sink_dpn_prop), GFP_KERNEL); |
56d4fe31a soundwire: Add MI... |
378 379 380 381 382 |
if (!prop->sink_dpn_prop) return -ENOMEM; /* Read dpn properties for sink port(s) */ sdw_slave_read_dpn(slave, prop->sink_dpn_prop, nval, |
31dba3129 soundwire: mipi_d... |
383 |
prop->sink_ports, "sink"); |
56d4fe31a soundwire: Add MI... |
384 |
|
56d4fe31a soundwire: Add MI... |
385 386 387 |
return 0; } EXPORT_SYMBOL(sdw_slave_read_prop); |