Commit 34101a0f authored by Geoffrey D. Bennett's avatar Geoffrey D. Bennett Committed by Takashi Iwai
Browse files

ALSA: scarlett2: Retrieve useful flash segment numbers



Call SCARLETT2_USB_INFO_FLASH and SCARLETT2_USB_INFO_SEGMENT to find
the App_Settings and App_Upgrade flash segment numbers, and store them
in the scarlett2_data struct. These will be used later to implement
reset to factory defaults and firmware upgrade functions.

Signed-off-by: default avatarGeoffrey D. Bennett <g@b4.vu>
Link: https://lore.kernel.org/r/70f0108a9cf99b69f7aa920c4bcdb0cf4bf3da98.1703001053.git.g@b4.vu


Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 103c23cc
Loading
Loading
Loading
Loading
+103 −0
Original line number Diff line number Diff line
@@ -190,6 +190,11 @@ static const u16 scarlett2_mixer_values[SCARLETT2_MIXER_VALUE_COUNT] = {
	16345
};

/* Flash segments that we may manipulate */
#define SCARLETT2_SEGMENT_ID_SETTINGS 0
#define SCARLETT2_SEGMENT_ID_FIRMWARE 1
#define SCARLETT2_SEGMENT_ID_COUNT 2

/* Maximum number of analogue outputs */
#define SCARLETT2_ANALOGUE_MAX 10

@@ -429,6 +434,8 @@ struct scarlett2_data {
	int num_mux_srcs;
	int num_mux_dsts;
	u32 firmware_version;
	u8 flash_segment_nums[SCARLETT2_SEGMENT_ID_COUNT];
	u8 flash_segment_blocks[SCARLETT2_SEGMENT_ID_COUNT];
	u16 scarlett2_seq;
	u8 sync_updated;
	u8 vol_updated;
@@ -1160,6 +1167,13 @@ static int scarlett2_get_port_start_num(
#define SCARLETT2_USB_VOLUME_STATUS_OFFSET 0x31
#define SCARLETT2_USB_METER_LEVELS_GET_MAGIC 1

#define SCARLETT2_FLASH_BLOCK_SIZE 4096
#define SCARLETT2_SEGMENT_NUM_MIN 1
#define SCARLETT2_SEGMENT_NUM_MAX 4

#define SCARLETT2_SEGMENT_SETTINGS_NAME "App_Settings"
#define SCARLETT2_SEGMENT_FIRMWARE_NAME "App_Upgrade"

/* volume status is read together (matches scarlett2_config_items[1]) */
struct scarlett2_usb_volume_status {
	/* dim/mute buttons */
@@ -4202,6 +4216,90 @@ static int scarlett2_usb_init(struct usb_mixer_interface *mixer)
	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)
{
@@ -4517,6 +4615,11 @@ static int snd_scarlett2_controls_create(
	if (err < 0)
		return err;

	/* Get the upgrade & settings flash segment numbers */
	err = scarlett2_get_flash_segment_nums(mixer);
	if (err < 0)
		return err;

	/* Add firmware version control */
	err = scarlett2_add_firmware_version_ctl(mixer);
	if (err < 0)