ASoC: Move SigmaDSP firmware loader to ASoC
authorLars-Peter Clausen <lars@metafoo.de>
Mon, 28 Nov 2011 08:44:17 +0000 (09:44 +0100)
committerMark Brown <broonie@opensource.wolfsonmicro.com>
Tue, 29 Nov 2011 12:01:10 +0000 (12:01 +0000)
It has been pointed out previously, that the firmware subsystem is not the right
place for the SigmaDSP firmware loader. Furthermore the SigmaDSP is currently
only used in audio products and we are aiming for better integration into the
ASoC framework in the future, with support for ALSA controls for firmware
parameters and support dynamic power management as well. So the natural choice
for the SigmaDSP firmware loader is the ASoC subsystem.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Acked-by: Mike Frysinger <vapier@gentoo.org>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
MAINTAINERS
drivers/firmware/Kconfig
drivers/firmware/Makefile
drivers/firmware/sigma.c [deleted file]
include/linux/sigma.h [deleted file]
sound/soc/codecs/Kconfig
sound/soc/codecs/Makefile
sound/soc/codecs/adau1701.c
sound/soc/codecs/sigmadsp.c [new file with mode: 0644]
sound/soc/codecs/sigmadsp.h [new file with mode: 0644]

index fd7e441b5ea7f83cd6b73bcf0b2b631aef485aac..6a93a930ec66ba0eedc2298f4979929cf0581c34 100644 (file)
@@ -542,6 +542,7 @@ F:  sound/soc/codecs/adau*
 F:     sound/soc/codecs/adav*
 F:     sound/soc/codecs/ad1*
 F:     sound/soc/codecs/ssm*
+F:     sound/soc/codecs/sigmadsp.*
 
 ANALOG DEVICES INC ASOC DRIVERS
 L:     uclinux-dist-devel@blackfin.uclinux.org
index efba163595db1dd6a981f426d3581351a0fbd8b6..9b00072a020fb5141060c5ee89cfe31edbd651be 100644 (file)
@@ -145,18 +145,6 @@ config ISCSI_IBFT
          detect iSCSI boot parameters dynamically during system boot, say Y.
          Otherwise, say N.
 
-config SIGMA
-       tristate "SigmaStudio firmware loader"
-       depends on I2C
-       select CRC32
-       default n
-       help
-         Enable helper functions for working with Analog Devices SigmaDSP
-         parts and binary firmwares produced by Analog Devices SigmaStudio.
-
-         If unsure, say N here.  Drivers that need these helpers will select
-         this option automatically.
-
 source "drivers/firmware/google/Kconfig"
 
 endmenu
index 47338c9791263e849a9db97b34fb9f777afa2145..5a7e27399729789054c5069ca14ab4738786266f 100644 (file)
@@ -12,6 +12,5 @@ obj-$(CONFIG_DMIID)           += dmi-id.o
 obj-$(CONFIG_ISCSI_IBFT_FIND)  += iscsi_ibft_find.o
 obj-$(CONFIG_ISCSI_IBFT)       += iscsi_ibft.o
 obj-$(CONFIG_FIRMWARE_MEMMAP)  += memmap.o
-obj-$(CONFIG_SIGMA)            += sigma.o
 
 obj-$(CONFIG_GOOGLE_FIRMWARE)  += google/
diff --git a/drivers/firmware/sigma.c b/drivers/firmware/sigma.c
deleted file mode 100644 (file)
index 1eedb6f..0000000
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Load Analog Devices SigmaStudio firmware files
- *
- * Copyright 2009-2011 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
-
-#include <linux/crc32.h>
-#include <linux/delay.h>
-#include <linux/firmware.h>
-#include <linux/kernel.h>
-#include <linux/i2c.h>
-#include <linux/module.h>
-#include <linux/sigma.h>
-
-static size_t sigma_action_size(struct sigma_action *sa)
-{
-       size_t payload = 0;
-
-       switch (sa->instr) {
-       case SIGMA_ACTION_WRITEXBYTES:
-       case SIGMA_ACTION_WRITESINGLE:
-       case SIGMA_ACTION_WRITESAFELOAD:
-               payload = sigma_action_len(sa);
-               break;
-       default:
-               break;
-       }
-
-       payload = ALIGN(payload, 2);
-
-       return payload + sizeof(struct sigma_action);
-}
-
-/*
- * Returns a negative error value in case of an error, 0 if processing of
- * the firmware should be stopped after this action, 1 otherwise.
- */
-static int
-process_sigma_action(struct i2c_client *client, struct sigma_action *sa)
-{
-       size_t len = sigma_action_len(sa);
-       int ret;
-
-       pr_debug("%s: instr:%i addr:%#x len:%zu\n", __func__,
-               sa->instr, sa->addr, len);
-
-       switch (sa->instr) {
-       case SIGMA_ACTION_WRITEXBYTES:
-       case SIGMA_ACTION_WRITESINGLE:
-       case SIGMA_ACTION_WRITESAFELOAD:
-               ret = i2c_master_send(client, (void *)&sa->addr, len);
-               if (ret < 0)
-                       return -EINVAL;
-               break;
-       case SIGMA_ACTION_DELAY:
-               udelay(len);
-               len = 0;
-               break;
-       case SIGMA_ACTION_END:
-               return 0;
-       default:
-               return -EINVAL;
-       }
-
-       return 1;
-}
-
-static int
-process_sigma_actions(struct i2c_client *client, struct sigma_firmware *ssfw)
-{
-       struct sigma_action *sa;
-       size_t size;
-       int ret;
-
-       while (ssfw->pos + sizeof(*sa) <= ssfw->fw->size) {
-               sa = (struct sigma_action *)(ssfw->fw->data + ssfw->pos);
-
-               size = sigma_action_size(sa);
-               ssfw->pos += size;
-               if (ssfw->pos > ssfw->fw->size || size == 0)
-                       break;
-
-               ret = process_sigma_action(client, sa);
-
-               pr_debug("%s: action returned %i\n", __func__, ret);
-
-               if (ret <= 0)
-                       return ret;
-       }
-
-       if (ssfw->pos != ssfw->fw->size)
-               return -EINVAL;
-
-       return 0;
-}
-
-int process_sigma_firmware(struct i2c_client *client, const char *name)
-{
-       int ret;
-       struct sigma_firmware_header *ssfw_head;
-       struct sigma_firmware ssfw;
-       const struct firmware *fw;
-       u32 crc;
-
-       pr_debug("%s: loading firmware %s\n", __func__, name);
-
-       /* first load the blob */
-       ret = request_firmware(&fw, name, &client->dev);
-       if (ret) {
-               pr_debug("%s: request_firmware() failed with %i\n", __func__, ret);
-               return ret;
-       }
-       ssfw.fw = fw;
-
-       /* then verify the header */
-       ret = -EINVAL;
-
-       /*
-        * Reject too small or unreasonable large files. The upper limit has been
-        * chosen a bit arbitrarily, but it should be enough for all practical
-        * purposes and having the limit makes it easier to avoid integer
-        * overflows later in the loading process.
-        */
-       if (fw->size < sizeof(*ssfw_head) || fw->size >= 0x4000000)
-               goto done;
-
-       ssfw_head = (void *)fw->data;
-       if (memcmp(ssfw_head->magic, SIGMA_MAGIC, ARRAY_SIZE(ssfw_head->magic)))
-               goto done;
-
-       crc = crc32(0, fw->data + sizeof(*ssfw_head),
-                       fw->size - sizeof(*ssfw_head));
-       pr_debug("%s: crc=%x\n", __func__, crc);
-       if (crc != le32_to_cpu(ssfw_head->crc))
-               goto done;
-
-       ssfw.pos = sizeof(*ssfw_head);
-
-       /* finally process all of the actions */
-       ret = process_sigma_actions(client, &ssfw);
-
- done:
-       release_firmware(fw);
-
-       pr_debug("%s: loaded %s\n", __func__, name);
-
-       return ret;
-}
-EXPORT_SYMBOL(process_sigma_firmware);
-
-MODULE_LICENSE("GPL");
diff --git a/include/linux/sigma.h b/include/linux/sigma.h
deleted file mode 100644 (file)
index d0de882..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Load firmware files from Analog Devices SigmaStudio
- *
- * Copyright 2009-2011 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
-
-#ifndef __SIGMA_FIRMWARE_H__
-#define __SIGMA_FIRMWARE_H__
-
-#include <linux/firmware.h>
-#include <linux/types.h>
-
-struct i2c_client;
-
-#define SIGMA_MAGIC "ADISIGM"
-
-struct sigma_firmware {
-       const struct firmware *fw;
-       size_t pos;
-};
-
-struct sigma_firmware_header {
-       unsigned char magic[7];
-       u8 version;
-       __le32 crc;
-};
-
-enum {
-       SIGMA_ACTION_WRITEXBYTES = 0,
-       SIGMA_ACTION_WRITESINGLE,
-       SIGMA_ACTION_WRITESAFELOAD,
-       SIGMA_ACTION_DELAY,
-       SIGMA_ACTION_PLLWAIT,
-       SIGMA_ACTION_NOOP,
-       SIGMA_ACTION_END,
-};
-
-struct sigma_action {
-       u8 instr;
-       u8 len_hi;
-       __le16 len;
-       __be16 addr;
-       unsigned char payload[];
-};
-
-static inline u32 sigma_action_len(struct sigma_action *sa)
-{
-       return (sa->len_hi << 16) | le16_to_cpu(sa->len);
-}
-
-extern int process_sigma_firmware(struct i2c_client *client, const char *name);
-
-#endif
index 686f45a07f34a0e80b255fc5a34c0c8aed1fe3b6..593174c78d7bfc5d4e7561b8e5b15f35e6a00b1a 100644 (file)
@@ -141,7 +141,7 @@ config SND_SOC_AD73311
        tristate
 
 config SND_SOC_ADAU1701
-       select SIGMA
+       select SND_SOC_SIGMADSP
        tristate
 
 config SND_SOC_ADAU1373
@@ -234,6 +234,10 @@ config SND_SOC_RT5631
 config SND_SOC_SGTL5000
        tristate
 
+config SND_SOC_SIGMADSP
+       tristate
+       select CRC32
+
 config SND_SOC_SN95031
        tristate
 
index 62b01e4e7983f8d1307daa06e615852e24913bb8..fa15006fcac59ff8c4dcdba3642e3700b50fb0e0 100644 (file)
@@ -33,6 +33,7 @@ snd-soc-rt5631-objs := rt5631.o
 snd-soc-sgtl5000-objs := sgtl5000.o
 snd-soc-alc5623-objs := alc5623.o
 snd-soc-alc5632-objs := alc5632.o
+snd-soc-sigmadsp-objs := sigmadsp.o
 snd-soc-sn95031-objs := sn95031.o
 snd-soc-spdif-objs := spdif_transciever.o
 snd-soc-ssm2602-objs := ssm2602.o
@@ -134,6 +135,7 @@ obj-$(CONFIG_SND_SOC_MAX9850)       += snd-soc-max9850.o
 obj-$(CONFIG_SND_SOC_PCM3008)  += snd-soc-pcm3008.o
 obj-$(CONFIG_SND_SOC_RT5631)   += snd-soc-rt5631.o
 obj-$(CONFIG_SND_SOC_SGTL5000)  += snd-soc-sgtl5000.o
+obj-$(CONFIG_SND_SOC_SIGMADSP) += snd-soc-sigmadsp.o
 obj-$(CONFIG_SND_SOC_SN95031)  +=snd-soc-sn95031.o
 obj-$(CONFIG_SND_SOC_SPDIF)    += snd-soc-spdif.o
 obj-$(CONFIG_SND_SOC_SSM2602)  += snd-soc-ssm2602.o
index 8b7e1c50d6e9df43d2a25956a698094eb2bb6738..6a6af567f02a9042cc280266762fe388fe8632ce 100644 (file)
 #include <linux/init.h>
 #include <linux/i2c.h>
 #include <linux/delay.h>
-#include <linux/sigma.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
 
+#include "sigmadsp.h"
 #include "adau1701.h"
 
 #define ADAU1701_DSPCTRL       0x1c
