Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e2786ca6 authored by Takashi Sakamoto's avatar Takashi Sakamoto Committed by Takashi Iwai
Browse files

ALSA: oxfw: Split stream functionality to a new file and add a header file



This is a help for works in followed patches.

And this commit remove 'fw_unit_get()/fw_unit_put()' because these
are called by helper functions in 'snd-firewire-lib'.

Signed-off-by: default avatarTakashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 1a4e39c2
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
snd-oxfw-objs := oxfw.o
snd-oxfw-objs := oxfw-stream.o oxfw.o
obj-m += snd-oxfw.o
obj-m += snd-oxfw.o
+80 −0
Original line number Original line Diff line number Diff line
/*
 * oxfw_stream.c - a part of driver for OXFW970/971 based devices
 *
 * Copyright (c) 2014 Takashi Sakamoto
 *
 * Licensed under the terms of the GNU General Public License, version 2.
 */

#include "oxfw.h"

int snd_oxfw_stream_init_simplex(struct snd_oxfw *oxfw)
{
	int err;

	err = cmp_connection_init(&oxfw->in_conn, oxfw->unit,
				  CMP_INPUT, 0);
	if (err < 0)
		goto end;

	err = amdtp_stream_init(&oxfw->rx_stream, oxfw->unit,
				AMDTP_OUT_STREAM, CIP_NONBLOCKING);
	if (err < 0) {
		amdtp_stream_destroy(&oxfw->rx_stream);
		cmp_connection_destroy(&oxfw->in_conn);
	}
end:
	return err;
}

static void stop_stream(struct snd_oxfw *oxfw)
{
	amdtp_stream_pcm_abort(&oxfw->rx_stream);
	amdtp_stream_stop(&oxfw->rx_stream);
	cmp_connection_break(&oxfw->in_conn);
}

int snd_oxfw_stream_start_simplex(struct snd_oxfw *oxfw)
{
	int err = 0;

	if (amdtp_streaming_error(&oxfw->rx_stream))
		stop_stream(oxfw);

	if (amdtp_stream_running(&oxfw->rx_stream))
		goto end;

	err = cmp_connection_establish(&oxfw->in_conn,
			amdtp_stream_get_max_payload(&oxfw->rx_stream));
	if (err < 0)
		goto end;

	err = amdtp_stream_start(&oxfw->rx_stream,
				 oxfw->in_conn.resources.channel,
				 oxfw->in_conn.speed);
	if (err < 0)
		stop_stream(oxfw);
end:
	return err;
}

void snd_oxfw_stream_stop_simplex(struct snd_oxfw *oxfw)
{
	stop_stream(oxfw);
}

void snd_oxfw_stream_destroy_simplex(struct snd_oxfw *oxfw)
{
	stop_stream(oxfw);

	amdtp_stream_destroy(&oxfw->rx_stream);
	cmp_connection_destroy(&oxfw->in_conn);
}

void snd_oxfw_stream_update_simplex(struct snd_oxfw *oxfw)
{
	if (cmp_connection_update(&oxfw->in_conn) < 0)
		stop_stream(oxfw);
	else
		amdtp_stream_update(&oxfw->rx_stream);
}
+22 −108
Original line number Original line Diff line number Diff line
@@ -5,22 +5,7 @@
 * Licensed under the terms of the GNU General Public License, version 2.
 * Licensed under the terms of the GNU General Public License, version 2.
 */
 */


#include <linux/device.h>
#include "oxfw.h"
#include <linux/firewire.h>
#include <linux/firewire-constants.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/mutex.h>
#include <linux/slab.h>
#include <sound/control.h>
#include <sound/core.h>
#include <sound/initval.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include "../cmp.h"
#include "../fcp.h"
#include "../amdtp.h"
#include "../lib.h"


#define OXFORD_FIRMWARE_ID_ADDRESS	(CSR_REGISTER_BASE + 0x50000)
#define OXFORD_FIRMWARE_ID_ADDRESS	(CSR_REGISTER_BASE + 0x50000)
/* 0x970?vvvv or 0x971?vvvv, where vvvv = firmware version */
/* 0x970?vvvv or 0x971?vvvv, where vvvv = firmware version */
@@ -35,29 +20,6 @@
#define SPECIFIER_1394TA	0x00a02d
#define SPECIFIER_1394TA	0x00a02d
#define VERSION_AVC		0x010001
#define VERSION_AVC		0x010001


struct device_info {
	const char *driver_name;
	const char *short_name;
	const char *long_name;
	int (*pcm_constraints)(struct snd_pcm_runtime *runtime);
	unsigned int mixer_channels;
	u8 mute_fb_id;
	u8 volume_fb_id;
};

struct snd_oxfw {
	struct snd_card *card;
	struct fw_unit *unit;
	const struct device_info *device_info;
	struct mutex mutex;
	struct cmp_connection in_conn;
	struct amdtp_stream rx_stream;
	bool mute;
	s16 volume[6];
	s16 volume_min;
	s16 volume_max;
};

