Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ASoC: cs35l56: Support for reading speaker ID from on-chip GPIOs

Add support for using the state of pins on the amplifier to indicate
the type of speaker fitted.

Previously, where there were alternate speaker vendors, this was
indicated using host CPU GPIOs.

Some new Dell models use spare pins on the CS35L63 as GPIOs for the
speaker ID detection.

Cirrus-specific SDCA Disco properties provide a list of the pins to be
used, and pull-up/down settings for the pads. This list is ordered,
MSbit to LSbit.

The code to set the firmware filename has been modified to check for
using chip pins for speaker ID. The entire block of code to set
firmware name has been moved out of cs35l56_component_probe() into
its own function to make it easier to KUnit test.

Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com>
Link: https://patch.msgid.link/20260205164838.1611295-2-rf@opensource.cirrus.com
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Richard Fitzgerald and committed by
Mark Brown
4d1e3e2c dc8384d8

+343 -4
+37
include/sound/cs35l56.h
··· 9 9 #ifndef __CS35L56_H 10 10 #define __CS35L56_H 11 11 12 + #include <linux/bits.h> 12 13 #include <linux/debugfs.h> 13 14 #include <linux/firmware/cirrus/cs_dsp.h> 14 15 #include <linux/regulator/consumer.h> ··· 27 26 #define CS35L56_GLOBAL_ENABLES 0x0002014 28 27 #define CS35L56_BLOCK_ENABLES 0x0002018 29 28 #define CS35L56_BLOCK_ENABLES2 0x000201C 29 + #define CS35L56_SYNC_GPIO1_CFG 0x0002410 30 + #define CS35L56_ASP2_DIO_GPIO13_CFG 0x0002440 31 + #define CS35L56_UPDATE_REGS 0x0002A0C 30 32 #define CS35L56_REFCLK_INPUT 0x0002C04 31 33 #define CS35L56_GLOBAL_SAMPLE_RATE 0x0002C0C 32 34 #define CS35L56_OTP_MEM_53 0x00300D4 ··· 69 65 #define CS35L56_IRQ1_MASK_8 0x000E0AC 70 66 #define CS35L56_IRQ1_MASK_18 0x000E0D4 71 67 #define CS35L56_IRQ1_MASK_20 0x000E0DC 68 + #define CS35L56_GPIO_STATUS1 0x000F000 69 + #define CS35L56_GPIO1_CTRL1 0x000F008 70 + #define CS35L56_GPIO13_CTRL1 0x000F038 72 71 #define CS35L56_MIXER_NGATE_CH1_CFG 0x0010004 73 72 #define CS35L56_MIXER_NGATE_CH2_CFG 0x0010008 74 73 #define CS35L56_DSP_MBOX_1_RAW 0x0011000 ··· 137 130 #define CS35L56_MTLREVID_MASK 0x0000000F 138 131 #define CS35L56_REVID_B0 0x000000B0 139 132 133 + /* PAD_INTF */ 134 + #define CS35L56_PAD_GPIO_PULL_MASK GENMASK(3, 2) 135 + #define CS35L56_PAD_GPIO_IE BIT(0) 136 + 137 + #define CS35L56_PAD_PULL_NONE 0 138 + #define CS35L56_PAD_PULL_UP 1 139 + #define CS35L56_PAD_PULL_DOWN 2 140 + 141 + /* UPDATE_REGS */ 142 + #define CS35L56_UPDT_GPIO_PRES BIT(6) 143 + 140 144 /* ASP_ENABLES1 */ 141 145 #define CS35L56_ASP_RX2_EN_SHIFT 17 142 146 #define CS35L56_ASP_RX1_EN_SHIFT 16 ··· 202 184 203 185 /* MIXER_NGATE_CHn_CFG */ 204 186 #define CS35L56_AUX_NGATE_CHn_EN 0x00000001 187 + 188 + /* GPIOn_CTRL1 */ 189 + #define CS35L56_GPIO_DIR_MASK BIT(31) 190 + #define CS35L56_GPIO_FN_MASK GENMASK(2, 0) 191 + 192 + #define CS35L56_GPIO_FN_GPIO 0x00000001 205 193 206 194 /* Mixer input sources */ 207 195 #define CS35L56_INPUT_SRC_NONE 0x00 ··· 303 279 #define CS35L56_HALO_STATE_TIMEOUT_US 250000 304 280 #define CS35L56_RESET_PULSE_MIN_US 1100 305 281 #define CS35L56_WAKE_HOLD_TIME_US 1000 282 + #define CS35L56_PAD_PULL_SETTLE_US 10 306 283 307 284 #define CS35L56_CALIBRATION_POLL_US (100 * USEC_PER_MSEC) 308 285 #define CS35L56_CALIBRATION_TIMEOUT_US (5 * USEC_PER_SEC) ··· 313 288 314 289 #define CS35L56_NUM_BULK_SUPPLIES 3 315 290 #define CS35L56_NUM_DSP_REGIONS 5 291 + 292 + #define CS35L56_MAX_GPIO 13 293 + #define CS35L63_MAX_GPIO 9 316 294 317 295 /* Additional margin for SYSTEM_RESET to control port ready on SPI */ 318 296 #define CS35L56_SPI_RESET_TO_PORT_READY_US (CS35L56_CONTROL_PORT_READY_US + 2500) ··· 366 338 const struct cirrus_amp_cal_controls *calibration_controls; 367 339 struct dentry *debugfs; 368 340 u64 silicon_uid; 341 + u8 onchip_spkid_gpios[5]; 342 + u8 num_onchip_spkid_gpios; 343 + u8 onchip_spkid_pulls[5]; 344 + u8 num_onchip_spkid_pulls; 369 345 }; 370 346 371 347 static inline bool cs35l56_is_otp_register(unsigned int reg) ··· 445 413 void cs35l56_log_tuning(struct cs35l56_base *cs35l56_base, struct cs_dsp *cs_dsp); 446 414 int cs35l56_hw_init(struct cs35l56_base *cs35l56_base); 447 415 int cs35l56_get_speaker_id(struct cs35l56_base *cs35l56_base); 416 + int cs35l56_check_and_save_onchip_spkid_gpios(struct cs35l56_base *cs35l56_base, 417 + const u32 *gpios, int num_gpios, 418 + const u32 *pulls, int num_pulls); 419 + int cs35l56_configure_onchip_spkid_pads(struct cs35l56_base *cs35l56_base); 420 + int cs35l56_read_onchip_spkid(struct cs35l56_base *cs35l56_base); 448 421 int cs35l56_get_bclk_freq_id(unsigned int freq); 449 422 void cs35l56_fill_supply_names(struct regulator_bulk_data *data); 450 423
+167
sound/soc/codecs/cs35l56-shared.c
··· 6 6 // Cirrus Logic International Semiconductor Ltd. 7 7 8 8 #include <linux/array_size.h> 9 + #include <linux/bitfield.h> 9 10 #include <linux/cleanup.h> 10 11 #include <linux/debugfs.h> 11 12 #include <linux/firmware/cirrus/wmfw.h> 12 13 #include <linux/fs.h> 13 14 #include <linux/gpio/consumer.h> 14 15 #include <linux/kstrtox.h> 16 + #include <linux/pm_runtime.h> 15 17 #include <linux/regmap.h> 16 18 #include <linux/regulator/consumer.h> 17 19 #include <linux/spi/spi.h> ··· 184 182 case CS35L56_OTP_MEM_53: 185 183 case CS35L56_OTP_MEM_54: 186 184 case CS35L56_OTP_MEM_55: 185 + case CS35L56_SYNC_GPIO1_CFG ... CS35L56_ASP2_DIO_GPIO13_CFG: 186 + case CS35L56_UPDATE_REGS: 187 187 case CS35L56_ASP1_ENABLES1: 188 188 case CS35L56_ASP1_CONTROL1: 189 189 case CS35L56_ASP1_CONTROL2: ··· 217 213 case CS35L56_IRQ1_MASK_8: 218 214 case CS35L56_IRQ1_MASK_18: 219 215 case CS35L56_IRQ1_MASK_20: 216 + case CS35L56_GPIO_STATUS1 ... CS35L56_GPIO13_CTRL1: 220 217 case CS35L56_MIXER_NGATE_CH1_CFG: 221 218 case CS35L56_MIXER_NGATE_CH2_CFG: 222 219 case CS35L56_DSP_VIRTUAL1_MBOX_1: ··· 267 262 case CS35L56_GLOBAL_ENABLES: /* owned by firmware */ 268 263 case CS35L56_BLOCK_ENABLES: /* owned by firmware */ 269 264 case CS35L56_BLOCK_ENABLES2: /* owned by firmware */ 265 + case CS35L56_SYNC_GPIO1_CFG ... CS35L56_ASP2_DIO_GPIO13_CFG: 266 + case CS35L56_UPDATE_REGS: 270 267 case CS35L56_REFCLK_INPUT: /* owned by firmware */ 271 268 case CS35L56_GLOBAL_SAMPLE_RATE: /* owned by firmware */ 272 269 case CS35L56_DACPCM1_INPUT: /* owned by firmware */ ··· 279 272 case CS35L56_IRQ1_EINT_1 ... CS35L56_IRQ1_EINT_8: 280 273 case CS35L56_IRQ1_EINT_18: 281 274 case CS35L56_IRQ1_EINT_20: 275 + case CS35L56_GPIO_STATUS1 ... CS35L56_GPIO13_CTRL1: 282 276 case CS35L56_MIXER_NGATE_CH1_CFG: 283 277 case CS35L56_MIXER_NGATE_CH2_CFG: 284 278 case CS35L56_DSP_VIRTUAL1_MBOX_1: ··· 1559 1551 return ret; 1560 1552 } 1561 1553 EXPORT_SYMBOL_NS_GPL(cs35l56_get_speaker_id, "SND_SOC_CS35L56_SHARED"); 1554 + 1555 + int cs35l56_check_and_save_onchip_spkid_gpios(struct cs35l56_base *cs35l56_base, 1556 + const u32 *gpios, int num_gpios, 1557 + const u32 *pulls, int num_pulls) 1558 + { 1559 + int max_gpio; 1560 + int ret = 0; 1561 + int i; 1562 + 1563 + if ((num_gpios > ARRAY_SIZE(cs35l56_base->onchip_spkid_gpios)) || 1564 + (num_pulls > ARRAY_SIZE(cs35l56_base->onchip_spkid_pulls))) 1565 + return -EOVERFLOW; 1566 + 1567 + switch (cs35l56_base->type) { 1568 + case 0x54: 1569 + case 0x56: 1570 + case 0x57: 1571 + max_gpio = CS35L56_MAX_GPIO; 1572 + break; 1573 + default: 1574 + max_gpio = CS35L63_MAX_GPIO; 1575 + break; 1576 + } 1577 + 1578 + for (i = 0; i < num_gpios; i++) { 1579 + if (gpios[i] < 1 || gpios[i] > max_gpio) { 1580 + dev_err(cs35l56_base->dev, "Invalid spkid GPIO %d\n", gpios[i]); 1581 + /* Keep going so we log all bad values */ 1582 + ret = -EINVAL; 1583 + } 1584 + 1585 + /* Change to zero-based */ 1586 + cs35l56_base->onchip_spkid_gpios[i] = gpios[i] - 1; 1587 + } 1588 + 1589 + for (i = 0; i < num_pulls; i++) { 1590 + switch (pulls[i]) { 1591 + case 0: 1592 + cs35l56_base->onchip_spkid_pulls[i] = CS35L56_PAD_PULL_NONE; 1593 + break; 1594 + case 1: 1595 + cs35l56_base->onchip_spkid_pulls[i] = CS35L56_PAD_PULL_UP; 1596 + break; 1597 + case 2: 1598 + cs35l56_base->onchip_spkid_pulls[i] = CS35L56_PAD_PULL_DOWN; 1599 + break; 1600 + default: 1601 + dev_err(cs35l56_base->dev, "Invalid spkid pull %d\n", pulls[i]); 1602 + /* Keep going so we log all bad values */ 1603 + ret = -EINVAL; 1604 + break; 1605 + } 1606 + } 1607 + if (ret) 1608 + return ret; 1609 + 1610 + cs35l56_base->num_onchip_spkid_gpios = num_gpios; 1611 + cs35l56_base->num_onchip_spkid_pulls = num_pulls; 1612 + 1613 + return 0; 1614 + } 1615 + EXPORT_SYMBOL_NS_GPL(cs35l56_check_and_save_onchip_spkid_gpios, "SND_SOC_CS35L56_SHARED"); 1616 + 1617 + /* Caller must pm_runtime resume before calling this function */ 1618 + int cs35l56_configure_onchip_spkid_pads(struct cs35l56_base *cs35l56_base) 1619 + { 1620 + struct regmap *regmap = cs35l56_base->regmap; 1621 + unsigned int addr_offset, val; 1622 + int num_gpios, num_pulls; 1623 + int i, ret; 1624 + 1625 + if (cs35l56_base->num_onchip_spkid_gpios == 0) 1626 + return 0; 1627 + 1628 + num_gpios = min(cs35l56_base->num_onchip_spkid_gpios, 1629 + ARRAY_SIZE(cs35l56_base->onchip_spkid_gpios)); 1630 + num_pulls = min(cs35l56_base->num_onchip_spkid_pulls, 1631 + ARRAY_SIZE(cs35l56_base->onchip_spkid_pulls)); 1632 + 1633 + for (i = 0; i < num_gpios; i++) { 1634 + addr_offset = cs35l56_base->onchip_spkid_gpios[i] * sizeof(u32); 1635 + 1636 + /* Set unspecified pulls to NONE */ 1637 + if (i < num_pulls) { 1638 + val = FIELD_PREP(CS35L56_PAD_GPIO_PULL_MASK, 1639 + cs35l56_base->onchip_spkid_pulls[i]); 1640 + } else { 1641 + val = FIELD_PREP(CS35L56_PAD_GPIO_PULL_MASK, CS35L56_PAD_PULL_NONE); 1642 + } 1643 + 1644 + ret = regmap_update_bits(regmap, CS35L56_SYNC_GPIO1_CFG + addr_offset, 1645 + CS35L56_PAD_GPIO_PULL_MASK | CS35L56_PAD_GPIO_IE, 1646 + val | CS35L56_PAD_GPIO_IE); 1647 + if (ret) { 1648 + dev_err(cs35l56_base->dev, "GPIO%d set pad fail: %d\n", 1649 + cs35l56_base->onchip_spkid_gpios[i] + 1, ret); 1650 + return ret; 1651 + } 1652 + } 1653 + 1654 + ret = regmap_write(regmap, CS35L56_UPDATE_REGS, CS35L56_UPDT_GPIO_PRES); 1655 + if (ret) { 1656 + dev_err(cs35l56_base->dev, "UPDT_GPIO_PRES failed:%d\n", ret); 1657 + return ret; 1658 + } 1659 + 1660 + usleep_range(CS35L56_PAD_PULL_SETTLE_US, CS35L56_PAD_PULL_SETTLE_US * 2); 1661 + 1662 + return 0; 1663 + } 1664 + EXPORT_SYMBOL_NS_GPL(cs35l56_configure_onchip_spkid_pads, "SND_SOC_CS35L56_SHARED"); 1665 + 1666 + /* Caller must pm_runtime resume before calling this function */ 1667 + int cs35l56_read_onchip_spkid(struct cs35l56_base *cs35l56_base) 1668 + { 1669 + struct regmap *regmap = cs35l56_base->regmap; 1670 + unsigned int addr_offset, val; 1671 + int num_gpios; 1672 + int speaker_id = 0; 1673 + int i, ret; 1674 + 1675 + if (cs35l56_base->num_onchip_spkid_gpios == 0) 1676 + return -ENOENT; 1677 + 1678 + num_gpios = min(cs35l56_base->num_onchip_spkid_gpios, 1679 + ARRAY_SIZE(cs35l56_base->onchip_spkid_gpios)); 1680 + 1681 + for (i = 0; i < num_gpios; i++) { 1682 + addr_offset = cs35l56_base->onchip_spkid_gpios[i] * sizeof(u32); 1683 + 1684 + ret = regmap_update_bits(regmap, CS35L56_GPIO1_CTRL1 + addr_offset, 1685 + CS35L56_GPIO_DIR_MASK | CS35L56_GPIO_FN_MASK, 1686 + CS35L56_GPIO_DIR_MASK | CS35L56_GPIO_FN_GPIO); 1687 + if (ret) { 1688 + dev_err(cs35l56_base->dev, "GPIO%u set func fail: %d\n", 1689 + cs35l56_base->onchip_spkid_gpios[i] + 1, ret); 1690 + return ret; 1691 + } 1692 + } 1693 + 1694 + ret = regmap_read(regmap, CS35L56_GPIO_STATUS1, &val); 1695 + if (ret) { 1696 + dev_err(cs35l56_base->dev, "GPIO%d status read failed: %d\n", 1697 + cs35l56_base->onchip_spkid_gpios[i] + 1, ret); 1698 + return ret; 1699 + } 1700 + 1701 + for (i = 0; i < num_gpios; i++) { 1702 + speaker_id <<= 1; 1703 + 1704 + if (val & BIT(cs35l56_base->onchip_spkid_gpios[i])) 1705 + speaker_id |= 1; 1706 + } 1707 + 1708 + dev_dbg(cs35l56_base->dev, "Onchip GPIO Speaker ID = %d\n", speaker_id); 1709 + 1710 + return speaker_id; 1711 + } 1712 + EXPORT_SYMBOL_NS_GPL(cs35l56_read_onchip_spkid, "SND_SOC_CS35L56_SHARED"); 1562 1713 1563 1714 static const u32 cs35l56_bclk_valid_for_pll_freq_table[] = { 1564 1715 [0x0C] = 128000,
+137 -4
sound/soc/codecs/cs35l56.c
··· 1179 1179 } 1180 1180 EXPORT_SYMBOL_IF_KUNIT(cs35l56_set_fw_suffix); 1181 1181 1182 - static int cs35l56_component_probe(struct snd_soc_component *component) 1182 + VISIBLE_IF_KUNIT int cs35l56_set_fw_name(struct snd_soc_component *component) 1183 1183 { 1184 - struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component); 1185 1184 struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(component); 1186 - struct dentry *debugfs_root = component->debugfs_root; 1187 1185 unsigned short vendor, device; 1188 1186 int ret; 1189 1187 1190 - BUILD_BUG_ON(ARRAY_SIZE(cs35l56_tx_input_texts) != ARRAY_SIZE(cs35l56_tx_input_values)); 1188 + if ((cs35l56->speaker_id < 0) && cs35l56->base.num_onchip_spkid_gpios) { 1189 + PM_RUNTIME_ACQUIRE(cs35l56->base.dev, pm); 1190 + ret = PM_RUNTIME_ACQUIRE_ERR(&pm); 1191 + if (ret) 1192 + return ret; 1193 + 1194 + ret = cs35l56_configure_onchip_spkid_pads(&cs35l56->base); 1195 + if (ret) 1196 + return ret; 1197 + 1198 + ret = cs35l56_read_onchip_spkid(&cs35l56->base); 1199 + if (ret < 0) 1200 + return ret; 1201 + 1202 + cs35l56->speaker_id = ret; 1203 + } 1191 1204 1192 1205 if (!cs35l56->dsp.system_name && 1193 1206 (snd_soc_card_get_pci_ssid(component->card, &vendor, &device) == 0)) { ··· 1221 1208 return -ENOMEM; 1222 1209 } 1223 1210 1211 + return 0; 1212 + } 1213 + EXPORT_SYMBOL_IF_KUNIT(cs35l56_set_fw_name); 1214 + 1215 + static int cs35l56_component_probe(struct snd_soc_component *component) 1216 + { 1217 + struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component); 1218 + struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(component); 1219 + struct dentry *debugfs_root = component->debugfs_root; 1220 + int ret; 1221 + 1222 + BUILD_BUG_ON(ARRAY_SIZE(cs35l56_tx_input_texts) != ARRAY_SIZE(cs35l56_tx_input_values)); 1223 + 1224 1224 if (!wait_for_completion_timeout(&cs35l56->init_completion, 1225 1225 msecs_to_jiffies(5000))) { 1226 1226 dev_err(cs35l56->base.dev, "%s: init_completion timed out\n", __func__); ··· 1245 1219 return -ENOMEM; 1246 1220 1247 1221 cs35l56->component = component; 1222 + ret = cs35l56_set_fw_name(component); 1223 + if (ret) 1224 + return ret; 1225 + 1248 1226 ret = cs35l56_set_fw_suffix(cs35l56); 1249 1227 if (ret) 1250 1228 return ret; ··· 1562 1532 return 0; 1563 1533 } 1564 1534 1535 + static int cs35l56_read_fwnode_u32_array(struct device *dev, 1536 + struct fwnode_handle *parent_node, 1537 + const char *prop_name, 1538 + int max_count, 1539 + u32 *dest) 1540 + { 1541 + int count, ret; 1542 + 1543 + count = fwnode_property_count_u32(parent_node, prop_name); 1544 + if ((count == 0) || (count == -EINVAL) || (count == -ENODATA)) { 1545 + dev_dbg(dev, "%s not found in %s\n", prop_name, fwnode_get_name(parent_node)); 1546 + return 0; 1547 + } 1548 + 1549 + if (count < 0) { 1550 + dev_err(dev, "Get %s error:%d\n", prop_name, count); 1551 + return count; 1552 + } 1553 + 1554 + if (count > max_count) { 1555 + dev_err(dev, "%s too many entries (%d)\n", prop_name, count); 1556 + return -EOVERFLOW; 1557 + } 1558 + 1559 + ret = fwnode_property_read_u32_array(parent_node, prop_name, dest, count); 1560 + if (ret) { 1561 + dev_err(dev, "Error reading %s: %d\n", prop_name, ret); 1562 + return ret; 1563 + } 1564 + 1565 + return count; 1566 + } 1567 + 1568 + static int cs35l56_process_xu_onchip_speaker_id(struct cs35l56_private *cs35l56, 1569 + struct fwnode_handle *ext_node) 1570 + { 1571 + static const char * const gpio_name = "01fa-spk-id-gpios-onchip"; 1572 + static const char * const pull_name = "01fa-spk-id-gpios-onchip-pull"; 1573 + u32 gpios[5], pulls[5]; 1574 + int num_gpios, num_pulls; 1575 + int ret; 1576 + 1577 + static_assert(ARRAY_SIZE(gpios) == ARRAY_SIZE(cs35l56->base.onchip_spkid_gpios)); 1578 + static_assert(ARRAY_SIZE(pulls) == ARRAY_SIZE(cs35l56->base.onchip_spkid_pulls)); 1579 + 1580 + num_gpios = cs35l56_read_fwnode_u32_array(cs35l56->base.dev, ext_node, gpio_name, 1581 + ARRAY_SIZE(gpios), gpios); 1582 + if (num_gpios < 1) 1583 + return num_gpios; 1584 + 1585 + num_pulls = cs35l56_read_fwnode_u32_array(cs35l56->base.dev, ext_node, pull_name, 1586 + ARRAY_SIZE(pulls), pulls); 1587 + if (num_pulls < 0) 1588 + return num_pulls; 1589 + 1590 + if (num_pulls != num_gpios) { 1591 + dev_warn(cs35l56->base.dev, "%s count(%d) != %s count(%d)\n", 1592 + pull_name, num_pulls, gpio_name, num_gpios); 1593 + } 1594 + 1595 + ret = cs35l56_check_and_save_onchip_spkid_gpios(&cs35l56->base, 1596 + gpios, num_gpios, 1597 + pulls, num_pulls); 1598 + if (ret) { 1599 + return dev_err_probe(cs35l56->base.dev, ret, "Error in %s/%s\n", 1600 + gpio_name, pull_name); 1601 + } 1602 + 1603 + return 0; 1604 + } 1605 + 1606 + VISIBLE_IF_KUNIT int cs35l56_process_xu_properties(struct cs35l56_private *cs35l56) 1607 + { 1608 + struct fwnode_handle *ext_node = NULL; 1609 + struct fwnode_handle *link; 1610 + int ret; 1611 + 1612 + if (!cs35l56->sdw_peripheral) 1613 + return 0; 1614 + 1615 + fwnode_for_each_child_node(dev_fwnode(cs35l56->base.dev), link) { 1616 + ext_node = fwnode_get_named_child_node(link, 1617 + "mipi-sdca-function-expansion-subproperties"); 1618 + if (ext_node) { 1619 + fwnode_handle_put(link); 1620 + break; 1621 + } 1622 + } 1623 + 1624 + if (!ext_node) 1625 + return 0; 1626 + 1627 + ret = cs35l56_process_xu_onchip_speaker_id(cs35l56, ext_node); 1628 + fwnode_handle_put(ext_node); 1629 + 1630 + return ret; 1631 + } 1632 + EXPORT_SYMBOL_IF_KUNIT(cs35l56_process_xu_properties); 1633 + 1565 1634 static int cs35l56_get_firmware_uid(struct cs35l56_private *cs35l56) 1566 1635 { 1567 1636 struct device *dev = cs35l56->base.dev; ··· 1839 1710 1840 1711 ret = cs35l56_get_firmware_uid(cs35l56); 1841 1712 if (ret != 0) 1713 + goto err; 1714 + 1715 + ret = cs35l56_process_xu_properties(cs35l56); 1716 + if (ret) 1842 1717 goto err; 1843 1718 1844 1719 ret = cs35l56_dsp_init(cs35l56);
+2
sound/soc/codecs/cs35l56.h
··· 76 76 77 77 #if IS_ENABLED(CONFIG_KUNIT) 78 78 int cs35l56_set_fw_suffix(struct cs35l56_private *cs35l56); 79 + int cs35l56_set_fw_name(struct snd_soc_component *component); 80 + int cs35l56_process_xu_properties(struct cs35l56_private *cs35l56); 79 81 #endif 80 82 81 83 #endif /* ifndef CS35L56_H */