18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * oxfw.h - a part of driver for OXFW970/971 based devices
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include <linux/device.h>
98c2ecf20Sopenharmony_ci#include <linux/firewire.h>
108c2ecf20Sopenharmony_ci#include <linux/firewire-constants.h>
118c2ecf20Sopenharmony_ci#include <linux/module.h>
128c2ecf20Sopenharmony_ci#include <linux/mod_devicetable.h>
138c2ecf20Sopenharmony_ci#include <linux/mutex.h>
148c2ecf20Sopenharmony_ci#include <linux/slab.h>
158c2ecf20Sopenharmony_ci#include <linux/compat.h>
168c2ecf20Sopenharmony_ci#include <linux/sched/signal.h>
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci#include <sound/control.h>
198c2ecf20Sopenharmony_ci#include <sound/core.h>
208c2ecf20Sopenharmony_ci#include <sound/initval.h>
218c2ecf20Sopenharmony_ci#include <sound/pcm.h>
228c2ecf20Sopenharmony_ci#include <sound/pcm_params.h>
238c2ecf20Sopenharmony_ci#include <sound/info.h>
248c2ecf20Sopenharmony_ci#include <sound/rawmidi.h>
258c2ecf20Sopenharmony_ci#include <sound/firewire.h>
268c2ecf20Sopenharmony_ci#include <sound/hwdep.h>
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci#include "../lib.h"
298c2ecf20Sopenharmony_ci#include "../fcp.h"
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
358c2ecf20Sopenharmony_ci/* This is an arbitrary number for convinience. */
368c2ecf20Sopenharmony_ci#define	SND_OXFW_STREAM_FORMAT_ENTRIES	10
378c2ecf20Sopenharmony_cistruct snd_oxfw {
388c2ecf20Sopenharmony_ci	struct snd_card *card;
398c2ecf20Sopenharmony_ci	struct fw_unit *unit;
408c2ecf20Sopenharmony_ci	struct mutex mutex;
418c2ecf20Sopenharmony_ci	spinlock_t lock;
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci	bool registered;
448c2ecf20Sopenharmony_ci	struct delayed_work dwork;
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci	bool wrong_dbs;
478c2ecf20Sopenharmony_ci	bool has_output;
488c2ecf20Sopenharmony_ci	bool has_input;
498c2ecf20Sopenharmony_ci	u8 *tx_stream_formats[SND_OXFW_STREAM_FORMAT_ENTRIES];
508c2ecf20Sopenharmony_ci	u8 *rx_stream_formats[SND_OXFW_STREAM_FORMAT_ENTRIES];
518c2ecf20Sopenharmony_ci	bool assumed;
528c2ecf20Sopenharmony_ci	struct cmp_connection out_conn;
538c2ecf20Sopenharmony_ci	struct cmp_connection in_conn;
548c2ecf20Sopenharmony_ci	struct amdtp_stream tx_stream;
558c2ecf20Sopenharmony_ci	struct amdtp_stream rx_stream;
568c2ecf20Sopenharmony_ci	unsigned int substreams_count;
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci	unsigned int midi_input_ports;
598c2ecf20Sopenharmony_ci	unsigned int midi_output_ports;
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci	int dev_lock_count;
628c2ecf20Sopenharmony_ci	bool dev_lock_changed;
638c2ecf20Sopenharmony_ci	wait_queue_head_t hwdep_wait;
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ci	const struct ieee1394_device_id *entry;
668c2ecf20Sopenharmony_ci	void *spec;
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_ci	struct amdtp_domain domain;
698c2ecf20Sopenharmony_ci};
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ci/*
728c2ecf20Sopenharmony_ci * AV/C Stream Format Information Specification 1.1 Working Draft
738c2ecf20Sopenharmony_ci * (Apr 2005, 1394TA)
748c2ecf20Sopenharmony_ci */
758c2ecf20Sopenharmony_ciint avc_stream_set_format(struct fw_unit *unit, enum avc_general_plug_dir dir,
768c2ecf20Sopenharmony_ci			  unsigned int pid, u8 *format, unsigned int len);
778c2ecf20Sopenharmony_ciint avc_stream_get_format(struct fw_unit *unit,
788c2ecf20Sopenharmony_ci			  enum avc_general_plug_dir dir, unsigned int pid,
798c2ecf20Sopenharmony_ci			  u8 *buf, unsigned int *len, unsigned int eid);
808c2ecf20Sopenharmony_cistatic inline int
818c2ecf20Sopenharmony_ciavc_stream_get_format_single(struct fw_unit *unit,
828c2ecf20Sopenharmony_ci			     enum avc_general_plug_dir dir, unsigned int pid,
838c2ecf20Sopenharmony_ci			     u8 *buf, unsigned int *len)
848c2ecf20Sopenharmony_ci{
858c2ecf20Sopenharmony_ci	return avc_stream_get_format(unit, dir, pid, buf, len, 0xff);
868c2ecf20Sopenharmony_ci}
878c2ecf20Sopenharmony_cistatic inline int
888c2ecf20Sopenharmony_ciavc_stream_get_format_list(struct fw_unit *unit,
898c2ecf20Sopenharmony_ci			   enum avc_general_plug_dir dir, unsigned int pid,
908c2ecf20Sopenharmony_ci			   u8 *buf, unsigned int *len,
918c2ecf20Sopenharmony_ci			   unsigned int eid)
928c2ecf20Sopenharmony_ci{
938c2ecf20Sopenharmony_ci	return avc_stream_get_format(unit, dir, pid, buf, len, eid);
948c2ecf20Sopenharmony_ci}
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ci/*
978c2ecf20Sopenharmony_ci * AV/C Digital Interface Command Set General Specification 4.2
988c2ecf20Sopenharmony_ci * (Sep 2004, 1394TA)
998c2ecf20Sopenharmony_ci */
1008c2ecf20Sopenharmony_ciint avc_general_inquiry_sig_fmt(struct fw_unit *unit, unsigned int rate,
1018c2ecf20Sopenharmony_ci				enum avc_general_plug_dir dir,
1028c2ecf20Sopenharmony_ci				unsigned short pid);
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_ciint snd_oxfw_stream_init_duplex(struct snd_oxfw *oxfw);
1058c2ecf20Sopenharmony_ciint snd_oxfw_stream_reserve_duplex(struct snd_oxfw *oxfw,
1068c2ecf20Sopenharmony_ci				   struct amdtp_stream *stream,
1078c2ecf20Sopenharmony_ci				   unsigned int rate, unsigned int pcm_channels,
1088c2ecf20Sopenharmony_ci				   unsigned int frames_per_period,
1098c2ecf20Sopenharmony_ci				   unsigned int frames_per_buffer);
1108c2ecf20Sopenharmony_ciint snd_oxfw_stream_start_duplex(struct snd_oxfw *oxfw);
1118c2ecf20Sopenharmony_civoid snd_oxfw_stream_stop_duplex(struct snd_oxfw *oxfw);
1128c2ecf20Sopenharmony_civoid snd_oxfw_stream_destroy_duplex(struct snd_oxfw *oxfw);
1138c2ecf20Sopenharmony_civoid snd_oxfw_stream_update_duplex(struct snd_oxfw *oxfw);
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_cistruct snd_oxfw_stream_formation {
1168c2ecf20Sopenharmony_ci	unsigned int rate;
1178c2ecf20Sopenharmony_ci	unsigned int pcm;
1188c2ecf20Sopenharmony_ci	unsigned int midi;
1198c2ecf20Sopenharmony_ci};
1208c2ecf20Sopenharmony_ciint snd_oxfw_stream_parse_format(u8 *format,
1218c2ecf20Sopenharmony_ci				 struct snd_oxfw_stream_formation *formation);
1228c2ecf20Sopenharmony_ciint snd_oxfw_stream_get_current_formation(struct snd_oxfw *oxfw,
1238c2ecf20Sopenharmony_ci				enum avc_general_plug_dir dir,
1248c2ecf20Sopenharmony_ci				struct snd_oxfw_stream_formation *formation);
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_ciint snd_oxfw_stream_discover(struct snd_oxfw *oxfw);
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_civoid snd_oxfw_stream_lock_changed(struct snd_oxfw *oxfw);
1298c2ecf20Sopenharmony_ciint snd_oxfw_stream_lock_try(struct snd_oxfw *oxfw);
1308c2ecf20Sopenharmony_civoid snd_oxfw_stream_lock_release(struct snd_oxfw *oxfw);
1318c2ecf20Sopenharmony_ci
1328c2ecf20Sopenharmony_ciint snd_oxfw_create_pcm(struct snd_oxfw *oxfw);
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_civoid snd_oxfw_proc_init(struct snd_oxfw *oxfw);
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_ciint snd_oxfw_create_midi(struct snd_oxfw *oxfw);
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_ciint snd_oxfw_create_hwdep(struct snd_oxfw *oxfw);
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_ciint snd_oxfw_add_spkr(struct snd_oxfw *oxfw, bool is_lacie);
1418c2ecf20Sopenharmony_ciint snd_oxfw_scs1x_add(struct snd_oxfw *oxfw);
1428c2ecf20Sopenharmony_civoid snd_oxfw_scs1x_update(struct snd_oxfw *oxfw);
143