diff --git a/drivers/soundwire/cadence_master.c b/drivers/soundwire/cadence_master.c index fa6e2421050dc0..dc76002cd80220 100644 --- a/drivers/soundwire/cadence_master.c +++ b/drivers/soundwire/cadence_master.c @@ -2139,6 +2139,7 @@ EXPORT_SYMBOL(sdw_cdns_bpt_find_bandwidth); int sdw_cdns_bpt_find_buffer_sizes(int command, /* 0: write, 1: read */ int row, int col, unsigned int data_bytes, unsigned int requested_bytes_per_frame, + unsigned int bra_block_alignment, unsigned int *data_per_frame, unsigned int *pdi0_buffer_size, unsigned int *pdi1_buffer_size, unsigned int *num_frames) { @@ -2163,6 +2164,16 @@ int sdw_cdns_bpt_find_buffer_sizes(int command, /* 0: write, 1: read */ if (requested_bytes_per_frame < actual_bpt_bytes) actual_bpt_bytes = requested_bytes_per_frame; + if (bra_block_alignment) { + /* align to a multiple of bra_block_alignment */ + if (actual_bpt_bytes < bra_block_alignment) { + pr_err("requested bytes per frame %u is smaller than block alignment %u\n", + actual_bpt_bytes, bra_block_alignment); + return -EINVAL; + } + actual_bpt_bytes -= (actual_bpt_bytes % bra_block_alignment); + } + *data_per_frame = actual_bpt_bytes; if (data_bytes < actual_bpt_bytes) diff --git a/drivers/soundwire/cadence_master.h b/drivers/soundwire/cadence_master.h index 668f807cff4b23..f4e41a9ab16589 100644 --- a/drivers/soundwire/cadence_master.h +++ b/drivers/soundwire/cadence_master.h @@ -218,6 +218,7 @@ int sdw_cdns_bpt_find_bandwidth(int command, /* 0: write, 1: read */ int sdw_cdns_bpt_find_buffer_sizes(int command, /* 0: write, 1: read */ int row, int col, unsigned int data_bytes, unsigned int requested_bytes_per_frame, + unsigned int bra_block_alignment, unsigned int *data_per_frame, unsigned int *pdi0_buffer_size, unsigned int *pdi1_buffer_size, unsigned int *num_frames); diff --git a/drivers/soundwire/intel_ace2x.c b/drivers/soundwire/intel_ace2x.c index 6cd3a873237501..c7746820461524 100644 --- a/drivers/soundwire/intel_ace2x.c +++ b/drivers/soundwire/intel_ace2x.c @@ -57,6 +57,7 @@ static int intel_ace2x_bpt_open_stream(struct sdw_intel *sdw, struct sdw_slave * struct sdw_port_config *pconfig; unsigned int pdi0_buf_size_pre_frame; unsigned int pdi1_buf_size_pre_frame; + unsigned int max_data_per_frame; unsigned int pdi0_buffer_size_; unsigned int pdi1_buffer_size_; unsigned int pdi0_buffer_size; @@ -168,11 +169,18 @@ static int intel_ace2x_bpt_open_stream(struct sdw_intel *sdw, struct sdw_slave * pdi0_buffer_size = 0; pdi1_buffer_size = 0; num_frames = 0; + + if (slave->prop.bra_max_data_per_frame) + max_data_per_frame = slave->prop.bra_max_data_per_frame; + else + max_data_per_frame = SDW_BRA_MAX_BYTES_PER_FRAME; + /* Add up pdi buffer size and frame numbers of each BPT sections */ for (i = 0; i < msg->sections; i++) { ret = sdw_cdns_bpt_find_buffer_sizes(command, cdns->bus.params.row, cdns->bus.params.col, - msg->sec[i].len, SDW_BPT_MSG_MAX_BYTES, + msg->sec[i].len, max_data_per_frame, + slave->prop.bra_block_alignment, &data_per_frame, &pdi0_buffer_size_, &pdi1_buffer_size_, &num_frames_); if (ret < 0) @@ -196,7 +204,8 @@ static int intel_ace2x_bpt_open_stream(struct sdw_intel *sdw, struct sdw_slave * /* Get buffer size of a full frame */ ret = sdw_cdns_bpt_find_buffer_sizes(command, cdns->bus.params.row, cdns->bus.params.col, - data_per_frame, SDW_BPT_MSG_MAX_BYTES, + data_per_frame, max_data_per_frame, + slave->prop.bra_block_alignment, &data_per_frame, &pdi0_buf_size_pre_frame, &pdi1_buf_size_pre_frame, &fake_num_frames); if (ret < 0) diff --git a/drivers/soundwire/mipi_disco.c b/drivers/soundwire/mipi_disco.c index c69b78cd0b6209..cfccaa33f4380b 100644 --- a/drivers/soundwire/mipi_disco.c +++ b/drivers/soundwire/mipi_disco.c @@ -471,6 +471,12 @@ int sdw_slave_read_prop(struct sdw_slave *slave) device_property_read_u32(dev, "mipi-sdw-sdca-interrupt-register-list", &prop->sdca_interrupt_register_list); + device_property_read_u32(dev, "mipi-sdw-bra-mode-block-alignment", + &prop->bra_block_alignment); + + device_property_read_u32(dev, "mipi-sdw-bra-mode-max-data-per-frame", + &prop->bra_max_data_per_frame); + prop->commit_register_supported = mipi_device_property_read_bool(dev, "mipi-sdw-commit-register-supported"); diff --git a/include/linux/soundwire/sdw.h b/include/linux/soundwire/sdw.h index 0845182f75f9ab..f7fda6921ecdd2 100644 --- a/include/linux/soundwire/sdw.h +++ b/include/linux/soundwire/sdw.h @@ -364,6 +364,10 @@ struct sdw_dpn_prop { * @commit_register_supported: is PCP_Commit register supported * @scp_int1_mask: SCP_INT1_MASK desired settings * @lane_maps: Lane mapping for the slave, only valid if lane_control_support is set + * @bra_block_alignment: If non-zero the length of data in a BRA frame must be + * a multiple of this number of bytes. + * @bra_max_data_per_frame: If non-zero the maximum data payload size (in bytes per + * frame excluding header, CRC, and footer) for this BRA Mode * @clock_reg_supported: the Peripheral implements the clock base and scale * registers introduced with the SoundWire 1.2 specification. SDCA devices * do not need to set this boolean property as the registers are required. @@ -394,6 +398,8 @@ struct sdw_slave_prop { u8 commit_register_supported; u8 scp_int1_mask; u8 lane_maps[SDW_MAX_LANES]; + u32 bra_block_alignment; + u32 bra_max_data_per_frame; bool clock_reg_supported; bool use_domain_irq; }; @@ -838,6 +844,12 @@ struct sdw_defer { */ #define SDW_BPT_MSG_MAX_BYTES (1024 * 1024) +/* + * According to mipi SoundWire DisCo Specification_v2-1, + * this maximum value shall not exceed 470. + */ +#define SDW_BRA_MAX_BYTES_PER_FRAME 470 + struct sdw_bpt_msg; /**