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.6.0
|
||||||
- qcom,soundwire-v1.7.0
|
- qcom,soundwire-v1.7.0
|
||||||
- qcom,soundwire-v2.0.0
|
- qcom,soundwire-v2.0.0
|
||||||
|
- qcom,soundwire-v3.1.0
|
||||||
- items:
|
- items:
|
||||||
- enum:
|
- enum:
|
||||||
- qcom,soundwire-v2.1.0
|
- qcom,soundwire-v2.1.0
|
||||||
|
|
@ -73,10 +74,12 @@ properties:
|
||||||
qcom,din-ports:
|
qcom,din-ports:
|
||||||
$ref: /schemas/types.yaml#/definitions/uint32
|
$ref: /schemas/types.yaml#/definitions/uint32
|
||||||
description: count of data in ports
|
description: count of data in ports
|
||||||
|
deprecated: true
|
||||||
|
|
||||||
qcom,dout-ports:
|
qcom,dout-ports:
|
||||||
$ref: /schemas/types.yaml#/definitions/uint32
|
$ref: /schemas/types.yaml#/definitions/uint32
|
||||||
description: count of data out ports
|
description: count of data out ports
|
||||||
|
deprecated: true
|
||||||
|
|
||||||
qcom,ports-word-length:
|
qcom,ports-word-length:
|
||||||
$ref: /schemas/types.yaml#/definitions/uint8-array
|
$ref: /schemas/types.yaml#/definitions/uint8-array
|
||||||
|
|
@ -223,8 +226,6 @@ required:
|
||||||
- '#sound-dai-cells'
|
- '#sound-dai-cells'
|
||||||
- '#address-cells'
|
- '#address-cells'
|
||||||
- '#size-cells'
|
- '#size-cells'
|
||||||
- qcom,dout-ports
|
|
||||||
- qcom,din-ports
|
|
||||||
- qcom,ports-offset1
|
- qcom,ports-offset1
|
||||||
- qcom,ports-offset2
|
- qcom,ports-offset2
|
||||||
|
|
||||||
|
|
@ -257,9 +258,6 @@ examples:
|
||||||
clocks = <&lpass_rx_macro>;
|
clocks = <&lpass_rx_macro>;
|
||||||
clock-names = "iface";
|
clock-names = "iface";
|
||||||
|
|
||||||
qcom,din-ports = <0>;
|
|
||||||
qcom,dout-ports = <5>;
|
|
||||||
|
|
||||||
resets = <&lpass_audiocc LPASS_AUDIO_SWR_RX_CGCR>;
|
resets = <&lpass_audiocc LPASS_AUDIO_SWR_RX_CGCR>;
|
||||||
reset-names = "swr_audio_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;
|
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.
|
* 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)
|
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) {
|
int len = 0;
|
||||||
dev_err(bus->dev, "Invalid BPT message length %d\n", msg->len);
|
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;
|
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
|
* @addr: Start Register address accessed in the Slave
|
||||||
* @len: number of bytes to transfer. More than 64Kb can be transferred
|
* @len: number of bytes to transfer. More than 64Kb can be transferred
|
||||||
* but a practical limit of SDW_BPT_MSG_MAX_BYTES is enforced.
|
* but a practical limit of SDW_BPT_MSG_MAX_BYTES is enforced.
|
||||||
* @dev_num: Slave device number
|
* @buf: section data buffer (filled by host for write, filled
|
||||||
* @flags: transfer flags, indicate if xfer is read or write
|
|
||||||
* @buf: message data buffer (filled by host for write, filled
|
|
||||||
* by Peripheral hardware for reads)
|
* by Peripheral hardware for reads)
|
||||||
*/
|
*/
|
||||||
struct sdw_bpt_msg {
|
struct sdw_bpt_section {
|
||||||
u32 addr;
|
u32 addr;
|
||||||
u32 len;
|
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 dev_num;
|
||||||
u8 flags;
|
u8 flags;
|
||||||
u8 *buf;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SDW_DOUBLE_RATE_FACTOR 2
|
#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;
|
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 sdw_cdns_bpt_find_buffer_sizes(int command, /* 0: write, 1: read */
|
||||||
int row, int col, unsigned int data_bytes,
|
int row, int col, unsigned int data_bytes,
|
||||||
unsigned int requested_bytes_per_frame,
|
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)
|
if (!actual_bpt_bytes)
|
||||||
return -EINVAL;
|
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,
|
* the caller may want to set the number of bytes per frame,
|
||||||
* allow when possible
|
* 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;
|
*data_per_frame = actual_bpt_bytes;
|
||||||
|
|
||||||
|
if (data_bytes < actual_bpt_bytes)
|
||||||
|
actual_bpt_bytes = data_bytes;
|
||||||
|
|
||||||
if (command == 0) {
|
if (command == 0) {
|
||||||
/*
|
/*
|
||||||
* for writes we need to send all the data_bytes per frame,
|
* 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
|
#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 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 data_per_frame, u8 *dma_buffer,
|
||||||
int *dma_buffer_total_bytes)
|
int dma_buffer_size, int *dma_buffer_total_bytes)
|
||||||
{
|
{
|
||||||
int total_dma_data_written = 0;
|
int total_dma_data_written = 0;
|
||||||
u8 *p_dma_buffer = dma_buffer;
|
u8 *p_dma_buffer = dma_buffer;
|
||||||
u8 header[SDW_CDNS_BRA_HDR];
|
u8 header[SDW_CDNS_BRA_HDR];
|
||||||
|
unsigned int start_register;
|
||||||
|
unsigned int section_size;
|
||||||
int dma_data_written;
|
int dma_data_written;
|
||||||
u8 *p_data = data;
|
u8 *p_data;
|
||||||
u8 counter;
|
u8 counter;
|
||||||
int ret;
|
int ret;
|
||||||
|
int i;
|
||||||
|
|
||||||
counter = CDNS_BPT_ROLLING_COUNTER_START;
|
counter = CDNS_BPT_ROLLING_COUNTER_START;
|
||||||
|
|
||||||
|
|
@ -2312,47 +2345,57 @@ 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] |= GENMASK(7, 6); /* header is active */
|
||||||
header[0] |= (dev_num << 2);
|
header[0] |= (dev_num << 2);
|
||||||
|
|
||||||
while (data_size >= data_per_frame) {
|
for (i = 0; i < num_sec; i++) {
|
||||||
header[1] = data_per_frame;
|
start_register = sec[i].addr;
|
||||||
header[2] = start_register >> 24 & 0xFF;
|
section_size = sec[i].len;
|
||||||
header[3] = start_register >> 16 & 0xFF;
|
p_data = sec[i].buf;
|
||||||
header[4] = start_register >> 8 & 0xFF;
|
|
||||||
header[5] = start_register >> 0 & 0xFF;
|
|
||||||
|
|
||||||
ret = sdw_cdns_prepare_write_pd0_buffer(header, SDW_CDNS_BRA_HDR,
|
while (section_size >= data_per_frame) {
|
||||||
p_data, data_per_frame,
|
header[1] = data_per_frame;
|
||||||
p_dma_buffer, dma_buffer_size,
|
header[2] = start_register >> 24 & 0xFF;
|
||||||
&dma_data_written, counter);
|
header[3] = start_register >> 16 & 0xFF;
|
||||||
if (ret < 0)
|
header[4] = start_register >> 8 & 0xFF;
|
||||||
return ret;
|
header[5] = start_register >> 0 & 0xFF;
|
||||||
|
|
||||||
counter++;
|
ret = sdw_cdns_prepare_write_pd0_buffer(header, SDW_CDNS_BRA_HDR,
|
||||||
|
p_data, data_per_frame,
|
||||||
|
p_dma_buffer, dma_buffer_size,
|
||||||
|
&dma_data_written, counter);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
p_data += data_per_frame;
|
counter++;
|
||||||
data_size -= data_per_frame;
|
|
||||||
|
|
||||||
p_dma_buffer += dma_data_written;
|
p_data += data_per_frame;
|
||||||
dma_buffer_size -= dma_data_written;
|
section_size -= data_per_frame;
|
||||||
total_dma_data_written += dma_data_written;
|
|
||||||
|
|
||||||
start_register += data_per_frame;
|
p_dma_buffer += dma_data_written;
|
||||||
}
|
dma_buffer_size -= dma_data_written;
|
||||||
|
total_dma_data_written += dma_data_written;
|
||||||
|
|
||||||
if (data_size) {
|
start_register += data_per_frame;
|
||||||
header[1] = data_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,
|
if (section_size) {
|
||||||
p_data, data_size,
|
header[1] = section_size;
|
||||||
p_dma_buffer, dma_buffer_size,
|
header[2] = start_register >> 24 & 0xFF;
|
||||||
&dma_data_written, counter);
|
header[3] = start_register >> 16 & 0xFF;
|
||||||
if (ret < 0)
|
header[4] = start_register >> 8 & 0xFF;
|
||||||
return ret;
|
header[5] = start_register >> 0 & 0xFF;
|
||||||
|
|
||||||
total_dma_data_written += dma_data_written;
|
ret = sdw_cdns_prepare_write_pd0_buffer(header, SDW_CDNS_BRA_HDR,
|
||||||
|
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;
|
*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);
|
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 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;
|
int total_dma_data_written = 0;
|
||||||
u8 *p_dma_buffer = dma_buffer;
|
u8 *p_dma_buffer = dma_buffer;
|
||||||
u8 header[SDW_CDNS_BRA_HDR];
|
u8 header[SDW_CDNS_BRA_HDR];
|
||||||
|
unsigned int start_register;
|
||||||
|
unsigned int data_size;
|
||||||
int dma_data_written;
|
int dma_data_written;
|
||||||
u8 counter;
|
u8 counter;
|
||||||
int ret;
|
int ret;
|
||||||
|
int i;
|
||||||
|
|
||||||
counter = CDNS_BPT_ROLLING_COUNTER_START;
|
counter = CDNS_BPT_ROLLING_COUNTER_START;
|
||||||
|
|
||||||
|
|
@ -2378,13 +2424,58 @@ 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] |= GENMASK(7, 6); /* header is active */
|
||||||
header[0] |= (dev_num << 2);
|
header[0] |= (dev_num << 2);
|
||||||
|
|
||||||
while (data_size >= data_per_frame) {
|
for (i = 0; i < num_sec; i++) {
|
||||||
header[1] = data_per_frame;
|
start_register = sec[i].addr;
|
||||||
header[2] = start_register >> 24 & 0xFF;
|
data_size = sec[i].len;
|
||||||
header[3] = start_register >> 16 & 0xFF;
|
while (data_size >= data_per_frame) {
|
||||||
header[4] = start_register >> 8 & 0xFF;
|
header[1] = data_per_frame;
|
||||||
header[5] = start_register >> 0 & 0xFF;
|
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_read_pd0_buffer(header, SDW_CDNS_BRA_HDR,
|
||||||
|
p_dma_buffer, dma_buffer_size,
|
||||||
|
&dma_data_written, counter);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
counter++;
|
||||||
|
|
||||||
|
data_size -= data_per_frame;
|
||||||
|
|
||||||
|
p_dma_buffer += dma_data_written;
|
||||||
|
dma_buffer_size -= dma_data_written;
|
||||||
|
total_dma_data_written += dma_data_written;
|
||||||
|
|
||||||
|
start_register += data_per_frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data_size) {
|
||||||
|
header[1] = data_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_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,
|
ret = sdw_cdns_prepare_read_pd0_buffer(header, SDW_CDNS_BRA_HDR, p_dma_buffer,
|
||||||
dma_buffer_size, &dma_data_written,
|
dma_buffer_size, &dma_data_written,
|
||||||
counter);
|
counter);
|
||||||
|
|
@ -2393,28 +2484,24 @@ int sdw_cdns_prepare_read_dma_buffer(u8 dev_num, u32 start_register, int data_si
|
||||||
|
|
||||||
counter++;
|
counter++;
|
||||||
|
|
||||||
data_size -= data_per_frame;
|
fake_size -= data_per_frame;
|
||||||
|
|
||||||
p_dma_buffer += dma_data_written;
|
p_dma_buffer += dma_data_written;
|
||||||
dma_buffer_size -= dma_data_written;
|
dma_buffer_size -= dma_data_written;
|
||||||
total_dma_data_written += dma_data_written;
|
total_dma_data_written += dma_data_written;
|
||||||
|
|
||||||
start_register += data_per_frame;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data_size) {
|
if (fake_size) {
|
||||||
header[1] = data_size;
|
header[1] = fake_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_read_pd0_buffer(header, SDW_CDNS_BRA_HDR, p_dma_buffer,
|
ret = sdw_cdns_prepare_read_pd0_buffer(header, SDW_CDNS_BRA_HDR, p_dma_buffer,
|
||||||
dma_buffer_size, &dma_data_written,
|
dma_buffer_size, &dma_data_written,
|
||||||
counter);
|
counter);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
counter++;
|
||||||
|
|
||||||
|
p_dma_buffer += dma_data_written;
|
||||||
|
dma_buffer_size -= dma_data_written;
|
||||||
total_dma_data_written += 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);
|
ret = check_frame_start(header, counter);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(dev, "%s: bad frame %d/%d start header %x\n",
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = check_frame_end(footer);
|
ret = check_frame_end(footer);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(dev, "%s: bad frame %d/%d end footer %x\n",
|
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;
|
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,
|
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 total_num_bytes = 0;
|
||||||
|
int buffer_size = 0;
|
||||||
|
int sec_index;
|
||||||
u32 *p_data;
|
u32 *p_data;
|
||||||
u8 *p_buf;
|
u8 *p_buf;
|
||||||
int counter;
|
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;
|
counter = CDNS_BPT_ROLLING_COUNTER_START;
|
||||||
p_data = (u32 *)dma_buffer;
|
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++) {
|
for (i = 0; i < num_frames; i++) {
|
||||||
header = *p_data++;
|
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);
|
ret = check_frame_start(header, counter);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(dev, "%s: bad frame %d/%d start header %x\n",
|
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;
|
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) {
|
if (crc != expected_crc) {
|
||||||
dev_err(dev, "%s: bad frame %d/%d crc %#x expected %#x\n",
|
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;
|
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);
|
ret = check_frame_end(footer);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(dev, "%s: bad frame %d/%d end footer %x\n",
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
counter++;
|
counter++;
|
||||||
counter &= GENMASK(3, 0);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
|
/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
|
||||||
/* Copyright(c) 2015-17 Intel Corporation. */
|
/* Copyright(c) 2015-17 Intel Corporation. */
|
||||||
#include <sound/soc.h>
|
#include <sound/soc.h>
|
||||||
|
#include "bus.h"
|
||||||
|
|
||||||
#ifndef __SDW_CADENCE_H
|
#ifndef __SDW_CADENCE_H
|
||||||
#define __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);
|
int sdw_cdns_config_update_set_wait(struct sdw_cdns *cdns);
|
||||||
|
|
||||||
/* SoundWire BPT/BRA helpers to format data */
|
/* 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 sdw_cdns_bpt_find_buffer_sizes(int command, /* 0: write, 1: read */
|
||||||
int row, int col, unsigned int data_bytes,
|
int row, int col, unsigned int data_bytes,
|
||||||
unsigned int requested_bytes_per_frame,
|
unsigned int requested_bytes_per_frame,
|
||||||
unsigned int *data_per_frame, unsigned int *pdi0_buffer_size,
|
unsigned int *data_per_frame, unsigned int *pdi0_buffer_size,
|
||||||
unsigned int *pdi1_buffer_size, unsigned int *num_frames);
|
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 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 data_per_frame, u8 *dma_buffer,
|
||||||
int *dma_buffer_total_bytes);
|
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 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 sdw_cdns_check_write_response(struct device *dev, u8 *dma_buffer,
|
||||||
int dma_buffer_size, int num_frames);
|
int dma_buffer_size, int num_frames);
|
||||||
|
|
||||||
int sdw_cdns_check_read_response(struct device *dev, u8 *dma_buffer, int dma_buffer_size,
|
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 */
|
#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)
|
static int do_bpt_sequence(struct sdw_slave *slave, bool write, u8 *buffer)
|
||||||
{
|
{
|
||||||
struct sdw_bpt_msg msg = {0};
|
struct sdw_bpt_msg msg = {0};
|
||||||
|
struct sdw_bpt_section *sec;
|
||||||
|
|
||||||
msg.addr = start_addr;
|
sec = kcalloc(1, sizeof(*sec), GFP_KERNEL);
|
||||||
msg.len = num_bytes;
|
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;
|
msg.dev_num = slave->dev_num;
|
||||||
if (write)
|
if (write)
|
||||||
msg.flags = SDW_MSG_FLAG_WRITE;
|
msg.flags = SDW_MSG_FLAG_WRITE;
|
||||||
else
|
else
|
||||||
msg.flags = SDW_MSG_FLAG_READ;
|
msg.flags = SDW_MSG_FLAG_READ;
|
||||||
msg.buf = buffer;
|
sec[0].buf = buffer;
|
||||||
|
|
||||||
return sdw_bpt_send_sync(slave->bus, slave, &msg);
|
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;
|
struct sdw_master_runtime *m_rt;
|
||||||
|
|
||||||
list_for_each_entry(m_rt, &bus->m_rt_list, bus_node) {
|
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_master_ports(m_rt);
|
||||||
sdw_compute_dp0_slave_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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define READ_PDI1_MIN_SIZE 12
|
||||||
|
|
||||||
static int intel_ace2x_bpt_open_stream(struct sdw_intel *sdw, struct sdw_slave *slave,
|
static int intel_ace2x_bpt_open_stream(struct sdw_intel *sdw, struct sdw_slave *slave,
|
||||||
struct sdw_bpt_msg *msg)
|
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_runtime *stream;
|
||||||
struct sdw_stream_config sconfig;
|
struct sdw_stream_config sconfig;
|
||||||
struct sdw_port_config *pconfig;
|
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 pdi0_buffer_size;
|
||||||
unsigned int tx_dma_bandwidth;
|
unsigned int tx_dma_bandwidth;
|
||||||
unsigned int pdi1_buffer_size;
|
unsigned int pdi1_buffer_size;
|
||||||
unsigned int rx_dma_bandwidth;
|
unsigned int rx_dma_bandwidth;
|
||||||
|
unsigned int fake_num_frames;
|
||||||
unsigned int data_per_frame;
|
unsigned int data_per_frame;
|
||||||
unsigned int tx_total_bytes;
|
unsigned int tx_total_bytes;
|
||||||
struct sdw_cdns_pdi *pdi0;
|
struct sdw_cdns_pdi *pdi0;
|
||||||
struct sdw_cdns_pdi *pdi1;
|
struct sdw_cdns_pdi *pdi1;
|
||||||
|
unsigned int rx_alignment;
|
||||||
|
unsigned int tx_alignment;
|
||||||
|
unsigned int num_frames_;
|
||||||
unsigned int num_frames;
|
unsigned int num_frames;
|
||||||
|
unsigned int fake_size;
|
||||||
|
unsigned int tx_pad;
|
||||||
|
unsigned int rx_pad;
|
||||||
int command;
|
int command;
|
||||||
int ret1;
|
int ret1;
|
||||||
int ret;
|
int ret;
|
||||||
int dir;
|
int dir;
|
||||||
|
int len;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
stream = sdw_alloc_stream("BPT", SDW_STREAM_BPT);
|
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;
|
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,
|
ret = sdw_cdns_bpt_find_bandwidth(command, cdns->bus.params.row,
|
||||||
msg->len, SDW_BPT_MSG_MAX_BYTES, &data_per_frame,
|
cdns->bus.params.col,
|
||||||
&pdi0_buffer_size, &pdi1_buffer_size, &num_frames);
|
prop->default_frame_rate,
|
||||||
|
&tx_dma_bandwidth, &rx_dma_bandwidth);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto deprepare_stream;
|
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.pdi0_buffer_size = pdi0_buffer_size;
|
||||||
sdw->bpt_ctx.pdi1_buffer_size = pdi1_buffer_size;
|
sdw->bpt_ctx.pdi1_buffer_size = pdi1_buffer_size;
|
||||||
sdw->bpt_ctx.num_frames = num_frames;
|
sdw->bpt_ctx.num_frames = num_frames;
|
||||||
sdw->bpt_ctx.data_per_frame = data_per_frame;
|
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_alignment = hda_sdw_bpt_get_buf_size_alignment(rx_dma_bandwidth);
|
||||||
rx_dma_bandwidth = div_u64((u64)pdi1_buffer_size * 8 * (u64)prop->default_frame_rate,
|
tx_alignment = hda_sdw_bpt_get_buf_size_alignment(tx_dma_bandwidth);
|
||||||
num_frames);
|
|
||||||
|
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",
|
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",
|
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);
|
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) {
|
if (!command) {
|
||||||
ret = sdw_cdns_prepare_write_dma_buffer(msg->dev_num, msg->addr, msg->buf,
|
ret = sdw_cdns_prepare_write_dma_buffer(msg->dev_num, msg->sec, msg->sections,
|
||||||
msg->len, data_per_frame,
|
data_per_frame,
|
||||||
sdw->bpt_ctx.dmab_tx_bdl.area,
|
sdw->bpt_ctx.dmab_tx_bdl.area,
|
||||||
pdi0_buffer_size, &tx_total_bytes);
|
pdi0_buffer_size, &tx_total_bytes);
|
||||||
} else {
|
} else {
|
||||||
ret = sdw_cdns_prepare_read_dma_buffer(msg->dev_num, msg->addr, msg->len,
|
ret = sdw_cdns_prepare_read_dma_buffer(msg->dev_num, msg->sec, msg->sections,
|
||||||
data_per_frame,
|
data_per_frame,
|
||||||
sdw->bpt_ctx.dmab_tx_bdl.area,
|
sdw->bpt_ctx.dmab_tx_bdl.area,
|
||||||
pdi0_buffer_size, &tx_total_bytes);
|
pdi0_buffer_size, &tx_total_bytes,
|
||||||
|
fake_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ret)
|
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_bpt_msg *msg)
|
||||||
{
|
{
|
||||||
struct sdw_cdns *cdns = &sdw->cdns;
|
struct sdw_cdns *cdns = &sdw->cdns;
|
||||||
|
int len = 0;
|
||||||
int ret;
|
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",
|
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;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -316,7 +390,7 @@ static int intel_ace2x_bpt_wait(struct sdw_intel *sdw, struct sdw_slave *slave,
|
||||||
} else {
|
} else {
|
||||||
ret = sdw_cdns_check_read_response(cdns->dev, sdw->bpt_ctx.dmab_rx_bdl.area,
|
ret = sdw_cdns_check_read_response(cdns->dev, sdw->bpt_ctx.dmab_rx_bdl.area,
|
||||||
sdw->bpt_ctx.pdi1_buffer_size,
|
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);
|
sdw->bpt_ctx.data_per_frame);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
dev_err(cdns->dev, "%s: BPT Read failed %d\n", __func__, ret);
|
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_5_1 0x01050001
|
||||||
#define SWRM_VERSION_1_7_0 0x01070000
|
#define SWRM_VERSION_1_7_0 0x01070000
|
||||||
#define SWRM_VERSION_2_0_0 0x02000000
|
#define SWRM_VERSION_2_0_0 0x02000000
|
||||||
|
#define SWRM_VERSION_3_1_0 0x03010000
|
||||||
#define SWRM_COMP_HW_VERSION 0x00
|
#define SWRM_COMP_HW_VERSION 0x00
|
||||||
#define SWRM_COMP_CFG_ADDR 0x04
|
#define SWRM_COMP_CFG_ADDR 0x04
|
||||||
#define SWRM_COMP_CFG_IRQ_LEVEL_OR_PULSE_MSK BIT(1)
|
#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_RD_FIFO_DEPTH GENMASK(19, 15)
|
||||||
#define SWRM_COMP_PARAMS_DOUT_PORTS_MASK GENMASK(4, 0)
|
#define SWRM_COMP_PARAMS_DOUT_PORTS_MASK GENMASK(4, 0)
|
||||||
#define SWRM_COMP_PARAMS_DIN_PORTS_MASK GENMASK(9, 5)
|
#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_COMP_MASTER_ID 0x104
|
||||||
#define SWRM_V1_3_INTERRUPT_STATUS 0x200
|
#define SWRM_V1_3_INTERRUPT_STATUS 0x200
|
||||||
#define SWRM_V2_0_INTERRUPT_STATUS 0x5000
|
#define SWRM_V2_0_INTERRUPT_STATUS 0x5000
|
||||||
|
|
@ -99,14 +103,15 @@
|
||||||
#define SWRM_MCP_SLV_STATUS 0x1090
|
#define SWRM_MCP_SLV_STATUS 0x1090
|
||||||
#define SWRM_MCP_SLV_STATUS_MASK GENMASK(1, 0)
|
#define SWRM_MCP_SLV_STATUS_MASK GENMASK(1, 0)
|
||||||
#define SWRM_MCP_SLV_STATUS_SZ 2
|
#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_DPn_PORT_CTRL_BANK(offset, n, m) (offset + 0x100 * (n - 1) + 0x40 * m)
|
||||||
#define SWRM_DP_BLOCK_CTRL_1(n) (0x112C + 0x100 * (n - 1))
|
#define SWRM_DPn_PORT_CTRL_2_BANK(offset, n, m) (offset + 0x100 * (n - 1) + 0x40 * m)
|
||||||
#define SWRM_DP_BLOCK_CTRL2_BANK(n, m) (0x1130 + 0x100 * (n - 1) + 0x40 * m)
|
#define SWRM_DPn_BLOCK_CTRL_1(offset, n) (offset + 0x100 * (n - 1))
|
||||||
#define SWRM_DP_PORT_HCTRL_BANK(n, m) (0x1134 + 0x100 * (n - 1) + 0x40 * m)
|
#define SWRM_DPn_BLOCK_CTRL2_BANK(offset, n, m) (offset + 0x100 * (n - 1) + 0x40 * m)
|
||||||
#define SWRM_DP_BLOCK_CTRL3_BANK(n, m) (0x1138 + 0x100 * (n - 1) + 0x40 * m)
|
#define SWRM_DPn_PORT_HCTRL_BANK(offset, n, m) (offset + 0x100 * (n - 1) + 0x40 * m)
|
||||||
#define SWRM_DP_SAMPLECTRL2_BANK(n, m) (0x113C + 0x100 * (n - 1) + 0x40 * m)
|
#define SWRM_DPn_BLOCK_CTRL3_BANK(offset, n, m) (offset + 0x100 * (n - 1) + 0x40 * m)
|
||||||
#define SWRM_DIN_DPn_PCM_PORT_CTRL(n) (0x1054 + 0x100 * (n - 1))
|
#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_V1_3_MSTR_MAX_REG_ADDR 0x1740
|
||||||
#define SWR_V2_0_MSTR_MAX_REG_ADDR 0x50ac
|
#define SWR_V2_0_MSTR_MAX_REG_ADDR 0x50ac
|
||||||
|
|
||||||
|
|
@ -128,7 +133,6 @@
|
||||||
#define MAX_FREQ_NUM 1
|
#define MAX_FREQ_NUM 1
|
||||||
#define TIMEOUT_MS 100
|
#define TIMEOUT_MS 100
|
||||||
#define QCOM_SWRM_MAX_RD_LEN 0x1
|
#define QCOM_SWRM_MAX_RD_LEN 0x1
|
||||||
#define QCOM_SDW_MAX_PORTS 14
|
|
||||||
#define DEFAULT_CLK_FREQ 9600000
|
#define DEFAULT_CLK_FREQ 9600000
|
||||||
#define SWRM_MAX_DAIS 0xF
|
#define SWRM_MAX_DAIS 0xF
|
||||||
#define SWR_INVALID_PARAM 0xFF
|
#define SWR_INVALID_PARAM 0xFF
|
||||||
|
|
@ -172,6 +176,13 @@ enum {
|
||||||
SWRM_REG_CMD_FIFO_RD_CMD,
|
SWRM_REG_CMD_FIFO_RD_CMD,
|
||||||
SWRM_REG_CMD_FIFO_STATUS,
|
SWRM_REG_CMD_FIFO_STATUS,
|
||||||
SWRM_REG_CMD_FIFO_RD_FIFO_ADDR,
|
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 {
|
struct qcom_swrm_ctrl {
|
||||||
|
|
@ -195,6 +206,7 @@ struct qcom_swrm_ctrl {
|
||||||
int wake_irq;
|
int wake_irq;
|
||||||
int num_din_ports;
|
int num_din_ports;
|
||||||
int num_dout_ports;
|
int num_dout_ports;
|
||||||
|
int nports;
|
||||||
int cols_index;
|
int cols_index;
|
||||||
int rows_index;
|
int rows_index;
|
||||||
unsigned long port_mask;
|
unsigned long port_mask;
|
||||||
|
|
@ -202,14 +214,13 @@ struct qcom_swrm_ctrl {
|
||||||
u8 rcmd_id;
|
u8 rcmd_id;
|
||||||
u8 wcmd_id;
|
u8 wcmd_id;
|
||||||
/* Port numbers are 1 - 14 */
|
/* 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];
|
struct sdw_stream_runtime *sruntime[SWRM_MAX_DAIS];
|
||||||
enum sdw_slave_status status[SDW_MAX_DEVICES + 1];
|
enum sdw_slave_status status[SDW_MAX_DEVICES + 1];
|
||||||
int (*reg_read)(struct qcom_swrm_ctrl *ctrl, int reg, u32 *val);
|
int (*reg_read)(struct qcom_swrm_ctrl *ctrl, int reg, u32 *val);
|
||||||
int (*reg_write)(struct qcom_swrm_ctrl *ctrl, int reg, int val);
|
int (*reg_write)(struct qcom_swrm_ctrl *ctrl, int reg, int val);
|
||||||
u32 slave_status;
|
u32 slave_status;
|
||||||
u32 wr_fifo_depth;
|
u32 wr_fifo_depth;
|
||||||
u32 rd_fifo_depth;
|
|
||||||
bool clock_stop_not_supported;
|
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_RD_CMD] = SWRM_V1_3_CMD_FIFO_RD_CMD,
|
||||||
[SWRM_REG_CMD_FIFO_STATUS] = SWRM_V1_3_CMD_FIFO_STATUS,
|
[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_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 = {
|
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_RD_CMD] = SWRM_V2_0_CMD_FIFO_RD_CMD,
|
||||||
[SWRM_REG_CMD_FIFO_STATUS] = SWRM_V2_0_CMD_FIFO_STATUS,
|
[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_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 = {
|
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,
|
.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)
|
#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,
|
static int qcom_swrm_ahb_reg_read(struct qcom_swrm_ctrl *ctrl, int reg,
|
||||||
|
|
@ -898,8 +949,11 @@ static int qcom_swrm_init(struct qcom_swrm_ctrl *ctrl)
|
||||||
swrm_wait_for_frame_gen_enabled(ctrl);
|
swrm_wait_for_frame_gen_enabled(ctrl);
|
||||||
ctrl->slave_status = 0;
|
ctrl->slave_status = 0;
|
||||||
ctrl->reg_read(ctrl, SWRM_COMP_PARAMS, &val);
|
ctrl->reg_read(ctrl, SWRM_COMP_PARAMS, &val);
|
||||||
ctrl->rd_fifo_depth = FIELD_GET(SWRM_COMP_PARAMS_RD_FIFO_DEPTH, val);
|
|
||||||
ctrl->wr_fifo_depth = FIELD_GET(SWRM_COMP_PARAMS_WR_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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -966,10 +1020,10 @@ static int qcom_swrm_port_params(struct sdw_bus *bus,
|
||||||
unsigned int bank)
|
unsigned int bank)
|
||||||
{
|
{
|
||||||
struct qcom_swrm_ctrl *ctrl = to_qcom_sdw(bus);
|
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);
|
p_params->bps - 1);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int qcom_swrm_transport_params(struct sdw_bus *bus,
|
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_ctrl *ctrl = to_qcom_sdw(bus);
|
||||||
struct qcom_swrm_port_config *pcfg;
|
struct qcom_swrm_port_config *pcfg;
|
||||||
u32 value;
|
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;
|
int ret;
|
||||||
|
|
||||||
|
reg = SWRM_DPn_PORT_CTRL_BANK(offset, params->port_num, bank);
|
||||||
|
|
||||||
pcfg = &ctrl->pconfig[params->port_num];
|
pcfg = &ctrl->pconfig[params->port_num];
|
||||||
|
|
||||||
value = pcfg->off1 << SWRM_DP_PORT_CTRL_OFFSET1_SHFT;
|
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;
|
goto err;
|
||||||
|
|
||||||
if (pcfg->si > 0xff) {
|
if (pcfg->si > 0xff) {
|
||||||
|
offset = ctrl->reg_layout[SWRM_OFFSET_DP_SAMPLECTRL2_BANK];
|
||||||
value = (pcfg->si >> 8) & 0xff;
|
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);
|
ret = ctrl->reg_write(ctrl, reg, value);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pcfg->lane_control != SWR_INVALID_PARAM) {
|
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;
|
value = pcfg->lane_control;
|
||||||
ret = ctrl->reg_write(ctrl, reg, value);
|
ret = ctrl->reg_write(ctrl, reg, value);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
|
@ -1009,20 +1069,23 @@ static int qcom_swrm_transport_params(struct sdw_bus *bus,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pcfg->blk_group_count != SWR_INVALID_PARAM) {
|
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;
|
value = pcfg->blk_group_count;
|
||||||
ret = ctrl->reg_write(ctrl, reg, value);
|
ret = ctrl->reg_write(ctrl, reg, value);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pcfg->hstart != SWR_INVALID_PARAM
|
offset = ctrl->reg_layout[SWRM_OFFSET_DP_PORT_HCTRL_BANK];
|
||||||
&& pcfg->hstop != SWR_INVALID_PARAM) {
|
reg = SWRM_DPn_PORT_HCTRL_BANK(offset, params->port_num, bank);
|
||||||
reg = SWRM_DP_PORT_HCTRL_BANK(params->port_num, bank);
|
|
||||||
|
if (pcfg->hstart != SWR_INVALID_PARAM && pcfg->hstop != SWR_INVALID_PARAM) {
|
||||||
value = (pcfg->hstop << 4) | pcfg->hstart;
|
value = (pcfg->hstop << 4) | pcfg->hstart;
|
||||||
ret = ctrl->reg_write(ctrl, reg, value);
|
ret = ctrl->reg_write(ctrl, reg, value);
|
||||||
} else {
|
} else {
|
||||||
reg = SWRM_DP_PORT_HCTRL_BANK(params->port_num, bank);
|
|
||||||
value = (SWR_HSTOP_MAX_VAL << 4) | SWR_HSTART_MIN_VAL;
|
value = (SWR_HSTOP_MAX_VAL << 4) | SWR_HSTART_MIN_VAL;
|
||||||
ret = ctrl->reg_write(ctrl, reg, value);
|
ret = ctrl->reg_write(ctrl, reg, value);
|
||||||
}
|
}
|
||||||
|
|
@ -1031,7 +1094,8 @@ static int qcom_swrm_transport_params(struct sdw_bus *bus,
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
if (pcfg->bp_mode != SWR_INVALID_PARAM) {
|
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);
|
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,
|
struct sdw_enable_ch *enable_ch,
|
||||||
unsigned int bank)
|
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);
|
struct qcom_swrm_ctrl *ctrl = to_qcom_sdw(bus);
|
||||||
u32 val;
|
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);
|
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,
|
struct snd_pcm_hw_params *params,
|
||||||
int direction)
|
int direction)
|
||||||
{
|
{
|
||||||
struct sdw_port_config pconfig[QCOM_SDW_MAX_PORTS];
|
|
||||||
struct sdw_stream_config sconfig;
|
struct sdw_stream_config sconfig;
|
||||||
struct sdw_master_runtime *m_rt;
|
struct sdw_master_runtime *m_rt;
|
||||||
struct sdw_slave_runtime *s_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;
|
unsigned long *port_mask;
|
||||||
int maxport, pn, nports = 0, ret = 0;
|
int maxport, pn, nports = 0, ret = 0;
|
||||||
unsigned int m_port;
|
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)
|
if (direction == SNDRV_PCM_STREAM_CAPTURE)
|
||||||
sconfig.direction = SDW_DATA_DIR_TX;
|
sconfig.direction = SDW_DATA_DIR_TX;
|
||||||
|
|
@ -1188,8 +1258,7 @@ static int qcom_swrm_stream_alloc_ports(struct qcom_swrm_ctrl *ctrl,
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
port_mask = &ctrl->port_mask;
|
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) {
|
list_for_each_entry(s_rt, &m_rt->slave_rt_list, m_rt_node) {
|
||||||
slave = s_rt->slave;
|
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)
|
static int qcom_swrm_get_port_config(struct qcom_swrm_ctrl *ctrl)
|
||||||
{
|
{
|
||||||
struct device_node *np = ctrl->dev->of_node;
|
struct device_node *np = ctrl->dev->of_node;
|
||||||
u8 off1[QCOM_SDW_MAX_PORTS];
|
struct qcom_swrm_port_config *pcfg;
|
||||||
u8 off2[QCOM_SDW_MAX_PORTS];
|
int i, ret, val;
|
||||||
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;
|
|
||||||
|
|
||||||
ctrl->reg_read(ctrl, SWRM_COMP_PARAMS, &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);
|
ctrl->num_din_ports = FIELD_GET(SWRM_COMP_PARAMS_DIN_PORTS_MASK, val);
|
||||||
|
|
||||||
ret = of_property_read_u32(np, "qcom,din-ports", &val);
|
ret = of_property_read_u32(np, "qcom,din-ports", &val);
|
||||||
if (ret)
|
if (!ret) { /* only if present */
|
||||||
return ret;
|
if (val != ctrl->num_din_ports) {
|
||||||
|
dev_err(ctrl->dev, "din-ports (%d) mismatch with controller (%d)",
|
||||||
|
val, ctrl->num_din_ports);
|
||||||
|
}
|
||||||
|
|
||||||
if (val > ctrl->num_din_ports)
|
ctrl->num_din_ports = val;
|
||||||
return -EINVAL;
|
}
|
||||||
|
|
||||||
ctrl->num_din_ports = val;
|
|
||||||
|
|
||||||
ret = of_property_read_u32(np, "qcom,dout-ports", &val);
|
ret = of_property_read_u32(np, "qcom,dout-ports", &val);
|
||||||
if (ret)
|
if (!ret) { /* only if present */
|
||||||
return ret;
|
if (val != ctrl->num_dout_ports) {
|
||||||
|
dev_err(ctrl->dev, "dout-ports (%d) mismatch with controller (%d)",
|
||||||
|
val, ctrl->num_dout_ports);
|
||||||
|
}
|
||||||
|
|
||||||
if (val > ctrl->num_dout_ports)
|
ctrl->num_dout_ports = val;
|
||||||
return -EINVAL;
|
}
|
||||||
|
|
||||||
ctrl->num_dout_ports = val;
|
ctrl->nports = ctrl->num_dout_ports + ctrl->num_din_ports;
|
||||||
|
|
||||||
nports = ctrl->num_dout_ports + ctrl->num_din_ports;
|
ctrl->pconfig = devm_kcalloc(ctrl->dev, ctrl->nports + 1,
|
||||||
if (nports > QCOM_SDW_MAX_PORTS)
|
sizeof(*ctrl->pconfig), GFP_KERNEL);
|
||||||
return -EINVAL;
|
if (!ctrl->pconfig)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
/* Valid port numbers are from 1-14, so mask out port 0 explicitly */
|
|
||||||
set_bit(0, &ctrl->port_mask);
|
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_array(np, "qcom,ports-offset1",
|
ret = of_property_read_u8_index(np, "qcom,ports-offset1", i, &pcfg->off1);
|
||||||
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)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
si_16 = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = of_property_read_u8_array(np, "qcom,ports-block-pack-mode",
|
ret = of_property_read_u8_index(np, "qcom,ports-offset2", i, &pcfg->off2);
|
||||||
bp_mode, nports);
|
if (ret)
|
||||||
if (ret) {
|
|
||||||
if (ctrl->version <= SWRM_VERSION_1_3_0)
|
|
||||||
memset(bp_mode, SWR_INVALID_PARAM, QCOM_SDW_MAX_PORTS);
|
|
||||||
else
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
|
||||||
|
|
||||||
memset(hstart, SWR_INVALID_PARAM, QCOM_SDW_MAX_PORTS);
|
ret = of_property_read_u8_index(np, "qcom,ports-sinterval-low", i, (u8 *)&pcfg->si);
|
||||||
of_property_read_u8_array(np, "qcom,ports-hstart", hstart, nports);
|
if (ret) {
|
||||||
|
ret = of_property_read_u16_index(np, "qcom,ports-sinterval", i, &pcfg->si);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
memset(hstop, SWR_INVALID_PARAM, QCOM_SDW_MAX_PORTS);
|
ret = of_property_read_u8_index(np, "qcom,ports-block-pack-mode",
|
||||||
of_property_read_u8_array(np, "qcom,ports-hstop", hstop, nports);
|
i, &pcfg->bp_mode);
|
||||||
|
if (ret) {
|
||||||
|
if (ctrl->version <= SWRM_VERSION_1_3_0)
|
||||||
|
pcfg->bp_mode = SWR_INVALID_PARAM;
|
||||||
|
else
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
memset(word_length, SWR_INVALID_PARAM, QCOM_SDW_MAX_PORTS);
|
/* Optional properties */
|
||||||
of_property_read_u8_array(np, "qcom,ports-word-length", word_length, nports);
|
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(blk_group_count, SWR_INVALID_PARAM, QCOM_SDW_MAX_PORTS);
|
of_property_read_u8_index(np, "qcom,ports-hstart", i, &pcfg->hstart);
|
||||||
of_property_read_u8_array(np, "qcom,ports-block-group-count", blk_group_count, nports);
|
|
||||||
|
|
||||||
memset(lane_control, SWR_INVALID_PARAM, QCOM_SDW_MAX_PORTS);
|
of_property_read_u8_index(np, "qcom,ports-hstop", i, &pcfg->hstop);
|
||||||
of_property_read_u8_array(np, "qcom,ports-lane-control", lane_control, nports);
|
|
||||||
|
|
||||||
for (i = 0; i < nports; i++) {
|
of_property_read_u8_index(np, "qcom,ports-word-length", i, &pcfg->word_length);
|
||||||
/* Valid port number range is from 1-14 */
|
|
||||||
if (si_16)
|
of_property_read_u8_index(np, "qcom,ports-block-group-count",
|
||||||
ctrl->pconfig[i + 1].si = si[i];
|
i, &pcfg->blk_group_count);
|
||||||
else
|
|
||||||
ctrl->pconfig[i + 1].si = ((u8 *)si)[i];
|
of_property_read_u8_index(np, "qcom,ports-lane-control", i, &pcfg->lane_control);
|
||||||
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];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
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.6.0", .data = &swrm_v1_6_data },
|
||||||
{ .compatible = "qcom,soundwire-v1.7.0", .data = &swrm_v1_5_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-v2.0.0", .data = &swrm_v2_0_data },
|
||||||
|
{ .compatible = "qcom,soundwire-v3.1.0", .data = &swrm_v3_0_data },
|
||||||
{/* sentinel */},
|
{/* 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 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,
|
extern int of_property_count_elems_of_size(const struct device_node *np,
|
||||||
const char *propname, int elem_size);
|
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,
|
extern int of_property_read_u16_index(const struct device_node *np,
|
||||||
const char *propname,
|
const char *propname,
|
||||||
u32 index, u16 *out_value);
|
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;
|
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,
|
static inline int of_property_read_u16_index(const struct device_node *np,
|
||||||
const char *propname, u32 index, u16 *out_value)
|
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,
|
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_tx_bdl, struct hdac_ext_stream *bpt_rx_stream,
|
||||||
struct snd_dma_buffer *dmab_rx_bdl);
|
struct snd_dma_buffer *dmab_rx_bdl);
|
||||||
|
|
||||||
|
unsigned int hda_sdw_bpt_get_buf_size_alignment(unsigned int dma_bandwidth);
|
||||||
#else
|
#else
|
||||||
static inline int hda_sdw_bpt_open(struct device *dev, int link_id,
|
static inline int hda_sdw_bpt_open(struct device *dev, int link_id,
|
||||||
struct hdac_ext_stream **bpt_tx_stream,
|
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");
|
WARN_ONCE(1, "SoundWire BPT is disabled");
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline unsigned int hda_sdw_bpt_get_buf_size_alignment(unsigned int dma_bandwidth)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* __HDA_SDW_BPT_H */
|
#endif /* __HDA_SDW_BPT_H */
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
* Hardware interface for SoundWire BPT support with HDA DMA
|
* Hardware interface for SoundWire BPT support with HDA DMA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <linux/lcm.h>
|
||||||
#include <sound/hdaudio_ext.h>
|
#include <sound/hdaudio_ext.h>
|
||||||
#include <sound/hda-mlink.h>
|
#include <sound/hda-mlink.h>
|
||||||
#include <sound/hda-sdw-bpt.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;
|
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,
|
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,
|
struct snd_dma_buffer *dmab_tx_bdl, u32 bpt_tx_num_bytes,
|
||||||
u32 tx_dma_bandwidth, struct hdac_ext_stream **bpt_rx_stream,
|
u32 tx_dma_bandwidth, struct hdac_ext_stream **bpt_rx_stream,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue