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

ASoC: sigmadsp: Restructure in preparation for fw v2 support

The v2 file format of the SigmaDSP takes a more declarative style compared
to the imperative style of the v1 format. In addition some features that are
supported with v2 require the driver to keep state around for the firmware.
This requires a bit of restructuring of both the firmware loader itself and
the drivers making use of the firmware loader.

Instead of loading and executing the firmware in place when the DSP is
configured the firmware is now loaded at driver probe time. This is required
since the new firmware format will in addition to the firmware data itself
contain meta information describing the firmware and its requirements and
capabilities. Those will for example be used to restrict the supported
samplerates advertised by the driver to userspace to the list of samplerates
supported for the firmware.

This only does the restructuring required by the v2 format, but does not
yet add support for the new format itself.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Lars-Peter Clausen and committed by
Mark Brown
d48b088e 6b25730f

+426 -123
+28 -5
sound/soc/codecs/adau1701.c
··· 103 103 unsigned int sysclk; 104 104 struct regmap *regmap; 105 105 u8 pin_config[12]; 106 + 107 + struct sigmadsp *sigmadsp; 106 108 }; 107 109 108 110 static const struct snd_kcontrol_new adau1701_controls[] = { ··· 240 238 return 0; 241 239 } 242 240 243 - static int adau1701_reset(struct snd_soc_codec *codec, unsigned int clkdiv) 241 + static int adau1701_reset(struct snd_soc_codec *codec, unsigned int clkdiv, 242 + unsigned int rate) 244 243 { 245 244 struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec); 246 - struct i2c_client *client = to_i2c_client(codec->dev); 247 245 int ret; 246 + 247 + sigmadsp_reset(adau1701->sigmadsp); 248 248 249 249 if (clkdiv != ADAU1707_CLKDIV_UNSET && 250 250 gpio_is_valid(adau1701->gpio_pll_mode[0]) && ··· 288 284 * know the correct PLL setup 289 285 */ 290 286 if (clkdiv != ADAU1707_CLKDIV_UNSET) { 291 - ret = process_sigma_firmware(client, ADAU1701_FIRMWARE); 287 + ret = sigmadsp_setup(adau1701->sigmadsp, rate); 292 288 if (ret) { 293 289 dev_warn(codec->dev, "Failed to load firmware\n"); 294 290 return ret; ··· 389 385 * firmware upload. 390 386 */ 391 387 if (clkdiv != adau1701->pll_clkdiv) { 392 - ret = adau1701_reset(codec, clkdiv); 388 + ret = adau1701_reset(codec, clkdiv, params_rate(params)); 393 389 if (ret < 0) 394 390 return ret; 395 391 } ··· 558 554 return 0; 559 555 } 560 556 557 + static int adau1701_startup(struct snd_pcm_substream *substream, 558 + struct snd_soc_dai *dai) 559 + { 560 + struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(dai->codec); 561 + 562 + return sigmadsp_restrict_params(adau1701->sigmadsp, substream); 563 + } 564 + 561 565 #define ADAU1701_RATES (SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | \ 562 566 SNDRV_PCM_RATE_192000) 563 567 ··· 576 564 .set_fmt = adau1701_set_dai_fmt, 577 565 .hw_params = adau1701_hw_params, 578 566 .digital_mute = adau1701_digital_mute, 567 + .startup = adau1701_startup, 579 568 }; 580 569 581 570 static struct snd_soc_dai_driver adau1701_dai = { ··· 613 600 unsigned int val; 614 601 struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec); 615 602 603 + ret = sigmadsp_attach(adau1701->sigmadsp, &codec->component); 604 + if (ret) 605 + return ret; 606 + 616 607 /* 617 608 * Let the pll_clkdiv variable default to something that won't happen 618 609 * at runtime. That way, we can postpone the firmware download from ··· 626 609 adau1701->pll_clkdiv = ADAU1707_CLKDIV_UNSET; 627 610 628 611 /* initalize with pre-configured pll mode settings */ 629 - ret = adau1701_reset(codec, adau1701->pll_clkdiv); 612 + ret = adau1701_reset(codec, adau1701->pll_clkdiv, 0); 630 613 if (ret < 0) 631 614 return ret; 632 615 ··· 739 722 adau1701->gpio_pll_mode[1] = gpio_pll_mode[1]; 740 723 741 724 i2c_set_clientdata(client, adau1701); 725 + 726 + adau1701->sigmadsp = devm_sigmadsp_init_i2c(client, NULL, 727 + ADAU1701_FIRMWARE); 728 + if (IS_ERR(adau1701->sigmadsp)) 729 + return PTR_ERR(adau1701->sigmadsp); 730 + 742 731 ret = snd_soc_register_codec(&client->dev, &adau1701_codec_drv, 743 732 &adau1701_dai, 1); 744 733 return ret;
+10 -11
sound/soc/codecs/adau1761.c
··· 698 698 ARRAY_SIZE(adau1761_dapm_routes)); 699 699 if (ret) 700 700 return ret; 701 - 702 - ret = adau17x1_load_firmware(adau, codec->dev, 703 - ADAU1761_FIRMWARE); 704 - if (ret) 705 - dev_warn(codec->dev, "Failed to firmware\n"); 706 701 } 707 702 708 703 ret = adau17x1_add_routes(codec); ··· 766 771 enum adau17x1_type type, void (*switch_mode)(struct device *dev)) 767 772 { 768 773 struct snd_soc_dai_driver *dai_drv; 774 + const char *firmware_name; 769 775 int ret; 770 776 771 - ret = adau17x1_probe(dev, regmap, type, switch_mode); 777 + if (type == ADAU1361) { 778 + dai_drv = &adau1361_dai_driver; 779 + firmware_name = NULL; 780 + } else { 781 + dai_drv = &adau1761_dai_driver; 782 + firmware_name = ADAU1761_FIRMWARE; 783 + } 784 + 785 + ret = adau17x1_probe(dev, regmap, type, switch_mode, firmware_name); 772 786 if (ret) 773 787 return ret; 774 - 775 - if (type == ADAU1361) 776 - dai_drv = &adau1361_dai_driver; 777 - else 778 - dai_drv = &adau1761_dai_driver; 779 788 780 789 return snd_soc_register_codec(dev, &adau1761_codec_driver, dai_drv, 1); 781 790 }
+13 -17
sound/soc/codecs/adau1781.c
··· 385 385 { 386 386 struct adau1781_platform_data *pdata = dev_get_platdata(codec->dev); 387 387 struct adau *adau = snd_soc_codec_get_drvdata(codec); 388 - const char *firmware; 389 388 int ret; 390 389 391 390 ret = adau17x1_add_widgets(codec); ··· 421 422 return ret; 422 423 } 423 424 424 - switch (adau->type) { 425 - case ADAU1381: 426 - firmware = ADAU1381_FIRMWARE; 427 - break; 428 - case ADAU1781: 429 - firmware = ADAU1781_FIRMWARE; 430 - break; 431 - default: 432 - return -EINVAL; 433 - } 434 - 435 425 ret = adau17x1_add_routes(codec); 436 426 if (ret < 0) 437 427 return ret; 438 - 439 - ret = adau17x1_load_firmware(adau, codec->dev, firmware); 440 - if (ret) 441 - dev_warn(codec->dev, "Failed to load firmware\n"); 442 428 443 429 return 0; 444 430 } ··· 479 495 int adau1781_probe(struct device *dev, struct regmap *regmap, 480 496 enum adau17x1_type type, void (*switch_mode)(struct device *dev)) 481 497 { 498 + const char *firmware_name; 482 499 int ret; 483 500 484 - ret = adau17x1_probe(dev, regmap, type, switch_mode); 501 + switch (type) { 502 + case ADAU1381: 503 + firmware_name = ADAU1381_FIRMWARE; 504 + break; 505 + case ADAU1781: 506 + firmware_name = ADAU1781_FIRMWARE; 507 + break; 508 + default: 509 + return -EINVAL; 510 + } 511 + 512 + ret = adau17x1_probe(dev, regmap, type, switch_mode, firmware_name); 485 513 if (ret) 486 514 return ret; 487 515
+48 -6
sound/soc/codecs/adau17x1.c
··· 307 307 struct adau *adau = snd_soc_codec_get_drvdata(codec); 308 308 unsigned int val, div, dsp_div; 309 309 unsigned int freq; 310 + int ret; 310 311 311 312 if (adau->clk_src == ADAU17X1_CLK_SRC_PLL) 312 313 freq = adau->pll_freq; ··· 355 354 if (adau17x1_has_dsp(adau)) { 356 355 regmap_write(adau->regmap, ADAU17X1_SERIAL_SAMPLING_RATE, div); 357 356 regmap_write(adau->regmap, ADAU17X1_DSP_SAMPLING_RATE, dsp_div); 357 + } 358 + 359 + if (adau->sigmadsp) { 360 + ret = adau17x1_setup_firmware(adau, params_rate(params)); 361 + if (ret < 0) 362 + return ret; 358 363 } 359 364 360 365 if (adau->dai_fmt != SND_SOC_DAIFMT_RIGHT_J) ··· 668 661 return 0; 669 662 } 670 663 664 + static int adau17x1_startup(struct snd_pcm_substream *substream, 665 + struct snd_soc_dai *dai) 666 + { 667 + struct adau *adau = snd_soc_codec_get_drvdata(dai->codec); 668 + 669 + if (adau->sigmadsp) 670 + return sigmadsp_restrict_params(adau->sigmadsp, substream); 671 + 672 + return 0; 673 + } 674 + 671 675 const struct snd_soc_dai_ops adau17x1_dai_ops = { 672 676 .hw_params = adau17x1_hw_params, 673 677 .set_sysclk = adau17x1_set_dai_sysclk, 674 678 .set_fmt = adau17x1_set_dai_fmt, 675 679 .set_pll = adau17x1_set_dai_pll, 676 680 .set_tdm_slot = adau17x1_set_dai_tdm_slot, 681 + .startup = adau17x1_startup, 677 682 }; 678 683 EXPORT_SYMBOL_GPL(adau17x1_dai_ops); 679 684 ··· 764 745 } 765 746 EXPORT_SYMBOL_GPL(adau17x1_volatile_register); 766 747 767 - int adau17x1_load_firmware(struct adau *adau, struct device *dev, 768 - const char *firmware) 748 + int adau17x1_setup_firmware(struct adau *adau, unsigned int rate) 769 749 { 770 750 int ret; 771 751 int dspsr; ··· 776 758 regmap_write(adau->regmap, ADAU17X1_DSP_ENABLE, 1); 777 759 regmap_write(adau->regmap, ADAU17X1_DSP_SAMPLING_RATE, 0xf); 778 760 779 - ret = process_sigma_firmware_regmap(dev, adau->regmap, firmware); 761 + ret = sigmadsp_setup(adau->sigmadsp, rate); 780 762 if (ret) { 781 763 regmap_write(adau->regmap, ADAU17X1_DSP_ENABLE, 0); 782 764 return ret; ··· 785 767 786 768 return 0; 787 769 } 788 - EXPORT_SYMBOL_GPL(adau17x1_load_firmware); 770 + EXPORT_SYMBOL_GPL(adau17x1_setup_firmware); 789 771 790 772 int adau17x1_add_widgets(struct snd_soc_codec *codec) 791 773 { ··· 805 787 ret = snd_soc_dapm_new_controls(&codec->dapm, 806 788 adau17x1_dsp_dapm_widgets, 807 789 ARRAY_SIZE(adau17x1_dsp_dapm_widgets)); 790 + if (ret) 791 + return ret; 792 + 793 + if (!adau->sigmadsp) 794 + return 0; 795 + 796 + ret = sigmadsp_attach(adau->sigmadsp, &codec->component); 797 + if (ret) { 798 + dev_err(codec->dev, "Failed to attach firmware: %d\n", 799 + ret); 800 + return ret; 801 + } 808 802 } 809 - return ret; 803 + 804 + return 0; 810 805 } 811 806 EXPORT_SYMBOL_GPL(adau17x1_add_widgets); 812 807 ··· 860 829 EXPORT_SYMBOL_GPL(adau17x1_resume); 861 830 862 831 int adau17x1_probe(struct device *dev, struct regmap *regmap, 863 - enum adau17x1_type type, void (*switch_mode)(struct device *dev)) 832 + enum adau17x1_type type, void (*switch_mode)(struct device *dev), 833 + const char *firmware_name) 864 834 { 865 835 struct adau *adau; 866 836 ··· 877 845 adau->type = type; 878 846 879 847 dev_set_drvdata(dev, adau); 848 + 849 + if (firmware_name) { 850 + adau->sigmadsp = devm_sigmadsp_init_regmap(dev, regmap, NULL, 851 + firmware_name); 852 + if (IS_ERR(adau->sigmadsp)) { 853 + dev_warn(dev, "Could not find firmware file: %ld\n", 854 + PTR_ERR(adau->sigmadsp)); 855 + adau->sigmadsp = NULL; 856 + } 857 + } 880 858 881 859 if (switch_mode) 882 860 switch_mode(dev);
+6 -3
sound/soc/codecs/adau17x1.h
··· 4 4 #include <linux/regmap.h> 5 5 #include <linux/platform_data/adau17x1.h> 6 6 7 + #include "sigmadsp.h" 8 + 7 9 enum adau17x1_type { 8 10 ADAU1361, 9 11 ADAU1761, ··· 44 42 bool dsp_bypass[2]; 45 43 46 44 struct regmap *regmap; 45 + struct sigmadsp *sigmadsp; 47 46 }; 48 47 49 48 int adau17x1_add_widgets(struct snd_soc_codec *codec); 50 49 int adau17x1_add_routes(struct snd_soc_codec *codec); 51 50 int adau17x1_probe(struct device *dev, struct regmap *regmap, 52 - enum adau17x1_type type, void (*switch_mode)(struct device *dev)); 51 + enum adau17x1_type type, void (*switch_mode)(struct device *dev), 52 + const char *firmware_name); 53 53 int adau17x1_set_micbias_voltage(struct snd_soc_codec *codec, 54 54 enum adau17x1_micbias_voltage micbias); 55 55 bool adau17x1_readable_register(struct device *dev, unsigned int reg); ··· 60 56 61 57 extern const struct snd_soc_dai_ops adau17x1_dai_ops; 62 58 63 - int adau17x1_load_firmware(struct adau *adau, struct device *dev, 64 - const char *firmware); 59 + int adau17x1_setup_firmware(struct adau *adau, unsigned int rate); 65 60 bool adau17x1_has_dsp(struct adau *adau); 66 61 67 62 #define ADAU17X1_CLOCK_CONTROL 0x4000
+41 -11
sound/soc/codecs/sigmadsp-i2c.c
··· 6 6 * Licensed under the GPL-2 or later. 7 7 */ 8 8 9 - #include <linux/i2c.h> 10 9 #include <linux/export.h> 10 + #include <linux/i2c.h> 11 11 #include <linux/module.h> 12 + #include <linux/slab.h> 13 + #include <asm/unaligned.h> 12 14 13 15 #include "sigmadsp.h" 14 16 15 - static int sigma_action_write_i2c(void *control_data, 16 - const struct sigma_action *sa, size_t len) 17 + static int sigmadsp_write_i2c(void *control_data, 18 + unsigned int addr, const uint8_t data[], size_t len) 17 19 { 18 - return i2c_master_send(control_data, (const unsigned char *)&sa->addr, 19 - len); 20 + uint8_t *buf; 21 + int ret; 22 + 23 + buf = kzalloc(2 + len, GFP_KERNEL | GFP_DMA); 24 + if (!buf) 25 + return -ENOMEM; 26 + 27 + put_unaligned_be16(addr, buf); 28 + memcpy(buf + 2, data, len); 29 + 30 + ret = i2c_master_send(control_data, buf, len + 2); 31 + 32 + kfree(buf); 33 + 34 + return ret; 20 35 } 21 36 22 - int process_sigma_firmware(struct i2c_client *client, const char *name) 37 + /** 38 + * devm_sigmadsp_init_i2c() - Initialize SigmaDSP instance 39 + * @client: The parent I2C device 40 + * @ops: The sigmadsp_ops to use for this instance 41 + * @firmware_name: Name of the firmware file to load 42 + * 43 + * Allocates a SigmaDSP instance and loads the specified firmware file. 44 + * 45 + * Returns a pointer to a struct sigmadsp on success, or a PTR_ERR() on error. 46 + */ 47 + struct sigmadsp *devm_sigmadsp_init_i2c(struct i2c_client *client, 48 + const struct sigmadsp_ops *ops, const char *firmware_name) 23 49 { 24 - struct sigma_firmware ssfw; 50 + struct sigmadsp *sigmadsp; 25 51 26 - ssfw.control_data = client; 27 - ssfw.write = sigma_action_write_i2c; 52 + sigmadsp = devm_sigmadsp_init(&client->dev, ops, firmware_name); 53 + if (IS_ERR(sigmadsp)) 54 + return sigmadsp; 28 55 29 - return _process_sigma_firmware(&client->dev, &ssfw, name); 56 + sigmadsp->control_data = client; 57 + sigmadsp->write = sigmadsp_write_i2c; 58 + 59 + return sigmadsp; 30 60 } 31 - EXPORT_SYMBOL(process_sigma_firmware); 61 + EXPORT_SYMBOL_GPL(devm_sigmadsp_init_i2c); 32 62 33 63 MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); 34 64 MODULE_DESCRIPTION("SigmaDSP I2C firmware loader");
+27 -11
sound/soc/codecs/sigmadsp-regmap.c
··· 12 12 13 13 #include "sigmadsp.h" 14 14 15 - static int sigma_action_write_regmap(void *control_data, 16 - const struct sigma_action *sa, size_t len) 15 + static int sigmadsp_write_regmap(void *control_data, 16 + unsigned int addr, const uint8_t data[], size_t len) 17 17 { 18 - return regmap_raw_write(control_data, be16_to_cpu(sa->addr), 19 - sa->payload, len - 2); 18 + return regmap_raw_write(control_data, addr, 19 + data, len); 20 20 } 21 21 22 - int process_sigma_firmware_regmap(struct device *dev, struct regmap *regmap, 23 - const char *name) 22 + /** 23 + * devm_sigmadsp_init_i2c() - Initialize SigmaDSP instance 24 + * @dev: The parent device 25 + * @regmap: Regmap instance to use 26 + * @ops: The sigmadsp_ops to use for this instance 27 + * @firmware_name: Name of the firmware file to load 28 + * 29 + * Allocates a SigmaDSP instance and loads the specified firmware file. 30 + * 31 + * Returns a pointer to a struct sigmadsp on success, or a PTR_ERR() on error. 32 + */ 33 + struct sigmadsp *devm_sigmadsp_init_regmap(struct device *dev, 34 + struct regmap *regmap, const struct sigmadsp_ops *ops, 35 + const char *firmware_name) 24 36 { 25 - struct sigma_firmware ssfw; 37 + struct sigmadsp *sigmadsp; 26 38 27 - ssfw.control_data = regmap; 28 - ssfw.write = sigma_action_write_regmap; 39 + sigmadsp = devm_sigmadsp_init(dev, ops, firmware_name); 40 + if (IS_ERR(sigmadsp)) 41 + return sigmadsp; 29 42 30 - return _process_sigma_firmware(dev, &ssfw, name); 43 + sigmadsp->control_data = regmap; 44 + sigmadsp->write = sigmadsp_write_regmap; 45 + 46 + return sigmadsp; 31 47 } 32 - EXPORT_SYMBOL(process_sigma_firmware_regmap); 48 + EXPORT_SYMBOL_GPL(devm_sigmadsp_init_regmap); 33 49 34 50 MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); 35 51 MODULE_DESCRIPTION("SigmaDSP regmap firmware loader");
+216 -41
sound/soc/codecs/sigmadsp.c
··· 1 1 /* 2 2 * Load Analog Devices SigmaStudio firmware files 3 3 * 4 - * Copyright 2009-2011 Analog Devices Inc. 4 + * Copyright 2009-2014 Analog Devices Inc. 5 5 * 6 6 * Licensed under the GPL-2 or later. 7 7 */ ··· 12 12 #include <linux/i2c.h> 13 13 #include <linux/regmap.h> 14 14 #include <linux/module.h> 15 + #include <linux/slab.h> 16 + 17 + #include <sound/soc.h> 15 18 16 19 #include "sigmadsp.h" 17 20 18 21 #define SIGMA_MAGIC "ADISIGM" 22 + 23 + struct sigmadsp_data { 24 + struct list_head head; 25 + unsigned int addr; 26 + unsigned int length; 27 + uint8_t data[]; 28 + }; 19 29 20 30 struct sigma_firmware_header { 21 31 unsigned char magic[7]; ··· 39 29 SIGMA_ACTION_WRITESAFELOAD, 40 30 SIGMA_ACTION_END, 41 31 }; 32 + 33 + struct sigma_action { 34 + u8 instr; 35 + u8 len_hi; 36 + __le16 len; 37 + __be16 addr; 38 + unsigned char payload[]; 39 + } __packed; 40 + 41 + static int sigmadsp_write(struct sigmadsp *sigmadsp, unsigned int addr, 42 + const uint8_t data[], size_t len) 43 + { 44 + return sigmadsp->write(sigmadsp->control_data, addr, data, len); 45 + } 42 46 43 47 static inline u32 sigma_action_len(struct sigma_action *sa) 44 48 { ··· 82 58 * Returns a negative error value in case of an error, 0 if processing of 83 59 * the firmware should be stopped after this action, 1 otherwise. 84 60 */ 85 - static int 86 - process_sigma_action(struct sigma_firmware *ssfw, struct sigma_action *sa) 61 + static int process_sigma_action(struct sigmadsp *sigmadsp, 62 + struct sigma_action *sa) 87 63 { 88 64 size_t len = sigma_action_len(sa); 89 - int ret; 65 + struct sigmadsp_data *data; 90 66 91 67 pr_debug("%s: instr:%i addr:%#x len:%zu\n", __func__, 92 68 sa->instr, sa->addr, len); ··· 95 71 case SIGMA_ACTION_WRITEXBYTES: 96 72 case SIGMA_ACTION_WRITESINGLE: 97 73 case SIGMA_ACTION_WRITESAFELOAD: 98 - ret = ssfw->write(ssfw->control_data, sa, len); 99 - if (ret < 0) 74 + if (len < 3) 100 75 return -EINVAL; 76 + 77 + data = kzalloc(sizeof(*data) + len - 2, GFP_KERNEL); 78 + if (!data) 79 + return -ENOMEM; 80 + 81 + data->addr = be16_to_cpu(sa->addr); 82 + data->length = len - 2; 83 + memcpy(data->data, sa->payload, data->length); 84 + list_add_tail(&data->head, &sigmadsp->data_list); 101 85 break; 102 86 case SIGMA_ACTION_END: 103 87 return 0; ··· 116 84 return 1; 117 85 } 118 86 119 - static int 120 - process_sigma_actions(struct sigma_firmware *ssfw) 87 + static int sigmadsp_fw_load_v1(struct sigmadsp *sigmadsp, 88 + const struct firmware *fw) 121 89 { 122 90 struct sigma_action *sa; 123 - size_t size; 91 + size_t size, pos; 124 92 int ret; 125 93 126 - while (ssfw->pos + sizeof(*sa) <= ssfw->fw->size) { 127 - sa = (struct sigma_action *)(ssfw->fw->data + ssfw->pos); 94 + pos = sizeof(struct sigma_firmware_header); 95 + 96 + while (pos + sizeof(*sa) <= fw->size) { 97 + sa = (struct sigma_action *)(fw->data + pos); 128 98 129 99 size = sigma_action_size(sa); 130 - ssfw->pos += size; 131 - if (ssfw->pos > ssfw->fw->size || size == 0) 100 + pos += size; 101 + if (pos > fw->size || size == 0) 132 102 break; 133 103 134 - ret = process_sigma_action(ssfw, sa); 104 + ret = process_sigma_action(sigmadsp, sa); 135 105 136 106 pr_debug("%s: action returned %i\n", __func__, ret); 137 107 ··· 141 107 return ret; 142 108 } 143 109 144 - if (ssfw->pos != ssfw->fw->size) 110 + if (pos != fw->size) 145 111 return -EINVAL; 146 112 147 113 return 0; 148 114 } 149 115 150 - int _process_sigma_firmware(struct device *dev, 151 - struct sigma_firmware *ssfw, const char *name) 116 + static void sigmadsp_firmware_release(struct sigmadsp *sigmadsp) 152 117 { 153 - int ret; 154 - struct sigma_firmware_header *ssfw_head; 118 + struct sigmadsp_data *data, *_data; 119 + 120 + list_for_each_entry_safe(data, _data, &sigmadsp->data_list, head) 121 + kfree(data); 122 + 123 + INIT_LIST_HEAD(&sigmadsp->data_list); 124 + } 125 + 126 + static void devm_sigmadsp_release(struct device *dev, void *res) 127 + { 128 + sigmadsp_firmware_release((struct sigmadsp *)res); 129 + } 130 + 131 + static int sigmadsp_firmware_load(struct sigmadsp *sigmadsp, const char *name) 132 + { 133 + const struct sigma_firmware_header *ssfw_head; 155 134 const struct firmware *fw; 135 + int ret; 156 136 u32 crc; 157 137 158 - pr_debug("%s: loading firmware %s\n", __func__, name); 159 - 160 138 /* first load the blob */ 161 - ret = request_firmware(&fw, name, dev); 139 + ret = request_firmware(&fw, name, sigmadsp->dev); 162 140 if (ret) { 163 141 pr_debug("%s: request_firmware() failed with %i\n", __func__, ret); 164 - return ret; 142 + goto done; 165 143 } 166 - ssfw->fw = fw; 167 144 168 145 /* then verify the header */ 169 146 ret = -EINVAL; ··· 186 141 * overflows later in the loading process. 187 142 */ 188 143 if (fw->size < sizeof(*ssfw_head) || fw->size >= 0x4000000) { 189 - dev_err(dev, "Failed to load firmware: Invalid size\n"); 144 + dev_err(sigmadsp->dev, "Failed to load firmware: Invalid size\n"); 190 145 goto done; 191 146 } 192 147 193 148 ssfw_head = (void *)fw->data; 194 149 if (memcmp(ssfw_head->magic, SIGMA_MAGIC, ARRAY_SIZE(ssfw_head->magic))) { 195 - dev_err(dev, "Failed to load firmware: Invalid magic\n"); 196 - goto done; 197 - } 198 - 199 - if (ssfw_head->version != 1) { 200 - dev_err(dev, 201 - "Failed to load firmware: Invalid version %d. Supported firmware versions: 1\n", 202 - ssfw_head->version); 150 + dev_err(sigmadsp->dev, "Failed to load firmware: Invalid magic\n"); 203 151 goto done; 204 152 } 205 153 ··· 200 162 fw->size - sizeof(*ssfw_head)); 201 163 pr_debug("%s: crc=%x\n", __func__, crc); 202 164 if (crc != le32_to_cpu(ssfw_head->crc)) { 203 - dev_err(dev, "Failed to load firmware: Wrong crc checksum: expected %x got %x\n", 165 + dev_err(sigmadsp->dev, "Failed to load firmware: Wrong crc checksum: expected %x got %x\n", 204 166 le32_to_cpu(ssfw_head->crc), crc); 205 167 goto done; 206 168 } 207 169 208 - ssfw->pos = sizeof(*ssfw_head); 170 + switch (ssfw_head->version) { 171 + case 1: 172 + ret = sigmadsp_fw_load_v1(sigmadsp, fw); 173 + break; 174 + default: 175 + dev_err(sigmadsp->dev, 176 + "Failed to load firmware: Invalid version %d. Supported firmware versions: 1\n", 177 + ssfw_head->version); 178 + ret = -EINVAL; 179 + break; 180 + } 209 181 210 - /* finally process all of the actions */ 211 - ret = process_sigma_actions(ssfw); 182 + if (ret) 183 + sigmadsp_firmware_release(sigmadsp); 212 184 213 - done: 185 + done: 214 186 release_firmware(fw); 215 - 216 - pr_debug("%s: loaded %s\n", __func__, name); 217 187 218 188 return ret; 219 189 } 220 - EXPORT_SYMBOL_GPL(_process_sigma_firmware); 190 + 191 + static int sigmadsp_init(struct sigmadsp *sigmadsp, struct device *dev, 192 + const struct sigmadsp_ops *ops, const char *firmware_name) 193 + { 194 + sigmadsp->ops = ops; 195 + sigmadsp->dev = dev; 196 + 197 + INIT_LIST_HEAD(&sigmadsp->data_list); 198 + 199 + return sigmadsp_firmware_load(sigmadsp, firmware_name); 200 + } 201 + 202 + /** 203 + * devm_sigmadsp_init() - Initialize SigmaDSP instance 204 + * @dev: The parent device 205 + * @ops: The sigmadsp_ops to use for this instance 206 + * @firmware_name: Name of the firmware file to load 207 + * 208 + * Allocates a SigmaDSP instance and loads the specified firmware file. 209 + * 210 + * Returns a pointer to a struct sigmadsp on success, or a PTR_ERR() on error. 211 + */ 212 + struct sigmadsp *devm_sigmadsp_init(struct device *dev, 213 + const struct sigmadsp_ops *ops, const char *firmware_name) 214 + { 215 + struct sigmadsp *sigmadsp; 216 + int ret; 217 + 218 + sigmadsp = devres_alloc(devm_sigmadsp_release, sizeof(*sigmadsp), 219 + GFP_KERNEL); 220 + if (!sigmadsp) 221 + return ERR_PTR(-ENOMEM); 222 + 223 + ret = sigmadsp_init(sigmadsp, dev, ops, firmware_name); 224 + if (ret) { 225 + devres_free(sigmadsp); 226 + return ERR_PTR(ret); 227 + } 228 + 229 + devres_add(dev, sigmadsp); 230 + 231 + return sigmadsp; 232 + } 233 + EXPORT_SYMBOL_GPL(devm_sigmadsp_init); 234 + 235 + /** 236 + * sigmadsp_attach() - Attach a sigmadsp instance to a ASoC component 237 + * @sigmadsp: The sigmadsp instance to attach 238 + * @component: The component to attach to 239 + * 240 + * Typically called in the components probe callback. 241 + * 242 + * Note, once this function has been called the firmware must not be released 243 + * until after the ALSA snd_card that the component belongs to has been 244 + * disconnected, even if sigmadsp_attach() returns an error. 245 + */ 246 + int sigmadsp_attach(struct sigmadsp *sigmadsp, 247 + struct snd_soc_component *component) 248 + { 249 + sigmadsp->component = component; 250 + 251 + return 0; 252 + } 253 + EXPORT_SYMBOL_GPL(sigmadsp_attach); 254 + 255 + /** 256 + * sigmadsp_setup() - Setup the DSP for the specified samplerate 257 + * @sigmadsp: The sigmadsp instance to configure 258 + * @samplerate: The samplerate the DSP should be configured for 259 + * 260 + * Loads the appropriate firmware program and parameter memory (if not already 261 + * loaded) and enables the controls for the specified samplerate. Any control 262 + * parameter changes that have been made previously will be restored. 263 + * 264 + * Returns 0 on success, a negative error code otherwise. 265 + */ 266 + int sigmadsp_setup(struct sigmadsp *sigmadsp, unsigned int samplerate) 267 + { 268 + struct sigmadsp_data *data; 269 + int ret; 270 + 271 + if (sigmadsp->current_samplerate == samplerate) 272 + return 0; 273 + 274 + list_for_each_entry(data, &sigmadsp->data_list, head) { 275 + ret = sigmadsp_write(sigmadsp, data->addr, data->data, 276 + data->length); 277 + if (ret) 278 + goto err; 279 + } 280 + 281 + sigmadsp->current_samplerate = samplerate; 282 + 283 + return 0; 284 + err: 285 + sigmadsp_reset(sigmadsp); 286 + 287 + return ret; 288 + } 289 + EXPORT_SYMBOL_GPL(sigmadsp_setup); 290 + 291 + /** 292 + * sigmadsp_reset() - Notify the sigmadsp instance that the DSP has been reset 293 + * @sigmadsp: The sigmadsp instance to reset 294 + * 295 + * Should be called whenever the DSP has been reset and parameter and program 296 + * memory need to be re-loaded. 297 + */ 298 + void sigmadsp_reset(struct sigmadsp *sigmadsp) 299 + { 300 + sigmadsp->current_samplerate = 0; 301 + } 302 + EXPORT_SYMBOL_GPL(sigmadsp_reset); 303 + 304 + /** 305 + * sigmadsp_restrict_params() - Applies DSP firmware specific constraints 306 + * @sigmadsp: The sigmadsp instance 307 + * @substream: The substream to restrict 308 + * 309 + * Applies samplerate constraints that may be required by the firmware Should 310 + * typically be called from the CODEC/component drivers startup callback. 311 + * 312 + * Returns 0 on success, a negative error code otherwise. 313 + */ 314 + int sigmadsp_restrict_params(struct sigmadsp *sigmadsp, 315 + struct snd_pcm_substream *substream) 316 + { 317 + return 0; 318 + } 319 + EXPORT_SYMBOL_GPL(sigmadsp_restrict_params); 221 320 222 321 MODULE_LICENSE("GPL");
+37 -18
sound/soc/codecs/sigmadsp.h
··· 11 11 12 12 #include <linux/device.h> 13 13 #include <linux/regmap.h> 14 + #include <linux/list.h> 14 15 15 - struct sigma_action { 16 - u8 instr; 17 - u8 len_hi; 18 - __le16 len; 19 - __be16 addr; 20 - unsigned char payload[]; 21 - } __packed; 16 + #include <sound/pcm.h> 22 17 23 - struct sigma_firmware { 24 - const struct firmware *fw; 25 - size_t pos; 18 + struct sigmadsp; 19 + struct snd_soc_component; 20 + struct snd_pcm_substream; 26 21 27 - void *control_data; 28 - int (*write)(void *control_data, const struct sigma_action *sa, 29 - size_t len); 22 + struct sigmadsp_ops { 23 + int (*safeload)(struct sigmadsp *sigmadsp, unsigned int addr, 24 + const uint8_t *data, size_t len); 30 25 }; 31 26 32 - int _process_sigma_firmware(struct device *dev, 33 - struct sigma_firmware *ssfw, const char *name); 27 + struct sigmadsp { 28 + const struct sigmadsp_ops *ops; 29 + 30 + struct list_head data_list; 31 + 32 + unsigned int current_samplerate; 33 + struct snd_soc_component *component; 34 + struct device *dev; 35 + 36 + void *control_data; 37 + int (*write)(void *, unsigned int, const uint8_t *, size_t); 38 + }; 39 + 40 + struct sigmadsp *devm_sigmadsp_init(struct device *dev, 41 + const struct sigmadsp_ops *ops, const char *firmware_name); 42 + void sigmadsp_reset(struct sigmadsp *sigmadsp); 43 + 44 + int sigmadsp_restrict_params(struct sigmadsp *sigmadsp, 45 + struct snd_pcm_substream *substream); 34 46 35 47 struct i2c_client; 36 48 37 - extern int process_sigma_firmware(struct i2c_client *client, const char *name); 38 - extern int process_sigma_firmware_regmap(struct device *dev, 39 - struct regmap *regmap, const char *name); 49 + struct sigmadsp *devm_sigmadsp_init_regmap(struct device *dev, 50 + struct regmap *regmap, const struct sigmadsp_ops *ops, 51 + const char *firmware_name); 52 + struct sigmadsp *devm_sigmadsp_init_i2c(struct i2c_client *client, 53 + const struct sigmadsp_ops *ops, const char *firmware_name); 54 + 55 + int sigmadsp_attach(struct sigmadsp *sigmadsp, 56 + struct snd_soc_component *component); 57 + int sigmadsp_setup(struct sigmadsp *sigmadsp, unsigned int rate); 58 + void sigmadsp_reset(struct sigmadsp *sigmadsp); 40 59 41 60 #endif