ALSA: scarlett2: Move initialisation code lower in the source
BugLink: https://bugs.launchpad.net/bugs/2076402 So that more forward declarations won't be required when we add handling of the ACK notification, move the initialisation functions to after the notification functions. Signed-off-by: Geoffrey D. Bennett <g@b4.vu> Signed-off-by: Takashi Iwai <tiwai@suse.de> Message-ID: <0922071cb8be99a2394705de27b917d1e4e46f3f.1710264833.git.g@b4.vu> (cherry picked from commit 4074f8d23278e9e32aabe9dba60f6dddaf68e6ef) Signed-off-by: Roxana Nicolescu <roxana.nicolescu@canonical.com> Acked-by: Koichiro Den <koichiro.den@canonical.com> Acked-by: Hui Wang <hui.wang@canonical.com> Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
This commit is contained in:
committed by
Stefan Bader
parent
6d44043781
commit
1afa222af3
+409
-406
@@ -6383,412 +6383,7 @@ static int scarlett2_add_power_status_ctl(struct usb_mixer_interface *mixer)
|
||||
&private->power_status_ctl);
|
||||
}
|
||||
|
||||
/*** Cleanup/Suspend Callbacks ***/
|
||||
|
||||
static void scarlett2_private_free(struct usb_mixer_interface *mixer)
|
||||
{
|
||||
struct scarlett2_data *private = mixer->private_data;
|
||||
|
||||
cancel_delayed_work_sync(&private->work);
|
||||
kfree(private);
|
||||
mixer->private_data = NULL;
|
||||
}
|
||||
|
||||
static void scarlett2_private_suspend(struct usb_mixer_interface *mixer)
|
||||
{
|
||||
struct scarlett2_data *private = mixer->private_data;
|
||||
|
||||
if (cancel_delayed_work_sync(&private->work))
|
||||
scarlett2_config_save(private->mixer);
|
||||
}
|
||||
|
||||
/*** Initialisation ***/
|
||||
|
||||
static void scarlett2_count_io(struct scarlett2_data *private)
|
||||
{
|
||||
const struct scarlett2_device_info *info = private->info;
|
||||
const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count;
|
||||
int port_type, srcs = 0, dsts = 0;
|
||||
|
||||
/* Count the number of mux sources and destinations */
|
||||
for (port_type = 0;
|
||||
port_type < SCARLETT2_PORT_TYPE_COUNT;
|
||||
port_type++) {
|
||||
srcs += port_count[port_type][SCARLETT2_PORT_IN];
|
||||
dsts += port_count[port_type][SCARLETT2_PORT_OUT];
|
||||
}
|
||||
|
||||
private->num_mux_srcs = srcs;
|
||||
private->num_mux_dsts = dsts;
|
||||
|
||||
/* Mixer inputs are mux outputs and vice versa.
|
||||
* Scarlett Gen 4 DSP I/O uses SCARLETT2_PORT_TYPE_MIX but
|
||||
* doesn't have mixer controls.
|
||||
*/
|
||||
private->num_mix_in =
|
||||
port_count[SCARLETT2_PORT_TYPE_MIX][SCARLETT2_PORT_OUT] -
|
||||
info->dsp_count;
|
||||
|
||||
private->num_mix_out =
|
||||
port_count[SCARLETT2_PORT_TYPE_MIX][SCARLETT2_PORT_IN] -
|
||||
info->dsp_count;
|
||||
|
||||
/* Number of analogue line outputs */
|
||||
private->num_line_out =
|
||||
port_count[SCARLETT2_PORT_TYPE_ANALOGUE][SCARLETT2_PORT_OUT];
|
||||
|
||||
/* Number of monitor mix controls */
|
||||
private->num_monitor_mix_ctls =
|
||||
info->direct_monitor * 2 * private->num_mix_in;
|
||||
}
|
||||
|
||||
/* Look through the interface descriptors for the Focusrite Control
|
||||
* interface (bInterfaceClass = 255 Vendor Specific Class) and set
|
||||
* bInterfaceNumber, bEndpointAddress, wMaxPacketSize, and bInterval
|
||||
* in private
|
||||
*/
|
||||
static int scarlett2_find_fc_interface(struct usb_device *dev,
|
||||
struct scarlett2_data *private)
|
||||
{
|
||||
struct usb_host_config *config = dev->actconfig;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < config->desc.bNumInterfaces; i++) {
|
||||
struct usb_interface *intf = config->interface[i];
|
||||
struct usb_interface_descriptor *desc =
|
||||
&intf->altsetting[0].desc;
|
||||
struct usb_endpoint_descriptor *epd;
|
||||
|
||||
if (desc->bInterfaceClass != 255)
|
||||
continue;
|
||||
|
||||
epd = get_endpoint(intf->altsetting, 0);
|
||||
private->bInterfaceNumber = desc->bInterfaceNumber;
|
||||
private->bEndpointAddress = epd->bEndpointAddress &
|
||||
USB_ENDPOINT_NUMBER_MASK;
|
||||
private->wMaxPacketSize = le16_to_cpu(epd->wMaxPacketSize);
|
||||
private->bInterval = epd->bInterval;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Initialise private data */
|
||||
static int scarlett2_init_private(struct usb_mixer_interface *mixer,
|
||||
const struct scarlett2_device_entry *entry)
|
||||
{
|
||||
struct scarlett2_data *private =
|
||||
kzalloc(sizeof(struct scarlett2_data), GFP_KERNEL);
|
||||
|
||||
if (!private)
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_init(&private->usb_mutex);
|
||||
mutex_init(&private->data_mutex);
|
||||
INIT_DELAYED_WORK(&private->work, scarlett2_config_save_work);
|
||||
|
||||
mixer->private_data = private;
|
||||
mixer->private_free = scarlett2_private_free;
|
||||
mixer->private_suspend = scarlett2_private_suspend;
|
||||
|
||||
private->info = entry->info;
|
||||
private->config_set = entry->info->config_set;
|
||||
private->series_name = entry->series_name;
|
||||
scarlett2_count_io(private);
|
||||
private->scarlett2_seq = 0;
|
||||
private->mixer = mixer;
|
||||
|
||||
return scarlett2_find_fc_interface(mixer->chip->dev, private);
|
||||
}
|
||||
|
||||
/* Cargo cult proprietary initialisation sequence */
|
||||
static int scarlett2_usb_init(struct usb_mixer_interface *mixer)
|
||||
{
|
||||
struct usb_device *dev = mixer->chip->dev;
|
||||
struct scarlett2_data *private = mixer->private_data;
|
||||
u8 step0_buf[24];
|
||||
u8 step2_buf[84];
|
||||
int err;
|
||||
|
||||
if (usb_pipe_type_check(dev, usb_sndctrlpipe(dev, 0)))
|
||||
return -EINVAL;
|
||||
|
||||
/* step 0 */
|
||||
err = scarlett2_usb_rx(dev, private->bInterfaceNumber,
|
||||
SCARLETT2_USB_CMD_INIT,
|
||||
step0_buf, sizeof(step0_buf));
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
/* step 1 */
|
||||
private->scarlett2_seq = 1;
|
||||
err = scarlett2_usb(mixer, SCARLETT2_USB_INIT_1, NULL, 0, NULL, 0);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
/* step 2 */
|
||||
private->scarlett2_seq = 1;
|
||||
err = scarlett2_usb(mixer, SCARLETT2_USB_INIT_2,
|
||||
NULL, 0,
|
||||
step2_buf, sizeof(step2_buf));
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
/* extract 4-byte firmware version from step2_buf[8] */
|
||||
private->firmware_version = le32_to_cpu(*(__le32 *)(step2_buf + 8));
|
||||
usb_audio_info(mixer->chip,
|
||||
"Firmware version %d\n",
|
||||
private->firmware_version);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get the flash segment numbers for the App_Settings and App_Upgrade
|
||||
* segments and put them in the private data
|
||||
*/
|
||||
static int scarlett2_get_flash_segment_nums(struct usb_mixer_interface *mixer)
|
||||
{
|
||||
struct scarlett2_data *private = mixer->private_data;
|
||||
int err, count, i;
|
||||
|
||||
struct {
|
||||
__le32 size;
|
||||
__le32 count;
|
||||
u8 unknown[8];
|
||||
} __packed flash_info;
|
||||
|
||||
struct {
|
||||
__le32 size;
|
||||
__le32 flags;
|
||||
char name[16];
|
||||
} __packed segment_info;
|
||||
|
||||
err = scarlett2_usb(mixer, SCARLETT2_USB_INFO_FLASH,
|
||||
NULL, 0,
|
||||
&flash_info, sizeof(flash_info));
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
count = le32_to_cpu(flash_info.count);
|
||||
|
||||
/* sanity check count */
|
||||
if (count < SCARLETT2_SEGMENT_NUM_MIN ||
|
||||
count > SCARLETT2_SEGMENT_NUM_MAX + 1) {
|
||||
usb_audio_err(mixer->chip,
|
||||
"invalid flash segment count: %d\n", count);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
__le32 segment_num_req = cpu_to_le32(i);
|
||||
int flash_segment_id;
|
||||
|
||||
err = scarlett2_usb(mixer, SCARLETT2_USB_INFO_SEGMENT,
|
||||
&segment_num_req, sizeof(segment_num_req),
|
||||
&segment_info, sizeof(segment_info));
|
||||
if (err < 0) {
|
||||
usb_audio_err(mixer->chip,
|
||||
"failed to get flash segment info %d: %d\n",
|
||||
i, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (!strncmp(segment_info.name,
|
||||
SCARLETT2_SEGMENT_SETTINGS_NAME, 16))
|
||||
flash_segment_id = SCARLETT2_SEGMENT_ID_SETTINGS;
|
||||
else if (!strncmp(segment_info.name,
|
||||
SCARLETT2_SEGMENT_FIRMWARE_NAME, 16))
|
||||
flash_segment_id = SCARLETT2_SEGMENT_ID_FIRMWARE;
|
||||
else
|
||||
continue;
|
||||
|
||||
private->flash_segment_nums[flash_segment_id] = i;
|
||||
private->flash_segment_blocks[flash_segment_id] =
|
||||
le32_to_cpu(segment_info.size) /
|
||||
SCARLETT2_FLASH_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
/* segment 0 is App_Gold and we never want to touch that, so
|
||||
* use 0 as the "not-found" value
|
||||
*/
|
||||
if (!private->flash_segment_nums[SCARLETT2_SEGMENT_ID_SETTINGS]) {
|
||||
usb_audio_err(mixer->chip,
|
||||
"failed to find flash segment %s\n",
|
||||
SCARLETT2_SEGMENT_SETTINGS_NAME);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!private->flash_segment_nums[SCARLETT2_SEGMENT_ID_FIRMWARE]) {
|
||||
usb_audio_err(mixer->chip,
|
||||
"failed to find flash segment %s\n",
|
||||
SCARLETT2_SEGMENT_FIRMWARE_NAME);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read configuration from the interface on start */
|
||||
static int scarlett2_read_configs(struct usb_mixer_interface *mixer)
|
||||
{
|
||||
struct scarlett2_data *private = mixer->private_data;
|
||||
const struct scarlett2_device_info *info = private->info;
|
||||
int err, i;
|
||||
|
||||
if (scarlett2_has_config_item(private, SCARLETT2_CONFIG_MSD_SWITCH)) {
|
||||
err = scarlett2_usb_get_config(
|
||||
mixer, SCARLETT2_CONFIG_MSD_SWITCH,
|
||||
1, &private->msd_switch);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (private->firmware_version < info->min_firmware_version) {
|
||||
usb_audio_err(mixer->chip,
|
||||
"Focusrite %s firmware version %d is too old; "
|
||||
"need %d",
|
||||
private->series_name,
|
||||
private->firmware_version,
|
||||
info->min_firmware_version);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* no other controls are created if MSD mode is on */
|
||||
if (private->msd_switch)
|
||||
return 0;
|
||||
|
||||
err = scarlett2_update_input_level(mixer);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = scarlett2_update_input_pad(mixer);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = scarlett2_update_input_air(mixer);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = scarlett2_update_input_phantom(mixer);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = scarlett2_update_direct_monitor(mixer);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
/* the rest of the configuration is for devices with a mixer */
|
||||
if (!scarlett2_has_mixer(private))
|
||||
return 0;
|
||||
|
||||
err = scarlett2_update_monitor_mix(mixer);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = scarlett2_update_monitor_other(mixer);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (scarlett2_has_config_item(private,
|
||||
SCARLETT2_CONFIG_STANDALONE_SWITCH)) {
|
||||
err = scarlett2_usb_get_config(
|
||||
mixer, SCARLETT2_CONFIG_STANDALONE_SWITCH,
|
||||
1, &private->standalone_switch);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (scarlett2_has_config_item(private,
|
||||
SCARLETT2_CONFIG_POWER_EXT)) {
|
||||
err = scarlett2_update_power_status(mixer);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
err = scarlett2_update_sync(mixer);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (scarlett2_has_config_item(private,
|
||||
SCARLETT2_CONFIG_LINE_OUT_VOLUME)) {
|
||||
s16 sw_vol[SCARLETT2_ANALOGUE_MAX];
|
||||
|
||||
/* read SW line out volume */
|
||||
err = scarlett2_usb_get_config(
|
||||
mixer, SCARLETT2_CONFIG_LINE_OUT_VOLUME,
|
||||
private->num_line_out, &sw_vol);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
for (i = 0; i < private->num_line_out; i++)
|
||||
private->vol[i] = clamp(
|
||||
sw_vol[i] + SCARLETT2_VOLUME_BIAS,
|
||||
0, SCARLETT2_VOLUME_BIAS);
|
||||
|
||||
/* read SW mute */
|
||||
err = scarlett2_usb_get_config(
|
||||
mixer, SCARLETT2_CONFIG_MUTE_SWITCH,
|
||||
private->num_line_out, &private->mute_switch);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
for (i = 0; i < private->num_line_out; i++)
|
||||
private->mute_switch[i] =
|
||||
!!private->mute_switch[i];
|
||||
|
||||
/* read SW/HW switches */
|
||||
if (scarlett2_has_config_item(private,
|
||||
SCARLETT2_CONFIG_SW_HW_SWITCH)) {
|
||||
err = scarlett2_usb_get_config(
|
||||
mixer, SCARLETT2_CONFIG_SW_HW_SWITCH,
|
||||
private->num_line_out,
|
||||
&private->vol_sw_hw_switch);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
for (i = 0; i < private->num_line_out; i++)
|
||||
private->vol_sw_hw_switch[i] =
|
||||
!!private->vol_sw_hw_switch[i];
|
||||
}
|
||||
}
|
||||
|
||||
err = scarlett2_update_volumes(mixer);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = scarlett2_update_dim_mute(mixer);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = scarlett2_update_input_select(mixer);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = scarlett2_update_input_gain(mixer);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = scarlett2_update_autogain(mixer);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = scarlett2_update_input_safe(mixer);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (scarlett2_has_config_item(private,
|
||||
SCARLETT2_CONFIG_PCM_INPUT_SWITCH)) {
|
||||
err = scarlett2_update_pcm_input_switch(mixer);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
err = scarlett2_update_mix(mixer);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
return scarlett2_usb_get_mux(mixer);
|
||||
}
|
||||
/*** Notification Handlers ***/
|
||||
|
||||
/* Notify on sync change */
|
||||
static void scarlett2_notify_sync(struct usb_mixer_interface *mixer)
|
||||
@@ -7146,6 +6741,126 @@ requeue:
|
||||
}
|
||||
}
|
||||
|
||||
/*** Cleanup/Suspend Callbacks ***/
|
||||
|
||||
static void scarlett2_private_free(struct usb_mixer_interface *mixer)
|
||||
{
|
||||
struct scarlett2_data *private = mixer->private_data;
|
||||
|
||||
cancel_delayed_work_sync(&private->work);
|
||||
kfree(private);
|
||||
mixer->private_data = NULL;
|
||||
}
|
||||
|
||||
static void scarlett2_private_suspend(struct usb_mixer_interface *mixer)
|
||||
{
|
||||
struct scarlett2_data *private = mixer->private_data;
|
||||
|
||||
if (cancel_delayed_work_sync(&private->work))
|
||||
scarlett2_config_save(private->mixer);
|
||||
}
|
||||
|
||||
/*** Initialisation ***/
|
||||
|
||||
static void scarlett2_count_io(struct scarlett2_data *private)
|
||||
{
|
||||
const struct scarlett2_device_info *info = private->info;
|
||||
const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count;
|
||||
int port_type, srcs = 0, dsts = 0;
|
||||
|
||||
/* Count the number of mux sources and destinations */
|
||||
for (port_type = 0;
|
||||
port_type < SCARLETT2_PORT_TYPE_COUNT;
|
||||
port_type++) {
|
||||
srcs += port_count[port_type][SCARLETT2_PORT_IN];
|
||||
dsts += port_count[port_type][SCARLETT2_PORT_OUT];
|
||||
}
|
||||
|
||||
private->num_mux_srcs = srcs;
|
||||
private->num_mux_dsts = dsts;
|
||||
|
||||
/* Mixer inputs are mux outputs and vice versa.
|
||||
* Scarlett Gen 4 DSP I/O uses SCARLETT2_PORT_TYPE_MIX but
|
||||
* doesn't have mixer controls.
|
||||
*/
|
||||
private->num_mix_in =
|
||||
port_count[SCARLETT2_PORT_TYPE_MIX][SCARLETT2_PORT_OUT] -
|
||||
info->dsp_count;
|
||||
|
||||
private->num_mix_out =
|
||||
port_count[SCARLETT2_PORT_TYPE_MIX][SCARLETT2_PORT_IN] -
|
||||
info->dsp_count;
|
||||
|
||||
/* Number of analogue line outputs */
|
||||
private->num_line_out =
|
||||
port_count[SCARLETT2_PORT_TYPE_ANALOGUE][SCARLETT2_PORT_OUT];
|
||||
|
||||
/* Number of monitor mix controls */
|
||||
private->num_monitor_mix_ctls =
|
||||
info->direct_monitor * 2 * private->num_mix_in;
|
||||
}
|
||||
|
||||
/* Look through the interface descriptors for the Focusrite Control
|
||||
* interface (bInterfaceClass = 255 Vendor Specific Class) and set
|
||||
* bInterfaceNumber, bEndpointAddress, wMaxPacketSize, and bInterval
|
||||
* in private
|
||||
*/
|
||||
static int scarlett2_find_fc_interface(struct usb_device *dev,
|
||||
struct scarlett2_data *private)
|
||||
{
|
||||
struct usb_host_config *config = dev->actconfig;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < config->desc.bNumInterfaces; i++) {
|
||||
struct usb_interface *intf = config->interface[i];
|
||||
struct usb_interface_descriptor *desc =
|
||||
&intf->altsetting[0].desc;
|
||||
struct usb_endpoint_descriptor *epd;
|
||||
|
||||
if (desc->bInterfaceClass != 255)
|
||||
continue;
|
||||
|
||||
epd = get_endpoint(intf->altsetting, 0);
|
||||
private->bInterfaceNumber = desc->bInterfaceNumber;
|
||||
private->bEndpointAddress = epd->bEndpointAddress &
|
||||
USB_ENDPOINT_NUMBER_MASK;
|
||||
private->wMaxPacketSize = le16_to_cpu(epd->wMaxPacketSize);
|
||||
private->bInterval = epd->bInterval;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Initialise private data */
|
||||
static int scarlett2_init_private(struct usb_mixer_interface *mixer,
|
||||
const struct scarlett2_device_entry *entry)
|
||||
{
|
||||
struct scarlett2_data *private =
|
||||
kzalloc(sizeof(struct scarlett2_data), GFP_KERNEL);
|
||||
|
||||
if (!private)
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_init(&private->usb_mutex);
|
||||
mutex_init(&private->data_mutex);
|
||||
INIT_DELAYED_WORK(&private->work, scarlett2_config_save_work);
|
||||
|
||||
mixer->private_data = private;
|
||||
mixer->private_free = scarlett2_private_free;
|
||||
mixer->private_suspend = scarlett2_private_suspend;
|
||||
|
||||
private->info = entry->info;
|
||||
private->config_set = entry->info->config_set;
|
||||
private->series_name = entry->series_name;
|
||||
scarlett2_count_io(private);
|
||||
private->scarlett2_seq = 0;
|
||||
private->mixer = mixer;
|
||||
|
||||
return scarlett2_find_fc_interface(mixer->chip->dev, private);
|
||||
}
|
||||
|
||||
/* Submit a URB to receive notifications from the device */
|
||||
static int scarlett2_init_notify(struct usb_mixer_interface *mixer)
|
||||
{
|
||||
struct usb_device *dev = mixer->chip->dev;
|
||||
@@ -7177,6 +6892,294 @@ static int scarlett2_init_notify(struct usb_mixer_interface *mixer)
|
||||
return usb_submit_urb(mixer->urb, GFP_KERNEL);
|
||||
}
|
||||
|
||||
/* Cargo cult proprietary initialisation sequence */
|
||||
static int scarlett2_usb_init(struct usb_mixer_interface *mixer)
|
||||
{
|
||||
struct usb_device *dev = mixer->chip->dev;
|
||||
struct scarlett2_data *private = mixer->private_data;
|
||||
u8 step0_buf[24];
|
||||
u8 step2_buf[84];
|
||||
int err;
|
||||
|
||||
if (usb_pipe_type_check(dev, usb_sndctrlpipe(dev, 0)))
|
||||
return -EINVAL;
|
||||
|
||||
/* step 0 */
|
||||
err = scarlett2_usb_rx(dev, private->bInterfaceNumber,
|
||||
SCARLETT2_USB_CMD_INIT,
|
||||
step0_buf, sizeof(step0_buf));
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
/* step 1 */
|
||||
private->scarlett2_seq = 1;
|
||||
err = scarlett2_usb(mixer, SCARLETT2_USB_INIT_1, NULL, 0, NULL, 0);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
/* step 2 */
|
||||
private->scarlett2_seq = 1;
|
||||
err = scarlett2_usb(mixer, SCARLETT2_USB_INIT_2,
|
||||
NULL, 0,
|
||||
step2_buf, sizeof(step2_buf));
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
/* extract 4-byte firmware version from step2_buf[8] */
|
||||
private->firmware_version = le32_to_cpu(*(__le32 *)(step2_buf + 8));
|
||||
usb_audio_info(mixer->chip,
|
||||
"Firmware version %d\n",
|
||||
private->firmware_version);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get the flash segment numbers for the App_Settings and App_Upgrade
|
||||
* segments and put them in the private data
|
||||
*/
|
||||
static int scarlett2_get_flash_segment_nums(struct usb_mixer_interface *mixer)
|
||||
{
|
||||
struct scarlett2_data *private = mixer->private_data;
|
||||
int err, count, i;
|
||||
|
||||
struct {
|
||||
__le32 size;
|
||||
__le32 count;
|
||||
u8 unknown[8];
|
||||
} __packed flash_info;
|
||||
|
||||
struct {
|
||||
__le32 size;
|
||||
__le32 flags;
|
||||
char name[16];
|
||||
} __packed segment_info;
|
||||
|
||||
err = scarlett2_usb(mixer, SCARLETT2_USB_INFO_FLASH,
|
||||
NULL, 0,
|
||||
&flash_info, sizeof(flash_info));
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
count = le32_to_cpu(flash_info.count);
|
||||
|
||||
/* sanity check count */
|
||||
if (count < SCARLETT2_SEGMENT_NUM_MIN ||
|
||||
count > SCARLETT2_SEGMENT_NUM_MAX + 1) {
|
||||
usb_audio_err(mixer->chip,
|
||||
"invalid flash segment count: %d\n", count);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
__le32 segment_num_req = cpu_to_le32(i);
|
||||
int flash_segment_id;
|
||||
|
||||
err = scarlett2_usb(mixer, SCARLETT2_USB_INFO_SEGMENT,
|
||||
&segment_num_req, sizeof(segment_num_req),
|
||||
&segment_info, sizeof(segment_info));
|
||||
if (err < 0) {
|
||||
usb_audio_err(mixer->chip,
|
||||
"failed to get flash segment info %d: %d\n",
|
||||
i, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (!strncmp(segment_info.name,
|
||||
SCARLETT2_SEGMENT_SETTINGS_NAME, 16))
|
||||
flash_segment_id = SCARLETT2_SEGMENT_ID_SETTINGS;
|
||||
else if (!strncmp(segment_info.name,
|
||||
SCARLETT2_SEGMENT_FIRMWARE_NAME, 16))
|
||||
flash_segment_id = SCARLETT2_SEGMENT_ID_FIRMWARE;
|
||||
else
|
||||
continue;
|
||||
|
||||
private->flash_segment_nums[flash_segment_id] = i;
|
||||
private->flash_segment_blocks[flash_segment_id] =
|
||||
le32_to_cpu(segment_info.size) /
|
||||
SCARLETT2_FLASH_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
/* segment 0 is App_Gold and we never want to touch that, so
|
||||
* use 0 as the "not-found" value
|
||||
*/
|
||||
if (!private->flash_segment_nums[SCARLETT2_SEGMENT_ID_SETTINGS]) {
|
||||
usb_audio_err(mixer->chip,
|
||||
"failed to find flash segment %s\n",
|
||||
SCARLETT2_SEGMENT_SETTINGS_NAME);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!private->flash_segment_nums[SCARLETT2_SEGMENT_ID_FIRMWARE]) {
|
||||
usb_audio_err(mixer->chip,
|
||||
"failed to find flash segment %s\n",
|
||||
SCARLETT2_SEGMENT_FIRMWARE_NAME);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read configuration from the interface on start */
|
||||
static int scarlett2_read_configs(struct usb_mixer_interface *mixer)
|
||||
{
|
||||
struct scarlett2_data *private = mixer->private_data;
|
||||
const struct scarlett2_device_info *info = private->info;
|
||||
int err, i;
|
||||
|
||||
if (scarlett2_has_config_item(private, SCARLETT2_CONFIG_MSD_SWITCH)) {
|
||||
err = scarlett2_usb_get_config(
|
||||
mixer, SCARLETT2_CONFIG_MSD_SWITCH,
|
||||
1, &private->msd_switch);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (private->firmware_version < info->min_firmware_version) {
|
||||
usb_audio_err(mixer->chip,
|
||||
"Focusrite %s firmware version %d is too old; "
|
||||
"need %d",
|
||||
private->series_name,
|
||||
private->firmware_version,
|
||||
info->min_firmware_version);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* no other controls are created if MSD mode is on */
|
||||
if (private->msd_switch)
|
||||
return 0;
|
||||
|
||||
err = scarlett2_update_input_level(mixer);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = scarlett2_update_input_pad(mixer);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = scarlett2_update_input_air(mixer);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = scarlett2_update_input_phantom(mixer);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = scarlett2_update_direct_monitor(mixer);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
/* the rest of the configuration is for devices with a mixer */
|
||||
if (!scarlett2_has_mixer(private))
|
||||
return 0;
|
||||
|
||||
err = scarlett2_update_monitor_mix(mixer);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = scarlett2_update_monitor_other(mixer);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (scarlett2_has_config_item(private,
|
||||
SCARLETT2_CONFIG_STANDALONE_SWITCH)) {
|
||||
err = scarlett2_usb_get_config(
|
||||
mixer, SCARLETT2_CONFIG_STANDALONE_SWITCH,
|
||||
1, &private->standalone_switch);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (scarlett2_has_config_item(private,
|
||||
SCARLETT2_CONFIG_POWER_EXT)) {
|
||||
err = scarlett2_update_power_status(mixer);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
err = scarlett2_update_sync(mixer);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (scarlett2_has_config_item(private,
|
||||
SCARLETT2_CONFIG_LINE_OUT_VOLUME)) {
|
||||
s16 sw_vol[SCARLETT2_ANALOGUE_MAX];
|
||||
|
||||
/* read SW line out volume */
|
||||
err = scarlett2_usb_get_config(
|
||||
mixer, SCARLETT2_CONFIG_LINE_OUT_VOLUME,
|
||||
private->num_line_out, &sw_vol);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
for (i = 0; i < private->num_line_out; i++)
|
||||
private->vol[i] = clamp(
|
||||
sw_vol[i] + SCARLETT2_VOLUME_BIAS,
|
||||
0, SCARLETT2_VOLUME_BIAS);
|
||||
|
||||
/* read SW mute */
|
||||
err = scarlett2_usb_get_config(
|
||||
mixer, SCARLETT2_CONFIG_MUTE_SWITCH,
|
||||
private->num_line_out, &private->mute_switch);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
for (i = 0; i < private->num_line_out; i++)
|
||||
private->mute_switch[i] =
|
||||
!!private->mute_switch[i];
|
||||
|
||||
/* read SW/HW switches */
|
||||
if (scarlett2_has_config_item(private,
|
||||
SCARLETT2_CONFIG_SW_HW_SWITCH)) {
|
||||
err = scarlett2_usb_get_config(
|
||||
mixer, SCARLETT2_CONFIG_SW_HW_SWITCH,
|
||||
private->num_line_out,
|
||||
&private->vol_sw_hw_switch);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
for (i = 0; i < private->num_line_out; i++)
|
||||
private->vol_sw_hw_switch[i] =
|
||||
!!private->vol_sw_hw_switch[i];
|
||||
}
|
||||
}
|
||||
|
||||
err = scarlett2_update_volumes(mixer);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = scarlett2_update_dim_mute(mixer);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = scarlett2_update_input_select(mixer);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = scarlett2_update_input_gain(mixer);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = scarlett2_update_autogain(mixer);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = scarlett2_update_input_safe(mixer);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (scarlett2_has_config_item(private,
|
||||
SCARLETT2_CONFIG_PCM_INPUT_SWITCH)) {
|
||||
err = scarlett2_update_pcm_input_switch(mixer);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
err = scarlett2_update_mix(mixer);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
return scarlett2_usb_get_mux(mixer);
|
||||
}
|
||||
|
||||
static const struct scarlett2_device_entry *get_scarlett2_device_entry(
|
||||
struct usb_mixer_interface *mixer)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user