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: Yet another round of SDCA fixes

Charles Keepax <ckeepax@opensource.cirrus.com> says:

Another round of SDCA fixes a couple of fix to the IRQ cleanup
from Richard, and a minor tweak to the IRQ handling from me.

+184 -46
+10 -3
Documentation/devicetree/bindings/sound/ti,tas2552.yaml
··· 12 12 - Baojun Xu <baojun.xu@ti.com> 13 13 14 14 description: > 15 - The TAS2552 can receive its reference clock via MCLK, BCLK, IVCLKIN pin or 16 - use the internal 1.8MHz. This CLKIN is used by the PLL. In addition to PLL, 15 + The TAS2552 can receive its reference clock via MCLK, BCLK, IVCLKIN pin or 16 + use the internal 1.8MHz. This CLKIN is used by the PLL. In addition to PLL, 17 17 the PDM reference clock is also selectable: PLL, IVCLKIN, BCLK or MCLK. 18 18 19 19 For system integration the dt-bindings/sound/tas2552.h header file provides ··· 34 34 maxItems: 1 35 35 description: gpio pin to enable/disable the device 36 36 37 + '#sound-dai-cells': 38 + const: 0 39 + 37 40 required: 38 41 - compatible 39 42 - reg ··· 44 41 - iovdd-supply 45 42 - avdd-supply 46 43 47 - additionalProperties: false 44 + allOf: 45 + - $ref: dai-common.yaml# 46 + 47 + unevaluatedProperties: false 48 48 49 49 examples: 50 50 - | ··· 60 54 audio-codec@41 { 61 55 compatible = "ti,tas2552"; 62 56 reg = <0x41>; 57 + #sound-dai-cells = <0>; 63 58 vbat-supply = <&reg_vbat>; 64 59 iovdd-supply = <&reg_iovdd>; 65 60 avdd-supply = <&reg_avdd>;
+5
include/sound/sdca_interrupts.h
··· 69 69 int sdca_irq_request(struct device *dev, struct sdca_interrupt_info *interrupt_info, 70 70 int sdca_irq, const char *name, irq_handler_t handler, 71 71 void *data); 72 + void sdca_irq_free(struct device *dev, struct sdca_interrupt_info *interrupt_info, 73 + int sdca_irq, const char *name, void *data); 72 74 int sdca_irq_data_populate(struct device *dev, struct regmap *function_regmap, 73 75 struct snd_soc_component *component, 74 76 struct sdca_function_data *function, ··· 82 80 struct sdca_interrupt_info *info); 83 81 int sdca_irq_populate(struct sdca_function_data *function, 84 82 struct snd_soc_component *component, 83 + struct sdca_interrupt_info *info); 84 + void sdca_irq_cleanup(struct device *dev, 85 + struct sdca_function_data *function, 85 86 struct sdca_interrupt_info *info); 86 87 struct sdca_interrupt_info *sdca_irq_allocate(struct device *dev, 87 88 struct regmap *regmap, int irq);
+20 -4
sound/soc/amd/acp/acp-sdw-legacy-mach.c
··· 99 99 .callback = soc_sdw_quirk_cb, 100 100 .matches = { 101 101 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 102 - DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "21YW"), 102 + DMI_MATCH(DMI_PRODUCT_SKU, "21YW"), 103 103 }, 104 - .driver_data = (void *)(ASOC_SDW_CODEC_SPKR), 104 + .driver_data = (void *)((ASOC_SDW_CODEC_SPKR) | (ASOC_SDW_ACP_DMIC)), 105 105 }, 106 106 { 107 107 .callback = soc_sdw_quirk_cb, 108 108 .matches = { 109 109 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 110 - DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "21YX"), 110 + DMI_MATCH(DMI_PRODUCT_SKU, "21YX"), 111 111 }, 112 - .driver_data = (void *)(ASOC_SDW_CODEC_SPKR), 112 + .driver_data = (void *)((ASOC_SDW_CODEC_SPKR) | (ASOC_SDW_ACP_DMIC)), 113 + }, 114 + { 115 + .callback = soc_sdw_quirk_cb, 116 + .matches = { /* Lenovo P16s G5 AMD */ 117 + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 118 + DMI_MATCH(DMI_PRODUCT_SKU, "21XG"), 119 + }, 120 + .driver_data = (void *)(ASOC_SDW_ACP_DMIC), 121 + }, 122 + { 123 + .callback = soc_sdw_quirk_cb, 124 + .matches = { /* Lenovo P16s G5 AMD */ 125 + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 126 + DMI_MATCH(DMI_PRODUCT_SKU, "21XH"), 127 + }, 128 + .driver_data = (void *)(ASOC_SDW_ACP_DMIC), 113 129 }, 114 130 { 115 131 .callback = soc_sdw_quirk_cb,
+8 -1
sound/soc/codecs/nau8325.c
··· 142 142 static bool nau8325_writeable_reg(struct device *dev, unsigned int reg) 143 143 { 144 144 switch (reg) { 145 - case NAU8325_R00_HARDWARE_RST: 145 + case NAU8325_R00_HARDWARE_RST ... NAU8325_R01_SOFTWARE_RST: 146 146 case NAU8325_R03_CLK_CTRL ... NAU8325_R06_INT_CLR_STATUS: 147 147 case NAU8325_R09_IRQOUT ... NAU8325_R13_DAC_VOLUME: 148 148 case NAU8325_R29_DAC_CTRL1 ... NAU8325_R2A_DAC_CTRL2: ··· 670 670 regmap_write(regmap, NAU8325_R00_HARDWARE_RST, 0x0000); 671 671 } 672 672 673 + static void nau8325_software_reset(struct regmap *regmap) 674 + { 675 + regmap_write(regmap, NAU8325_R01_SOFTWARE_RST, 0x0000); 676 + regmap_write(regmap, NAU8325_R01_SOFTWARE_RST, 0x0000); 677 + } 678 + 673 679 static void nau8325_init_regs(struct nau8325 *nau8325) 674 680 { 675 681 struct regmap *regmap = nau8325->regmap; ··· 862 856 nau8325_print_device_properties(nau8325); 863 857 864 858 nau8325_reset_chip(nau8325->regmap); 859 + nau8325_software_reset(nau8325->regmap); 865 860 ret = regmap_read(nau8325->regmap, NAU8325_R02_DEVICE_ID, &value); 866 861 if (ret) { 867 862 dev_dbg(dev, "Failed to read device id (%d)", ret);
+6 -3
sound/soc/intel/avs/board_selection.c
··· 520 520 if (num_elems > max_ssps) { 521 521 dev_err(adev->dev, "board supports only %d SSP, %d specified\n", 522 522 max_ssps, num_elems); 523 - return -EINVAL; 523 + ret = -EINVAL; 524 + goto exit; 524 525 } 525 526 526 527 for (ssp_port = 0; ssp_port < num_elems; ssp_port++) { ··· 529 528 for_each_set_bit(tdm_slot, &tdm_slots, 16) { 530 529 ret = avs_register_i2s_test_board(adev, ssp_port, tdm_slot); 531 530 if (ret) 532 - return ret; 531 + goto exit; 533 532 } 534 533 } 535 534 536 - return 0; 535 + exit: 536 + kfree(array); 537 + return ret; 537 538 } 538 539 539 540 static int avs_register_i2s_board(struct avs_dev *adev, struct snd_soc_acpi_mach *mach)
+21 -13
sound/soc/sdca/sdca_class.c
··· 137 137 .unlock = class_regmap_unlock, 138 138 }; 139 139 140 + static void class_remove_functions(void *data) 141 + { 142 + struct sdca_class_drv *drv = data; 143 + 144 + sdca_dev_unregister_functions(drv->sdw); 145 + } 146 + 140 147 static void class_boot_work(struct work_struct *work) 141 148 { 142 149 struct sdca_class_drv *drv = container_of(work, ··· 164 157 if (ret) 165 158 goto err; 166 159 160 + /* Ensure function drivers are removed before the IRQ is destroyed */ 161 + ret = devm_add_action_or_reset(drv->dev, class_remove_functions, drv); 162 + if (ret) 163 + goto err; 164 + 167 165 dev_dbg(drv->dev, "boot work complete\n"); 168 166 169 167 pm_runtime_mark_last_busy(drv->dev); ··· 178 166 179 167 err: 180 168 pm_runtime_put_sync(drv->dev); 181 - } 182 - 183 - static void class_dev_remove(void *data) 184 - { 185 - struct sdca_class_drv *drv = data; 186 - 187 - cancel_work_sync(&drv->boot_work); 188 - 189 - sdca_dev_unregister_functions(drv->sdw); 190 169 } 191 170 192 171 static int class_sdw_probe(struct sdw_slave *sdw, const struct sdw_device_id *id) ··· 233 230 if (ret) 234 231 return ret; 235 232 236 - ret = devm_add_action_or_reset(dev, class_dev_remove, drv); 237 - if (ret) 238 - return ret; 239 - 240 233 queue_work(system_long_wq, &drv->boot_work); 241 234 242 235 return 0; 236 + } 237 + 238 + static void class_sdw_remove(struct sdw_slave *sdw) 239 + { 240 + struct device *dev = &sdw->dev; 241 + struct sdca_class_drv *drv = dev_get_drvdata(dev); 242 + 243 + cancel_work_sync(&drv->boot_work); 243 244 } 244 245 245 246 static int class_suspend(struct device *dev) ··· 337 330 }, 338 331 339 332 .probe = class_sdw_probe, 333 + .remove = class_sdw_remove, 340 334 .id_table = class_sdw_id, 341 335 .ops = &class_sdw_ops, 342 336 };
+17
sound/soc/sdca/sdca_class_function.c
··· 198 198 return sdca_irq_populate(drv->function, component, core->irq_info); 199 199 } 200 200 201 + static void class_function_component_remove(struct snd_soc_component *component) 202 + { 203 + struct class_function_drv *drv = snd_soc_component_get_drvdata(component); 204 + struct sdca_class_drv *core = drv->core; 205 + 206 + sdca_irq_cleanup(component->dev, drv->function, core->irq_info); 207 + } 208 + 201 209 static int class_function_set_jack(struct snd_soc_component *component, 202 210 struct snd_soc_jack *jack, void *d) 203 211 { ··· 217 209 218 210 static const struct snd_soc_component_driver class_function_component_drv = { 219 211 .probe = class_function_component_probe, 212 + .remove = class_function_component_remove, 220 213 .endianness = 1, 221 214 }; 222 215 ··· 417 408 return 0; 418 409 } 419 410 411 + static void class_function_remove(struct auxiliary_device *auxdev) 412 + { 413 + struct class_function_drv *drv = auxiliary_get_drvdata(auxdev); 414 + 415 + sdca_irq_cleanup(drv->dev, drv->function, drv->core->irq_info); 416 + } 417 + 420 418 static int class_function_runtime_suspend(struct device *dev) 421 419 { 422 420 struct auxiliary_device *auxdev = to_auxiliary_dev(dev); ··· 576 560 }, 577 561 578 562 .probe = class_function_probe, 563 + .remove = class_function_remove, 579 564 .id_table = class_function_id_table 580 565 }; 581 566 module_auxiliary_driver(class_function_drv);
+78 -14
sound/soc/sdca/sdca_interrupts.c
··· 117 117 118 118 status = val; 119 119 for_each_set_bit(mask, &status, BITS_PER_BYTE) { 120 - mask = 1 << mask; 121 - 122 - switch (mask) { 120 + switch (BIT(mask)) { 123 121 case SDCA_CTL_ENTITY_0_FUNCTION_NEEDS_INITIALIZATION: 124 122 //FIXME: Add init writes 125 123 break; ··· 138 140 } 139 141 } 140 142 141 - ret = regmap_write(interrupt->function_regmap, reg, val); 143 + ret = regmap_write(interrupt->function_regmap, reg, val & 0x7F); 142 144 if (ret < 0) { 143 145 dev_err(dev, "failed to clear function status: %d\n", ret); 144 146 goto error; ··· 250 252 if (irq < 0) 251 253 return irq; 252 254 253 - ret = devm_request_threaded_irq(dev, irq, NULL, handler, 254 - IRQF_ONESHOT, name, data); 255 + ret = request_threaded_irq(irq, NULL, handler, IRQF_ONESHOT, name, data); 255 256 if (ret) 256 257 return ret; 257 258 ··· 259 262 dev_dbg(dev, "requested irq %d for %s\n", irq, name); 260 263 261 264 return 0; 265 + } 266 + 267 + static void sdca_irq_free_locked(struct device *dev, struct sdca_interrupt_info *info, 268 + int sdca_irq, const char *name, void *data) 269 + { 270 + int irq; 271 + 272 + irq = regmap_irq_get_virq(info->irq_data, sdca_irq); 273 + if (irq < 0) 274 + return; 275 + 276 + free_irq(irq, data); 277 + 278 + info->irqs[sdca_irq].irq = 0; 279 + 280 + dev_dbg(dev, "freed irq %d for %s\n", irq, name); 262 281 } 263 282 264 283 /** ··· 316 303 EXPORT_SYMBOL_NS_GPL(sdca_irq_request, "SND_SOC_SDCA"); 317 304 318 305 /** 306 + * sdca_irq_free - free an individual SDCA interrupt 307 + * @dev: Pointer to the struct device. 308 + * @info: Pointer to the interrupt information structure. 309 + * @sdca_irq: SDCA interrupt position. 310 + * @name: Name to be given to the IRQ. 311 + * @data: Private data pointer that will be passed to the handler. 312 + * 313 + * Typically this is handled internally by sdca_irq_cleanup, however if 314 + * a device requires custom IRQ handling this can be called manually before 315 + * calling sdca_irq_cleanup, which will then skip that IRQ whilst processing. 316 + */ 317 + void sdca_irq_free(struct device *dev, struct sdca_interrupt_info *info, 318 + int sdca_irq, const char *name, void *data) 319 + { 320 + if (sdca_irq < 0 || sdca_irq >= SDCA_MAX_INTERRUPTS) 321 + return; 322 + 323 + guard(mutex)(&info->irq_lock); 324 + 325 + sdca_irq_free_locked(dev, info, sdca_irq, name, data); 326 + } 327 + EXPORT_SYMBOL_NS_GPL(sdca_irq_free, "SND_SOC_SDCA"); 328 + 329 + /** 319 330 * sdca_irq_data_populate - Populate common interrupt data 320 331 * @dev: Pointer to the Function device. 321 332 * @regmap: Pointer to the Function regmap. ··· 365 328 if (!dev) 366 329 return -ENODEV; 367 330 368 - name = devm_kasprintf(dev, GFP_KERNEL, "%s %s %s", function->desc->name, 369 - entity->label, control->label); 331 + name = kasprintf(GFP_KERNEL, "%s %s %s", function->desc->name, 332 + entity->label, control->label); 370 333 if (!name) 371 334 return -ENOMEM; 372 335 ··· 554 517 EXPORT_SYMBOL_NS_GPL(sdca_irq_populate, "SND_SOC_SDCA"); 555 518 556 519 /** 520 + * sdca_irq_cleanup - Free all the individual IRQs for an SDCA Function 521 + * @dev: Device pointer against which the sdca_interrupt_info was allocated. 522 + * @function: Pointer to the SDCA Function. 523 + * @info: Pointer to the SDCA interrupt info for this device. 524 + * 525 + * Typically this would be called from the driver for a single SDCA Function. 526 + */ 527 + void sdca_irq_cleanup(struct device *dev, 528 + struct sdca_function_data *function, 529 + struct sdca_interrupt_info *info) 530 + { 531 + int i; 532 + 533 + guard(mutex)(&info->irq_lock); 534 + 535 + for (i = 0; i < SDCA_MAX_INTERRUPTS; i++) { 536 + struct sdca_interrupt *interrupt = &info->irqs[i]; 537 + 538 + if (interrupt->function != function || !interrupt->irq) 539 + continue; 540 + 541 + sdca_irq_free_locked(dev, info, i, interrupt->name, interrupt); 542 + 543 + kfree(interrupt->name); 544 + } 545 + } 546 + EXPORT_SYMBOL_NS_GPL(sdca_irq_cleanup, "SND_SOC_SDCA"); 547 + 548 + /** 557 549 * sdca_irq_allocate - allocate an SDCA interrupt structure for a device 558 550 * @sdev: Device pointer against which things should be allocated. 559 551 * @regmap: regmap to be used for accessing the SDCA IRQ registers. ··· 630 564 static void irq_enable_flags(struct sdca_function_data *function, 631 565 struct sdca_interrupt_info *info, bool early) 632 566 { 633 - struct sdca_interrupt *interrupt; 634 567 int i; 635 568 636 569 for (i = 0; i < SDCA_MAX_INTERRUPTS; i++) { 637 - interrupt = &info->irqs[i]; 570 + struct sdca_interrupt *interrupt = &info->irqs[i]; 638 571 639 - if (!interrupt || interrupt->function != function) 572 + if (!interrupt->irq || interrupt->function != function) 640 573 continue; 641 574 642 575 switch (SDCA_CTL_TYPE(interrupt->entity->type, ··· 688 623 void sdca_irq_disable(struct sdca_function_data *function, 689 624 struct sdca_interrupt_info *info) 690 625 { 691 - struct sdca_interrupt *interrupt; 692 626 int i; 693 627 694 628 for (i = 0; i < SDCA_MAX_INTERRUPTS; i++) { 695 - interrupt = &info->irqs[i]; 629 + struct sdca_interrupt *interrupt = &info->irqs[i]; 696 630 697 - if (!interrupt || interrupt->function != function) 631 + if (!interrupt->irq || interrupt->function != function) 698 632 continue; 699 633 700 634 disable_irq(interrupt->irq);
+12 -2
sound/soc/sof/intel/hda-pcm.c
··· 219 219 int hda_dsp_pcm_open(struct snd_sof_dev *sdev, 220 220 struct snd_pcm_substream *substream) 221 221 { 222 + const struct sof_intel_dsp_desc *chip_info = get_chip_info(sdev->pdata); 222 223 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 223 224 struct snd_pcm_runtime *runtime = substream->runtime; 224 225 struct snd_soc_component *scomp = sdev->component; ··· 269 268 return -ENODEV; 270 269 } 271 270 272 - /* minimum as per HDA spec */ 273 - snd_pcm_hw_constraint_step(substream->runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 4); 271 + /* 272 + * Set period size constraint to ensure BDLE buffer length and 273 + * start address alignment requirements are met. Align to 128 274 + * bytes for newer Intel platforms, with older ones using 4 byte alignment. 275 + */ 276 + if (chip_info->hw_ip_version >= SOF_INTEL_ACE_4_0) 277 + snd_pcm_hw_constraint_step(substream->runtime, 0, 278 + SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 128); 279 + else 280 + snd_pcm_hw_constraint_step(substream->runtime, 0, 281 + SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 4); 274 282 275 283 /* avoid circular buffer wrap in middle of period */ 276 284 snd_pcm_hw_constraint_integer(substream->runtime,
+4 -6
sound/soc/sof/intel/hda.c
··· 1133 1133 1134 1134 #if IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE) 1135 1135 1136 - static bool is_endpoint_present(struct sdw_slave *sdw_device, 1137 - struct asoc_sdw_codec_info *dai_info, int dai_type) 1136 + static bool is_endpoint_present(struct sdw_slave *sdw_device, int dai_type) 1138 1137 { 1139 1138 int i; 1140 1139 ··· 1144 1145 } 1145 1146 1146 1147 for (i = 0; i < sdw_device->sdca_data.num_functions; i++) { 1147 - if (dai_type == dai_info->dais[i].dai_type) 1148 + if (dai_type == asoc_sdw_get_dai_type(sdw_device->sdca_data.function[i].type)) 1148 1149 return true; 1149 1150 } 1150 1151 dev_dbg(&sdw_device->dev, "Endpoint DAI type %d not found\n", dai_type); ··· 1201 1202 } 1202 1203 for (j = 0; j < codec_info_list[i].dai_num; j++) { 1203 1204 /* Check if the endpoint is present by the SDCA DisCo table */ 1204 - if (!is_endpoint_present(sdw_device, &codec_info_list[i], 1205 - codec_info_list[i].dais[j].dai_type)) 1205 + if (!is_endpoint_present(sdw_device, codec_info_list[i].dais[j].dai_type)) 1206 1206 continue; 1207 1207 1208 - endpoints[ep_index].num = ep_index; 1208 + endpoints[ep_index].num = j; 1209 1209 if (codec_info_list[i].dais[j].dai_type == SOC_SDW_DAI_TYPE_AMP) { 1210 1210 /* Assume all amp are aggregated */ 1211 1211 endpoints[ep_index].aggregated = 1;
+3
sound/soc/stm/stm32_sai_sub.c
··· 802 802 break; 803 803 /* Left justified */ 804 804 case SND_SOC_DAIFMT_MSB: 805 + cr1 |= SAI_XCR1_CKSTR; 805 806 frcr |= SAI_XFRCR_FSPOL | SAI_XFRCR_FSDEF; 806 807 break; 807 808 /* Right justified */ ··· 810 809 frcr |= SAI_XFRCR_FSPOL | SAI_XFRCR_FSDEF; 811 810 break; 812 811 case SND_SOC_DAIFMT_DSP_A: 812 + cr1 |= SAI_XCR1_CKSTR; 813 813 frcr |= SAI_XFRCR_FSPOL | SAI_XFRCR_FSOFF; 814 814 break; 815 815 case SND_SOC_DAIFMT_DSP_B: 816 + cr1 |= SAI_XCR1_CKSTR; 816 817 frcr |= SAI_XFRCR_FSPOL; 817 818 break; 818 819 default: