@@ -336,17 +336,99 @@ static bool is_clock_scaling_supported(struct sdw_bus *bus)
336
336
return true;
337
337
}
338
338
339
+ /**
340
+ * is_lane_connected_to_all_peripherals: Check if the given manager lane connects to all peripherals
341
+ * So that all peripherals can use the manager lane.
342
+ *
343
+ * @m_rt: Manager runtime
344
+ * @lane: Lane number
345
+ */
346
+ static bool is_lane_connected_to_all_peripherals (struct sdw_master_runtime * m_rt , unsigned int lane )
347
+ {
348
+ struct sdw_slave_prop * slave_prop ;
349
+ struct sdw_slave_runtime * s_rt ;
350
+ int i ;
351
+
352
+ list_for_each_entry (s_rt , & m_rt -> slave_rt_list , m_rt_node ) {
353
+ slave_prop = & s_rt -> slave -> prop ;
354
+ for (i = 1 ; i < SDW_MAX_LANES ; i ++ ) {
355
+ if (slave_prop -> lane_maps [i ] == lane ) {
356
+ dev_dbg (& s_rt -> slave -> dev ,
357
+ "M lane %d is connected to P lane %d\n" ,
358
+ lane , i );
359
+ break ;
360
+ }
361
+ }
362
+ if (i == SDW_MAX_LANES ) {
363
+ dev_dbg (& s_rt -> slave -> dev , "M lane %d is not connected\n" , lane );
364
+ return false;
365
+ }
366
+ }
367
+ return true;
368
+ }
369
+
370
+ static int get_manager_lane (struct sdw_bus * bus , struct sdw_master_runtime * m_rt ,
371
+ struct sdw_slave_runtime * s_rt , unsigned int curr_dr_freq )
372
+ {
373
+ struct sdw_slave_prop * slave_prop = & s_rt -> slave -> prop ;
374
+ struct sdw_port_runtime * m_p_rt ;
375
+ unsigned int required_bandwidth ;
376
+ int m_lane ;
377
+ int l ;
378
+
379
+ for (l = 1 ; l < SDW_MAX_LANES ; l ++ ) {
380
+ if (!slave_prop -> lane_maps [l ])
381
+ continue ;
382
+
383
+ required_bandwidth = 0 ;
384
+ list_for_each_entry (m_p_rt , & m_rt -> port_list , port_node ) {
385
+ required_bandwidth += m_rt -> stream -> params .rate *
386
+ hweight32 (m_p_rt -> ch_mask ) *
387
+ m_rt -> stream -> params .bps ;
388
+ }
389
+ if (required_bandwidth <=
390
+ curr_dr_freq - bus -> lane_used_bandwidth [l ]) {
391
+ /* Check if m_lane is connected to all Peripherals */
392
+ if (!is_lane_connected_to_all_peripherals (m_rt ,
393
+ slave_prop -> lane_maps [l ])) {
394
+ dev_dbg (bus -> dev ,
395
+ "Not all Peripherals are connected to M lane %d\n" ,
396
+ slave_prop -> lane_maps [l ]);
397
+ continue ;
398
+ }
399
+ m_lane = slave_prop -> lane_maps [l ];
400
+ dev_dbg (& s_rt -> slave -> dev , "M lane %d is used\n" , m_lane );
401
+ bus -> lane_used_bandwidth [l ] += required_bandwidth ;
402
+ /*
403
+ * Use non-zero manager lane, subtract the lane 0
404
+ * bandwidth that is already calculated
405
+ */
406
+ bus -> params .bandwidth -= required_bandwidth ;
407
+ return m_lane ;
408
+ }
409
+ }
410
+
411
+ /* No available multi lane found, only lane 0 can be used */
412
+ return 0 ;
413
+ }
414
+
339
415
/**
340
416
* sdw_compute_bus_params: Compute bus parameters
341
417
*
342
418
* @bus: SDW Bus instance
343
419
*/
344
420
static int sdw_compute_bus_params (struct sdw_bus * bus )
345
421
{
346
- unsigned int curr_dr_freq = 0 ;
347
422
struct sdw_master_prop * mstr_prop = & bus -> prop ;
348
- int i , clk_values , ret ;
423
+ struct sdw_slave_prop * slave_prop ;
424
+ struct sdw_port_runtime * m_p_rt ;
425
+ struct sdw_port_runtime * s_p_rt ;
426
+ struct sdw_master_runtime * m_rt ;
427
+ struct sdw_slave_runtime * s_rt ;
428
+ unsigned int curr_dr_freq = 0 ;
429
+ int i , l , clk_values , ret ;
349
430
bool is_gear = false;
431
+ int m_lane = 0 ;
350
432
u32 * clk_buf ;
351
433
352
434
if (mstr_prop -> num_clk_gears ) {
@@ -373,11 +455,26 @@ static int sdw_compute_bus_params(struct sdw_bus *bus)
373
455
(bus -> params .max_dr_freq >> clk_buf [i ]) :
374
456
clk_buf [i ] * SDW_DOUBLE_RATE_FACTOR ;
375
457
376
- if (curr_dr_freq * (mstr_prop -> default_col - 1 ) <
458
+ if (curr_dr_freq * (mstr_prop -> default_col - 1 ) >=
377
459
bus -> params .bandwidth * mstr_prop -> default_col )
378
- continue ;
460
+ break ;
461
+
462
+ list_for_each_entry (m_rt , & bus -> m_rt_list , bus_node ) {
463
+ /*
464
+ * Get the first s_rt that will be used to find the available lane that
465
+ * can be used. No need to check all Peripherals because we can't use
466
+ * multi-lane if we can't find any available lane for the first Peripheral.
467
+ */
468
+ s_rt = list_first_entry (& m_rt -> slave_rt_list ,
469
+ struct sdw_slave_runtime , m_rt_node );
379
470
380
- break ;
471
+ /*
472
+ * Find the available Manager lane that connected to the first Peripheral.
473
+ */
474
+ m_lane = get_manager_lane (bus , m_rt , s_rt , curr_dr_freq );
475
+ if (m_lane > 0 )
476
+ goto out ;
477
+ }
381
478
382
479
/*
383
480
* TODO: Check all the Slave(s) port(s) audio modes and find
@@ -391,6 +488,32 @@ static int sdw_compute_bus_params(struct sdw_bus *bus)
391
488
__func__ , bus -> params .bandwidth );
392
489
return - EINVAL ;
393
490
}
491
+ out :
492
+ /* multilane can be used */
493
+ if (m_lane > 0 ) {
494
+ /* Set Peripheral lanes */
495
+ list_for_each_entry (s_rt , & m_rt -> slave_rt_list , m_rt_node ) {
496
+ slave_prop = & s_rt -> slave -> prop ;
497
+ for (l = 1 ; l < SDW_MAX_LANES ; l ++ ) {
498
+ if (slave_prop -> lane_maps [l ] == m_lane ) {
499
+ list_for_each_entry (s_p_rt , & s_rt -> port_list , port_node ) {
500
+ s_p_rt -> lane = l ;
501
+ dev_dbg (& s_rt -> slave -> dev ,
502
+ "Set P lane %d for port %d\n" ,
503
+ l , s_p_rt -> num );
504
+ }
505
+ break ;
506
+ }
507
+ }
508
+ }
509
+ /*
510
+ * Set Manager lanes. Configure the last m_rt in bus->m_rt_list only since
511
+ * we don't want to touch other m_rts that are already working.
512
+ */
513
+ list_for_each_entry (m_p_rt , & m_rt -> port_list , port_node ) {
514
+ m_p_rt -> lane = m_lane ;
515
+ }
516
+ }
394
517
395
518
if (!mstr_prop -> default_frame_rate || !mstr_prop -> default_row )
396
519
return - EINVAL ;
0 commit comments