18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Driver for Digigram VX soundcards 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * DSP firmware management 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de> 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/device.h> 118c2ecf20Sopenharmony_ci#include <linux/firmware.h> 128c2ecf20Sopenharmony_ci#include <linux/slab.h> 138c2ecf20Sopenharmony_ci#include <linux/vmalloc.h> 148c2ecf20Sopenharmony_ci#include <linux/module.h> 158c2ecf20Sopenharmony_ci#include <sound/core.h> 168c2ecf20Sopenharmony_ci#include <sound/hwdep.h> 178c2ecf20Sopenharmony_ci#include <sound/vx_core.h> 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ciMODULE_FIRMWARE("vx/bx_1_vxp.b56"); 208c2ecf20Sopenharmony_ciMODULE_FIRMWARE("vx/bx_1_vp4.b56"); 218c2ecf20Sopenharmony_ciMODULE_FIRMWARE("vx/x1_1_vx2.xlx"); 228c2ecf20Sopenharmony_ciMODULE_FIRMWARE("vx/x1_2_v22.xlx"); 238c2ecf20Sopenharmony_ciMODULE_FIRMWARE("vx/x1_1_vxp.xlx"); 248c2ecf20Sopenharmony_ciMODULE_FIRMWARE("vx/x1_1_vp4.xlx"); 258c2ecf20Sopenharmony_ciMODULE_FIRMWARE("vx/bd56002.boot"); 268c2ecf20Sopenharmony_ciMODULE_FIRMWARE("vx/bd563v2.boot"); 278c2ecf20Sopenharmony_ciMODULE_FIRMWARE("vx/bd563s3.boot"); 288c2ecf20Sopenharmony_ciMODULE_FIRMWARE("vx/l_1_vx2.d56"); 298c2ecf20Sopenharmony_ciMODULE_FIRMWARE("vx/l_1_v22.d56"); 308c2ecf20Sopenharmony_ciMODULE_FIRMWARE("vx/l_1_vxp.d56"); 318c2ecf20Sopenharmony_ciMODULE_FIRMWARE("vx/l_1_vp4.d56"); 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ciint snd_vx_setup_firmware(struct vx_core *chip) 348c2ecf20Sopenharmony_ci{ 358c2ecf20Sopenharmony_ci static const char * const fw_files[VX_TYPE_NUMS][4] = { 368c2ecf20Sopenharmony_ci [VX_TYPE_BOARD] = { 378c2ecf20Sopenharmony_ci NULL, "x1_1_vx2.xlx", "bd56002.boot", "l_1_vx2.d56", 388c2ecf20Sopenharmony_ci }, 398c2ecf20Sopenharmony_ci [VX_TYPE_V2] = { 408c2ecf20Sopenharmony_ci NULL, "x1_2_v22.xlx", "bd563v2.boot", "l_1_v22.d56", 418c2ecf20Sopenharmony_ci }, 428c2ecf20Sopenharmony_ci [VX_TYPE_MIC] = { 438c2ecf20Sopenharmony_ci NULL, "x1_2_v22.xlx", "bd563v2.boot", "l_1_v22.d56", 448c2ecf20Sopenharmony_ci }, 458c2ecf20Sopenharmony_ci [VX_TYPE_VXPOCKET] = { 468c2ecf20Sopenharmony_ci "bx_1_vxp.b56", "x1_1_vxp.xlx", "bd563s3.boot", "l_1_vxp.d56" 478c2ecf20Sopenharmony_ci }, 488c2ecf20Sopenharmony_ci [VX_TYPE_VXP440] = { 498c2ecf20Sopenharmony_ci "bx_1_vp4.b56", "x1_1_vp4.xlx", "bd563s3.boot", "l_1_vp4.d56" 508c2ecf20Sopenharmony_ci }, 518c2ecf20Sopenharmony_ci }; 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci int i, err; 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci for (i = 0; i < 4; i++) { 568c2ecf20Sopenharmony_ci char path[32]; 578c2ecf20Sopenharmony_ci const struct firmware *fw; 588c2ecf20Sopenharmony_ci if (! fw_files[chip->type][i]) 598c2ecf20Sopenharmony_ci continue; 608c2ecf20Sopenharmony_ci sprintf(path, "vx/%s", fw_files[chip->type][i]); 618c2ecf20Sopenharmony_ci if (request_firmware(&fw, path, chip->dev)) { 628c2ecf20Sopenharmony_ci snd_printk(KERN_ERR "vx: can't load firmware %s\n", path); 638c2ecf20Sopenharmony_ci return -ENOENT; 648c2ecf20Sopenharmony_ci } 658c2ecf20Sopenharmony_ci err = chip->ops->load_dsp(chip, i, fw); 668c2ecf20Sopenharmony_ci if (err < 0) { 678c2ecf20Sopenharmony_ci release_firmware(fw); 688c2ecf20Sopenharmony_ci return err; 698c2ecf20Sopenharmony_ci } 708c2ecf20Sopenharmony_ci if (i == 1) 718c2ecf20Sopenharmony_ci chip->chip_status |= VX_STAT_XILINX_LOADED; 728c2ecf20Sopenharmony_ci#ifdef CONFIG_PM 738c2ecf20Sopenharmony_ci chip->firmware[i] = fw; 748c2ecf20Sopenharmony_ci#else 758c2ecf20Sopenharmony_ci release_firmware(fw); 768c2ecf20Sopenharmony_ci#endif 778c2ecf20Sopenharmony_ci } 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci /* ok, we reached to the last one */ 808c2ecf20Sopenharmony_ci /* create the devices if not built yet */ 818c2ecf20Sopenharmony_ci if ((err = snd_vx_pcm_new(chip)) < 0) 828c2ecf20Sopenharmony_ci return err; 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci if ((err = snd_vx_mixer_new(chip)) < 0) 858c2ecf20Sopenharmony_ci return err; 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci if (chip->ops->add_controls) 888c2ecf20Sopenharmony_ci if ((err = chip->ops->add_controls(chip)) < 0) 898c2ecf20Sopenharmony_ci return err; 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci chip->chip_status |= VX_STAT_DEVICE_INIT; 928c2ecf20Sopenharmony_ci chip->chip_status |= VX_STAT_CHIP_INIT; 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci return snd_card_register(chip->card); 958c2ecf20Sopenharmony_ci} 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci/* exported */ 988c2ecf20Sopenharmony_civoid snd_vx_free_firmware(struct vx_core *chip) 998c2ecf20Sopenharmony_ci{ 1008c2ecf20Sopenharmony_ci#ifdef CONFIG_PM 1018c2ecf20Sopenharmony_ci int i; 1028c2ecf20Sopenharmony_ci for (i = 0; i < 4; i++) 1038c2ecf20Sopenharmony_ci release_firmware(chip->firmware[i]); 1048c2ecf20Sopenharmony_ci#endif 1058c2ecf20Sopenharmony_ci} 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ciEXPORT_SYMBOL(snd_vx_setup_firmware); 1088c2ecf20Sopenharmony_ciEXPORT_SYMBOL(snd_vx_free_firmware); 109