Skip to content

Commit

Permalink
ASoC/soundwire: add initial support for SDCA
Browse files Browse the repository at this point in the history
Merge series from Bard Liao <yung-chuan.liao@linux.intel.com>:

We need to get rt712 version by reading SDCA version and functions.
This patch series adds initial support for SDCA and add a helper to tell
if the codec is RT712_VB.

This series may go via the ASoC tree with Vinod's Acked-by tag.

Bard Liao (1):
  soundwire: sdw_intel: include linux/acpi.h

Pierre-Louis Bossart (10):
  ASoC/soundwire: remove sdw_slave_extended_id
  ASoC: SDCA: add initial module
  soundwire: slave: lookup SDCA version and functions
  ASoC: SDCA: add quirk function for RT712_VB match
  ASoC: rt712-sdca: detect the SMART_MIC function during the probe stage
  ASoC: soc-acpi: introduce new 'machine check' callback
  ASoC: sdw_utils: add SmartMic DAI for RT712 VB
  ASoC: sdw_utils: add SmartMic DAI for RT713 VB
  ASoC: Intel: soc-acpi: add is_device_rt712_vb() helper
  ASoC: SOF: Intel: hda: use machine_check() for SoundWire

 drivers/soundwire/Kconfig                     |   1 +
 drivers/soundwire/amd_init.c                  |  12 +-
 drivers/soundwire/intel_init.c                |  13 +-
 drivers/soundwire/slave.c                     |  14 ++
 include/linux/soundwire/sdw.h                 |   9 +-
 include/linux/soundwire/sdw_amd.h             |   7 +-
 include/linux/soundwire/sdw_intel.h           |   8 +-
 include/sound/sdca.h                          |  62 +++++++
 include/sound/sdca_function.h                 |  55 ++++++
 include/sound/soc-acpi.h                      |   8 +-
 sound/soc/Kconfig                             |   1 +
 sound/soc/Makefile                            |   1 +
 sound/soc/amd/ps/pci-ps.c                     |   3 +-
 sound/soc/codecs/rt712-sdca-sdw.c             |   1 +
 sound/soc/codecs/rt712-sdca.c                 |  38 +++-
 sound/soc/codecs/rt712-sdca.h                 |   1 +
 sound/soc/intel/Kconfig                       |   5 +
 sound/soc/intel/common/Makefile               |   3 +
 .../intel/common/soc-acpi-intel-mtl-match.c   |  51 ++++++
 .../intel/common/soc-acpi-intel-sdca-quirks.c |  42 +++++
 .../intel/common/soc-acpi-intel-sdca-quirks.h |  14 ++
 sound/soc/sdca/Kconfig                        |  11 ++
 sound/soc/sdca/Makefile                       |   5 +
 sound/soc/sdca/sdca_device.c                  |  67 +++++++
 sound/soc/sdca/sdca_functions.c               | 173 ++++++++++++++++++
 sound/soc/sdw_utils/soc_sdw_utils.c           |  18 +-
 sound/soc/soc-acpi.c                          |  30 +--
 sound/soc/sof/amd/acp-common.c                |   3 +-
 sound/soc/sof/intel/hda.c                     |  19 +-
 29 files changed, 610 insertions(+), 65 deletions(-)
 create mode 100644 include/sound/sdca.h
 create mode 100644 include/sound/sdca_function.h
 create mode 100644 sound/soc/intel/common/soc-acpi-intel-sdca-quirks.c
 create mode 100644 sound/soc/intel/common/soc-acpi-intel-sdca-quirks.h
 create mode 100644 sound/soc/sdca/Kconfig
 create mode 100644 sound/soc/sdca/Makefile
 create mode 100644 sound/soc/sdca/sdca_device.c
 create mode 100644 sound/soc/sdca/sdca_functions.c

--
2.43.0
  • Loading branch information
Mark Brown committed Oct 18, 2024
2 parents 42fb516 + e92edcf commit 478fc2f
Show file tree
Hide file tree
Showing 29 changed files with 610 additions and 65 deletions.
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 @@ -488,9 +489,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 @@ -663,6 +664,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 @@ -686,6 +688,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
8 changes: 3 additions & 5 deletions include/linux/soundwire/sdw_intel.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#ifndef __SDW_INTEL_H
#define __SDW_INTEL_H

