cs40l50
struct cs40l50 *cs40l50 = dev_get_drvdata(pdev->dev.parent);
vib->dev = cs40l50->dev;
vib->regmap = cs40l50->regmap;
vib->input->id.product = cs40l50->devid;
vib->input->id.version = cs40l50->revid;
static int cs40l50_wseq_init(struct cs40l50 *cs40l50)
struct cs_dsp *dsp = &cs40l50->dsp;
cs40l50->wseqs[CS40L50_STANDBY].ctl = cs_dsp_get_ctl(dsp, "STANDBY_SEQUENCE",
if (!cs40l50->wseqs[CS40L50_STANDBY].ctl) {
dev_err(cs40l50->dev, "Control not found for standby sequence\n");
cs40l50->wseqs[CS40L50_ACTIVE].ctl = cs_dsp_get_ctl(dsp, "ACTIVE_SEQUENCE",
if (!cs40l50->wseqs[CS40L50_ACTIVE].ctl) {
dev_err(cs40l50->dev, "Control not found for active sequence\n");
cs40l50->wseqs[CS40L50_PWR_ON].ctl = cs_dsp_get_ctl(dsp, "PM_PWR_ON_SEQ",
if (!cs40l50->wseqs[CS40L50_PWR_ON].ctl) {
dev_err(cs40l50->dev, "Control not found for power-on sequence\n");
return cs_dsp_wseq_init(&cs40l50->dsp, cs40l50->wseqs, ARRAY_SIZE(cs40l50->wseqs));
static int cs40l50_dsp_config(struct cs40l50 *cs40l50)
ret = regmap_multi_reg_write(cs40l50->regmap, cs40l50_internal_vamp_config,
ret = cs_dsp_wseq_multi_write(&cs40l50->dsp, &cs40l50->wseqs[CS40L50_PWR_ON],
ret = regmap_multi_reg_write(cs40l50->regmap, cs40l50_irq_mask_override,
return cs_dsp_wseq_multi_write(&cs40l50->dsp, &cs40l50->wseqs[CS40L50_PWR_ON],
struct cs40l50 *cs40l50 = container_of(dsp, struct cs40l50, dsp);
ret = cs40l50_wseq_init(cs40l50);
ret = cs40l50_dsp_config(cs40l50);
dev_err(cs40l50->dev, "Failed to configure DSP: %d\n", ret);
ret = devm_mfd_add_devices(cs40l50->dev, PLATFORM_DEVID_NONE, cs40l50_devs,
dev_err(cs40l50->dev, "Failed to add child devices: %d\n", ret);
static int cs40l50_dsp_init(struct cs40l50 *cs40l50)
cs40l50->dsp.num = 1;
cs40l50->dsp.type = WMFW_HALO;
cs40l50->dsp.dev = cs40l50->dev;
cs40l50->dsp.regmap = cs40l50->regmap;
cs40l50->dsp.base = CS40L50_CORE_BASE;
cs40l50->dsp.base_sysinfo = CS40L50_SYS_INFO_ID;
cs40l50->dsp.mem = cs40l50_dsp_regions;
cs40l50->dsp.num_mems = ARRAY_SIZE(cs40l50_dsp_regions);
cs40l50->dsp.no_core_startstop = true;
cs40l50->dsp.client_ops = &client_ops;
ret = cs_dsp_halo_init(&cs40l50->dsp);
return devm_add_action_or_reset(cs40l50->dev, cs40l50_dsp_remove,
&cs40l50->dsp);
static int cs40l50_reset_dsp(struct cs40l50 *cs40l50)
mutex_lock(&cs40l50->lock);
if (cs40l50->dsp.running)
cs_dsp_stop(&cs40l50->dsp);
if (cs40l50->dsp.booted)
cs_dsp_power_down(&cs40l50->dsp);
ret = cs40l50_dsp_write(cs40l50->dev, cs40l50->regmap, CS40L50_SHUTDOWN);
ret = cs_dsp_power_up(&cs40l50->dsp, cs40l50->fw, "cs40l50.wmfw",
cs40l50->bin, "cs40l50.bin", "cs40l50");
ret = cs40l50_dsp_write(cs40l50->dev, cs40l50->regmap, CS40L50_SYSTEM_RESET);
ret = cs40l50_dsp_write(cs40l50->dev, cs40l50->regmap, CS40L50_PREVENT_HIBER);
ret = cs_dsp_run(&cs40l50->dsp);
mutex_unlock(&cs40l50->lock);
struct cs40l50 *cs40l50 = context;
cs40l50->bin = bin;
ret = cs40l50_reset_dsp(cs40l50);
dev_err(cs40l50->dev, "Failed to reset DSP: %d\n", ret);
ret = regmap_read(cs40l50->regmap, CS40L50_NUM_WAVES, &nwaves);
dev_info(cs40l50->dev, "%u RAM effects loaded\n", nwaves);
ret = devm_add_action_or_reset(cs40l50->dev, cs40l50_dsp_power_down,
&cs40l50->dsp);
dev_err(cs40l50->dev, "Failed to add power down action: %d\n", ret);
ret = devm_add_action_or_reset(cs40l50->dev, cs40l50_dsp_stop, &cs40l50->dsp);
dev_err(cs40l50->dev, "Failed to add stop action: %d\n", ret);
release_firmware(cs40l50->bin);
release_firmware(cs40l50->fw);
struct cs40l50 *cs40l50 = context;
dev_err(cs40l50->dev, "No firmware file found\n");
cs40l50->fw = fw;
cs40l50->dev, GFP_KERNEL, cs40l50,
dev_err(cs40l50->dev, "Failed to request %s: %d\n", CS40L50_WT, ret);
release_firmware(cs40l50->fw);
struct cs40l50 *cs40l50 = data;
mutex_lock(&cs40l50->lock);
dev_err(cs40l50->dev, "%s error\n", cs40l50_irqs[i].name);
ret = regmap_multi_reg_write(cs40l50->regmap, cs40l50_err_rls,
mutex_unlock(&cs40l50->lock);
struct cs40l50 *cs40l50 = data;
mutex_lock(&cs40l50->lock);
ret = regmap_read(cs40l50->regmap, CS40L50_DSP_QUEUE_WT, &wt_ptr);
ret = regmap_read(cs40l50->regmap, CS40L50_DSP_QUEUE_RD, &rd_ptr);
ret = regmap_read(cs40l50->regmap, rd_ptr, &val);
dev_dbg(cs40l50->dev, "DSP payload: %#X", val);
ret = regmap_write(cs40l50->regmap, CS40L50_DSP_QUEUE_RD, rd_ptr);
mutex_unlock(&cs40l50->lock);
static int cs40l50_irq_init(struct cs40l50 *cs40l50)
ret = devm_regmap_add_irq_chip(cs40l50->dev, cs40l50->regmap, cs40l50->irq,
&cs40l50_irq_chip, &cs40l50->irq_data);
dev_err(cs40l50->dev, "Failed adding IRQ chip\n");
virq = regmap_irq_get_virq(cs40l50->irq_data, i);
dev_err(cs40l50->dev, "Failed getting virq for %s\n",
ret = devm_request_threaded_irq(cs40l50->dev, virq, NULL,
cs40l50_irqs[i].name, cs40l50);
return dev_err_probe(cs40l50->dev, ret,
static int cs40l50_get_model(struct cs40l50 *cs40l50)
ret = regmap_read(cs40l50->regmap, CS40L50_DEVID, &cs40l50->devid);
if (cs40l50->devid != CS40L50_DEVID_A)
ret = regmap_read(cs40l50->regmap, CS40L50_REVID, &cs40l50->revid);
if (cs40l50->revid < CS40L50_REVID_B0)
dev_dbg(cs40l50->dev, "Cirrus Logic CS40L50 rev. %02X\n", cs40l50->revid);
int cs40l50_probe(struct cs40l50 *cs40l50)
struct device *dev = cs40l50->dev;
mutex_init(&cs40l50->lock);
cs40l50->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
if (IS_ERR(cs40l50->reset_gpio))
return dev_err_probe(dev, PTR_ERR(cs40l50->reset_gpio),
gpiod_set_value_cansleep(cs40l50->reset_gpio, 0);
ret = cs40l50_get_model(cs40l50);
ret = cs40l50_dsp_init(cs40l50);
ret = cs40l50_irq_init(cs40l50);
dev, GFP_KERNEL, cs40l50, cs40l50_request_firmware);
int cs40l50_remove(struct cs40l50 *cs40l50)
gpiod_set_value_cansleep(cs40l50->reset_gpio, 1);
struct cs40l50 *cs40l50 = dev_get_drvdata(dev);
return regmap_write(cs40l50->regmap, CS40L50_DSP_QUEUE, CS40L50_ALLOW_HIBER);
struct cs40l50 *cs40l50 = dev_get_drvdata(dev);
return cs40l50_dsp_write(dev, cs40l50->regmap, CS40L50_PREVENT_HIBER);
struct cs40l50 *cs40l50;
cs40l50 = devm_kzalloc(&i2c->dev, sizeof(*cs40l50), GFP_KERNEL);
if (!cs40l50)
i2c_set_clientdata(i2c, cs40l50);
cs40l50->dev = &i2c->dev;
cs40l50->irq = i2c->irq;
cs40l50->regmap = devm_regmap_init_i2c(i2c, &cs40l50_regmap);
if (IS_ERR(cs40l50->regmap))
return dev_err_probe(cs40l50->dev, PTR_ERR(cs40l50->regmap),
return cs40l50_probe(cs40l50);
struct cs40l50 *cs40l50 = i2c_get_clientdata(i2c);
cs40l50_remove(cs40l50);
struct cs40l50 *cs40l50;
cs40l50 = devm_kzalloc(&spi->dev, sizeof(*cs40l50), GFP_KERNEL);
if (!cs40l50)
spi_set_drvdata(spi, cs40l50);
cs40l50->dev = &spi->dev;
cs40l50->irq = spi->irq;
cs40l50->regmap = devm_regmap_init_spi(spi, &cs40l50_regmap);
if (IS_ERR(cs40l50->regmap))
return dev_err_probe(cs40l50->dev, PTR_ERR(cs40l50->regmap),
return cs40l50_probe(cs40l50);
struct cs40l50 *cs40l50 = spi_get_drvdata(spi);
cs40l50_remove(cs40l50);
int cs40l50_probe(struct cs40l50 *cs40l50);
int cs40l50_remove(struct cs40l50 *cs40l50);
struct cs40l50 *cs40l50 = dev_get_drvdata(pdev->dev.parent);
codec->regmap = cs40l50->regmap;