File Index
Files and directories
Sign in
FILE

motu-transaction.c

File preview with syntax highlighting.

linux-6.19.14/sound/firewire/motu/motu-transaction.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * motu-transaction.c - a part of driver for MOTU FireWire series
  4 *
  5 * Copyright (c) 2015-2017 Takashi Sakamoto <o-takashi@sakamocchi.jp>
  6 */
  7
  8
  9#include "motu.h"
 10
 11#define SND_MOTU_ADDR_BASE	0xfffff0000000ULL
 12#define ASYNC_ADDR_HI  0x0b04
 13#define ASYNC_ADDR_LO  0x0b08
 14
 15int snd_motu_transaction_read(struct snd_motu *motu, u32 offset, __be32 *reg,
 16			      size_t size)
 17{
 18	int tcode;
 19
 20	if (size % sizeof(__be32) > 0 || size <= 0)
 21		return -EINVAL;
 22	if (size == sizeof(__be32))
 23		tcode = TCODE_READ_QUADLET_REQUEST;
 24	else
 25		tcode = TCODE_READ_BLOCK_REQUEST;
 26
 27	return snd_fw_transaction(motu->unit, tcode,
 28				  SND_MOTU_ADDR_BASE + offset, reg, size, 0);
 29}
 30
 31int snd_motu_transaction_write(struct snd_motu *motu, u32 offset, __be32 *reg,
 32			       size_t size)
 33{
 34	int tcode;
 35
 36	if (size % sizeof(__be32) > 0 || size <= 0)
 37		return -EINVAL;
 38	if (size == sizeof(__be32))
 39		tcode = TCODE_WRITE_QUADLET_REQUEST;
 40	else
 41		tcode = TCODE_WRITE_BLOCK_REQUEST;
 42
 43	return snd_fw_transaction(motu->unit, tcode,
 44				  SND_MOTU_ADDR_BASE + offset, reg, size, 0);
 45}
 46
 47static void handle_message(struct fw_card *card, struct fw_request *request,
 48			   int tcode, int destination, int source,
 49			   int generation, unsigned long long offset,
 50			   void *data, size_t length, void *callback_data)
 51{
 52	struct snd_motu *motu = callback_data;
 53	__be32 *buf = (__be32 *)data;
 54
 55	if (tcode != TCODE_WRITE_QUADLET_REQUEST) {
 56		fw_send_response(card, request, RCODE_COMPLETE);
 57		return;
 58	}
 59
 60	if (offset != motu->async_handler.offset || length != 4) {
 61		fw_send_response(card, request, RCODE_ADDRESS_ERROR);
 62		return;
 63	}
 64
 65	scoped_guard(spinlock_irqsave, &motu->lock) {
 66		motu->msg = be32_to_cpu(*buf);
 67	}
 68
 69	fw_send_response(card, request, RCODE_COMPLETE);
 70
 71	wake_up(&motu->hwdep_wait);
 72}
 73
 74int snd_motu_transaction_reregister(struct snd_motu *motu)
 75{
 76	struct fw_device *device = fw_parent_device(motu->unit);
 77	__be32 data;
 78	int err;
 79
 80	if (motu->async_handler.callback_data == NULL)
 81		return -EINVAL;
 82
 83	/* Register messaging address. Block transaction is not allowed. */
 84	data = cpu_to_be32((device->card->node_id << 16) |
 85			   (motu->async_handler.offset >> 32));
 86	err = snd_motu_transaction_write(motu, ASYNC_ADDR_HI, &data,
 87					 sizeof(data));
 88	if (err < 0)
 89		return err;
 90
 91	data = cpu_to_be32(motu->async_handler.offset);
 92	return snd_motu_transaction_write(motu, ASYNC_ADDR_LO, &data,
 93					  sizeof(data));
 94}
 95
 96int snd_motu_transaction_register(struct snd_motu *motu)
 97{
 98	static const struct fw_address_region resp_register_region = {
 99		.start	= 0xffffe0000000ull,
100		.end	= 0xffffe000ffffull,
101	};
102	int err;
103
104	/* Perhaps, 4 byte messages are transferred. */
105	motu->async_handler.length = 4;
106	motu->async_handler.address_callback = handle_message;
107	motu->async_handler.callback_data = motu;
108
109	err = fw_core_add_address_handler(&motu->async_handler,
110					  &resp_register_region);
111	if (err < 0)
112		return err;
113
114	err = snd_motu_transaction_reregister(motu);
115	if (err < 0) {
116		fw_core_remove_address_handler(&motu->async_handler);
117		motu->async_handler.address_callback = NULL;
118	}
119
120	return err;
121}
122
123void snd_motu_transaction_unregister(struct snd_motu *motu)
124{
125	__be32 data;
126
127	if (motu->async_handler.address_callback != NULL)
128		fw_core_remove_address_handler(&motu->async_handler);
129	motu->async_handler.address_callback = NULL;
130
131	/* Unregister the address. */
132	data = cpu_to_be32(0x00000000);
133	snd_motu_transaction_write(motu, ASYNC_ADDR_HI, &data, sizeof(data));
134	snd_motu_transaction_write(motu, ASYNC_ADDR_LO, &data, sizeof(data));
135}
~/ Read-only file preview.