brintos

brintos / linux-shallow public Read only

0
0
Text · 28.3 KiB · e45e9ae Raw
973 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2//3// Components shared between ASoC and HDA CS35L56 drivers4//5// Copyright (C) 2023 Cirrus Logic, Inc. and6//                    Cirrus Logic International Semiconductor Ltd.7 8#include <linux/array_size.h>9#include <linux/firmware/cirrus/wmfw.h>10#include <linux/gpio/consumer.h>11#include <linux/regmap.h>12#include <linux/regulator/consumer.h>13#include <linux/types.h>14#include <sound/cs-amp-lib.h>15 16#include "cs35l56.h"17 18static const struct reg_sequence cs35l56_patch[] = {19	/*20	 * Firmware can change these to non-defaults to satisfy SDCA.21	 * Ensure that they are at known defaults.22	 */23	{ CS35L56_ASP1_ENABLES1,		0x00000000 },24	{ CS35L56_ASP1_CONTROL1,		0x00000028 },25	{ CS35L56_ASP1_CONTROL2,		0x18180200 },26	{ CS35L56_ASP1_CONTROL3,		0x00000002 },27	{ CS35L56_ASP1_FRAME_CONTROL1,		0x03020100 },28	{ CS35L56_ASP1_FRAME_CONTROL5,		0x00020100 },29	{ CS35L56_ASP1_DATA_CONTROL1,		0x00000018 },30	{ CS35L56_ASP1_DATA_CONTROL5,		0x00000018 },31	{ CS35L56_ASP1TX1_INPUT,		0x00000000 },32	{ CS35L56_ASP1TX2_INPUT,		0x00000000 },33	{ CS35L56_ASP1TX3_INPUT,		0x00000000 },34	{ CS35L56_ASP1TX4_INPUT,		0x00000000 },35	{ CS35L56_SWIRE_DP3_CH1_INPUT,		0x00000018 },36	{ CS35L56_SWIRE_DP3_CH2_INPUT,		0x00000019 },37	{ CS35L56_SWIRE_DP3_CH3_INPUT,		0x00000029 },38	{ CS35L56_SWIRE_DP3_CH4_INPUT,		0x00000028 },39	{ CS35L56_IRQ1_MASK_18,			0x1f7df0ff },40 41	/* These are not reset by a soft-reset, so patch to defaults. */42	{ CS35L56_MAIN_RENDER_USER_MUTE,	0x00000000 },43	{ CS35L56_MAIN_RENDER_USER_VOLUME,	0x00000000 },44	{ CS35L56_MAIN_POSTURE_NUMBER,		0x00000000 },45};46 47int cs35l56_set_patch(struct cs35l56_base *cs35l56_base)48{49	return regmap_register_patch(cs35l56_base->regmap, cs35l56_patch,50				     ARRAY_SIZE(cs35l56_patch));51}52EXPORT_SYMBOL_NS_GPL(cs35l56_set_patch, SND_SOC_CS35L56_SHARED);53 54static const struct reg_default cs35l56_reg_defaults[] = {55	/* no defaults for OTP_MEM - first read populates cache */56 57	{ CS35L56_ASP1_ENABLES1,		0x00000000 },58	{ CS35L56_ASP1_CONTROL1,		0x00000028 },59	{ CS35L56_ASP1_CONTROL2,		0x18180200 },60	{ CS35L56_ASP1_CONTROL3,		0x00000002 },61	{ CS35L56_ASP1_FRAME_CONTROL1,		0x03020100 },62	{ CS35L56_ASP1_FRAME_CONTROL5,		0x00020100 },63	{ CS35L56_ASP1_DATA_CONTROL1,		0x00000018 },64	{ CS35L56_ASP1_DATA_CONTROL5,		0x00000018 },65	{ CS35L56_ASP1TX1_INPUT,		0x00000000 },66	{ CS35L56_ASP1TX2_INPUT,		0x00000000 },67	{ CS35L56_ASP1TX3_INPUT,		0x00000000 },68	{ CS35L56_ASP1TX4_INPUT,		0x00000000 },69	{ CS35L56_SWIRE_DP3_CH1_INPUT,		0x00000018 },70	{ CS35L56_SWIRE_DP3_CH2_INPUT,		0x00000019 },71	{ CS35L56_SWIRE_DP3_CH3_INPUT,		0x00000029 },72	{ CS35L56_SWIRE_DP3_CH4_INPUT,		0x00000028 },73	{ CS35L56_IRQ1_MASK_1,			0x83ffffff },74	{ CS35L56_IRQ1_MASK_2,			0xffff7fff },75	{ CS35L56_IRQ1_MASK_4,			0xe0ffffff },76	{ CS35L56_IRQ1_MASK_8,			0xfc000fff },77	{ CS35L56_IRQ1_MASK_18,			0x1f7df0ff },78	{ CS35L56_IRQ1_MASK_20,			0x15c00000 },79	{ CS35L56_MAIN_RENDER_USER_MUTE,	0x00000000 },80	{ CS35L56_MAIN_RENDER_USER_VOLUME,	0x00000000 },81	{ CS35L56_MAIN_POSTURE_NUMBER,		0x00000000 },82};83 84static bool cs35l56_is_dsp_memory(unsigned int reg)85{86	switch (reg) {87	case CS35L56_DSP1_XMEM_PACKED_0 ... CS35L56_DSP1_XMEM_PACKED_6143:88	case CS35L56_DSP1_XMEM_UNPACKED32_0 ... CS35L56_DSP1_XMEM_UNPACKED32_4095:89	case CS35L56_DSP1_XMEM_UNPACKED24_0 ... CS35L56_DSP1_XMEM_UNPACKED24_8191:90	case CS35L56_DSP1_YMEM_PACKED_0 ... CS35L56_DSP1_YMEM_PACKED_4604:91	case CS35L56_DSP1_YMEM_UNPACKED32_0 ... CS35L56_DSP1_YMEM_UNPACKED32_3070:92	case CS35L56_DSP1_YMEM_UNPACKED24_0 ... CS35L56_DSP1_YMEM_UNPACKED24_6141:93	case CS35L56_DSP1_PMEM_0 ... CS35L56_DSP1_PMEM_5114:94		return true;95	default:96		return false;97	}98}99 100static bool cs35l56_readable_reg(struct device *dev, unsigned int reg)101{102	switch (reg) {103	case CS35L56_DEVID:104	case CS35L56_REVID:105	case CS35L56_RELID:106	case CS35L56_OTPID:107	case CS35L56_SFT_RESET:108	case CS35L56_GLOBAL_ENABLES:109	case CS35L56_BLOCK_ENABLES:110	case CS35L56_BLOCK_ENABLES2:111	case CS35L56_REFCLK_INPUT:112	case CS35L56_GLOBAL_SAMPLE_RATE:113	case CS35L56_OTP_MEM_53:114	case CS35L56_OTP_MEM_54:115	case CS35L56_OTP_MEM_55:116	case CS35L56_ASP1_ENABLES1:117	case CS35L56_ASP1_CONTROL1:118	case CS35L56_ASP1_CONTROL2:119	case CS35L56_ASP1_CONTROL3:120	case CS35L56_ASP1_FRAME_CONTROL1:121	case CS35L56_ASP1_FRAME_CONTROL5:122	case CS35L56_ASP1_DATA_CONTROL1:123	case CS35L56_ASP1_DATA_CONTROL5:124	case CS35L56_DACPCM1_INPUT:125	case CS35L56_DACPCM2_INPUT:126	case CS35L56_ASP1TX1_INPUT:127	case CS35L56_ASP1TX2_INPUT:128	case CS35L56_ASP1TX3_INPUT:129	case CS35L56_ASP1TX4_INPUT:130	case CS35L56_DSP1RX1_INPUT:131	case CS35L56_DSP1RX2_INPUT:132	case CS35L56_SWIRE_DP3_CH1_INPUT:133	case CS35L56_SWIRE_DP3_CH2_INPUT:134	case CS35L56_SWIRE_DP3_CH3_INPUT:135	case CS35L56_SWIRE_DP3_CH4_INPUT:136	case CS35L56_IRQ1_CFG:137	case CS35L56_IRQ1_STATUS:138	case CS35L56_IRQ1_EINT_1 ... CS35L56_IRQ1_EINT_8:139	case CS35L56_IRQ1_EINT_18:140	case CS35L56_IRQ1_EINT_20:141	case CS35L56_IRQ1_MASK_1:142	case CS35L56_IRQ1_MASK_2:143	case CS35L56_IRQ1_MASK_4:144	case CS35L56_IRQ1_MASK_8:145	case CS35L56_IRQ1_MASK_18:146	case CS35L56_IRQ1_MASK_20:147	case CS35L56_DSP_VIRTUAL1_MBOX_1:148	case CS35L56_DSP_VIRTUAL1_MBOX_2:149	case CS35L56_DSP_VIRTUAL1_MBOX_3:150	case CS35L56_DSP_VIRTUAL1_MBOX_4:151	case CS35L56_DSP_VIRTUAL1_MBOX_5:152	case CS35L56_DSP_VIRTUAL1_MBOX_6:153	case CS35L56_DSP_VIRTUAL1_MBOX_7:154	case CS35L56_DSP_VIRTUAL1_MBOX_8:155	case CS35L56_DSP_RESTRICT_STS1:156	case CS35L56_DSP1_SYS_INFO_ID ... CS35L56_DSP1_SYS_INFO_END:157	case CS35L56_DSP1_AHBM_WINDOW_DEBUG_0:158	case CS35L56_DSP1_AHBM_WINDOW_DEBUG_1:159	case CS35L56_DSP1_SCRATCH1:160	case CS35L56_DSP1_SCRATCH2:161	case CS35L56_DSP1_SCRATCH3:162	case CS35L56_DSP1_SCRATCH4:163		return true;164	default:165		return cs35l56_is_dsp_memory(reg);166	}167}168 169static bool cs35l56_precious_reg(struct device *dev, unsigned int reg)170{171	switch (reg) {172	case CS35L56_DSP1_XMEM_PACKED_0 ... CS35L56_DSP1_XMEM_PACKED_6143:173	case CS35L56_DSP1_YMEM_PACKED_0 ... CS35L56_DSP1_YMEM_PACKED_4604:174	case CS35L56_DSP1_PMEM_0 ... CS35L56_DSP1_PMEM_5114:175		return true;176	default:177		return false;178	}179}180 181static bool cs35l56_volatile_reg(struct device *dev, unsigned int reg)182{183	switch (reg) {184	case CS35L56_DEVID:185	case CS35L56_REVID:186	case CS35L56_RELID:187	case CS35L56_OTPID:188	case CS35L56_SFT_RESET:189	case CS35L56_GLOBAL_ENABLES:		   /* owned by firmware */190	case CS35L56_BLOCK_ENABLES:		   /* owned by firmware */191	case CS35L56_BLOCK_ENABLES2:		   /* owned by firmware */192	case CS35L56_REFCLK_INPUT:		   /* owned by firmware */193	case CS35L56_GLOBAL_SAMPLE_RATE:	   /* owned by firmware */194	case CS35L56_DACPCM1_INPUT:		   /* owned by firmware */195	case CS35L56_DACPCM2_INPUT:		   /* owned by firmware */196	case CS35L56_DSP1RX1_INPUT:		   /* owned by firmware */197	case CS35L56_DSP1RX2_INPUT:		   /* owned by firmware */198	case CS35L56_IRQ1_STATUS:199	case CS35L56_IRQ1_EINT_1 ... CS35L56_IRQ1_EINT_8:200	case CS35L56_IRQ1_EINT_18:201	case CS35L56_IRQ1_EINT_20:202	case CS35L56_DSP_VIRTUAL1_MBOX_1:203	case CS35L56_DSP_VIRTUAL1_MBOX_2:204	case CS35L56_DSP_VIRTUAL1_MBOX_3:205	case CS35L56_DSP_VIRTUAL1_MBOX_4:206	case CS35L56_DSP_VIRTUAL1_MBOX_5:207	case CS35L56_DSP_VIRTUAL1_MBOX_6:208	case CS35L56_DSP_VIRTUAL1_MBOX_7:209	case CS35L56_DSP_VIRTUAL1_MBOX_8:210	case CS35L56_DSP_RESTRICT_STS1:211	case CS35L56_DSP1_SYS_INFO_ID ... CS35L56_DSP1_SYS_INFO_END:212	case CS35L56_DSP1_AHBM_WINDOW_DEBUG_0:213	case CS35L56_DSP1_AHBM_WINDOW_DEBUG_1:214	case CS35L56_DSP1_SCRATCH1:215	case CS35L56_DSP1_SCRATCH2:216	case CS35L56_DSP1_SCRATCH3:217	case CS35L56_DSP1_SCRATCH4:218		return true;219	case CS35L56_MAIN_RENDER_USER_MUTE:220	case CS35L56_MAIN_RENDER_USER_VOLUME:221	case CS35L56_MAIN_POSTURE_NUMBER:222		return false;223	default:224		return cs35l56_is_dsp_memory(reg);225	}226}227 228int cs35l56_mbox_send(struct cs35l56_base *cs35l56_base, unsigned int command)229{230	unsigned int val;231	int ret;232 233	regmap_write(cs35l56_base->regmap, CS35L56_DSP_VIRTUAL1_MBOX_1, command);234	ret = regmap_read_poll_timeout(cs35l56_base->regmap, CS35L56_DSP_VIRTUAL1_MBOX_1,235				       val, (val == 0),236				       CS35L56_MBOX_POLL_US, CS35L56_MBOX_TIMEOUT_US);237	if (ret) {238		dev_warn(cs35l56_base->dev, "MBOX command %#x failed: %d\n", command, ret);239		return ret;240	}241 242	return 0;243}244EXPORT_SYMBOL_NS_GPL(cs35l56_mbox_send, SND_SOC_CS35L56_SHARED);245 246int cs35l56_firmware_shutdown(struct cs35l56_base *cs35l56_base)247{248	int ret;249	unsigned int val;250 251	ret = cs35l56_mbox_send(cs35l56_base, CS35L56_MBOX_CMD_SHUTDOWN);252	if (ret)253		return ret;254 255	ret = regmap_read_poll_timeout(cs35l56_base->regmap,  CS35L56_DSP1_PM_CUR_STATE,256				       val, (val == CS35L56_HALO_STATE_SHUTDOWN),257				       CS35L56_HALO_STATE_POLL_US,258				       CS35L56_HALO_STATE_TIMEOUT_US);259	if (ret < 0)260		dev_err(cs35l56_base->dev, "Failed to poll PM_CUR_STATE to 1 is %d (ret %d)\n",261			val, ret);262	return ret;263}264EXPORT_SYMBOL_NS_GPL(cs35l56_firmware_shutdown, SND_SOC_CS35L56_SHARED);265 266int cs35l56_wait_for_firmware_boot(struct cs35l56_base *cs35l56_base)267{268	unsigned int val = 0;269	int read_ret, poll_ret;270 271	/*272	 * The regmap must remain in cache-only until the chip has273	 * booted, so use a bypassed read of the status register.274	 */275	poll_ret = read_poll_timeout(regmap_read_bypassed, read_ret,276				     (val < 0xFFFF) && (val >= CS35L56_HALO_STATE_BOOT_DONE),277				     CS35L56_HALO_STATE_POLL_US,278				     CS35L56_HALO_STATE_TIMEOUT_US,279				     false,280				     cs35l56_base->regmap, CS35L56_DSP1_HALO_STATE, &val);281 282	if (poll_ret) {283		dev_err(cs35l56_base->dev, "Firmware boot timed out(%d): HALO_STATE=%#x\n",284			read_ret, val);285		return -EIO;286	}287 288	return 0;289}290EXPORT_SYMBOL_NS_GPL(cs35l56_wait_for_firmware_boot, SND_SOC_CS35L56_SHARED);291 292void cs35l56_wait_control_port_ready(void)293{294	/* Wait for control port to be ready (datasheet tIRS). */295	usleep_range(CS35L56_CONTROL_PORT_READY_US, 2 * CS35L56_CONTROL_PORT_READY_US);296}297EXPORT_SYMBOL_NS_GPL(cs35l56_wait_control_port_ready, SND_SOC_CS35L56_SHARED);298 299void cs35l56_wait_min_reset_pulse(void)300{301	/* Satisfy minimum reset pulse width spec */302	usleep_range(CS35L56_RESET_PULSE_MIN_US, 2 * CS35L56_RESET_PULSE_MIN_US);303}304EXPORT_SYMBOL_NS_GPL(cs35l56_wait_min_reset_pulse, SND_SOC_CS35L56_SHARED);305 306static const struct reg_sequence cs35l56_system_reset_seq[] = {307	REG_SEQ0(CS35L56_DSP1_HALO_STATE, 0),308	REG_SEQ0(CS35L56_DSP_VIRTUAL1_MBOX_1, CS35L56_MBOX_CMD_SYSTEM_RESET),309};310 311void cs35l56_system_reset(struct cs35l56_base *cs35l56_base, bool is_soundwire)312{313	/*314	 * Must enter cache-only first so there can't be any more register315	 * accesses other than the controlled system reset sequence below.316	 */317	regcache_cache_only(cs35l56_base->regmap, true);318	regmap_multi_reg_write_bypassed(cs35l56_base->regmap,319					cs35l56_system_reset_seq,320					ARRAY_SIZE(cs35l56_system_reset_seq));321 322	/* On SoundWire the registers won't be accessible until it re-enumerates. */323	if (is_soundwire)324		return;325 326	cs35l56_wait_control_port_ready();327 328	/* Leave in cache-only. This will be revoked when the chip has rebooted. */329}330EXPORT_SYMBOL_NS_GPL(cs35l56_system_reset, SND_SOC_CS35L56_SHARED);331 332int cs35l56_irq_request(struct cs35l56_base *cs35l56_base, int irq)333{334	int ret;335 336	if (irq < 1)337		return 0;338 339	ret = devm_request_threaded_irq(cs35l56_base->dev, irq, NULL, cs35l56_irq,340					IRQF_ONESHOT | IRQF_SHARED | IRQF_TRIGGER_LOW,341					"cs35l56", cs35l56_base);342	if (!ret)343		cs35l56_base->irq = irq;344	else345		dev_err(cs35l56_base->dev, "Failed to get IRQ: %d\n", ret);346 347	return ret;348}349EXPORT_SYMBOL_NS_GPL(cs35l56_irq_request, SND_SOC_CS35L56_SHARED);350 351irqreturn_t cs35l56_irq(int irq, void *data)352{353	struct cs35l56_base *cs35l56_base = data;354	unsigned int status1 = 0, status8 = 0, status20 = 0;355	unsigned int mask1, mask8, mask20;356	unsigned int val;357	int rv;358 359	irqreturn_t ret = IRQ_NONE;360 361	if (!cs35l56_base->init_done)362		return IRQ_NONE;363 364	mutex_lock(&cs35l56_base->irq_lock);365 366	rv = pm_runtime_resume_and_get(cs35l56_base->dev);367	if (rv < 0) {368		dev_err(cs35l56_base->dev, "irq: failed to get pm_runtime: %d\n", rv);369		goto err_unlock;370	}371 372	regmap_read(cs35l56_base->regmap, CS35L56_IRQ1_STATUS, &val);373	if ((val & CS35L56_IRQ1_STS_MASK) == 0) {374		dev_dbg(cs35l56_base->dev, "Spurious IRQ: no pending interrupt\n");375		goto err;376	}377 378	/* Ack interrupts */379	regmap_read(cs35l56_base->regmap, CS35L56_IRQ1_EINT_1, &status1);380	regmap_read(cs35l56_base->regmap, CS35L56_IRQ1_MASK_1, &mask1);381	status1 &= ~mask1;382	regmap_write(cs35l56_base->regmap, CS35L56_IRQ1_EINT_1, status1);383 384	regmap_read(cs35l56_base->regmap, CS35L56_IRQ1_EINT_8, &status8);385	regmap_read(cs35l56_base->regmap, CS35L56_IRQ1_MASK_8, &mask8);386	status8 &= ~mask8;387	regmap_write(cs35l56_base->regmap, CS35L56_IRQ1_EINT_8, status8);388 389	regmap_read(cs35l56_base->regmap, CS35L56_IRQ1_EINT_20, &status20);390	regmap_read(cs35l56_base->regmap, CS35L56_IRQ1_MASK_20, &mask20);391	status20 &= ~mask20;392	/* We don't want EINT20 but they default to unmasked: force mask */393	regmap_write(cs35l56_base->regmap, CS35L56_IRQ1_MASK_20, 0xffffffff);394 395	dev_dbg(cs35l56_base->dev, "%s: %#x %#x\n", __func__, status1, status8);396 397	/* Check to see if unmasked bits are active */398	if (!status1 && !status8 && !status20)399		goto err;400 401	if (status1 & CS35L56_AMP_SHORT_ERR_EINT1_MASK)402		dev_crit(cs35l56_base->dev, "Amp short error\n");403 404	if (status8 & CS35L56_TEMP_ERR_EINT1_MASK)405		dev_crit(cs35l56_base->dev, "Overtemp error\n");406 407	ret = IRQ_HANDLED;408 409err:410	pm_runtime_put(cs35l56_base->dev);411err_unlock:412	mutex_unlock(&cs35l56_base->irq_lock);413 414	return ret;415}416EXPORT_SYMBOL_NS_GPL(cs35l56_irq, SND_SOC_CS35L56_SHARED);417 418int cs35l56_is_fw_reload_needed(struct cs35l56_base *cs35l56_base)419{420	unsigned int val;421	int ret;422 423	/*424	 * In secure mode FIRMWARE_MISSING is cleared by the BIOS loader so425	 * can't be used here to test for memory retention.426	 * Assume that tuning must be re-loaded.427	 */428	if (cs35l56_base->secured)429		return true;430 431	ret = pm_runtime_resume_and_get(cs35l56_base->dev);432	if (ret) {433		dev_err(cs35l56_base->dev, "Failed to runtime_get: %d\n", ret);434		return ret;435	}436 437	ret = regmap_read(cs35l56_base->regmap, CS35L56_PROTECTION_STATUS, &val);438	if (ret)439		dev_err(cs35l56_base->dev, "Failed to read PROTECTION_STATUS: %d\n", ret);440	else441		ret = !!(val & CS35L56_FIRMWARE_MISSING);442 443	pm_runtime_put_autosuspend(cs35l56_base->dev);444 445	return ret;446}447EXPORT_SYMBOL_NS_GPL(cs35l56_is_fw_reload_needed, SND_SOC_CS35L56_SHARED);448 449static const struct reg_sequence cs35l56_hibernate_seq[] = {450	/* This must be the last register access */451	REG_SEQ0(CS35L56_DSP_VIRTUAL1_MBOX_1, CS35L56_MBOX_CMD_ALLOW_AUTO_HIBERNATE),452};453 454static void cs35l56_issue_wake_event(struct cs35l56_base *cs35l56_base)455{456	unsigned int val;457 458	/*459	 * Dummy transactions to trigger I2C/SPI auto-wake. Issue two460	 * transactions to meet the minimum required time from the rising edge461	 * to the last falling edge of wake.462	 *463	 * It uses bypassed read because we must wake the chip before464	 * disabling regmap cache-only.465	 */466	regmap_read_bypassed(cs35l56_base->regmap, CS35L56_IRQ1_STATUS, &val);467 468	usleep_range(CS35L56_WAKE_HOLD_TIME_US, 2 * CS35L56_WAKE_HOLD_TIME_US);469 470	regmap_read_bypassed(cs35l56_base->regmap, CS35L56_IRQ1_STATUS, &val);471 472	cs35l56_wait_control_port_ready();473}474 475int cs35l56_runtime_suspend_common(struct cs35l56_base *cs35l56_base)476{477	unsigned int val;478	int ret;479 480	if (!cs35l56_base->init_done)481		return 0;482 483	/* Firmware must have entered a power-save state */484	ret = regmap_read_poll_timeout(cs35l56_base->regmap,485				       CS35L56_TRANSDUCER_ACTUAL_PS,486				       val, (val >= CS35L56_PS3),487				       CS35L56_PS3_POLL_US,488				       CS35L56_PS3_TIMEOUT_US);489	if (ret)490		dev_warn(cs35l56_base->dev, "PS3 wait failed: %d\n", ret);491 492	/* Clear BOOT_DONE so it can be used to detect a reboot */493	regmap_write(cs35l56_base->regmap, CS35L56_IRQ1_EINT_4, CS35L56_OTP_BOOT_DONE_MASK);494 495	if (!cs35l56_base->can_hibernate) {496		regcache_cache_only(cs35l56_base->regmap, true);497		dev_dbg(cs35l56_base->dev, "Suspended: no hibernate");498 499		return 0;500	}501 502	/*503	 * Must enter cache-only first so there can't be any more register504	 * accesses other than the controlled hibernate sequence below.505	 */506	regcache_cache_only(cs35l56_base->regmap, true);507 508	regmap_multi_reg_write_bypassed(cs35l56_base->regmap,509					cs35l56_hibernate_seq,510					ARRAY_SIZE(cs35l56_hibernate_seq));511 512	dev_dbg(cs35l56_base->dev, "Suspended: hibernate");513 514	return 0;515}516EXPORT_SYMBOL_NS_GPL(cs35l56_runtime_suspend_common, SND_SOC_CS35L56_SHARED);517 518int cs35l56_runtime_resume_common(struct cs35l56_base *cs35l56_base, bool is_soundwire)519{520	unsigned int val;521	int ret;522 523	if (!cs35l56_base->init_done)524		return 0;525 526	if (!cs35l56_base->can_hibernate)527		goto out_sync;528 529	/* Must be done before releasing cache-only */530	if (!is_soundwire)531		cs35l56_issue_wake_event(cs35l56_base);532 533out_sync:534	ret = cs35l56_wait_for_firmware_boot(cs35l56_base);535	if (ret) {536		dev_err(cs35l56_base->dev, "Hibernate wake failed: %d\n", ret);537		goto err;538	}539 540	regcache_cache_only(cs35l56_base->regmap, false);541 542	ret = cs35l56_mbox_send(cs35l56_base, CS35L56_MBOX_CMD_PREVENT_AUTO_HIBERNATE);543	if (ret)544		goto err;545 546	/* BOOT_DONE will be 1 if the amp reset */547	regmap_read(cs35l56_base->regmap, CS35L56_IRQ1_EINT_4, &val);548	if (val & CS35L56_OTP_BOOT_DONE_MASK) {549		dev_dbg(cs35l56_base->dev, "Registers reset in suspend\n");550		regcache_mark_dirty(cs35l56_base->regmap);551	}552 553	regcache_sync(cs35l56_base->regmap);554 555	dev_dbg(cs35l56_base->dev, "Resumed");556 557	return 0;558 559err:560	regcache_cache_only(cs35l56_base->regmap, true);561 562	regmap_multi_reg_write_bypassed(cs35l56_base->regmap,563					cs35l56_hibernate_seq,564					ARRAY_SIZE(cs35l56_hibernate_seq));565 566	return ret;567}568EXPORT_SYMBOL_NS_GPL(cs35l56_runtime_resume_common, SND_SOC_CS35L56_SHARED);569 570static const struct cs_dsp_region cs35l56_dsp1_regions[] = {571	{ .type = WMFW_HALO_PM_PACKED,	.base = CS35L56_DSP1_PMEM_0 },572	{ .type = WMFW_HALO_XM_PACKED,	.base = CS35L56_DSP1_XMEM_PACKED_0 },573	{ .type = WMFW_HALO_YM_PACKED,	.base = CS35L56_DSP1_YMEM_PACKED_0 },574	{ .type = WMFW_ADSP2_XM,	.base = CS35L56_DSP1_XMEM_UNPACKED24_0 },575	{ .type = WMFW_ADSP2_YM,	.base = CS35L56_DSP1_YMEM_UNPACKED24_0 },576};577 578void cs35l56_init_cs_dsp(struct cs35l56_base *cs35l56_base, struct cs_dsp *cs_dsp)579{580	cs_dsp->num = 1;581	cs_dsp->type = WMFW_HALO;582	cs_dsp->rev = 0;583	cs_dsp->dev = cs35l56_base->dev;584	cs_dsp->regmap = cs35l56_base->regmap;585	cs_dsp->base = CS35L56_DSP1_CORE_BASE;586	cs_dsp->base_sysinfo = CS35L56_DSP1_SYS_INFO_ID;587	cs_dsp->mem = cs35l56_dsp1_regions;588	cs_dsp->num_mems = ARRAY_SIZE(cs35l56_dsp1_regions);589	cs_dsp->no_core_startstop = true;590}591EXPORT_SYMBOL_NS_GPL(cs35l56_init_cs_dsp, SND_SOC_CS35L56_SHARED);592 593struct cs35l56_pte {594	u8 x;595	u8 wafer_id;596	u8 pte[2];597	u8 lot[3];598	u8 y;599	u8 unused[3];600	u8 dvs;601} __packed;602static_assert((sizeof(struct cs35l56_pte) % sizeof(u32)) == 0);603 604static int cs35l56_read_silicon_uid(struct cs35l56_base *cs35l56_base, u64 *uid)605{606	struct cs35l56_pte pte;607	u64 unique_id;608	int ret;609 610	ret = regmap_raw_read(cs35l56_base->regmap, CS35L56_OTP_MEM_53, &pte, sizeof(pte));611	if (ret) {612		dev_err(cs35l56_base->dev, "Failed to read OTP: %d\n", ret);613		return ret;614	}615 616	unique_id = (u32)pte.lot[2] | ((u32)pte.lot[1] << 8) | ((u32)pte.lot[0] << 16);617	unique_id <<= 32;618	unique_id |= (u32)pte.x | ((u32)pte.y << 8) | ((u32)pte.wafer_id << 16) |619		     ((u32)pte.dvs << 24);620 621	dev_dbg(cs35l56_base->dev, "UniqueID = %#llx\n", unique_id);622 623	*uid = unique_id;624 625	return 0;626}627 628/* Firmware calibration controls */629const struct cirrus_amp_cal_controls cs35l56_calibration_controls = {630	.alg_id =	0x9f210,631	.mem_region =	WMFW_ADSP2_YM,632	.ambient =	"CAL_AMBIENT",633	.calr =		"CAL_R",634	.status =	"CAL_STATUS",635	.checksum =	"CAL_CHECKSUM",636};637EXPORT_SYMBOL_NS_GPL(cs35l56_calibration_controls, SND_SOC_CS35L56_SHARED);638 639int cs35l56_get_calibration(struct cs35l56_base *cs35l56_base)640{641	u64 silicon_uid = 0;642	int ret;643 644	/* Driver can't apply calibration to a secured part, so skip */645	if (cs35l56_base->secured)646		return 0;647 648	ret = cs35l56_read_silicon_uid(cs35l56_base, &silicon_uid);649	if (ret < 0)650		return ret;651 652	ret = cs_amp_get_efi_calibration_data(cs35l56_base->dev, silicon_uid,653					      cs35l56_base->cal_index,654					      &cs35l56_base->cal_data);655 656	/* Only return an error status if probe should be aborted */657	if ((ret == -ENOENT) || (ret == -EOVERFLOW))658		return 0;659 660	if (ret < 0)661		return ret;662 663	cs35l56_base->cal_data_valid = true;664 665	return 0;666}667EXPORT_SYMBOL_NS_GPL(cs35l56_get_calibration, SND_SOC_CS35L56_SHARED);668 669int cs35l56_read_prot_status(struct cs35l56_base *cs35l56_base,670			     bool *fw_missing, unsigned int *fw_version)671{672	unsigned int prot_status;673	int ret;674 675	ret = regmap_read(cs35l56_base->regmap, CS35L56_PROTECTION_STATUS, &prot_status);676	if (ret) {677		dev_err(cs35l56_base->dev, "Get PROTECTION_STATUS failed: %d\n", ret);678		return ret;679	}680 681	*fw_missing = !!(prot_status & CS35L56_FIRMWARE_MISSING);682 683	ret = regmap_read(cs35l56_base->regmap, CS35L56_DSP1_FW_VER, fw_version);684	if (ret) {685		dev_err(cs35l56_base->dev, "Get FW VER failed: %d\n", ret);686		return ret;687	}688 689	return 0;690}691EXPORT_SYMBOL_NS_GPL(cs35l56_read_prot_status, SND_SOC_CS35L56_SHARED);692 693int cs35l56_hw_init(struct cs35l56_base *cs35l56_base)694{695	int ret;696	unsigned int devid, revid, otpid, secured, fw_ver;697	bool fw_missing;698 699	/*700	 * When the system is not using a reset_gpio ensure the device is701	 * awake, otherwise the device has just been released from reset and702	 * the driver must wait for the control port to become usable.703	 */704	if (!cs35l56_base->reset_gpio)705		cs35l56_issue_wake_event(cs35l56_base);706	else707		cs35l56_wait_control_port_ready();708 709	ret = regmap_read_bypassed(cs35l56_base->regmap, CS35L56_REVID, &revid);710	if (ret < 0) {711		dev_err(cs35l56_base->dev, "Get Revision ID failed\n");712		return ret;713	}714	cs35l56_base->rev = revid & (CS35L56_AREVID_MASK | CS35L56_MTLREVID_MASK);715 716	ret = cs35l56_wait_for_firmware_boot(cs35l56_base);717	if (ret)718		return ret;719 720	ret = regmap_read_bypassed(cs35l56_base->regmap, CS35L56_DEVID, &devid);721	if (ret < 0) {722		dev_err(cs35l56_base->dev, "Get Device ID failed\n");723		return ret;724	}725	devid &= CS35L56_DEVID_MASK;726 727	switch (devid) {728	case 0x35A54:729	case 0x35A56:730	case 0x35A57:731		break;732	default:733		dev_err(cs35l56_base->dev, "Unknown device %x\n", devid);734		return ret;735	}736 737	cs35l56_base->type = devid & 0xFF;738 739	/* Silicon is now identified and booted so exit cache-only */740	regcache_cache_only(cs35l56_base->regmap, false);741 742	ret = regmap_read(cs35l56_base->regmap, CS35L56_DSP_RESTRICT_STS1, &secured);743	if (ret) {744		dev_err(cs35l56_base->dev, "Get Secure status failed\n");745		return ret;746	}747 748	/* When any bus is restricted treat the device as secured */749	if (secured & CS35L56_RESTRICTED_MASK)750		cs35l56_base->secured = true;751 752	ret = regmap_read(cs35l56_base->regmap, CS35L56_OTPID, &otpid);753	if (ret < 0) {754		dev_err(cs35l56_base->dev, "Get OTP ID failed\n");755		return ret;756	}757 758	ret = cs35l56_read_prot_status(cs35l56_base, &fw_missing, &fw_ver);759	if (ret)760		return ret;761 762	dev_info(cs35l56_base->dev, "Cirrus Logic CS35L%02X%s Rev %02X OTP%d fw:%d.%d.%d (patched=%u)\n",763		 cs35l56_base->type, cs35l56_base->secured ? "s" : "", cs35l56_base->rev, otpid,764		 fw_ver >> 16, (fw_ver >> 8) & 0xff, fw_ver & 0xff, !fw_missing);765 766	/* Wake source and *_BLOCKED interrupts default to unmasked, so mask them */767	regmap_write(cs35l56_base->regmap, CS35L56_IRQ1_MASK_20, 0xffffffff);768	regmap_update_bits(cs35l56_base->regmap, CS35L56_IRQ1_MASK_1,769			   CS35L56_AMP_SHORT_ERR_EINT1_MASK,770			   0);771	regmap_update_bits(cs35l56_base->regmap, CS35L56_IRQ1_MASK_8,772			   CS35L56_TEMP_ERR_EINT1_MASK,773			   0);774 775	return 0;776}777EXPORT_SYMBOL_NS_GPL(cs35l56_hw_init, SND_SOC_CS35L56_SHARED);778 779int cs35l56_get_speaker_id(struct cs35l56_base *cs35l56_base)780{781	struct gpio_descs *descs;782	u32 speaker_id;783	int i, ret;784 785	/* Attempt to read the speaker type from a device property first */786	ret = device_property_read_u32(cs35l56_base->dev, "cirrus,speaker-id", &speaker_id);787	if (!ret) {788		dev_dbg(cs35l56_base->dev, "Speaker ID = %d\n", speaker_id);789		return speaker_id;790	}791 792	/* Read the speaker type qualifier from the motherboard GPIOs */793	descs = gpiod_get_array_optional(cs35l56_base->dev, "spk-id", GPIOD_IN);794	if (!descs) {795		return -ENOENT;796	} else if (IS_ERR(descs)) {797		ret = PTR_ERR(descs);798		return dev_err_probe(cs35l56_base->dev, ret, "Failed to get spk-id-gpios\n");799	}800 801	speaker_id = 0;802	for (i = 0; i < descs->ndescs; i++) {803		ret = gpiod_get_value_cansleep(descs->desc[i]);804		if (ret < 0) {805			dev_err_probe(cs35l56_base->dev, ret, "Failed to read spk-id[%d]\n", i);806			goto err;807		}808 809		speaker_id |= (ret << i);810	}811 812	dev_dbg(cs35l56_base->dev, "Speaker ID = %d\n", speaker_id);813	ret = speaker_id;814err:815	gpiod_put_array(descs);816 817	return ret;818}819EXPORT_SYMBOL_NS_GPL(cs35l56_get_speaker_id, SND_SOC_CS35L56_SHARED);820 821static const u32 cs35l56_bclk_valid_for_pll_freq_table[] = {822	[0x0C] = 128000,823	[0x0F] = 256000,824	[0x11] = 384000,825	[0x12] = 512000,826	[0x15] = 768000,827	[0x17] = 1024000,828	[0x1A] = 1500000,829	[0x1B] = 1536000,830	[0x1C] = 2000000,831	[0x1D] = 2048000,832	[0x1E] = 2400000,833	[0x20] = 3000000,834	[0x21] = 3072000,835	[0x23] = 4000000,836	[0x24] = 4096000,837	[0x25] = 4800000,838	[0x27] = 6000000,839	[0x28] = 6144000,840	[0x29] = 6250000,841	[0x2A] = 6400000,842	[0x2E] = 8000000,843	[0x2F] = 8192000,844	[0x30] = 9600000,845	[0x32] = 12000000,846	[0x33] = 12288000,847	[0x37] = 13500000,848	[0x38] = 19200000,849	[0x39] = 22579200,850	[0x3B] = 24576000,851};852 853int cs35l56_get_bclk_freq_id(unsigned int freq)854{855	int i;856 857	if (freq == 0)858		return -EINVAL;859 860	/* The BCLK frequency must be a valid PLL REFCLK */861	for (i = 0; i < ARRAY_SIZE(cs35l56_bclk_valid_for_pll_freq_table); ++i) {862		if (cs35l56_bclk_valid_for_pll_freq_table[i] == freq)863			return i;864	}865 866	return -EINVAL;867}868EXPORT_SYMBOL_NS_GPL(cs35l56_get_bclk_freq_id, SND_SOC_CS35L56_SHARED);869 870static const char * const cs35l56_supplies[/* auto-sized */] = {871	"VDD_P",872	"VDD_IO",873	"VDD_A",874};875 876void cs35l56_fill_supply_names(struct regulator_bulk_data *data)877{878	int i;879 880	BUILD_BUG_ON(ARRAY_SIZE(cs35l56_supplies) != CS35L56_NUM_BULK_SUPPLIES);881	for (i = 0; i < ARRAY_SIZE(cs35l56_supplies); i++)882		data[i].supply = cs35l56_supplies[i];883}884EXPORT_SYMBOL_NS_GPL(cs35l56_fill_supply_names, SND_SOC_CS35L56_SHARED);885 886const char * const cs35l56_tx_input_texts[] = {887	"None", "ASP1RX1", "ASP1RX2", "VMON", "IMON", "ERRVOL", "CLASSH",888	"VDDBMON", "VBSTMON", "DSP1TX1", "DSP1TX2", "DSP1TX3", "DSP1TX4",889	"DSP1TX5", "DSP1TX6", "DSP1TX7", "DSP1TX8", "TEMPMON",890	"INTERPOLATOR", "SDW1RX1", "SDW1RX2",891};892EXPORT_SYMBOL_NS_GPL(cs35l56_tx_input_texts, SND_SOC_CS35L56_SHARED);893 894const unsigned int cs35l56_tx_input_values[] = {895	CS35L56_INPUT_SRC_NONE,896	CS35L56_INPUT_SRC_ASP1RX1,897	CS35L56_INPUT_SRC_ASP1RX2,898	CS35L56_INPUT_SRC_VMON,899	CS35L56_INPUT_SRC_IMON,900	CS35L56_INPUT_SRC_ERR_VOL,901	CS35L56_INPUT_SRC_CLASSH,902	CS35L56_INPUT_SRC_VDDBMON,903	CS35L56_INPUT_SRC_VBSTMON,904	CS35L56_INPUT_SRC_DSP1TX1,905	CS35L56_INPUT_SRC_DSP1TX2,906	CS35L56_INPUT_SRC_DSP1TX3,907	CS35L56_INPUT_SRC_DSP1TX4,908	CS35L56_INPUT_SRC_DSP1TX5,909	CS35L56_INPUT_SRC_DSP1TX6,910	CS35L56_INPUT_SRC_DSP1TX7,911	CS35L56_INPUT_SRC_DSP1TX8,912	CS35L56_INPUT_SRC_TEMPMON,913	CS35L56_INPUT_SRC_INTERPOLATOR,914	CS35L56_INPUT_SRC_SWIRE_DP1_CHANNEL1,915	CS35L56_INPUT_SRC_SWIRE_DP1_CHANNEL2,916};917EXPORT_SYMBOL_NS_GPL(cs35l56_tx_input_values, SND_SOC_CS35L56_SHARED);918 919const struct regmap_config cs35l56_regmap_i2c = {920	.reg_bits = 32,921	.val_bits = 32,922	.reg_stride = 4,923	.reg_format_endian = REGMAP_ENDIAN_BIG,924	.val_format_endian = REGMAP_ENDIAN_BIG,925	.max_register = CS35L56_DSP1_PMEM_5114,926	.reg_defaults = cs35l56_reg_defaults,927	.num_reg_defaults = ARRAY_SIZE(cs35l56_reg_defaults),928	.volatile_reg = cs35l56_volatile_reg,929	.readable_reg = cs35l56_readable_reg,930	.precious_reg = cs35l56_precious_reg,931	.cache_type = REGCACHE_MAPLE,932};933EXPORT_SYMBOL_NS_GPL(cs35l56_regmap_i2c, SND_SOC_CS35L56_SHARED);934 935const struct regmap_config cs35l56_regmap_spi = {936	.reg_bits = 32,937	.val_bits = 32,938	.pad_bits = 16,939	.reg_stride = 4,940	.reg_format_endian = REGMAP_ENDIAN_BIG,941	.val_format_endian = REGMAP_ENDIAN_BIG,942	.max_register = CS35L56_DSP1_PMEM_5114,943	.reg_defaults = cs35l56_reg_defaults,944	.num_reg_defaults = ARRAY_SIZE(cs35l56_reg_defaults),945	.volatile_reg = cs35l56_volatile_reg,946	.readable_reg = cs35l56_readable_reg,947	.precious_reg = cs35l56_precious_reg,948	.cache_type = REGCACHE_MAPLE,949};950EXPORT_SYMBOL_NS_GPL(cs35l56_regmap_spi, SND_SOC_CS35L56_SHARED);951 952const struct regmap_config cs35l56_regmap_sdw = {953	.reg_bits = 32,954	.val_bits = 32,955	.reg_stride = 4,956	.reg_format_endian = REGMAP_ENDIAN_LITTLE,957	.val_format_endian = REGMAP_ENDIAN_BIG,958	.max_register = CS35L56_DSP1_PMEM_5114,959	.reg_defaults = cs35l56_reg_defaults,960	.num_reg_defaults = ARRAY_SIZE(cs35l56_reg_defaults),961	.volatile_reg = cs35l56_volatile_reg,962	.readable_reg = cs35l56_readable_reg,963	.precious_reg = cs35l56_precious_reg,964	.cache_type = REGCACHE_MAPLE,965};966EXPORT_SYMBOL_NS_GPL(cs35l56_regmap_sdw, SND_SOC_CS35L56_SHARED);967 968MODULE_DESCRIPTION("ASoC CS35L56 Shared");969MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");970MODULE_AUTHOR("Simon Trimmer <simont@opensource.cirrus.com>");971MODULE_LICENSE("GPL");972MODULE_IMPORT_NS(SND_SOC_CS_AMP_LIB);973