@@ -336,17 +336,99 @@ static bool is_clock_scaling_supported(struct sdw_bus *bus)
336336 return true;
337337}
338338
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+
339415/**
340416 * sdw_compute_bus_params: Compute bus parameters
341417 *
342418 * @bus: SDW Bus instance
343419 */
344420static int sdw_compute_bus_params (struct sdw_bus * bus )
345421{
346- unsigned int curr_dr_freq = 0 ;
347422 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 ;
349430 bool is_gear = false;
431+ int m_lane = 0 ;
350432 u32 * clk_buf ;
351433
352434 if (mstr_prop -> num_clk_gears ) {
@@ -373,11 +455,26 @@ static int sdw_compute_bus_params(struct sdw_bus *bus)
373455 (bus -> params .max_dr_freq >> clk_buf [i ]) :
374456 clk_buf [i ] * SDW_DOUBLE_RATE_FACTOR ;
375457
376- if (curr_dr_freq * (mstr_prop -> default_col - 1 ) <
458+ if (curr_dr_freq * (mstr_prop -> default_col - 1 ) >=
377459 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 );
379470
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+ }
381478
382479 /*
383480 * 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)
391488 __func__ , bus -> params .bandwidth );
392489 return - EINVAL ;
393490 }
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+ }
394517
395518 if (!mstr_prop -> default_frame_rate || !mstr_prop -> default_row )
396519 return - EINVAL ;
0 commit comments