mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 06:01:57 +00:00
soundwire updates for 6.11
- Simplification across subsystem using cleanup.h - Support for debugfs to read/write commands - Few Intel and Qualcomm driver updates -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEE+vs47OPLdNbVcHzyfBQHDyUjg0cFAmagr0MACgkQfBQHDyUj g0cglxAAsf0vto3EdhyJf0fU257phqu87DDQ/iWLjRMZ+wZuVsLgSEEWMI+uVU/j 3nvWxPc0o95Jo6424GVIAKZO5FenqFvPPcj1IEpAtnuQddx21dKeW8RT+Ft4N/rg c5cODKCC5RbrcVBBR0Zvw4e/y+RKOBlW/oIGhNoiVcKmPuqVzeVt7GMJiut5cXOE 8t58q24oFq6ZWAAmQJLvlgf01a0vis9fWvnFL2Ylf7iv9FfLClv5LIye6HLtSOqp 6FEV3G90qjlzxcA4vt2lTpIDxyaTHQuW9YTqlq9if2fnEPulMrQnbTqtfw1cM7OC gvjcVh70n45Vq6GpRipwnVj1bRc3vdXw+Qi78hu9X81Yo4JS1EnbmJDWFU1G7C9w HDe8ywClheUAPCrmwfYx/Xsmcx2ut1QUBo90TCgzFVIpvXvlGyE/goV7XhhPImSN FywpBr/6F3Etv9Z9nH45sUgv6dNf4J/71lGutA8XFHYy9s8oK3tyKDoskq89ymg4 jQP9kQ8X97yVUznscQqYXb4zTJ6SAO0MOMpfGZltv7qI96/pnX7ijPOsaW7UGnpX ImI0iIfVbGQ3r6lTWf9+GJaR2XMXznfpDPKLFmwxopeGQwUBnHV75pSPgIeKVtb8 OF4427Hq/1yrDuyXbdQAOvyi/em+xYQGfL761grgWEdN8LyJn5Q= =FNSV -----END PGP SIGNATURE----- Merge tag 'soundwire-6.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/soundwire Pull soundwire updates from Vinod Koul: - Simplification across subsystem using cleanup.h - Support for debugfs to read/write commands - Few Intel and Qualcomm driver updates * tag 'soundwire-6.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/soundwire: soundwire: debugfs: simplify with cleanup.h soundwire: cadence: simplify with cleanup.h soundwire: intel_ace2x: simplify with cleanup.h soundwire: intel_ace2x: simplify return path in hw_params soundwire: intel: simplify with cleanup.h soundwire: intel: simplify return path in hw_params soundwire: amd_init: simplify with cleanup.h soundwire: amd: simplify with cleanup.h soundwire: amd: simplify return path in hw_params soundwire: intel_auxdevice: start the bus at default frequency soundwire: intel_auxdevice: add cs42l43 codec to wake_capable_list drivers:soundwire: qcom: cleanup port maask calculations soundwire: bus: simplify by using local slave->prop soundwire: generic_bandwidth_allocation: change port_bo parameter to pointer soundwire: Intel: clarify Copyright information soundwire: intel_ace2.x: add AC timing extensions for PantherLake soundwire: bus: add stream refcount soundwire: debugfs: add interface to read/write commands
This commit is contained in:
commit
ad7b0b7b87
@ -8,6 +8,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/cleanup.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
@ -69,7 +70,6 @@ static struct sdw_amd_ctx *sdw_amd_probe_controller(struct sdw_amd_res *res)
|
||||
{
|
||||
struct sdw_amd_ctx *ctx;
|
||||
struct acpi_device *adev;
|
||||
struct resource *sdw_res;
|
||||
struct acp_sdw_pdata sdw_pdata[2];
|
||||
struct platform_device_info pdevinfo[2];
|
||||
u32 link_mask;
|
||||
@ -104,7 +104,8 @@ static struct sdw_amd_ctx *sdw_amd_probe_controller(struct sdw_amd_res *res)
|
||||
|
||||
ctx->count = count;
|
||||
ctx->link_mask = res->link_mask;
|
||||
sdw_res = kzalloc(sizeof(*sdw_res), GFP_KERNEL);
|
||||
struct resource *sdw_res __free(kfree) = kzalloc(sizeof(*sdw_res),
|
||||
GFP_KERNEL);
|
||||
if (!sdw_res) {
|
||||
kfree(ctx);
|
||||
return NULL;
|
||||
@ -132,7 +133,6 @@ static struct sdw_amd_ctx *sdw_amd_probe_controller(struct sdw_amd_res *res)
|
||||
if (IS_ERR(ctx->pdev[index]))
|
||||
goto err;
|
||||
}
|
||||
kfree(sdw_res);
|
||||
return ctx;
|
||||
err:
|
||||
while (index--) {
|
||||
@ -142,7 +142,6 @@ err:
|
||||
platform_device_unregister(ctx->pdev[index]);
|
||||
}
|
||||
|
||||
kfree(sdw_res);
|
||||
kfree(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -6,6 +6,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/completion.h>
|
||||
#include <linux/cleanup.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/jiffies.h>
|
||||
@ -603,7 +604,6 @@ static int amd_sdw_hw_params(struct snd_pcm_substream *substream,
|
||||
struct amd_sdw_manager *amd_manager = snd_soc_dai_get_drvdata(dai);
|
||||
struct sdw_amd_dai_runtime *dai_runtime;
|
||||
struct sdw_stream_config sconfig;
|
||||
struct sdw_port_config *pconfig;
|
||||
int ch, dir;
|
||||
int ret;
|
||||
|
||||
@ -626,11 +626,10 @@ static int amd_sdw_hw_params(struct snd_pcm_substream *substream,
|
||||
sconfig.bps = snd_pcm_format_width(params_format(params));
|
||||
|
||||
/* Port configuration */
|
||||
pconfig = kzalloc(sizeof(*pconfig), GFP_KERNEL);
|
||||
if (!pconfig) {
|
||||
ret = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
struct sdw_port_config *pconfig __free(kfree) = kzalloc(sizeof(*pconfig),
|
||||
GFP_KERNEL);
|
||||
if (!pconfig)
|
||||
return -ENOMEM;
|
||||
|
||||
pconfig->num = dai->id;
|
||||
pconfig->ch_mask = (1 << ch) - 1;
|
||||
@ -639,8 +638,6 @@ static int amd_sdw_hw_params(struct snd_pcm_substream *substream,
|
||||
if (ret)
|
||||
dev_err(amd_manager->dev, "add manager to stream failed:%d\n", ret);
|
||||
|
||||
kfree(pconfig);
|
||||
error:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1410,7 +1410,7 @@ static int sdw_initialize_slave(struct sdw_slave *slave)
|
||||
}
|
||||
}
|
||||
if ((slave->bus->prop.quirks & SDW_MASTER_QUIRKS_CLEAR_INITIAL_PARITY) &&
|
||||
!(slave->prop.quirks & SDW_SLAVE_QUIRKS_INVALID_INITIAL_PARITY)) {
|
||||
!(prop->quirks & SDW_SLAVE_QUIRKS_INVALID_INITIAL_PARITY)) {
|
||||
/* Clear parity interrupt before enabling interrupt mask */
|
||||
status = sdw_read_no_pm(slave, SDW_SCP_INT1);
|
||||
if (status < 0) {
|
||||
@ -1436,7 +1436,7 @@ static int sdw_initialize_slave(struct sdw_slave *slave)
|
||||
* device-dependent, it might e.g. only be enabled in
|
||||
* steady-state after a couple of frames.
|
||||
*/
|
||||
val = slave->prop.scp_int1_mask;
|
||||
val = prop->scp_int1_mask;
|
||||
|
||||
/* Enable SCP interrupts */
|
||||
ret = sdw_update_no_pm(slave, SDW_SCP_INTMASK1, val, val);
|
||||
@ -1447,7 +1447,7 @@ static int sdw_initialize_slave(struct sdw_slave *slave)
|
||||
}
|
||||
|
||||
/* No need to continue if DP0 is not present */
|
||||
if (!slave->prop.dp0_prop)
|
||||
if (!prop->dp0_prop)
|
||||
return 0;
|
||||
|
||||
/* Enable DP0 interrupts */
|
||||
|
@ -6,6 +6,7 @@
|
||||
* Used by Master driver
|
||||
*/
|
||||
|
||||
#include <linux/cleanup.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/debugfs.h>
|
||||
@ -323,12 +324,11 @@ static ssize_t cdns_sprintf(struct sdw_cdns *cdns,
|
||||
static int cdns_reg_show(struct seq_file *s, void *data)
|
||||
{
|
||||
struct sdw_cdns *cdns = s->private;
|
||||
char *buf;
|
||||
ssize_t ret;
|
||||
int num_ports;
|
||||
int i, j;
|
||||
|
||||
buf = kzalloc(RD_BUF, GFP_KERNEL);
|
||||
char *buf __free(kfree) = kzalloc(RD_BUF, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -389,7 +389,6 @@ static int cdns_reg_show(struct seq_file *s, void *data)
|
||||
ret += cdns_sprintf(cdns, buf, ret, CDNS_PDI_CONFIG(i));
|
||||
|
||||
seq_printf(s, "%s", buf);
|
||||
kfree(buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,8 +1,10 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
// Copyright(c) 2017-2019 Intel Corporation.
|
||||
|
||||
#include <linux/cleanup.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/slab.h>
|
||||
@ -48,18 +50,16 @@ static ssize_t sdw_sprintf(struct sdw_slave *slave,
|
||||
static int sdw_slave_reg_show(struct seq_file *s_file, void *data)
|
||||
{
|
||||
struct sdw_slave *slave = s_file->private;
|
||||
char *buf;
|
||||
ssize_t ret;
|
||||
int i, j;
|
||||
|
||||
buf = kzalloc(RD_BUF, GFP_KERNEL);
|
||||
char *buf __free(kfree) = kzalloc(RD_BUF, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = pm_runtime_get_sync(&slave->dev);
|
||||
if (ret < 0 && ret != -EACCES) {
|
||||
pm_runtime_put_noidle(&slave->dev);
|
||||
kfree(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -131,12 +131,149 @@ static int sdw_slave_reg_show(struct seq_file *s_file, void *data)
|
||||
pm_runtime_mark_last_busy(&slave->dev);
|
||||
pm_runtime_put(&slave->dev);
|
||||
|
||||
kfree(buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
DEFINE_SHOW_ATTRIBUTE(sdw_slave_reg);
|
||||
|
||||
#define MAX_CMD_BYTES 256
|
||||
|
||||
static int cmd;
|
||||
static u32 start_addr;
|
||||
static size_t num_bytes;
|
||||
static u8 read_buffer[MAX_CMD_BYTES];
|
||||
static char *firmware_file;
|
||||
|
||||
static int set_command(void *data, u64 value)
|
||||
{
|
||||
struct sdw_slave *slave = data;
|
||||
|
||||
if (value > 1)
|
||||
return -EINVAL;
|
||||
|
||||
/* Userspace changed the hardware state behind the kernel's back */
|
||||
add_taint(TAINT_USER, LOCKDEP_STILL_OK);
|
||||
|
||||
dev_dbg(&slave->dev, "command: %s\n", value ? "read" : "write");
|
||||
cmd = value;
|
||||
|
||||
return 0;
|
||||
}
|
||||
DEFINE_DEBUGFS_ATTRIBUTE(set_command_fops, NULL,
|
||||
set_command, "%llu\n");
|
||||
|
||||
static int set_start_address(void *data, u64 value)
|
||||
{
|
||||
struct sdw_slave *slave = data;
|
||||
|
||||
/* Userspace changed the hardware state behind the kernel's back */
|
||||
add_taint(TAINT_USER, LOCKDEP_STILL_OK);
|
||||
|
||||
dev_dbg(&slave->dev, "start address %#llx\n", value);
|
||||
|
||||
start_addr = value;
|
||||
|
||||
return 0;
|
||||
}
|
||||
DEFINE_DEBUGFS_ATTRIBUTE(set_start_address_fops, NULL,
|
||||
set_start_address, "%llu\n");
|
||||
|
||||
static int set_num_bytes(void *data, u64 value)
|
||||
{
|
||||
struct sdw_slave *slave = data;
|
||||
|
||||
if (value == 0 || value > MAX_CMD_BYTES)
|
||||
return -EINVAL;
|
||||
|
||||
/* Userspace changed the hardware state behind the kernel's back */
|
||||
add_taint(TAINT_USER, LOCKDEP_STILL_OK);
|
||||
|
||||
dev_dbg(&slave->dev, "number of bytes %lld\n", value);
|
||||
|
||||
num_bytes = value;
|
||||
|
||||
return 0;
|
||||
}
|
||||
DEFINE_DEBUGFS_ATTRIBUTE(set_num_bytes_fops, NULL,
|
||||
set_num_bytes, "%llu\n");
|
||||
|
||||
static int cmd_go(void *data, u64 value)
|
||||
{
|
||||
struct sdw_slave *slave = data;
|
||||
int ret;
|
||||
|
||||
if (value != 1)
|
||||
return -EINVAL;
|
||||
|
||||
/* one last check */
|
||||
if (start_addr > SDW_REG_MAX ||
|
||||
num_bytes == 0 || num_bytes > MAX_CMD_BYTES)
|
||||
return -EINVAL;
|
||||
|
||||
ret = pm_runtime_get_sync(&slave->dev);
|
||||
if (ret < 0 && ret != -EACCES) {
|
||||
pm_runtime_put_noidle(&slave->dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Userspace changed the hardware state behind the kernel's back */
|
||||
add_taint(TAINT_USER, LOCKDEP_STILL_OK);
|
||||
|
||||
dev_dbg(&slave->dev, "starting command\n");
|
||||
|
||||
if (cmd == 0) {
|
||||
const struct firmware *fw;
|
||||
|
||||
ret = request_firmware(&fw, firmware_file, &slave->dev);
|
||||
if (ret < 0) {
|
||||
dev_err(&slave->dev, "firmware %s not found\n", firmware_file);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (fw->size != num_bytes) {
|
||||
dev_err(&slave->dev,
|
||||
"firmware %s: unexpected size %zd, desired %zd\n",
|
||||
firmware_file, fw->size, num_bytes);
|
||||
release_firmware(fw);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = sdw_nwrite_no_pm(slave, start_addr, num_bytes, fw->data);
|
||||
release_firmware(fw);
|
||||
} else {
|
||||
ret = sdw_nread_no_pm(slave, start_addr, num_bytes, read_buffer);
|
||||
}
|
||||
|
||||
dev_dbg(&slave->dev, "command completed %d\n", ret);
|
||||
|
||||
out:
|
||||
pm_runtime_mark_last_busy(&slave->dev);
|
||||
pm_runtime_put(&slave->dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
DEFINE_DEBUGFS_ATTRIBUTE(cmd_go_fops, NULL,
|
||||
cmd_go, "%llu\n");
|
||||
|
||||
#define MAX_LINE_LEN 128
|
||||
|
||||
static int read_buffer_show(struct seq_file *s_file, void *data)
|
||||
{
|
||||
char buf[MAX_LINE_LEN];
|
||||
int i;
|
||||
|
||||
if (num_bytes == 0 || num_bytes > MAX_CMD_BYTES)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < num_bytes; i++) {
|
||||
scnprintf(buf, MAX_LINE_LEN, "address %#x val 0x%02x\n",
|
||||
start_addr + i, read_buffer[i]);
|
||||
seq_printf(s_file, "%s", buf);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
DEFINE_SHOW_ATTRIBUTE(read_buffer);
|
||||
|
||||
void sdw_slave_debugfs_init(struct sdw_slave *slave)
|
||||
{
|
||||
struct dentry *master;
|
||||
@ -151,6 +288,16 @@ void sdw_slave_debugfs_init(struct sdw_slave *slave)
|
||||
|
||||
debugfs_create_file("registers", 0400, d, slave, &sdw_slave_reg_fops);
|
||||
|
||||
/* interface to send arbitrary commands */
|
||||
debugfs_create_file("command", 0200, d, slave, &set_command_fops);
|
||||
debugfs_create_file("start_address", 0200, d, slave, &set_start_address_fops);
|
||||
debugfs_create_file("num_bytes", 0200, d, slave, &set_num_bytes_fops);
|
||||
debugfs_create_file("go", 0200, d, slave, &cmd_go_fops);
|
||||
|
||||
debugfs_create_file("read_buffer", 0400, d, slave, &read_buffer_fops);
|
||||
firmware_file = NULL;
|
||||
debugfs_create_str("firmware_file", 0200, d, &firmware_file);
|
||||
|
||||
slave->debugfs = d;
|
||||
}
|
||||
|
||||
|
@ -83,7 +83,7 @@ EXPORT_SYMBOL(sdw_compute_slave_ports);
|
||||
|
||||
static void sdw_compute_master_ports(struct sdw_master_runtime *m_rt,
|
||||
struct sdw_group_params *params,
|
||||
int port_bo, int hstop)
|
||||
int *port_bo, int hstop)
|
||||
{
|
||||
struct sdw_transport_data t_data = {0};
|
||||
struct sdw_port_runtime *p_rt;
|
||||
@ -108,7 +108,7 @@ static void sdw_compute_master_ports(struct sdw_master_runtime *m_rt,
|
||||
|
||||
sdw_fill_xport_params(&p_rt->transport_params, p_rt->num,
|
||||
false, SDW_BLK_GRP_CNT_1, sample_int,
|
||||
port_bo, port_bo >> 8, hstart, hstop,
|
||||
*port_bo, (*port_bo) >> 8, hstart, hstop,
|
||||
SDW_BLK_PKG_PER_PORT, 0x0);
|
||||
|
||||
sdw_fill_port_params(&p_rt->port_params,
|
||||
@ -120,15 +120,15 @@ static void sdw_compute_master_ports(struct sdw_master_runtime *m_rt,
|
||||
if (!(p_rt == list_first_entry(&m_rt->port_list,
|
||||
struct sdw_port_runtime,
|
||||
port_node))) {
|
||||
port_bo += bps * ch;
|
||||
(*port_bo) += bps * ch;
|
||||
continue;
|
||||
}
|
||||
|
||||
t_data.hstart = hstart;
|
||||
t_data.hstop = hstop;
|
||||
t_data.block_offset = port_bo;
|
||||
t_data.block_offset = *port_bo;
|
||||
t_data.sub_block_offset = 0;
|
||||
port_bo += bps * ch;
|
||||
(*port_bo) += bps * ch;
|
||||
}
|
||||
|
||||
sdw_compute_slave_ports(m_rt, &t_data);
|
||||
@ -146,9 +146,7 @@ static void _sdw_compute_port_params(struct sdw_bus *bus,
|
||||
port_bo = 1;
|
||||
|
||||
list_for_each_entry(m_rt, &bus->m_rt_list, bus_node) {
|
||||
sdw_compute_master_ports(m_rt, ¶ms[i], port_bo, hstop);
|
||||
|
||||
port_bo += m_rt->ch_count * m_rt->stream->params.bps;
|
||||
sdw_compute_master_ports(m_rt, ¶ms[i], &port_bo, hstop);
|
||||
}
|
||||
|
||||
hstop = hstop - params[i].hwidth;
|
||||
|
@ -6,6 +6,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/cleanup.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
@ -73,12 +74,11 @@ static int intel_reg_show(struct seq_file *s_file, void *data)
|
||||
struct sdw_intel *sdw = s_file->private;
|
||||
void __iomem *s = sdw->link_res->shim;
|
||||
void __iomem *a = sdw->link_res->alh;
|
||||
char *buf;
|
||||
ssize_t ret;
|
||||
int i, j;
|
||||
unsigned int links, reg;
|
||||
|
||||
buf = kzalloc(RD_BUF, GFP_KERNEL);
|
||||
char *buf __free(kfree) = kzalloc(RD_BUF, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -129,7 +129,6 @@ static int intel_reg_show(struct seq_file *s_file, void *data)
|
||||
ret += intel_sprintf(a, true, buf, ret, SDW_ALH_STRMZCFG(i));
|
||||
|
||||
seq_printf(s_file, "%s", buf);
|
||||
kfree(buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -727,7 +726,6 @@ static int intel_hw_params(struct snd_pcm_substream *substream,
|
||||
struct sdw_cdns_dai_runtime *dai_runtime;
|
||||
struct sdw_cdns_pdi *pdi;
|
||||
struct sdw_stream_config sconfig;
|
||||
struct sdw_port_config *pconfig;
|
||||
int ch, dir;
|
||||
int ret;
|
||||
|
||||
@ -743,10 +741,8 @@ static int intel_hw_params(struct snd_pcm_substream *substream,
|
||||
|
||||
pdi = sdw_cdns_alloc_pdi(cdns, &cdns->pcm, ch, dir, dai->id);
|
||||
|
||||
if (!pdi) {
|
||||
ret = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
if (!pdi)
|
||||
return -EINVAL;
|
||||
|
||||
/* do run-time configurations for SHIM, ALH and PDI/PORT */
|
||||
intel_pdi_shim_configure(sdw, pdi);
|
||||
@ -763,7 +759,7 @@ static int intel_hw_params(struct snd_pcm_substream *substream,
|
||||
sdw->instance,
|
||||
pdi->intel_alh_id);
|
||||
if (ret)
|
||||
goto error;
|
||||
return ret;
|
||||
|
||||
sconfig.direction = dir;
|
||||
sconfig.ch_count = ch;
|
||||
@ -773,11 +769,10 @@ static int intel_hw_params(struct snd_pcm_substream *substream,
|
||||
sconfig.bps = snd_pcm_format_width(params_format(params));
|
||||
|
||||
/* Port configuration */
|
||||
pconfig = kzalloc(sizeof(*pconfig), GFP_KERNEL);
|
||||
if (!pconfig) {
|
||||
ret = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
struct sdw_port_config *pconfig __free(kfree) = kzalloc(sizeof(*pconfig),
|
||||
GFP_KERNEL);
|
||||
if (!pconfig)
|
||||
return -ENOMEM;
|
||||
|
||||
pconfig->num = pdi->num;
|
||||
pconfig->ch_mask = (1 << ch) - 1;
|
||||
@ -787,8 +782,6 @@ static int intel_hw_params(struct snd_pcm_substream *substream,
|
||||
if (ret)
|
||||
dev_err(cdns->dev, "add master to stream failed:%d\n", ret);
|
||||
|
||||
kfree(pconfig);
|
||||
error:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -59,6 +59,11 @@ struct sdw_intel {
|
||||
};
|
||||
|
||||
struct sdw_intel_prop {
|
||||
u16 clde;
|
||||
u16 doaise2;
|
||||
u16 dodse2;
|
||||
u16 clds;
|
||||
u16 clss;
|
||||
u16 doaise;
|
||||
u16 doais;
|
||||
u16 dodse;
|
||||
|
@ -1,11 +1,12 @@
|
||||
// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
|
||||
// Copyright(c) 2023 Intel Corporation. All rights reserved.
|
||||
// Copyright(c) 2023 Intel Corporation
|
||||
|
||||
/*
|
||||
* Soundwire Intel ops for LunarLake
|
||||
*/
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/cleanup.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/soundwire/sdw_registers.h>
|
||||
#include <linux/soundwire/sdw.h>
|
||||
@ -27,6 +28,11 @@ static void intel_shim_vs_init(struct sdw_intel *sdw)
|
||||
void __iomem *shim_vs = sdw->link_res->shim_vs;
|
||||
struct sdw_bus *bus = &sdw->cdns.bus;
|
||||
struct sdw_intel_prop *intel_prop;
|
||||
u16 clde;
|
||||
u16 doaise2;
|
||||
u16 dodse2;
|
||||
u16 clds;
|
||||
u16 clss;
|
||||
u16 doaise;
|
||||
u16 doais;
|
||||
u16 dodse;
|
||||
@ -34,12 +40,22 @@ static void intel_shim_vs_init(struct sdw_intel *sdw)
|
||||
u16 act;
|
||||
|
||||
intel_prop = bus->vendor_specific_prop;
|
||||
clde = intel_prop->clde;
|
||||
doaise2 = intel_prop->doaise2;
|
||||
dodse2 = intel_prop->dodse2;
|
||||
clds = intel_prop->clds;
|
||||
clss = intel_prop->clss;
|
||||
doaise = intel_prop->doaise;
|
||||
doais = intel_prop->doais;
|
||||
dodse = intel_prop->dodse;
|
||||
dods = intel_prop->dods;
|
||||
|
||||
act = intel_readw(shim_vs, SDW_SHIM2_INTEL_VS_ACTMCTL);
|
||||
u16p_replace_bits(&act, clde, SDW_SHIM3_INTEL_VS_ACTMCTL_CLDE);
|
||||
u16p_replace_bits(&act, doaise2, SDW_SHIM3_INTEL_VS_ACTMCTL_DOAISE2);
|
||||
u16p_replace_bits(&act, dodse2, SDW_SHIM3_INTEL_VS_ACTMCTL_DODSE2);
|
||||
u16p_replace_bits(&act, clds, SDW_SHIM3_INTEL_VS_ACTMCTL_CLDS);
|
||||
u16p_replace_bits(&act, clss, SDW_SHIM3_INTEL_VS_ACTMCTL_CLSS);
|
||||
u16p_replace_bits(&act, doaise, SDW_SHIM2_INTEL_VS_ACTMCTL_DOAISE);
|
||||
u16p_replace_bits(&act, doais, SDW_SHIM2_INTEL_VS_ACTMCTL_DOAIS);
|
||||
u16p_replace_bits(&act, dodse, SDW_SHIM2_INTEL_VS_ACTMCTL_DODSE);
|
||||
@ -295,7 +311,6 @@ static int intel_hw_params(struct snd_pcm_substream *substream,
|
||||
struct sdw_cdns_dai_runtime *dai_runtime;
|
||||
struct sdw_cdns_pdi *pdi;
|
||||
struct sdw_stream_config sconfig;
|
||||
struct sdw_port_config *pconfig;
|
||||
int ch, dir;
|
||||
int ret;
|
||||
|
||||
@ -310,11 +325,8 @@ static int intel_hw_params(struct snd_pcm_substream *substream,
|
||||
dir = SDW_DATA_DIR_TX;
|
||||
|
||||
pdi = sdw_cdns_alloc_pdi(cdns, &cdns->pcm, ch, dir, dai->id);
|
||||
|
||||
if (!pdi) {
|
||||
ret = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
if (!pdi)
|
||||
return -EINVAL;
|
||||
|
||||
/* use same definitions for alh_id as previous generations */
|
||||
pdi->intel_alh_id = (sdw->instance * 16) + pdi->num + 3;
|
||||
@ -335,7 +347,7 @@ static int intel_hw_params(struct snd_pcm_substream *substream,
|
||||
sdw->instance,
|
||||
pdi->intel_alh_id);
|
||||
if (ret)
|
||||
goto error;
|
||||
return ret;
|
||||
|
||||
sconfig.direction = dir;
|
||||
sconfig.ch_count = ch;
|
||||
@ -345,11 +357,10 @@ static int intel_hw_params(struct snd_pcm_substream *substream,
|
||||
sconfig.bps = snd_pcm_format_width(params_format(params));
|
||||
|
||||
/* Port configuration */
|
||||
pconfig = kzalloc(sizeof(*pconfig), GFP_KERNEL);
|
||||
if (!pconfig) {
|
||||
ret = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
struct sdw_port_config *pconfig __free(kfree) = kzalloc(sizeof(*pconfig),
|
||||
GFP_KERNEL);
|
||||
if (!pconfig)
|
||||
return -ENOMEM;
|
||||
|
||||
pconfig->num = pdi->num;
|
||||
pconfig->ch_mask = (1 << ch) - 1;
|
||||
@ -359,8 +370,6 @@ static int intel_hw_params(struct snd_pcm_substream *substream,
|
||||
if (ret)
|
||||
dev_err(cdns->dev, "add master to stream failed:%d\n", ret);
|
||||
|
||||
kfree(pconfig);
|
||||
error:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
// Copyright(c) 2023 Intel Corporation. All rights reserved.
|
||||
// Copyright(c) 2023 Intel Corporation
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/debugfs.h>
|
||||
|
@ -47,6 +47,7 @@ struct wake_capable_part {
|
||||
};
|
||||
|
||||
static struct wake_capable_part wake_capable_list[] = {
|
||||
{0x01fa, 0x4243},
|
||||
{0x025d, 0x5682},
|
||||
{0x025d, 0x700},
|
||||
{0x025d, 0x711},
|
||||
@ -161,11 +162,31 @@ static int sdw_master_read_intel_prop(struct sdw_bus *bus)
|
||||
}
|
||||
|
||||
/* initialize with hardware defaults, in case the properties are not found */
|
||||
intel_prop->clde = 0x0;
|
||||
intel_prop->doaise2 = 0x0;
|
||||
intel_prop->dodse2 = 0x0;
|
||||
intel_prop->clds = 0x0;
|
||||
intel_prop->clss = 0x0;
|
||||
intel_prop->doaise = 0x1;
|
||||
intel_prop->doais = 0x3;
|
||||
intel_prop->dodse = 0x0;
|
||||
intel_prop->dods = 0x1;
|
||||
|
||||
fwnode_property_read_u16(link,
|
||||
"intel-sdw-clde",
|
||||
&intel_prop->clde);
|
||||
fwnode_property_read_u16(link,
|
||||
"intel-sdw-doaise2",
|
||||
&intel_prop->doaise2);
|
||||
fwnode_property_read_u16(link,
|
||||
"intel-sdw-dodse2",
|
||||
&intel_prop->dodse2);
|
||||
fwnode_property_read_u16(link,
|
||||
"intel-sdw-clds",
|
||||
&intel_prop->clds);
|
||||
fwnode_property_read_u16(link,
|
||||
"intel-sdw-clss",
|
||||
&intel_prop->clss);
|
||||
fwnode_property_read_u16(link,
|
||||
"intel-sdw-doaise",
|
||||
&intel_prop->doaise);
|
||||
@ -193,9 +214,30 @@ static int sdw_master_read_intel_prop(struct sdw_bus *bus)
|
||||
|
||||
static int intel_prop_read(struct sdw_bus *bus)
|
||||
{
|
||||
struct sdw_master_prop *prop;
|
||||
|
||||
/* Initialize with default handler to read all DisCo properties */
|
||||
sdw_master_read_prop(bus);
|
||||
|
||||
/*
|
||||
* Only one bus frequency is supported so far, filter
|
||||
* frequencies reported in the DSDT
|
||||
*/
|
||||
prop = &bus->prop;
|
||||
if (prop->clk_freq && prop->num_clk_freq > 1) {
|
||||
unsigned int default_bus_frequency;
|
||||
|
||||
default_bus_frequency =
|
||||
prop->default_frame_rate *
|
||||
prop->default_row *
|
||||
prop->default_col /
|
||||
SDW_DOUBLE_RATE_FACTOR;
|
||||
|
||||
prop->num_clk_freq = 1;
|
||||
prop->clk_freq[0] = default_bus_frequency;
|
||||
prop->max_clk_freq = default_bus_frequency;
|
||||
}
|
||||
|
||||
/* read Intel-specific properties */
|
||||
sdw_master_read_intel_prop(bus);
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
|
||||
// Copyright(c) 2015-2023 Intel Corporation. All rights reserved.
|
||||
// Copyright(c) 2015-2023 Intel Corporation
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/soundwire/sdw_registers.h>
|
||||
|
@ -197,8 +197,7 @@ struct qcom_swrm_ctrl {
|
||||
int num_dout_ports;
|
||||
int cols_index;
|
||||
int rows_index;
|
||||
unsigned long dout_port_mask;
|
||||
unsigned long din_port_mask;
|
||||
unsigned long port_mask;
|
||||
u32 intr_mask;
|
||||
u8 rcmd_id;
|
||||
u8 wcmd_id;
|
||||
@ -1146,11 +1145,7 @@ static void qcom_swrm_stream_free_ports(struct qcom_swrm_ctrl *ctrl,
|
||||
mutex_lock(&ctrl->port_lock);
|
||||
|
||||
list_for_each_entry(m_rt, &stream->master_list, stream_node) {
|
||||
if (m_rt->direction == SDW_DATA_DIR_RX)
|
||||
port_mask = &ctrl->dout_port_mask;
|
||||
else
|
||||
port_mask = &ctrl->din_port_mask;
|
||||
|
||||
port_mask = &ctrl->port_mask;
|
||||
list_for_each_entry(p_rt, &m_rt->port_list, port_node)
|
||||
clear_bit(p_rt->num, port_mask);
|
||||
}
|
||||
@ -1195,13 +1190,9 @@ static int qcom_swrm_stream_alloc_ports(struct qcom_swrm_ctrl *ctrl,
|
||||
if (ctrl->bus.id != m_rt->bus->id)
|
||||
continue;
|
||||
|
||||
if (m_rt->direction == SDW_DATA_DIR_RX) {
|
||||
maxport = ctrl->num_dout_ports;
|
||||
port_mask = &ctrl->dout_port_mask;
|
||||
} else {
|
||||
maxport = ctrl->num_din_ports;
|
||||
port_mask = &ctrl->din_port_mask;
|
||||
}
|
||||
port_mask = &ctrl->port_mask;
|
||||
maxport = ctrl->num_dout_ports + ctrl->num_din_ports;
|
||||
|
||||
|
||||
list_for_each_entry(s_rt, &m_rt->slave_rt_list, m_rt_node) {
|
||||
slave = s_rt->slave;
|
||||
@ -1401,8 +1392,7 @@ static int qcom_swrm_get_port_config(struct qcom_swrm_ctrl *ctrl)
|
||||
return -EINVAL;
|
||||
|
||||
/* Valid port numbers are from 1-14, so mask out port 0 explicitly */
|
||||
set_bit(0, &ctrl->dout_port_mask);
|
||||
set_bit(0, &ctrl->din_port_mask);
|
||||
set_bit(0, &ctrl->port_mask);
|
||||
|
||||
ret = of_property_read_u8_array(np, "qcom,ports-offset1",
|
||||
off1, nports);
|
||||
|
@ -1181,6 +1181,8 @@ static struct sdw_master_runtime
|
||||
m_rt->bus = bus;
|
||||
m_rt->stream = stream;
|
||||
|
||||
bus->stream_refcount++;
|
||||
|
||||
return m_rt;
|
||||
}
|
||||
|
||||
@ -1217,6 +1219,7 @@ static void sdw_master_rt_free(struct sdw_master_runtime *m_rt,
|
||||
struct sdw_stream_runtime *stream)
|
||||
{
|
||||
struct sdw_slave_runtime *s_rt, *_s_rt;
|
||||
struct sdw_bus *bus = m_rt->bus;
|
||||
|
||||
list_for_each_entry_safe(s_rt, _s_rt, &m_rt->slave_rt_list, m_rt_node) {
|
||||
sdw_slave_port_free(s_rt->slave, stream);
|
||||
@ -1226,6 +1229,8 @@ static void sdw_master_rt_free(struct sdw_master_runtime *m_rt,
|
||||
list_del(&m_rt->stream_node);
|
||||
list_del(&m_rt->bus_node);
|
||||
kfree(m_rt);
|
||||
|
||||
bus->stream_refcount--;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -903,6 +903,7 @@ struct sdw_master_ops {
|
||||
* meaningful if multi_link is set. If set to 1, hardware-based
|
||||
* synchronization will be used even if a stream only uses a single
|
||||
* SoundWire segment.
|
||||
* @stream_refcount: number of streams currently using this bus
|
||||
*/
|
||||
struct sdw_bus {
|
||||
struct device *dev;
|
||||
@ -933,6 +934,7 @@ struct sdw_bus {
|
||||
u32 bank_switch_timeout;
|
||||
bool multi_link;
|
||||
int hw_sync_min_links;
|
||||
int stream_refcount;
|
||||
};
|
||||
|
||||
int sdw_bus_master_add(struct sdw_bus *bus, struct device *parent,
|
||||
|
@ -182,6 +182,11 @@
|
||||
#define SDW_SHIM2_INTEL_VS_ACTMCTL_DODSE BIT(2)
|
||||
#define SDW_SHIM2_INTEL_VS_ACTMCTL_DOAIS GENMASK(4, 3)
|
||||
#define SDW_SHIM2_INTEL_VS_ACTMCTL_DOAISE BIT(5)
|
||||
#define SDW_SHIM3_INTEL_VS_ACTMCTL_CLSS BIT(6)
|
||||
#define SDW_SHIM3_INTEL_VS_ACTMCTL_CLDS GENMASK(11, 7)
|
||||
#define SDW_SHIM3_INTEL_VS_ACTMCTL_DODSE2 GENMASK(13, 12)
|
||||
#define SDW_SHIM3_INTEL_VS_ACTMCTL_DOAISE2 BIT(14)
|
||||
#define SDW_SHIM3_INTEL_VS_ACTMCTL_CLDE BIT(15)
|
||||
|
||||
/**
|
||||
* struct sdw_intel_stream_params_data: configuration passed during
|
||||
|
Loading…
Reference in New Issue
Block a user