[Sound-open-firmware] [PATCH 1/4] rimage: update to new SOF driver file format.
Support the SOF driver file format.
Signed-off-by: Liam Girdwood liam.r.girdwood@linux.intel.com --- rimage/baytrail.c | 73 +++++++++------------- rimage/cherrytrail.c | 9 ++- rimage/file_format.h | 166 ++++++++++++++++++++++++++++++--------------------- rimage/rimage.c | 26 +++----- rimage/rimage.h | 11 ++++ 5 files changed, 151 insertions(+), 134 deletions(-)
diff --git a/rimage/baytrail.c b/rimage/baytrail.c index 0053f97..12ccd23 100644 --- a/rimage/baytrail.c +++ b/rimage/baytrail.c @@ -40,17 +40,6 @@ static const struct section byt_sections[] = { {"NMIExceptionVector", 0xff2c061c}, };
-static const enum reef_module_id modules[] = { - REEF_MODULE_BASE_FW, - REEF_MODULE_AAC_5_1, - REEF_MODULE_PCM, - REEF_MODULE_PCM_SYSTEM, - REEF_MODULE_PCM_CAPTURE, - REEF_MODULE_PCM_REFERENCE, - REEF_MODULE_BLUETOOTH_RENDER_MODULE, - REEF_MODULE_BLUETOOTH_CAPTURE_MODULE, -}; - static int is_iram(struct image *image, Elf32_Shdr *section) { const struct adsp *adsp = image->adsp; @@ -86,7 +75,7 @@ static int block_idx = 0; static int write_block(struct image *image, Elf32_Shdr *section) { const struct adsp *adsp = image->adsp; - struct dma_block_info block; + struct snd_sof_blk_hdr block; size_t count; void *buffer; int ret; @@ -94,11 +83,13 @@ static int write_block(struct image *image, Elf32_Shdr *section) block.size = section->sh_size;
if (is_iram(image, section)) { - block.type = REEF_IRAM; - block.ram_offset = section->sh_addr - adsp->iram_base; + block.type = SOF_BLK_TEXT; + block.offset = section->sh_addr - adsp->iram_base + + adsp->host_iram_offset; } else if (is_dram(image, section)) { - block.type = REEF_DRAM; - block.ram_offset = section->sh_addr - adsp->dram_base; + block.type = SOF_BLK_DATA; + block.offset = section->sh_addr - adsp->dram_base + + adsp->host_dram_offset; } else { fprintf(stderr, "error: invalid block address/size 0x%x/0x%x\n", section->sh_addr, section->sh_size); @@ -153,18 +144,18 @@ out: int byt_write_modules(struct image *image) { const struct adsp *adsp = image->adsp; - struct byt_module_header hdr; + struct snd_sof_mod_hdr hdr; Elf32_Shdr *section; size_t count; int i, err; uint32_t valid = (SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR);
- memcpy(hdr.signature, REEF_FW_SIGN, REEF_FW_SIGNATURE_SIZE); - hdr.blocks = image->num_sections - image->num_bss; - hdr.mod_size = image->text_size + image->data_size + \ - sizeof(struct dma_block_info) * hdr.blocks; - hdr.type = REEF_MODULE_BASE_FW; - hdr.entry_point = 0;//section->sh_addr; + fprintf(stdout, "Using BYT file format\n"); + + hdr.num_blocks = image->num_sections - image->num_bss; + hdr.size = image->text_size + image->data_size + + sizeof(struct snd_sof_blk_hdr) * hdr.num_blocks; + hdr.type = SOF_FW_BASE;
count = fwrite(&hdr, sizeof(hdr), 1, image->out_fd); if (count != 1) { @@ -191,41 +182,28 @@ int byt_write_modules(struct image *image) } }
- /* write the remaining 7 fake modules headers, to make the linux driver happy */ - hdr.mod_size = 0; - hdr.blocks = 0; - - for (i = 1; i < sizeof(modules) / sizeof(modules[0]); i++) { - hdr.type = modules[i]; - count = fwrite(&hdr, sizeof(hdr), 1, image->out_fd); - if (count != 1) { - fprintf(stderr, "error: failed to write section header %d\n", i); - return -errno ; - } - } - return 0; }
/* used by others */ int byt_write_header(struct image *image) { - struct fw_header hdr; + struct snd_sof_fw_header hdr; size_t count;
- memcpy(hdr.signature, REEF_FW_SIGN, REEF_FW_SIGNATURE_SIZE); + memcpy(hdr.sig, SND_SOF_FW_SIG, SND_SOF_FW_SIG_SIZE);
- hdr.modules = sizeof(modules) / sizeof(modules[0]); - hdr.file_format = 0; + hdr.num_modules = 1; + hdr.abi = SND_SOF_FW_ABI;
- image->fw_size += sizeof(struct dma_block_info) * + image->fw_size += sizeof(struct snd_sof_blk_hdr) * (image->num_sections - image->num_bss); - image->fw_size += sizeof(struct byt_module_header) * hdr.modules; + image->fw_size += sizeof(struct snd_sof_mod_hdr) * hdr.num_modules; hdr.file_size = image->fw_size;
fprintf(stdout, "fw: image size %ld (0x%lx) bytes %d modules\n\n", hdr.file_size + sizeof(hdr), hdr.file_size + sizeof(hdr), - hdr.modules); + hdr.num_modules); count = fwrite(&hdr, sizeof(hdr), 1, image->out_fd); if (count != 1) return -errno; @@ -233,14 +211,19 @@ int byt_write_header(struct image *image) return 0; }
+#define IRAM_OFFSET 0x0C0000 +#define IRAM_SIZE (80 * 1024) +#define DRAM_OFFSET 0x100000 +#define DRAM_SIZE (160 * 1024) + const struct adsp byt_machine = { .name = "byt", .iram_base = 0xff2c0000, .iram_size = 0x14000, + .host_iram_offset = IRAM_OFFSET, .dram_base = 0xff300000, .dram_size = 0x28000, - .image_size = 0xff300000 - 0xff2c0000 + 0x28000, - .dram_offset = 0xff300000 - 0xff2c0000, + .host_dram_offset = DRAM_OFFSET, .machine_id = MACHINE_BAYTRAIL, .ops = { .write_header = byt_write_header, diff --git a/rimage/cherrytrail.c b/rimage/cherrytrail.c index a37a13d..e27bea6 100644 --- a/rimage/cherrytrail.c +++ b/rimage/cherrytrail.c @@ -40,14 +40,19 @@ static const struct section cht_sections[] = { {"NMIExceptionVector", 0xff2c061c}, };
+#define IRAM_OFFSET 0x0C0000 +#define IRAM_SIZE (80 * 1024) +#define DRAM_OFFSET 0x100000 +#define DRAM_SIZE (160 * 1024) + const struct adsp cht_machine = { .name = "cht", .iram_base = 0xff2c0000, .iram_size = 0x14000, + .host_iram_offset = IRAM_OFFSET, .dram_base = 0xff300000, .dram_size = 0x28000, - .image_size = 0xff300000 - 0xff2c0000 + 0x28000, - .dram_offset = 0xff300000 - 0xff2c0000, + .host_dram_offset = DRAM_OFFSET, .machine_id = MACHINE_CHERRYTRAIL, .ops = { .write_header = byt_write_header, diff --git a/rimage/file_format.h b/rimage/file_format.h index 941df33..c813f49 100644 --- a/rimage/file_format.h +++ b/rimage/file_format.h @@ -1,88 +1,116 @@ /* - * ELF to firmware image creator. + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. * - * Copyright (c) 2015, Intel Corporation. + * GPL LICENSE SUMMARY * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. + * Copyright(c) 2017 Intel Corporation. All rights reserved. * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * BSD LICENSE + * + * Copyright(c) 2017 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Liam Girdwood liam.r.girdwood@linux.intel.com */
-#ifndef __FILE_FORMAT_H__ -#define __FILE_FORMAT_H__ +/* + * Firmware file format . + */
-#define REEF_FW_SIGNATURE_SIZE 4 -#define REEF_FW_SIGN "$SST" -#define REEF_FW_LIB_SIGN "$LIB" +#ifndef __INCLUDE_UAPI_SOF_FW_H__ +#define __INCLUDE_UAPI_SOF_FW_H__
-#define REEF_IRAM 1 -#define REEF_DRAM 2 -#define REEF_REGS 3 -#define REEF_CACHE 3 +#define SND_SOF_FW_SIG_SIZE 4 +#define SND_SOF_FW_ABI 1 +#define SND_SOF_FW_SIG "Reef"
-enum reef_module_id { - REEF_MODULE_BASE_FW = 0x0, - REEF_MODULE_MP3 = 0x1, - REEF_MODULE_AAC_5_1 = 0x2, - REEF_MODULE_AAC_2_0 = 0x3, - REEF_MODULE_SRC = 0x4, - REEF_MODULE_WAVES = 0x5, - REEF_MODULE_DOLBY = 0x6, - REEF_MODULE_BOOST = 0x7, - REEF_MODULE_LPAL = 0x8, - REEF_MODULE_DTS = 0x9, - REEF_MODULE_PCM_CAPTURE = 0xA, - REEF_MODULE_PCM_SYSTEM = 0xB, - REEF_MODULE_PCM_REFERENCE = 0xC, - REEF_MODULE_PCM = 0xD, - REEF_MODULE_BLUETOOTH_RENDER_MODULE = 0xE, - REEF_MODULE_BLUETOOTH_CAPTURE_MODULE = 0xF, - REEF_MAX_MODULE_ID, +/* + * Firmware module is made up of 1 . N blocks of different types. The + * Block header is used to determine where and how block is to be copied in the + * DSP/host memory space. + */ +enum snd_sof_fw_blk_type { + SOF_BLK_IMAGE = 0, /* whole image - parsed by ROMs */ + SOF_BLK_TEXT = 1, + SOF_BLK_DATA = 2, + SOF_BLK_CACHE = 3, + SOF_BLK_REGS = 4, + SOF_BLK_SIG = 5, + SOF_BLK_ROM = 6, + /* add new block types here */ };
-struct dma_block_info { - uint32_t type; /* IRAM/DRAM */ - uint32_t size; /* Bytes */ - uint32_t ram_offset; /* Offset in I/DRAM */ - uint32_t rsvd; /* Reserved field */ +struct snd_sof_blk_hdr { + enum snd_sof_fw_blk_type type; + uint32_t size; /* bytes minus this header */ + uint32_t offset; /* offset from base */ } __attribute__((packed));
-struct fw_module_info { - uint32_t persistent_size; - uint32_t scratch_size; -} __attribute__((packed)); +/* + * Firmware file is made up of 1 .. N different modules types. The module + * type is used to determine how to load and parse the module. + */ +enum snd_sof_fw_mod_type { + SOF_FW_BASE = 0, /* base firmware image */ + SOF_FW_MODULE = 1, /* firmware module */ +};
-struct fw_header { - unsigned char signature[REEF_FW_SIGNATURE_SIZE]; /* FW signature */ - uint32_t file_size; /* size of fw minus this header */ - uint32_t modules; /* # of modules */ - uint32_t file_format; /* version of header format */ - uint32_t reserved[4]; +struct snd_sof_mod_hdr { + enum snd_sof_fw_mod_type type; + uint32_t size; /* bytes minus this header */ + uint32_t num_blocks; /* number of blocks */ } __attribute__((packed));
-/* ABI 0 - used by reef driver and CoE BDW/HSW firmware*/ -struct hsw_module_header { - unsigned char signature[REEF_FW_SIGNATURE_SIZE]; /* module signature */ - uint32_t mod_size; /* size of module */ - uint32_t blocks; /* # of blocks */ - uint16_t padding; - uint16_t type; /* codec type, pp lib */ - uint32_t entry_point; - struct fw_module_info info; +/* + * Firmware file header. + */ +struct snd_sof_fw_header { + unsigned char sig[SND_SOF_FW_SIG_SIZE]; /* "Reef" */ + uint32_t file_size; /* size of file minus this header */ + uint32_t num_modules; /* number of modules */ + uint32_t abi; /* version of header format */ } __attribute__((packed));
-/* ABI 1 - used by CoE/MCG BYT/CHT/BSW driver */ -struct byt_module_header { - unsigned char signature[REEF_FW_SIGNATURE_SIZE]; - uint32_t mod_size; /* size of module */ - uint32_t blocks; /* # of blocks */ - uint32_t type; /* codec type, pp lib */ - uint32_t entry_point; -}__attribute__((packed)); - #endif diff --git a/rimage/rimage.c b/rimage/rimage.c index bed6b48..0695ce3 100644 --- a/rimage/rimage.c +++ b/rimage/rimage.c @@ -223,9 +223,12 @@ int main(int argc, char *argv[]) { struct image image; const char *mach = NULL; - int opt, ret, i, binary = 0; + int opt, ret, i;
memset(&image, 0, sizeof(image)); + image.text_start = 0xffffffff; + image.data_start = 0xffffffff; + image.bss_start = 0xffffffff;
while ((opt = getopt(argc, argv, "ho:i:m:vba:sk:")) != -1) { switch (opt) { @@ -241,9 +244,6 @@ int main(int argc, char *argv[]) case 'v': image.verbose = 1; break; - case 'b': - binary = 1; - break; case 's': image.dump_sections = 1; break; @@ -282,26 +282,16 @@ found: image.in_file, errno); }
- /* open outfile for reading */ + /* open outfile for writing */ + unlink(image.out_file); image.out_fd = fopen(image.out_file, "w"); if (image.out_fd == NULL) { fprintf(stderr, "error: unable to open %s for writing %d\n", image.out_file, errno); }
- if (binary) { - - switch(image.adsp->machine_id) { - case MACHINE_BAYTRAIL: - ret = write_byt_binary_image(&image); - break; - default: - fprintf(stderr, "error: not supported machine for binary input!\n"); - return ret; - } - - } else - ret = write_elf_data(&image); + /* write data */ + ret = write_elf_data(&image);
/* close files */ fclose(image.out_fd); diff --git a/rimage/rimage.h b/rimage/rimage.h index 2c02932..9b8200a 100644 --- a/rimage/rimage.h +++ b/rimage/rimage.h @@ -50,6 +50,13 @@ struct image { int data_size; int file_size; int num_modules; + uint32_t text_start; + uint32_t text_end; + uint32_t data_start; + uint32_t data_end; + uint32_t bss_start; + uint32_t bss_end; +
/* disa */ void *in_buffer; @@ -82,8 +89,12 @@ struct adsp { uint32_t iram_size; uint32_t dram_base; uint32_t dram_size; + uint32_t host_iram_offset; + uint32_t host_dram_offset; + uint32_t image_size; uint32_t dram_offset; + enum machine_id machine_id; struct adsp_ops ops; const struct section *sections;
Signed-off-by: Liam Girdwood liam.r.girdwood@linux.intel.com --- rmbox/rmbox.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
diff --git a/rmbox/rmbox.c b/rmbox/rmbox.c index d2247f7..6105e38 100644 --- a/rmbox/rmbox.c +++ b/rmbox/rmbox.c @@ -34,6 +34,10 @@ #define TRACE_CLASS_LOCK (10 << 24) #define TRACE_CLASS_MEM (11 << 24) #define TRACE_CLASS_MIXER (12 << 24) +#define TRACE_CLASS_BUFFER (13 << 24) +#define TRACE_CLASS_VOLUME (14 << 24) +#define TRACE_CLASS_SWITCH (15 << 24) +#define TRACE_CLASS_MUX (16 << 24)
#define MAILBOX_HOST_OFFSET 0x144000
@@ -134,6 +138,14 @@ static void show_trace(uint32_t val, uint32_t addr, uint32_t *timestamp) trace = "mem"; else if (class == TRACE_CLASS_MIXER) trace = "mixer"; + else if (class == TRACE_CLASS_BUFFER) + trace = "buffer"; + else if (class == TRACE_CLASS_VOLUME) + trace = "volume"; + else if (class == TRACE_CLASS_SWITCH) + trace = "switch"; + else if (class == TRACE_CLASS_MUX) + trace = "mux"; else { printf("value 0x%8.8x\n", (uint32_t)val); return;
Signed-off-by: Liam Girdwood liam.r.girdwood@linux.intel.com --- rmbox/rmbox.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/rmbox/rmbox.c b/rmbox/rmbox.c index 6105e38..0983ca6 100644 --- a/rmbox/rmbox.c +++ b/rmbox/rmbox.c @@ -267,6 +267,7 @@ int main(int argc, char *argv[]) if (in_fd == NULL) { fprintf(stderr, "error: unable to open %s for reading %d\n", in_file, errno); + return -EIO; }
/* open outfile for writing */ @@ -277,6 +278,7 @@ int main(int argc, char *argv[]) if (out_fd == NULL) { fprintf(stderr, "error: unable to open %s for writing %d\n", out_file, errno); + return -EIO; }
/* start to converting mailbox */
Signed-off-by: Liam Girdwood liam.r.girdwood@linux.intel.com --- rmbox/rmbox.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-)
diff --git a/rmbox/rmbox.c b/rmbox/rmbox.c index 0983ca6..f5e9c34 100644 --- a/rmbox/rmbox.c +++ b/rmbox/rmbox.c @@ -92,14 +92,14 @@ static void usage(char *name) exit(0); }
-static inline float clk_to_usecs(uint32_t time) +static inline float to_usecs(uint32_t time, uint32_t clk) { - /* trace timestamp uses SSP system clock at default 19.2MHz ticks */ + /* trace timestamp uses CPU system clock at default 25MHz ticks */ // TODO: support variable clock rates - return (float)time / 19.2; + return (float)time / clk; }
-static void show_trace(uint32_t val, uint32_t addr, uint32_t *timestamp) +static void show_trace(uint32_t val, uint32_t addr, uint32_t *timestamp, uint32_t clk) { const char *trace; uint32_t class; @@ -107,8 +107,8 @@ static void show_trace(uint32_t val, uint32_t addr, uint32_t *timestamp) /* timestamp or value ? */ if ((addr % 8) == 0) { printf("trace.io: timestamp 0x%8.8x (%2.2f us) \tdelta 0x%8.8x (%2.2f us)\t", - (uint32_t)val, clk_to_usecs(val), - (uint32_t)val - *timestamp, clk_to_usecs(val - *timestamp)); + (uint32_t)val, to_usecs(val, clk), + (uint32_t)val - *timestamp, to_usecs(val - *timestamp, clk)); *timestamp = val; return; } @@ -238,12 +238,12 @@ static int snapshot(const char *name) int main(int argc, char *argv[]) { int opt, count; - const char * out_file = NULL, *in_file = "/sys/kernel/debug/mbox"; + const char * out_file = NULL, *in_file = "/sys/kernel/debug/sof/mbox"; FILE *in_fd = NULL, *out_fd = NULL; char c, tmp[4] = {0}; - uint32_t addr = 0, val, timestamp = 0; + uint32_t addr = 0, val, clk = 25, timestamp = 0;
- while ((opt = getopt(argc, argv, "ho:i:s:m:")) != -1) { + while ((opt = getopt(argc, argv, "ho:i:s:m:c:")) != -1) { switch (opt) { case 'o': out_file = optarg; @@ -251,6 +251,9 @@ int main(int argc, char *argv[]) case 'i': in_file = optarg; break; + case 'c': + clk = atoi(optarg); + break; case 's': return snapshot(optarg); case 'h': @@ -299,7 +302,7 @@ convert:
if (addr >= MAILBOX_TRACE_OFFSET && addr < MAILBOX_TRACE_OFFSET + MAILBOX_TRACE_SIZE) - show_trace(val, addr, ×tamp); + show_trace(val, addr, ×tamp, clk); else if (addr >= MAILBOX_DEBUG_OFFSET && addr < MAILBOX_DEBUG_OFFSET + MAILBOX_DEBUG_SIZE) show_debug(val, addr);
participants (1)
-
Liam Girdwood