soundwire updates for 6.19
- Support for multiple sections in a BPT stream - Aligning DMA frame with BPT frames - Qualcomm: support for v3.1.0 controllers -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEE+vs47OPLdNbVcHzyfBQHDyUjg0cFAmk8DksACgkQfBQHDyUj g0eK1g/6Awba2J+ME+ZJ/Narqh7qwQRk0/Q9HcnPCxeXGc8peDtuhIxatmqHM+Eg ReoZTIIDA+/ysa1oFrdhi0MBRoZSC1eQpvL9mAQEZ5MxG368flnLncP26rYwyJHT rzBy0Ca/feRMddBbeTqR7OehyDsj4CiBeInRy1aY/UvaFypIgnCagyHWO6TZzYDF gCEVvsGaa7I3qcc1yhi+hP6jvTPMd5FtH2pKKVgL8aNvNgWSv664WX+zz2KY9KSV vcjA5z1rIJ3hohuGx+cqZeQGVS2PBxUyHWjvGlp3wtSVzMRGyb2TDWYsJy8+xKkM 2Raz1uDMJPz+mDsCYlbU2h5I6SJBBhPa7fYJpuFs5KG4GY4p/ndsdh0LRStf5QtE pQmxOiisvbwKgKFlzOLM10zVdRL44VLldwevBt5G7uozpH8FDJ7CTCdSVRAzk2yf poB5zRVh1fewWi8I23T29t+GXXMq59s+Yre5lpvIp5+UO6ZDeSqcNhL6YCT6xJaZ ze7pkVSRY7V3lcLGP2tM19785XZr9SPZxbNojF+X/FlQbhkAp6QvMQe6v67ouoKK K9/9LRMyFYvDq0D19pOdbhCcEUvXWKFgyuUXdfWCpjzkHnpDQZws38FhFhYWeBzm LJKkTlAzI1DPEvpFc5YQf2jx4V4OH5W8lPUzunA9MmXN7MWprJ4= =tDi0 -----END PGP SIGNATURE----- Merge tag 'soundwire-6.19-rc1_updated' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/soundwire Pull soundwire updates from Vinod Koul: - Support for multiple sections in a BPT stream - Align DMA frame with BPT frames - Qualcomm support for v3.1.0 controllers * tag 'soundwire-6.19-rc1_updated' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/soundwire: soundwire: intel_ace2x: handle multi BPT sections soundwire: pass sdw_bpt_section to cdns BPT helpers soundwire: introduce BPT section soundwire: intel_ace2x: add fake frame to BRA read command soundwire: cadence_master: add fake_size parameter to sdw_cdns_prepare_read_dma_buffer ASoC: SOF: Intel: export hda_sdw_bpt_get_buf_size_aligment soundwire: cadence: export sdw_cdns_bpt_find_bandwidth soundwire: cadence_master: set data_per_frame as frame capability soundwire: only compute BPT stream in sdw_compute_dp0_port_params soundwire: cadence_master: make frame index trace more readable soundwire: qcom: adding support for v3.1.0 dt-bindings: soundwire: qcom: Document v3.1.0 version of IP block soundwire: qcom: prepare for v3.x soundwire: qcom: deprecate qcom,din/out-ports dt-bindings: soundwire: qcom: deprecate qcom,din/out-ports soundwire: qcom: remove unused rd_fifo_depth of: base: Add of_property_read_u8_indexmaster
commit
db9c438739
|
|
@ -23,6 +23,7 @@ properties:
|
|||
- qcom,soundwire-v1.6.0
|
||||
- qcom,soundwire-v1.7.0
|
||||
- qcom,soundwire-v2.0.0
|
||||
- qcom,soundwire-v3.1.0
|
||||
- items:
|
||||
- enum:
|
||||
- qcom,soundwire-v2.1.0
|
||||
|
|
@ -73,10 +74,12 @@ properties:
|
|||
qcom,din-ports:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: count of data in ports
|
||||
deprecated: true
|
||||
|
||||
qcom,dout-ports:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: count of data out ports
|
||||
deprecated: true
|
||||
|
||||
qcom,ports-word-length:
|
||||
$ref: /schemas/types.yaml#/definitions/uint8-array
|
||||
|
|
@ -223,8 +226,6 @@ required:
|
|||
- '#sound-dai-cells'
|
||||
- '#address-cells'
|
||||
- '#size-cells'
|
||||
- qcom,dout-ports
|
||||
- qcom,din-ports
|
||||
- qcom,ports-offset1
|
||||
- qcom,ports-offset2
|
||||
|
||||
|
|
@ -257,9 +258,6 @@ examples:
|
|||
clocks = <&lpass_rx_macro>;
|
||||
clock-names = "iface";
|
||||
|
||||
qcom,din-ports = <0>;
|
||||
qcom,dout-ports = <5>;
|
||||
|
||||
resets = <&lpass_audiocc LPASS_AUDIO_SWR_RX_CGCR>;
|
||||
reset-names = "swr_audio_cgcr";
|
||||
|
||||
|
|
|
|||
|
|
@ -147,6 +147,39 @@ static void *of_find_property_value_of_size(const struct device_node *np,
|
|||
return prop->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* of_property_read_u8_index - Find and read a u8 from a multi-value property.
|
||||
*
|
||||
* @np: device node from which the property value is to be read.
|
||||
* @propname: name of the property to be searched.
|
||||
* @index: index of the u8 in the list of values
|
||||
* @out_value: pointer to return value, modified only if no error.
|
||||
*
|
||||
* Search for a property in a device node and read nth 8-bit value from
|
||||
* it.
|
||||
*
|
||||
* Return: 0 on success, -EINVAL if the property does not exist,
|
||||
* -ENODATA if property does not have a value, and -EOVERFLOW if the
|
||||
* property data isn't large enough.
|
||||
*
|
||||
* The out_value is modified only if a valid u8 value can be decoded.
|
||||
*/
|
||||
int of_property_read_u8_index(const struct device_node *np,
|
||||
const char *propname,
|
||||
u32 index, u8 *out_value)
|
||||
{
|
||||
const u8 *val = of_find_property_value_of_size(np, propname,
|
||||
((index + 1) * sizeof(*out_value)),
|
||||
0, NULL);
|
||||
|
||||
if (IS_ERR(val))
|
||||
return PTR_ERR(val);
|
||||
|
||||
*out_value = val[index];
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(of_property_read_u8_index);
|
||||
|
||||
/**
|
||||
* of_property_read_u16_index - Find and read a u16 from a multi-value property.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -2052,8 +2052,14 @@ EXPORT_SYMBOL(sdw_clear_slave_status);
|
|||
|
||||
int sdw_bpt_send_async(struct sdw_bus *bus, struct sdw_slave *slave, struct sdw_bpt_msg *msg)
|
||||
{
|
||||
if (msg->len > SDW_BPT_MSG_MAX_BYTES) {
|
||||
dev_err(bus->dev, "Invalid BPT message length %d\n", msg->len);
|
||||
int len = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < msg->sections; i++)
|
||||
len += msg->sec[i].len;
|
||||
|
||||
if (len > SDW_BPT_MSG_MAX_BYTES) {
|
||||
dev_err(bus->dev, "Invalid BPT message length %d\n", len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -73,21 +73,31 @@ struct sdw_msg {
|
|||
};
|
||||
|
||||
/**
|
||||
* struct sdw_btp_msg - Message structure
|
||||
* struct sdw_btp_section - Message section structure
|
||||
* @addr: Start Register address accessed in the Slave
|
||||
* @len: number of bytes to transfer. More than 64Kb can be transferred
|
||||
* but a practical limit of SDW_BPT_MSG_MAX_BYTES is enforced.
|
||||
* @dev_num: Slave device number
|
||||
* @flags: transfer flags, indicate if xfer is read or write
|
||||
* @buf: message data buffer (filled by host for write, filled
|
||||
* @buf: section data buffer (filled by host for write, filled
|
||||
* by Peripheral hardware for reads)
|
||||
*/
|
||||
struct sdw_bpt_msg {
|
||||
struct sdw_bpt_section {
|
||||
u32 addr;
|
||||
u32 len;
|
||||
u8 *buf;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct sdw_btp_msg - Message structure
|
||||
* @sec: Pointer to array of sections
|
||||
* @sections: Number of sections in the array
|
||||
* @dev_num: Slave device number
|
||||
* @flags: transfer flags, indicate if xfer is read or write
|
||||
*/
|
||||
struct sdw_bpt_msg {
|
||||
struct sdw_bpt_section *sec;
|
||||
int sections;
|
||||
u8 dev_num;
|
||||
u8 flags;
|
||||
u8 *buf;
|
||||
};
|
||||
|
||||
#define SDW_DOUBLE_RATE_FACTOR 2
|
||||
|
|
|
|||
|
|
@ -2094,6 +2094,36 @@ static unsigned int sdw_cdns_read_pdi1_buffer_size(unsigned int actual_data_size
|
|||
return total * 2;
|
||||
}
|
||||
|
||||
int sdw_cdns_bpt_find_bandwidth(int command, /* 0: write, 1: read */
|
||||
int row, int col, int frame_rate,
|
||||
unsigned int *tx_dma_bandwidth,
|
||||
unsigned int *rx_dma_bandwidth)
|
||||
{
|
||||
unsigned int bpt_bits = row * (col - 1);
|
||||
unsigned int bpt_bytes = bpt_bits >> 3;
|
||||
unsigned int pdi0_buffer_size;
|
||||
unsigned int pdi1_buffer_size;
|
||||
unsigned int data_per_frame;
|
||||
|
||||
data_per_frame = sdw_cdns_bra_actual_data_size(bpt_bytes);
|
||||
if (!data_per_frame)
|
||||
return -EINVAL;
|
||||
|
||||
if (command == 0) {
|
||||
pdi0_buffer_size = sdw_cdns_write_pdi0_buffer_size(data_per_frame);
|
||||
pdi1_buffer_size = SDW_CDNS_WRITE_PDI1_BUFFER_SIZE;
|
||||
} else {
|
||||
pdi0_buffer_size = SDW_CDNS_READ_PDI0_BUFFER_SIZE;
|
||||
pdi1_buffer_size = sdw_cdns_read_pdi1_buffer_size(data_per_frame);
|
||||
}
|
||||
|
||||
*tx_dma_bandwidth = pdi0_buffer_size * 8 * frame_rate;
|
||||
*rx_dma_bandwidth = pdi1_buffer_size * 8 * frame_rate;
|
||||
|
||||
return 0;
|
||||
}
|
||||
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,
|
||||
|
|
@ -2114,9 +2144,6 @@ int sdw_cdns_bpt_find_buffer_sizes(int command, /* 0: write, 1: read */
|
|||
if (!actual_bpt_bytes)
|
||||
return -EINVAL;
|
||||
|
||||
if (data_bytes < actual_bpt_bytes)
|
||||
actual_bpt_bytes = data_bytes;
|
||||
|
||||
/*
|
||||
* the caller may want to set the number of bytes per frame,
|
||||
* allow when possible
|
||||
|
|
@ -2126,6 +2153,9 @@ int sdw_cdns_bpt_find_buffer_sizes(int command, /* 0: write, 1: read */
|
|||
|
||||
*data_per_frame = actual_bpt_bytes;
|
||||
|
||||
if (data_bytes < actual_bpt_bytes)
|
||||
actual_bpt_bytes = data_bytes;
|
||||
|
||||
if (command == 0) {
|
||||
/*
|
||||
* for writes we need to send all the data_bytes per frame,
|
||||
|
|
@ -2294,17 +2324,20 @@ static int sdw_cdns_prepare_read_pd0_buffer(u8 *header, unsigned int header_size
|
|||
|
||||
#define CDNS_BPT_ROLLING_COUNTER_START 1
|
||||
|
||||
int sdw_cdns_prepare_write_dma_buffer(u8 dev_num, u32 start_register, u8 *data, int data_size,
|
||||
int data_per_frame, u8 *dma_buffer, int dma_buffer_size,
|
||||
int *dma_buffer_total_bytes)
|
||||
int sdw_cdns_prepare_write_dma_buffer(u8 dev_num, struct sdw_bpt_section *sec, int num_sec,
|
||||
int data_per_frame, u8 *dma_buffer,
|
||||
int dma_buffer_size, int *dma_buffer_total_bytes)
|
||||
{
|
||||
int total_dma_data_written = 0;
|
||||
u8 *p_dma_buffer = dma_buffer;
|
||||
u8 header[SDW_CDNS_BRA_HDR];
|
||||
unsigned int start_register;
|
||||
unsigned int section_size;
|
||||
int dma_data_written;
|
||||
u8 *p_data = data;
|
||||
u8 *p_data;
|
||||
u8 counter;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
counter = CDNS_BPT_ROLLING_COUNTER_START;
|
||||
|
||||
|
|
@ -2312,7 +2345,12 @@ int sdw_cdns_prepare_write_dma_buffer(u8 dev_num, u32 start_register, u8 *data,
|
|||
header[0] |= GENMASK(7, 6); /* header is active */
|
||||
header[0] |= (dev_num << 2);
|
||||
|
||||
while (data_size >= data_per_frame) {
|
||||
for (i = 0; i < num_sec; i++) {
|
||||
start_register = sec[i].addr;
|
||||
section_size = sec[i].len;
|
||||
p_data = sec[i].buf;
|
||||
|
||||
while (section_size >= data_per_frame) {
|
||||
header[1] = data_per_frame;
|
||||
header[2] = start_register >> 24 & 0xFF;
|
||||
header[3] = start_register >> 16 & 0xFF;
|
||||
|
|
@ -2329,7 +2367,7 @@ int sdw_cdns_prepare_write_dma_buffer(u8 dev_num, u32 start_register, u8 *data,
|
|||
counter++;
|
||||
|
||||
p_data += data_per_frame;
|
||||
data_size -= data_per_frame;
|
||||
section_size -= data_per_frame;
|
||||
|
||||
p_dma_buffer += dma_data_written;
|
||||
dma_buffer_size -= dma_data_written;
|
||||
|
|
@ -2338,22 +2376,27 @@ int sdw_cdns_prepare_write_dma_buffer(u8 dev_num, u32 start_register, u8 *data,
|
|||
start_register += data_per_frame;
|
||||
}
|
||||
|
||||
if (data_size) {
|
||||
header[1] = data_size;
|
||||
if (section_size) {
|
||||
header[1] = section_size;
|
||||
header[2] = start_register >> 24 & 0xFF;
|
||||
header[3] = start_register >> 16 & 0xFF;
|
||||
header[4] = start_register >> 8 & 0xFF;
|
||||
header[5] = start_register >> 0 & 0xFF;
|
||||
|
||||
ret = sdw_cdns_prepare_write_pd0_buffer(header, SDW_CDNS_BRA_HDR,
|
||||
p_data, data_size,
|
||||
p_data, section_size,
|
||||
p_dma_buffer, dma_buffer_size,
|
||||
&dma_data_written, counter);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
counter++;
|
||||
|
||||
p_dma_buffer += dma_data_written;
|
||||
dma_buffer_size -= dma_data_written;
|
||||
total_dma_data_written += dma_data_written;
|
||||
}
|
||||
}
|
||||
|
||||
*dma_buffer_total_bytes = total_dma_data_written;
|
||||
|
||||
|
|
@ -2361,16 +2404,19 @@ int sdw_cdns_prepare_write_dma_buffer(u8 dev_num, u32 start_register, u8 *data,
|
|||
}
|
||||
EXPORT_SYMBOL(sdw_cdns_prepare_write_dma_buffer);
|
||||
|
||||
int sdw_cdns_prepare_read_dma_buffer(u8 dev_num, u32 start_register, int data_size,
|
||||
int sdw_cdns_prepare_read_dma_buffer(u8 dev_num, struct sdw_bpt_section *sec, int num_sec,
|
||||
int data_per_frame, u8 *dma_buffer, int dma_buffer_size,
|
||||
int *dma_buffer_total_bytes)
|
||||
int *dma_buffer_total_bytes, unsigned int fake_size)
|
||||
{
|
||||
int total_dma_data_written = 0;
|
||||
u8 *p_dma_buffer = dma_buffer;
|
||||
u8 header[SDW_CDNS_BRA_HDR];
|
||||
unsigned int start_register;
|
||||
unsigned int data_size;
|
||||
int dma_data_written;
|
||||
u8 counter;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
counter = CDNS_BPT_ROLLING_COUNTER_START;
|
||||
|
||||
|
|
@ -2378,6 +2424,9 @@ int sdw_cdns_prepare_read_dma_buffer(u8 dev_num, u32 start_register, int data_si
|
|||
header[0] |= GENMASK(7, 6); /* header is active */
|
||||
header[0] |= (dev_num << 2);
|
||||
|
||||
for (i = 0; i < num_sec; i++) {
|
||||
start_register = sec[i].addr;
|
||||
data_size = sec[i].len;
|
||||
while (data_size >= data_per_frame) {
|
||||
header[1] = data_per_frame;
|
||||
header[2] = start_register >> 24 & 0xFF;
|
||||
|
|
@ -2385,9 +2434,9 @@ int sdw_cdns_prepare_read_dma_buffer(u8 dev_num, u32 start_register, int data_si
|
|||
header[4] = start_register >> 8 & 0xFF;
|
||||
header[5] = start_register >> 0 & 0xFF;
|
||||
|
||||
ret = sdw_cdns_prepare_read_pd0_buffer(header, SDW_CDNS_BRA_HDR, p_dma_buffer,
|
||||
dma_buffer_size, &dma_data_written,
|
||||
counter);
|
||||
ret = sdw_cdns_prepare_read_pd0_buffer(header, SDW_CDNS_BRA_HDR,
|
||||
p_dma_buffer, dma_buffer_size,
|
||||
&dma_data_written, counter);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
|
@ -2409,12 +2458,50 @@ int sdw_cdns_prepare_read_dma_buffer(u8 dev_num, u32 start_register, int data_si
|
|||
header[4] = start_register >> 8 & 0xFF;
|
||||
header[5] = start_register >> 0 & 0xFF;
|
||||
|
||||
ret = sdw_cdns_prepare_read_pd0_buffer(header, SDW_CDNS_BRA_HDR,
|
||||
p_dma_buffer, dma_buffer_size,
|
||||
&dma_data_written, counter);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
counter++;
|
||||
|
||||
p_dma_buffer += dma_data_written;
|
||||
dma_buffer_size -= dma_data_written;
|
||||
total_dma_data_written += dma_data_written;
|
||||
}
|
||||
}
|
||||
|
||||
/* Add fake frame */
|
||||
header[0] &= ~GENMASK(7, 6); /* Set inactive flag in BPT/BRA frame heade */
|
||||
while (fake_size >= data_per_frame) {
|
||||
header[1] = data_per_frame;
|
||||
ret = sdw_cdns_prepare_read_pd0_buffer(header, SDW_CDNS_BRA_HDR, p_dma_buffer,
|
||||
dma_buffer_size, &dma_data_written,
|
||||
counter);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
counter++;
|
||||
|
||||
fake_size -= data_per_frame;
|
||||
p_dma_buffer += dma_data_written;
|
||||
dma_buffer_size -= dma_data_written;
|
||||
total_dma_data_written += dma_data_written;
|
||||
}
|
||||
|
||||
if (fake_size) {
|
||||
header[1] = fake_size;
|
||||
ret = sdw_cdns_prepare_read_pd0_buffer(header, SDW_CDNS_BRA_HDR, p_dma_buffer,
|
||||
dma_buffer_size, &dma_data_written,
|
||||
counter);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
counter++;
|
||||
|
||||
p_dma_buffer += dma_data_written;
|
||||
dma_buffer_size -= dma_data_written;
|
||||
total_dma_data_written += dma_data_written;
|
||||
}
|
||||
|
||||
|
|
@ -2495,14 +2582,14 @@ int sdw_cdns_check_write_response(struct device *dev, u8 *dma_buffer,
|
|||
ret = check_frame_start(header, counter);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "%s: bad frame %d/%d start header %x\n",
|
||||
__func__, i, num_frames, header);
|
||||
__func__, i + 1, num_frames, header);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = check_frame_end(footer);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "%s: bad frame %d/%d end footer %x\n",
|
||||
__func__, i, num_frames, footer);
|
||||
__func__, i + 1, num_frames, footer);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -2549,9 +2636,12 @@ static u8 extract_read_data(u32 *data, int num_bytes, u8 *buffer)
|
|||
}
|
||||
|
||||
int sdw_cdns_check_read_response(struct device *dev, u8 *dma_buffer, int dma_buffer_size,
|
||||
u8 *buffer, int buffer_size, int num_frames, int data_per_frame)
|
||||
struct sdw_bpt_section *sec, int num_sec, int num_frames,
|
||||
int data_per_frame)
|
||||
{
|
||||
int total_num_bytes = 0;
|
||||
int buffer_size = 0;
|
||||
int sec_index;
|
||||
u32 *p_data;
|
||||
u8 *p_buf;
|
||||
int counter;
|
||||
|
|
@ -2565,7 +2655,10 @@ int sdw_cdns_check_read_response(struct device *dev, u8 *dma_buffer, int dma_buf
|
|||
|
||||
counter = CDNS_BPT_ROLLING_COUNTER_START;
|
||||
p_data = (u32 *)dma_buffer;
|
||||
p_buf = buffer;
|
||||
|
||||
sec_index = 0;
|
||||
p_buf = sec[sec_index].buf;
|
||||
buffer_size = sec[sec_index].len;
|
||||
|
||||
for (i = 0; i < num_frames; i++) {
|
||||
header = *p_data++;
|
||||
|
|
@ -2573,7 +2666,7 @@ int sdw_cdns_check_read_response(struct device *dev, u8 *dma_buffer, int dma_buf
|
|||
ret = check_frame_start(header, counter);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "%s: bad frame %d/%d start header %x\n",
|
||||
__func__, i, num_frames, header);
|
||||
__func__, i + 1, num_frames, header);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -2588,7 +2681,7 @@ int sdw_cdns_check_read_response(struct device *dev, u8 *dma_buffer, int dma_buf
|
|||
|
||||
if (crc != expected_crc) {
|
||||
dev_err(dev, "%s: bad frame %d/%d crc %#x expected %#x\n",
|
||||
__func__, i, num_frames, crc, expected_crc);
|
||||
__func__, i + 1, num_frames, crc, expected_crc);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
|
|
@ -2599,12 +2692,24 @@ int sdw_cdns_check_read_response(struct device *dev, u8 *dma_buffer, int dma_buf
|
|||
ret = check_frame_end(footer);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "%s: bad frame %d/%d end footer %x\n",
|
||||
__func__, i, num_frames, footer);
|
||||
__func__, i + 1, num_frames, footer);
|
||||
return ret;
|
||||
}
|
||||
|
||||
counter++;
|
||||
counter &= GENMASK(3, 0);
|
||||
|
||||
if (buffer_size == total_num_bytes && (i + 1) < num_frames) {
|
||||
sec_index++;
|
||||
if (sec_index >= num_sec) {
|
||||
dev_err(dev, "%s: incorrect section index %d i %d\n",
|
||||
__func__, sec_index, i);
|
||||
return -EINVAL;
|
||||
}
|
||||
p_buf = sec[sec_index].buf;
|
||||
buffer_size = sec[sec_index].len;
|
||||
total_num_bytes = 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
|
||||
/* Copyright(c) 2015-17 Intel Corporation. */
|
||||
#include <sound/soc.h>
|
||||
#include "bus.h"
|
||||
|
||||
#ifndef __SDW_CADENCE_H
|
||||
#define __SDW_CADENCE_H
|
||||
|
|
@ -209,23 +210,29 @@ void sdw_cdns_config_update(struct sdw_cdns *cdns);
|
|||
int sdw_cdns_config_update_set_wait(struct sdw_cdns *cdns);
|
||||
|
||||
/* SoundWire BPT/BRA helpers to format data */
|
||||
int sdw_cdns_bpt_find_bandwidth(int command, /* 0: write, 1: read */
|
||||
int row, int col, int frame_rate,
|
||||
unsigned int *tx_dma_bandwidth,
|
||||
unsigned int *rx_dma_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 *data_per_frame, unsigned int *pdi0_buffer_size,
|
||||
unsigned int *pdi1_buffer_size, unsigned int *num_frames);
|
||||
|
||||
int sdw_cdns_prepare_write_dma_buffer(u8 dev_num, u32 start_register, u8 *data, int data_size,
|
||||
int data_per_frame, u8 *dma_buffer, int dma_buffer_size,
|
||||
int *dma_buffer_total_bytes);
|
||||
int sdw_cdns_prepare_write_dma_buffer(u8 dev_num, struct sdw_bpt_section *sec, int num_sec,
|
||||
int data_per_frame, u8 *dma_buffer,
|
||||
int dma_buffer_size, int *dma_buffer_total_bytes);
|
||||
|
||||
int sdw_cdns_prepare_read_dma_buffer(u8 dev_num, u32 start_register, int data_size,
|
||||
int sdw_cdns_prepare_read_dma_buffer(u8 dev_num, struct sdw_bpt_section *sec, int num_sec,
|
||||
int data_per_frame, u8 *dma_buffer, int dma_buffer_size,
|
||||
int *dma_buffer_total_bytes);
|
||||
int *dma_buffer_total_bytes, unsigned int fake_size);
|
||||
|
||||
int sdw_cdns_check_write_response(struct device *dev, u8 *dma_buffer,
|
||||
int dma_buffer_size, int num_frames);
|
||||
|
||||
int sdw_cdns_check_read_response(struct device *dev, u8 *dma_buffer, int dma_buffer_size,
|
||||
u8 *buffer, int buffer_size, int num_frames, int data_per_frame);
|
||||
struct sdw_bpt_section *sec, int num_sec, int num_frames,
|
||||
int data_per_frame);
|
||||
#endif /* __SDW_CADENCE_H */
|
||||
|
|
|
|||
|
|
@ -222,15 +222,23 @@ DEFINE_DEBUGFS_ATTRIBUTE(set_num_bytes_fops, NULL,
|
|||
static int do_bpt_sequence(struct sdw_slave *slave, bool write, u8 *buffer)
|
||||
{
|
||||
struct sdw_bpt_msg msg = {0};
|
||||
struct sdw_bpt_section *sec;
|
||||
|
||||
msg.addr = start_addr;
|
||||
msg.len = num_bytes;
|
||||
sec = kcalloc(1, sizeof(*sec), GFP_KERNEL);
|
||||
if (!sec)
|
||||
return -ENOMEM;
|
||||
msg.sections = 1;
|
||||
|
||||
sec[0].addr = start_addr;
|
||||
sec[0].len = num_bytes;
|
||||
|
||||
msg.sec = sec;
|
||||
msg.dev_num = slave->dev_num;
|
||||
if (write)
|
||||
msg.flags = SDW_MSG_FLAG_WRITE;
|
||||
else
|
||||
msg.flags = SDW_MSG_FLAG_READ;
|
||||
msg.buf = buffer;
|
||||
sec[0].buf = buffer;
|
||||
|
||||
return sdw_bpt_send_sync(slave->bus, slave, &msg);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -124,6 +124,9 @@ static void sdw_compute_dp0_port_params(struct sdw_bus *bus)
|
|||
struct sdw_master_runtime *m_rt;
|
||||
|
||||
list_for_each_entry(m_rt, &bus->m_rt_list, bus_node) {
|
||||
/* DP0 is for BPT only */
|
||||
if (m_rt->stream->type != SDW_STREAM_BPT)
|
||||
continue;
|
||||
sdw_compute_dp0_master_ports(m_rt);
|
||||
sdw_compute_dp0_slave_ports(m_rt);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,6 +44,8 @@ static int sdw_slave_bpt_stream_add(struct sdw_slave *slave, struct sdw_stream_r
|
|||
return ret;
|
||||
}
|
||||
|
||||
#define READ_PDI1_MIN_SIZE 12
|
||||
|
||||
static int intel_ace2x_bpt_open_stream(struct sdw_intel *sdw, struct sdw_slave *slave,
|
||||
struct sdw_bpt_msg *msg)
|
||||
{
|
||||
|
|
@ -53,19 +55,31 @@ static int intel_ace2x_bpt_open_stream(struct sdw_intel *sdw, struct sdw_slave *
|
|||
struct sdw_stream_runtime *stream;
|
||||
struct sdw_stream_config sconfig;
|
||||
struct sdw_port_config *pconfig;
|
||||
unsigned int pdi0_buf_size_pre_frame;
|
||||
unsigned int pdi1_buf_size_pre_frame;
|
||||
unsigned int pdi0_buffer_size_;
|
||||
unsigned int pdi1_buffer_size_;
|
||||
unsigned int pdi0_buffer_size;
|
||||
unsigned int tx_dma_bandwidth;
|
||||
unsigned int pdi1_buffer_size;
|
||||
unsigned int rx_dma_bandwidth;
|
||||
unsigned int fake_num_frames;
|
||||
unsigned int data_per_frame;
|
||||
unsigned int tx_total_bytes;
|
||||
struct sdw_cdns_pdi *pdi0;
|
||||
struct sdw_cdns_pdi *pdi1;
|
||||
unsigned int rx_alignment;
|
||||
unsigned int tx_alignment;
|
||||
unsigned int num_frames_;
|
||||
unsigned int num_frames;
|
||||
unsigned int fake_size;
|
||||
unsigned int tx_pad;
|
||||
unsigned int rx_pad;
|
||||
int command;
|
||||
int ret1;
|
||||
int ret;
|
||||
int dir;
|
||||
int len;
|
||||
int i;
|
||||
|
||||
stream = sdw_alloc_stream("BPT", SDW_STREAM_BPT);
|
||||
|
|
@ -138,23 +152,77 @@ static int intel_ace2x_bpt_open_stream(struct sdw_intel *sdw, struct sdw_slave *
|
|||
|
||||
command = (msg->flags & SDW_MSG_FLAG_WRITE) ? 0 : 1;
|
||||
|
||||
ret = sdw_cdns_bpt_find_buffer_sizes(command, cdns->bus.params.row, cdns->bus.params.col,
|
||||
msg->len, SDW_BPT_MSG_MAX_BYTES, &data_per_frame,
|
||||
&pdi0_buffer_size, &pdi1_buffer_size, &num_frames);
|
||||
ret = sdw_cdns_bpt_find_bandwidth(command, cdns->bus.params.row,
|
||||
cdns->bus.params.col,
|
||||
prop->default_frame_rate,
|
||||
&tx_dma_bandwidth, &rx_dma_bandwidth);
|
||||
if (ret < 0)
|
||||
goto deprepare_stream;
|
||||
|
||||
len = 0;
|
||||
pdi0_buffer_size = 0;
|
||||
pdi1_buffer_size = 0;
|
||||
num_frames = 0;
|
||||
/* 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,
|
||||
&data_per_frame, &pdi0_buffer_size_,
|
||||
&pdi1_buffer_size_, &num_frames_);
|
||||
if (ret < 0)
|
||||
goto deprepare_stream;
|
||||
|
||||
len += msg->sec[i].len;
|
||||
pdi0_buffer_size += pdi0_buffer_size_;
|
||||
pdi1_buffer_size += pdi1_buffer_size_;
|
||||
num_frames += num_frames_;
|
||||
}
|
||||
|
||||
sdw->bpt_ctx.pdi0_buffer_size = pdi0_buffer_size;
|
||||
sdw->bpt_ctx.pdi1_buffer_size = pdi1_buffer_size;
|
||||
sdw->bpt_ctx.num_frames = num_frames;
|
||||
sdw->bpt_ctx.data_per_frame = data_per_frame;
|
||||
tx_dma_bandwidth = div_u64((u64)pdi0_buffer_size * 8 * (u64)prop->default_frame_rate,
|
||||
num_frames);
|
||||
rx_dma_bandwidth = div_u64((u64)pdi1_buffer_size * 8 * (u64)prop->default_frame_rate,
|
||||
num_frames);
|
||||
|
||||
rx_alignment = hda_sdw_bpt_get_buf_size_alignment(rx_dma_bandwidth);
|
||||
tx_alignment = hda_sdw_bpt_get_buf_size_alignment(tx_dma_bandwidth);
|
||||
|
||||
if (command) { /* read */
|
||||
/* 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, &pdi0_buf_size_pre_frame,
|
||||
&pdi1_buf_size_pre_frame, &fake_num_frames);
|
||||
if (ret < 0)
|
||||
goto deprepare_stream;
|
||||
|
||||
/* find fake pdi1 buffer size */
|
||||
rx_pad = rx_alignment - (pdi1_buffer_size % rx_alignment);
|
||||
while (rx_pad <= READ_PDI1_MIN_SIZE)
|
||||
rx_pad += rx_alignment;
|
||||
|
||||
pdi1_buffer_size += rx_pad;
|
||||
/* It is fine if we request more than enough byte to read */
|
||||
fake_num_frames = DIV_ROUND_UP(rx_pad, pdi1_buf_size_pre_frame);
|
||||
fake_size = fake_num_frames * data_per_frame;
|
||||
|
||||
/* find fake pdi0 buffer size */
|
||||
pdi0_buffer_size += (fake_num_frames * pdi0_buf_size_pre_frame);
|
||||
tx_pad = tx_alignment - (pdi0_buffer_size % tx_alignment);
|
||||
pdi0_buffer_size += tx_pad;
|
||||
} else { /* write */
|
||||
/*
|
||||
* For the write command, the rx data block is 4, and the rx buffer size of a frame
|
||||
* is 8. So the rx buffer size (pdi0_buffer_size) is always a multiple of rx
|
||||
* alignment.
|
||||
*/
|
||||
tx_pad = tx_alignment - (pdi0_buffer_size % tx_alignment);
|
||||
pdi0_buffer_size += tx_pad;
|
||||
}
|
||||
|
||||
dev_dbg(cdns->dev, "Message len %d transferred in %d frames (%d per frame)\n",
|
||||
msg->len, num_frames, data_per_frame);
|
||||
len, num_frames, data_per_frame);
|
||||
dev_dbg(cdns->dev, "sizes pdi0 %d pdi1 %d tx_bandwidth %d rx_bandwidth %d\n",
|
||||
pdi0_buffer_size, pdi1_buffer_size, tx_dma_bandwidth, rx_dma_bandwidth);
|
||||
|
||||
|
|
@ -169,15 +237,16 @@ static int intel_ace2x_bpt_open_stream(struct sdw_intel *sdw, struct sdw_slave *
|
|||
}
|
||||
|
||||
if (!command) {
|
||||
ret = sdw_cdns_prepare_write_dma_buffer(msg->dev_num, msg->addr, msg->buf,
|
||||
msg->len, data_per_frame,
|
||||
sdw->bpt_ctx.dmab_tx_bdl.area,
|
||||
pdi0_buffer_size, &tx_total_bytes);
|
||||
} else {
|
||||
ret = sdw_cdns_prepare_read_dma_buffer(msg->dev_num, msg->addr, msg->len,
|
||||
ret = sdw_cdns_prepare_write_dma_buffer(msg->dev_num, msg->sec, msg->sections,
|
||||
data_per_frame,
|
||||
sdw->bpt_ctx.dmab_tx_bdl.area,
|
||||
pdi0_buffer_size, &tx_total_bytes);
|
||||
} else {
|
||||
ret = sdw_cdns_prepare_read_dma_buffer(msg->dev_num, msg->sec, msg->sections,
|
||||
data_per_frame,
|
||||
sdw->bpt_ctx.dmab_tx_bdl.area,
|
||||
pdi0_buffer_size, &tx_total_bytes,
|
||||
fake_size);
|
||||
}
|
||||
|
||||
if (!ret)
|
||||
|
|
@ -252,11 +321,16 @@ static int intel_ace2x_bpt_send_async(struct sdw_intel *sdw, struct sdw_slave *s
|
|||
struct sdw_bpt_msg *msg)
|
||||
{
|
||||
struct sdw_cdns *cdns = &sdw->cdns;
|
||||
int len = 0;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
if (msg->len < INTEL_BPT_MSG_BYTE_MIN) {
|
||||
for (i = 0; i < msg->sections; i++)
|
||||
len += msg->sec[i].len;
|
||||
|
||||
if (len < INTEL_BPT_MSG_BYTE_MIN) {
|
||||
dev_err(cdns->dev, "BPT message length %d is less than the minimum bytes %d\n",
|
||||
msg->len, INTEL_BPT_MSG_BYTE_MIN);
|
||||
len, INTEL_BPT_MSG_BYTE_MIN);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
@ -316,7 +390,7 @@ static int intel_ace2x_bpt_wait(struct sdw_intel *sdw, struct sdw_slave *slave,
|
|||
} else {
|
||||
ret = sdw_cdns_check_read_response(cdns->dev, sdw->bpt_ctx.dmab_rx_bdl.area,
|
||||
sdw->bpt_ctx.pdi1_buffer_size,
|
||||
msg->buf, msg->len, sdw->bpt_ctx.num_frames,
|
||||
msg->sec, msg->sections, sdw->bpt_ctx.num_frames,
|
||||
sdw->bpt_ctx.data_per_frame);
|
||||
if (ret < 0)
|
||||
dev_err(cdns->dev, "%s: BPT Read failed %d\n", __func__, ret);
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
#define SWRM_VERSION_1_5_1 0x01050001
|
||||
#define SWRM_VERSION_1_7_0 0x01070000
|
||||
#define SWRM_VERSION_2_0_0 0x02000000
|
||||
#define SWRM_VERSION_3_1_0 0x03010000
|
||||
#define SWRM_COMP_HW_VERSION 0x00
|
||||
#define SWRM_COMP_CFG_ADDR 0x04
|
||||
#define SWRM_COMP_CFG_IRQ_LEVEL_OR_PULSE_MSK BIT(1)
|
||||
|
|
@ -40,6 +41,9 @@
|
|||
#define SWRM_COMP_PARAMS_RD_FIFO_DEPTH GENMASK(19, 15)
|
||||
#define SWRM_COMP_PARAMS_DOUT_PORTS_MASK GENMASK(4, 0)
|
||||
#define SWRM_COMP_PARAMS_DIN_PORTS_MASK GENMASK(9, 5)
|
||||
#define SWRM_V3_COMP_PARAMS_WR_FIFO_DEPTH GENMASK(17, 10)
|
||||
#define SWRM_V3_COMP_PARAMS_RD_FIFO_DEPTH GENMASK(23, 18)
|
||||
|
||||
#define SWRM_COMP_MASTER_ID 0x104
|
||||
#define SWRM_V1_3_INTERRUPT_STATUS 0x200
|
||||
#define SWRM_V2_0_INTERRUPT_STATUS 0x5000
|
||||
|
|
@ -99,14 +103,15 @@
|
|||
#define SWRM_MCP_SLV_STATUS 0x1090
|
||||
#define SWRM_MCP_SLV_STATUS_MASK GENMASK(1, 0)
|
||||
#define SWRM_MCP_SLV_STATUS_SZ 2
|
||||
#define SWRM_DP_PORT_CTRL_BANK(n, m) (0x1124 + 0x100 * (n - 1) + 0x40 * m)
|
||||
#define SWRM_DP_PORT_CTRL_2_BANK(n, m) (0x1128 + 0x100 * (n - 1) + 0x40 * m)
|
||||
#define SWRM_DP_BLOCK_CTRL_1(n) (0x112C + 0x100 * (n - 1))
|
||||
#define SWRM_DP_BLOCK_CTRL2_BANK(n, m) (0x1130 + 0x100 * (n - 1) + 0x40 * m)
|
||||
#define SWRM_DP_PORT_HCTRL_BANK(n, m) (0x1134 + 0x100 * (n - 1) + 0x40 * m)
|
||||
#define SWRM_DP_BLOCK_CTRL3_BANK(n, m) (0x1138 + 0x100 * (n - 1) + 0x40 * m)
|
||||
#define SWRM_DP_SAMPLECTRL2_BANK(n, m) (0x113C + 0x100 * (n - 1) + 0x40 * m)
|
||||
#define SWRM_DIN_DPn_PCM_PORT_CTRL(n) (0x1054 + 0x100 * (n - 1))
|
||||
|
||||
#define SWRM_DPn_PORT_CTRL_BANK(offset, n, m) (offset + 0x100 * (n - 1) + 0x40 * m)
|
||||
#define SWRM_DPn_PORT_CTRL_2_BANK(offset, n, m) (offset + 0x100 * (n - 1) + 0x40 * m)
|
||||
#define SWRM_DPn_BLOCK_CTRL_1(offset, n) (offset + 0x100 * (n - 1))
|
||||
#define SWRM_DPn_BLOCK_CTRL2_BANK(offset, n, m) (offset + 0x100 * (n - 1) + 0x40 * m)
|
||||
#define SWRM_DPn_PORT_HCTRL_BANK(offset, n, m) (offset + 0x100 * (n - 1) + 0x40 * m)
|
||||
#define SWRM_DPn_BLOCK_CTRL3_BANK(offset, n, m) (offset + 0x100 * (n - 1) + 0x40 * m)
|
||||
#define SWRM_DPn_SAMPLECTRL2_BANK(offset, n, m) (offset + 0x100 * (n - 1) + 0x40 * m)
|
||||
|
||||
#define SWR_V1_3_MSTR_MAX_REG_ADDR 0x1740
|
||||
#define SWR_V2_0_MSTR_MAX_REG_ADDR 0x50ac
|
||||
|
||||
|
|
@ -128,7 +133,6 @@
|
|||
#define MAX_FREQ_NUM 1
|
||||
#define TIMEOUT_MS 100
|
||||
#define QCOM_SWRM_MAX_RD_LEN 0x1
|
||||
#define QCOM_SDW_MAX_PORTS 14
|
||||
#define DEFAULT_CLK_FREQ 9600000
|
||||
#define SWRM_MAX_DAIS 0xF
|
||||
#define SWR_INVALID_PARAM 0xFF
|
||||
|
|
@ -172,6 +176,13 @@ enum {
|
|||
SWRM_REG_CMD_FIFO_RD_CMD,
|
||||
SWRM_REG_CMD_FIFO_STATUS,
|
||||
SWRM_REG_CMD_FIFO_RD_FIFO_ADDR,
|
||||
SWRM_OFFSET_DP_PORT_CTRL_BANK,
|
||||
SWRM_OFFSET_DP_PORT_CTRL_2_BANK,
|
||||
SWRM_OFFSET_DP_BLOCK_CTRL_1,
|
||||
SWRM_OFFSET_DP_BLOCK_CTRL2_BANK,
|
||||
SWRM_OFFSET_DP_PORT_HCTRL_BANK,
|
||||
SWRM_OFFSET_DP_BLOCK_CTRL3_BANK,
|
||||
SWRM_OFFSET_DP_SAMPLECTRL2_BANK,
|
||||
};
|
||||
|
||||
struct qcom_swrm_ctrl {
|
||||
|
|
@ -195,6 +206,7 @@ struct qcom_swrm_ctrl {
|
|||
int wake_irq;
|
||||
int num_din_ports;
|
||||
int num_dout_ports;
|
||||
int nports;
|
||||
int cols_index;
|
||||
int rows_index;
|
||||
unsigned long port_mask;
|
||||
|
|
@ -202,14 +214,13 @@ struct qcom_swrm_ctrl {
|
|||
u8 rcmd_id;
|
||||
u8 wcmd_id;
|
||||
/* Port numbers are 1 - 14 */
|
||||
struct qcom_swrm_port_config pconfig[QCOM_SDW_MAX_PORTS + 1];
|
||||
struct qcom_swrm_port_config *pconfig;
|
||||
struct sdw_stream_runtime *sruntime[SWRM_MAX_DAIS];
|
||||
enum sdw_slave_status status[SDW_MAX_DEVICES + 1];
|
||||
int (*reg_read)(struct qcom_swrm_ctrl *ctrl, int reg, u32 *val);
|
||||
int (*reg_write)(struct qcom_swrm_ctrl *ctrl, int reg, int val);
|
||||
u32 slave_status;
|
||||
u32 wr_fifo_depth;
|
||||
u32 rd_fifo_depth;
|
||||
bool clock_stop_not_supported;
|
||||
};
|
||||
|
||||
|
|
@ -231,6 +242,13 @@ static const unsigned int swrm_v1_3_reg_layout[] = {
|
|||
[SWRM_REG_CMD_FIFO_RD_CMD] = SWRM_V1_3_CMD_FIFO_RD_CMD,
|
||||
[SWRM_REG_CMD_FIFO_STATUS] = SWRM_V1_3_CMD_FIFO_STATUS,
|
||||
[SWRM_REG_CMD_FIFO_RD_FIFO_ADDR] = SWRM_V1_3_CMD_FIFO_RD_FIFO_ADDR,
|
||||
[SWRM_OFFSET_DP_PORT_CTRL_BANK] = 0x1124,
|
||||
[SWRM_OFFSET_DP_PORT_CTRL_2_BANK] = 0x1128,
|
||||
[SWRM_OFFSET_DP_BLOCK_CTRL_1] = 0x112c,
|
||||
[SWRM_OFFSET_DP_BLOCK_CTRL2_BANK] = 0x1130,
|
||||
[SWRM_OFFSET_DP_PORT_HCTRL_BANK] = 0x1134,
|
||||
[SWRM_OFFSET_DP_BLOCK_CTRL3_BANK] = 0x1138,
|
||||
[SWRM_OFFSET_DP_SAMPLECTRL2_BANK] = 0x113c,
|
||||
};
|
||||
|
||||
static const struct qcom_swrm_data swrm_v1_3_data = {
|
||||
|
|
@ -265,6 +283,13 @@ static const unsigned int swrm_v2_0_reg_layout[] = {
|
|||
[SWRM_REG_CMD_FIFO_RD_CMD] = SWRM_V2_0_CMD_FIFO_RD_CMD,
|
||||
[SWRM_REG_CMD_FIFO_STATUS] = SWRM_V2_0_CMD_FIFO_STATUS,
|
||||
[SWRM_REG_CMD_FIFO_RD_FIFO_ADDR] = SWRM_V2_0_CMD_FIFO_RD_FIFO_ADDR,
|
||||
[SWRM_OFFSET_DP_PORT_CTRL_BANK] = 0x1124,
|
||||
[SWRM_OFFSET_DP_PORT_CTRL_2_BANK] = 0x1128,
|
||||
[SWRM_OFFSET_DP_BLOCK_CTRL_1] = 0x112c,
|
||||
[SWRM_OFFSET_DP_BLOCK_CTRL2_BANK] = 0x1130,
|
||||
[SWRM_OFFSET_DP_PORT_HCTRL_BANK] = 0x1134,
|
||||
[SWRM_OFFSET_DP_BLOCK_CTRL3_BANK] = 0x1138,
|
||||
[SWRM_OFFSET_DP_SAMPLECTRL2_BANK] = 0x113c,
|
||||
};
|
||||
|
||||
static const struct qcom_swrm_data swrm_v2_0_data = {
|
||||
|
|
@ -275,6 +300,32 @@ static const struct qcom_swrm_data swrm_v2_0_data = {
|
|||
.reg_layout = swrm_v2_0_reg_layout,
|
||||
};
|
||||
|
||||
static const unsigned int swrm_v3_0_reg_layout[] = {
|
||||
[SWRM_REG_FRAME_GEN_ENABLED] = SWRM_V2_0_LINK_STATUS,
|
||||
[SWRM_REG_INTERRUPT_STATUS] = SWRM_V2_0_INTERRUPT_STATUS,
|
||||
[SWRM_REG_INTERRUPT_MASK_ADDR] = 0, /* Not present */
|
||||
[SWRM_REG_INTERRUPT_CLEAR] = SWRM_V2_0_INTERRUPT_CLEAR,
|
||||
[SWRM_REG_INTERRUPT_CPU_EN] = SWRM_V2_0_INTERRUPT_CPU_EN,
|
||||
[SWRM_REG_CMD_FIFO_WR_CMD] = SWRM_V2_0_CMD_FIFO_WR_CMD,
|
||||
[SWRM_REG_CMD_FIFO_RD_CMD] = SWRM_V2_0_CMD_FIFO_RD_CMD,
|
||||
[SWRM_REG_CMD_FIFO_STATUS] = SWRM_V2_0_CMD_FIFO_STATUS,
|
||||
[SWRM_REG_CMD_FIFO_RD_FIFO_ADDR] = SWRM_V2_0_CMD_FIFO_RD_FIFO_ADDR,
|
||||
[SWRM_OFFSET_DP_PORT_CTRL_BANK] = 0x1224,
|
||||
[SWRM_OFFSET_DP_PORT_CTRL_2_BANK] = 0x1228,
|
||||
[SWRM_OFFSET_DP_BLOCK_CTRL_1] = 0x122c,
|
||||
[SWRM_OFFSET_DP_BLOCK_CTRL2_BANK] = 0x1230,
|
||||
[SWRM_OFFSET_DP_PORT_HCTRL_BANK] = 0x1234,
|
||||
[SWRM_OFFSET_DP_BLOCK_CTRL3_BANK] = 0x1238,
|
||||
[SWRM_OFFSET_DP_SAMPLECTRL2_BANK] = 0x123c,
|
||||
};
|
||||
|
||||
static const struct qcom_swrm_data swrm_v3_0_data = {
|
||||
.default_rows = 50,
|
||||
.default_cols = 16,
|
||||
.sw_clk_gate_required = true,
|
||||
.max_reg = SWR_V2_0_MSTR_MAX_REG_ADDR,
|
||||
.reg_layout = swrm_v3_0_reg_layout,
|
||||
};
|
||||
#define to_qcom_sdw(b) container_of(b, struct qcom_swrm_ctrl, bus)
|
||||
|
||||
static int qcom_swrm_ahb_reg_read(struct qcom_swrm_ctrl *ctrl, int reg,
|
||||
|
|
@ -898,7 +949,10 @@ static int qcom_swrm_init(struct qcom_swrm_ctrl *ctrl)
|
|||
swrm_wait_for_frame_gen_enabled(ctrl);
|
||||
ctrl->slave_status = 0;
|
||||
ctrl->reg_read(ctrl, SWRM_COMP_PARAMS, &val);
|
||||
ctrl->rd_fifo_depth = FIELD_GET(SWRM_COMP_PARAMS_RD_FIFO_DEPTH, val);
|
||||
|
||||
if (ctrl->version >= SWRM_VERSION_3_1_0)
|
||||
ctrl->wr_fifo_depth = FIELD_GET(SWRM_V3_COMP_PARAMS_WR_FIFO_DEPTH, val);
|
||||
else
|
||||
ctrl->wr_fifo_depth = FIELD_GET(SWRM_COMP_PARAMS_WR_FIFO_DEPTH, val);
|
||||
|
||||
return 0;
|
||||
|
|
@ -966,10 +1020,10 @@ static int qcom_swrm_port_params(struct sdw_bus *bus,
|
|||
unsigned int bank)
|
||||
{
|
||||
struct qcom_swrm_ctrl *ctrl = to_qcom_sdw(bus);
|
||||
u32 offset = ctrl->reg_layout[SWRM_OFFSET_DP_BLOCK_CTRL_1];
|
||||
|
||||
return ctrl->reg_write(ctrl, SWRM_DP_BLOCK_CTRL_1(p_params->num),
|
||||
return ctrl->reg_write(ctrl, SWRM_DPn_BLOCK_CTRL_1(offset, p_params->num),
|
||||
p_params->bps - 1);
|
||||
|
||||
}
|
||||
|
||||
static int qcom_swrm_transport_params(struct sdw_bus *bus,
|
||||
|
|
@ -979,9 +1033,11 @@ static int qcom_swrm_transport_params(struct sdw_bus *bus,
|
|||
struct qcom_swrm_ctrl *ctrl = to_qcom_sdw(bus);
|
||||
struct qcom_swrm_port_config *pcfg;
|
||||
u32 value;
|
||||
int reg = SWRM_DP_PORT_CTRL_BANK((params->port_num), bank);
|
||||
int reg, offset = ctrl->reg_layout[SWRM_OFFSET_DP_PORT_CTRL_BANK];
|
||||
int ret;
|
||||
|
||||
reg = SWRM_DPn_PORT_CTRL_BANK(offset, params->port_num, bank);
|
||||
|
||||
pcfg = &ctrl->pconfig[params->port_num];
|
||||
|
||||
value = pcfg->off1 << SWRM_DP_PORT_CTRL_OFFSET1_SHFT;
|
||||
|
|
@ -993,15 +1049,19 @@ static int qcom_swrm_transport_params(struct sdw_bus *bus,
|
|||
goto err;
|
||||
|
||||
if (pcfg->si > 0xff) {
|
||||
offset = ctrl->reg_layout[SWRM_OFFSET_DP_SAMPLECTRL2_BANK];
|
||||
value = (pcfg->si >> 8) & 0xff;
|
||||
reg = SWRM_DP_SAMPLECTRL2_BANK(params->port_num, bank);
|
||||
reg = SWRM_DPn_SAMPLECTRL2_BANK(offset, params->port_num, bank);
|
||||
|
||||
ret = ctrl->reg_write(ctrl, reg, value);
|
||||
if (ret)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (pcfg->lane_control != SWR_INVALID_PARAM) {
|
||||
reg = SWRM_DP_PORT_CTRL_2_BANK(params->port_num, bank);
|
||||
offset = ctrl->reg_layout[SWRM_OFFSET_DP_PORT_CTRL_2_BANK];
|
||||
reg = SWRM_DPn_PORT_CTRL_2_BANK(offset, params->port_num, bank);
|
||||
|
||||
value = pcfg->lane_control;
|
||||
ret = ctrl->reg_write(ctrl, reg, value);
|
||||
if (ret)
|
||||
|
|
@ -1009,20 +1069,23 @@ static int qcom_swrm_transport_params(struct sdw_bus *bus,
|
|||
}
|
||||
|
||||
if (pcfg->blk_group_count != SWR_INVALID_PARAM) {
|
||||
reg = SWRM_DP_BLOCK_CTRL2_BANK(params->port_num, bank);
|
||||
offset = ctrl->reg_layout[SWRM_OFFSET_DP_BLOCK_CTRL2_BANK];
|
||||
|
||||
reg = SWRM_DPn_BLOCK_CTRL2_BANK(offset, params->port_num, bank);
|
||||
|
||||
value = pcfg->blk_group_count;
|
||||
ret = ctrl->reg_write(ctrl, reg, value);
|
||||
if (ret)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (pcfg->hstart != SWR_INVALID_PARAM
|
||||
&& pcfg->hstop != SWR_INVALID_PARAM) {
|
||||
reg = SWRM_DP_PORT_HCTRL_BANK(params->port_num, bank);
|
||||
offset = ctrl->reg_layout[SWRM_OFFSET_DP_PORT_HCTRL_BANK];
|
||||
reg = SWRM_DPn_PORT_HCTRL_BANK(offset, params->port_num, bank);
|
||||
|
||||
if (pcfg->hstart != SWR_INVALID_PARAM && pcfg->hstop != SWR_INVALID_PARAM) {
|
||||
value = (pcfg->hstop << 4) | pcfg->hstart;
|
||||
ret = ctrl->reg_write(ctrl, reg, value);
|
||||
} else {
|
||||
reg = SWRM_DP_PORT_HCTRL_BANK(params->port_num, bank);
|
||||
value = (SWR_HSTOP_MAX_VAL << 4) | SWR_HSTART_MIN_VAL;
|
||||
ret = ctrl->reg_write(ctrl, reg, value);
|
||||
}
|
||||
|
|
@ -1031,7 +1094,8 @@ static int qcom_swrm_transport_params(struct sdw_bus *bus,
|
|||
goto err;
|
||||
|
||||
if (pcfg->bp_mode != SWR_INVALID_PARAM) {
|
||||
reg = SWRM_DP_BLOCK_CTRL3_BANK(params->port_num, bank);
|
||||
offset = ctrl->reg_layout[SWRM_OFFSET_DP_BLOCK_CTRL3_BANK];
|
||||
reg = SWRM_DPn_BLOCK_CTRL3_BANK(offset, params->port_num, bank);
|
||||
ret = ctrl->reg_write(ctrl, reg, pcfg->bp_mode);
|
||||
}
|
||||
|
||||
|
|
@ -1043,9 +1107,12 @@ static int qcom_swrm_port_enable(struct sdw_bus *bus,
|
|||
struct sdw_enable_ch *enable_ch,
|
||||
unsigned int bank)
|
||||
{
|
||||
u32 reg = SWRM_DP_PORT_CTRL_BANK(enable_ch->port_num, bank);
|
||||
u32 reg;
|
||||
struct qcom_swrm_ctrl *ctrl = to_qcom_sdw(bus);
|
||||
u32 val;
|
||||
u32 offset = ctrl->reg_layout[SWRM_OFFSET_DP_PORT_CTRL_BANK];
|
||||
|
||||
reg = SWRM_DPn_PORT_CTRL_BANK(offset, enable_ch->port_num, bank);
|
||||
|
||||
ctrl->reg_read(ctrl, reg, &val);
|
||||
|
||||
|
|
@ -1155,7 +1222,6 @@ static int qcom_swrm_stream_alloc_ports(struct qcom_swrm_ctrl *ctrl,
|
|||
struct snd_pcm_hw_params *params,
|
||||
int direction)
|
||||
{
|
||||
struct sdw_port_config pconfig[QCOM_SDW_MAX_PORTS];
|
||||
struct sdw_stream_config sconfig;
|
||||
struct sdw_master_runtime *m_rt;
|
||||
struct sdw_slave_runtime *s_rt;
|
||||
|
|
@ -1164,6 +1230,10 @@ static int qcom_swrm_stream_alloc_ports(struct qcom_swrm_ctrl *ctrl,
|
|||
unsigned long *port_mask;
|
||||
int maxport, pn, nports = 0, ret = 0;
|
||||
unsigned int m_port;
|
||||
struct sdw_port_config *pconfig __free(kfree) = kcalloc(ctrl->nports,
|
||||
sizeof(*pconfig), GFP_KERNEL);
|
||||
if (!pconfig)
|
||||
return -ENOMEM;
|
||||
|
||||
if (direction == SNDRV_PCM_STREAM_CAPTURE)
|
||||
sconfig.direction = SDW_DATA_DIR_TX;
|
||||
|
|
@ -1188,8 +1258,7 @@ static int qcom_swrm_stream_alloc_ports(struct qcom_swrm_ctrl *ctrl,
|
|||
continue;
|
||||
|
||||
port_mask = &ctrl->port_mask;
|
||||
maxport = ctrl->num_dout_ports + ctrl->num_din_ports;
|
||||
|
||||
maxport = ctrl->nports;
|
||||
|
||||
list_for_each_entry(s_rt, &m_rt->slave_rt_list, m_rt_node) {
|
||||
slave = s_rt->slave;
|
||||
|
|
@ -1349,17 +1418,8 @@ static int qcom_swrm_register_dais(struct qcom_swrm_ctrl *ctrl)
|
|||
static int qcom_swrm_get_port_config(struct qcom_swrm_ctrl *ctrl)
|
||||
{
|
||||
struct device_node *np = ctrl->dev->of_node;
|
||||
u8 off1[QCOM_SDW_MAX_PORTS];
|
||||
u8 off2[QCOM_SDW_MAX_PORTS];
|
||||
u16 si[QCOM_SDW_MAX_PORTS];
|
||||
u8 bp_mode[QCOM_SDW_MAX_PORTS] = { 0, };
|
||||
u8 hstart[QCOM_SDW_MAX_PORTS];
|
||||
u8 hstop[QCOM_SDW_MAX_PORTS];
|
||||
u8 word_length[QCOM_SDW_MAX_PORTS];
|
||||
u8 blk_group_count[QCOM_SDW_MAX_PORTS];
|
||||
u8 lane_control[QCOM_SDW_MAX_PORTS];
|
||||
int i, ret, nports, val;
|
||||
bool si_16 = false;
|
||||
struct qcom_swrm_port_config *pcfg;
|
||||
int i, ret, val;
|
||||
|
||||
ctrl->reg_read(ctrl, SWRM_COMP_PARAMS, &val);
|
||||
|
||||
|
|
@ -1367,88 +1427,78 @@ static int qcom_swrm_get_port_config(struct qcom_swrm_ctrl *ctrl)
|
|||
ctrl->num_din_ports = FIELD_GET(SWRM_COMP_PARAMS_DIN_PORTS_MASK, val);
|
||||
|
||||
ret = of_property_read_u32(np, "qcom,din-ports", &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (val > ctrl->num_din_ports)
|
||||
return -EINVAL;
|
||||
if (!ret) { /* only if present */
|
||||
if (val != ctrl->num_din_ports) {
|
||||
dev_err(ctrl->dev, "din-ports (%d) mismatch with controller (%d)",
|
||||
val, ctrl->num_din_ports);
|
||||
}
|
||||
|
||||
ctrl->num_din_ports = val;
|
||||
}
|
||||
|
||||
ret = of_property_read_u32(np, "qcom,dout-ports", &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (val > ctrl->num_dout_ports)
|
||||
return -EINVAL;
|
||||
if (!ret) { /* only if present */
|
||||
if (val != ctrl->num_dout_ports) {
|
||||
dev_err(ctrl->dev, "dout-ports (%d) mismatch with controller (%d)",
|
||||
val, ctrl->num_dout_ports);
|
||||
}
|
||||
|
||||
ctrl->num_dout_ports = val;
|
||||
|
||||
nports = ctrl->num_dout_ports + ctrl->num_din_ports;
|
||||
if (nports > QCOM_SDW_MAX_PORTS)
|
||||
return -EINVAL;
|
||||
|
||||
/* Valid port numbers are from 1-14, so mask out port 0 explicitly */
|
||||
set_bit(0, &ctrl->port_mask);
|
||||
|
||||
ret = of_property_read_u8_array(np, "qcom,ports-offset1",
|
||||
off1, nports);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = of_property_read_u8_array(np, "qcom,ports-offset2",
|
||||
off2, nports);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = of_property_read_u8_array(np, "qcom,ports-sinterval-low",
|
||||
(u8 *)si, nports);
|
||||
if (ret) {
|
||||
ret = of_property_read_u16_array(np, "qcom,ports-sinterval",
|
||||
si, nports);
|
||||
if (ret)
|
||||
return ret;
|
||||
si_16 = true;
|
||||
}
|
||||
|
||||
ret = of_property_read_u8_array(np, "qcom,ports-block-pack-mode",
|
||||
bp_mode, nports);
|
||||
ctrl->nports = ctrl->num_dout_ports + ctrl->num_din_ports;
|
||||
|
||||
ctrl->pconfig = devm_kcalloc(ctrl->dev, ctrl->nports + 1,
|
||||
sizeof(*ctrl->pconfig), GFP_KERNEL);
|
||||
if (!ctrl->pconfig)
|
||||
return -ENOMEM;
|
||||
|
||||
set_bit(0, &ctrl->port_mask);
|
||||
/* Valid port numbers are from 1, so mask out port 0 explicitly */
|
||||
for (i = 0; i < ctrl->nports; i++) {
|
||||
pcfg = &ctrl->pconfig[i + 1];
|
||||
|
||||
ret = of_property_read_u8_index(np, "qcom,ports-offset1", i, &pcfg->off1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = of_property_read_u8_index(np, "qcom,ports-offset2", i, &pcfg->off2);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = of_property_read_u8_index(np, "qcom,ports-sinterval-low", i, (u8 *)&pcfg->si);
|
||||
if (ret) {
|
||||
ret = of_property_read_u16_index(np, "qcom,ports-sinterval", i, &pcfg->si);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = of_property_read_u8_index(np, "qcom,ports-block-pack-mode",
|
||||
i, &pcfg->bp_mode);
|
||||
if (ret) {
|
||||
if (ctrl->version <= SWRM_VERSION_1_3_0)
|
||||
memset(bp_mode, SWR_INVALID_PARAM, QCOM_SDW_MAX_PORTS);
|
||||
pcfg->bp_mode = SWR_INVALID_PARAM;
|
||||
else
|
||||
return ret;
|
||||
}
|
||||
|
||||
memset(hstart, SWR_INVALID_PARAM, QCOM_SDW_MAX_PORTS);
|
||||
of_property_read_u8_array(np, "qcom,ports-hstart", hstart, nports);
|
||||
/* Optional properties */
|
||||
pcfg->hstart = SWR_INVALID_PARAM;
|
||||
pcfg->hstop = SWR_INVALID_PARAM;
|
||||
pcfg->word_length = SWR_INVALID_PARAM;
|
||||
pcfg->blk_group_count = SWR_INVALID_PARAM;
|
||||
pcfg->lane_control = SWR_INVALID_PARAM;
|
||||
|
||||
memset(hstop, SWR_INVALID_PARAM, QCOM_SDW_MAX_PORTS);
|
||||
of_property_read_u8_array(np, "qcom,ports-hstop", hstop, nports);
|
||||
of_property_read_u8_index(np, "qcom,ports-hstart", i, &pcfg->hstart);
|
||||
|
||||
memset(word_length, SWR_INVALID_PARAM, QCOM_SDW_MAX_PORTS);
|
||||
of_property_read_u8_array(np, "qcom,ports-word-length", word_length, nports);
|
||||
of_property_read_u8_index(np, "qcom,ports-hstop", i, &pcfg->hstop);
|
||||
|
||||
memset(blk_group_count, SWR_INVALID_PARAM, QCOM_SDW_MAX_PORTS);
|
||||
of_property_read_u8_array(np, "qcom,ports-block-group-count", blk_group_count, nports);
|
||||
of_property_read_u8_index(np, "qcom,ports-word-length", i, &pcfg->word_length);
|
||||
|
||||
memset(lane_control, SWR_INVALID_PARAM, QCOM_SDW_MAX_PORTS);
|
||||
of_property_read_u8_array(np, "qcom,ports-lane-control", lane_control, nports);
|
||||
of_property_read_u8_index(np, "qcom,ports-block-group-count",
|
||||
i, &pcfg->blk_group_count);
|
||||
|
||||
for (i = 0; i < nports; i++) {
|
||||
/* Valid port number range is from 1-14 */
|
||||
if (si_16)
|
||||
ctrl->pconfig[i + 1].si = si[i];
|
||||
else
|
||||
ctrl->pconfig[i + 1].si = ((u8 *)si)[i];
|
||||
ctrl->pconfig[i + 1].off1 = off1[i];
|
||||
ctrl->pconfig[i + 1].off2 = off2[i];
|
||||
ctrl->pconfig[i + 1].bp_mode = bp_mode[i];
|
||||
ctrl->pconfig[i + 1].hstart = hstart[i];
|
||||
ctrl->pconfig[i + 1].hstop = hstop[i];
|
||||
ctrl->pconfig[i + 1].word_length = word_length[i];
|
||||
ctrl->pconfig[i + 1].blk_group_count = blk_group_count[i];
|
||||
ctrl->pconfig[i + 1].lane_control = lane_control[i];
|
||||
of_property_read_u8_index(np, "qcom,ports-lane-control", i, &pcfg->lane_control);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -1769,6 +1819,7 @@ static const struct of_device_id qcom_swrm_of_match[] = {
|
|||
{ .compatible = "qcom,soundwire-v1.6.0", .data = &swrm_v1_6_data },
|
||||
{ .compatible = "qcom,soundwire-v1.7.0", .data = &swrm_v1_5_data },
|
||||
{ .compatible = "qcom,soundwire-v2.0.0", .data = &swrm_v2_0_data },
|
||||
{ .compatible = "qcom,soundwire-v3.1.0", .data = &swrm_v3_0_data },
|
||||
{/* sentinel */},
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -316,6 +316,9 @@ extern struct property *of_find_property(const struct device_node *np,
|
|||
extern bool of_property_read_bool(const struct device_node *np, const char *propname);
|
||||
extern int of_property_count_elems_of_size(const struct device_node *np,
|
||||
const char *propname, int elem_size);
|
||||
extern int of_property_read_u8_index(const struct device_node *np,
|
||||
const char *propname,
|
||||
u32 index, u8 *out_value);
|
||||
extern int of_property_read_u16_index(const struct device_node *np,
|
||||
const char *propname,
|
||||
u32 index, u16 *out_value);
|
||||
|
|
@ -648,6 +651,12 @@ static inline int of_property_count_elems_of_size(const struct device_node *np,
|
|||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline int of_property_read_u8_index(const struct device_node *np,
|
||||
const char *propname, u32 index, u8 *out_value)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline int of_property_read_u16_index(const struct device_node *np,
|
||||
const char *propname, u32 index, u16 *out_value)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@ int hda_sdw_bpt_wait(struct device *dev, struct hdac_ext_stream *bpt_tx_stream,
|
|||
int hda_sdw_bpt_close(struct device *dev, struct hdac_ext_stream *bpt_tx_stream,
|
||||
struct snd_dma_buffer *dmab_tx_bdl, struct hdac_ext_stream *bpt_rx_stream,
|
||||
struct snd_dma_buffer *dmab_rx_bdl);
|
||||
|
||||
unsigned int hda_sdw_bpt_get_buf_size_alignment(unsigned int dma_bandwidth);
|
||||
#else
|
||||
static inline int hda_sdw_bpt_open(struct device *dev, int link_id,
|
||||
struct hdac_ext_stream **bpt_tx_stream,
|
||||
|
|
@ -64,6 +66,11 @@ static inline int hda_sdw_bpt_close(struct device *dev, struct hdac_ext_stream *
|
|||
WARN_ONCE(1, "SoundWire BPT is disabled");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline unsigned int hda_sdw_bpt_get_buf_size_alignment(unsigned int dma_bandwidth)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __HDA_SDW_BPT_H */
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
* Hardware interface for SoundWire BPT support with HDA DMA
|
||||
*/
|
||||
|
||||
#include <linux/lcm.h>
|
||||
#include <sound/hdaudio_ext.h>
|
||||
#include <sound/hda-mlink.h>
|
||||
#include <sound/hda-sdw-bpt.h>
|
||||
|
|
@ -236,6 +237,18 @@ static int hda_sdw_bpt_dma_disable(struct device *dev, struct hdac_ext_stream *s
|
|||
return ret;
|
||||
}
|
||||
|
||||
#define FIFO_ALIGNMENT 64
|
||||
|
||||
unsigned int hda_sdw_bpt_get_buf_size_alignment(unsigned int dma_bandwidth)
|
||||
{
|
||||
unsigned int num_channels = DIV_ROUND_UP(dma_bandwidth, BPT_FREQUENCY * 32);
|
||||
unsigned int data_block = num_channels * 4;
|
||||
unsigned int alignment = lcm(data_block, FIFO_ALIGNMENT);
|
||||
|
||||
return alignment;
|
||||
}
|
||||
EXPORT_SYMBOL_NS(hda_sdw_bpt_get_buf_size_alignment, "SND_SOC_SOF_INTEL_HDA_SDW_BPT");
|
||||
|
||||
int hda_sdw_bpt_open(struct device *dev, int link_id, struct hdac_ext_stream **bpt_tx_stream,
|
||||
struct snd_dma_buffer *dmab_tx_bdl, u32 bpt_tx_num_bytes,
|
||||
u32 tx_dma_bandwidth, struct hdac_ext_stream **bpt_rx_stream,
|
||||
|
|
|
|||
Loading…
Reference in New Issue