2011-09-05 04:04:49 +08:00
|
|
|
/*
|
|
|
|
* TC Applied Technologies Digital Interface Communications Engine driver
|
|
|
|
*
|
|
|
|
* Copyright (c) Clemens Ladisch <clemens@ladisch.de>
|
|
|
|
* Licensed under the terms of the GNU General Public License, version 2.
|
|
|
|
*/
|
|
|
|
|
ALSA: dice: Split transaction functionality into a file
This commit adds a file with some helper functions for transaction, and move
some codes into the file with some arrangements.
For Dice chipset, well-known FCP or AV/C commands are not used to control
devices. It's achieved by read/write transactions into specific addresses.
Dice's address area is split into 5 areas. Each area has its own role. The
offset for each area can be got by reading head of the address area. By
reading these areas, drivers can get to know device status. By writing these
areas, drivers can change device status.
Dice has a specific mechanism called as 'notification'. When device status is
changed, Dice devices tells the event by sending transaction. This notification
is sent to an address which drivers register in advance. But this causes an
issue to drivers.
To handle the notification, drivers need to allocate its own callback function
to the address region in host controller. This region is exclusive. For the
other applications, drivers must give a mechanism to read the received
notification. For this purpose, Dice driver already implements hwdep interface.
Dice chipset doesn't allow drivers to register several addresses. In this
reason, when this driver is applied to a device, the other drivers should
_not_ try to register its own address to the device.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2014-11-28 23:59:13 +08:00
|
|
|
#include "dice.h"
|
2011-09-05 04:04:49 +08:00
|
|
|
|
|
|
|
MODULE_DESCRIPTION("DICE driver");
|
|
|
|
MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
|
|
|
|
MODULE_LICENSE("GPL v2");
|
|
|
|
|
2012-02-14 04:55:13 +08:00
|
|
|
#define OUI_WEISS 0x001c6a
|
2015-11-14 15:42:04 +08:00
|
|
|
#define OUI_LOUD 0x000ff2
|
2012-02-14 04:55:13 +08:00
|
|
|
|
|
|
|
#define DICE_CATEGORY_ID 0x04
|
|
|
|
#define WEISS_CATEGORY_ID 0x00
|
2015-11-14 15:42:04 +08:00
|
|
|
#define LOUD_CATEGORY_ID 0x10
|
2011-09-05 04:16:02 +08:00
|
|
|
|
ALSA: dice: postpone card registration
Some models based on ASIC for Dice II series (STD, CP) change their
hardware configurations after appearing on IEEE 1394 bus. This is due to
interactions of boot loader (RedBoot), firmwares (eCos) and vendor's
configurations. This causes current ALSA dice driver to get wrong
information about the hardware's capability because its probe function
runs just after detecting unit of the model.
As long as I investigated, it takes a bit time (less than 1 second) to load
the firmware after bootstrap. Just after loaded, the driver can get
information about the unit. Then the hardware is initialized according to
vendor's configurations. After, the got information becomes wrong.
Between bootstrap, firmware loading and post configuration, some bus resets
are observed.
This commit offloads most processing of probe function into workqueue and
schedules the workqueue after successive bus resets. This has an effect to
get correct hardware information and avoid involvement to bus reset storm.
For code simplicity, this change effects all of Dice-based models, i.e.
Dice II, Dice Jr., Dice Mini and Dice III.
I use a loose strategy to manage a race condition between the work and the
bus reset. This is due to a specification of dice transaction. When bus
reset occurs, registered address for the transaction is cleared. Drivers
must re-register their own address again. While, this operation is required
for the work because the work includes to wait for the transaction. This
commit uses no lock primitives for the race condition. Instead, checking
'registered' member of 'struct snd_dice' avoid executing the work again.
If sound card is not registered, the work can be scheduled again by bus
reset handler.
When .remove callback is executed, the sound card is going to be released.
The work should not be pending or executed in the releasing. This commit
uses cancel_delayed_work_sync() in .remove callback and wait till the
pending work finished. After .remove callback, .update callback is not
executed, therefore no works are scheduled again.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2015-12-31 12:58:12 +08:00
|
|
|
#define PROBE_DELAY_MS (2 * MSEC_PER_SEC)
|
|
|
|
|
2015-12-31 12:58:11 +08:00
|
|
|
static int check_dice_category(struct fw_unit *unit)
|
2011-09-05 04:16:02 +08:00
|
|
|
{
|
|
|
|
struct fw_device *device = fw_parent_device(unit);
|
|
|
|
struct fw_csr_iterator it;
|
2015-12-31 12:58:11 +08:00
|
|
|
int key, val, vendor = -1, model = -1;
|
|
|
|
unsigned int category;
|
ALSA: dice: Split transaction functionality into a file
This commit adds a file with some helper functions for transaction, and move
some codes into the file with some arrangements.
For Dice chipset, well-known FCP or AV/C commands are not used to control
devices. It's achieved by read/write transactions into specific addresses.
Dice's address area is split into 5 areas. Each area has its own role. The
offset for each area can be got by reading head of the address area. By
reading these areas, drivers can get to know device status. By writing these
areas, drivers can change device status.
Dice has a specific mechanism called as 'notification'. When device status is
changed, Dice devices tells the event by sending transaction. This notification
is sent to an address which drivers register in advance. But this causes an
issue to drivers.
To handle the notification, drivers need to allocate its own callback function
to the address region in host controller. This region is exclusive. For the
other applications, drivers must give a mechanism to read the received
notification. For this purpose, Dice driver already implements hwdep interface.
Dice chipset doesn't allow drivers to register several addresses. In this
reason, when this driver is applied to a device, the other drivers should
_not_ try to register its own address to the device.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2014-11-28 23:59:13 +08:00
|
|
|
|
2011-09-05 04:16:02 +08:00
|
|
|
/*
|
|
|
|
* Check that GUID and unit directory are constructed according to DICE
|
|
|
|
* rules, i.e., that the specifier ID is the GUID's OUI, and that the
|
2012-02-14 04:55:13 +08:00
|
|
|
* GUID chip ID consists of the 8-bit category ID, the 10-bit product
|
|
|
|
* ID, and a 22-bit serial number.
|
2011-09-05 04:16:02 +08:00
|
|
|
*/
|
|
|
|
fw_csr_iterator_init(&it, unit->directory);
|
ALSA: dice: Split transaction functionality into a file
This commit adds a file with some helper functions for transaction, and move
some codes into the file with some arrangements.
For Dice chipset, well-known FCP or AV/C commands are not used to control
devices. It's achieved by read/write transactions into specific addresses.
Dice's address area is split into 5 areas. Each area has its own role. The
offset for each area can be got by reading head of the address area. By
reading these areas, drivers can get to know device status. By writing these
areas, drivers can change device status.
Dice has a specific mechanism called as 'notification'. When device status is
changed, Dice devices tells the event by sending transaction. This notification
is sent to an address which drivers register in advance. But this causes an
issue to drivers.
To handle the notification, drivers need to allocate its own callback function
to the address region in host controller. This region is exclusive. For the
other applications, drivers must give a mechanism to read the received
notification. For this purpose, Dice driver already implements hwdep interface.
Dice chipset doesn't allow drivers to register several addresses. In this
reason, when this driver is applied to a device, the other drivers should
_not_ try to register its own address to the device.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2014-11-28 23:59:13 +08:00
|
|
|
while (fw_csr_iterator_next(&it, &key, &val)) {
|
2011-09-05 04:16:02 +08:00
|
|
|
switch (key) {
|
|
|
|
case CSR_SPECIFIER_ID:
|
ALSA: dice: Split transaction functionality into a file
This commit adds a file with some helper functions for transaction, and move
some codes into the file with some arrangements.
For Dice chipset, well-known FCP or AV/C commands are not used to control
devices. It's achieved by read/write transactions into specific addresses.
Dice's address area is split into 5 areas. Each area has its own role. The
offset for each area can be got by reading head of the address area. By
reading these areas, drivers can get to know device status. By writing these
areas, drivers can change device status.
Dice has a specific mechanism called as 'notification'. When device status is
changed, Dice devices tells the event by sending transaction. This notification
is sent to an address which drivers register in advance. But this causes an
issue to drivers.
To handle the notification, drivers need to allocate its own callback function
to the address region in host controller. This region is exclusive. For the
other applications, drivers must give a mechanism to read the received
notification. For this purpose, Dice driver already implements hwdep interface.
Dice chipset doesn't allow drivers to register several addresses. In this
reason, when this driver is applied to a device, the other drivers should
_not_ try to register its own address to the device.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2014-11-28 23:59:13 +08:00
|
|
|
vendor = val;
|
2011-09-05 04:16:02 +08:00
|
|
|
break;
|
|
|
|
case CSR_MODEL:
|
ALSA: dice: Split transaction functionality into a file
This commit adds a file with some helper functions for transaction, and move
some codes into the file with some arrangements.
For Dice chipset, well-known FCP or AV/C commands are not used to control
devices. It's achieved by read/write transactions into specific addresses.
Dice's address area is split into 5 areas. Each area has its own role. The
offset for each area can be got by reading head of the address area. By
reading these areas, drivers can get to know device status. By writing these
areas, drivers can change device status.
Dice has a specific mechanism called as 'notification'. When device status is
changed, Dice devices tells the event by sending transaction. This notification
is sent to an address which drivers register in advance. But this causes an
issue to drivers.
To handle the notification, drivers need to allocate its own callback function
to the address region in host controller. This region is exclusive. For the
other applications, drivers must give a mechanism to read the received
notification. For this purpose, Dice driver already implements hwdep interface.
Dice chipset doesn't allow drivers to register several addresses. In this
reason, when this driver is applied to a device, the other drivers should
_not_ try to register its own address to the device.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2014-11-28 23:59:13 +08:00
|
|
|
model = val;
|
2011-09-05 04:16:02 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2012-02-14 04:55:13 +08:00
|
|
|
if (vendor == OUI_WEISS)
|
|
|
|
category = WEISS_CATEGORY_ID;
|
2015-11-14 15:42:04 +08:00
|
|
|
else if (vendor == OUI_LOUD)
|
|
|
|
category = LOUD_CATEGORY_ID;
|
2012-02-14 04:55:13 +08:00
|
|
|
else
|
|
|
|
category = DICE_CATEGORY_ID;
|
|
|
|
if (device->config_rom[3] != ((vendor << 8) | category) ||
|
2015-12-31 12:58:11 +08:00
|
|
|
device->config_rom[4] >> 22 != model)
|
|
|
|
return -ENODEV;
|
2011-09-05 04:16:02 +08:00
|
|
|
|
2015-12-31 12:58:11 +08:00
|
|
|
return 0;
|
2011-09-05 04:16:02 +08:00
|
|
|
}
|
|
|
|
|
2014-11-28 23:59:14 +08:00
|
|
|
static int highest_supported_mode_rate(struct snd_dice *dice,
|
|
|
|
unsigned int mode, unsigned int *rate)
|
2011-12-05 05:23:59 +08:00
|
|
|
{
|
2014-11-28 23:59:14 +08:00
|
|
|
unsigned int i, m;
|
2011-12-05 05:23:59 +08:00
|
|
|
|
2014-11-28 23:59:14 +08:00
|
|
|
for (i = ARRAY_SIZE(snd_dice_rates); i > 0; i--) {
|
|
|
|
*rate = snd_dice_rates[i - 1];
|
|
|
|
if (snd_dice_stream_get_rate_mode(dice, *rate, &m) < 0)
|
|
|
|
continue;
|
|
|
|
if (mode == m)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (i == 0)
|
|
|
|
return -EINVAL;
|
2011-12-05 05:23:59 +08:00
|
|
|
|
2014-11-28 23:59:14 +08:00
|
|
|
return 0;
|
2011-12-05 05:23:59 +08:00
|
|
|
}
|
|
|
|
|
2014-11-28 23:59:11 +08:00
|
|
|
static int dice_read_mode_params(struct snd_dice *dice, unsigned int mode)
|
2011-12-05 05:23:59 +08:00
|
|
|
{
|
|
|
|
__be32 values[2];
|
2014-11-28 23:59:14 +08:00
|
|
|
unsigned int rate;
|
|
|
|
int err;
|
2011-12-05 05:23:59 +08:00
|
|
|
|
2014-11-28 23:59:14 +08:00
|
|
|
if (highest_supported_mode_rate(dice, mode, &rate) < 0) {
|
2014-12-08 23:10:36 +08:00
|
|
|
dice->tx_channels[mode] = 0;
|
|
|
|
dice->tx_midi_ports[mode] = 0;
|
2011-12-05 05:23:59 +08:00
|
|
|
dice->rx_channels[mode] = 0;
|
|
|
|
dice->rx_midi_ports[mode] = 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-11-28 23:59:14 +08:00
|
|
|
err = snd_dice_transaction_set_rate(dice, rate);
|
2011-12-05 05:23:59 +08:00
|
|
|
if (err < 0)
|
|
|
|
return err;
|
|
|
|
|
2014-12-08 23:10:36 +08:00
|
|
|
err = snd_dice_transaction_read_tx(dice, TX_NUMBER_AUDIO,
|
|
|
|
values, sizeof(values));
|
|
|
|
if (err < 0)
|
|
|
|
return err;
|
|
|
|
|
|
|
|
dice->tx_channels[mode] = be32_to_cpu(values[0]);
|
|
|
|
dice->tx_midi_ports[mode] = be32_to_cpu(values[1]);
|
|
|
|
|
ALSA: dice: Split transaction functionality into a file
This commit adds a file with some helper functions for transaction, and move
some codes into the file with some arrangements.
For Dice chipset, well-known FCP or AV/C commands are not used to control
devices. It's achieved by read/write transactions into specific addresses.
Dice's address area is split into 5 areas. Each area has its own role. The
offset for each area can be got by reading head of the address area. By
reading these areas, drivers can get to know device status. By writing these
areas, drivers can change device status.
Dice has a specific mechanism called as 'notification'. When device status is
changed, Dice devices tells the event by sending transaction. This notification
is sent to an address which drivers register in advance. But this causes an
issue to drivers.
To handle the notification, drivers need to allocate its own callback function
to the address region in host controller. This region is exclusive. For the
other applications, drivers must give a mechanism to read the received
notification. For this purpose, Dice driver already implements hwdep interface.
Dice chipset doesn't allow drivers to register several addresses. In this
reason, when this driver is applied to a device, the other drivers should
_not_ try to register its own address to the device.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2014-11-28 23:59:13 +08:00
|
|
|
err = snd_dice_transaction_read_rx(dice, RX_NUMBER_AUDIO,
|
|
|
|
values, sizeof(values));
|
2011-12-05 05:23:59 +08:00
|
|
|
if (err < 0)
|
|
|
|
return err;
|
|
|
|
|
|
|
|
dice->rx_channels[mode] = be32_to_cpu(values[0]);
|
|
|
|
dice->rx_midi_ports[mode] = be32_to_cpu(values[1]);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-11-28 23:59:11 +08:00
|
|
|
static int dice_read_params(struct snd_dice *dice)
|
2011-09-05 04:04:49 +08:00
|
|
|
{
|
2011-12-05 04:47:00 +08:00
|
|
|
__be32 value;
|
2011-12-05 05:23:59 +08:00
|
|
|
int mode, err;
|
2011-09-05 04:04:49 +08:00
|
|
|
|
2011-12-05 04:47:00 +08:00
|
|
|
/* some very old firmwares don't tell about their clock support */
|
ALSA: dice: Split transaction functionality into a file
This commit adds a file with some helper functions for transaction, and move
some codes into the file with some arrangements.
For Dice chipset, well-known FCP or AV/C commands are not used to control
devices. It's achieved by read/write transactions into specific addresses.
Dice's address area is split into 5 areas. Each area has its own role. The
offset for each area can be got by reading head of the address area. By
reading these areas, drivers can get to know device status. By writing these
areas, drivers can change device status.
Dice has a specific mechanism called as 'notification'. When device status is
changed, Dice devices tells the event by sending transaction. This notification
is sent to an address which drivers register in advance. But this causes an
issue to drivers.
To handle the notification, drivers need to allocate its own callback function
to the address region in host controller. This region is exclusive. For the
other applications, drivers must give a mechanism to read the received
notification. For this purpose, Dice driver already implements hwdep interface.
Dice chipset doesn't allow drivers to register several addresses. In this
reason, when this driver is applied to a device, the other drivers should
_not_ try to register its own address to the device.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2014-11-28 23:59:13 +08:00
|
|
|
if (dice->clock_caps > 0) {
|
|
|
|
err = snd_dice_transaction_read_global(dice,
|
|
|
|
GLOBAL_CLOCK_CAPABILITIES,
|
|
|
|
&value, 4);
|
2011-12-05 04:47:00 +08:00
|
|
|
if (err < 0)
|
|
|
|
return err;
|
|
|
|
dice->clock_caps = be32_to_cpu(value);
|
|
|
|
} else {
|
|
|
|
/* this should be supported by any device */
|
|
|
|
dice->clock_caps = CLOCK_CAP_RATE_44100 |
|
|
|
|
CLOCK_CAP_RATE_48000 |
|
|
|
|
CLOCK_CAP_SOURCE_ARX1 |
|
|
|
|
CLOCK_CAP_SOURCE_INTERNAL;
|
|
|
|
}
|
|
|
|
|
2011-12-05 05:23:59 +08:00
|
|
|
for (mode = 2; mode >= 0; --mode) {
|
|
|
|
err = dice_read_mode_params(dice, mode);
|
|
|
|
if (err < 0)
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2011-09-05 04:04:49 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-11-28 23:59:11 +08:00
|
|
|
static void dice_card_strings(struct snd_dice *dice)
|
2011-09-05 04:04:49 +08:00
|
|
|
{
|
|
|
|
struct snd_card *card = dice->card;
|
|
|
|
struct fw_device *dev = fw_parent_device(dice->unit);
|
|
|
|
char vendor[32], model[32];
|
|
|
|
unsigned int i;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
strcpy(card->driver, "DICE");
|
|
|
|
|
|
|
|
strcpy(card->shortname, "DICE");
|
|
|
|
BUILD_BUG_ON(NICK_NAME_SIZE < sizeof(card->shortname));
|
ALSA: dice: Split transaction functionality into a file
This commit adds a file with some helper functions for transaction, and move
some codes into the file with some arrangements.
For Dice chipset, well-known FCP or AV/C commands are not used to control
devices. It's achieved by read/write transactions into specific addresses.
Dice's address area is split into 5 areas. Each area has its own role. The
offset for each area can be got by reading head of the address area. By
reading these areas, drivers can get to know device status. By writing these
areas, drivers can change device status.
Dice has a specific mechanism called as 'notification'. When device status is
changed, Dice devices tells the event by sending transaction. This notification
is sent to an address which drivers register in advance. But this causes an
issue to drivers.
To handle the notification, drivers need to allocate its own callback function
to the address region in host controller. This region is exclusive. For the
other applications, drivers must give a mechanism to read the received
notification. For this purpose, Dice driver already implements hwdep interface.
Dice chipset doesn't allow drivers to register several addresses. In this
reason, when this driver is applied to a device, the other drivers should
_not_ try to register its own address to the device.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2014-11-28 23:59:13 +08:00
|
|
|
err = snd_dice_transaction_read_global(dice, GLOBAL_NICK_NAME,
|
|
|
|
card->shortname,
|
|
|
|
sizeof(card->shortname));
|
2011-09-05 04:04:49 +08:00
|
|
|
if (err >= 0) {
|
|
|
|
/* DICE strings are returned in "always-wrong" endianness */
|
|
|
|
BUILD_BUG_ON(sizeof(card->shortname) % 4 != 0);
|
|
|
|
for (i = 0; i < sizeof(card->shortname); i += 4)
|
|
|
|
swab32s((u32 *)&card->shortname[i]);
|
|
|
|
card->shortname[sizeof(card->shortname) - 1] = '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
strcpy(vendor, "?");
|
|
|
|
fw_csr_string(dev->config_rom + 5, CSR_VENDOR, vendor, sizeof(vendor));
|
|
|
|
strcpy(model, "?");
|
|
|
|
fw_csr_string(dice->unit->directory, CSR_MODEL, model, sizeof(model));
|
|
|
|
snprintf(card->longname, sizeof(card->longname),
|
2011-09-05 04:16:02 +08:00
|
|
|
"%s %s (serial %u) at %s, S%d",
|
|
|
|
vendor, model, dev->config_rom[4] & 0x3fffff,
|
2011-09-05 04:04:49 +08:00
|
|
|
dev_name(&dice->unit->device), 100 << dev->max_speed);
|
|
|
|
|
|
|
|
strcpy(card->mixername, "DICE");
|
|
|
|
}
|
|
|
|
|
ALSA: dice: postpone card registration
Some models based on ASIC for Dice II series (STD, CP) change their
hardware configurations after appearing on IEEE 1394 bus. This is due to
interactions of boot loader (RedBoot), firmwares (eCos) and vendor's
configurations. This causes current ALSA dice driver to get wrong
information about the hardware's capability because its probe function
runs just after detecting unit of the model.
As long as I investigated, it takes a bit time (less than 1 second) to load
the firmware after bootstrap. Just after loaded, the driver can get
information about the unit. Then the hardware is initialized according to
vendor's configurations. After, the got information becomes wrong.
Between bootstrap, firmware loading and post configuration, some bus resets
are observed.
This commit offloads most processing of probe function into workqueue and
schedules the workqueue after successive bus resets. This has an effect to
get correct hardware information and avoid involvement to bus reset storm.
For code simplicity, this change effects all of Dice-based models, i.e.
Dice II, Dice Jr., Dice Mini and Dice III.
I use a loose strategy to manage a race condition between the work and the
bus reset. This is due to a specification of dice transaction. When bus
reset occurs, registered address for the transaction is cleared. Drivers
must re-register their own address again. While, this operation is required
for the work because the work includes to wait for the transaction. This
commit uses no lock primitives for the race condition. Instead, checking
'registered' member of 'struct snd_dice' avoid executing the work again.
If sound card is not registered, the work can be scheduled again by bus
reset handler.
When .remove callback is executed, the sound card is going to be released.
The work should not be pending or executed in the releasing. This commit
uses cancel_delayed_work_sync() in .remove callback and wait till the
pending work finished. After .remove callback, .update callback is not
executed, therefore no works are scheduled again.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2015-12-31 12:58:12 +08:00
|
|
|
static void dice_free(struct snd_dice *dice)
|
|
|
|
{
|
|
|
|
snd_dice_stream_destroy_duplex(dice);
|
|
|
|
snd_dice_transaction_destroy(dice);
|
|
|
|
fw_unit_put(dice->unit);
|
|
|
|
|
|
|
|
mutex_destroy(&dice->mutex);
|
|
|
|
kfree(dice);
|
|
|
|
}
|
|
|
|
|
2015-02-21 22:54:57 +08:00
|
|
|
/*
|
|
|
|
* This module releases the FireWire unit data after all ALSA character devices
|
|
|
|
* are released by applications. This is for releasing stream data or finishing
|
|
|
|
* transactions safely. Thus at returning from .remove(), this module still keep
|
|
|
|
* references for the unit.
|
|
|
|
*/
|
ALSA: dice: Split transaction functionality into a file
This commit adds a file with some helper functions for transaction, and move
some codes into the file with some arrangements.
For Dice chipset, well-known FCP or AV/C commands are not used to control
devices. It's achieved by read/write transactions into specific addresses.
Dice's address area is split into 5 areas. Each area has its own role. The
offset for each area can be got by reading head of the address area. By
reading these areas, drivers can get to know device status. By writing these
areas, drivers can change device status.
Dice has a specific mechanism called as 'notification'. When device status is
changed, Dice devices tells the event by sending transaction. This notification
is sent to an address which drivers register in advance. But this causes an
issue to drivers.
To handle the notification, drivers need to allocate its own callback function
to the address region in host controller. This region is exclusive. For the
other applications, drivers must give a mechanism to read the received
notification. For this purpose, Dice driver already implements hwdep interface.
Dice chipset doesn't allow drivers to register several addresses. In this
reason, when this driver is applied to a device, the other drivers should
_not_ try to register its own address to the device.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2014-11-28 23:59:13 +08:00
|
|
|
static void dice_card_free(struct snd_card *card)
|
|
|
|
{
|
ALSA: dice: postpone card registration
Some models based on ASIC for Dice II series (STD, CP) change their
hardware configurations after appearing on IEEE 1394 bus. This is due to
interactions of boot loader (RedBoot), firmwares (eCos) and vendor's
configurations. This causes current ALSA dice driver to get wrong
information about the hardware's capability because its probe function
runs just after detecting unit of the model.
As long as I investigated, it takes a bit time (less than 1 second) to load
the firmware after bootstrap. Just after loaded, the driver can get
information about the unit. Then the hardware is initialized according to
vendor's configurations. After, the got information becomes wrong.
Between bootstrap, firmware loading and post configuration, some bus resets
are observed.
This commit offloads most processing of probe function into workqueue and
schedules the workqueue after successive bus resets. This has an effect to
get correct hardware information and avoid involvement to bus reset storm.
For code simplicity, this change effects all of Dice-based models, i.e.
Dice II, Dice Jr., Dice Mini and Dice III.
I use a loose strategy to manage a race condition between the work and the
bus reset. This is due to a specification of dice transaction. When bus
reset occurs, registered address for the transaction is cleared. Drivers
must re-register their own address again. While, this operation is required
for the work because the work includes to wait for the transaction. This
commit uses no lock primitives for the race condition. Instead, checking
'registered' member of 'struct snd_dice' avoid executing the work again.
If sound card is not registered, the work can be scheduled again by bus
reset handler.
When .remove callback is executed, the sound card is going to be released.
The work should not be pending or executed in the releasing. This commit
uses cancel_delayed_work_sync() in .remove callback and wait till the
pending work finished. After .remove callback, .update callback is not
executed, therefore no works are scheduled again.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2015-12-31 12:58:12 +08:00
|
|
|
dice_free(card->private_data);
|
ALSA: dice: Split transaction functionality into a file
This commit adds a file with some helper functions for transaction, and move
some codes into the file with some arrangements.
For Dice chipset, well-known FCP or AV/C commands are not used to control
devices. It's achieved by read/write transactions into specific addresses.
Dice's address area is split into 5 areas. Each area has its own role. The
offset for each area can be got by reading head of the address area. By
reading these areas, drivers can get to know device status. By writing these
areas, drivers can change device status.
Dice has a specific mechanism called as 'notification'. When device status is
changed, Dice devices tells the event by sending transaction. This notification
is sent to an address which drivers register in advance. But this causes an
issue to drivers.
To handle the notification, drivers need to allocate its own callback function
to the address region in host controller. This region is exclusive. For the
other applications, drivers must give a mechanism to read the received
notification. For this purpose, Dice driver already implements hwdep interface.
Dice chipset doesn't allow drivers to register several addresses. In this
reason, when this driver is applied to a device, the other drivers should
_not_ try to register its own address to the device.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2014-11-28 23:59:13 +08:00
|
|
|
}
|
|
|
|
|
ALSA: dice: postpone card registration
Some models based on ASIC for Dice II series (STD, CP) change their
hardware configurations after appearing on IEEE 1394 bus. This is due to
interactions of boot loader (RedBoot), firmwares (eCos) and vendor's
configurations. This causes current ALSA dice driver to get wrong
information about the hardware's capability because its probe function
runs just after detecting unit of the model.
As long as I investigated, it takes a bit time (less than 1 second) to load
the firmware after bootstrap. Just after loaded, the driver can get
information about the unit. Then the hardware is initialized according to
vendor's configurations. After, the got information becomes wrong.
Between bootstrap, firmware loading and post configuration, some bus resets
are observed.
This commit offloads most processing of probe function into workqueue and
schedules the workqueue after successive bus resets. This has an effect to
get correct hardware information and avoid involvement to bus reset storm.
For code simplicity, this change effects all of Dice-based models, i.e.
Dice II, Dice Jr., Dice Mini and Dice III.
I use a loose strategy to manage a race condition between the work and the
bus reset. This is due to a specification of dice transaction. When bus
reset occurs, registered address for the transaction is cleared. Drivers
must re-register their own address again. While, this operation is required
for the work because the work includes to wait for the transaction. This
commit uses no lock primitives for the race condition. Instead, checking
'registered' member of 'struct snd_dice' avoid executing the work again.
If sound card is not registered, the work can be scheduled again by bus
reset handler.
When .remove callback is executed, the sound card is going to be released.
The work should not be pending or executed in the releasing. This commit
uses cancel_delayed_work_sync() in .remove callback and wait till the
pending work finished. After .remove callback, .update callback is not
executed, therefore no works are scheduled again.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2015-12-31 12:58:12 +08:00
|
|
|
static void do_registration(struct work_struct *work)
|
2011-09-05 04:04:49 +08:00
|
|
|
{
|
ALSA: dice: postpone card registration
Some models based on ASIC for Dice II series (STD, CP) change their
hardware configurations after appearing on IEEE 1394 bus. This is due to
interactions of boot loader (RedBoot), firmwares (eCos) and vendor's
configurations. This causes current ALSA dice driver to get wrong
information about the hardware's capability because its probe function
runs just after detecting unit of the model.
As long as I investigated, it takes a bit time (less than 1 second) to load
the firmware after bootstrap. Just after loaded, the driver can get
information about the unit. Then the hardware is initialized according to
vendor's configurations. After, the got information becomes wrong.
Between bootstrap, firmware loading and post configuration, some bus resets
are observed.
This commit offloads most processing of probe function into workqueue and
schedules the workqueue after successive bus resets. This has an effect to
get correct hardware information and avoid involvement to bus reset storm.
For code simplicity, this change effects all of Dice-based models, i.e.
Dice II, Dice Jr., Dice Mini and Dice III.
I use a loose strategy to manage a race condition between the work and the
bus reset. This is due to a specification of dice transaction. When bus
reset occurs, registered address for the transaction is cleared. Drivers
must re-register their own address again. While, this operation is required
for the work because the work includes to wait for the transaction. This
commit uses no lock primitives for the race condition. Instead, checking
'registered' member of 'struct snd_dice' avoid executing the work again.
If sound card is not registered, the work can be scheduled again by bus
reset handler.
When .remove callback is executed, the sound card is going to be released.
The work should not be pending or executed in the releasing. This commit
uses cancel_delayed_work_sync() in .remove callback and wait till the
pending work finished. After .remove callback, .update callback is not
executed, therefore no works are scheduled again.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2015-12-31 12:58:12 +08:00
|
|
|
struct snd_dice *dice = container_of(work, struct snd_dice, dwork.work);
|
2011-09-05 04:04:49 +08:00
|
|
|
int err;
|
|
|
|
|
ALSA: dice: postpone card registration
Some models based on ASIC for Dice II series (STD, CP) change their
hardware configurations after appearing on IEEE 1394 bus. This is due to
interactions of boot loader (RedBoot), firmwares (eCos) and vendor's
configurations. This causes current ALSA dice driver to get wrong
information about the hardware's capability because its probe function
runs just after detecting unit of the model.
As long as I investigated, it takes a bit time (less than 1 second) to load
the firmware after bootstrap. Just after loaded, the driver can get
information about the unit. Then the hardware is initialized according to
vendor's configurations. After, the got information becomes wrong.
Between bootstrap, firmware loading and post configuration, some bus resets
are observed.
This commit offloads most processing of probe function into workqueue and
schedules the workqueue after successive bus resets. This has an effect to
get correct hardware information and avoid involvement to bus reset storm.
For code simplicity, this change effects all of Dice-based models, i.e.
Dice II, Dice Jr., Dice Mini and Dice III.
I use a loose strategy to manage a race condition between the work and the
bus reset. This is due to a specification of dice transaction. When bus
reset occurs, registered address for the transaction is cleared. Drivers
must re-register their own address again. While, this operation is required
for the work because the work includes to wait for the transaction. This
commit uses no lock primitives for the race condition. Instead, checking
'registered' member of 'struct snd_dice' avoid executing the work again.
If sound card is not registered, the work can be scheduled again by bus
reset handler.
When .remove callback is executed, the sound card is going to be released.
The work should not be pending or executed in the releasing. This commit
uses cancel_delayed_work_sync() in .remove callback and wait till the
pending work finished. After .remove callback, .update callback is not
executed, therefore no works are scheduled again.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2015-12-31 12:58:12 +08:00
|
|
|
if (dice->registered)
|
|
|
|
return;
|
2011-09-05 04:16:02 +08:00
|
|
|
|
ALSA: dice: postpone card registration
Some models based on ASIC for Dice II series (STD, CP) change their
hardware configurations after appearing on IEEE 1394 bus. This is due to
interactions of boot loader (RedBoot), firmwares (eCos) and vendor's
configurations. This causes current ALSA dice driver to get wrong
information about the hardware's capability because its probe function
runs just after detecting unit of the model.
As long as I investigated, it takes a bit time (less than 1 second) to load
the firmware after bootstrap. Just after loaded, the driver can get
information about the unit. Then the hardware is initialized according to
vendor's configurations. After, the got information becomes wrong.
Between bootstrap, firmware loading and post configuration, some bus resets
are observed.
This commit offloads most processing of probe function into workqueue and
schedules the workqueue after successive bus resets. This has an effect to
get correct hardware information and avoid involvement to bus reset storm.
For code simplicity, this change effects all of Dice-based models, i.e.
Dice II, Dice Jr., Dice Mini and Dice III.
I use a loose strategy to manage a race condition between the work and the
bus reset. This is due to a specification of dice transaction. When bus
reset occurs, registered address for the transaction is cleared. Drivers
must re-register their own address again. While, this operation is required
for the work because the work includes to wait for the transaction. This
commit uses no lock primitives for the race condition. Instead, checking
'registered' member of 'struct snd_dice' avoid executing the work again.
If sound card is not registered, the work can be scheduled again by bus
reset handler.
When .remove callback is executed, the sound card is going to be released.
The work should not be pending or executed in the releasing. This commit
uses cancel_delayed_work_sync() in .remove callback and wait till the
pending work finished. After .remove callback, .update callback is not
executed, therefore no works are scheduled again.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2015-12-31 12:58:12 +08:00
|
|
|
err = snd_card_new(&dice->unit->device, -1, NULL, THIS_MODULE, 0,
|
|
|
|
&dice->card);
|
2011-09-05 04:04:49 +08:00
|
|
|
if (err < 0)
|
ALSA: dice: postpone card registration
Some models based on ASIC for Dice II series (STD, CP) change their
hardware configurations after appearing on IEEE 1394 bus. This is due to
interactions of boot loader (RedBoot), firmwares (eCos) and vendor's
configurations. This causes current ALSA dice driver to get wrong
information about the hardware's capability because its probe function
runs just after detecting unit of the model.
As long as I investigated, it takes a bit time (less than 1 second) to load
the firmware after bootstrap. Just after loaded, the driver can get
information about the unit. Then the hardware is initialized according to
vendor's configurations. After, the got information becomes wrong.
Between bootstrap, firmware loading and post configuration, some bus resets
are observed.
This commit offloads most processing of probe function into workqueue and
schedules the workqueue after successive bus resets. This has an effect to
get correct hardware information and avoid involvement to bus reset storm.
For code simplicity, this change effects all of Dice-based models, i.e.
Dice II, Dice Jr., Dice Mini and Dice III.
I use a loose strategy to manage a race condition between the work and the
bus reset. This is due to a specification of dice transaction. When bus
reset occurs, registered address for the transaction is cleared. Drivers
must re-register their own address again. While, this operation is required
for the work because the work includes to wait for the transaction. This
commit uses no lock primitives for the race condition. Instead, checking
'registered' member of 'struct snd_dice' avoid executing the work again.
If sound card is not registered, the work can be scheduled again by bus
reset handler.
When .remove callback is executed, the sound card is going to be released.
The work should not be pending or executed in the releasing. This commit
uses cancel_delayed_work_sync() in .remove callback and wait till the
pending work finished. After .remove callback, .update callback is not
executed, therefore no works are scheduled again.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2015-12-31 12:58:12 +08:00
|
|
|
return;
|
2011-09-05 04:04:49 +08:00
|
|
|
|
ALSA: dice: Split transaction functionality into a file
This commit adds a file with some helper functions for transaction, and move
some codes into the file with some arrangements.
For Dice chipset, well-known FCP or AV/C commands are not used to control
devices. It's achieved by read/write transactions into specific addresses.
Dice's address area is split into 5 areas. Each area has its own role. The
offset for each area can be got by reading head of the address area. By
reading these areas, drivers can get to know device status. By writing these
areas, drivers can change device status.
Dice has a specific mechanism called as 'notification'. When device status is
changed, Dice devices tells the event by sending transaction. This notification
is sent to an address which drivers register in advance. But this causes an
issue to drivers.
To handle the notification, drivers need to allocate its own callback function
to the address region in host controller. This region is exclusive. For the
other applications, drivers must give a mechanism to read the received
notification. For this purpose, Dice driver already implements hwdep interface.
Dice chipset doesn't allow drivers to register several addresses. In this
reason, when this driver is applied to a device, the other drivers should
_not_ try to register its own address to the device.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2014-11-28 23:59:13 +08:00
|
|
|
err = snd_dice_transaction_init(dice);
|
2011-09-05 04:04:49 +08:00
|
|
|
if (err < 0)
|
ALSA: dice: Split transaction functionality into a file
This commit adds a file with some helper functions for transaction, and move
some codes into the file with some arrangements.
For Dice chipset, well-known FCP or AV/C commands are not used to control
devices. It's achieved by read/write transactions into specific addresses.
Dice's address area is split into 5 areas. Each area has its own role. The
offset for each area can be got by reading head of the address area. By
reading these areas, drivers can get to know device status. By writing these
areas, drivers can change device status.
Dice has a specific mechanism called as 'notification'. When device status is
changed, Dice devices tells the event by sending transaction. This notification
is sent to an address which drivers register in advance. But this causes an
issue to drivers.
To handle the notification, drivers need to allocate its own callback function
to the address region in host controller. This region is exclusive. For the
other applications, drivers must give a mechanism to read the received
notification. For this purpose, Dice driver already implements hwdep interface.
Dice chipset doesn't allow drivers to register several addresses. In this
reason, when this driver is applied to a device, the other drivers should
_not_ try to register its own address to the device.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2014-11-28 23:59:13 +08:00
|
|
|
goto error;
|
2011-12-06 05:09:42 +08:00
|
|
|
|
|
|
|
err = dice_read_params(dice);
|
|
|
|
if (err < 0)
|
ALSA: dice: Split transaction functionality into a file
This commit adds a file with some helper functions for transaction, and move
some codes into the file with some arrangements.
For Dice chipset, well-known FCP or AV/C commands are not used to control
devices. It's achieved by read/write transactions into specific addresses.
Dice's address area is split into 5 areas. Each area has its own role. The
offset for each area can be got by reading head of the address area. By
reading these areas, drivers can get to know device status. By writing these
areas, drivers can change device status.
Dice has a specific mechanism called as 'notification'. When device status is
changed, Dice devices tells the event by sending transaction. This notification
is sent to an address which drivers register in advance. But this causes an
issue to drivers.
To handle the notification, drivers need to allocate its own callback function
to the address region in host controller. This region is exclusive. For the
other applications, drivers must give a mechanism to read the received
notification. For this purpose, Dice driver already implements hwdep interface.
Dice chipset doesn't allow drivers to register several addresses. In this
reason, when this driver is applied to a device, the other drivers should
_not_ try to register its own address to the device.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2014-11-28 23:59:13 +08:00
|
|
|
goto error;
|
2011-09-05 04:04:49 +08:00
|
|
|
|
|
|
|
dice_card_strings(dice);
|
|
|
|
|
ALSA: dice: postpone card registration
Some models based on ASIC for Dice II series (STD, CP) change their
hardware configurations after appearing on IEEE 1394 bus. This is due to
interactions of boot loader (RedBoot), firmwares (eCos) and vendor's
configurations. This causes current ALSA dice driver to get wrong
information about the hardware's capability because its probe function
runs just after detecting unit of the model.
As long as I investigated, it takes a bit time (less than 1 second) to load
the firmware after bootstrap. Just after loaded, the driver can get
information about the unit. Then the hardware is initialized according to
vendor's configurations. After, the got information becomes wrong.
Between bootstrap, firmware loading and post configuration, some bus resets
are observed.
This commit offloads most processing of probe function into workqueue and
schedules the workqueue after successive bus resets. This has an effect to
get correct hardware information and avoid involvement to bus reset storm.
For code simplicity, this change effects all of Dice-based models, i.e.
Dice II, Dice Jr., Dice Mini and Dice III.
I use a loose strategy to manage a race condition between the work and the
bus reset. This is due to a specification of dice transaction. When bus
reset occurs, registered address for the transaction is cleared. Drivers
must re-register their own address again. While, this operation is required
for the work because the work includes to wait for the transaction. This
commit uses no lock primitives for the race condition. Instead, checking
'registered' member of 'struct snd_dice' avoid executing the work again.
If sound card is not registered, the work can be scheduled again by bus
reset handler.
When .remove callback is executed, the sound card is going to be released.
The work should not be pending or executed in the releasing. This commit
uses cancel_delayed_work_sync() in .remove callback and wait till the
pending work finished. After .remove callback, .update callback is not
executed, therefore no works are scheduled again.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2015-12-31 12:58:12 +08:00
|
|
|
snd_dice_create_proc(dice);
|
|
|
|
|
2014-11-28 23:59:15 +08:00
|
|
|
err = snd_dice_create_pcm(dice);
|
2011-09-05 04:04:49 +08:00
|
|
|
if (err < 0)
|
|
|
|
goto error;
|
|
|
|
|
ALSA: dice: postpone card registration
Some models based on ASIC for Dice II series (STD, CP) change their
hardware configurations after appearing on IEEE 1394 bus. This is due to
interactions of boot loader (RedBoot), firmwares (eCos) and vendor's
configurations. This causes current ALSA dice driver to get wrong
information about the hardware's capability because its probe function
runs just after detecting unit of the model.
As long as I investigated, it takes a bit time (less than 1 second) to load
the firmware after bootstrap. Just after loaded, the driver can get
information about the unit. Then the hardware is initialized according to
vendor's configurations. After, the got information becomes wrong.
Between bootstrap, firmware loading and post configuration, some bus resets
are observed.
This commit offloads most processing of probe function into workqueue and
schedules the workqueue after successive bus resets. This has an effect to
get correct hardware information and avoid involvement to bus reset storm.
For code simplicity, this change effects all of Dice-based models, i.e.
Dice II, Dice Jr., Dice Mini and Dice III.
I use a loose strategy to manage a race condition between the work and the
bus reset. This is due to a specification of dice transaction. When bus
reset occurs, registered address for the transaction is cleared. Drivers
must re-register their own address again. While, this operation is required
for the work because the work includes to wait for the transaction. This
commit uses no lock primitives for the race condition. Instead, checking
'registered' member of 'struct snd_dice' avoid executing the work again.
If sound card is not registered, the work can be scheduled again by bus
reset handler.
When .remove callback is executed, the sound card is going to be released.
The work should not be pending or executed in the releasing. This commit
uses cancel_delayed_work_sync() in .remove callback and wait till the
pending work finished. After .remove callback, .update callback is not
executed, therefore no works are scheduled again.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2015-12-31 12:58:12 +08:00
|
|
|
err = snd_dice_create_midi(dice);
|
2011-09-05 04:04:49 +08:00
|
|
|
if (err < 0)
|
|
|
|
goto error;
|
|
|
|
|
ALSA: dice: postpone card registration
Some models based on ASIC for Dice II series (STD, CP) change their
hardware configurations after appearing on IEEE 1394 bus. This is due to
interactions of boot loader (RedBoot), firmwares (eCos) and vendor's
configurations. This causes current ALSA dice driver to get wrong
information about the hardware's capability because its probe function
runs just after detecting unit of the model.
As long as I investigated, it takes a bit time (less than 1 second) to load
the firmware after bootstrap. Just after loaded, the driver can get
information about the unit. Then the hardware is initialized according to
vendor's configurations. After, the got information becomes wrong.
Between bootstrap, firmware loading and post configuration, some bus resets
are observed.
This commit offloads most processing of probe function into workqueue and
schedules the workqueue after successive bus resets. This has an effect to
get correct hardware information and avoid involvement to bus reset storm.
For code simplicity, this change effects all of Dice-based models, i.e.
Dice II, Dice Jr., Dice Mini and Dice III.
I use a loose strategy to manage a race condition between the work and the
bus reset. This is due to a specification of dice transaction. When bus
reset occurs, registered address for the transaction is cleared. Drivers
must re-register their own address again. While, this operation is required
for the work because the work includes to wait for the transaction. This
commit uses no lock primitives for the race condition. Instead, checking
'registered' member of 'struct snd_dice' avoid executing the work again.
If sound card is not registered, the work can be scheduled again by bus
reset handler.
When .remove callback is executed, the sound card is going to be released.
The work should not be pending or executed in the releasing. This commit
uses cancel_delayed_work_sync() in .remove callback and wait till the
pending work finished. After .remove callback, .update callback is not
executed, therefore no works are scheduled again.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2015-12-31 12:58:12 +08:00
|
|
|
err = snd_dice_create_hwdep(dice);
|
2014-12-08 23:10:39 +08:00
|
|
|
if (err < 0)
|
|
|
|
goto error;
|
|
|
|
|
ALSA: dice: postpone card registration
Some models based on ASIC for Dice II series (STD, CP) change their
hardware configurations after appearing on IEEE 1394 bus. This is due to
interactions of boot loader (RedBoot), firmwares (eCos) and vendor's
configurations. This causes current ALSA dice driver to get wrong
information about the hardware's capability because its probe function
runs just after detecting unit of the model.
As long as I investigated, it takes a bit time (less than 1 second) to load
the firmware after bootstrap. Just after loaded, the driver can get
information about the unit. Then the hardware is initialized according to
vendor's configurations. After, the got information becomes wrong.
Between bootstrap, firmware loading and post configuration, some bus resets
are observed.
This commit offloads most processing of probe function into workqueue and
schedules the workqueue after successive bus resets. This has an effect to
get correct hardware information and avoid involvement to bus reset storm.
For code simplicity, this change effects all of Dice-based models, i.e.
Dice II, Dice Jr., Dice Mini and Dice III.
I use a loose strategy to manage a race condition between the work and the
bus reset. This is due to a specification of dice transaction. When bus
reset occurs, registered address for the transaction is cleared. Drivers
must re-register their own address again. While, this operation is required
for the work because the work includes to wait for the transaction. This
commit uses no lock primitives for the race condition. Instead, checking
'registered' member of 'struct snd_dice' avoid executing the work again.
If sound card is not registered, the work can be scheduled again by bus
reset handler.
When .remove callback is executed, the sound card is going to be released.
The work should not be pending or executed in the releasing. This commit
uses cancel_delayed_work_sync() in .remove callback and wait till the
pending work finished. After .remove callback, .update callback is not
executed, therefore no works are scheduled again.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2015-12-31 12:58:12 +08:00
|
|
|
err = snd_card_register(dice->card);
|
2011-09-05 04:04:49 +08:00
|
|
|
if (err < 0)
|
|
|
|
goto error;
|
|
|
|
|
ALSA: dice: postpone card registration
Some models based on ASIC for Dice II series (STD, CP) change their
hardware configurations after appearing on IEEE 1394 bus. This is due to
interactions of boot loader (RedBoot), firmwares (eCos) and vendor's
configurations. This causes current ALSA dice driver to get wrong
information about the hardware's capability because its probe function
runs just after detecting unit of the model.
As long as I investigated, it takes a bit time (less than 1 second) to load
the firmware after bootstrap. Just after loaded, the driver can get
information about the unit. Then the hardware is initialized according to
vendor's configurations. After, the got information becomes wrong.
Between bootstrap, firmware loading and post configuration, some bus resets
are observed.
This commit offloads most processing of probe function into workqueue and
schedules the workqueue after successive bus resets. This has an effect to
get correct hardware information and avoid involvement to bus reset storm.
For code simplicity, this change effects all of Dice-based models, i.e.
Dice II, Dice Jr., Dice Mini and Dice III.
I use a loose strategy to manage a race condition between the work and the
bus reset. This is due to a specification of dice transaction. When bus
reset occurs, registered address for the transaction is cleared. Drivers
must re-register their own address again. While, this operation is required
for the work because the work includes to wait for the transaction. This
commit uses no lock primitives for the race condition. Instead, checking
'registered' member of 'struct snd_dice' avoid executing the work again.
If sound card is not registered, the work can be scheduled again by bus
reset handler.
When .remove callback is executed, the sound card is going to be released.
The work should not be pending or executed in the releasing. This commit
uses cancel_delayed_work_sync() in .remove callback and wait till the
pending work finished. After .remove callback, .update callback is not
executed, therefore no works are scheduled again.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2015-12-31 12:58:12 +08:00
|
|
|
/*
|
|
|
|
* After registered, dice instance can be released corresponding to
|
|
|
|
* releasing the sound card instance.
|
|
|
|
*/
|
|
|
|
dice->card->private_free = dice_card_free;
|
|
|
|
dice->card->private_data = dice;
|
|
|
|
dice->registered = true;
|
|
|
|
|
|
|
|
return;
|
|
|
|
error:
|
|
|
|
snd_dice_transaction_destroy(dice);
|
|
|
|
snd_card_free(dice->card);
|
|
|
|
dev_info(&dice->unit->device,
|
|
|
|
"Sound card registration failed: %d\n", err);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void schedule_registration(struct snd_dice *dice)
|
|
|
|
{
|
|
|
|
struct fw_card *fw_card = fw_parent_device(dice->unit)->card;
|
|
|
|
u64 now, delay;
|
|
|
|
|
|
|
|
now = get_jiffies_64();
|
|
|
|
delay = fw_card->reset_jiffies + msecs_to_jiffies(PROBE_DELAY_MS);
|
|
|
|
|
|
|
|
if (time_after64(delay, now))
|
|
|
|
delay -= now;
|
|
|
|
else
|
|
|
|
delay = 0;
|
|
|
|
|
|
|
|
mod_delayed_work(system_wq, &dice->dwork, delay);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int dice_probe(struct fw_unit *unit, const struct ieee1394_device_id *id)
|
|
|
|
{
|
|
|
|
struct snd_dice *dice;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
err = check_dice_category(unit);
|
|
|
|
if (err < 0)
|
|
|
|
return -ENODEV;
|
|
|
|
|
|
|
|
/* Allocate this independent of sound card instance. */
|
|
|
|
dice = kzalloc(sizeof(struct snd_dice), GFP_KERNEL);
|
|
|
|
if (dice == NULL)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
dice->unit = fw_unit_get(unit);
|
|
|
|
dev_set_drvdata(&unit->device, dice);
|
|
|
|
|
|
|
|
spin_lock_init(&dice->lock);
|
|
|
|
mutex_init(&dice->mutex);
|
|
|
|
init_completion(&dice->clock_accepted);
|
|
|
|
init_waitqueue_head(&dice->hwdep_wait);
|
|
|
|
|
|
|
|
err = snd_dice_stream_init_duplex(dice);
|
ALSA: dice: Split transaction functionality into a file
This commit adds a file with some helper functions for transaction, and move
some codes into the file with some arrangements.
For Dice chipset, well-known FCP or AV/C commands are not used to control
devices. It's achieved by read/write transactions into specific addresses.
Dice's address area is split into 5 areas. Each area has its own role. The
offset for each area can be got by reading head of the address area. By
reading these areas, drivers can get to know device status. By writing these
areas, drivers can change device status.
Dice has a specific mechanism called as 'notification'. When device status is
changed, Dice devices tells the event by sending transaction. This notification
is sent to an address which drivers register in advance. But this causes an
issue to drivers.
To handle the notification, drivers need to allocate its own callback function
to the address region in host controller. This region is exclusive. For the
other applications, drivers must give a mechanism to read the received
notification. For this purpose, Dice driver already implements hwdep interface.
Dice chipset doesn't allow drivers to register several addresses. In this
reason, when this driver is applied to a device, the other drivers should
_not_ try to register its own address to the device.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2014-11-28 23:59:13 +08:00
|
|
|
if (err < 0) {
|
ALSA: dice: postpone card registration
Some models based on ASIC for Dice II series (STD, CP) change their
hardware configurations after appearing on IEEE 1394 bus. This is due to
interactions of boot loader (RedBoot), firmwares (eCos) and vendor's
configurations. This causes current ALSA dice driver to get wrong
information about the hardware's capability because its probe function
runs just after detecting unit of the model.
As long as I investigated, it takes a bit time (less than 1 second) to load
the firmware after bootstrap. Just after loaded, the driver can get
information about the unit. Then the hardware is initialized according to
vendor's configurations. After, the got information becomes wrong.
Between bootstrap, firmware loading and post configuration, some bus resets
are observed.
This commit offloads most processing of probe function into workqueue and
schedules the workqueue after successive bus resets. This has an effect to
get correct hardware information and avoid involvement to bus reset storm.
For code simplicity, this change effects all of Dice-based models, i.e.
Dice II, Dice Jr., Dice Mini and Dice III.
I use a loose strategy to manage a race condition between the work and the
bus reset. This is due to a specification of dice transaction. When bus
reset occurs, registered address for the transaction is cleared. Drivers
must re-register their own address again. While, this operation is required
for the work because the work includes to wait for the transaction. This
commit uses no lock primitives for the race condition. Instead, checking
'registered' member of 'struct snd_dice' avoid executing the work again.
If sound card is not registered, the work can be scheduled again by bus
reset handler.
When .remove callback is executed, the sound card is going to be released.
The work should not be pending or executed in the releasing. This commit
uses cancel_delayed_work_sync() in .remove callback and wait till the
pending work finished. After .remove callback, .update callback is not
executed, therefore no works are scheduled again.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2015-12-31 12:58:12 +08:00
|
|
|
dice_free(dice);
|
|
|
|
return err;
|
ALSA: dice: Split transaction functionality into a file
This commit adds a file with some helper functions for transaction, and move
some codes into the file with some arrangements.
For Dice chipset, well-known FCP or AV/C commands are not used to control
devices. It's achieved by read/write transactions into specific addresses.
Dice's address area is split into 5 areas. Each area has its own role. The
offset for each area can be got by reading head of the address area. By
reading these areas, drivers can get to know device status. By writing these
areas, drivers can change device status.
Dice has a specific mechanism called as 'notification'. When device status is
changed, Dice devices tells the event by sending transaction. This notification
is sent to an address which drivers register in advance. But this causes an
issue to drivers.
To handle the notification, drivers need to allocate its own callback function
to the address region in host controller. This region is exclusive. For the
other applications, drivers must give a mechanism to read the received
notification. For this purpose, Dice driver already implements hwdep interface.
Dice chipset doesn't allow drivers to register several addresses. In this
reason, when this driver is applied to a device, the other drivers should
_not_ try to register its own address to the device.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2014-11-28 23:59:13 +08:00
|
|
|
}
|
2011-09-05 04:04:49 +08:00
|
|
|
|
ALSA: dice: postpone card registration
Some models based on ASIC for Dice II series (STD, CP) change their
hardware configurations after appearing on IEEE 1394 bus. This is due to
interactions of boot loader (RedBoot), firmwares (eCos) and vendor's
configurations. This causes current ALSA dice driver to get wrong
information about the hardware's capability because its probe function
runs just after detecting unit of the model.
As long as I investigated, it takes a bit time (less than 1 second) to load
the firmware after bootstrap. Just after loaded, the driver can get
information about the unit. Then the hardware is initialized according to
vendor's configurations. After, the got information becomes wrong.
Between bootstrap, firmware loading and post configuration, some bus resets
are observed.
This commit offloads most processing of probe function into workqueue and
schedules the workqueue after successive bus resets. This has an effect to
get correct hardware information and avoid involvement to bus reset storm.
For code simplicity, this change effects all of Dice-based models, i.e.
Dice II, Dice Jr., Dice Mini and Dice III.
I use a loose strategy to manage a race condition between the work and the
bus reset. This is due to a specification of dice transaction. When bus
reset occurs, registered address for the transaction is cleared. Drivers
must re-register their own address again. While, this operation is required
for the work because the work includes to wait for the transaction. This
commit uses no lock primitives for the race condition. Instead, checking
'registered' member of 'struct snd_dice' avoid executing the work again.
If sound card is not registered, the work can be scheduled again by bus
reset handler.
When .remove callback is executed, the sound card is going to be released.
The work should not be pending or executed in the releasing. This commit
uses cancel_delayed_work_sync() in .remove callback and wait till the
pending work finished. After .remove callback, .update callback is not
executed, therefore no works are scheduled again.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2015-12-31 12:58:12 +08:00
|
|
|
/* Allocate and register this sound card later. */
|
|
|
|
INIT_DEFERRABLE_WORK(&dice->dwork, do_registration);
|
|
|
|
schedule_registration(dice);
|
|
|
|
|
|
|
|
return 0;
|
2011-09-05 04:04:49 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void dice_remove(struct fw_unit *unit)
|
|
|
|
{
|
2014-11-28 23:59:11 +08:00
|
|
|
struct snd_dice *dice = dev_get_drvdata(&unit->device);
|
2011-09-05 04:04:49 +08:00
|
|
|
|
ALSA: dice: postpone card registration
Some models based on ASIC for Dice II series (STD, CP) change their
hardware configurations after appearing on IEEE 1394 bus. This is due to
interactions of boot loader (RedBoot), firmwares (eCos) and vendor's
configurations. This causes current ALSA dice driver to get wrong
information about the hardware's capability because its probe function
runs just after detecting unit of the model.
As long as I investigated, it takes a bit time (less than 1 second) to load
the firmware after bootstrap. Just after loaded, the driver can get
information about the unit. Then the hardware is initialized according to
vendor's configurations. After, the got information becomes wrong.
Between bootstrap, firmware loading and post configuration, some bus resets
are observed.
This commit offloads most processing of probe function into workqueue and
schedules the workqueue after successive bus resets. This has an effect to
get correct hardware information and avoid involvement to bus reset storm.
For code simplicity, this change effects all of Dice-based models, i.e.
Dice II, Dice Jr., Dice Mini and Dice III.
I use a loose strategy to manage a race condition between the work and the
bus reset. This is due to a specification of dice transaction. When bus
reset occurs, registered address for the transaction is cleared. Drivers
must re-register their own address again. While, this operation is required
for the work because the work includes to wait for the transaction. This
commit uses no lock primitives for the race condition. Instead, checking
'registered' member of 'struct snd_dice' avoid executing the work again.
If sound card is not registered, the work can be scheduled again by bus
reset handler.
When .remove callback is executed, the sound card is going to be released.
The work should not be pending or executed in the releasing. This commit
uses cancel_delayed_work_sync() in .remove callback and wait till the
pending work finished. After .remove callback, .update callback is not
executed, therefore no works are scheduled again.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2015-12-31 12:58:12 +08:00
|
|
|
/*
|
|
|
|
* Confirm to stop the work for registration before the sound card is
|
|
|
|
* going to be released. The work is not scheduled again because bus
|
|
|
|
* reset handler is not called anymore.
|
|
|
|
*/
|
|
|
|
cancel_delayed_work_sync(&dice->dwork);
|
|
|
|
|
|
|
|
if (dice->registered) {
|
|
|
|
/* No need to wait for releasing card object in this context. */
|
|
|
|
snd_card_free_when_closed(dice->card);
|
|
|
|
} else {
|
|
|
|
/* Don't forget this case. */
|
|
|
|
dice_free(dice);
|
|
|
|
}
|
2011-09-05 04:04:49 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void dice_bus_reset(struct fw_unit *unit)
|
|
|
|
{
|
2014-11-28 23:59:11 +08:00
|
|
|
struct snd_dice *dice = dev_get_drvdata(&unit->device);
|
2011-09-05 04:04:49 +08:00
|
|
|
|
ALSA: dice: postpone card registration
Some models based on ASIC for Dice II series (STD, CP) change their
hardware configurations after appearing on IEEE 1394 bus. This is due to
interactions of boot loader (RedBoot), firmwares (eCos) and vendor's
configurations. This causes current ALSA dice driver to get wrong
information about the hardware's capability because its probe function
runs just after detecting unit of the model.
As long as I investigated, it takes a bit time (less than 1 second) to load
the firmware after bootstrap. Just after loaded, the driver can get
information about the unit. Then the hardware is initialized according to
vendor's configurations. After, the got information becomes wrong.
Between bootstrap, firmware loading and post configuration, some bus resets
are observed.
This commit offloads most processing of probe function into workqueue and
schedules the workqueue after successive bus resets. This has an effect to
get correct hardware information and avoid involvement to bus reset storm.
For code simplicity, this change effects all of Dice-based models, i.e.
Dice II, Dice Jr., Dice Mini and Dice III.
I use a loose strategy to manage a race condition between the work and the
bus reset. This is due to a specification of dice transaction. When bus
reset occurs, registered address for the transaction is cleared. Drivers
must re-register their own address again. While, this operation is required
for the work because the work includes to wait for the transaction. This
commit uses no lock primitives for the race condition. Instead, checking
'registered' member of 'struct snd_dice' avoid executing the work again.
If sound card is not registered, the work can be scheduled again by bus
reset handler.
When .remove callback is executed, the sound card is going to be released.
The work should not be pending or executed in the releasing. This commit
uses cancel_delayed_work_sync() in .remove callback and wait till the
pending work finished. After .remove callback, .update callback is not
executed, therefore no works are scheduled again.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2015-12-31 12:58:12 +08:00
|
|
|
/* Postpone a workqueue for deferred registration. */
|
|
|
|
if (!dice->registered)
|
|
|
|
schedule_registration(dice);
|
|
|
|
|
ALSA: dice: Split transaction functionality into a file
This commit adds a file with some helper functions for transaction, and move
some codes into the file with some arrangements.
For Dice chipset, well-known FCP or AV/C commands are not used to control
devices. It's achieved by read/write transactions into specific addresses.
Dice's address area is split into 5 areas. Each area has its own role. The
offset for each area can be got by reading head of the address area. By
reading these areas, drivers can get to know device status. By writing these
areas, drivers can change device status.
Dice has a specific mechanism called as 'notification'. When device status is
changed, Dice devices tells the event by sending transaction. This notification
is sent to an address which drivers register in advance. But this causes an
issue to drivers.
To handle the notification, drivers need to allocate its own callback function
to the address region in host controller. This region is exclusive. For the
other applications, drivers must give a mechanism to read the received
notification. For this purpose, Dice driver already implements hwdep interface.
Dice chipset doesn't allow drivers to register several addresses. In this
reason, when this driver is applied to a device, the other drivers should
_not_ try to register its own address to the device.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2014-11-28 23:59:13 +08:00
|
|
|
/* The handler address register becomes initialized. */
|
|
|
|
snd_dice_transaction_reinit(dice);
|
|
|
|
|
ALSA: dice: postpone card registration
Some models based on ASIC for Dice II series (STD, CP) change their
hardware configurations after appearing on IEEE 1394 bus. This is due to
interactions of boot loader (RedBoot), firmwares (eCos) and vendor's
configurations. This causes current ALSA dice driver to get wrong
information about the hardware's capability because its probe function
runs just after detecting unit of the model.
As long as I investigated, it takes a bit time (less than 1 second) to load
the firmware after bootstrap. Just after loaded, the driver can get
information about the unit. Then the hardware is initialized according to
vendor's configurations. After, the got information becomes wrong.
Between bootstrap, firmware loading and post configuration, some bus resets
are observed.
This commit offloads most processing of probe function into workqueue and
schedules the workqueue after successive bus resets. This has an effect to
get correct hardware information and avoid involvement to bus reset storm.
For code simplicity, this change effects all of Dice-based models, i.e.
Dice II, Dice Jr., Dice Mini and Dice III.
I use a loose strategy to manage a race condition between the work and the
bus reset. This is due to a specification of dice transaction. When bus
reset occurs, registered address for the transaction is cleared. Drivers
must re-register their own address again. While, this operation is required
for the work because the work includes to wait for the transaction. This
commit uses no lock primitives for the race condition. Instead, checking
'registered' member of 'struct snd_dice' avoid executing the work again.
If sound card is not registered, the work can be scheduled again by bus
reset handler.
When .remove callback is executed, the sound card is going to be released.
The work should not be pending or executed in the releasing. This commit
uses cancel_delayed_work_sync() in .remove callback and wait till the
pending work finished. After .remove callback, .update callback is not
executed, therefore no works are scheduled again.
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2015-12-31 12:58:12 +08:00
|
|
|
/*
|
|
|
|
* After registration, userspace can start packet streaming, then this
|
|
|
|
* code block works fine.
|
|
|
|
*/
|
|
|
|
if (dice->registered) {
|
|
|
|
mutex_lock(&dice->mutex);
|
|
|
|
snd_dice_stream_update_duplex(dice);
|
|
|
|
mutex_unlock(&dice->mutex);
|
|
|
|
}
|
2011-09-05 04:04:49 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
#define DICE_INTERFACE 0x000001
|
|
|
|
|
|
|
|
static const struct ieee1394_device_id dice_id_table[] = {
|
|
|
|
{
|
2011-09-05 04:16:02 +08:00
|
|
|
.match_flags = IEEE1394_MATCH_VERSION,
|
|
|
|
.version = DICE_INTERFACE,
|
2011-09-05 04:04:49 +08:00
|
|
|
},
|
|
|
|
{ }
|
|
|
|
};
|
|
|
|
MODULE_DEVICE_TABLE(ieee1394, dice_id_table);
|
|
|
|
|
|
|
|
static struct fw_driver dice_driver = {
|
|
|
|
.driver = {
|
|
|
|
.owner = THIS_MODULE,
|
|
|
|
.name = KBUILD_MODNAME,
|
|
|
|
.bus = &fw_bus_type,
|
|
|
|
},
|
|
|
|
.probe = dice_probe,
|
|
|
|
.update = dice_bus_reset,
|
|
|
|
.remove = dice_remove,
|
|
|
|
.id_table = dice_id_table,
|
|
|
|
};
|
|
|
|
|
|
|
|
static int __init alsa_dice_init(void)
|
|
|
|
{
|
|
|
|
return driver_register(&dice_driver.driver);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void __exit alsa_dice_exit(void)
|
|
|
|
{
|
|
|
|
driver_unregister(&dice_driver.driver);
|
|
|
|
}
|
|
|
|
|
|
|
|
module_init(alsa_dice_init);
|
|
|
|
module_exit(alsa_dice_exit);
|