1d62a7d41SVinod Koul // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) 2d62a7d41SVinod Koul // Copyright(c) 2015-17 Intel Corporation. 3d62a7d41SVinod Koul 4d62a7d41SVinod Koul /* 5d62a7d41SVinod Koul * SDW Intel Init Routines 6d62a7d41SVinod Koul * 7d62a7d41SVinod Koul * Initializes and creates SDW devices based on ACPI and Hardware values 8d62a7d41SVinod Koul */ 9d62a7d41SVinod Koul 10d62a7d41SVinod Koul #include <linux/acpi.h> 114abbd783SPaul Gortmaker #include <linux/export.h> 123fc40449SVinod Koul #include <linux/io.h> 134abbd783SPaul Gortmaker #include <linux/module.h> 14d62a7d41SVinod Koul #include <linux/platform_device.h> 15d62a7d41SVinod Koul #include <linux/soundwire/sdw_intel.h> 16b6109dd6SPierre-Louis Bossart #include "cadence_master.h" 17d62a7d41SVinod Koul #include "intel.h" 18d62a7d41SVinod Koul 196f11586fSPierre-Louis Bossart #define SDW_LINK_TYPE 4 /* from Intel ACPI documentation */ 20d62a7d41SVinod Koul #define SDW_MAX_LINKS 4 21d62a7d41SVinod Koul #define SDW_SHIM_LCAP 0x0 22d62a7d41SVinod Koul #define SDW_SHIM_BASE 0x2C000 23d62a7d41SVinod Koul #define SDW_ALH_BASE 0x2C800 24d62a7d41SVinod Koul #define SDW_LINK_BASE 0x30000 25d62a7d41SVinod Koul #define SDW_LINK_SIZE 0x10000 26d62a7d41SVinod Koul 27*6d2c6669SPierre-Louis Bossart static int ctrl_link_mask; 28*6d2c6669SPierre-Louis Bossart module_param_named(sdw_link_mask, ctrl_link_mask, int, 0444); 2950302fc7SPierre-Louis Bossart MODULE_PARM_DESC(sdw_link_mask, "Intel link mask (one bit per link)"); 3050302fc7SPierre-Louis Bossart 31*6d2c6669SPierre-Louis Bossart static bool is_link_enabled(struct fwnode_handle *fw_node, int i) 32*6d2c6669SPierre-Louis Bossart { 33*6d2c6669SPierre-Louis Bossart struct fwnode_handle *link; 34*6d2c6669SPierre-Louis Bossart char name[32]; 35*6d2c6669SPierre-Louis Bossart u32 quirk_mask = 0; 36*6d2c6669SPierre-Louis Bossart 37*6d2c6669SPierre-Louis Bossart /* Find master handle */ 38*6d2c6669SPierre-Louis Bossart snprintf(name, sizeof(name), 39*6d2c6669SPierre-Louis Bossart "mipi-sdw-link-%d-subproperties", i); 40*6d2c6669SPierre-Louis Bossart 41*6d2c6669SPierre-Louis Bossart link = fwnode_get_named_child_node(fw_node, name); 42*6d2c6669SPierre-Louis Bossart if (!link) 43*6d2c6669SPierre-Louis Bossart return false; 44*6d2c6669SPierre-Louis Bossart 45*6d2c6669SPierre-Louis Bossart fwnode_property_read_u32(link, 46*6d2c6669SPierre-Louis Bossart "intel-quirk-mask", 47*6d2c6669SPierre-Louis Bossart &quirk_mask); 48*6d2c6669SPierre-Louis Bossart 49*6d2c6669SPierre-Louis Bossart if (quirk_mask & SDW_INTEL_QUIRK_MASK_BUS_DISABLE) 50*6d2c6669SPierre-Louis Bossart return false; 51*6d2c6669SPierre-Louis Bossart 52*6d2c6669SPierre-Louis Bossart return true; 53*6d2c6669SPierre-Louis Bossart } 54*6d2c6669SPierre-Louis Bossart 55*6d2c6669SPierre-Louis Bossart static int sdw_intel_cleanup(struct sdw_intel_ctx *ctx) 56d62a7d41SVinod Koul { 57f98f690fSPierre-Louis Bossart struct sdw_intel_link_res *link = ctx->links; 58*6d2c6669SPierre-Louis Bossart u32 link_mask; 59d62a7d41SVinod Koul int i; 60d62a7d41SVinod Koul 61d62a7d41SVinod Koul if (!link) 62d62a7d41SVinod Koul return 0; 63d62a7d41SVinod Koul 64*6d2c6669SPierre-Louis Bossart link_mask = ctx->link_mask; 65*6d2c6669SPierre-Louis Bossart 66*6d2c6669SPierre-Louis Bossart for (i = 0; i < ctx->count; i++, link++) { 67*6d2c6669SPierre-Louis Bossart if (!(link_mask & BIT(i))) 68*6d2c6669SPierre-Louis Bossart continue; 69*6d2c6669SPierre-Louis Bossart 70d62a7d41SVinod Koul if (link->pdev) 71d62a7d41SVinod Koul platform_device_unregister(link->pdev); 72d62a7d41SVinod Koul } 73d62a7d41SVinod Koul 74d62a7d41SVinod Koul return 0; 75d62a7d41SVinod Koul } 76d62a7d41SVinod Koul 77*6d2c6669SPierre-Louis Bossart static int 78*6d2c6669SPierre-Louis Bossart sdw_intel_scan_controller(struct sdw_intel_acpi_info *info) 79d62a7d41SVinod Koul { 80d62a7d41SVinod Koul struct acpi_device *adev; 81d62a7d41SVinod Koul int ret, i; 82d62a7d41SVinod Koul u8 count; 83d62a7d41SVinod Koul 84*6d2c6669SPierre-Louis Bossart if (acpi_bus_get_device(info->handle, &adev)) 85*6d2c6669SPierre-Louis Bossart return -EINVAL; 86d62a7d41SVinod Koul 87d62a7d41SVinod Koul /* Found controller, find links supported */ 88d62a7d41SVinod Koul count = 0; 89d62a7d41SVinod Koul ret = fwnode_property_read_u8_array(acpi_fwnode_handle(adev), 90d62a7d41SVinod Koul "mipi-sdw-master-count", &count, 1); 91d62a7d41SVinod Koul 92*6d2c6669SPierre-Louis Bossart /* 93*6d2c6669SPierre-Louis Bossart * In theory we could check the number of links supported in 94*6d2c6669SPierre-Louis Bossart * hardware, but in that step we cannot assume SoundWire IP is 95*6d2c6669SPierre-Louis Bossart * powered. 96*6d2c6669SPierre-Louis Bossart * 97*6d2c6669SPierre-Louis Bossart * In addition, if the BIOS doesn't even provide this 98*6d2c6669SPierre-Louis Bossart * 'master-count' property then all the inits based on link 99*6d2c6669SPierre-Louis Bossart * masks will fail as well. 100*6d2c6669SPierre-Louis Bossart * 101*6d2c6669SPierre-Louis Bossart * We will check the hardware capabilities in the startup() step 102*6d2c6669SPierre-Louis Bossart */ 103*6d2c6669SPierre-Louis Bossart 104d62a7d41SVinod Koul if (ret) { 105d62a7d41SVinod Koul dev_err(&adev->dev, 106d62a7d41SVinod Koul "Failed to read mipi-sdw-master-count: %d\n", ret); 107*6d2c6669SPierre-Louis Bossart return -EINVAL; 108d62a7d41SVinod Koul } 109d62a7d41SVinod Koul 110d62a7d41SVinod Koul /* Check count is within bounds */ 111d62a7d41SVinod Koul if (count > SDW_MAX_LINKS) { 112d62a7d41SVinod Koul dev_err(&adev->dev, "Link count %d exceeds max %d\n", 113d62a7d41SVinod Koul count, SDW_MAX_LINKS); 114*6d2c6669SPierre-Louis Bossart return -EINVAL; 1156f7219feSGuennadi Liakhovetski } 1166f7219feSGuennadi Liakhovetski 1176f7219feSGuennadi Liakhovetski if (!count) { 118432732b8SPierre-Louis Bossart dev_warn(&adev->dev, "No SoundWire links detected\n"); 119*6d2c6669SPierre-Louis Bossart return -EINVAL; 120*6d2c6669SPierre-Louis Bossart } 121*6d2c6669SPierre-Louis Bossart dev_dbg(&adev->dev, "ACPI reports %d SDW Link devices\n", count); 122*6d2c6669SPierre-Louis Bossart 123*6d2c6669SPierre-Louis Bossart info->count = count; 124*6d2c6669SPierre-Louis Bossart info->link_mask = 0; 125*6d2c6669SPierre-Louis Bossart 126*6d2c6669SPierre-Louis Bossart for (i = 0; i < count; i++) { 127*6d2c6669SPierre-Louis Bossart if (ctrl_link_mask && !(ctrl_link_mask & BIT(i))) { 128*6d2c6669SPierre-Louis Bossart dev_dbg(&adev->dev, 129*6d2c6669SPierre-Louis Bossart "Link %d masked, will not be enabled\n", i); 130*6d2c6669SPierre-Louis Bossart continue; 131d62a7d41SVinod Koul } 132d62a7d41SVinod Koul 133*6d2c6669SPierre-Louis Bossart if (!is_link_enabled(acpi_fwnode_handle(adev), i)) { 134*6d2c6669SPierre-Louis Bossart dev_dbg(&adev->dev, 135*6d2c6669SPierre-Louis Bossart "Link %d not selected in firmware\n", i); 136*6d2c6669SPierre-Louis Bossart continue; 137*6d2c6669SPierre-Louis Bossart } 138*6d2c6669SPierre-Louis Bossart 139*6d2c6669SPierre-Louis Bossart info->link_mask |= BIT(i); 140*6d2c6669SPierre-Louis Bossart } 141*6d2c6669SPierre-Louis Bossart 142*6d2c6669SPierre-Louis Bossart return 0; 143*6d2c6669SPierre-Louis Bossart } 144*6d2c6669SPierre-Louis Bossart 145*6d2c6669SPierre-Louis Bossart static struct sdw_intel_ctx 146*6d2c6669SPierre-Louis Bossart *sdw_intel_probe_controller(struct sdw_intel_res *res) 147*6d2c6669SPierre-Louis Bossart { 148*6d2c6669SPierre-Louis Bossart struct platform_device_info pdevinfo; 149*6d2c6669SPierre-Louis Bossart struct platform_device *pdev; 150*6d2c6669SPierre-Louis Bossart struct sdw_intel_link_res *link; 151*6d2c6669SPierre-Louis Bossart struct sdw_intel_ctx *ctx; 152*6d2c6669SPierre-Louis Bossart struct acpi_device *adev; 153*6d2c6669SPierre-Louis Bossart u32 link_mask; 154*6d2c6669SPierre-Louis Bossart int count; 155*6d2c6669SPierre-Louis Bossart int i; 156*6d2c6669SPierre-Louis Bossart 157*6d2c6669SPierre-Louis Bossart if (!res) 158*6d2c6669SPierre-Louis Bossart return NULL; 159*6d2c6669SPierre-Louis Bossart 160*6d2c6669SPierre-Louis Bossart if (acpi_bus_get_device(res->handle, &adev)) 161*6d2c6669SPierre-Louis Bossart return NULL; 162*6d2c6669SPierre-Louis Bossart 163*6d2c6669SPierre-Louis Bossart if (!res->count) 164*6d2c6669SPierre-Louis Bossart return NULL; 165*6d2c6669SPierre-Louis Bossart 166*6d2c6669SPierre-Louis Bossart count = res->count; 167d62a7d41SVinod Koul dev_dbg(&adev->dev, "Creating %d SDW Link devices\n", count); 168d62a7d41SVinod Koul 169dd906cc6SPierre-Louis Bossart ctx = devm_kzalloc(&adev->dev, sizeof(*ctx), GFP_KERNEL); 170d62a7d41SVinod Koul if (!ctx) 171d62a7d41SVinod Koul return NULL; 172d62a7d41SVinod Koul 173d62a7d41SVinod Koul ctx->count = count; 174dd906cc6SPierre-Louis Bossart ctx->links = devm_kcalloc(&adev->dev, ctx->count, 175dd906cc6SPierre-Louis Bossart sizeof(*ctx->links), GFP_KERNEL); 176d62a7d41SVinod Koul if (!ctx->links) 177dd906cc6SPierre-Louis Bossart return NULL; 178d62a7d41SVinod Koul 179*6d2c6669SPierre-Louis Bossart ctx->count = count; 180*6d2c6669SPierre-Louis Bossart ctx->mmio_base = res->mmio_base; 181*6d2c6669SPierre-Louis Bossart ctx->link_mask = res->link_mask; 182*6d2c6669SPierre-Louis Bossart ctx->handle = res->handle; 183*6d2c6669SPierre-Louis Bossart 184d62a7d41SVinod Koul link = ctx->links; 185*6d2c6669SPierre-Louis Bossart link_mask = ctx->link_mask; 186d62a7d41SVinod Koul 187d62a7d41SVinod Koul /* Create SDW Master devices */ 188*6d2c6669SPierre-Louis Bossart for (i = 0; i < count; i++, link++) { 1899cd1c5a7SPierre-Louis Bossart if (!(link_mask & BIT(i))) { 19050302fc7SPierre-Louis Bossart dev_dbg(&adev->dev, 19150302fc7SPierre-Louis Bossart "Link %d masked, will not be enabled\n", i); 19250302fc7SPierre-Louis Bossart continue; 19350302fc7SPierre-Louis Bossart } 19450302fc7SPierre-Louis Bossart 195*6d2c6669SPierre-Louis Bossart link->mmio_base = res->mmio_base; 196f98f690fSPierre-Louis Bossart link->registers = res->mmio_base + SDW_LINK_BASE 197d62a7d41SVinod Koul + (SDW_LINK_SIZE * i); 198f98f690fSPierre-Louis Bossart link->shim = res->mmio_base + SDW_SHIM_BASE; 199f98f690fSPierre-Louis Bossart link->alh = res->mmio_base + SDW_ALH_BASE; 200d62a7d41SVinod Koul 201f98f690fSPierre-Louis Bossart link->ops = res->ops; 2024b206d34SRander Wang link->dev = res->dev; 203c46302ecSVinod Koul 204d62a7d41SVinod Koul memset(&pdevinfo, 0, sizeof(pdevinfo)); 205d62a7d41SVinod Koul 206d62a7d41SVinod Koul pdevinfo.parent = res->parent; 207*6d2c6669SPierre-Louis Bossart pdevinfo.name = "intel-sdw"; 208d62a7d41SVinod Koul pdevinfo.id = i; 209d62a7d41SVinod Koul pdevinfo.fwnode = acpi_fwnode_handle(adev); 2104ab34412SPierre-Louis Bossart pdevinfo.data = link; 2114ab34412SPierre-Louis Bossart pdevinfo.size_data = sizeof(*link); 212d62a7d41SVinod Koul 213d62a7d41SVinod Koul pdev = platform_device_register_full(&pdevinfo); 214d62a7d41SVinod Koul if (IS_ERR(pdev)) { 215d62a7d41SVinod Koul dev_err(&adev->dev, 216d62a7d41SVinod Koul "platform device creation failed: %ld\n", 217d62a7d41SVinod Koul PTR_ERR(pdev)); 218*6d2c6669SPierre-Louis Bossart goto err; 219d62a7d41SVinod Koul } 220d62a7d41SVinod Koul link->pdev = pdev; 221d62a7d41SVinod Koul } 222d62a7d41SVinod Koul 223d62a7d41SVinod Koul return ctx; 224d62a7d41SVinod Koul 225*6d2c6669SPierre-Louis Bossart err: 226dd906cc6SPierre-Louis Bossart ctx->count = i; 227*6d2c6669SPierre-Louis Bossart sdw_intel_cleanup(ctx); 228d62a7d41SVinod Koul return NULL; 229d62a7d41SVinod Koul } 230d62a7d41SVinod Koul 231*6d2c6669SPierre-Louis Bossart static int 232*6d2c6669SPierre-Louis Bossart sdw_intel_startup_controller(struct sdw_intel_ctx *ctx) 233*6d2c6669SPierre-Louis Bossart { 234*6d2c6669SPierre-Louis Bossart struct acpi_device *adev; 235*6d2c6669SPierre-Louis Bossart struct sdw_intel_link_res *link; 236*6d2c6669SPierre-Louis Bossart u32 caps; 237*6d2c6669SPierre-Louis Bossart u32 link_mask; 238*6d2c6669SPierre-Louis Bossart int i; 239*6d2c6669SPierre-Louis Bossart 240*6d2c6669SPierre-Louis Bossart if (acpi_bus_get_device(ctx->handle, &adev)) 241*6d2c6669SPierre-Louis Bossart return -EINVAL; 242*6d2c6669SPierre-Louis Bossart 243*6d2c6669SPierre-Louis Bossart /* Check SNDWLCAP.LCOUNT */ 244*6d2c6669SPierre-Louis Bossart caps = ioread32(ctx->mmio_base + SDW_SHIM_BASE + SDW_SHIM_LCAP); 245*6d2c6669SPierre-Louis Bossart caps &= GENMASK(2, 0); 246*6d2c6669SPierre-Louis Bossart 247*6d2c6669SPierre-Louis Bossart /* Check HW supported vs property value */ 248*6d2c6669SPierre-Louis Bossart if (caps < ctx->count) { 249*6d2c6669SPierre-Louis Bossart dev_err(&adev->dev, 250*6d2c6669SPierre-Louis Bossart "BIOS master count is larger than hardware capabilities\n"); 251*6d2c6669SPierre-Louis Bossart return -EINVAL; 252*6d2c6669SPierre-Louis Bossart } 253*6d2c6669SPierre-Louis Bossart 254*6d2c6669SPierre-Louis Bossart if (!ctx->links) 255*6d2c6669SPierre-Louis Bossart return -EINVAL; 256*6d2c6669SPierre-Louis Bossart 257*6d2c6669SPierre-Louis Bossart link = ctx->links; 258*6d2c6669SPierre-Louis Bossart link_mask = ctx->link_mask; 259*6d2c6669SPierre-Louis Bossart 260*6d2c6669SPierre-Louis Bossart /* Startup SDW Master devices */ 261*6d2c6669SPierre-Louis Bossart for (i = 0; i < ctx->count; i++, link++) { 262*6d2c6669SPierre-Louis Bossart if (!(link_mask & BIT(i))) 263*6d2c6669SPierre-Louis Bossart continue; 264*6d2c6669SPierre-Louis Bossart 265*6d2c6669SPierre-Louis Bossart intel_master_startup(link->pdev); 266*6d2c6669SPierre-Louis Bossart } 267*6d2c6669SPierre-Louis Bossart 268*6d2c6669SPierre-Louis Bossart return 0; 269*6d2c6669SPierre-Louis Bossart } 270*6d2c6669SPierre-Louis Bossart 271d62a7d41SVinod Koul static acpi_status sdw_intel_acpi_cb(acpi_handle handle, u32 level, 272d62a7d41SVinod Koul void *cdata, void **return_value) 273d62a7d41SVinod Koul { 274*6d2c6669SPierre-Louis Bossart struct sdw_intel_acpi_info *info = cdata; 275d62a7d41SVinod Koul struct acpi_device *adev; 2766f11586fSPierre-Louis Bossart acpi_status status; 2776f11586fSPierre-Louis Bossart u64 adr; 2786f11586fSPierre-Louis Bossart 2796f11586fSPierre-Louis Bossart status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &adr); 2806f11586fSPierre-Louis Bossart if (ACPI_FAILURE(status)) 2816f11586fSPierre-Louis Bossart return AE_OK; /* keep going */ 282d62a7d41SVinod Koul 283d62a7d41SVinod Koul if (acpi_bus_get_device(handle, &adev)) { 284e1c815f4SVinod Koul pr_err("%s: Couldn't find ACPI handle\n", __func__); 285d62a7d41SVinod Koul return AE_NOT_FOUND; 286d62a7d41SVinod Koul } 287d62a7d41SVinod Koul 288*6d2c6669SPierre-Louis Bossart info->handle = handle; 2896f11586fSPierre-Louis Bossart 2906f11586fSPierre-Louis Bossart /* 2916f11586fSPierre-Louis Bossart * On some Intel platforms, multiple children of the HDAS 2926f11586fSPierre-Louis Bossart * device can be found, but only one of them is the SoundWire 2936f11586fSPierre-Louis Bossart * controller. The SNDW device is always exposed with 2946f11586fSPierre-Louis Bossart * Name(_ADR, 0x40000000), with bits 31..28 representing the 2956f11586fSPierre-Louis Bossart * SoundWire link so filter accordingly 2966f11586fSPierre-Louis Bossart */ 2976f11586fSPierre-Louis Bossart if ((adr & GENMASK(31, 28)) >> 28 != SDW_LINK_TYPE) 2986f11586fSPierre-Louis Bossart return AE_OK; /* keep going */ 2996f11586fSPierre-Louis Bossart 3006f11586fSPierre-Louis Bossart /* device found, stop namespace walk */ 3016f11586fSPierre-Louis Bossart return AE_CTRL_TERMINATE; 302d62a7d41SVinod Koul } 303d62a7d41SVinod Koul 304d62a7d41SVinod Koul /** 305*6d2c6669SPierre-Louis Bossart * sdw_intel_acpi_scan() - SoundWire Intel init routine 306d62a7d41SVinod Koul * @parent_handle: ACPI parent handle 307*6d2c6669SPierre-Louis Bossart * @info: description of what firmware/DSDT tables expose 308d62a7d41SVinod Koul * 309*6d2c6669SPierre-Louis Bossart * This scans the namespace and queries firmware to figure out which 310*6d2c6669SPierre-Louis Bossart * links to enable. A follow-up use of sdw_intel_probe() and 311*6d2c6669SPierre-Louis Bossart * sdw_intel_startup() is required for creation of devices and bus 312*6d2c6669SPierre-Louis Bossart * startup 313d62a7d41SVinod Koul */ 314*6d2c6669SPierre-Louis Bossart int sdw_intel_acpi_scan(acpi_handle *parent_handle, 315*6d2c6669SPierre-Louis Bossart struct sdw_intel_acpi_info *info) 316d62a7d41SVinod Koul { 317d62a7d41SVinod Koul acpi_status status; 318d62a7d41SVinod Koul 319d62a7d41SVinod Koul status = acpi_walk_namespace(ACPI_TYPE_DEVICE, 320d62a7d41SVinod Koul parent_handle, 1, 321d62a7d41SVinod Koul sdw_intel_acpi_cb, 322*6d2c6669SPierre-Louis Bossart NULL, info, NULL); 323d62a7d41SVinod Koul if (ACPI_FAILURE(status)) 324*6d2c6669SPierre-Louis Bossart return -ENODEV; 325d62a7d41SVinod Koul 326*6d2c6669SPierre-Louis Bossart return sdw_intel_scan_controller(info); 327d62a7d41SVinod Koul } 328*6d2c6669SPierre-Louis Bossart EXPORT_SYMBOL(sdw_intel_acpi_scan); 329d62a7d41SVinod Koul 330d62a7d41SVinod Koul /** 331*6d2c6669SPierre-Louis Bossart * sdw_intel_probe() - SoundWire Intel probe routine 332*6d2c6669SPierre-Louis Bossart * @res: resource data 333*6d2c6669SPierre-Louis Bossart * 334*6d2c6669SPierre-Louis Bossart * This registers a platform device for each Master handled by the controller, 335*6d2c6669SPierre-Louis Bossart * and SoundWire Master and Slave devices will be created by the platform 336*6d2c6669SPierre-Louis Bossart * device probe. All the information necessary is stored in the context, and 337*6d2c6669SPierre-Louis Bossart * the res argument pointer can be freed after this step. 338*6d2c6669SPierre-Louis Bossart * This function will be called after sdw_intel_acpi_scan() by SOF probe. 339*6d2c6669SPierre-Louis Bossart */ 340*6d2c6669SPierre-Louis Bossart struct sdw_intel_ctx 341*6d2c6669SPierre-Louis Bossart *sdw_intel_probe(struct sdw_intel_res *res) 342*6d2c6669SPierre-Louis Bossart { 343*6d2c6669SPierre-Louis Bossart return sdw_intel_probe_controller(res); 344*6d2c6669SPierre-Louis Bossart } 345*6d2c6669SPierre-Louis Bossart EXPORT_SYMBOL(sdw_intel_probe); 346*6d2c6669SPierre-Louis Bossart 347*6d2c6669SPierre-Louis Bossart /** 348*6d2c6669SPierre-Louis Bossart * sdw_intel_startup() - SoundWire Intel startup 349*6d2c6669SPierre-Louis Bossart * @ctx: SoundWire context allocated in the probe 350*6d2c6669SPierre-Louis Bossart * 351*6d2c6669SPierre-Louis Bossart * Startup Intel SoundWire controller. This function will be called after 352*6d2c6669SPierre-Louis Bossart * Intel Audio DSP is powered up. 353*6d2c6669SPierre-Louis Bossart */ 354*6d2c6669SPierre-Louis Bossart int sdw_intel_startup(struct sdw_intel_ctx *ctx) 355*6d2c6669SPierre-Louis Bossart { 356*6d2c6669SPierre-Louis Bossart return sdw_intel_startup_controller(ctx); 357*6d2c6669SPierre-Louis Bossart } 358*6d2c6669SPierre-Louis Bossart EXPORT_SYMBOL(sdw_intel_startup); 359*6d2c6669SPierre-Louis Bossart /** 360d62a7d41SVinod Koul * sdw_intel_exit() - SoundWire Intel exit 361*6d2c6669SPierre-Louis Bossart * @ctx: SoundWire context allocated in the probe 362d62a7d41SVinod Koul * 363d62a7d41SVinod Koul * Delete the controller instances created and cleanup 364d62a7d41SVinod Koul */ 365f98f690fSPierre-Louis Bossart void sdw_intel_exit(struct sdw_intel_ctx *ctx) 366d62a7d41SVinod Koul { 367*6d2c6669SPierre-Louis Bossart sdw_intel_cleanup(ctx); 368d62a7d41SVinod Koul } 369d62a7d41SVinod Koul EXPORT_SYMBOL(sdw_intel_exit); 370d62a7d41SVinod Koul 371d62a7d41SVinod Koul MODULE_LICENSE("Dual BSD/GPL"); 372d62a7d41SVinod Koul MODULE_DESCRIPTION("Intel Soundwire Init Library"); 373