1*3af1815aSCharles Keepax // SPDX-License-Identifier: GPL-2.0 2*3af1815aSCharles Keepax // Copyright (C) 2025 Cirrus Logic, Inc. and 3*3af1815aSCharles Keepax // Cirrus Logic International Semiconductor Ltd. 4*3af1815aSCharles Keepax 5*3af1815aSCharles Keepax /* 6*3af1815aSCharles Keepax * The MIPI SDCA specification is available for public downloads at 7*3af1815aSCharles Keepax * https://www.mipi.org/mipi-sdca-v1-0-download 8*3af1815aSCharles Keepax */ 9*3af1815aSCharles Keepax 10*3af1815aSCharles Keepax #include <linux/auxiliary_bus.h> 11*3af1815aSCharles Keepax #include <linux/minmax.h> 12*3af1815aSCharles Keepax #include <linux/module.h> 13*3af1815aSCharles Keepax #include <linux/pm.h> 14*3af1815aSCharles Keepax #include <linux/pm_runtime.h> 15*3af1815aSCharles Keepax #include <linux/soundwire/sdw.h> 16*3af1815aSCharles Keepax #include <linux/soundwire/sdw_registers.h> 17*3af1815aSCharles Keepax #include <sound/pcm.h> 18*3af1815aSCharles Keepax #include <sound/sdca_asoc.h> 19*3af1815aSCharles Keepax #include <sound/sdca_fdl.h> 20*3af1815aSCharles Keepax #include <sound/sdca_function.h> 21*3af1815aSCharles Keepax #include <sound/sdca_interrupts.h> 22*3af1815aSCharles Keepax #include <sound/sdca_regmap.h> 23*3af1815aSCharles Keepax #include <sound/sdw.h> 24*3af1815aSCharles Keepax #include <sound/soc-component.h> 25*3af1815aSCharles Keepax #include <sound/soc-dai.h> 26*3af1815aSCharles Keepax #include <sound/soc.h> 27*3af1815aSCharles Keepax #include "sdca_class.h" 28*3af1815aSCharles Keepax 29*3af1815aSCharles Keepax struct class_function_drv { 30*3af1815aSCharles Keepax struct device *dev; 31*3af1815aSCharles Keepax struct regmap *regmap; 32*3af1815aSCharles Keepax struct sdca_class_drv *core; 33*3af1815aSCharles Keepax 34*3af1815aSCharles Keepax struct sdca_function_data *function; 35*3af1815aSCharles Keepax }; 36*3af1815aSCharles Keepax 37*3af1815aSCharles Keepax static void class_function_regmap_lock(void *data) 38*3af1815aSCharles Keepax { 39*3af1815aSCharles Keepax struct mutex *lock = data; 40*3af1815aSCharles Keepax 41*3af1815aSCharles Keepax mutex_lock(lock); 42*3af1815aSCharles Keepax } 43*3af1815aSCharles Keepax 44*3af1815aSCharles Keepax static void class_function_regmap_unlock(void *data) 45*3af1815aSCharles Keepax { 46*3af1815aSCharles Keepax struct mutex *lock = data; 47*3af1815aSCharles Keepax 48*3af1815aSCharles Keepax mutex_unlock(lock); 49*3af1815aSCharles Keepax } 50*3af1815aSCharles Keepax 51*3af1815aSCharles Keepax static bool class_function_regmap_writeable(struct device *dev, unsigned int reg) 52*3af1815aSCharles Keepax { 53*3af1815aSCharles Keepax struct auxiliary_device *auxdev = to_auxiliary_dev(dev); 54*3af1815aSCharles Keepax struct class_function_drv *drv = auxiliary_get_drvdata(auxdev); 55*3af1815aSCharles Keepax 56*3af1815aSCharles Keepax return sdca_regmap_writeable(drv->function, reg); 57*3af1815aSCharles Keepax } 58*3af1815aSCharles Keepax 59*3af1815aSCharles Keepax static bool class_function_regmap_readable(struct device *dev, unsigned int reg) 60*3af1815aSCharles Keepax { 61*3af1815aSCharles Keepax struct auxiliary_device *auxdev = to_auxiliary_dev(dev); 62*3af1815aSCharles Keepax struct class_function_drv *drv = auxiliary_get_drvdata(auxdev); 63*3af1815aSCharles Keepax 64*3af1815aSCharles Keepax return sdca_regmap_readable(drv->function, reg); 65*3af1815aSCharles Keepax } 66*3af1815aSCharles Keepax 67*3af1815aSCharles Keepax static bool class_function_regmap_volatile(struct device *dev, unsigned int reg) 68*3af1815aSCharles Keepax { 69*3af1815aSCharles Keepax struct auxiliary_device *auxdev = to_auxiliary_dev(dev); 70*3af1815aSCharles Keepax struct class_function_drv *drv = auxiliary_get_drvdata(auxdev); 71*3af1815aSCharles Keepax 72*3af1815aSCharles Keepax return sdca_regmap_volatile(drv->function, reg); 73*3af1815aSCharles Keepax } 74*3af1815aSCharles Keepax 75*3af1815aSCharles Keepax static const struct regmap_config class_function_regmap_config = { 76*3af1815aSCharles Keepax .name = "sdca", 77*3af1815aSCharles Keepax .reg_bits = 32, 78*3af1815aSCharles Keepax .val_bits = 32, 79*3af1815aSCharles Keepax .reg_format_endian = REGMAP_ENDIAN_LITTLE, 80*3af1815aSCharles Keepax .val_format_endian = REGMAP_ENDIAN_LITTLE, 81*3af1815aSCharles Keepax 82*3af1815aSCharles Keepax .max_register = SDW_SDCA_MAX_REGISTER, 83*3af1815aSCharles Keepax .readable_reg = class_function_regmap_readable, 84*3af1815aSCharles Keepax .writeable_reg = class_function_regmap_writeable, 85*3af1815aSCharles Keepax .volatile_reg = class_function_regmap_volatile, 86*3af1815aSCharles Keepax 87*3af1815aSCharles Keepax .cache_type = REGCACHE_MAPLE, 88*3af1815aSCharles Keepax 89*3af1815aSCharles Keepax .lock = class_function_regmap_lock, 90*3af1815aSCharles Keepax .unlock = class_function_regmap_unlock, 91*3af1815aSCharles Keepax }; 92*3af1815aSCharles Keepax 93*3af1815aSCharles Keepax static int class_function_regmap_mbq_size(struct device *dev, unsigned int reg) 94*3af1815aSCharles Keepax { 95*3af1815aSCharles Keepax struct auxiliary_device *auxdev = to_auxiliary_dev(dev); 96*3af1815aSCharles Keepax struct class_function_drv *drv = auxiliary_get_drvdata(auxdev); 97*3af1815aSCharles Keepax 98*3af1815aSCharles Keepax return sdca_regmap_mbq_size(drv->function, reg); 99*3af1815aSCharles Keepax } 100*3af1815aSCharles Keepax 101*3af1815aSCharles Keepax static bool class_function_regmap_deferrable(struct device *dev, unsigned int reg) 102*3af1815aSCharles Keepax { 103*3af1815aSCharles Keepax struct auxiliary_device *auxdev = to_auxiliary_dev(dev); 104*3af1815aSCharles Keepax struct class_function_drv *drv = auxiliary_get_drvdata(auxdev); 105*3af1815aSCharles Keepax 106*3af1815aSCharles Keepax return sdca_regmap_deferrable(drv->function, reg); 107*3af1815aSCharles Keepax } 108*3af1815aSCharles Keepax 109*3af1815aSCharles Keepax static const struct regmap_sdw_mbq_cfg class_function_mbq_config = { 110*3af1815aSCharles Keepax .mbq_size = class_function_regmap_mbq_size, 111*3af1815aSCharles Keepax .deferrable = class_function_regmap_deferrable, 112*3af1815aSCharles Keepax .retry_us = 1000, 113*3af1815aSCharles Keepax .timeout_us = 10000, 114*3af1815aSCharles Keepax }; 115*3af1815aSCharles Keepax 116*3af1815aSCharles Keepax static int class_function_startup(struct snd_pcm_substream *substream, 117*3af1815aSCharles Keepax struct snd_soc_dai *dai) 118*3af1815aSCharles Keepax { 119*3af1815aSCharles Keepax struct class_function_drv *drv = snd_soc_component_get_drvdata(dai->component); 120*3af1815aSCharles Keepax 121*3af1815aSCharles Keepax return sdca_asoc_set_constraints(drv->dev, drv->regmap, drv->function, 122*3af1815aSCharles Keepax substream, dai); 123*3af1815aSCharles Keepax } 124*3af1815aSCharles Keepax 125*3af1815aSCharles Keepax static int class_function_sdw_add_peripheral(struct snd_pcm_substream *substream, 126*3af1815aSCharles Keepax struct snd_pcm_hw_params *params, 127*3af1815aSCharles Keepax struct snd_soc_dai *dai) 128*3af1815aSCharles Keepax { 129*3af1815aSCharles Keepax struct class_function_drv *drv = snd_soc_component_get_drvdata(dai->component); 130*3af1815aSCharles Keepax struct sdw_stream_runtime *sdw_stream = snd_soc_dai_get_dma_data(dai, substream); 131*3af1815aSCharles Keepax struct sdw_slave *sdw = dev_to_sdw_dev(drv->dev->parent); 132*3af1815aSCharles Keepax struct sdw_stream_config sconfig = {0}; 133*3af1815aSCharles Keepax struct sdw_port_config pconfig = {0}; 134*3af1815aSCharles Keepax int ret; 135*3af1815aSCharles Keepax 136*3af1815aSCharles Keepax if (!sdw_stream) 137*3af1815aSCharles Keepax return -EINVAL; 138*3af1815aSCharles Keepax 139*3af1815aSCharles Keepax snd_sdw_params_to_config(substream, params, &sconfig, &pconfig); 140*3af1815aSCharles Keepax 141*3af1815aSCharles Keepax /* 142*3af1815aSCharles Keepax * FIXME: As also noted in sdca_asoc_get_port(), currently only 143*3af1815aSCharles Keepax * a single unshared port is supported for each DAI. 144*3af1815aSCharles Keepax */ 145*3af1815aSCharles Keepax ret = sdca_asoc_get_port(drv->dev, drv->regmap, drv->function, dai); 146*3af1815aSCharles Keepax if (ret < 0) 147*3af1815aSCharles Keepax return ret; 148*3af1815aSCharles Keepax 149*3af1815aSCharles Keepax pconfig.num = ret; 150*3af1815aSCharles Keepax 151*3af1815aSCharles Keepax ret = sdw_stream_add_slave(sdw, &sconfig, &pconfig, 1, sdw_stream); 152*3af1815aSCharles Keepax if (ret) { 153*3af1815aSCharles Keepax dev_err(drv->dev, "failed to add sdw stream: %d\n", ret); 154*3af1815aSCharles Keepax return ret; 155*3af1815aSCharles Keepax } 156*3af1815aSCharles Keepax 157*3af1815aSCharles Keepax return sdca_asoc_hw_params(drv->dev, drv->regmap, drv->function, 158*3af1815aSCharles Keepax substream, params, dai); 159*3af1815aSCharles Keepax } 160*3af1815aSCharles Keepax 161*3af1815aSCharles Keepax static int class_function_sdw_remove_peripheral(struct snd_pcm_substream *substream, 162*3af1815aSCharles Keepax struct snd_soc_dai *dai) 163*3af1815aSCharles Keepax { 164*3af1815aSCharles Keepax struct class_function_drv *drv = snd_soc_component_get_drvdata(dai->component); 165*3af1815aSCharles Keepax struct sdw_stream_runtime *sdw_stream = snd_soc_dai_get_dma_data(dai, substream); 166*3af1815aSCharles Keepax struct sdw_slave *sdw = dev_to_sdw_dev(drv->dev->parent); 167*3af1815aSCharles Keepax 168*3af1815aSCharles Keepax if (!sdw_stream) 169*3af1815aSCharles Keepax return -EINVAL; 170*3af1815aSCharles Keepax 171*3af1815aSCharles Keepax return sdw_stream_remove_slave(sdw, sdw_stream); 172*3af1815aSCharles Keepax } 173*3af1815aSCharles Keepax 174*3af1815aSCharles Keepax static int class_function_sdw_set_stream(struct snd_soc_dai *dai, void *sdw_stream, 175*3af1815aSCharles Keepax int direction) 176*3af1815aSCharles Keepax { 177*3af1815aSCharles Keepax snd_soc_dai_dma_data_set(dai, direction, sdw_stream); 178*3af1815aSCharles Keepax 179*3af1815aSCharles Keepax return 0; 180*3af1815aSCharles Keepax } 181*3af1815aSCharles Keepax 182*3af1815aSCharles Keepax static const struct snd_soc_dai_ops class_function_sdw_ops = { 183*3af1815aSCharles Keepax .startup = class_function_startup, 184*3af1815aSCharles Keepax .shutdown = sdca_asoc_free_constraints, 185*3af1815aSCharles Keepax .set_stream = class_function_sdw_set_stream, 186*3af1815aSCharles Keepax .hw_params = class_function_sdw_add_peripheral, 187*3af1815aSCharles Keepax .hw_free = class_function_sdw_remove_peripheral, 188*3af1815aSCharles Keepax }; 189*3af1815aSCharles Keepax 190*3af1815aSCharles Keepax static int class_function_component_probe(struct snd_soc_component *component) 191*3af1815aSCharles Keepax { 192*3af1815aSCharles Keepax struct class_function_drv *drv = snd_soc_component_get_drvdata(component); 193*3af1815aSCharles Keepax struct sdca_class_drv *core = drv->core; 194*3af1815aSCharles Keepax 195*3af1815aSCharles Keepax return sdca_irq_populate(drv->function, component, core->irq_info); 196*3af1815aSCharles Keepax } 197*3af1815aSCharles Keepax 198*3af1815aSCharles Keepax static const struct snd_soc_component_driver class_function_component_drv = { 199*3af1815aSCharles Keepax .probe = class_function_component_probe, 200*3af1815aSCharles Keepax .endianness = 1, 201*3af1815aSCharles Keepax }; 202*3af1815aSCharles Keepax 203*3af1815aSCharles Keepax static int class_function_boot(struct class_function_drv *drv) 204*3af1815aSCharles Keepax { 205*3af1815aSCharles Keepax unsigned int reg = SDW_SDCA_CTL(drv->function->desc->adr, 206*3af1815aSCharles Keepax SDCA_ENTITY_TYPE_ENTITY_0, 207*3af1815aSCharles Keepax SDCA_CTL_ENTITY_0_FUNCTION_STATUS, 0); 208*3af1815aSCharles Keepax unsigned int val; 209*3af1815aSCharles Keepax int ret; 210*3af1815aSCharles Keepax 211*3af1815aSCharles Keepax ret = regmap_read(drv->regmap, reg, &val); 212*3af1815aSCharles Keepax if (ret < 0) { 213*3af1815aSCharles Keepax dev_err(drv->dev, "failed to read function status: %d\n", ret); 214*3af1815aSCharles Keepax return ret; 215*3af1815aSCharles Keepax } 216*3af1815aSCharles Keepax 217*3af1815aSCharles Keepax if (!(val & SDCA_CTL_ENTITY_0_FUNCTION_HAS_BEEN_RESET)) { 218*3af1815aSCharles Keepax dev_dbg(drv->dev, "reset function device\n"); 219*3af1815aSCharles Keepax 220*3af1815aSCharles Keepax ret = sdca_reset_function(drv->dev, drv->function, drv->regmap); 221*3af1815aSCharles Keepax if (ret) 222*3af1815aSCharles Keepax return ret; 223*3af1815aSCharles Keepax } 224*3af1815aSCharles Keepax 225*3af1815aSCharles Keepax if (val & SDCA_CTL_ENTITY_0_FUNCTION_NEEDS_INITIALIZATION) { 226*3af1815aSCharles Keepax dev_dbg(drv->dev, "write initialisation\n"); 227*3af1815aSCharles Keepax 228*3af1815aSCharles Keepax ret = sdca_regmap_write_init(drv->dev, drv->core->dev_regmap, 229*3af1815aSCharles Keepax drv->function); 230*3af1815aSCharles Keepax if (ret) 231*3af1815aSCharles Keepax return ret; 232*3af1815aSCharles Keepax 233*3af1815aSCharles Keepax ret = regmap_write(drv->regmap, reg, 234*3af1815aSCharles Keepax SDCA_CTL_ENTITY_0_FUNCTION_NEEDS_INITIALIZATION); 235*3af1815aSCharles Keepax if (ret < 0) { 236*3af1815aSCharles Keepax dev_err(drv->dev, 237*3af1815aSCharles Keepax "failed to clear function init status: %d\n", 238*3af1815aSCharles Keepax ret); 239*3af1815aSCharles Keepax return ret; 240*3af1815aSCharles Keepax } 241*3af1815aSCharles Keepax } 242*3af1815aSCharles Keepax 243*3af1815aSCharles Keepax /* Start FDL process */ 244*3af1815aSCharles Keepax ret = sdca_irq_populate_early(drv->dev, drv->regmap, drv->function, 245*3af1815aSCharles Keepax drv->core->irq_info); 246*3af1815aSCharles Keepax if (ret) 247*3af1815aSCharles Keepax return ret; 248*3af1815aSCharles Keepax 249*3af1815aSCharles Keepax ret = sdca_fdl_sync(drv->dev, drv->function, drv->core->irq_info); 250*3af1815aSCharles Keepax if (ret) 251*3af1815aSCharles Keepax return ret; 252*3af1815aSCharles Keepax 253*3af1815aSCharles Keepax ret = sdca_regmap_write_defaults(drv->dev, drv->regmap, drv->function); 254*3af1815aSCharles Keepax if (ret) 255*3af1815aSCharles Keepax return ret; 256*3af1815aSCharles Keepax 257*3af1815aSCharles Keepax ret = regmap_write(drv->regmap, reg, 0xFF); 258*3af1815aSCharles Keepax if (ret < 0) { 259*3af1815aSCharles Keepax dev_err(drv->dev, "failed to clear function status: %d\n", ret); 260*3af1815aSCharles Keepax return ret; 261*3af1815aSCharles Keepax } 262*3af1815aSCharles Keepax 263*3af1815aSCharles Keepax return 0; 264*3af1815aSCharles Keepax } 265*3af1815aSCharles Keepax 266*3af1815aSCharles Keepax static int class_function_probe(struct auxiliary_device *auxdev, 267*3af1815aSCharles Keepax const struct auxiliary_device_id *aux_dev_id) 268*3af1815aSCharles Keepax { 269*3af1815aSCharles Keepax struct device *dev = &auxdev->dev; 270*3af1815aSCharles Keepax struct sdca_class_drv *core = dev_get_drvdata(dev->parent); 271*3af1815aSCharles Keepax struct sdca_device_data *data = &core->sdw->sdca_data; 272*3af1815aSCharles Keepax struct sdca_function_desc *desc; 273*3af1815aSCharles Keepax struct snd_soc_component_driver *cmp_drv; 274*3af1815aSCharles Keepax struct snd_soc_dai_driver *dais; 275*3af1815aSCharles Keepax struct class_function_drv *drv; 276*3af1815aSCharles Keepax struct regmap_sdw_mbq_cfg *mbq_config; 277*3af1815aSCharles Keepax struct regmap_config *config; 278*3af1815aSCharles Keepax struct reg_default *defaults; 279*3af1815aSCharles Keepax int ndefaults; 280*3af1815aSCharles Keepax int num_dais; 281*3af1815aSCharles Keepax int ret; 282*3af1815aSCharles Keepax int i; 283*3af1815aSCharles Keepax 284*3af1815aSCharles Keepax drv = devm_kzalloc(dev, sizeof(*drv), GFP_KERNEL); 285*3af1815aSCharles Keepax if (!drv) 286*3af1815aSCharles Keepax return -ENOMEM; 287*3af1815aSCharles Keepax 288*3af1815aSCharles Keepax cmp_drv = devm_kmemdup(dev, &class_function_component_drv, sizeof(*cmp_drv), 289*3af1815aSCharles Keepax GFP_KERNEL); 290*3af1815aSCharles Keepax if (!cmp_drv) 291*3af1815aSCharles Keepax return -ENOMEM; 292*3af1815aSCharles Keepax 293*3af1815aSCharles Keepax config = devm_kmemdup(dev, &class_function_regmap_config, sizeof(*config), 294*3af1815aSCharles Keepax GFP_KERNEL); 295*3af1815aSCharles Keepax if (!config) 296*3af1815aSCharles Keepax return -ENOMEM; 297*3af1815aSCharles Keepax 298*3af1815aSCharles Keepax mbq_config = devm_kmemdup(dev, &class_function_mbq_config, sizeof(*mbq_config), 299*3af1815aSCharles Keepax GFP_KERNEL); 300*3af1815aSCharles Keepax if (!mbq_config) 301*3af1815aSCharles Keepax return -ENOMEM; 302*3af1815aSCharles Keepax 303*3af1815aSCharles Keepax drv->dev = dev; 304*3af1815aSCharles Keepax drv->core = core; 305*3af1815aSCharles Keepax 306*3af1815aSCharles Keepax for (i = 0; i < data->num_functions; i++) { 307*3af1815aSCharles Keepax desc = &data->function[i]; 308*3af1815aSCharles Keepax 309*3af1815aSCharles Keepax if (desc->type == aux_dev_id->driver_data) 310*3af1815aSCharles Keepax break; 311*3af1815aSCharles Keepax } 312*3af1815aSCharles Keepax if (i == core->sdw->sdca_data.num_functions) { 313*3af1815aSCharles Keepax dev_err(dev, "failed to locate function\n"); 314*3af1815aSCharles Keepax return -EINVAL; 315*3af1815aSCharles Keepax } 316*3af1815aSCharles Keepax 317*3af1815aSCharles Keepax drv->function = &core->functions[i]; 318*3af1815aSCharles Keepax 319*3af1815aSCharles Keepax ret = sdca_parse_function(dev, core->sdw, desc, drv->function); 320*3af1815aSCharles Keepax if (ret) 321*3af1815aSCharles Keepax return ret; 322*3af1815aSCharles Keepax 323*3af1815aSCharles Keepax ndefaults = sdca_regmap_count_constants(dev, drv->function); 324*3af1815aSCharles Keepax if (ndefaults < 0) 325*3af1815aSCharles Keepax return ndefaults; 326*3af1815aSCharles Keepax 327*3af1815aSCharles Keepax defaults = devm_kcalloc(dev, ndefaults, sizeof(*defaults), GFP_KERNEL); 328*3af1815aSCharles Keepax if (!defaults) 329*3af1815aSCharles Keepax return -ENOMEM; 330*3af1815aSCharles Keepax 331*3af1815aSCharles Keepax ret = sdca_regmap_populate_constants(dev, drv->function, defaults); 332*3af1815aSCharles Keepax if (ret < 0) 333*3af1815aSCharles Keepax return ret; 334*3af1815aSCharles Keepax 335*3af1815aSCharles Keepax regcache_sort_defaults(defaults, ndefaults); 336*3af1815aSCharles Keepax 337*3af1815aSCharles Keepax auxiliary_set_drvdata(auxdev, drv); 338*3af1815aSCharles Keepax 339*3af1815aSCharles Keepax config->reg_defaults = defaults; 340*3af1815aSCharles Keepax config->num_reg_defaults = ndefaults; 341*3af1815aSCharles Keepax config->lock_arg = &core->regmap_lock; 342*3af1815aSCharles Keepax 343*3af1815aSCharles Keepax if (drv->function->busy_max_delay) { 344*3af1815aSCharles Keepax mbq_config->timeout_us = drv->function->busy_max_delay; 345*3af1815aSCharles Keepax mbq_config->retry_us = umax(drv->function->busy_max_delay / 10, 346*3af1815aSCharles Keepax mbq_config->retry_us); 347*3af1815aSCharles Keepax } 348*3af1815aSCharles Keepax 349*3af1815aSCharles Keepax drv->regmap = devm_regmap_init_sdw_mbq_cfg(dev, core->sdw, config, mbq_config); 350*3af1815aSCharles Keepax if (IS_ERR(drv->regmap)) 351*3af1815aSCharles Keepax return dev_err_probe(dev, PTR_ERR(drv->regmap), 352*3af1815aSCharles Keepax "failed to create regmap"); 353*3af1815aSCharles Keepax 354*3af1815aSCharles Keepax ret = sdca_asoc_populate_component(dev, drv->function, cmp_drv, 355*3af1815aSCharles Keepax &dais, &num_dais, 356*3af1815aSCharles Keepax &class_function_sdw_ops); 357*3af1815aSCharles Keepax if (ret) 358*3af1815aSCharles Keepax return ret; 359*3af1815aSCharles Keepax 360*3af1815aSCharles Keepax pm_runtime_set_autosuspend_delay(dev, 200); 361*3af1815aSCharles Keepax pm_runtime_use_autosuspend(dev); 362*3af1815aSCharles Keepax pm_runtime_set_active(dev); 363*3af1815aSCharles Keepax pm_runtime_get_noresume(dev); 364*3af1815aSCharles Keepax 365*3af1815aSCharles Keepax ret = devm_pm_runtime_enable(dev); 366*3af1815aSCharles Keepax if (ret) 367*3af1815aSCharles Keepax return ret; 368*3af1815aSCharles Keepax 369*3af1815aSCharles Keepax ret = class_function_boot(drv); 370*3af1815aSCharles Keepax if (ret) 371*3af1815aSCharles Keepax return ret; 372*3af1815aSCharles Keepax 373*3af1815aSCharles Keepax ret = devm_snd_soc_register_component(dev, cmp_drv, dais, num_dais); 374*3af1815aSCharles Keepax if (ret) 375*3af1815aSCharles Keepax return dev_err_probe(dev, ret, "failed to register component\n"); 376*3af1815aSCharles Keepax 377*3af1815aSCharles Keepax pm_runtime_mark_last_busy(dev); 378*3af1815aSCharles Keepax pm_runtime_put_autosuspend(dev); 379*3af1815aSCharles Keepax 380*3af1815aSCharles Keepax return 0; 381*3af1815aSCharles Keepax } 382*3af1815aSCharles Keepax 383*3af1815aSCharles Keepax static int class_function_runtime_suspend(struct device *dev) 384*3af1815aSCharles Keepax { 385*3af1815aSCharles Keepax struct auxiliary_device *auxdev = to_auxiliary_dev(dev); 386*3af1815aSCharles Keepax struct class_function_drv *drv = auxiliary_get_drvdata(auxdev); 387*3af1815aSCharles Keepax 388*3af1815aSCharles Keepax /* 389*3af1815aSCharles Keepax * Whilst the driver doesn't power the chip down here, going into 390*3af1815aSCharles Keepax * runtime suspend means the driver can't be sure the bus won't 391*3af1815aSCharles Keepax * power down which would prevent communication with the device. 392*3af1815aSCharles Keepax */ 393*3af1815aSCharles Keepax regcache_cache_only(drv->regmap, true); 394*3af1815aSCharles Keepax 395*3af1815aSCharles Keepax return 0; 396*3af1815aSCharles Keepax } 397*3af1815aSCharles Keepax 398*3af1815aSCharles Keepax static int class_function_runtime_resume(struct device *dev) 399*3af1815aSCharles Keepax { 400*3af1815aSCharles Keepax struct auxiliary_device *auxdev = to_auxiliary_dev(dev); 401*3af1815aSCharles Keepax struct class_function_drv *drv = auxiliary_get_drvdata(auxdev); 402*3af1815aSCharles Keepax int ret; 403*3af1815aSCharles Keepax 404*3af1815aSCharles Keepax regcache_mark_dirty(drv->regmap); 405*3af1815aSCharles Keepax regcache_cache_only(drv->regmap, false); 406*3af1815aSCharles Keepax 407*3af1815aSCharles Keepax ret = regcache_sync(drv->regmap); 408*3af1815aSCharles Keepax if (ret) { 409*3af1815aSCharles Keepax dev_err(drv->dev, "failed to restore register cache: %d\n", ret); 410*3af1815aSCharles Keepax goto err; 411*3af1815aSCharles Keepax } 412*3af1815aSCharles Keepax 413*3af1815aSCharles Keepax return 0; 414*3af1815aSCharles Keepax 415*3af1815aSCharles Keepax err: 416*3af1815aSCharles Keepax regcache_cache_only(drv->regmap, true); 417*3af1815aSCharles Keepax 418*3af1815aSCharles Keepax return ret; 419*3af1815aSCharles Keepax } 420*3af1815aSCharles Keepax 421*3af1815aSCharles Keepax static const struct dev_pm_ops class_function_pm_ops = { 422*3af1815aSCharles Keepax RUNTIME_PM_OPS(class_function_runtime_suspend, 423*3af1815aSCharles Keepax class_function_runtime_resume, NULL) 424*3af1815aSCharles Keepax }; 425*3af1815aSCharles Keepax 426*3af1815aSCharles Keepax static const struct auxiliary_device_id class_function_id_table[] = { 427*3af1815aSCharles Keepax { 428*3af1815aSCharles Keepax .name = "snd_soc_sdca." SDCA_FUNCTION_TYPE_SMART_AMP_NAME, 429*3af1815aSCharles Keepax .driver_data = SDCA_FUNCTION_TYPE_SMART_AMP, 430*3af1815aSCharles Keepax }, 431*3af1815aSCharles Keepax { 432*3af1815aSCharles Keepax .name = "snd_soc_sdca." SDCA_FUNCTION_TYPE_SMART_MIC_NAME, 433*3af1815aSCharles Keepax .driver_data = SDCA_FUNCTION_TYPE_SMART_MIC, 434*3af1815aSCharles Keepax }, 435*3af1815aSCharles Keepax { 436*3af1815aSCharles Keepax .name = "snd_soc_sdca." SDCA_FUNCTION_TYPE_UAJ_NAME, 437*3af1815aSCharles Keepax .driver_data = SDCA_FUNCTION_TYPE_UAJ, 438*3af1815aSCharles Keepax }, 439*3af1815aSCharles Keepax { 440*3af1815aSCharles Keepax .name = "snd_soc_sdca." SDCA_FUNCTION_TYPE_HID_NAME, 441*3af1815aSCharles Keepax .driver_data = SDCA_FUNCTION_TYPE_HID, 442*3af1815aSCharles Keepax }, 443*3af1815aSCharles Keepax {}, 444*3af1815aSCharles Keepax }; 445*3af1815aSCharles Keepax MODULE_DEVICE_TABLE(auxiliary, class_function_id_table); 446*3af1815aSCharles Keepax 447*3af1815aSCharles Keepax static struct auxiliary_driver class_function_drv = { 448*3af1815aSCharles Keepax .driver = { 449*3af1815aSCharles Keepax .name = "sdca_function", 450*3af1815aSCharles Keepax .pm = pm_ptr(&class_function_pm_ops), 451*3af1815aSCharles Keepax }, 452*3af1815aSCharles Keepax 453*3af1815aSCharles Keepax .probe = class_function_probe, 454*3af1815aSCharles Keepax .id_table = class_function_id_table 455*3af1815aSCharles Keepax }; 456*3af1815aSCharles Keepax module_auxiliary_driver(class_function_drv); 457*3af1815aSCharles Keepax 458*3af1815aSCharles Keepax MODULE_LICENSE("GPL"); 459*3af1815aSCharles Keepax MODULE_DESCRIPTION("SDCA Class Function Driver"); 460*3af1815aSCharles Keepax MODULE_IMPORT_NS("SND_SOC_SDCA"); 461