Commit ad7b0b7b authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
parents 7a46b17d fdd3d14c
Loading
Loading
Loading
Loading
+3 −4
Original line number Diff line number Diff line
@@ -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 @@ static struct sdw_amd_ctx *sdw_amd_probe_controller(struct sdw_amd_res *res)
		platform_device_unregister(ctx->pdev[index]);
	}

	kfree(sdw_res);
	kfree(ctx);
	return NULL;
}
+5 −8
Original line number Diff line number Diff line
@@ -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;
}

+3 −3
Original line number Diff line number Diff line
@@ -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 */
+2 −3
Original line number Diff line number Diff line
@@ -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;
}
+152 −5
Original line number Diff line number Diff line
// 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;
}

Loading