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

Merge branch 'topic/firewire' into for-next

Pull FireWire fixes

Signed-off-by: Takashi Iwai <tiwai@suse.de>

+685 -343
+1
Documentation/devicetree/bindings/sound/mt8186-mt6366-rt1019-rt5682s.yaml
··· 16 16 compatible: 17 17 enum: 18 18 - mediatek,mt8186-mt6366-rt1019-rt5682s-sound 19 + - mediatek,mt8186-mt6366-rt5682s-max98360-sound 19 20 20 21 mediatek,platform: 21 22 $ref: "/schemas/types.yaml#/definitions/phandle"
+3 -1
Documentation/devicetree/bindings/sound/qcom,lpass-tx-macro.yaml
··· 30 30 const: 0 31 31 32 32 clocks: 33 - maxItems: 5 33 + oneOf: 34 + - maxItems: 3 35 + - maxItems: 5 34 36 35 37 clock-names: 36 38 oneOf:
+47 -11
Documentation/devicetree/bindings/sound/qcom,lpass-wsa-macro.yaml
··· 9 9 maintainers: 10 10 - Srinivas Kandagatla <srinivas.kandagatla@linaro.org> 11 11 12 - allOf: 13 - - $ref: dai-common.yaml# 14 - 15 12 properties: 16 13 compatible: 17 14 enum: ··· 27 30 const: 0 28 31 29 32 clocks: 30 - maxItems: 5 33 + minItems: 5 34 + maxItems: 6 31 35 32 36 clock-names: 33 - items: 34 - - const: mclk 35 - - const: npl 36 - - const: macro 37 - - const: dcodec 38 - - const: fsgen 37 + minItems: 5 38 + maxItems: 6 39 39 40 40 clock-output-names: 41 41 maxItems: 1 ··· 49 55 - reg 50 56 - "#sound-dai-cells" 51 57 58 + allOf: 59 + - $ref: dai-common.yaml# 60 + 61 + - if: 62 + properties: 63 + compatible: 64 + enum: 65 + - qcom,sc7280-lpass-wsa-macro 66 + - qcom,sm8450-lpass-wsa-macro 67 + - qcom,sc8280xp-lpass-wsa-macro 68 + then: 69 + properties: 70 + clocks: 71 + maxItems: 5 72 + clock-names: 73 + items: 74 + - const: mclk 75 + - const: npl 76 + - const: macro 77 + - const: dcodec 78 + - const: fsgen 79 + 80 + - if: 81 + properties: 82 + compatible: 83 + enum: 84 + - qcom,sm8250-lpass-wsa-macro 85 + then: 86 + properties: 87 + clocks: 88 + minItems: 6 89 + clock-names: 90 + items: 91 + - const: mclk 92 + - const: npl 93 + - const: macro 94 + - const: dcodec 95 + - const: va 96 + - const: fsgen 97 + 52 98 unevaluatedProperties: false 53 99 54 100 examples: 55 101 - | 102 + #include <dt-bindings/clock/qcom,sm8250-lpass-aoncc.h> 56 103 #include <dt-bindings/sound/qcom,q6afe.h> 57 104 codec@3240000 { 58 105 compatible = "qcom,sm8250-lpass-wsa-macro"; ··· 104 69 <&audiocc 0>, 105 70 <&q6afecc LPASS_HW_MACRO_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>, 106 71 <&q6afecc LPASS_HW_DCODEC_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>, 72 + <&aoncc LPASS_CDC_VA_MCLK>, 107 73 <&vamacro>; 108 - clock-names = "mclk", "npl", "macro", "dcodec", "fsgen"; 74 + clock-names = "mclk", "npl", "macro", "dcodec", "va", "fsgen"; 109 75 clock-output-names = "mclk"; 110 76 };
+18 -25
drivers/firewire/core-cdev.c
··· 111 111 struct client_resource resource; 112 112 struct fw_card *card; 113 113 struct fw_request *request; 114 + bool is_fcp; 114 115 void *data; 115 116 size_t length; 116 117 }; ··· 644 643 client->device->max_speed); 645 644 } 646 645 647 - static inline bool is_fcp_request(struct fw_request *request) 648 - { 649 - return request == NULL; 650 - } 651 - 652 646 static void release_request(struct client *client, 653 647 struct client_resource *resource) 654 648 { 655 649 struct inbound_transaction_resource *r = container_of(resource, 656 650 struct inbound_transaction_resource, resource); 657 651 658 - if (is_fcp_request(r->request)) 659 - kfree(r->data); 652 + if (r->is_fcp) 653 + fw_request_put(r->request); 660 654 else 661 655 fw_send_response(r->card, r->request, RCODE_CONFLICT_ERROR); 662 656 ··· 665 669 void *payload, size_t length, void *callback_data) 666 670 { 667 671 struct address_handler_resource *handler = callback_data; 672 + bool is_fcp = is_in_fcp_region(offset, length); 668 673 struct inbound_transaction_resource *r; 669 674 struct inbound_transaction_event *e; 670 675 size_t event_size0; 671 - void *fcp_frame = NULL; 672 676 int ret; 673 677 674 678 /* card may be different from handler->client->device->card */ 675 679 fw_card_get(card); 680 + 681 + // Extend the lifetime of data for request so that its payload is safely accessible in 682 + // the process context for the client. 683 + if (is_fcp) 684 + fw_request_get(request); 676 685 677 686 r = kmalloc(sizeof(*r), GFP_ATOMIC); 678 687 e = kmalloc(sizeof(*e), GFP_ATOMIC); ··· 686 685 687 686 r->card = card; 688 687 r->request = request; 688 + r->is_fcp = is_fcp; 689 689 r->data = payload; 690 690 r->length = length; 691 - 692 - if (is_fcp_request(request)) { 693 - /* 694 - * FIXME: Let core-transaction.c manage a 695 - * single reference-counted copy? 696 - */ 697 - fcp_frame = kmemdup(payload, length, GFP_ATOMIC); 698 - if (fcp_frame == NULL) 699 - goto failed; 700 - 701 - r->data = fcp_frame; 702 - } 703 691 704 692 r->resource.release = release_request; 705 693 ret = add_client_resource(handler->client, &r->resource, GFP_ATOMIC); ··· 731 741 failed: 732 742 kfree(r); 733 743 kfree(e); 734 - kfree(fcp_frame); 735 744 736 - if (!is_fcp_request(request)) 745 + if (!is_fcp) 737 746 fw_send_response(card, request, RCODE_CONFLICT_ERROR); 747 + else 748 + fw_request_put(request); 738 749 739 750 fw_card_put(card); 740 751 } ··· 810 819 811 820 r = container_of(resource, struct inbound_transaction_resource, 812 821 resource); 813 - if (is_fcp_request(r->request)) 822 + if (r->is_fcp) { 823 + fw_request_put(r->request); 814 824 goto out; 825 + } 815 826 816 827 if (a->length != fw_get_response_length(r->request)) { 817 828 ret = -EINVAL; 818 - kfree(r->request); 829 + fw_request_put(r->request); 819 830 goto out; 820 831 } 821 832 if (copy_from_user(r->data, u64_to_uptr(a->data), a->length)) { 822 833 ret = -EFAULT; 823 - kfree(r->request); 834 + fw_request_put(r->request); 824 835 goto out; 825 836 } 826 837 fw_send_response(r->card, r->request, a->rcode);
+39 -14
drivers/firewire/core-transaction.c
··· 535 535 { .start = 0xfffff0000900ULL, .end = 0x1000000000000ULL, }; 536 536 #endif /* 0 */ 537 537 538 - static bool is_in_fcp_region(u64 offset, size_t length) 539 - { 540 - return offset >= (CSR_REGISTER_BASE | CSR_FCP_COMMAND) && 541 - offset + length <= (CSR_REGISTER_BASE | CSR_FCP_END); 542 - } 543 - 544 538 /** 545 539 * fw_core_add_address_handler() - register for incoming requests 546 540 * @handler: callback ··· 611 617 EXPORT_SYMBOL(fw_core_remove_address_handler); 612 618 613 619 struct fw_request { 620 + struct kref kref; 614 621 struct fw_packet response; 615 622 u32 request_header[4]; 616 623 int ack; ··· 620 625 u32 data[]; 621 626 }; 622 627 628 + void fw_request_get(struct fw_request *request) 629 + { 630 + kref_get(&request->kref); 631 + } 632 + 633 + static void release_request(struct kref *kref) 634 + { 635 + struct fw_request *request = container_of(kref, struct fw_request, kref); 636 + 637 + kfree(request); 638 + } 639 + 640 + void fw_request_put(struct fw_request *request) 641 + { 642 + kref_put(&request->kref, release_request); 643 + } 644 + 623 645 static void free_response_callback(struct fw_packet *packet, 624 646 struct fw_card *card, int status) 625 647 { 626 - struct fw_request *request; 648 + struct fw_request *request = container_of(packet, struct fw_request, response); 627 649 628 - request = container_of(packet, struct fw_request, response); 629 - kfree(request); 650 + // Decrease the reference count since not at in-flight. 651 + fw_request_put(request); 652 + 653 + // Decrease the reference count to release the object. 654 + fw_request_put(request); 630 655 } 631 656 632 657 int fw_get_response_length(struct fw_request *r) ··· 797 782 request = kmalloc(sizeof(*request) + length, GFP_ATOMIC); 798 783 if (request == NULL) 799 784 return NULL; 785 + kref_init(&request->kref); 800 786 801 787 request->response.speed = p->speed; 802 788 request->response.timestamp = ··· 816 800 return request; 817 801 } 818 802 803 + /** 804 + * fw_send_response: - send response packet for asynchronous transaction. 805 + * @card: interface to send the response at. 806 + * @request: firewire request data for the transaction. 807 + * @rcode: response code to send. 808 + * 809 + * Submit a response packet into the asynchronous response transmission queue. The @request 810 + * is going to be released when the transmission successfully finishes later. 811 + */ 819 812 void fw_send_response(struct fw_card *card, 820 813 struct fw_request *request, int rcode) 821 814 { 822 - if (WARN_ONCE(!request, "invalid for FCP address handlers")) 823 - return; 824 - 825 815 /* unified transaction or broadcast transaction: don't respond */ 826 816 if (request->ack != ACK_PENDING || 827 817 HEADER_DESTINATION_IS_BROADCAST(request->request_header[0])) { 828 - kfree(request); 818 + fw_request_put(request); 829 819 return; 830 820 } 831 821 ··· 842 820 else 843 821 fw_fill_response(&request->response, request->request_header, 844 822 rcode, NULL, 0); 823 + 824 + // Increase the reference count so that the object is kept during in-flight. 825 + fw_request_get(request); 845 826 846 827 card->driver->send_response(card, &request->response); 847 828 } ··· 935 910 rcu_read_lock(); 936 911 list_for_each_entry_rcu(handler, &address_handler_list, link) { 937 912 if (is_enclosing_handler(handler, offset, request->length)) 938 - handler->address_callback(card, NULL, tcode, 913 + handler->address_callback(card, request, tcode, 939 914 destination, source, 940 915 p->generation, offset, 941 916 request->data,
+9
drivers/firewire/core.h
··· 244 244 void fw_fill_response(struct fw_packet *response, u32 *request_header, 245 245 int rcode, void *payload, size_t length); 246 246 247 + void fw_request_get(struct fw_request *request); 248 + void fw_request_put(struct fw_request *request); 249 + 247 250 #define FW_PHY_CONFIG_NO_NODE_ID -1 248 251 #define FW_PHY_CONFIG_CURRENT_GAP_COUNT -1 249 252 void fw_send_phy_config(struct fw_card *card, ··· 255 252 static inline bool is_ping_packet(u32 *data) 256 253 { 257 254 return (data[0] & 0xc0ffffff) == 0 && ~data[0] == data[1]; 255 + } 256 + 257 + static inline bool is_in_fcp_region(u64 offset, size_t length) 258 + { 259 + return offset >= (CSR_REGISTER_BASE | CSR_FCP_COMMAND) && 260 + offset + length <= (CSR_REGISTER_BASE | CSR_FCP_END); 258 261 } 259 262 260 263 #endif /* _FIREWIRE_CORE_H */
+5 -7
drivers/spi/spi-mt65xx.c
··· 1253 1253 dev_notice(dev, "SPI dma_set_mask(%d) failed, ret:%d\n", 1254 1254 addr_bits, ret); 1255 1255 1256 + ret = devm_request_irq(dev, irq, mtk_spi_interrupt, 1257 + IRQF_TRIGGER_NONE, dev_name(dev), master); 1258 + if (ret) 1259 + return dev_err_probe(dev, ret, "failed to register irq\n"); 1260 + 1256 1261 pm_runtime_enable(dev); 1257 1262 1258 1263 ret = devm_spi_register_master(dev, master); 1259 1264 if (ret) { 1260 1265 pm_runtime_disable(dev); 1261 1266 return dev_err_probe(dev, ret, "failed to register master\n"); 1262 - } 1263 - 1264 - ret = devm_request_irq(dev, irq, mtk_spi_interrupt, 1265 - IRQF_TRIGGER_NONE, dev_name(dev), master); 1266 - if (ret) { 1267 - pm_runtime_disable(dev); 1268 - return dev_err_probe(dev, ret, "failed to register irq\n"); 1269 1267 } 1270 1268 1271 1269 return 0;
+2 -3
include/linux/firewire.h
··· 278 278 * Otherwise there is a danger of recursion of inbound and outbound 279 279 * transactions from and to the local node. 280 280 * 281 - * The callback is responsible that either fw_send_response() or kfree() 282 - * is called on the @request, except for FCP registers for which the core 283 - * takes care of that. 281 + * The callback is responsible that fw_send_response() is called on the @request, except for FCP 282 + * registers for which the core takes care of that. 284 283 */ 285 284 typedef void (*fw_address_callback_t)(struct fw_card *card, 286 285 struct fw_request *request,
+15 -9
sound/core/control.c
··· 1203 1203 const u32 pattern = 0xdeadbeef; 1204 1204 int ret; 1205 1205 1206 + down_read(&card->controls_rwsem); 1206 1207 kctl = snd_ctl_find_id(card, &control->id); 1207 - if (kctl == NULL) 1208 - return -ENOENT; 1208 + if (kctl == NULL) { 1209 + ret = -ENOENT; 1210 + goto unlock; 1211 + } 1209 1212 1210 1213 index_offset = snd_ctl_get_ioff(kctl, &control->id); 1211 1214 vd = &kctl->vd[index_offset]; 1212 - if (!(vd->access & SNDRV_CTL_ELEM_ACCESS_READ) || kctl->get == NULL) 1213 - return -EPERM; 1215 + if (!(vd->access & SNDRV_CTL_ELEM_ACCESS_READ) || kctl->get == NULL) { 1216 + ret = -EPERM; 1217 + goto unlock; 1218 + } 1214 1219 1215 1220 snd_ctl_build_ioff(&control->id, kctl, index_offset); 1216 1221 ··· 1225 1220 info.id = control->id; 1226 1221 ret = __snd_ctl_elem_info(card, kctl, &info, NULL); 1227 1222 if (ret < 0) 1228 - return ret; 1223 + goto unlock; 1229 1224 #endif 1230 1225 1231 1226 if (!snd_ctl_skip_validation(&info)) ··· 1235 1230 ret = kctl->get(kctl, control); 1236 1231 snd_power_unref(card); 1237 1232 if (ret < 0) 1238 - return ret; 1233 + goto unlock; 1239 1234 if (!snd_ctl_skip_validation(&info) && 1240 1235 sanity_check_elem_value(card, control, &info, pattern) < 0) { 1241 1236 dev_err(card->dev, ··· 1243 1238 control->id.iface, control->id.device, 1244 1239 control->id.subdevice, control->id.name, 1245 1240 control->id.index); 1246 - return -EINVAL; 1241 + ret = -EINVAL; 1242 + goto unlock; 1247 1243 } 1244 + unlock: 1245 + up_read(&card->controls_rwsem); 1248 1246 return ret; 1249 1247 } 1250 1248 ··· 1261 1253 if (IS_ERR(control)) 1262 1254 return PTR_ERR(control); 1263 1255 1264 - down_read(&card->controls_rwsem); 1265 1256 result = snd_ctl_elem_read(card, control); 1266 - up_read(&card->controls_rwsem); 1267 1257 if (result < 0) 1268 1258 goto error; 1269 1259
+2 -3
sound/core/control_led.c
··· 530 530 bool attach) 531 531 { 532 532 char buf2[256], *s, *os; 533 - size_t len = max(sizeof(s) - 1, count); 534 533 struct snd_ctl_elem_id id; 535 534 int err; 536 535 537 - strncpy(buf2, buf, len); 538 - buf2[len] = '\0'; 536 + if (strscpy(buf2, buf, sizeof(buf2)) < 0) 537 + return -E2BIG; 539 538 memset(&id, 0, sizeof(id)); 540 539 id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; 541 540 s = buf2;
+15 -5
sound/pci/hda/cs35l41_hda.c
··· 598 598 dev_dbg(cs35l41->dev, "System Suspend\n"); 599 599 600 600 if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST_NO_VSPK_SWITCH) { 601 - dev_err(cs35l41->dev, "System Suspend not supported\n"); 602 - return -EINVAL; 601 + dev_err_once(cs35l41->dev, "System Suspend not supported\n"); 602 + return 0; /* don't block the whole system suspend */ 603 603 } 604 604 605 605 ret = pm_runtime_force_suspend(dev); ··· 624 624 dev_dbg(cs35l41->dev, "System Resume\n"); 625 625 626 626 if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST_NO_VSPK_SWITCH) { 627 - dev_err(cs35l41->dev, "System Resume not supported\n"); 628 - return -EINVAL; 627 + dev_err_once(cs35l41->dev, "System Resume not supported\n"); 628 + return 0; /* don't block the whole system resume */ 629 629 } 630 630 631 631 if (cs35l41->reset_gpio) { ··· 645 645 mutex_unlock(&cs35l41->fw_mutex); 646 646 647 647 return ret; 648 + } 649 + 650 + static int cs35l41_runtime_idle(struct device *dev) 651 + { 652 + struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev); 653 + 654 + if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST_NO_VSPK_SWITCH) 655 + return -EBUSY; /* suspend not supported yet on this model */ 656 + return 0; 648 657 } 649 658 650 659 static int cs35l41_runtime_suspend(struct device *dev) ··· 1545 1536 EXPORT_SYMBOL_NS_GPL(cs35l41_hda_remove, SND_HDA_SCODEC_CS35L41); 1546 1537 1547 1538 const struct dev_pm_ops cs35l41_hda_pm_ops = { 1548 - RUNTIME_PM_OPS(cs35l41_runtime_suspend, cs35l41_runtime_resume, NULL) 1539 + RUNTIME_PM_OPS(cs35l41_runtime_suspend, cs35l41_runtime_resume, 1540 + cs35l41_runtime_idle) 1549 1541 SYSTEM_SLEEP_PM_OPS(cs35l41_system_suspend, cs35l41_system_resume) 1550 1542 }; 1551 1543 EXPORT_SYMBOL_NS_GPL(cs35l41_hda_pm_ops, SND_HDA_SCODEC_CS35L41);
+2
sound/pci/hda/hda_bind.c
··· 144 144 145 145 error: 146 146 snd_hda_codec_cleanup_for_unbind(codec); 147 + codec->preset = NULL; 147 148 return err; 148 149 } 149 150 ··· 167 166 if (codec->patch_ops.free) 168 167 codec->patch_ops.free(codec); 169 168 snd_hda_codec_cleanup_for_unbind(codec); 169 + codec->preset = NULL; 170 170 module_put(dev->driver->owner); 171 171 return 0; 172 172 }
-1
sound/pci/hda/hda_codec.c
··· 795 795 snd_array_free(&codec->cvt_setups); 796 796 snd_array_free(&codec->spdif_out); 797 797 snd_array_free(&codec->verbs); 798 - codec->preset = NULL; 799 798 codec->follower_dig_outs = NULL; 800 799 codec->spdif_status_reset = 0; 801 800 snd_array_free(&codec->mixers);
+1
sound/pci/hda/patch_hdmi.c
··· 1981 1981 SND_PCI_QUIRK(0x103c, 0x870f, "HP", 1), 1982 1982 SND_PCI_QUIRK(0x103c, 0x871a, "HP", 1), 1983 1983 SND_PCI_QUIRK(0x103c, 0x8711, "HP", 1), 1984 + SND_PCI_QUIRK(0x103c, 0x8715, "HP", 1), 1984 1985 SND_PCI_QUIRK(0x1462, 0xec94, "MS-7C94", 1), 1985 1986 SND_PCI_QUIRK(0x8086, 0x2081, "Intel NUC 10", 1), 1986 1987 {}
+42 -14
sound/pci/hda/patch_realtek.c
··· 3564 3564 hda_nid_t hp_pin = alc_get_hp_pin(spec); 3565 3565 bool hp_pin_sense; 3566 3566 3567 + if (spec->ultra_low_power) { 3568 + alc_update_coef_idx(codec, 0x03, 1<<1, 1<<1); 3569 + alc_update_coef_idx(codec, 0x08, 3<<2, 3<<2); 3570 + alc_update_coef_idx(codec, 0x08, 7<<4, 0); 3571 + alc_update_coef_idx(codec, 0x3b, 1<<15, 0); 3572 + alc_update_coef_idx(codec, 0x0e, 7<<6, 7<<6); 3573 + msleep(30); 3574 + } 3575 + 3567 3576 if (!hp_pin) 3568 3577 hp_pin = 0x21; 3569 3578 ··· 3584 3575 msleep(2); 3585 3576 3586 3577 alc_update_coefex_idx(codec, 0x57, 0x04, 0x0007, 0x1); /* Low power */ 3587 - if (spec->ultra_low_power) { 3588 - alc_update_coef_idx(codec, 0x03, 1<<1, 1<<1); 3589 - alc_update_coef_idx(codec, 0x08, 3<<2, 3<<2); 3590 - alc_update_coef_idx(codec, 0x08, 7<<4, 0); 3591 - alc_update_coef_idx(codec, 0x3b, 1<<15, 0); 3592 - alc_update_coef_idx(codec, 0x0e, 7<<6, 7<<6); 3593 - msleep(30); 3594 - } 3595 3578 3596 3579 snd_hda_codec_write(codec, hp_pin, 0, 3597 3580 AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); ··· 3714 3713 hda_nid_t hp_pin = alc_get_hp_pin(spec); 3715 3714 bool hp1_pin_sense, hp2_pin_sense; 3716 3715 3716 + if (spec->ultra_low_power) { 3717 + alc_update_coef_idx(codec, 0x08, 0x0f << 2, 3<<2); 3718 + alc_update_coef_idx(codec, 0x0e, 7<<6, 7<<6); 3719 + alc_update_coef_idx(codec, 0x33, 1<<11, 0); 3720 + msleep(30); 3721 + } 3722 + 3717 3723 if (spec->codec_variant != ALC269_TYPE_ALC287 && 3718 3724 spec->codec_variant != ALC269_TYPE_ALC245) 3719 3725 /* required only at boot or S3 and S4 resume time */ ··· 3742 3734 msleep(2); 3743 3735 3744 3736 alc_update_coefex_idx(codec, 0x57, 0x04, 0x0007, 0x1); /* Low power */ 3745 - if (spec->ultra_low_power) { 3746 - alc_update_coef_idx(codec, 0x08, 0x0f << 2, 3<<2); 3747 - alc_update_coef_idx(codec, 0x0e, 7<<6, 7<<6); 3748 - alc_update_coef_idx(codec, 0x33, 1<<11, 0); 3749 - msleep(30); 3750 - } 3751 3737 3752 3738 if (hp1_pin_sense || spec->ultra_low_power) 3753 3739 snd_hda_codec_write(codec, hp_pin, 0, ··· 4646 4644 } 4647 4645 } 4648 4646 4647 + static void alc285_fixup_hp_gpio_micmute_led(struct hda_codec *codec, 4648 + const struct hda_fixup *fix, int action) 4649 + { 4650 + struct alc_spec *spec = codec->spec; 4651 + 4652 + if (action == HDA_FIXUP_ACT_PRE_PROBE) 4653 + spec->micmute_led_polarity = 1; 4654 + alc_fixup_hp_gpio_led(codec, action, 0, 0x04); 4655 + } 4656 + 4649 4657 static void alc236_fixup_hp_coef_micmute_led(struct hda_codec *codec, 4650 4658 const struct hda_fixup *fix, int action) 4651 4659 { ··· 4675 4663 { 4676 4664 alc285_fixup_hp_mute_led_coefbit(codec, fix, action); 4677 4665 alc285_fixup_hp_coef_micmute_led(codec, fix, action); 4666 + } 4667 + 4668 + static void alc285_fixup_hp_spectre_x360_mute_led(struct hda_codec *codec, 4669 + const struct hda_fixup *fix, int action) 4670 + { 4671 + alc285_fixup_hp_mute_led_coefbit(codec, fix, action); 4672 + alc285_fixup_hp_gpio_micmute_led(codec, fix, action); 4678 4673 } 4679 4674 4680 4675 static void alc236_fixup_hp_mute_led(struct hda_codec *codec, ··· 7125 7106 ALC285_FIXUP_ASUS_G533Z_PINS, 7126 7107 ALC285_FIXUP_HP_GPIO_LED, 7127 7108 ALC285_FIXUP_HP_MUTE_LED, 7109 + ALC285_FIXUP_HP_SPECTRE_X360_MUTE_LED, 7128 7110 ALC236_FIXUP_HP_GPIO_LED, 7129 7111 ALC236_FIXUP_HP_MUTE_LED, 7130 7112 ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF, ··· 8506 8486 .type = HDA_FIXUP_FUNC, 8507 8487 .v.func = alc285_fixup_hp_mute_led, 8508 8488 }, 8489 + [ALC285_FIXUP_HP_SPECTRE_X360_MUTE_LED] = { 8490 + .type = HDA_FIXUP_FUNC, 8491 + .v.func = alc285_fixup_hp_spectre_x360_mute_led, 8492 + }, 8509 8493 [ALC236_FIXUP_HP_GPIO_LED] = { 8510 8494 .type = HDA_FIXUP_FUNC, 8511 8495 .v.func = alc236_fixup_hp_gpio_led, ··· 9263 9239 SND_PCI_QUIRK(0x1028, 0x0b1a, "Dell Precision 5570", ALC289_FIXUP_DUAL_SPK), 9264 9240 SND_PCI_QUIRK(0x1028, 0x0b37, "Dell Inspiron 16 Plus 7620 2-in-1", ALC295_FIXUP_DELL_INSPIRON_TOP_SPEAKERS), 9265 9241 SND_PCI_QUIRK(0x1028, 0x0b71, "Dell Inspiron 16 Plus 7620", ALC295_FIXUP_DELL_INSPIRON_TOP_SPEAKERS), 9242 + SND_PCI_QUIRK(0x1028, 0x0c03, "Dell Precision 5340", ALC269_FIXUP_DELL4_MIC_NO_PRESENCE), 9266 9243 SND_PCI_QUIRK(0x1028, 0x0c19, "Dell Precision 3340", ALC236_FIXUP_DELL_DUAL_CODECS), 9267 9244 SND_PCI_QUIRK(0x1028, 0x0c1a, "Dell Precision 3340", ALC236_FIXUP_DELL_DUAL_CODECS), 9268 9245 SND_PCI_QUIRK(0x1028, 0x0c1b, "Dell Precision 3440", ALC236_FIXUP_DELL_DUAL_CODECS), ··· 9352 9327 SND_PCI_QUIRK(0x103c, 0x86c7, "HP Envy AiO 32", ALC274_FIXUP_HP_ENVY_GPIO), 9353 9328 SND_PCI_QUIRK(0x103c, 0x86e7, "HP Spectre x360 15-eb0xxx", ALC285_FIXUP_HP_SPECTRE_X360_EB1), 9354 9329 SND_PCI_QUIRK(0x103c, 0x86e8, "HP Spectre x360 15-eb0xxx", ALC285_FIXUP_HP_SPECTRE_X360_EB1), 9330 + SND_PCI_QUIRK(0x103c, 0x86f9, "HP Spectre x360 13-aw0xxx", ALC285_FIXUP_HP_SPECTRE_X360_MUTE_LED), 9355 9331 SND_PCI_QUIRK(0x103c, 0x8716, "HP Elite Dragonfly G2 Notebook PC", ALC285_FIXUP_HP_GPIO_AMP_INIT), 9356 9332 SND_PCI_QUIRK(0x103c, 0x8720, "HP EliteBook x360 1040 G8 Notebook PC", ALC285_FIXUP_HP_GPIO_AMP_INIT), 9357 9333 SND_PCI_QUIRK(0x103c, 0x8724, "HP EliteBook 850 G7", ALC285_FIXUP_HP_GPIO_LED), ··· 9432 9406 SND_PCI_QUIRK(0x103c, 0x8ad2, "HP EliteBook 860 16 inch G9 Notebook PC", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), 9433 9407 SND_PCI_QUIRK(0x103c, 0x8b5d, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF), 9434 9408 SND_PCI_QUIRK(0x103c, 0x8b5e, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF), 9409 + SND_PCI_QUIRK(0x103c, 0x8b92, "HP", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), 9410 + SND_PCI_QUIRK(0x103c, 0x8bf0, "HP", ALC236_FIXUP_HP_GPIO_LED), 9435 9411 SND_PCI_QUIRK(0x1043, 0x103e, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC), 9436 9412 SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300), 9437 9413 SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
+3
sound/pci/hda/patch_via.c
··· 819 819 return 0; 820 820 nums = snd_hda_get_connections(codec, spec->gen.mixer_nid, conn, 821 821 ARRAY_SIZE(conn) - 1); 822 + if (nums < 0) 823 + return nums; 824 + 822 825 for (i = 0; i < nums; i++) { 823 826 if (get_wcaps_type(get_wcaps(codec, conn[i])) == AC_WID_AUD_OUT) 824 827 return 0;
+14
sound/soc/amd/yc/acp6x-mach.c
··· 209 209 { 210 210 .driver_data = &acp6x_card, 211 211 .matches = { 212 + DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."), 213 + DMI_MATCH(DMI_PRODUCT_NAME, "M5402RA"), 214 + } 215 + }, 216 + { 217 + .driver_data = &acp6x_card, 218 + .matches = { 212 219 DMI_MATCH(DMI_BOARD_VENDOR, "Alienware"), 213 220 DMI_MATCH(DMI_PRODUCT_NAME, "Alienware m17 R5 AMD"), 214 221 } ··· 225 218 .matches = { 226 219 DMI_MATCH(DMI_BOARD_VENDOR, "TIMI"), 227 220 DMI_MATCH(DMI_PRODUCT_NAME, "Redmi Book Pro 14 2022"), 221 + } 222 + }, 223 + { 224 + .driver_data = &acp6x_card, 225 + .matches = { 226 + DMI_MATCH(DMI_BOARD_VENDOR, "Razer"), 227 + DMI_MATCH(DMI_PRODUCT_NAME, "Blade 14 (2022) - RZ09-0427"), 228 228 } 229 229 }, 230 230 {}
+12
sound/soc/codecs/rt9120.c
··· 177 177 return 0; 178 178 } 179 179 180 + static int rt9120_codec_suspend(struct snd_soc_component *comp) 181 + { 182 + return pm_runtime_force_suspend(comp->dev); 183 + } 184 + 185 + static int rt9120_codec_resume(struct snd_soc_component *comp) 186 + { 187 + return pm_runtime_force_resume(comp->dev); 188 + } 189 + 180 190 static const struct snd_soc_component_driver rt9120_component_driver = { 181 191 .probe = rt9120_codec_probe, 192 + .suspend = rt9120_codec_suspend, 193 + .resume = rt9120_codec_resume, 182 194 .controls = rt9120_snd_controls, 183 195 .num_controls = ARRAY_SIZE(rt9120_snd_controls), 184 196 .dapm_widgets = rt9120_dapm_widgets,
+7
sound/soc/codecs/wm8904.c
··· 697 697 int dcs_mask; 698 698 int dcs_l, dcs_r; 699 699 int dcs_l_reg, dcs_r_reg; 700 + int an_out_reg; 700 701 int timeout; 701 702 int pwr_reg; 702 703 ··· 713 712 dcs_mask = WM8904_DCS_ENA_CHAN_0 | WM8904_DCS_ENA_CHAN_1; 714 713 dcs_r_reg = WM8904_DC_SERVO_8; 715 714 dcs_l_reg = WM8904_DC_SERVO_9; 715 + an_out_reg = WM8904_ANALOGUE_OUT1_LEFT; 716 716 dcs_l = 0; 717 717 dcs_r = 1; 718 718 break; ··· 722 720 dcs_mask = WM8904_DCS_ENA_CHAN_2 | WM8904_DCS_ENA_CHAN_3; 723 721 dcs_r_reg = WM8904_DC_SERVO_6; 724 722 dcs_l_reg = WM8904_DC_SERVO_7; 723 + an_out_reg = WM8904_ANALOGUE_OUT2_LEFT; 725 724 dcs_l = 2; 726 725 dcs_r = 3; 727 726 break; ··· 795 792 snd_soc_component_update_bits(component, reg, 796 793 WM8904_HPL_ENA_OUTP | WM8904_HPR_ENA_OUTP, 797 794 WM8904_HPL_ENA_OUTP | WM8904_HPR_ENA_OUTP); 795 + 796 + /* Update volume, requires PGA to be powered */ 797 + val = snd_soc_component_read(component, an_out_reg); 798 + snd_soc_component_write(component, an_out_reg, val); 798 799 break; 799 800 800 801 case SND_SOC_DAPM_POST_PMU:
+4 -4
sound/soc/fsl/fsl-asoc-card.c
··· 121 121 122 122 static const struct snd_soc_dapm_route audio_map_ac97[] = { 123 123 /* 1st half -- Normal DAPM routes */ 124 - {"Playback", NULL, "AC97 Playback"}, 125 - {"AC97 Capture", NULL, "Capture"}, 124 + {"AC97 Playback", NULL, "CPU AC97 Playback"}, 125 + {"CPU AC97 Capture", NULL, "AC97 Capture"}, 126 126 /* 2nd half -- ASRC DAPM routes */ 127 - {"AC97 Playback", NULL, "ASRC-Playback"}, 128 - {"ASRC-Capture", NULL, "AC97 Capture"}, 127 + {"CPU AC97 Playback", NULL, "ASRC-Playback"}, 128 + {"ASRC-Capture", NULL, "CPU AC97 Capture"}, 129 129 }; 130 130 131 131 static const struct snd_soc_dapm_route audio_map_tx[] = {
+8 -8
sound/soc/fsl/fsl_micfil.c
··· 315 315 316 316 static const struct snd_kcontrol_new fsl_micfil_snd_controls[] = { 317 317 SOC_SINGLE_SX_TLV("CH0 Volume", REG_MICFIL_OUT_CTRL, 318 - MICFIL_OUTGAIN_CHX_SHIFT(0), 0xF, 0x7, gain_tlv), 318 + MICFIL_OUTGAIN_CHX_SHIFT(0), 0x8, 0xF, gain_tlv), 319 319 SOC_SINGLE_SX_TLV("CH1 Volume", REG_MICFIL_OUT_CTRL, 320 - MICFIL_OUTGAIN_CHX_SHIFT(1), 0xF, 0x7, gain_tlv), 320 + MICFIL_OUTGAIN_CHX_SHIFT(1), 0x8, 0xF, gain_tlv), 321 321 SOC_SINGLE_SX_TLV("CH2 Volume", REG_MICFIL_OUT_CTRL, 322 - MICFIL_OUTGAIN_CHX_SHIFT(2), 0xF, 0x7, gain_tlv), 322 + MICFIL_OUTGAIN_CHX_SHIFT(2), 0x8, 0xF, gain_tlv), 323 323 SOC_SINGLE_SX_TLV("CH3 Volume", REG_MICFIL_OUT_CTRL, 324 - MICFIL_OUTGAIN_CHX_SHIFT(3), 0xF, 0x7, gain_tlv), 324 + MICFIL_OUTGAIN_CHX_SHIFT(3), 0x8, 0xF, gain_tlv), 325 325 SOC_SINGLE_SX_TLV("CH4 Volume", REG_MICFIL_OUT_CTRL, 326 - MICFIL_OUTGAIN_CHX_SHIFT(4), 0xF, 0x7, gain_tlv), 326 + MICFIL_OUTGAIN_CHX_SHIFT(4), 0x8, 0xF, gain_tlv), 327 327 SOC_SINGLE_SX_TLV("CH5 Volume", REG_MICFIL_OUT_CTRL, 328 - MICFIL_OUTGAIN_CHX_SHIFT(5), 0xF, 0x7, gain_tlv), 328 + MICFIL_OUTGAIN_CHX_SHIFT(5), 0x8, 0xF, gain_tlv), 329 329 SOC_SINGLE_SX_TLV("CH6 Volume", REG_MICFIL_OUT_CTRL, 330 - MICFIL_OUTGAIN_CHX_SHIFT(6), 0xF, 0x7, gain_tlv), 330 + MICFIL_OUTGAIN_CHX_SHIFT(6), 0x8, 0xF, gain_tlv), 331 331 SOC_SINGLE_SX_TLV("CH7 Volume", REG_MICFIL_OUT_CTRL, 332 - MICFIL_OUTGAIN_CHX_SHIFT(7), 0xF, 0x7, gain_tlv), 332 + MICFIL_OUTGAIN_CHX_SHIFT(7), 0x8, 0xF, gain_tlv), 333 333 SOC_ENUM_EXT("MICFIL Quality Select", 334 334 fsl_micfil_quality_enum, 335 335 micfil_quality_get, micfil_quality_set),
+2 -2
sound/soc/fsl/fsl_ssi.c
··· 1189 1189 .symmetric_channels = 1, 1190 1190 .probe = fsl_ssi_dai_probe, 1191 1191 .playback = { 1192 - .stream_name = "AC97 Playback", 1192 + .stream_name = "CPU AC97 Playback", 1193 1193 .channels_min = 2, 1194 1194 .channels_max = 2, 1195 1195 .rates = SNDRV_PCM_RATE_8000_48000, 1196 1196 .formats = SNDRV_PCM_FMTBIT_S16 | SNDRV_PCM_FMTBIT_S20, 1197 1197 }, 1198 1198 .capture = { 1199 - .stream_name = "AC97 Capture", 1199 + .stream_name = "CPU AC97 Capture", 1200 1200 .channels_min = 2, 1201 1201 .channels_max = 2, 1202 1202 .rates = SNDRV_PCM_RATE_48000,
+2
sound/soc/intel/boards/Kconfig
··· 554 554 select SND_SOC_RT1015P 555 555 select SND_SOC_MAX98373_I2C 556 556 select SND_SOC_MAX98357A 557 + select SND_SOC_NAU8315 557 558 select SND_SOC_DMIC 558 559 select SND_SOC_HDAC_HDMI 559 560 select SND_SOC_INTEL_HDA_DSP_COMMON 560 561 select SND_SOC_INTEL_SOF_MAXIM_COMMON 562 + select SND_SOC_INTEL_SOF_REALTEK_COMMON 561 563 help 562 564 This adds support for ASoC machine driver for SOF platforms 563 565 with nau8825 codec.
+27 -4
sound/soc/intel/boards/sof_nau8825.c
··· 48 48 #define SOF_MAX98373_SPEAKER_AMP_PRESENT BIT(15) 49 49 #define SOF_MAX98360A_SPEAKER_AMP_PRESENT BIT(16) 50 50 #define SOF_RT1015P_SPEAKER_AMP_PRESENT BIT(17) 51 + #define SOF_NAU8318_SPEAKER_AMP_PRESENT BIT(18) 51 52 52 53 static unsigned long sof_nau8825_quirk = SOF_NAU8825_SSP_CODEC(0); 53 54 ··· 339 338 } 340 339 }; 341 340 341 + static struct snd_soc_dai_link_component nau8318_components[] = { 342 + { 343 + .name = "NVTN2012:00", 344 + .dai_name = "nau8315-hifi", 345 + } 346 + }; 347 + 342 348 static struct snd_soc_dai_link_component dummy_component[] = { 343 349 { 344 350 .name = "snd-soc-dummy", ··· 494 486 max_98360a_dai_link(&links[id]); 495 487 } else if (sof_nau8825_quirk & SOF_RT1015P_SPEAKER_AMP_PRESENT) { 496 488 sof_rt1015p_dai_link(&links[id]); 489 + } else if (sof_nau8825_quirk & 490 + SOF_NAU8318_SPEAKER_AMP_PRESENT) { 491 + links[id].codecs = nau8318_components; 492 + links[id].num_codecs = ARRAY_SIZE(nau8318_components); 493 + links[id].init = speaker_codec_init; 497 494 } else { 498 495 goto devm_err; 499 496 } ··· 631 618 632 619 }, 633 620 { 634 - .name = "adl_rt1019p_nau8825", 621 + .name = "adl_rt1019p_8825", 635 622 .driver_data = (kernel_ulong_t)(SOF_NAU8825_SSP_CODEC(0) | 636 623 SOF_SPEAKER_AMP_PRESENT | 637 624 SOF_RT1019P_SPEAKER_AMP_PRESENT | ··· 639 626 SOF_NAU8825_NUM_HDMIDEV(4)), 640 627 }, 641 628 { 642 - .name = "adl_max98373_nau8825", 629 + .name = "adl_max98373_8825", 643 630 .driver_data = (kernel_ulong_t)(SOF_NAU8825_SSP_CODEC(0) | 644 631 SOF_SPEAKER_AMP_PRESENT | 645 632 SOF_MAX98373_SPEAKER_AMP_PRESENT | ··· 650 637 }, 651 638 { 652 639 /* The limitation of length of char array, shorten the name */ 653 - .name = "adl_mx98360a_nau8825", 640 + .name = "adl_mx98360a_8825", 654 641 .driver_data = (kernel_ulong_t)(SOF_NAU8825_SSP_CODEC(0) | 655 642 SOF_SPEAKER_AMP_PRESENT | 656 643 SOF_MAX98360A_SPEAKER_AMP_PRESENT | ··· 661 648 662 649 }, 663 650 { 664 - .name = "adl_rt1015p_nau8825", 651 + .name = "adl_rt1015p_8825", 665 652 .driver_data = (kernel_ulong_t)(SOF_NAU8825_SSP_CODEC(0) | 666 653 SOF_SPEAKER_AMP_PRESENT | 667 654 SOF_RT1015P_SPEAKER_AMP_PRESENT | 655 + SOF_NAU8825_SSP_AMP(1) | 656 + SOF_NAU8825_NUM_HDMIDEV(4) | 657 + SOF_BT_OFFLOAD_SSP(2) | 658 + SOF_SSP_BT_OFFLOAD_PRESENT), 659 + }, 660 + { 661 + .name = "adl_nau8318_8825", 662 + .driver_data = (kernel_ulong_t)(SOF_NAU8825_SSP_CODEC(0) | 663 + SOF_SPEAKER_AMP_PRESENT | 664 + SOF_NAU8318_SPEAKER_AMP_PRESENT | 668 665 SOF_NAU8825_SSP_AMP(1) | 669 666 SOF_NAU8825_NUM_HDMIDEV(4) | 670 667 SOF_BT_OFFLOAD_SSP(2) |
+16 -4
sound/soc/intel/common/soc-acpi-intel-adl-match.c
··· 450 450 .codecs = {"INTC10B0"} 451 451 }; 452 452 453 + static const struct snd_soc_acpi_codecs adl_nau8318_amp = { 454 + .num_codecs = 1, 455 + .codecs = {"NVTN2012"} 456 + }; 457 + 453 458 struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_machines[] = { 454 459 { 455 460 .comp_ids = &adl_rt5682_rt5682s_hp, ··· 479 474 }, 480 475 { 481 476 .id = "10508825", 482 - .drv_name = "adl_rt1019p_nau8825", 477 + .drv_name = "adl_rt1019p_8825", 483 478 .machine_quirk = snd_soc_acpi_codec_list, 484 479 .quirk_data = &adl_rt1019p_amp, 485 480 .sof_tplg_filename = "sof-adl-rt1019-nau8825.tplg", 486 481 }, 487 482 { 488 483 .id = "10508825", 489 - .drv_name = "adl_max98373_nau8825", 484 + .drv_name = "adl_max98373_8825", 490 485 .machine_quirk = snd_soc_acpi_codec_list, 491 486 .quirk_data = &adl_max98373_amp, 492 487 .sof_tplg_filename = "sof-adl-max98373-nau8825.tplg", 493 488 }, 494 489 { 495 490 .id = "10508825", 496 - .drv_name = "adl_mx98360a_nau8825", 491 + .drv_name = "adl_mx98360a_8825", 497 492 .machine_quirk = snd_soc_acpi_codec_list, 498 493 .quirk_data = &adl_max98360a_amp, 499 494 .sof_tplg_filename = "sof-adl-max98360a-nau8825.tplg", ··· 507 502 }, 508 503 { 509 504 .id = "10508825", 510 - .drv_name = "adl_rt1015p_nau8825", 505 + .drv_name = "adl_rt1015p_8825", 511 506 .machine_quirk = snd_soc_acpi_codec_list, 512 507 .quirk_data = &adl_rt1015p_amp, 513 508 .sof_tplg_filename = "sof-adl-rt1015-nau8825.tplg", 509 + }, 510 + { 511 + .id = "10508825", 512 + .drv_name = "adl_nau8318_8825", 513 + .machine_quirk = snd_soc_acpi_codec_list, 514 + .quirk_data = &adl_nau8318_amp, 515 + .sof_tplg_filename = "sof-adl-nau8318-nau8825.tplg", 514 516 }, 515 517 { 516 518 .id = "10508825",
+50
sound/soc/intel/common/soc-acpi-intel-rpl-match.c
··· 203 203 {} 204 204 }; 205 205 206 + static const struct snd_soc_acpi_link_adr rpl_sdw_rt711_link2_rt1316_link01[] = { 207 + { 208 + .mask = BIT(2), 209 + .num_adr = ARRAY_SIZE(rt711_sdca_2_adr), 210 + .adr_d = rt711_sdca_2_adr, 211 + }, 212 + { 213 + .mask = BIT(0), 214 + .num_adr = ARRAY_SIZE(rt1316_0_group2_adr), 215 + .adr_d = rt1316_0_group2_adr, 216 + }, 217 + { 218 + .mask = BIT(1), 219 + .num_adr = ARRAY_SIZE(rt1316_1_group2_adr), 220 + .adr_d = rt1316_1_group2_adr, 221 + }, 222 + {} 223 + }; 224 + 206 225 static const struct snd_soc_acpi_link_adr rpl_sdw_rt711_link0_rt1318_link12_rt714_link3[] = { 207 226 { 208 227 .mask = BIT(0), ··· 242 223 .mask = BIT(3), 243 224 .num_adr = ARRAY_SIZE(rt714_3_adr), 244 225 .adr_d = rt714_3_adr, 226 + }, 227 + {} 228 + }; 229 + 230 + static const struct snd_soc_acpi_link_adr rpl_sdw_rt711_link0_rt1318_link12[] = { 231 + { 232 + .mask = BIT(0), 233 + .num_adr = ARRAY_SIZE(rt711_sdca_0_adr), 234 + .adr_d = rt711_sdca_0_adr, 235 + }, 236 + { 237 + .mask = BIT(1), 238 + .num_adr = ARRAY_SIZE(rt1318_1_group1_adr), 239 + .adr_d = rt1318_1_group1_adr, 240 + }, 241 + { 242 + .mask = BIT(2), 243 + .num_adr = ARRAY_SIZE(rt1318_2_group1_adr), 244 + .adr_d = rt1318_2_group1_adr, 245 245 }, 246 246 {} 247 247 }; ··· 310 272 .sof_tplg_filename = "sof-rpl-rt711-l0-rt1318-l12-rt714-l3.tplg", 311 273 }, 312 274 { 275 + .link_mask = 0x7, /* rt711 on link0 & two rt1318s on link1 and link2 */ 276 + .links = rpl_sdw_rt711_link0_rt1318_link12, 277 + .drv_name = "sof_sdw", 278 + .sof_tplg_filename = "sof-rpl-rt711-l0-rt1318-l12.tplg", 279 + }, 280 + { 313 281 .link_mask = 0x7, /* rt714 on link0 & two rt1316s on link1 and link2 */ 314 282 .links = rpl_sdw_rt1316_link12_rt714_link0, 315 283 .drv_name = "sof_sdw", 316 284 .sof_tplg_filename = "sof-rpl-rt1316-l12-rt714-l0.tplg", 285 + }, 286 + { 287 + .link_mask = 0x7, /* rt711 on link2 & two rt1316s on link0 and link1 */ 288 + .links = rpl_sdw_rt711_link2_rt1316_link01, 289 + .drv_name = "sof_sdw", 290 + .sof_tplg_filename = "sof-rpl-rt711-l2-rt1316-l01.tplg", 317 291 }, 318 292 { 319 293 .link_mask = 0x1, /* link0 required */
+3 -1
sound/soc/mediatek/Kconfig
··· 182 182 If unsure select "N". 183 183 184 184 config SND_SOC_MT8186_MT6366_RT1019_RT5682S 185 - tristate "ASoC Audio driver for MT8186 with RT1019 RT5682S codec" 185 + tristate "ASoC Audio driver for MT8186 with RT1019 RT5682S MAX98357A/MAX98360 codec" 186 186 depends on I2C && GPIOLIB 187 187 depends on SND_SOC_MT8186 && MTK_PMIC_WRAP 188 + select SND_SOC_MAX98357A 188 189 select SND_SOC_MT6358 190 + select SND_SOC_MAX98357A 189 191 select SND_SOC_RT1015P 190 192 select SND_SOC_RT5682S 191 193 select SND_SOC_BT_SCO
+21 -1
sound/soc/mediatek/mt8186/mt8186-mt6366-rt1019-rt5682s.c
··· 1083 1083 .num_configs = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_codec_conf), 1084 1084 }; 1085 1085 1086 + static struct snd_soc_card mt8186_mt6366_rt5682s_max98360_soc_card = { 1087 + .name = "mt8186_rt5682s_max98360", 1088 + .owner = THIS_MODULE, 1089 + .dai_link = mt8186_mt6366_rt1019_rt5682s_dai_links, 1090 + .num_links = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_dai_links), 1091 + .controls = mt8186_mt6366_rt1019_rt5682s_controls, 1092 + .num_controls = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_controls), 1093 + .dapm_widgets = mt8186_mt6366_rt1019_rt5682s_widgets, 1094 + .num_dapm_widgets = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_widgets), 1095 + .dapm_routes = mt8186_mt6366_rt1019_rt5682s_routes, 1096 + .num_dapm_routes = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_routes), 1097 + .codec_conf = mt8186_mt6366_rt1019_rt5682s_codec_conf, 1098 + .num_configs = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_codec_conf), 1099 + }; 1100 + 1086 1101 static int mt8186_mt6366_rt1019_rt5682s_dev_probe(struct platform_device *pdev) 1087 1102 { 1088 1103 struct snd_soc_card *card; ··· 1247 1232 1248 1233 #if IS_ENABLED(CONFIG_OF) 1249 1234 static const struct of_device_id mt8186_mt6366_rt1019_rt5682s_dt_match[] = { 1250 - { .compatible = "mediatek,mt8186-mt6366-rt1019-rt5682s-sound", 1235 + { 1236 + .compatible = "mediatek,mt8186-mt6366-rt1019-rt5682s-sound", 1251 1237 .data = &mt8186_mt6366_rt1019_rt5682s_soc_card, 1238 + }, 1239 + { 1240 + .compatible = "mediatek,mt8186-mt6366-rt5682s-max98360-sound", 1241 + .data = &mt8186_mt6366_rt5682s_max98360_soc_card, 1252 1242 }, 1253 1243 {} 1254 1244 };
+12 -9
sound/soc/qcom/Kconfig
··· 2 2 menuconfig SND_SOC_QCOM 3 3 tristate "ASoC support for QCOM platforms" 4 4 depends on ARCH_QCOM || COMPILE_TEST 5 - imply SND_SOC_QCOM_COMMON 6 5 help 7 6 Say Y or M if you want to add support to use audio devices 8 7 in Qualcomm Technologies SOC-based platforms. ··· 59 60 config SND_SOC_APQ8016_SBC 60 61 tristate "SoC Audio support for APQ8016 SBC platforms" 61 62 select SND_SOC_LPASS_APQ8016 62 - depends on SND_SOC_QCOM_COMMON 63 + select SND_SOC_QCOM_COMMON 63 64 help 64 65 Support for Qualcomm Technologies LPASS audio block in 65 66 APQ8016 SOC-based systems. 66 67 Say Y if you want to use audio devices on MI2S. 67 68 68 69 config SND_SOC_QCOM_COMMON 69 - depends on SOUNDWIRE 70 + tristate 71 + 72 + config SND_SOC_QCOM_SDW 70 73 tristate 71 74 72 75 config SND_SOC_QDSP6_COMMON ··· 145 144 depends on QCOM_APR 146 145 depends on COMMON_CLK 147 146 select SND_SOC_QDSP6 148 - depends on SND_SOC_QCOM_COMMON 147 + select SND_SOC_QCOM_COMMON 149 148 help 150 149 Support for Qualcomm Technologies LPASS audio block in 151 150 APQ8096 SoC-based systems. ··· 156 155 depends on QCOM_APR && I2C && SOUNDWIRE 157 156 depends on COMMON_CLK 158 157 select SND_SOC_QDSP6 159 - depends on SND_SOC_QCOM_COMMON 158 + select SND_SOC_QCOM_COMMON 160 159 select SND_SOC_RT5663 161 160 select SND_SOC_MAX98927 162 161 imply SND_SOC_CROS_EC_CODEC ··· 170 169 depends on QCOM_APR && SOUNDWIRE 171 170 depends on COMMON_CLK 172 171 select SND_SOC_QDSP6 173 - depends on SND_SOC_QCOM_COMMON 172 + select SND_SOC_QCOM_COMMON 173 + select SND_SOC_QCOM_SDW 174 174 help 175 175 To add support for audio on Qualcomm Technologies Inc. 176 176 SM8250 SoC-based systems. ··· 182 180 depends on QCOM_APR && SOUNDWIRE 183 181 depends on COMMON_CLK 184 182 select SND_SOC_QDSP6 185 - depends on SND_SOC_QCOM_COMMON 183 + select SND_SOC_QCOM_COMMON 184 + select SND_SOC_QCOM_SDW 186 185 help 187 186 To add support for audio on Qualcomm Technologies Inc. 188 187 SC8280XP SoC-based systems. ··· 193 190 tristate "SoC Machine driver for SC7180 boards" 194 191 depends on I2C && GPIOLIB 195 192 depends on SOUNDWIRE || SOUNDWIRE=n 196 - depends on SND_SOC_QCOM_COMMON 193 + select SND_SOC_QCOM_COMMON 197 194 select SND_SOC_LPASS_SC7180 198 195 select SND_SOC_MAX98357A 199 196 select SND_SOC_RT5682_I2C ··· 207 204 config SND_SOC_SC7280 208 205 tristate "SoC Machine driver for SC7280 boards" 209 206 depends on I2C && SOUNDWIRE 210 - depends on SND_SOC_QCOM_COMMON 207 + select SND_SOC_QCOM_COMMON 211 208 select SND_SOC_LPASS_SC7280 212 209 select SND_SOC_MAX98357A 213 210 select SND_SOC_WCD938X_SDW
+2
sound/soc/qcom/Makefile
··· 28 28 snd-soc-sm8250-objs := sm8250.o 29 29 snd-soc-sc8280xp-objs := sc8280xp.o 30 30 snd-soc-qcom-common-objs := common.o 31 + snd-soc-qcom-sdw-objs := sdw.o 31 32 32 33 obj-$(CONFIG_SND_SOC_STORM) += snd-soc-storm.o 33 34 obj-$(CONFIG_SND_SOC_APQ8016_SBC) += snd-soc-apq8016-sbc.o ··· 39 38 obj-$(CONFIG_SND_SOC_SDM845) += snd-soc-sdm845.o 40 39 obj-$(CONFIG_SND_SOC_SM8250) += snd-soc-sm8250.o 41 40 obj-$(CONFIG_SND_SOC_QCOM_COMMON) += snd-soc-qcom-common.o 41 + obj-$(CONFIG_SND_SOC_QCOM_SDW) += snd-soc-qcom-sdw.o 42 42 43 43 #DSP lib 44 44 obj-$(CONFIG_SND_SOC_QDSP6) += qdsp6/
-114
sound/soc/qcom/common.c
··· 180 180 } 181 181 EXPORT_SYMBOL_GPL(qcom_snd_parse_of); 182 182 183 - int qcom_snd_sdw_prepare(struct snd_pcm_substream *substream, 184 - struct sdw_stream_runtime *sruntime, 185 - bool *stream_prepared) 186 - { 187 - struct snd_soc_pcm_runtime *rtd = substream->private_data; 188 - struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 189 - int ret; 190 - 191 - if (!sruntime) 192 - return 0; 193 - 194 - switch (cpu_dai->id) { 195 - case WSA_CODEC_DMA_RX_0: 196 - case WSA_CODEC_DMA_RX_1: 197 - case RX_CODEC_DMA_RX_0: 198 - case RX_CODEC_DMA_RX_1: 199 - case TX_CODEC_DMA_TX_0: 200 - case TX_CODEC_DMA_TX_1: 201 - case TX_CODEC_DMA_TX_2: 202 - case TX_CODEC_DMA_TX_3: 203 - break; 204 - default: 205 - return 0; 206 - } 207 - 208 - if (*stream_prepared) { 209 - sdw_disable_stream(sruntime); 210 - sdw_deprepare_stream(sruntime); 211 - *stream_prepared = false; 212 - } 213 - 214 - ret = sdw_prepare_stream(sruntime); 215 - if (ret) 216 - return ret; 217 - 218 - /** 219 - * NOTE: there is a strict hw requirement about the ordering of port 220 - * enables and actual WSA881x PA enable. PA enable should only happen 221 - * after soundwire ports are enabled if not DC on the line is 222 - * accumulated resulting in Click/Pop Noise 223 - * PA enable/mute are handled as part of codec DAPM and digital mute. 224 - */ 225 - 226 - ret = sdw_enable_stream(sruntime); 227 - if (ret) { 228 - sdw_deprepare_stream(sruntime); 229 - return ret; 230 - } 231 - *stream_prepared = true; 232 - 233 - return ret; 234 - } 235 - EXPORT_SYMBOL_GPL(qcom_snd_sdw_prepare); 236 - 237 - int qcom_snd_sdw_hw_params(struct snd_pcm_substream *substream, 238 - struct snd_pcm_hw_params *params, 239 - struct sdw_stream_runtime **psruntime) 240 - { 241 - struct snd_soc_pcm_runtime *rtd = substream->private_data; 242 - struct snd_soc_dai *codec_dai; 243 - struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 244 - struct sdw_stream_runtime *sruntime; 245 - int i; 246 - 247 - switch (cpu_dai->id) { 248 - case WSA_CODEC_DMA_RX_0: 249 - case RX_CODEC_DMA_RX_0: 250 - case RX_CODEC_DMA_RX_1: 251 - case TX_CODEC_DMA_TX_0: 252 - case TX_CODEC_DMA_TX_1: 253 - case TX_CODEC_DMA_TX_2: 254 - case TX_CODEC_DMA_TX_3: 255 - for_each_rtd_codec_dais(rtd, i, codec_dai) { 256 - sruntime = snd_soc_dai_get_stream(codec_dai, substream->stream); 257 - if (sruntime != ERR_PTR(-ENOTSUPP)) 258 - *psruntime = sruntime; 259 - } 260 - break; 261 - } 262 - 263 - return 0; 264 - 265 - } 266 - EXPORT_SYMBOL_GPL(qcom_snd_sdw_hw_params); 267 - 268 - int qcom_snd_sdw_hw_free(struct snd_pcm_substream *substream, 269 - struct sdw_stream_runtime *sruntime, bool *stream_prepared) 270 - { 271 - struct snd_soc_pcm_runtime *rtd = substream->private_data; 272 - struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 273 - 274 - switch (cpu_dai->id) { 275 - case WSA_CODEC_DMA_RX_0: 276 - case WSA_CODEC_DMA_RX_1: 277 - case RX_CODEC_DMA_RX_0: 278 - case RX_CODEC_DMA_RX_1: 279 - case TX_CODEC_DMA_TX_0: 280 - case TX_CODEC_DMA_TX_1: 281 - case TX_CODEC_DMA_TX_2: 282 - case TX_CODEC_DMA_TX_3: 283 - if (sruntime && *stream_prepared) { 284 - sdw_disable_stream(sruntime); 285 - sdw_deprepare_stream(sruntime); 286 - *stream_prepared = false; 287 - } 288 - break; 289 - default: 290 - break; 291 - } 292 - 293 - return 0; 294 - } 295 - EXPORT_SYMBOL_GPL(qcom_snd_sdw_hw_free); 296 - 297 183 int qcom_snd_wcd_jack_setup(struct snd_soc_pcm_runtime *rtd, 298 184 struct snd_soc_jack *jack, bool *jack_setup) 299 185 {
-10
sound/soc/qcom/common.h
··· 5 5 #define __QCOM_SND_COMMON_H__ 6 6 7 7 #include <sound/soc.h> 8 - #include <linux/soundwire/sdw.h> 9 8 10 9 int qcom_snd_parse_of(struct snd_soc_card *card); 11 10 int qcom_snd_wcd_jack_setup(struct snd_soc_pcm_runtime *rtd, 12 11 struct snd_soc_jack *jack, bool *jack_setup); 13 12 14 - int qcom_snd_sdw_prepare(struct snd_pcm_substream *substream, 15 - struct sdw_stream_runtime *runtime, 16 - bool *stream_prepared); 17 - int qcom_snd_sdw_hw_params(struct snd_pcm_substream *substream, 18 - struct snd_pcm_hw_params *params, 19 - struct sdw_stream_runtime **psruntime); 20 - int qcom_snd_sdw_hw_free(struct snd_pcm_substream *substream, 21 - struct sdw_stream_runtime *sruntime, 22 - bool *stream_prepared); 23 13 #endif
+3 -2
sound/soc/qcom/lpass-cpu.c
··· 1037 1037 struct lpass_data *data) 1038 1038 { 1039 1039 struct device_node *node; 1040 - int ret, id; 1040 + int ret, i, id; 1041 1041 1042 1042 /* Allow all channels by default for backwards compatibility */ 1043 - for (id = 0; id < data->variant->num_dai; id++) { 1043 + for (i = 0; i < data->variant->num_dai; i++) { 1044 + id = data->variant->dai_driver[i].id; 1044 1045 data->mi2s_playback_sd_mode[id] = LPAIF_I2SCTL_MODE_8CH; 1045 1046 data->mi2s_capture_sd_mode[id] = LPAIF_I2SCTL_MODE_8CH; 1046 1047 }
+1
sound/soc/qcom/sc8280xp.c
··· 12 12 #include <linux/input-event-codes.h> 13 13 #include "qdsp6/q6afe.h" 14 14 #include "common.h" 15 + #include "sdw.h" 15 16 16 17 #define DRIVER_NAME "sc8280xp" 17 18
+123
sound/soc/qcom/sdw.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // Copyright (c) 2018, Linaro Limited. 3 + // Copyright (c) 2018, The Linux Foundation. All rights reserved. 4 + 5 + #include <linux/module.h> 6 + #include <sound/soc.h> 7 + #include "qdsp6/q6afe.h" 8 + #include "sdw.h" 9 + 10 + int qcom_snd_sdw_prepare(struct snd_pcm_substream *substream, 11 + struct sdw_stream_runtime *sruntime, 12 + bool *stream_prepared) 13 + { 14 + struct snd_soc_pcm_runtime *rtd = substream->private_data; 15 + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 16 + int ret; 17 + 18 + if (!sruntime) 19 + return 0; 20 + 21 + switch (cpu_dai->id) { 22 + case WSA_CODEC_DMA_RX_0: 23 + case WSA_CODEC_DMA_RX_1: 24 + case RX_CODEC_DMA_RX_0: 25 + case RX_CODEC_DMA_RX_1: 26 + case TX_CODEC_DMA_TX_0: 27 + case TX_CODEC_DMA_TX_1: 28 + case TX_CODEC_DMA_TX_2: 29 + case TX_CODEC_DMA_TX_3: 30 + break; 31 + default: 32 + return 0; 33 + } 34 + 35 + if (*stream_prepared) { 36 + sdw_disable_stream(sruntime); 37 + sdw_deprepare_stream(sruntime); 38 + *stream_prepared = false; 39 + } 40 + 41 + ret = sdw_prepare_stream(sruntime); 42 + if (ret) 43 + return ret; 44 + 45 + /** 46 + * NOTE: there is a strict hw requirement about the ordering of port 47 + * enables and actual WSA881x PA enable. PA enable should only happen 48 + * after soundwire ports are enabled if not DC on the line is 49 + * accumulated resulting in Click/Pop Noise 50 + * PA enable/mute are handled as part of codec DAPM and digital mute. 51 + */ 52 + 53 + ret = sdw_enable_stream(sruntime); 54 + if (ret) { 55 + sdw_deprepare_stream(sruntime); 56 + return ret; 57 + } 58 + *stream_prepared = true; 59 + 60 + return ret; 61 + } 62 + EXPORT_SYMBOL_GPL(qcom_snd_sdw_prepare); 63 + 64 + int qcom_snd_sdw_hw_params(struct snd_pcm_substream *substream, 65 + struct snd_pcm_hw_params *params, 66 + struct sdw_stream_runtime **psruntime) 67 + { 68 + struct snd_soc_pcm_runtime *rtd = substream->private_data; 69 + struct snd_soc_dai *codec_dai; 70 + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 71 + struct sdw_stream_runtime *sruntime; 72 + int i; 73 + 74 + switch (cpu_dai->id) { 75 + case WSA_CODEC_DMA_RX_0: 76 + case RX_CODEC_DMA_RX_0: 77 + case RX_CODEC_DMA_RX_1: 78 + case TX_CODEC_DMA_TX_0: 79 + case TX_CODEC_DMA_TX_1: 80 + case TX_CODEC_DMA_TX_2: 81 + case TX_CODEC_DMA_TX_3: 82 + for_each_rtd_codec_dais(rtd, i, codec_dai) { 83 + sruntime = snd_soc_dai_get_stream(codec_dai, substream->stream); 84 + if (sruntime != ERR_PTR(-ENOTSUPP)) 85 + *psruntime = sruntime; 86 + } 87 + break; 88 + } 89 + 90 + return 0; 91 + 92 + } 93 + EXPORT_SYMBOL_GPL(qcom_snd_sdw_hw_params); 94 + 95 + int qcom_snd_sdw_hw_free(struct snd_pcm_substream *substream, 96 + struct sdw_stream_runtime *sruntime, bool *stream_prepared) 97 + { 98 + struct snd_soc_pcm_runtime *rtd = substream->private_data; 99 + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 100 + 101 + switch (cpu_dai->id) { 102 + case WSA_CODEC_DMA_RX_0: 103 + case WSA_CODEC_DMA_RX_1: 104 + case RX_CODEC_DMA_RX_0: 105 + case RX_CODEC_DMA_RX_1: 106 + case TX_CODEC_DMA_TX_0: 107 + case TX_CODEC_DMA_TX_1: 108 + case TX_CODEC_DMA_TX_2: 109 + case TX_CODEC_DMA_TX_3: 110 + if (sruntime && *stream_prepared) { 111 + sdw_disable_stream(sruntime); 112 + sdw_deprepare_stream(sruntime); 113 + *stream_prepared = false; 114 + } 115 + break; 116 + default: 117 + break; 118 + } 119 + 120 + return 0; 121 + } 122 + EXPORT_SYMBOL_GPL(qcom_snd_sdw_hw_free); 123 + MODULE_LICENSE("GPL v2");
+18
sound/soc/qcom/sdw.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + // Copyright (c) 2018, The Linux Foundation. All rights reserved. 3 + 4 + #ifndef __QCOM_SND_SDW_H__ 5 + #define __QCOM_SND_SDW_H__ 6 + 7 + #include <linux/soundwire/sdw.h> 8 + 9 + int qcom_snd_sdw_prepare(struct snd_pcm_substream *substream, 10 + struct sdw_stream_runtime *runtime, 11 + bool *stream_prepared); 12 + int qcom_snd_sdw_hw_params(struct snd_pcm_substream *substream, 13 + struct snd_pcm_hw_params *params, 14 + struct sdw_stream_runtime **psruntime); 15 + int qcom_snd_sdw_hw_free(struct snd_pcm_substream *substream, 16 + struct sdw_stream_runtime *sruntime, 17 + bool *stream_prepared); 18 + #endif
+1
sound/soc/qcom/sm8250.c
··· 12 12 #include <linux/input-event-codes.h> 13 13 #include "qdsp6/q6afe.h" 14 14 #include "common.h" 15 + #include "sdw.h" 15 16 16 17 #define DRIVER_NAME "sm8250" 17 18 #define MI2S_BCLK_RATE 1536000
+3 -1
sound/soc/sof/debug.c
··· 353 353 return err; 354 354 } 355 355 356 - return 0; 356 + return snd_sof_debugfs_buf_item(sdev, &sdev->fw_state, 357 + sizeof(sdev->fw_state), 358 + "fw_state", 0444); 357 359 } 358 360 EXPORT_SYMBOL_GPL(snd_sof_dbg_init); 359 361
+4 -5
sound/soc/sof/pm.c
··· 182 182 const struct sof_ipc_pm_ops *pm_ops = sdev->ipc->ops->pm; 183 183 const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg; 184 184 pm_message_t pm_state; 185 - u32 target_state = 0; 185 + u32 target_state = snd_sof_dsp_power_target(sdev); 186 186 int ret; 187 187 188 188 /* do nothing if dsp suspend callback is not set */ ··· 191 191 192 192 if (runtime_suspend && !sof_ops(sdev)->runtime_suspend) 193 193 return 0; 194 + 195 + if (tplg_ops && tplg_ops->tear_down_all_pipelines) 196 + tplg_ops->tear_down_all_pipelines(sdev, false); 194 197 195 198 if (sdev->fw_state != SOF_FW_BOOT_COMPLETE) 196 199 goto suspend; ··· 209 206 } 210 207 } 211 208 212 - target_state = snd_sof_dsp_power_target(sdev); 213 209 pm_state.event = target_state; 214 210 215 211 /* Skip to platform-specific suspend if DSP is entering D0 */ ··· 218 216 sof_suspend_clients(sdev, pm_state); 219 217 goto suspend; 220 218 } 221 - 222 - if (tplg_ops->tear_down_all_pipelines) 223 - tplg_ops->tear_down_all_pipelines(sdev, false); 224 219 225 220 /* suspend DMA trace */ 226 221 sof_fw_trace_suspend(sdev, pm_state);
+2 -1
sound/usb/implicit.c
··· 471 471 subs = find_matching_substream(chip, stream, target->sync_ep, 472 472 target->fmt_type); 473 473 if (!subs) 474 - return sync_fmt; 474 + goto end; 475 475 476 476 high_score = 0; 477 477 list_for_each_entry(fp, &subs->fmt_list, list) { ··· 485 485 } 486 486 } 487 487 488 + end: 488 489 if (fixed_rate) 489 490 *fixed_rate = snd_usb_pcm_has_fixed_rate(subs); 490 491 return sync_fmt;
+138 -84
sound/usb/pcm.c
··· 160 160 bool snd_usb_pcm_has_fixed_rate(struct snd_usb_substream *subs) 161 161 { 162 162 const struct audioformat *fp; 163 - struct snd_usb_audio *chip = subs->stream->chip; 163 + struct snd_usb_audio *chip; 164 164 int rate = -1; 165 165 166 + if (!subs) 167 + return false; 168 + chip = subs->stream->chip; 166 169 if (!(chip->quirk_flags & QUIRK_FLAG_FIXED_RATE)) 167 170 return false; 168 171 list_for_each_entry(fp, &subs->fmt_list, list) { ··· 528 525 if (snd_usb_endpoint_compatible(chip, subs->data_endpoint, 529 526 fmt, hw_params)) 530 527 goto unlock; 528 + if (stop_endpoints(subs, false)) 529 + sync_pending_stops(subs); 531 530 close_endpoints(chip, subs); 532 531 } 533 532 ··· 792 787 return changed; 793 788 } 794 789 790 + /* get the specified endpoint object that is being used by other streams 791 + * (i.e. the parameter is locked) 792 + */ 793 + static const struct snd_usb_endpoint * 794 + get_endpoint_in_use(struct snd_usb_audio *chip, int endpoint, 795 + const struct snd_usb_endpoint *ref_ep) 796 + { 797 + const struct snd_usb_endpoint *ep; 798 + 799 + ep = snd_usb_get_endpoint(chip, endpoint); 800 + if (ep && ep->cur_audiofmt && (ep != ref_ep || ep->opened > 1)) 801 + return ep; 802 + return NULL; 803 + } 804 + 795 805 static int hw_rule_rate(struct snd_pcm_hw_params *params, 796 806 struct snd_pcm_hw_rule *rule) 797 807 { 798 808 struct snd_usb_substream *subs = rule->private; 799 809 struct snd_usb_audio *chip = subs->stream->chip; 810 + const struct snd_usb_endpoint *ep; 800 811 const struct audioformat *fp; 801 812 struct snd_interval *it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); 802 813 unsigned int rmin, rmax, r; ··· 824 803 list_for_each_entry(fp, &subs->fmt_list, list) { 825 804 if (!hw_check_valid_format(subs, params, fp)) 826 805 continue; 806 + 807 + ep = get_endpoint_in_use(chip, fp->endpoint, 808 + subs->data_endpoint); 809 + if (ep) { 810 + hwc_debug("rate limit %d for ep#%x\n", 811 + ep->cur_rate, fp->endpoint); 812 + rmin = min(rmin, ep->cur_rate); 813 + rmax = max(rmax, ep->cur_rate); 814 + continue; 815 + } 816 + 817 + if (fp->implicit_fb) { 818 + ep = get_endpoint_in_use(chip, fp->sync_ep, 819 + subs->sync_endpoint); 820 + if (ep) { 821 + hwc_debug("rate limit %d for sync_ep#%x\n", 822 + ep->cur_rate, fp->sync_ep); 823 + rmin = min(rmin, ep->cur_rate); 824 + rmax = max(rmax, ep->cur_rate); 825 + continue; 826 + } 827 + } 828 + 827 829 r = snd_usb_endpoint_get_clock_rate(chip, fp->clock); 828 830 if (r > 0) { 829 831 if (!snd_interval_test(it, r)) ··· 916 872 struct snd_pcm_hw_rule *rule) 917 873 { 918 874 struct snd_usb_substream *subs = rule->private; 875 + struct snd_usb_audio *chip = subs->stream->chip; 876 + const struct snd_usb_endpoint *ep; 919 877 const struct audioformat *fp; 920 878 struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); 921 879 u64 fbits; ··· 927 881 list_for_each_entry(fp, &subs->fmt_list, list) { 928 882 if (!hw_check_valid_format(subs, params, fp)) 929 883 continue; 884 + 885 + ep = get_endpoint_in_use(chip, fp->endpoint, 886 + subs->data_endpoint); 887 + if (ep) { 888 + hwc_debug("format limit %d for ep#%x\n", 889 + ep->cur_format, fp->endpoint); 890 + fbits |= pcm_format_to_bits(ep->cur_format); 891 + continue; 892 + } 893 + 894 + if (fp->implicit_fb) { 895 + ep = get_endpoint_in_use(chip, fp->sync_ep, 896 + subs->sync_endpoint); 897 + if (ep) { 898 + hwc_debug("format limit %d for sync_ep#%x\n", 899 + ep->cur_format, fp->sync_ep); 900 + fbits |= pcm_format_to_bits(ep->cur_format); 901 + continue; 902 + } 903 + } 904 + 930 905 fbits |= fp->formats; 931 906 } 932 907 return apply_hw_params_format_bits(fmt, fbits); ··· 980 913 return apply_hw_params_minmax(it, pmin, UINT_MAX); 981 914 } 982 915 983 - /* get the EP or the sync EP for implicit fb when it's already set up */ 984 - static const struct snd_usb_endpoint * 985 - get_sync_ep_from_substream(struct snd_usb_substream *subs) 986 - { 987 - struct snd_usb_audio *chip = subs->stream->chip; 988 - const struct audioformat *fp; 989 - const struct snd_usb_endpoint *ep; 990 - 991 - list_for_each_entry(fp, &subs->fmt_list, list) { 992 - ep = snd_usb_get_endpoint(chip, fp->endpoint); 993 - if (ep && ep->cur_audiofmt) { 994 - /* if EP is already opened solely for this substream, 995 - * we still allow us to change the parameter; otherwise 996 - * this substream has to follow the existing parameter 997 - */ 998 - if (ep->cur_audiofmt != subs->cur_audiofmt || ep->opened > 1) 999 - return ep; 1000 - } 1001 - if (!fp->implicit_fb) 1002 - continue; 1003 - /* for the implicit fb, check the sync ep as well */ 1004 - ep = snd_usb_get_endpoint(chip, fp->sync_ep); 1005 - if (ep && ep->cur_audiofmt) 1006 - return ep; 1007 - } 1008 - return NULL; 1009 - } 1010 - 1011 916 /* additional hw constraints for implicit feedback mode */ 1012 - static int hw_rule_format_implicit_fb(struct snd_pcm_hw_params *params, 1013 - struct snd_pcm_hw_rule *rule) 1014 - { 1015 - struct snd_usb_substream *subs = rule->private; 1016 - const struct snd_usb_endpoint *ep; 1017 - struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); 1018 - 1019 - ep = get_sync_ep_from_substream(subs); 1020 - if (!ep) 1021 - return 0; 1022 - 1023 - hwc_debug("applying %s\n", __func__); 1024 - return apply_hw_params_format_bits(fmt, pcm_format_to_bits(ep->cur_format)); 1025 - } 1026 - 1027 - static int hw_rule_rate_implicit_fb(struct snd_pcm_hw_params *params, 1028 - struct snd_pcm_hw_rule *rule) 1029 - { 1030 - struct snd_usb_substream *subs = rule->private; 1031 - const struct snd_usb_endpoint *ep; 1032 - struct snd_interval *it; 1033 - 1034 - ep = get_sync_ep_from_substream(subs); 1035 - if (!ep) 1036 - return 0; 1037 - 1038 - hwc_debug("applying %s\n", __func__); 1039 - it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); 1040 - return apply_hw_params_minmax(it, ep->cur_rate, ep->cur_rate); 1041 - } 1042 - 1043 917 static int hw_rule_period_size_implicit_fb(struct snd_pcm_hw_params *params, 1044 918 struct snd_pcm_hw_rule *rule) 1045 919 { 1046 920 struct snd_usb_substream *subs = rule->private; 921 + struct snd_usb_audio *chip = subs->stream->chip; 922 + const struct audioformat *fp; 1047 923 const struct snd_usb_endpoint *ep; 1048 924 struct snd_interval *it; 925 + unsigned int rmin, rmax; 1049 926 1050 - ep = get_sync_ep_from_substream(subs); 1051 - if (!ep) 1052 - return 0; 1053 - 1054 - hwc_debug("applying %s\n", __func__); 1055 927 it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE); 1056 - return apply_hw_params_minmax(it, ep->cur_period_frames, 1057 - ep->cur_period_frames); 928 + hwc_debug("hw_rule_period_size: (%u,%u)\n", it->min, it->max); 929 + rmin = UINT_MAX; 930 + rmax = 0; 931 + list_for_each_entry(fp, &subs->fmt_list, list) { 932 + if (!hw_check_valid_format(subs, params, fp)) 933 + continue; 934 + ep = get_endpoint_in_use(chip, fp->endpoint, 935 + subs->data_endpoint); 936 + if (ep) { 937 + hwc_debug("period size limit %d for ep#%x\n", 938 + ep->cur_period_frames, fp->endpoint); 939 + rmin = min(rmin, ep->cur_period_frames); 940 + rmax = max(rmax, ep->cur_period_frames); 941 + continue; 942 + } 943 + 944 + if (fp->implicit_fb) { 945 + ep = get_endpoint_in_use(chip, fp->sync_ep, 946 + subs->sync_endpoint); 947 + if (ep) { 948 + hwc_debug("period size limit %d for sync_ep#%x\n", 949 + ep->cur_period_frames, fp->sync_ep); 950 + rmin = min(rmin, ep->cur_period_frames); 951 + rmax = max(rmax, ep->cur_period_frames); 952 + continue; 953 + } 954 + } 955 + } 956 + 957 + if (!rmax) 958 + return 0; /* no limit by implicit fb */ 959 + return apply_hw_params_minmax(it, rmin, rmax); 1058 960 } 1059 961 1060 962 static int hw_rule_periods_implicit_fb(struct snd_pcm_hw_params *params, 1061 963 struct snd_pcm_hw_rule *rule) 1062 964 { 1063 965 struct snd_usb_substream *subs = rule->private; 966 + struct snd_usb_audio *chip = subs->stream->chip; 967 + const struct audioformat *fp; 1064 968 const struct snd_usb_endpoint *ep; 1065 969 struct snd_interval *it; 970 + unsigned int rmin, rmax; 1066 971 1067 - ep = get_sync_ep_from_substream(subs); 1068 - if (!ep) 1069 - return 0; 1070 - 1071 - hwc_debug("applying %s\n", __func__); 1072 972 it = hw_param_interval(params, SNDRV_PCM_HW_PARAM_PERIODS); 1073 - return apply_hw_params_minmax(it, ep->cur_buffer_periods, 1074 - ep->cur_buffer_periods); 973 + hwc_debug("hw_rule_periods: (%u,%u)\n", it->min, it->max); 974 + rmin = UINT_MAX; 975 + rmax = 0; 976 + list_for_each_entry(fp, &subs->fmt_list, list) { 977 + if (!hw_check_valid_format(subs, params, fp)) 978 + continue; 979 + ep = get_endpoint_in_use(chip, fp->endpoint, 980 + subs->data_endpoint); 981 + if (ep) { 982 + hwc_debug("periods limit %d for ep#%x\n", 983 + ep->cur_buffer_periods, fp->endpoint); 984 + rmin = min(rmin, ep->cur_buffer_periods); 985 + rmax = max(rmax, ep->cur_buffer_periods); 986 + continue; 987 + } 988 + 989 + if (fp->implicit_fb) { 990 + ep = get_endpoint_in_use(chip, fp->sync_ep, 991 + subs->sync_endpoint); 992 + if (ep) { 993 + hwc_debug("periods limit %d for sync_ep#%x\n", 994 + ep->cur_buffer_periods, fp->sync_ep); 995 + rmin = min(rmin, ep->cur_buffer_periods); 996 + rmax = max(rmax, ep->cur_buffer_periods); 997 + continue; 998 + } 999 + } 1000 + } 1001 + 1002 + if (!rmax) 1003 + return 0; /* no limit by implicit fb */ 1004 + return apply_hw_params_minmax(it, rmin, rmax); 1075 1005 } 1076 1006 1077 1007 /* ··· 1177 1113 return err; 1178 1114 1179 1115 /* additional hw constraints for implicit fb */ 1180 - err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT, 1181 - hw_rule_format_implicit_fb, subs, 1182 - SNDRV_PCM_HW_PARAM_FORMAT, -1); 1183 - if (err < 0) 1184 - return err; 1185 - err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, 1186 - hw_rule_rate_implicit_fb, subs, 1187 - SNDRV_PCM_HW_PARAM_RATE, -1); 1188 - if (err < 0) 1189 - return err; 1190 1116 err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 1191 1117 hw_rule_period_size_implicit_fb, subs, 1192 1118 SNDRV_PCM_HW_PARAM_PERIOD_SIZE, -1);
+2
sound/usb/quirks.c
··· 2152 2152 QUIRK_FLAG_GENERIC_IMPLICIT_FB), 2153 2153 DEVICE_FLG(0x0525, 0xa4ad, /* Hamedal C20 usb camero */ 2154 2154 QUIRK_FLAG_IFACE_SKIP_CLOSE), 2155 + DEVICE_FLG(0x0ecb, 0x205c, /* JBL Quantum610 Wireless */ 2156 + QUIRK_FLAG_FIXED_RATE), 2155 2157 DEVICE_FLG(0x0ecb, 0x2069, /* JBL Quantum810 Wireless */ 2156 2158 QUIRK_FLAG_FIXED_RATE), 2157 2159
+6
sound/usb/stream.c
··· 1222 1222 if (err < 0) 1223 1223 return err; 1224 1224 } 1225 + 1226 + /* try to set the interface... */ 1227 + usb_set_interface(chip->dev, iface_no, 0); 1228 + snd_usb_init_pitch(chip, fp); 1229 + snd_usb_init_sample_rate(chip, fp, fp->rate_max); 1230 + usb_set_interface(chip->dev, iface_no, altno); 1225 1231 } 1226 1232 return 0; 1227 1233 }