MODULE_DESCRIPTION("Oxford Semiconductor FW970/971 driver");
MODULE_DESCRIPTION("Oxford Semiconductor FW970/971 driver");
MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
MODULE_LICENSE("GPL v2");
MODULE_LICENSE("GPL v2");
@@ -180,14 +142,6 @@ static int oxfw_close(struct snd_pcm_substream *substream)
	return 0;
	return 0;
}
}


static void oxfw_stop_stream(struct snd_oxfw *oxfw)
{
	if (amdtp_stream_running(&oxfw->rx_stream)) {
		amdtp_stream_stop(&oxfw->rx_stream);
		cmp_connection_break(&oxfw->in_conn);
	}
}

static int oxfw_hw_params(struct snd_pcm_substream *substream,
static int oxfw_hw_params(struct snd_pcm_substream *substream,
			   struct snd_pcm_hw_params *hw_params)
			   struct snd_pcm_hw_params *hw_params)
{
{
@@ -195,8 +149,8 @@ static int oxfw_hw_params(struct snd_pcm_substream *substream,
	int err;
	int err;


	mutex_lock(&oxfw->mutex);
	mutex_lock(&oxfw->mutex);
	oxfw_stop_stream(oxfw);

	mutex_unlock(&oxfw->mutex);
	snd_oxfw_stream_stop_simplex(oxfw);


	err = snd_pcm_lib_alloc_vmalloc_buffer(substream,
	err = snd_pcm_lib_alloc_vmalloc_buffer(substream,
					       params_buffer_bytes(hw_params));
					       params_buffer_bytes(hw_params));
@@ -223,6 +177,7 @@ static int oxfw_hw_params(struct snd_pcm_substream *substream,
err_buffer:
err_buffer:
	snd_pcm_lib_free_vmalloc_buffer(substream);
	snd_pcm_lib_free_vmalloc_buffer(substream);
error:
error:
	mutex_unlock(&oxfw->mutex);
	return err;
	return err;
}
}


@@ -231,7 +186,7 @@ static int oxfw_hw_free(struct snd_pcm_substream *substream)
	struct snd_oxfw *oxfw = substream->private_data;
	struct snd_oxfw *oxfw = substream->private_data;


	mutex_lock(&oxfw->mutex);
	mutex_lock(&oxfw->mutex);
	oxfw_stop_stream(oxfw);
	snd_oxfw_stream_stop_simplex(oxfw);
	mutex_unlock(&oxfw->mutex);
	mutex_unlock(&oxfw->mutex);


	return snd_pcm_lib_free_vmalloc_buffer(substream);
	return snd_pcm_lib_free_vmalloc_buffer(substream);
@@ -244,33 +199,15 @@ static int oxfw_prepare(struct snd_pcm_substream *substream)


	mutex_lock(&oxfw->mutex);
	mutex_lock(&oxfw->mutex);


	if (amdtp_streaming_error(&oxfw->rx_stream))
	snd_oxfw_stream_stop_simplex(oxfw);
		oxfw_stop_stream(oxfw);

	if (!amdtp_stream_running(&oxfw->rx_stream)) {
		err = cmp_connection_establish(&oxfw->in_conn,
			amdtp_stream_get_max_payload(&oxfw->rx_stream));
		if (err < 0)
			goto err_mutex;


		err = amdtp_stream_start(&oxfw->rx_stream,
	err = snd_oxfw_stream_start_simplex(oxfw);
					 oxfw->in_conn.resources.channel,
					 oxfw->in_conn.speed);
	if (err < 0)
	if (err < 0)
			goto err_connection;
		goto end;
	}

	mutex_unlock(&oxfw->mutex);


	amdtp_stream_pcm_prepare(&oxfw->rx_stream);
	amdtp_stream_pcm_prepare(&oxfw->rx_stream);

end:
	return 0;

err_connection:
	cmp_connection_break(&oxfw->in_conn);
err_mutex:
	mutex_unlock(&oxfw->mutex);
	mutex_unlock(&oxfw->mutex);

	return err;
	return err;
}
}


@@ -615,9 +552,6 @@ static void oxfw_card_free(struct snd_card *card)
{
{
	struct snd_oxfw *oxfw = card->private_data;
	struct snd_oxfw *oxfw = card->private_data;


	amdtp_stream_destroy(&oxfw->rx_stream);
	cmp_connection_destroy(&oxfw->in_conn);
	fw_unit_put(oxfw->unit);
	mutex_destroy(&oxfw->mutex);
	mutex_destroy(&oxfw->mutex);
}
}


