Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DRAFT] Initial SDCA regmap integration #5150

Open
wants to merge 21 commits into
base: topic/sof-dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
0673651
ASoC/soundwire: remove sdw_slave_extended_id
plbossart May 17, 2024
5f2314b
ASoC: SDCA: add initial module
plbossart Apr 16, 2024
4d5c222
soundwire: slave: lookup SDCA version and functions
plbossart May 14, 2024
4ad35f8
ASoC: SDCA: add quirk function for RT712_VB match
plbossart May 15, 2024
ff286cc
ASoC: soc-acpi: introduce new 'machine check' callback
plbossart May 16, 2024
3b58ad8
ASoC: Intel: soc-acpi: add is_device_rt712_vb() helper
plbossart May 15, 2024
64d415e
ASoC: SOF: Intel: hda: use machine_check() for SoundWire
plbossart May 15, 2024
3a7b55e
ASoC: SDCA: add helpers to handle SDCA interrupt sources
plbossart May 30, 2024
75d9b0d
ASoC: SDCA: add code to parse Function information
plbossart May 22, 2024
fc6acaa
ASoC: SDCA: add function devices
plbossart May 21, 2024
e0500c0
ASoC: SDCA: Add control parsing
charleskeepax Aug 8, 2024
506f757
ASoC: SDCA: Move calls to sdca_parse_function to device level
charleskeepax Aug 19, 2024
ec260ac
ASoC: SDCA: Allow passing in a regmap for each auxiliary device
charleskeepax Aug 20, 2024
5cfdf55
soundwire: SDCA: Add additional SDCA macros
charleskeepax Jun 12, 2024
392b639
regmap: sdw-mbq: Add support for further MBQ register sizes
charleskeepax May 10, 2024
36c9e09
regmap: sdw-mbq: Add support for SDCA deferred controls
charleskeepax Jun 20, 2024
0294c5a
ASoC: SDCA: Add generic regmap sdca helpers
charleskeepax Aug 13, 2024
4001fed
ASoC: SDCA: Add disco constants/default handling
charleskeepax Aug 13, 2024
6a64950
mfd: cs42l43: Strip the driver right back
charleskeepax Apr 29, 2024
7229554
mfd: cs42l43: Properly configure the firmware
charleskeepax Apr 29, 2024
4f60798
mfd: cs42l43: Setup device to use new SDCA class functionality
charleskeepax Aug 16, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions drivers/soundwire/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
menuconfig SOUNDWIRE
tristate "SoundWire support"
depends on ACPI || OF
depends on SND_SOC_SDCA_OPTIONAL
help
SoundWire is a 2-Pin interface with data and clock line ratified
by the MIPI Alliance. SoundWire is used for transporting data
Expand Down
12 changes: 6 additions & 6 deletions drivers/soundwire/amd_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ EXPORT_SYMBOL_NS(sdw_amd_probe, SOUNDWIRE_AMD_INIT);
void sdw_amd_exit(struct sdw_amd_ctx *ctx)
{
sdw_amd_cleanup(ctx);
kfree(ctx->ids);
kfree(ctx->peripherals);
kfree(ctx);
}
EXPORT_SYMBOL_NS(sdw_amd_exit, SOUNDWIRE_AMD_INIT);
Expand All @@ -204,19 +204,19 @@ int sdw_amd_get_slave_info(struct sdw_amd_ctx *ctx)
num_slaves++;
}

ctx->ids = kcalloc(num_slaves, sizeof(*ctx->ids), GFP_KERNEL);
if (!ctx->ids)
ctx->peripherals = kmalloc(struct_size(ctx->peripherals, array, num_slaves),
GFP_KERNEL);
if (!ctx->peripherals)
return -ENOMEM;
ctx->num_slaves = num_slaves;
ctx->peripherals->num_peripherals = num_slaves;
for (index = 0; index < ctx->count; index++) {
if (!(ctx->link_mask & BIT(index)))
continue;
amd_manager = dev_get_drvdata(&ctx->pdev[index]->dev);
if (amd_manager) {
bus = &amd_manager->bus;
list_for_each_entry(slave, &bus->slaves, node) {
ctx->ids[i].id = slave->id;
ctx->ids[i].link_id = bus->link_id;
ctx->peripherals->array[i] = slave;
i++;
}
}
Expand Down
13 changes: 6 additions & 7 deletions drivers/soundwire/intel_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -252,17 +252,16 @@ static struct sdw_intel_ctx
num_slaves++;
}

