cregit-Linux how code gets into the kernel

Release 4.18 sound/firewire/dice/dice-extension.c

// SPDX-License-Identifier: GPL-2.0
/*
 * dice-extension.c - a part of driver for DICE based devices
 *
 * Copyright (c) 2018 Takashi Sakamoto
 */

#include "dice.h"

/* For TCD2210/2220, TCAT defines extension of application protocol. */


#define DICE_EXT_APP_SPACE		0xffffe0200000uLL


#define DICE_EXT_APP_CAPS_OFFSET	0x00

#define DICE_EXT_APP_CAPS_SIZE		0x04

#define DICE_EXT_APP_CMD_OFFSET		0x08

#define DICE_EXT_APP_CMD_SIZE		0x0c

#define DICE_EXT_APP_MIXER_OFFSET	0x10

#define DICE_EXT_APP_MIXER_SIZE		0x14

#define DICE_EXT_APP_PEAK_OFFSET	0x18

#define DICE_EXT_APP_PEAK_SIZE		0x1c

#define DICE_EXT_APP_ROUTER_OFFSET	0x20

#define DICE_EXT_APP_ROUTER_SIZE	0x24

#define DICE_EXT_APP_STREAM_OFFSET	0x28

#define DICE_EXT_APP_STREAM_SIZE	0x2c

#define DICE_EXT_APP_CURRENT_OFFSET	0x30

#define DICE_EXT_APP_CURRENT_SIZE	0x34

#define DICE_EXT_APP_STANDALONE_OFFSET	0x38

#define DICE_EXT_APP_STANDALONE_SIZE	0x3c

#define DICE_EXT_APP_APPLICATION_OFFSET	0x40

#define DICE_EXT_APP_APPLICATION_SIZE	0x44


#define EXT_APP_STREAM_TX_NUMBER	0x0000

#define EXT_APP_STREAM_RX_NUMBER	0x0004

#define EXT_APP_STREAM_ENTRIES		0x0008

#define EXT_APP_STREAM_ENTRY_SIZE	0x010c

#define  EXT_APP_NUMBER_AUDIO		0x0000

#define  EXT_APP_NUMBER_MIDI		0x0004

#define  EXT_APP_NAMES			0x0008

#define   EXT_APP_NAMES_SIZE		256

#define  EXT_APP_AC3			0x0108


#define EXT_APP_CONFIG_LOW_ROUTER	0x0000

#define EXT_APP_CONFIG_LOW_STREAM	0x1000

#define EXT_APP_CONFIG_MIDDLE_ROUTER	0x2000

#define EXT_APP_CONFIG_MIDDLE_STREAM	0x3000

#define EXT_APP_CONFIG_HIGH_ROUTER	0x4000

#define EXT_APP_CONFIG_HIGH_STREAM	0x5000


static inline int read_transaction(struct snd_dice *dice, u64 section_addr, u32 offset, void *buf, size_t len) { return snd_fw_transaction(dice->unit, len == 4 ? TCODE_READ_QUADLET_REQUEST : TCODE_READ_BLOCK_REQUEST, section_addr + offset, buf, len, 0); }

Contributors

PersonTokensPropCommitsCommitProp
Takashi Sakamoto51100.00%1100.00%
Total51100.00%1100.00%


static int read_stream_entries(struct snd_dice *dice, u64 section_addr, u32 base_offset, unsigned int stream_count, unsigned int mode, unsigned int pcm_channels[MAX_STREAMS][3], unsigned int midi_ports[MAX_STREAMS]) { u32 entry_offset; __be32 reg[2]; int err; int i; for (i = 0; i < stream_count; ++i) { entry_offset = base_offset + i * EXT_APP_STREAM_ENTRY_SIZE; err = read_transaction(dice, section_addr, entry_offset + EXT_APP_NUMBER_AUDIO, reg, sizeof(reg)); if (err < 0) return err; pcm_channels[i][mode] = be32_to_cpu(reg[0]); midi_ports[i] = max(midi_ports[i], be32_to_cpu(reg[1])); } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Takashi Sakamoto149100.00%1100.00%
Total149100.00%1100.00%


static int detect_stream_formats(struct snd_dice *dice, u64 section_addr) { u32 base_offset; __be32 reg[2]; unsigned int stream_count; int mode; int err = 0; for (mode = 0; mode < SND_DICE_RATE_MODE_COUNT; ++mode) { unsigned int cap; /* * Some models report stream formats at highest mode, however * they don't support the mode. Check clock capabilities. */ if (mode == 2) { cap = CLOCK_CAP_RATE_176400 | CLOCK_CAP_RATE_192000; } else if (mode == 1) { cap = CLOCK_CAP_RATE_88200 | CLOCK_CAP_RATE_96000; } else { cap = CLOCK_CAP_RATE_32000 | CLOCK_CAP_RATE_44100 | CLOCK_CAP_RATE_48000; } if (!(cap & dice->clock_caps)) continue; base_offset = 0x2000 * mode + 0x1000; err = read_transaction(dice, section_addr, base_offset + EXT_APP_STREAM_TX_NUMBER, &reg, sizeof(reg)); if (err < 0) break; base_offset += EXT_APP_STREAM_ENTRIES; stream_count = be32_to_cpu(reg[0]); err = read_stream_entries(dice, section_addr, base_offset, stream_count, mode, dice->tx_pcm_chs, dice->tx_midi_ports); if (err < 0) break; base_offset += stream_count * EXT_APP_STREAM_ENTRY_SIZE; stream_count = be32_to_cpu(reg[1]); err = read_stream_entries(dice, section_addr, base_offset, stream_count, mode, dice->rx_pcm_chs, dice->rx_midi_ports); if (err < 0) break; } return err; }

Contributors

PersonTokensPropCommitsCommitProp
Takashi Sakamoto236100.00%1100.00%
Total236100.00%1100.00%


int snd_dice_detect_extension_formats(struct snd_dice *dice) { __be32 *pointers; unsigned int i; u64 section_addr; int err; pointers = kmalloc_array(9, sizeof(__be32) * 2, GFP_KERNEL); if (pointers == NULL) return -ENOMEM; err = snd_fw_transaction(dice->unit, TCODE_READ_BLOCK_REQUEST, DICE_EXT_APP_SPACE, pointers, 9 * sizeof(__be32) * 2, 0); if (err < 0) goto end; /* Check two of them for offset have the same value or not. */ for (i = 0; i < 9; ++i) { int j; for (j = i + 1; j < 9; ++j) { if (pointers[i * 2] == pointers[j * 2]) goto end; } } section_addr = DICE_EXT_APP_SPACE + be32_to_cpu(pointers[12]) * 4; err = detect_stream_formats(dice, section_addr); end: kfree(pointers); return err; }

Contributors

PersonTokensPropCommitsCommitProp
Takashi Sakamoto173100.00%1100.00%
Total173100.00%1100.00%


Overall Contributors

PersonTokensPropCommitsCommitProp
Takashi Sakamoto751100.00%1100.00%
Total751100.00%1100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.