xref: /linux/drivers/soundwire/generic_bandwidth_allocation.c (revision 72deda0abee6e705ae71a93f69f55e33be5bca5c)
1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
2 // Copyright(c) 2015-2020 Intel Corporation.
3 
4 /*
5  * Bandwidth management algorithm based on 2^n gears
6  *
7  */
8 
9 #include <linux/bitops.h>
10 #include <linux/device.h>
11 #include <linux/module.h>
12 #include <linux/mod_devicetable.h>
13 #include <linux/slab.h>
14 #include <linux/soundwire/sdw.h>
15 #include "bus.h"
16 
17 #define SDW_STRM_RATE_GROUPING		1
18 
19 struct sdw_group_params {
20 	unsigned int rate;
21 	unsigned int lane;
22 	int full_bw;
23 	int payload_bw;
24 	int hwidth;
25 };
26 
27 struct sdw_group {
28 	unsigned int count;
29 	unsigned int max_size;
30 	unsigned int *rates;
31 	unsigned int *lanes;
32 };
33 
34 void sdw_compute_slave_ports(struct sdw_master_runtime *m_rt,
35 			     struct sdw_transport_data *t_data)
36 {
37 	struct sdw_slave_runtime *s_rt = NULL;
38 	struct sdw_port_runtime *p_rt;
39 	int port_bo, sample_int;
40 	unsigned int rate, bps, ch = 0;
41 	unsigned int slave_total_ch;
42 	struct sdw_bus_params *b_params = &m_rt->bus->params;
43 
44 	port_bo = t_data->block_offset;
45 
46 	list_for_each_entry(s_rt, &m_rt->slave_rt_list, m_rt_node) {
47 		rate = m_rt->stream->params.rate;
48 		bps = m_rt->stream->params.bps;
49 		sample_int = (m_rt->bus->params.curr_dr_freq / rate);
50 		slave_total_ch = 0;
51 
52 		list_for_each_entry(p_rt, &s_rt->port_list, port_node) {
53 			if (p_rt->lane != t_data->lane)
54 				continue;
55 
56 			ch = hweight32(p_rt->ch_mask);
57 
58 			sdw_fill_xport_params(&p_rt->transport_params,
59 					      p_rt->num, false,
60 					      SDW_BLK_GRP_CNT_1,
61 					      sample_int, port_bo, port_bo >> 8,
62 					      t_data->hstart,
63 					      t_data->hstop,
64 					      SDW_BLK_PKG_PER_PORT, p_rt->lane);
65 
66 			sdw_fill_port_params(&p_rt->port_params,
67 					     p_rt->num, bps,
68 					     SDW_PORT_FLOW_MODE_ISOCH,
69 					     b_params->s_data_mode);
70 
71 			port_bo += bps * ch;
72 			slave_total_ch += ch;
73 		}
74 
75 		if (m_rt->direction == SDW_DATA_DIR_TX &&
76 		    m_rt->ch_count == slave_total_ch) {
77 			/*
78 			 * Slave devices were configured to access all channels
79 			 * of the stream, which indicates that they operate in
80 			 * 'mirror mode'. Make sure we reset the port offset for
81 			 * the next device in the list
82 			 */
83 			port_bo = t_data->block_offset;
84 		}
85 	}
86 }
87 EXPORT_SYMBOL(sdw_compute_slave_ports);
88 
89 static void sdw_compute_master_ports(struct sdw_master_runtime *m_rt,
90 				     struct sdw_group_params *params,
91 				     int *port_bo, int hstop)
92 {
93 	struct sdw_transport_data t_data = {0};
94 	struct sdw_port_runtime *p_rt;
95 	struct sdw_bus *bus = m_rt->bus;
96 	struct sdw_bus_params *b_params = &bus->params;
97 	int sample_int, hstart = 0;
98 	unsigned int rate, bps, ch;
99 
100 	rate = m_rt->stream->params.rate;
101 	bps = m_rt->stream->params.bps;
102 	ch = m_rt->ch_count;
103 	sample_int = (bus->params.curr_dr_freq / rate);
104 
105 	if (rate != params->rate)
106 		return;
107 
108 	t_data.hstop = hstop;
109 	hstart = hstop - params->hwidth + 1;
110 	t_data.hstart = hstart;
111 
112 	list_for_each_entry(p_rt, &m_rt->port_list, port_node) {
113 		if (p_rt->lane != params->lane)
114 			continue;
115 
116 		sdw_fill_xport_params(&p_rt->transport_params, p_rt->num,
117 				      false, SDW_BLK_GRP_CNT_1, sample_int,
118 				      *port_bo, (*port_bo) >> 8, hstart, hstop,
119 				      SDW_BLK_PKG_PER_PORT, p_rt->lane);
120 
121 		sdw_fill_port_params(&p_rt->port_params,
122 				     p_rt->num, bps,
123 				     SDW_PORT_FLOW_MODE_ISOCH,
124 				     b_params->m_data_mode);
125 
126 		/* Check for first entry */
127 		if (!(p_rt == list_first_entry(&m_rt->port_list,
128 					       struct sdw_port_runtime,
129 					       port_node))) {
130 			(*port_bo) += bps * ch;
131 			continue;
132 		}
133 
134 		t_data.hstart = hstart;
135 		t_data.hstop = hstop;
136 		t_data.block_offset = *port_bo;
137 		t_data.sub_block_offset = 0;
138 		(*port_bo) += bps * ch;
139 	}
140 
141 	t_data.lane = params->lane;
142 	sdw_compute_slave_ports(m_rt, &t_data);
143 }
144 
145 static void _sdw_compute_port_params(struct sdw_bus *bus,
146 				     struct sdw_group_params *params, int count)
147 {
148 	struct sdw_master_runtime *m_rt;
149 	int port_bo, i, l;
150 	int hstop;
151 
152 	/* Run loop for all groups to compute transport parameters */
153 	for (l = 0; l < SDW_MAX_LANES; l++) {
154 		if (l > 0 && !bus->lane_used_bandwidth[l])
155 			continue;
156 		/* reset hstop for each lane */
157 		hstop = bus->params.col - 1;
158 		for (i = 0; i < count; i++) {
159 			if (params[i].lane != l)
160 				continue;
161 			port_bo = 1;
162 
163 			list_for_each_entry(m_rt, &bus->m_rt_list, bus_node) {
164 				sdw_compute_master_ports(m_rt, &params[i], &port_bo, hstop);
165 			}
166 
167 			hstop = hstop - params[i].hwidth;
168 		}
169 	}
170 }
171 
172 static int sdw_compute_group_params(struct sdw_bus *bus,
173 				    struct sdw_stream_runtime *stream,
174 				    struct sdw_group_params *params,
175 				    struct sdw_group *group)
176 {
177 	struct sdw_master_runtime *m_rt;
178 	struct sdw_port_runtime *p_rt;
179 	int sel_col = bus->params.col;
180 	unsigned int rate, bps, ch;
181 	int i, l, column_needed;
182 
183 	/* Calculate bandwidth per group */
184 	for (i = 0; i < group->count; i++) {
185 		params[i].rate = group->rates[i];
186 		params[i].lane = group->lanes[i];
187 		params[i].full_bw = bus->params.curr_dr_freq / params[i].rate;
188 	}
189 
190 	list_for_each_entry(m_rt, &bus->m_rt_list, bus_node) {
191 		if (m_rt->stream == stream) {
192 			/* Only runtime during prepare should be added */
193 			if (stream->state != SDW_STREAM_CONFIGURED)
194 				continue;
195 		} else {
196 			/*
197 			 * Include runtimes with running (ENABLED state) and paused (DISABLED state)
198 			 * streams
199 			 */
200 			if (m_rt->stream->state != SDW_STREAM_ENABLED &&
201 			    m_rt->stream->state != SDW_STREAM_DISABLED)
202 				continue;
203 		}
204 		list_for_each_entry(p_rt, &m_rt->port_list, port_node) {
205 			rate = m_rt->stream->params.rate;
206 			bps = m_rt->stream->params.bps;
207 			ch = hweight32(p_rt->ch_mask);
208 
209 			for (i = 0; i < group->count; i++) {
210 				if (rate == params[i].rate && p_rt->lane == params[i].lane)
211 					params[i].payload_bw += bps * ch;
212 			}
213 		}
214 	}
215 
216 	for (l = 0; l < SDW_MAX_LANES; l++) {
217 		if (l > 0 && !bus->lane_used_bandwidth[l])
218 			continue;
219 		/* reset column_needed for each lane */
220 		column_needed = 0;
221 		for (i = 0; i < group->count; i++) {
222 			if (params[i].lane != l)
223 				continue;
224 
225 			params[i].hwidth = (sel_col * params[i].payload_bw +
226 					    params[i].full_bw - 1) / params[i].full_bw;
227 
228 			column_needed += params[i].hwidth;
229 			/* There is no control column for lane 1 and above */
230 			if (column_needed > sel_col)
231 				return -EINVAL;
232 			/* Column 0 is control column on lane 0 */
233 			if (params[i].lane == 0 && column_needed > sel_col - 1)
234 				return -EINVAL;
235 		}
236 	}
237 
238 
239 	return 0;
240 }
241 
242 static int sdw_add_element_group_count(struct sdw_group *group,
243 				       unsigned int rate, unsigned int lane)
244 {
245 	int num = group->count;
246 	int i;
247 
248 	for (i = 0; i <= num; i++) {
249 		if (rate == group->rates[i] && lane == group->lanes[i])
250 			break;
251 
252 		if (i != num)
253 			continue;
254 
255 		if (group->count >= group->max_size) {
256 			unsigned int *rates;
257 			unsigned int *lanes;
258 
259 			group->max_size += 1;
260 			rates = krealloc(group->rates,
261 					 (sizeof(int) * group->max_size),
262 					 GFP_KERNEL);
263 			if (!rates)
264 				return -ENOMEM;
265 
266 			group->rates = rates;
267 
268 			lanes = krealloc(group->lanes,
269 					 (sizeof(int) * group->max_size),
270 					 GFP_KERNEL);
271 			if (!lanes)
272 				return -ENOMEM;
273 
274 			group->lanes = lanes;
275 		}
276 
277 		group->rates[group->count] = rate;
278 		group->lanes[group->count++] = lane;
279 	}
280 
281 	return 0;
282 }
283 
284 static int sdw_get_group_count(struct sdw_bus *bus,
285 			       struct sdw_group *group)
286 {
287 	struct sdw_master_runtime *m_rt;
288 	struct sdw_port_runtime *p_rt;
289 	unsigned int rate;
290 	int ret = 0;
291 
292 	group->count = 0;
293 	group->max_size = SDW_STRM_RATE_GROUPING;
294 	group->rates = kcalloc(group->max_size, sizeof(int), GFP_KERNEL);
295 	if (!group->rates)
296 		return -ENOMEM;
297 
298 	group->lanes = kcalloc(group->max_size, sizeof(int), GFP_KERNEL);
299 	if (!group->lanes) {
300 		kfree(group->rates);
301 		group->rates = NULL;
302 		return -ENOMEM;
303 	}
304 
305 	list_for_each_entry(m_rt, &bus->m_rt_list, bus_node) {
306 		if (m_rt->stream->state == SDW_STREAM_DEPREPARED)
307 			continue;
308 
309 		rate = m_rt->stream->params.rate;
310 		if (m_rt == list_first_entry(&bus->m_rt_list,
311 					     struct sdw_master_runtime,
312 					     bus_node)) {
313 			group->rates[group->count++] = rate;
314 		}
315 		/*
316 		 * Different ports could use different lane, add group element
317 		 * even if m_rt is the first entry
318 		 */
319 		list_for_each_entry(p_rt, &m_rt->port_list, port_node) {
320 			ret = sdw_add_element_group_count(group, rate, p_rt->lane);
321 			if (ret < 0) {
322 				kfree(group->rates);
323 				kfree(group->lanes);
324 				return ret;
325 			}
326 		}
327 	}
328 
329 	return ret;
330 }
331 
332 /**
333  * sdw_compute_port_params: Compute transport and port parameters
334  *
335  * @bus: SDW Bus instance
336  * @stream: Soundwire stream
337  */
338 static int sdw_compute_port_params(struct sdw_bus *bus, struct sdw_stream_runtime *stream)
339 {
340 	struct sdw_group_params *params = NULL;
341 	struct sdw_group group;
342 	int ret;
343 
344 	ret = sdw_get_group_count(bus, &group);
345 	if (ret < 0)
346 		return ret;
347 
348 	if (group.count == 0)
349 		goto out;
350 
351 	params = kcalloc(group.count, sizeof(*params), GFP_KERNEL);
352 	if (!params) {
353 		ret = -ENOMEM;
354 		goto out;
355 	}
356 
357 	/* Compute transport parameters for grouped streams */
358 	ret = sdw_compute_group_params(bus, stream, params, &group);
359 	if (ret < 0)
360 		goto free_params;
361 
362 	_sdw_compute_port_params(bus, params, group.count);
363 
364 free_params:
365 	kfree(params);
366 out:
367 	kfree(group.rates);
368 	kfree(group.lanes);
369 
370 	return ret;
371 }
372 
373 static int sdw_select_row_col(struct sdw_bus *bus, int clk_freq)
374 {
375 	struct sdw_master_prop *prop = &bus->prop;
376 	int r, c;
377 
378 	for (c = 0; c < SDW_FRAME_COLS; c++) {
379 		for (r = 0; r < SDW_FRAME_ROWS; r++) {
380 			if (sdw_rows[r] != prop->default_row ||
381 			    sdw_cols[c] != prop->default_col)
382 				continue;
383 
384 			if (clk_freq * (sdw_cols[c] - 1) <
385 			    bus->params.bandwidth * sdw_cols[c])
386 				continue;
387 
388 			bus->params.row = sdw_rows[r];
389 			bus->params.col = sdw_cols[c];
390 			return 0;
391 		}
392 	}
393 
394 	return -EINVAL;
395 }
396 
397 static bool is_clock_scaling_supported(struct sdw_bus *bus)
398 {
399 	struct sdw_master_runtime *m_rt;
400 	struct sdw_slave_runtime *s_rt;
401 
402 	list_for_each_entry(m_rt, &bus->m_rt_list, bus_node)
403 		list_for_each_entry(s_rt, &m_rt->slave_rt_list, m_rt_node)
404 			if (!is_clock_scaling_supported_by_slave(s_rt->slave))
405 				return false;
406 
407 	return true;
408 }
409 
410 /**
411  * is_lane_connected_to_all_peripherals: Check if the given manager lane connects to all peripherals
412  * So that all peripherals can use the manager lane.
413  *
414  * @m_rt: Manager runtime
415  * @lane: Lane number
416  */
417 static bool is_lane_connected_to_all_peripherals(struct sdw_master_runtime *m_rt, unsigned int lane)
418 {
419 	struct sdw_slave_prop *slave_prop;
420 	struct sdw_slave_runtime *s_rt;
421 	int i;
422 
423 	list_for_each_entry(s_rt, &m_rt->slave_rt_list, m_rt_node) {
424 		slave_prop = &s_rt->slave->prop;
425 		for (i = 1; i < SDW_MAX_LANES; i++) {
426 			if (slave_prop->lane_maps[i] == lane) {
427 				dev_dbg(&s_rt->slave->dev,
428 					"M lane %d is connected to P lane %d\n",
429 					lane, i);
430 				break;
431 			}
432 		}
433 		if (i == SDW_MAX_LANES) {
434 			dev_dbg(&s_rt->slave->dev, "M lane %d is not connected\n", lane);
435 			return false;
436 		}
437 	}
438 	return true;
439 }
440 
441 static int get_manager_lane(struct sdw_bus *bus, struct sdw_master_runtime *m_rt,
442 			    struct sdw_slave_runtime *s_rt, unsigned int curr_dr_freq)
443 {
444 	struct sdw_slave_prop *slave_prop = &s_rt->slave->prop;
445 	struct sdw_port_runtime *m_p_rt;
446 	unsigned int required_bandwidth;
447 	int m_lane;
448 	int l;
449 
450 	for (l = 1; l < SDW_MAX_LANES; l++) {
451 		if (!slave_prop->lane_maps[l])
452 			continue;
453 
454 		required_bandwidth = 0;
455 		list_for_each_entry(m_p_rt, &m_rt->port_list, port_node) {
456 			required_bandwidth += m_rt->stream->params.rate *
457 					      hweight32(m_p_rt->ch_mask) *
458 					      m_rt->stream->params.bps;
459 		}
460 		if (required_bandwidth <=
461 		    curr_dr_freq - bus->lane_used_bandwidth[l]) {
462 			/* Check if m_lane is connected to all Peripherals */
463 			if (!is_lane_connected_to_all_peripherals(m_rt,
464 				slave_prop->lane_maps[l])) {
465 				dev_dbg(bus->dev,
466 					"Not all Peripherals are connected to M lane %d\n",
467 					slave_prop->lane_maps[l]);
468 				continue;
469 			}
470 			m_lane = slave_prop->lane_maps[l];
471 			dev_dbg(&s_rt->slave->dev, "M lane %d is used\n", m_lane);
472 			bus->lane_used_bandwidth[l] += required_bandwidth;
473 			/*
474 			 * Use non-zero manager lane, subtract the lane 0
475 			 * bandwidth that is already calculated
476 			 */
477 			bus->params.bandwidth -= required_bandwidth;
478 			return m_lane;
479 		}
480 	}
481 
482 	/* No available multi lane found, only lane 0 can be used */
483 	return 0;
484 }
485 
486 /**
487  * sdw_compute_bus_params: Compute bus parameters
488  *
489  * @bus: SDW Bus instance
490  */
491 static int sdw_compute_bus_params(struct sdw_bus *bus)
492 {
493 	struct sdw_master_prop *mstr_prop = &bus->prop;
494 	struct sdw_slave_prop *slave_prop;
495 	struct sdw_port_runtime *m_p_rt;
496 	struct sdw_port_runtime *s_p_rt;
497 	struct sdw_master_runtime *m_rt;
498 	struct sdw_slave_runtime *s_rt;
499 	unsigned int curr_dr_freq = 0;
500 	int i, l, clk_values, ret;
501 	bool is_gear = false;
502 	int m_lane = 0;
503 	u32 *clk_buf;
504 
505 	if (mstr_prop->num_clk_gears) {
506 		clk_values = mstr_prop->num_clk_gears;
507 		clk_buf = mstr_prop->clk_gears;
508 		is_gear = true;
509 	} else if (mstr_prop->num_clk_freq) {
510 		clk_values = mstr_prop->num_clk_freq;
511 		clk_buf = mstr_prop->clk_freq;
512 	} else {
513 		clk_values = 1;
514 		clk_buf = NULL;
515 	}
516 
517 	/* If dynamic scaling is not supported, don't try higher freq */
518 	if (!is_clock_scaling_supported(bus))
519 		clk_values = 1;
520 
521 	for (i = 0; i < clk_values; i++) {
522 		if (!clk_buf)
523 			curr_dr_freq = bus->params.max_dr_freq;
524 		else
525 			curr_dr_freq = (is_gear) ?
526 				(bus->params.max_dr_freq >>  clk_buf[i]) :
527 				clk_buf[i] * SDW_DOUBLE_RATE_FACTOR;
528 
529 		if (curr_dr_freq * (mstr_prop->default_col - 1) >=
530 		    bus->params.bandwidth * mstr_prop->default_col)
531 			break;
532 
533 		list_for_each_entry(m_rt, &bus->m_rt_list, bus_node) {
534 			/*
535 			 * Get the first s_rt that will be used to find the available lane that
536 			 * can be used. No need to check all Peripherals because we can't use
537 			 * multi-lane if we can't find any available lane for the first Peripheral.
538 			 */
539 			s_rt = list_first_entry(&m_rt->slave_rt_list,
540 						struct sdw_slave_runtime, m_rt_node);
541 
542 			/*
543 			 * Find the available Manager lane that connected to the first Peripheral.
544 			 */
545 			m_lane = get_manager_lane(bus, m_rt, s_rt, curr_dr_freq);
546 			if (m_lane > 0)
547 				goto out;
548 		}
549 
550 		/*
551 		 * TODO: Check all the Slave(s) port(s) audio modes and find
552 		 * whether given clock rate is supported with glitchless
553 		 * transition.
554 		 */
555 	}
556 
557 	if (i == clk_values) {
558 		dev_err(bus->dev, "%s: could not find clock value for bandwidth %d\n",
559 			__func__, bus->params.bandwidth);
560 		return -EINVAL;
561 	}
562 out:
563 	/* multilane can be used */
564 	if (m_lane > 0) {
565 		/* Set Peripheral lanes */
566 		list_for_each_entry(s_rt, &m_rt->slave_rt_list, m_rt_node) {
567 			slave_prop = &s_rt->slave->prop;
568 			for (l = 1; l < SDW_MAX_LANES; l++) {
569 				if (slave_prop->lane_maps[l] == m_lane) {
570 					list_for_each_entry(s_p_rt, &s_rt->port_list, port_node) {
571 						s_p_rt->lane = l;
572 						dev_dbg(&s_rt->slave->dev,
573 							"Set P lane %d for port %d\n",
574 							l, s_p_rt->num);
575 					}
576 					break;
577 				}
578 			}
579 		}
580 		/*
581 		 * Set Manager lanes. Configure the last m_rt in bus->m_rt_list only since
582 		 * we don't want to touch other m_rts that are already working.
583 		 */
584 		list_for_each_entry(m_p_rt, &m_rt->port_list, port_node) {
585 			m_p_rt->lane = m_lane;
586 		}
587 	}
588 
589 	if (!mstr_prop->default_frame_rate || !mstr_prop->default_row)
590 		return -EINVAL;
591 
592 	mstr_prop->default_col = curr_dr_freq / mstr_prop->default_frame_rate /
593 				 mstr_prop->default_row;
594 
595 	ret = sdw_select_row_col(bus, curr_dr_freq);
596 	if (ret < 0) {
597 		dev_err(bus->dev, "%s: could not find frame configuration for bus dr_freq %d\n",
598 			__func__, curr_dr_freq);
599 		return -EINVAL;
600 	}
601 
602 	bus->params.curr_dr_freq = curr_dr_freq;
603 	return 0;
604 }
605 
606 /**
607  * sdw_compute_params: Compute bus, transport and port parameters
608  *
609  * @bus: SDW Bus instance
610  * @stream: Soundwire stream
611  */
612 int sdw_compute_params(struct sdw_bus *bus, struct sdw_stream_runtime *stream)
613 {
614 	int ret;
615 
616 	/* Computes clock frequency, frame shape and frame frequency */
617 	ret = sdw_compute_bus_params(bus);
618 	if (ret < 0)
619 		return ret;
620 
621 	/* Compute transport and port params */
622 	ret = sdw_compute_port_params(bus, stream);
623 	if (ret < 0) {
624 		dev_err(bus->dev, "Compute transport params failed: %d\n", ret);
625 		return ret;
626 	}
627 
628 	return 0;
629 }
630 EXPORT_SYMBOL(sdw_compute_params);
631 
632 MODULE_LICENSE("Dual BSD/GPL");
633 MODULE_DESCRIPTION("SoundWire Generic Bandwidth Allocation");
634