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