ctx->ids = kcalloc(num_slaves, sizeof(*ctx->ids), GFP_KERNEL);
if (!ctx->ids)
ctx->peripherals = kmalloc(struct_size(ctx->peripherals, array, num_slaves),
GFP_KERNEL);
if (!ctx->peripherals)
goto err;

ctx->num_slaves = num_slaves;
ctx->peripherals->num_peripherals = num_slaves;
i = 0;
list_for_each_entry(link, &ctx->link_list, list) {
bus = &link->cdns->bus;
list_for_each_entry(slave, &bus->slaves, node) {
ctx->ids[i].id = slave->id;
ctx->ids[i].link_id = bus->link_id;
ctx->peripherals->array[i] = slave;
i++;
}
}
Expand Down Expand Up @@ -371,7 +370,7 @@ void sdw_intel_exit(struct sdw_intel_ctx *ctx)
}

sdw_intel_cleanup(ctx);
kfree(ctx->ids);
kfree(ctx->peripherals);
kfree(ctx->ldev);
kfree(ctx);
}
Expand Down
14 changes: 14 additions & 0 deletions drivers/soundwire/slave.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <linux/of.h>
#include <linux/soundwire/sdw.h>
#include <linux/soundwire/sdw_type.h>
#include <sound/sdca.h>
#include "bus.h"
#include "sysfs_local.h"