@@ -635,23 +569,13 @@ static int oxfw_probe(struct fw_unit *unit,
	if (err < 0)
	if (err < 0)
		return err;
		return err;


	card->private_free = oxfw_card_free;
	oxfw = card->private_data;
	oxfw = card->private_data;
	oxfw->card = card;
	oxfw->card = card;
	mutex_init(&oxfw->mutex);
	mutex_init(&oxfw->mutex);
	oxfw->unit = fw_unit_get(unit);
	oxfw->unit = unit;
	oxfw->device_info = (const struct device_info *)id->driver_data;
	oxfw->device_info = (const struct device_info *)id->driver_data;


	err = cmp_connection_init(&oxfw->in_conn, unit, CMP_INPUT, 0);
	if (err < 0)
		goto err_unit;

	err = amdtp_stream_init(&oxfw->rx_stream, unit, AMDTP_OUT_STREAM,
				CIP_NONBLOCKING);
	if (err < 0)
		goto err_connection;

	card->private_free = oxfw_card_free;

	strcpy(card->driver, oxfw->device_info->driver_name);
	strcpy(card->driver, oxfw->device_info->driver_name);
	strcpy(card->shortname, oxfw->device_info->short_name);
	strcpy(card->shortname, oxfw->device_info->short_name);
	firmware = oxfw_read_firmware_version(unit);
	firmware = oxfw_read_firmware_version(unit);
@@ -671,19 +595,18 @@ static int oxfw_probe(struct fw_unit *unit,
	if (err < 0)
	if (err < 0)
		goto error;
		goto error;


	err = snd_card_register(card);
	err = snd_oxfw_stream_init_simplex(oxfw);
	if (err < 0)
	if (err < 0)
		goto error;
		goto error;


	err = snd_card_register(card);
	if (err < 0) {
		snd_oxfw_stream_destroy_simplex(oxfw);
		goto error;
	}
	dev_set_drvdata(&unit->device, oxfw);
	dev_set_drvdata(&unit->device, oxfw);


	return 0;
	return 0;

err_connection:
	cmp_connection_destroy(&oxfw->in_conn);
err_unit:
	fw_unit_put(oxfw->unit);
	mutex_destroy(&oxfw->mutex);
error:
error:
	snd_card_free(card);
	snd_card_free(card);
	return err;
	return err;
@@ -695,27 +618,18 @@ static void oxfw_bus_reset(struct fw_unit *unit)


	fcp_bus_reset(oxfw->unit);
	fcp_bus_reset(oxfw->unit);


	if (cmp_connection_update(&oxfw->in_conn) < 0) {
		amdtp_stream_pcm_abort(&oxfw->rx_stream);
	mutex_lock(&oxfw->mutex);
	mutex_lock(&oxfw->mutex);
		oxfw_stop_stream(oxfw);
	snd_oxfw_stream_update_simplex(oxfw);
	mutex_unlock(&oxfw->mutex);
	mutex_unlock(&oxfw->mutex);
		return;
	}

	amdtp_stream_update(&oxfw->rx_stream);
}
}


static void oxfw_remove(struct fw_unit *unit)
static void oxfw_remove(struct fw_unit *unit)
{
{
	struct snd_oxfw *oxfw = dev_get_drvdata(&unit->device);
	struct snd_oxfw *oxfw = dev_get_drvdata(&unit->device);


	amdtp_stream_pcm_abort(&oxfw->rx_stream);
	snd_card_disconnect(oxfw->card);
	snd_card_disconnect(oxfw->card);


	mutex_lock(&oxfw->mutex);
	snd_oxfw_stream_destroy_simplex(oxfw);
	oxfw_stop_stream(oxfw);
	mutex_unlock(&oxfw->mutex);


	snd_card_free_when_closed(oxfw->card);
	snd_card_free_when_closed(oxfw->card);
}
}
+56 −0
Original line number Original line Diff line number Diff line
/*
 * oxfw.h - a part of driver for OXFW970/971 based devices
 *
 * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
 * Licensed under the terms of the GNU General Public License, version 2.
 */

#include <linux/device.h>
#include <linux/firewire.h>
#include <linux/firewire-constants.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/mutex.h>
#include <linux/slab.h>

#include <sound/control.h>
#include <sound/core.h>
#include <sound/initval.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>

#include "../lib.h"
#include "../fcp.h"
#include "../packets-buffer.h"
#include "../iso-resources.h"
#include "../amdtp.h"
#include "../cmp.h"

struct device_info {
	const char *driver_name;
	const char *short_name;
	const char *long_name;
	int (*pcm_constraints)(struct snd_pcm_runtime *runtime);
	unsigned int mixer_channels;
	u8 mute_fb_id;
	u8 volume_fb_id;
};

struct snd_oxfw {
	struct snd_card *card;
	struct fw_unit *unit;
	const struct device_info *device_info;
	struct mutex mutex;
	struct cmp_connection in_conn;
	struct amdtp_stream rx_stream;
	bool mute;
	s16 volume[6];
	s16 volume_min;
	s16 volume_max;
};

int snd_oxfw_stream_init_simplex(struct snd_oxfw *oxfw);
int snd_oxfw_stream_start_simplex(struct snd_oxfw *oxfw);
void snd_oxfw_stream_stop_simplex(struct snd_oxfw *oxfw);
void snd_oxfw_stream_destroy_simplex(struct snd_oxfw *oxfw);
void snd_oxfw_stream_update_simplex(struct snd_oxfw *oxfw);