#include <linux/acpi.h>
#include <linux/irqreturn.h>
#include <linux/soundwire/sdw.h>

Expand Down Expand Up @@ -286,31 +287,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
62 changes: 62 additions & 0 deletions include/sound/sdca.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/* 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;

#define SDCA_MAX_FUNCTION_COUNT 8

/**
* sdca_device_desc - short descriptor for an SDCA Function
* @adr: ACPI address (used for SDCA register access)
* @type: Function topology type
* @name: human-readable string
*/
struct sdca_function_desc {
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
*/
struct sdca_device_data {
u32 interface_revision;
int num_functions;
struct sdca_function_desc sdca_func[SDCA_MAX_FUNCTION_COUNT];
};

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);

#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;
}
#endif

#endif
55 changes: 55 additions & 0 deletions include/sound/sdca_function.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/* 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_FUNCTION_H__
#define __SDCA_FUNCTION_H__

/*
* SDCA Function Types from SDCA specification v1.0a Section 5.1.2
* all Function types not described are reserved
* Note that SIMPLE_AMP, SIMPLE_MIC and SIMPLE_JACK Function Types
* are NOT defined in SDCA 1.0a, but they were defined in earlier
* drafts and are planned for 1.1.
*/

enum sdca_function_type {
SDCA_FUNCTION_TYPE_SMART_AMP = 0x01, /* Amplifier with protection features */
SDCA_FUNCTION_TYPE_SIMPLE_AMP = 0x02, /* subset of SmartAmp */
SDCA_FUNCTION_TYPE_SMART_MIC = 0x03, /* Smart microphone with acoustic triggers */
SDCA_FUNCTION_TYPE_SIMPLE_MIC = 0x04, /* subset of SmartMic */
SDCA_FUNCTION_TYPE_SPEAKER_MIC = 0x05, /* Combination of SmartMic and SmartAmp */
SDCA_FUNCTION_TYPE_UAJ = 0x06, /* 3.5mm Universal Audio jack */
SDCA_FUNCTION_TYPE_RJ = 0x07, /* Retaskable jack */
SDCA_FUNCTION_TYPE_SIMPLE_JACK = 0x08, /* Subset of UAJ */
SDCA_FUNCTION_TYPE_HID = 0x0A, /* Human Interface Device, for e.g. buttons */
SDCA_FUNCTION_TYPE_IMP_DEF = 0x1F, /* Implementation-defined function */
};

/* Human-readable names used for kernel logs and Function device registration/bind */
#define SDCA_FUNCTION_TYPE_SMART_AMP_NAME "SmartAmp"
#define SDCA_FUNCTION_TYPE_SIMPLE_AMP_NAME "SimpleAmp"
#define SDCA_FUNCTION_TYPE_SMART_MIC_NAME "SmartMic"
#define SDCA_FUNCTION_TYPE_SIMPLE_MIC_NAME "SimpleMic"
#define SDCA_FUNCTION_TYPE_SPEAKER_MIC_NAME "SpeakerMic"
#define SDCA_FUNCTION_TYPE_UAJ_NAME "UAJ"
#define SDCA_FUNCTION_TYPE_RJ_NAME "RJ"
#define SDCA_FUNCTION_TYPE_SIMPLE_NAME "SimpleJack"
#define SDCA_FUNCTION_TYPE_HID_NAME "HID"

enum sdca_entity0_controls {
SDCA_CONTROL_ENTITY_0_COMMIT_GROUP_MASK = 0x01,
SDCA_CONTROL_ENTITY_0_INTSTAT_CLEAR = 0x02,
SDCA_CONTROL_ENTITY_0_INT_ENABLE = 0x03,
SDCA_CONTROL_ENTITY_0_FUNCTION_SDCA_VERSION = 0x04,
SDCA_CONTROL_ENTITY_0_FUNCTION_TOPOLOGY = 0x05,
SDCA_CONTROL_ENTITY_0_FUNCTION_MANUFACTURER_ID = 0x06,
SDCA_CONTROL_ENTITY_0_FUNCTION_ID = 0x07,
SDCA_CONTROL_ENTITY_0_FUNCTION_VERSION = 0x08
};