Expand Down Expand Up @@ -70,6 +71,17 @@ int sdw_slave_add(struct sdw_bus *bus,
list_add_tail(&slave->node, &bus->slaves);
mutex_unlock(&bus->bus_lock);

/*
* The Soundwire driver probe may optionally register SDCA
* sub-devices, one per Function. This means the information
* on the SDCA revision and the number/type of Functions need
* to be extracted from platform firmware before the SoundWire
* driver probe, and as a consequence before the SoundWire
* device_register() below.
*/
sdca_lookup_interface_revision(slave);
sdca_lookup_functions(slave);

ret = device_register(&slave->dev);
if (ret) {
dev_err(bus->dev, "Failed to add slave: ret %d\n", ret);
Expand Down Expand Up @@ -259,3 +271,5 @@ int sdw_of_find_slaves(struct sdw_bus *bus)

return 0;
}

MODULE_IMPORT_NS(SND_SOC_SDCA);
9 changes: 6 additions & 3 deletions include/linux/soundwire/sdw.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <linux/irqdomain.h>
#include <linux/mod_devicetable.h>
#include <linux/bitfield.h>
#include <sound/sdca.h>

struct sdw_bus;
struct sdw_slave;
Expand Down Expand Up @@ -467,9 +468,9 @@ struct sdw_slave_id {
__u8 sdw_version:4;
};

struct sdw_extended_slave_id {
int link_id;
struct sdw_slave_id id;
struct sdw_peripherals {
int num_peripherals;
struct sdw_slave *array[];
};

/*
Expand Down Expand Up @@ -642,6 +643,7 @@ struct sdw_slave_ops {
* @is_mockup_device: status flag used to squelch errors in the command/control
* protocol for SoundWire mockup devices
* @sdw_dev_lock: mutex used to protect callbacks/remove races
* @sdca_data: structure containing all device data for SDCA helpers
*/
struct sdw_slave {
struct sdw_slave_id id;
Expand All @@ -665,6 +667,7 @@ struct sdw_slave {
bool first_interrupt_done;
bool is_mockup_device;
struct mutex sdw_dev_lock; /* protect callbacks/remove races */
struct sdca_device_data sdca_data;
};

#define dev_to_sdw_dev(_dev) container_of(_dev, struct sdw_slave, dev)
Expand Down
7 changes: 2 additions & 5 deletions include/linux/soundwire/sdw_amd.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,19 +115,16 @@ struct sdw_amd_acpi_info {
* struct sdw_amd_ctx - context allocated by the controller driver probe
*
* @count: link count
* @num_slaves: total number of devices exposed across all enabled links
* @link_mask: bit-wise mask listing SoundWire links reported by the
* Controller
* @ids: array of slave_id, representing Slaves exposed across all enabled
* links
* @pdev: platform device structure
* @peripherals: array representing Peripherals exposed across all enabled links
*/
struct sdw_amd_ctx {
int count;
int num_slaves;
u32 link_mask;
struct sdw_extended_slave_id *ids;
struct platform_device *pdev[AMD_SDW_MAX_MANAGER_COUNT];
struct sdw_peripherals *peripherals;
};

/**
Expand Down
7 changes: 2 additions & 5 deletions include/linux/soundwire/sdw_intel.h
Original file line number Diff line number Diff line change
Expand Up @@ -286,31 +286,28 @@ struct hdac_bus;
* hardware capabilities after all power dependencies are settled.
* @link_mask: bit-wise mask listing SoundWire links reported by the
* Controller
* @num_slaves: total number of devices exposed across all enabled links
* @handle: ACPI parent handle
* @ldev: information for each link (controller-specific and kept
* opaque here)
* @ids: array of slave_id, representing Slaves exposed across all enabled
* links
* @link_list: list to handle interrupts across all links
* @shim_lock: mutex to handle concurrent rmw access to shared SHIM registers.
* @shim_mask: flags to track initialization of SHIM shared registers
* @shim_base: sdw shim base.
* @alh_base: sdw alh base.
* @peripherals: array representing Peripherals exposed across all enabled links
*/
struct sdw_intel_ctx {
int count;
void __iomem *mmio_base;
u32 link_mask;
int num_slaves;
acpi_handle handle;
struct sdw_intel_link_dev **ldev;
struct sdw_extended_slave_id *ids;
struct list_head link_list;
struct mutex shim_lock; /* lock for access to shared SHIM registers */
u32 shim_mask;
u32 shim_base;
u32 alh_base;
struct sdw_peripherals *peripherals;
};

/**
Expand Down
184 changes: 184 additions & 0 deletions include/sound/sdca.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
/*
* The MIPI SDCA specification is available for public downloads at
* https://www.mipi.org/mipi-sdca-v1-0-download
*
* Copyright(c) 2024 Intel Corporation
*/

#ifndef __SDCA_H__
#define __SDCA_H__

struct sdw_slave;
struct sdca_dev;
struct sdca_function_data;

#define SDCA_MAX_INTERRUPTS 31 /* the last bit is reserved for future extensions */

/**
* struct sdca_interrupt_source - interface between interrupt source and
* SoundWire SDCA interrupt handler
*
* @index: SDCA interrupt number in [0, SDCA_MAX_INTERRUPTS - 1]
* @context: source-specific information, used by @callback
* @callback: provided by interrupt source for source-specific handling.
*/
struct sdca_interrupt_source {
int index;
void *context;
void (*callback)(void *context);
};

/**
* struct sdca_interrupt_info - Peripheral device-level information
* used for interrupt handler
*
* @sources: array of pointers, addressed with an interrupt index
* matching @registered_source_mask bits.
* @irqs_lock: mutex protecting concurrent access to @sources,
* @registered_source_mask and reventing SDCA interrupts from being disabled
* on suspend while being handled.
* @enabled_interrupt_mask: mask indicating which interrupts from @registered_source_mask
* are currently enabled.
* @detected_interrupt_mask: bitfields set in interrupt handler, and accessible
* in deferred processing.
* @supported_hw_register_mask: Up to 4 registers may be implemented
*/
struct sdca_interrupt_info {
struct sdca_interrupt_source *sources[SDCA_MAX_INTERRUPTS];
struct mutex irqs_lock; /* protects SDCA interrupts */
u32 registered_source_mask;
u32 enabled_interrupt_mask;
u32 detected_interrupt_mask;
int supported_hw_register_mask;
};

#define SDCA_MAX_FUNCTION_COUNT 8

/**
* sdca_device_desc - short descriptor for an SDCA Function
* @function_node: firmware node for the Function
* @func_dev: pointer to SDCA function device.
* @adr: ACPI address (used for SDCA register access)
* @type: Function topology type
* @name: human-readable string
*/
struct sdca_function_desc {
struct fwnode_handle *function_node;
struct sdca_function_data *function;
struct sdca_dev *func_dev;
u64 adr;
u32 type;
const char *name;
};

/**
* sdca_device_data - structure containing all SDCA related information
* @sdca_interface_revision: value read from _DSD property, mainly to check
* for changes between silicon versions
* @num_functions: total number of supported SDCA functions. Invalid/unsupported
* functions will be skipped.
* @sdca_func: array of function descriptors
* @interrupt_info: device-level interrupt configuration/handling
*/
struct sdca_device_data {
u32 interface_revision;
int num_functions;
struct sdca_function_desc sdca_func[SDCA_MAX_FUNCTION_COUNT];
struct sdca_interrupt_info *interrupt_info;
};

enum sdca_quirk {
SDCA_QUIRKS_RT712_VB,
};

#if IS_ENABLED(CONFIG_ACPI) && IS_ENABLED(CONFIG_SND_SOC_SDCA)

void sdca_lookup_functions(struct sdw_slave *slave);
void sdca_lookup_interface_revision(struct sdw_slave *slave);
bool sdca_device_quirk_match(struct sdw_slave *slave, enum sdca_quirk quirk);
int sdca_dev_register_functions(struct sdw_slave *slave);
int sdca_dev_parse_functions(struct sdw_slave *slave);
void sdca_dev_unregister_functions(struct sdw_slave *slave);

#else

static inline void sdca_lookup_functions(struct sdw_slave *slave) {}
static inline void sdca_lookup_interface_revision(struct sdw_slave *slave) {}
static inline bool sdca_device_quirk_match(struct sdw_slave *slave, enum sdca_quirk quirk)
{
return false;
}

static inline int sdca_dev_register_functions(struct sdw_slave *slave)
{
return 0;
}

static inline int sdca_dev_parse_functions(struct sdw_slave *slave)
{
return 0;
}

static inline void sdca_dev_unregister_functions(struct sdw_slave *slave) {}

#endif

#if IS_ENABLED(CONFIG_SND_SOC_SDCA_IRQ_HANDLER)

int sdca_interrupt_info_alloc(struct sdw_slave *slave);
void sdca_interrupt_info_release(struct sdw_slave *slave);
int sdca_interrupt_info_reset(struct sdw_slave *slave);
int sdca_interrupt_initialize(struct sdw_slave *slave,
int supported_hw_register_mask);
int sdca_interrupt_register_source(struct sdw_slave *slave,
struct sdca_interrupt_source *source);
int sdca_interrupt_enable(struct sdw_slave *slave,
u32 source_mask,
bool enable);
void sdca_interrupt_clear_history(struct sdw_slave *slave, u32 preserve_mask);
int sdca_interrupt_handler(struct sdw_slave *slave);

#else

static inline int sdca_interrupt_info_alloc(struct sdw_slave *slave)
{
return 0;
}

static inline void sdca_interrupt_info_release(struct sdw_slave *slave) {}

static inline int sdca_interrupt_info_reset(struct sdw_slave *slave)
{
return 0;
}

static inline int sdca_interrupt_initialize(struct sdw_slave *slave,
int supported_hw_register_mask)
{
return 0;
}

static inline int sdca_interrupt_register_source(struct sdw_slave *slave,
struct sdca_interrupt_source *source)
{
return 0;
}

static inline int sdca_interrupt_enable(struct sdw_slave *slave,
u32 source_mask,
bool enable)
{
return 0;
}

static inline void sdca_interrupt_clear_history(struct sdw_slave *slave, u32 preserve_mask) {}

static inline int sdca_interrupt_handler(struct sdw_slave *slave)
{
return 0;
}

#endif /* IS_ENABLED(CONFIG_SND_SOC_SDCA_IRQ_HANDLER) */

#endif
Loading