Lines Matching +full:dsp +full:- +full:standby
1 // SPDX-License-Identifier: GPL-2.0
4 * integrated DSP, and closed-loop algorithms
19 { .name = "cs40l50-codec", },
20 { .name = "cs40l50-vibra", },
33 "vdd-io",
82 dev_err(dev, "Timed out writing %#X to DSP: %d\n", val, ret); in cs40l50_dsp_write()
90 dev_err(dev, "DSP failed to ACK %#X: %d\n", val, ret); in cs40l50_dsp_write()
116 struct cs_dsp *dsp = &cs40l50->dsp; in cs40l50_wseq_init() local
118 cs40l50->wseqs[CS40L50_STANDBY].ctl = cs_dsp_get_ctl(dsp, "STANDBY_SEQUENCE", in cs40l50_wseq_init()
121 if (!cs40l50->wseqs[CS40L50_STANDBY].ctl) { in cs40l50_wseq_init()
122 dev_err(cs40l50->dev, "Control not found for standby sequence\n"); in cs40l50_wseq_init()
123 return -ENOENT; in cs40l50_wseq_init()
126 cs40l50->wseqs[CS40L50_ACTIVE].ctl = cs_dsp_get_ctl(dsp, "ACTIVE_SEQUENCE", in cs40l50_wseq_init()
129 if (!cs40l50->wseqs[CS40L50_ACTIVE].ctl) { in cs40l50_wseq_init()
130 dev_err(cs40l50->dev, "Control not found for active sequence\n"); in cs40l50_wseq_init()
131 return -ENOENT; in cs40l50_wseq_init()
134 cs40l50->wseqs[CS40L50_PWR_ON].ctl = cs_dsp_get_ctl(dsp, "PM_PWR_ON_SEQ", in cs40l50_wseq_init()
137 if (!cs40l50->wseqs[CS40L50_PWR_ON].ctl) { in cs40l50_wseq_init()
138 dev_err(cs40l50->dev, "Control not found for power-on sequence\n"); in cs40l50_wseq_init()
139 return -ENOENT; in cs40l50_wseq_init()
142 return cs_dsp_wseq_init(&cs40l50->dsp, cs40l50->wseqs, ARRAY_SIZE(cs40l50->wseqs)); in cs40l50_wseq_init()
150 ret = regmap_multi_reg_write(cs40l50->regmap, cs40l50_internal_vamp_config, in cs40l50_dsp_config()
155 ret = cs_dsp_wseq_multi_write(&cs40l50->dsp, &cs40l50->wseqs[CS40L50_PWR_ON], in cs40l50_dsp_config()
162 ret = regmap_multi_reg_write(cs40l50->regmap, cs40l50_irq_mask_override, in cs40l50_dsp_config()
167 return cs_dsp_wseq_multi_write(&cs40l50->dsp, &cs40l50->wseqs[CS40L50_PWR_ON], in cs40l50_dsp_config()
172 static int cs40l50_dsp_post_run(struct cs_dsp *dsp) in cs40l50_dsp_post_run() argument
174 struct cs40l50 *cs40l50 = container_of(dsp, struct cs40l50, dsp); in cs40l50_dsp_post_run()
183 dev_err(cs40l50->dev, "Failed to configure DSP: %d\n", ret); in cs40l50_dsp_post_run()
187 ret = devm_mfd_add_devices(cs40l50->dev, PLATFORM_DEVID_NONE, cs40l50_devs, in cs40l50_dsp_post_run()
190 dev_err(cs40l50->dev, "Failed to add child devices: %d\n", ret); in cs40l50_dsp_post_run()
208 cs40l50->dsp.num = 1; in cs40l50_dsp_init()
209 cs40l50->dsp.type = WMFW_HALO; in cs40l50_dsp_init()
210 cs40l50->dsp.dev = cs40l50->dev; in cs40l50_dsp_init()
211 cs40l50->dsp.regmap = cs40l50->regmap; in cs40l50_dsp_init()
212 cs40l50->dsp.base = CS40L50_CORE_BASE; in cs40l50_dsp_init()
213 cs40l50->dsp.base_sysinfo = CS40L50_SYS_INFO_ID; in cs40l50_dsp_init()
214 cs40l50->dsp.mem = cs40l50_dsp_regions; in cs40l50_dsp_init()
215 cs40l50->dsp.num_mems = ARRAY_SIZE(cs40l50_dsp_regions); in cs40l50_dsp_init()
216 cs40l50->dsp.no_core_startstop = true; in cs40l50_dsp_init()
217 cs40l50->dsp.client_ops = &client_ops; in cs40l50_dsp_init()
219 ret = cs_dsp_halo_init(&cs40l50->dsp); in cs40l50_dsp_init()
223 return devm_add_action_or_reset(cs40l50->dev, cs40l50_dsp_remove, in cs40l50_dsp_init()
224 &cs40l50->dsp); in cs40l50_dsp_init()
231 mutex_lock(&cs40l50->lock); in cs40l50_reset_dsp()
233 if (cs40l50->dsp.running) in cs40l50_reset_dsp()
234 cs_dsp_stop(&cs40l50->dsp); in cs40l50_reset_dsp()
236 if (cs40l50->dsp.booted) in cs40l50_reset_dsp()
237 cs_dsp_power_down(&cs40l50->dsp); in cs40l50_reset_dsp()
239 ret = cs40l50_dsp_write(cs40l50->dev, cs40l50->regmap, CS40L50_SHUTDOWN); in cs40l50_reset_dsp()
243 ret = cs_dsp_power_up(&cs40l50->dsp, cs40l50->fw, "cs40l50.wmfw", in cs40l50_reset_dsp()
244 cs40l50->bin, "cs40l50.bin", "cs40l50"); in cs40l50_reset_dsp()
248 ret = cs40l50_dsp_write(cs40l50->dev, cs40l50->regmap, CS40L50_SYSTEM_RESET); in cs40l50_reset_dsp()
252 ret = cs40l50_dsp_write(cs40l50->dev, cs40l50->regmap, CS40L50_PREVENT_HIBER); in cs40l50_reset_dsp()
256 ret = cs_dsp_run(&cs40l50->dsp); in cs40l50_reset_dsp()
258 mutex_unlock(&cs40l50->lock); in cs40l50_reset_dsp()
279 /* Wavetable is optional; bringup DSP regardless */ in cs40l50_dsp_bringup()
280 cs40l50->bin = bin; in cs40l50_dsp_bringup()
284 dev_err(cs40l50->dev, "Failed to reset DSP: %d\n", ret); in cs40l50_dsp_bringup()
288 ret = regmap_read(cs40l50->regmap, CS40L50_NUM_WAVES, &nwaves); in cs40l50_dsp_bringup()
292 dev_info(cs40l50->dev, "%u RAM effects loaded\n", nwaves); in cs40l50_dsp_bringup()
294 /* Add teardown actions for first-time bringup */ in cs40l50_dsp_bringup()
295 ret = devm_add_action_or_reset(cs40l50->dev, cs40l50_dsp_power_down, in cs40l50_dsp_bringup()
296 &cs40l50->dsp); in cs40l50_dsp_bringup()
298 dev_err(cs40l50->dev, "Failed to add power down action: %d\n", ret); in cs40l50_dsp_bringup()
302 ret = devm_add_action_or_reset(cs40l50->dev, cs40l50_dsp_stop, &cs40l50->dsp); in cs40l50_dsp_bringup()
304 dev_err(cs40l50->dev, "Failed to add stop action: %d\n", ret); in cs40l50_dsp_bringup()
306 release_firmware(cs40l50->bin); in cs40l50_dsp_bringup()
307 release_firmware(cs40l50->fw); in cs40l50_dsp_bringup()
316 dev_err(cs40l50->dev, "No firmware file found\n"); in cs40l50_request_firmware()
320 cs40l50->fw = fw; in cs40l50_request_firmware()
323 cs40l50->dev, GFP_KERNEL, cs40l50, in cs40l50_request_firmware()
326 dev_err(cs40l50->dev, "Failed to request %s: %d\n", CS40L50_WT, ret); in cs40l50_request_firmware()
327 release_firmware(cs40l50->fw); in cs40l50_request_firmware()
337 { "DSP", },
357 mutex_lock(&cs40l50->lock); in cs40l50_hw_err()
362 dev_err(cs40l50->dev, "%s error\n", cs40l50_irqs[i].name); in cs40l50_hw_err()
363 ret = regmap_multi_reg_write(cs40l50->regmap, cs40l50_err_rls, in cs40l50_hw_err()
369 mutex_unlock(&cs40l50->lock); in cs40l50_hw_err()
379 mutex_lock(&cs40l50->lock); in cs40l50_dsp_queue()
381 /* Read from DSP queue, log, and update read pointer */ in cs40l50_dsp_queue()
383 ret = regmap_read(cs40l50->regmap, CS40L50_DSP_QUEUE_WT, &wt_ptr); in cs40l50_dsp_queue()
387 ret = regmap_read(cs40l50->regmap, CS40L50_DSP_QUEUE_RD, &rd_ptr); in cs40l50_dsp_queue()
395 ret = regmap_read(cs40l50->regmap, rd_ptr, &val); in cs40l50_dsp_queue()
399 dev_dbg(cs40l50->dev, "DSP payload: %#X", val); in cs40l50_dsp_queue()
406 ret = regmap_write(cs40l50->regmap, CS40L50_DSP_QUEUE_RD, rd_ptr); in cs40l50_dsp_queue()
409 mutex_unlock(&cs40l50->lock); in cs40l50_dsp_queue()
418 ret = devm_regmap_add_irq_chip(cs40l50->dev, cs40l50->regmap, cs40l50->irq, in cs40l50_irq_init()
420 &cs40l50_irq_chip, &cs40l50->irq_data); in cs40l50_irq_init()
422 dev_err(cs40l50->dev, "Failed adding IRQ chip\n"); in cs40l50_irq_init()
427 virq = regmap_irq_get_virq(cs40l50->irq_data, i); in cs40l50_irq_init()
429 dev_err(cs40l50->dev, "Failed getting virq for %s\n", in cs40l50_irq_init()
436 /* Handle DSP and hardware interrupts separately */ in cs40l50_irq_init()
437 ret = devm_request_threaded_irq(cs40l50->dev, virq, NULL, in cs40l50_irq_init()
442 return dev_err_probe(cs40l50->dev, ret, in cs40l50_irq_init()
455 ret = regmap_read(cs40l50->regmap, CS40L50_DEVID, &cs40l50->devid); in cs40l50_get_model()
459 if (cs40l50->devid != CS40L50_DEVID_A) in cs40l50_get_model()
460 return -EINVAL; in cs40l50_get_model()
462 ret = regmap_read(cs40l50->regmap, CS40L50_REVID, &cs40l50->revid); in cs40l50_get_model()
466 if (cs40l50->revid < CS40L50_REVID_B0) in cs40l50_get_model()
467 return -EINVAL; in cs40l50_get_model()
469 dev_dbg(cs40l50->dev, "Cirrus Logic CS40L50 rev. %02X\n", cs40l50->revid); in cs40l50_get_model()
490 struct device *dev = cs40l50->dev; in cs40l50_probe()
493 mutex_init(&cs40l50->lock); in cs40l50_probe()
495 cs40l50->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH); in cs40l50_probe()
496 if (IS_ERR(cs40l50->reset_gpio)) in cs40l50_probe()
497 return dev_err_probe(dev, PTR_ERR(cs40l50->reset_gpio), in cs40l50_probe()
508 gpiod_set_value_cansleep(cs40l50->reset_gpio, 0); in cs40l50_probe()
519 return dev_err_probe(dev, ret, "Failed to initialize DSP\n"); in cs40l50_probe()
543 gpiod_set_value_cansleep(cs40l50->reset_gpio, 1); in cs40l50_remove()
553 return regmap_write(cs40l50->regmap, CS40L50_DSP_QUEUE, CS40L50_ALLOW_HIBER); in cs40l50_runtime_suspend()
560 return cs40l50_dsp_write(dev, cs40l50->regmap, CS40L50_PREVENT_HIBER); in cs40l50_runtime_resume()