diff --git a/sound/soc/codecs/sigmadsp.c b/sound/soc/codecs/sigmadsp.c
new file mode 100644 (file)
index 0000000..acb97a9
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * Load Analog Devices SigmaStudio firmware files
+ *
+ * Copyright 2009-2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/crc32.h>
+#include <linux/delay.h>
+#include <linux/firmware.h>
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+
+#include "sigmadsp.h"
+
+static size_t sigma_action_size(struct sigma_action *sa)
+{
+       size_t payload = 0;
+
+       switch (sa->instr) {
+       case SIGMA_ACTION_WRITEXBYTES:
+       case SIGMA_ACTION_WRITESINGLE:
+       case SIGMA_ACTION_WRITESAFELOAD:
+               payload = sigma_action_len(sa);
+               break;
+       default:
+               break;
+       }
+
+       payload = ALIGN(payload, 2);
+
+       return payload + sizeof(struct sigma_action);
+}
+
+/*
+ * Returns a negative error value in case of an error, 0 if processing of
+ * the firmware should be stopped after this action, 1 otherwise.
+ */
+static int
+process_sigma_action(struct i2c_client *client, struct sigma_action *sa)
+{
+       size_t len = sigma_action_len(sa);
+       int ret;
+
+       pr_debug("%s: instr:%i addr:%#x len:%zu\n", __func__,
+               sa->instr, sa->addr, len);
+
+       switch (sa->instr) {
+       case SIGMA_ACTION_WRITEXBYTES:
+       case SIGMA_ACTION_WRITESINGLE:
+       case SIGMA_ACTION_WRITESAFELOAD:
+               ret = i2c_master_send(client, (void *)&sa->addr, len);
+               if (ret < 0)
+                       return -EINVAL;
+               break;
+       case SIGMA_ACTION_DELAY:
+               udelay(len);
+               len = 0;
+               break;
+       case SIGMA_ACTION_END:
+               return 0;
+       default:
+               return -EINVAL;
+       }
+
+       return 1;
+}
+
+static int
+process_sigma_actions(struct i2c_client *client, struct sigma_firmware *ssfw)
+{
+       struct sigma_action *sa;
+       size_t size;
+       int ret;
+
+       while (ssfw->pos + sizeof(*sa) <= ssfw->fw->size) {
+               sa = (struct sigma_action *)(ssfw->fw->data + ssfw->pos);
+
+               size = sigma_action_size(sa);
+               ssfw->pos += size;
+               if (ssfw->pos > ssfw->fw->size || size == 0)
+                       break;
+
+               ret = process_sigma_action(client, sa);
+
+               pr_debug("%s: action returned %i\n", __func__, ret);
+
+               if (ret <= 0)
+                       return ret;
+       }
+
+       if (ssfw->pos != ssfw->fw->size)
+               return -EINVAL;
+
+       return 0;
+}
+
+int process_sigma_firmware(struct i2c_client *client, const char *name)
+{
+       int ret;
+       struct sigma_firmware_header *ssfw_head;
+       struct sigma_firmware ssfw;
+       const struct firmware *fw;
+       u32 crc;
+
+       pr_debug("%s: loading firmware %s\n", __func__, name);
+
+       /* first load the blob */
+       ret = request_firmware(&fw, name, &client->dev);
+       if (ret) {
+               pr_debug("%s: request_firmware() failed with %i\n", __func__, ret);
+               return ret;
+       }
+       ssfw.fw = fw;
+
+       /* then verify the header */
+       ret = -EINVAL;
+
+       /*
+        * Reject too small or unreasonable large files. The upper limit has been
+        * chosen a bit arbitrarily, but it should be enough for all practical
+        * purposes and having the limit makes it easier to avoid integer
+        * overflows later in the loading process.
+        */
+       if (fw->size < sizeof(*ssfw_head) || fw->size >= 0x4000000)
+               goto done;
+
+       ssfw_head = (void *)fw->data;
+       if (memcmp(ssfw_head->magic, SIGMA_MAGIC, ARRAY_SIZE(ssfw_head->magic)))
+               goto done;
+
+       crc = crc32(0, fw->data + sizeof(*ssfw_head),
+                       fw->size - sizeof(*ssfw_head));
+       pr_debug("%s: crc=%x\n", __func__, crc);
+       if (crc != le32_to_cpu(ssfw_head->crc))
+               goto done;
+
+       ssfw.pos = sizeof(*ssfw_head);
+
+       /* finally process all of the actions */
+       ret = process_sigma_actions(client, &ssfw);
+
+ done:
+       release_firmware(fw);
+
+       pr_debug("%s: loaded %s\n", __func__, name);
+
+       return ret;
+}
+EXPORT_SYMBOL(process_sigma_firmware);
+
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/sigmadsp.h b/sound/soc/codecs/sigmadsp.h
new file mode 100644 (file)
index 0000000..d0de882
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Load firmware files from Analog Devices SigmaStudio
+ *
+ * Copyright 2009-2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef __SIGMA_FIRMWARE_H__
+#define __SIGMA_FIRMWARE_H__
+
+#include <linux/firmware.h>
+#include <linux/types.h>
+
+struct i2c_client;
+
+#define SIGMA_MAGIC "ADISIGM"
+
+struct sigma_firmware {
+       const struct firmware *fw;
+       size_t pos;
+};
+
+struct sigma_firmware_header {
+       unsigned char magic[7];
+       u8 version;
+       __le32 crc;
+};
+
+enum {
+       SIGMA_ACTION_WRITEXBYTES = 0,
+       SIGMA_ACTION_WRITESINGLE,
+       SIGMA_ACTION_WRITESAFELOAD,
+       SIGMA_ACTION_DELAY,
+       SIGMA_ACTION_PLLWAIT,
+       SIGMA_ACTION_NOOP,
+       SIGMA_ACTION_END,
+};
+
+struct sigma_action {
+       u8 instr;
+       u8 len_hi;
+       __le16 len;
+       __be16 addr;
+       unsigned char payload[];
+};
+
+static inline u32 sigma_action_len(struct sigma_action *sa)
+{
+       return (sa->len_hi << 16) | le16_to_cpu(sa->len);
+}
+
+extern int process_sigma_firmware(struct i2c_client *client, const char *name);
+
+#endif