#endif
8 changes: 6 additions & 2 deletions include/sound/soc-acpi.h
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,10 @@ struct snd_soc_acpi_link_adr {
* ACPI ID alone is not sufficient, wrong or misleading
* @quirk_data: data used to uniquely identify a machine, usually a list of
* audio codecs whose presence if checked with ACPI
* @machine_check: pointer to quirk function. The functionality is similar to
* the use of @machine_quirk, except that the return value is a boolean: the intent
* is to skip a machine if the additional hardware/firmware verification invalidates
* the initial selection in the snd_soc_acpi_mach table.
* @pdata: intended for platform data or machine specific-ops. This structure
* is not constant since this field may be updated at run-time
* @sof_tplg_filename: Sound Open Firmware topology file name, if enabled
Expand All @@ -203,6 +207,7 @@ struct snd_soc_acpi_mach {
const char *board;
struct snd_soc_acpi_mach * (*machine_quirk)(void *arg);
const void *quirk_data;
bool (*machine_check)(void *arg);
void *pdata;
struct snd_soc_acpi_mach_params mach_params;
const char *sof_tplg_filename;
Expand Down Expand Up @@ -233,7 +238,6 @@ static inline bool snd_soc_acpi_sof_parent(struct device *dev)

bool snd_soc_acpi_sdw_link_slaves_found(struct device *dev,
const struct snd_soc_acpi_link_adr *link,
struct sdw_extended_slave_id *ids,
int num_slaves);
struct sdw_peripherals *peripherals);

#endif
1 change: 1 addition & 0 deletions sound/soc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ source "sound/soc/pxa/Kconfig"
source "sound/soc/qcom/Kconfig"
source "sound/soc/rockchip/Kconfig"
source "sound/soc/samsung/Kconfig"
source "sound/soc/sdca/Kconfig"
source "sound/soc/sh/Kconfig"
source "sound/soc/sof/Kconfig"
source "sound/soc/spear/Kconfig"
Expand Down
1 change: 1 addition & 0 deletions sound/soc/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ obj-$(CONFIG_SND_SOC) += pxa/
obj-$(CONFIG_SND_SOC) += qcom/
obj-$(CONFIG_SND_SOC) += rockchip/
obj-$(CONFIG_SND_SOC) += samsung/
obj-$(CONFIG_SND_SOC) += sdca/
obj-$(CONFIG_SND_SOC) += sh/
obj-$(CONFIG_SND_SOC) += sof/
obj-$(CONFIG_SND_SOC) += spear/
Expand Down
3 changes: 1 addition & 2 deletions sound/soc/amd/ps/pci-ps.c
Original file line number Diff line number Diff line change
Expand Up @@ -302,8 +302,7 @@ static struct snd_soc_acpi_mach *acp63_sdw_machine_select(struct device *dev)
link = mach->links;
for (i = 0; i < acp_data->info.count && link->num_adr; link++, i++) {
if (!snd_soc_acpi_sdw_link_slaves_found(dev, link,
acp_data->sdw->ids,
acp_data->sdw->num_slaves))
acp_data->sdw->peripherals))
break;
}
if (i == acp_data->info.count || !link->num_adr)
Expand Down
1 change: 1 addition & 0 deletions sound/soc/codecs/rt712-sdca-sdw.c
Original file line number Diff line number Diff line change
Expand Up @@ -507,3 +507,4 @@ module_sdw_driver(rt712_sdca_sdw_driver);
MODULE_DESCRIPTION("ASoC RT712 SDCA SDW driver");
MODULE_AUTHOR("Shuming Fan <shumingf@realtek.com>");
MODULE_LICENSE("GPL");
MODULE_IMPORT_NS(SND_SOC_SDCA);
Loading

0 comments on commit 478fc2f

Please sign in to comment.