18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * fireworks.h - a part of driver for Fireworks based devices 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (c) 2009-2010 Clemens Ladisch 68c2ecf20Sopenharmony_ci * Copyright (c) 2013-2014 Takashi Sakamoto 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci#ifndef SOUND_FIREWORKS_H_INCLUDED 98c2ecf20Sopenharmony_ci#define SOUND_FIREWORKS_H_INCLUDED 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <linux/compat.h> 128c2ecf20Sopenharmony_ci#include <linux/device.h> 138c2ecf20Sopenharmony_ci#include <linux/firewire.h> 148c2ecf20Sopenharmony_ci#include <linux/firewire-constants.h> 158c2ecf20Sopenharmony_ci#include <linux/module.h> 168c2ecf20Sopenharmony_ci#include <linux/mod_devicetable.h> 178c2ecf20Sopenharmony_ci#include <linux/delay.h> 188c2ecf20Sopenharmony_ci#include <linux/slab.h> 198c2ecf20Sopenharmony_ci#include <linux/sched/signal.h> 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci#include <sound/core.h> 228c2ecf20Sopenharmony_ci#include <sound/initval.h> 238c2ecf20Sopenharmony_ci#include <sound/pcm.h> 248c2ecf20Sopenharmony_ci#include <sound/info.h> 258c2ecf20Sopenharmony_ci#include <sound/rawmidi.h> 268c2ecf20Sopenharmony_ci#include <sound/pcm_params.h> 278c2ecf20Sopenharmony_ci#include <sound/firewire.h> 288c2ecf20Sopenharmony_ci#include <sound/hwdep.h> 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci#include "../packets-buffer.h" 318c2ecf20Sopenharmony_ci#include "../iso-resources.h" 328c2ecf20Sopenharmony_ci#include "../amdtp-am824.h" 338c2ecf20Sopenharmony_ci#include "../cmp.h" 348c2ecf20Sopenharmony_ci#include "../lib.h" 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci#define SND_EFW_MAX_MIDI_OUT_PORTS 2 378c2ecf20Sopenharmony_ci#define SND_EFW_MAX_MIDI_IN_PORTS 2 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci#define SND_EFW_MULTIPLIER_MODES 3 408c2ecf20Sopenharmony_ci#define HWINFO_NAME_SIZE_BYTES 32 418c2ecf20Sopenharmony_ci#define HWINFO_MAX_CAPS_GROUPS 8 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci/* 448c2ecf20Sopenharmony_ci * This should be greater than maximum bytes for EFW response content. 458c2ecf20Sopenharmony_ci * Currently response against command for isochronous channel mapping is 468c2ecf20Sopenharmony_ci * confirmed to be the maximum one. But for flexibility, use maximum data 478c2ecf20Sopenharmony_ci * payload for asynchronous primary packets at S100 (Cable base rate) in 488c2ecf20Sopenharmony_ci * IEEE Std 1394-1995. 498c2ecf20Sopenharmony_ci */ 508c2ecf20Sopenharmony_ci#define SND_EFW_RESPONSE_MAXIMUM_BYTES 0x200U 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ciextern unsigned int snd_efw_resp_buf_size; 538c2ecf20Sopenharmony_ciextern bool snd_efw_resp_buf_debug; 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_cistruct snd_efw_phys_grp { 568c2ecf20Sopenharmony_ci u8 type; /* see enum snd_efw_grp_type */ 578c2ecf20Sopenharmony_ci u8 count; 588c2ecf20Sopenharmony_ci} __packed; 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_cistruct snd_efw { 618c2ecf20Sopenharmony_ci struct snd_card *card; 628c2ecf20Sopenharmony_ci struct fw_unit *unit; 638c2ecf20Sopenharmony_ci int card_index; 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci struct mutex mutex; 668c2ecf20Sopenharmony_ci spinlock_t lock; 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci bool registered; 698c2ecf20Sopenharmony_ci struct delayed_work dwork; 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci /* for transaction */ 728c2ecf20Sopenharmony_ci u32 seqnum; 738c2ecf20Sopenharmony_ci bool resp_addr_changable; 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci /* for quirks */ 768c2ecf20Sopenharmony_ci bool is_af9; 778c2ecf20Sopenharmony_ci bool is_fireworks3; 788c2ecf20Sopenharmony_ci u32 firmware_version; 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci unsigned int midi_in_ports; 818c2ecf20Sopenharmony_ci unsigned int midi_out_ports; 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci unsigned int supported_sampling_rate; 848c2ecf20Sopenharmony_ci unsigned int pcm_capture_channels[SND_EFW_MULTIPLIER_MODES]; 858c2ecf20Sopenharmony_ci unsigned int pcm_playback_channels[SND_EFW_MULTIPLIER_MODES]; 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci struct amdtp_stream tx_stream; 888c2ecf20Sopenharmony_ci struct amdtp_stream rx_stream; 898c2ecf20Sopenharmony_ci struct cmp_connection out_conn; 908c2ecf20Sopenharmony_ci struct cmp_connection in_conn; 918c2ecf20Sopenharmony_ci unsigned int substreams_counter; 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci /* hardware metering parameters */ 948c2ecf20Sopenharmony_ci unsigned int phys_out; 958c2ecf20Sopenharmony_ci unsigned int phys_in; 968c2ecf20Sopenharmony_ci unsigned int phys_out_grp_count; 978c2ecf20Sopenharmony_ci unsigned int phys_in_grp_count; 988c2ecf20Sopenharmony_ci struct snd_efw_phys_grp phys_out_grps[HWINFO_MAX_CAPS_GROUPS]; 998c2ecf20Sopenharmony_ci struct snd_efw_phys_grp phys_in_grps[HWINFO_MAX_CAPS_GROUPS]; 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci /* for uapi */ 1028c2ecf20Sopenharmony_ci int dev_lock_count; 1038c2ecf20Sopenharmony_ci bool dev_lock_changed; 1048c2ecf20Sopenharmony_ci wait_queue_head_t hwdep_wait; 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci /* response queue */ 1078c2ecf20Sopenharmony_ci u8 *resp_buf; 1088c2ecf20Sopenharmony_ci u8 *pull_ptr; 1098c2ecf20Sopenharmony_ci u8 *push_ptr; 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci struct amdtp_domain domain; 1128c2ecf20Sopenharmony_ci}; 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ciint snd_efw_transaction_cmd(struct fw_unit *unit, 1158c2ecf20Sopenharmony_ci const void *cmd, unsigned int size); 1168c2ecf20Sopenharmony_ciint snd_efw_transaction_run(struct fw_unit *unit, 1178c2ecf20Sopenharmony_ci const void *cmd, unsigned int cmd_size, 1188c2ecf20Sopenharmony_ci void *resp, unsigned int resp_size); 1198c2ecf20Sopenharmony_ciint snd_efw_transaction_register(void); 1208c2ecf20Sopenharmony_civoid snd_efw_transaction_unregister(void); 1218c2ecf20Sopenharmony_civoid snd_efw_transaction_bus_reset(struct fw_unit *unit); 1228c2ecf20Sopenharmony_civoid snd_efw_transaction_add_instance(struct snd_efw *efw); 1238c2ecf20Sopenharmony_civoid snd_efw_transaction_remove_instance(struct snd_efw *efw); 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_cistruct snd_efw_hwinfo { 1268c2ecf20Sopenharmony_ci u32 flags; 1278c2ecf20Sopenharmony_ci u32 guid_hi; 1288c2ecf20Sopenharmony_ci u32 guid_lo; 1298c2ecf20Sopenharmony_ci u32 type; 1308c2ecf20Sopenharmony_ci u32 version; 1318c2ecf20Sopenharmony_ci char vendor_name[HWINFO_NAME_SIZE_BYTES]; 1328c2ecf20Sopenharmony_ci char model_name[HWINFO_NAME_SIZE_BYTES]; 1338c2ecf20Sopenharmony_ci u32 supported_clocks; 1348c2ecf20Sopenharmony_ci u32 amdtp_rx_pcm_channels; 1358c2ecf20Sopenharmony_ci u32 amdtp_tx_pcm_channels; 1368c2ecf20Sopenharmony_ci u32 phys_out; 1378c2ecf20Sopenharmony_ci u32 phys_in; 1388c2ecf20Sopenharmony_ci u32 phys_out_grp_count; 1398c2ecf20Sopenharmony_ci struct snd_efw_phys_grp phys_out_grps[HWINFO_MAX_CAPS_GROUPS]; 1408c2ecf20Sopenharmony_ci u32 phys_in_grp_count; 1418c2ecf20Sopenharmony_ci struct snd_efw_phys_grp phys_in_grps[HWINFO_MAX_CAPS_GROUPS]; 1428c2ecf20Sopenharmony_ci u32 midi_out_ports; 1438c2ecf20Sopenharmony_ci u32 midi_in_ports; 1448c2ecf20Sopenharmony_ci u32 max_sample_rate; 1458c2ecf20Sopenharmony_ci u32 min_sample_rate; 1468c2ecf20Sopenharmony_ci u32 dsp_version; 1478c2ecf20Sopenharmony_ci u32 arm_version; 1488c2ecf20Sopenharmony_ci u32 mixer_playback_channels; 1498c2ecf20Sopenharmony_ci u32 mixer_capture_channels; 1508c2ecf20Sopenharmony_ci u32 fpga_version; 1518c2ecf20Sopenharmony_ci u32 amdtp_rx_pcm_channels_2x; 1528c2ecf20Sopenharmony_ci u32 amdtp_tx_pcm_channels_2x; 1538c2ecf20Sopenharmony_ci u32 amdtp_rx_pcm_channels_4x; 1548c2ecf20Sopenharmony_ci u32 amdtp_tx_pcm_channels_4x; 1558c2ecf20Sopenharmony_ci u32 reserved[16]; 1568c2ecf20Sopenharmony_ci} __packed; 1578c2ecf20Sopenharmony_cienum snd_efw_grp_type { 1588c2ecf20Sopenharmony_ci SND_EFW_CH_TYPE_ANALOG = 0, 1598c2ecf20Sopenharmony_ci SND_EFW_CH_TYPE_SPDIF = 1, 1608c2ecf20Sopenharmony_ci SND_EFW_CH_TYPE_ADAT = 2, 1618c2ecf20Sopenharmony_ci SND_EFW_CH_TYPE_SPDIF_OR_ADAT = 3, 1628c2ecf20Sopenharmony_ci SND_EFW_CH_TYPE_ANALOG_MIRRORING = 4, 1638c2ecf20Sopenharmony_ci SND_EFW_CH_TYPE_HEADPHONES = 5, 1648c2ecf20Sopenharmony_ci SND_EFW_CH_TYPE_I2S = 6, 1658c2ecf20Sopenharmony_ci SND_EFW_CH_TYPE_GUITAR = 7, 1668c2ecf20Sopenharmony_ci SND_EFW_CH_TYPE_PIEZO_GUITAR = 8, 1678c2ecf20Sopenharmony_ci SND_EFW_CH_TYPE_GUITAR_STRING = 9, 1688c2ecf20Sopenharmony_ci SND_EFW_CH_TYPE_DUMMY 1698c2ecf20Sopenharmony_ci}; 1708c2ecf20Sopenharmony_cistruct snd_efw_phys_meters { 1718c2ecf20Sopenharmony_ci u32 status; /* guitar state/midi signal/clock input detect */ 1728c2ecf20Sopenharmony_ci u32 reserved0; 1738c2ecf20Sopenharmony_ci u32 reserved1; 1748c2ecf20Sopenharmony_ci u32 reserved2; 1758c2ecf20Sopenharmony_ci u32 reserved3; 1768c2ecf20Sopenharmony_ci u32 out_meters; 1778c2ecf20Sopenharmony_ci u32 in_meters; 1788c2ecf20Sopenharmony_ci u32 reserved4; 1798c2ecf20Sopenharmony_ci u32 reserved5; 1808c2ecf20Sopenharmony_ci u32 values[]; 1818c2ecf20Sopenharmony_ci} __packed; 1828c2ecf20Sopenharmony_cienum snd_efw_clock_source { 1838c2ecf20Sopenharmony_ci SND_EFW_CLOCK_SOURCE_INTERNAL = 0, 1848c2ecf20Sopenharmony_ci SND_EFW_CLOCK_SOURCE_SYTMATCH = 1, 1858c2ecf20Sopenharmony_ci SND_EFW_CLOCK_SOURCE_WORDCLOCK = 2, 1868c2ecf20Sopenharmony_ci SND_EFW_CLOCK_SOURCE_SPDIF = 3, 1878c2ecf20Sopenharmony_ci SND_EFW_CLOCK_SOURCE_ADAT_1 = 4, 1888c2ecf20Sopenharmony_ci SND_EFW_CLOCK_SOURCE_ADAT_2 = 5, 1898c2ecf20Sopenharmony_ci SND_EFW_CLOCK_SOURCE_CONTINUOUS = 6 /* internal variable clock */ 1908c2ecf20Sopenharmony_ci}; 1918c2ecf20Sopenharmony_cienum snd_efw_transport_mode { 1928c2ecf20Sopenharmony_ci SND_EFW_TRANSPORT_MODE_WINDOWS = 0, 1938c2ecf20Sopenharmony_ci SND_EFW_TRANSPORT_MODE_IEC61883 = 1, 1948c2ecf20Sopenharmony_ci}; 1958c2ecf20Sopenharmony_ciint snd_efw_command_set_resp_addr(struct snd_efw *efw, 1968c2ecf20Sopenharmony_ci u16 addr_high, u32 addr_low); 1978c2ecf20Sopenharmony_ciint snd_efw_command_set_tx_mode(struct snd_efw *efw, 1988c2ecf20Sopenharmony_ci enum snd_efw_transport_mode mode); 1998c2ecf20Sopenharmony_ciint snd_efw_command_get_hwinfo(struct snd_efw *efw, 2008c2ecf20Sopenharmony_ci struct snd_efw_hwinfo *hwinfo); 2018c2ecf20Sopenharmony_ciint snd_efw_command_get_phys_meters(struct snd_efw *efw, 2028c2ecf20Sopenharmony_ci struct snd_efw_phys_meters *meters, 2038c2ecf20Sopenharmony_ci unsigned int len); 2048c2ecf20Sopenharmony_ciint snd_efw_command_get_clock_source(struct snd_efw *efw, 2058c2ecf20Sopenharmony_ci enum snd_efw_clock_source *source); 2068c2ecf20Sopenharmony_ciint snd_efw_command_get_sampling_rate(struct snd_efw *efw, unsigned int *rate); 2078c2ecf20Sopenharmony_ciint snd_efw_command_set_sampling_rate(struct snd_efw *efw, unsigned int rate); 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ciint snd_efw_stream_init_duplex(struct snd_efw *efw); 2108c2ecf20Sopenharmony_ciint snd_efw_stream_reserve_duplex(struct snd_efw *efw, unsigned int rate, 2118c2ecf20Sopenharmony_ci unsigned int frames_per_period, 2128c2ecf20Sopenharmony_ci unsigned int frames_per_buffer); 2138c2ecf20Sopenharmony_ciint snd_efw_stream_start_duplex(struct snd_efw *efw); 2148c2ecf20Sopenharmony_civoid snd_efw_stream_stop_duplex(struct snd_efw *efw); 2158c2ecf20Sopenharmony_civoid snd_efw_stream_update_duplex(struct snd_efw *efw); 2168c2ecf20Sopenharmony_civoid snd_efw_stream_destroy_duplex(struct snd_efw *efw); 2178c2ecf20Sopenharmony_civoid snd_efw_stream_lock_changed(struct snd_efw *efw); 2188c2ecf20Sopenharmony_ciint snd_efw_stream_lock_try(struct snd_efw *efw); 2198c2ecf20Sopenharmony_civoid snd_efw_stream_lock_release(struct snd_efw *efw); 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_civoid snd_efw_proc_init(struct snd_efw *efw); 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ciint snd_efw_create_midi_devices(struct snd_efw *efw); 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ciint snd_efw_create_pcm_devices(struct snd_efw *efw); 2268c2ecf20Sopenharmony_ciint snd_efw_get_multiplier_mode(unsigned int sampling_rate, unsigned int *mode); 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ciint snd_efw_create_hwdep_device(struct snd_efw *efw); 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ci#define SND_EFW_DEV_ENTRY(vendor, model) \ 2318c2ecf20Sopenharmony_ci{ \ 2328c2ecf20Sopenharmony_ci .match_flags = IEEE1394_MATCH_VENDOR_ID | \ 2338c2ecf20Sopenharmony_ci IEEE1394_MATCH_MODEL_ID, \ 2348c2ecf20Sopenharmony_ci .vendor_id = vendor,\ 2358c2ecf20Sopenharmony_ci .model_id = model \ 2368c2ecf20Sopenharmony_ci} 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci#endif 239