18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Driver for the Korg 1212 IO PCI card 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (c) 2001 Haroldo Gamal <gamal@alternex.com.br> 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <linux/delay.h> 98c2ecf20Sopenharmony_ci#include <linux/init.h> 108c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 118c2ecf20Sopenharmony_ci#include <linux/pci.h> 128c2ecf20Sopenharmony_ci#include <linux/slab.h> 138c2ecf20Sopenharmony_ci#include <linux/wait.h> 148c2ecf20Sopenharmony_ci#include <linux/module.h> 158c2ecf20Sopenharmony_ci#include <linux/mutex.h> 168c2ecf20Sopenharmony_ci#include <linux/firmware.h> 178c2ecf20Sopenharmony_ci#include <linux/io.h> 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci#include <sound/core.h> 208c2ecf20Sopenharmony_ci#include <sound/info.h> 218c2ecf20Sopenharmony_ci#include <sound/control.h> 228c2ecf20Sopenharmony_ci#include <sound/pcm.h> 238c2ecf20Sopenharmony_ci#include <sound/pcm_params.h> 248c2ecf20Sopenharmony_ci#include <sound/initval.h> 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci// ---------------------------------------------------------------------------- 278c2ecf20Sopenharmony_ci// Debug Stuff 288c2ecf20Sopenharmony_ci// ---------------------------------------------------------------------------- 298c2ecf20Sopenharmony_ci#define K1212_DEBUG_LEVEL 0 308c2ecf20Sopenharmony_ci#if K1212_DEBUG_LEVEL > 0 318c2ecf20Sopenharmony_ci#define K1212_DEBUG_PRINTK(fmt,args...) printk(KERN_DEBUG fmt,##args) 328c2ecf20Sopenharmony_ci#else 338c2ecf20Sopenharmony_ci#define K1212_DEBUG_PRINTK(fmt,...) do { } while (0) 348c2ecf20Sopenharmony_ci#endif 358c2ecf20Sopenharmony_ci#if K1212_DEBUG_LEVEL > 1 368c2ecf20Sopenharmony_ci#define K1212_DEBUG_PRINTK_VERBOSE(fmt,args...) printk(KERN_DEBUG fmt,##args) 378c2ecf20Sopenharmony_ci#else 388c2ecf20Sopenharmony_ci#define K1212_DEBUG_PRINTK_VERBOSE(fmt,...) 398c2ecf20Sopenharmony_ci#endif 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci// ---------------------------------------------------------------------------- 428c2ecf20Sopenharmony_ci// Record/Play Buffer Allocation Method. If K1212_LARGEALLOC is defined all 438c2ecf20Sopenharmony_ci// buffers are alocated as a large piece inside KorgSharedBuffer. 448c2ecf20Sopenharmony_ci// ---------------------------------------------------------------------------- 458c2ecf20Sopenharmony_ci//#define K1212_LARGEALLOC 1 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci// ---------------------------------------------------------------------------- 488c2ecf20Sopenharmony_ci// Valid states of the Korg 1212 I/O card. 498c2ecf20Sopenharmony_ci// ---------------------------------------------------------------------------- 508c2ecf20Sopenharmony_cienum CardState { 518c2ecf20Sopenharmony_ci K1212_STATE_NONEXISTENT, // there is no card here 528c2ecf20Sopenharmony_ci K1212_STATE_UNINITIALIZED, // the card is awaiting DSP download 538c2ecf20Sopenharmony_ci K1212_STATE_DSP_IN_PROCESS, // the card is currently downloading its DSP code 548c2ecf20Sopenharmony_ci K1212_STATE_DSP_COMPLETE, // the card has finished the DSP download 558c2ecf20Sopenharmony_ci K1212_STATE_READY, // the card can be opened by an application. Any application 568c2ecf20Sopenharmony_ci // requests prior to this state should fail. Only an open 578c2ecf20Sopenharmony_ci // request can be made at this state. 588c2ecf20Sopenharmony_ci K1212_STATE_OPEN, // an application has opened the card 598c2ecf20Sopenharmony_ci K1212_STATE_SETUP, // the card has been setup for play 608c2ecf20Sopenharmony_ci K1212_STATE_PLAYING, // the card is playing 618c2ecf20Sopenharmony_ci K1212_STATE_MONITOR, // the card is in the monitor mode 628c2ecf20Sopenharmony_ci K1212_STATE_CALIBRATING, // the card is currently calibrating 638c2ecf20Sopenharmony_ci K1212_STATE_ERRORSTOP, // the card has stopped itself because of an error and we 648c2ecf20Sopenharmony_ci // are in the process of cleaning things up. 658c2ecf20Sopenharmony_ci K1212_STATE_MAX_STATE // state values of this and beyond are invalid 668c2ecf20Sopenharmony_ci}; 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci// ---------------------------------------------------------------------------- 698c2ecf20Sopenharmony_ci// The following enumeration defines the constants written to the card's 708c2ecf20Sopenharmony_ci// host-to-card doorbell to initiate a command. 718c2ecf20Sopenharmony_ci// ---------------------------------------------------------------------------- 728c2ecf20Sopenharmony_cienum korg1212_dbcnst { 738c2ecf20Sopenharmony_ci K1212_DB_RequestForData = 0, // sent by the card to request a buffer fill. 748c2ecf20Sopenharmony_ci K1212_DB_TriggerPlay = 1, // starts playback/record on the card. 758c2ecf20Sopenharmony_ci K1212_DB_SelectPlayMode = 2, // select monitor, playback setup, or stop. 768c2ecf20Sopenharmony_ci K1212_DB_ConfigureBufferMemory = 3, // tells card where the host audio buffers are. 778c2ecf20Sopenharmony_ci K1212_DB_RequestAdatTimecode = 4, // asks the card for the latest ADAT timecode value. 788c2ecf20Sopenharmony_ci K1212_DB_SetClockSourceRate = 5, // sets the clock source and rate for the card. 798c2ecf20Sopenharmony_ci K1212_DB_ConfigureMiscMemory = 6, // tells card where other buffers are. 808c2ecf20Sopenharmony_ci K1212_DB_TriggerFromAdat = 7, // tells card to trigger from Adat at a specific 818c2ecf20Sopenharmony_ci // timecode value. 828c2ecf20Sopenharmony_ci K1212_DB_DMAERROR = 0x80, // DMA Error - the PCI bus is congestioned. 838c2ecf20Sopenharmony_ci K1212_DB_CARDSTOPPED = 0x81, // Card has stopped by user request. 848c2ecf20Sopenharmony_ci K1212_DB_RebootCard = 0xA0, // instructs the card to reboot. 858c2ecf20Sopenharmony_ci K1212_DB_BootFromDSPPage4 = 0xA4, // instructs the card to boot from the DSP microcode 868c2ecf20Sopenharmony_ci // on page 4 (local page to card). 878c2ecf20Sopenharmony_ci K1212_DB_DSPDownloadDone = 0xAE, // sent by the card to indicate the download has 888c2ecf20Sopenharmony_ci // completed. 898c2ecf20Sopenharmony_ci K1212_DB_StartDSPDownload = 0xAF // tells the card to download its DSP firmware. 908c2ecf20Sopenharmony_ci}; 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci// ---------------------------------------------------------------------------- 948c2ecf20Sopenharmony_ci// The following enumeration defines return codes 958c2ecf20Sopenharmony_ci// to the Korg 1212 I/O driver. 968c2ecf20Sopenharmony_ci// ---------------------------------------------------------------------------- 978c2ecf20Sopenharmony_cienum snd_korg1212rc { 988c2ecf20Sopenharmony_ci K1212_CMDRET_Success = 0, // command was successfully placed 998c2ecf20Sopenharmony_ci K1212_CMDRET_DIOCFailure, // the DeviceIoControl call failed 1008c2ecf20Sopenharmony_ci K1212_CMDRET_PMFailure, // the protected mode call failed 1018c2ecf20Sopenharmony_ci K1212_CMDRET_FailUnspecified, // unspecified failure 1028c2ecf20Sopenharmony_ci K1212_CMDRET_FailBadState, // the specified command can not be given in 1038c2ecf20Sopenharmony_ci // the card's current state. (or the wave device's 1048c2ecf20Sopenharmony_ci // state) 1058c2ecf20Sopenharmony_ci K1212_CMDRET_CardUninitialized, // the card is uninitialized and cannot be used 1068c2ecf20Sopenharmony_ci K1212_CMDRET_BadIndex, // an out of range card index was specified 1078c2ecf20Sopenharmony_ci K1212_CMDRET_BadHandle, // an invalid card handle was specified 1088c2ecf20Sopenharmony_ci K1212_CMDRET_NoFillRoutine, // a play request has been made before a fill routine set 1098c2ecf20Sopenharmony_ci K1212_CMDRET_FillRoutineInUse, // can't set a new fill routine while one is in use 1108c2ecf20Sopenharmony_ci K1212_CMDRET_NoAckFromCard, // the card never acknowledged a command 1118c2ecf20Sopenharmony_ci K1212_CMDRET_BadParams, // bad parameters were provided by the caller 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci K1212_CMDRET_BadDevice, // the specified wave device was out of range 1148c2ecf20Sopenharmony_ci K1212_CMDRET_BadFormat // the specified wave format is unsupported 1158c2ecf20Sopenharmony_ci}; 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci// ---------------------------------------------------------------------------- 1188c2ecf20Sopenharmony_ci// The following enumeration defines the constants used to select the play 1198c2ecf20Sopenharmony_ci// mode for the card in the SelectPlayMode command. 1208c2ecf20Sopenharmony_ci// ---------------------------------------------------------------------------- 1218c2ecf20Sopenharmony_cienum PlayModeSelector { 1228c2ecf20Sopenharmony_ci K1212_MODE_SetupPlay = 0x00000001, // provides card with pre-play information 1238c2ecf20Sopenharmony_ci K1212_MODE_MonitorOn = 0x00000002, // tells card to turn on monitor mode 1248c2ecf20Sopenharmony_ci K1212_MODE_MonitorOff = 0x00000004, // tells card to turn off monitor mode 1258c2ecf20Sopenharmony_ci K1212_MODE_StopPlay = 0x00000008 // stops playback on the card 1268c2ecf20Sopenharmony_ci}; 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci// ---------------------------------------------------------------------------- 1298c2ecf20Sopenharmony_ci// The following enumeration defines the constants used to select the monitor 1308c2ecf20Sopenharmony_ci// mode for the card in the SetMonitorMode command. 1318c2ecf20Sopenharmony_ci// ---------------------------------------------------------------------------- 1328c2ecf20Sopenharmony_cienum MonitorModeSelector { 1338c2ecf20Sopenharmony_ci K1212_MONMODE_Off = 0, // tells card to turn off monitor mode 1348c2ecf20Sopenharmony_ci K1212_MONMODE_On // tells card to turn on monitor mode 1358c2ecf20Sopenharmony_ci}; 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci#define MAILBOX0_OFFSET 0x40 // location of mailbox 0 relative to base address 1388c2ecf20Sopenharmony_ci#define MAILBOX1_OFFSET 0x44 // location of mailbox 1 relative to base address 1398c2ecf20Sopenharmony_ci#define MAILBOX2_OFFSET 0x48 // location of mailbox 2 relative to base address 1408c2ecf20Sopenharmony_ci#define MAILBOX3_OFFSET 0x4c // location of mailbox 3 relative to base address 1418c2ecf20Sopenharmony_ci#define OUT_DOORBELL_OFFSET 0x60 // location of PCI to local doorbell 1428c2ecf20Sopenharmony_ci#define IN_DOORBELL_OFFSET 0x64 // location of local to PCI doorbell 1438c2ecf20Sopenharmony_ci#define STATUS_REG_OFFSET 0x68 // location of interrupt control/status register 1448c2ecf20Sopenharmony_ci#define PCI_CONTROL_OFFSET 0x6c // location of the EEPROM, PCI, User I/O, init control 1458c2ecf20Sopenharmony_ci // register 1468c2ecf20Sopenharmony_ci#define SENS_CONTROL_OFFSET 0x6e // location of the input sensitivity setting register. 1478c2ecf20Sopenharmony_ci // this is the upper word of the PCI control reg. 1488c2ecf20Sopenharmony_ci#define DEV_VEND_ID_OFFSET 0x70 // location of the device and vendor ID register 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci#define MAX_COMMAND_RETRIES 5 // maximum number of times the driver will attempt 1518c2ecf20Sopenharmony_ci // to send a command before giving up. 1528c2ecf20Sopenharmony_ci#define COMMAND_ACK_MASK 0x8000 // the MSB is set in the command acknowledgment from 1538c2ecf20Sopenharmony_ci // the card. 1548c2ecf20Sopenharmony_ci#define DOORBELL_VAL_MASK 0x00FF // the doorbell value is one byte 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci#define CARD_BOOT_DELAY_IN_MS 10 1578c2ecf20Sopenharmony_ci#define CARD_BOOT_TIMEOUT 10 1588c2ecf20Sopenharmony_ci#define DSP_BOOT_DELAY_IN_MS 200 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci#define kNumBuffers 8 1618c2ecf20Sopenharmony_ci#define k1212MaxCards 4 1628c2ecf20Sopenharmony_ci#define k1212NumWaveDevices 6 1638c2ecf20Sopenharmony_ci#define k16BitChannels 10 1648c2ecf20Sopenharmony_ci#define k32BitChannels 2 1658c2ecf20Sopenharmony_ci#define kAudioChannels (k16BitChannels + k32BitChannels) 1668c2ecf20Sopenharmony_ci#define kPlayBufferFrames 1024 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci#define K1212_ANALOG_CHANNELS 2 1698c2ecf20Sopenharmony_ci#define K1212_SPDIF_CHANNELS 2 1708c2ecf20Sopenharmony_ci#define K1212_ADAT_CHANNELS 8 1718c2ecf20Sopenharmony_ci#define K1212_CHANNELS (K1212_ADAT_CHANNELS + K1212_ANALOG_CHANNELS) 1728c2ecf20Sopenharmony_ci#define K1212_MIN_CHANNELS 1 1738c2ecf20Sopenharmony_ci#define K1212_MAX_CHANNELS K1212_CHANNELS 1748c2ecf20Sopenharmony_ci#define K1212_FRAME_SIZE (sizeof(struct KorgAudioFrame)) 1758c2ecf20Sopenharmony_ci#define K1212_MAX_SAMPLES (kPlayBufferFrames*kNumBuffers) 1768c2ecf20Sopenharmony_ci#define K1212_PERIODS (kNumBuffers) 1778c2ecf20Sopenharmony_ci#define K1212_PERIOD_BYTES (K1212_FRAME_SIZE*kPlayBufferFrames) 1788c2ecf20Sopenharmony_ci#define K1212_BUF_SIZE (K1212_PERIOD_BYTES*kNumBuffers) 1798c2ecf20Sopenharmony_ci#define K1212_ANALOG_BUF_SIZE (K1212_ANALOG_CHANNELS * 2 * kPlayBufferFrames * kNumBuffers) 1808c2ecf20Sopenharmony_ci#define K1212_SPDIF_BUF_SIZE (K1212_SPDIF_CHANNELS * 3 * kPlayBufferFrames * kNumBuffers) 1818c2ecf20Sopenharmony_ci#define K1212_ADAT_BUF_SIZE (K1212_ADAT_CHANNELS * 2 * kPlayBufferFrames * kNumBuffers) 1828c2ecf20Sopenharmony_ci#define K1212_MAX_BUF_SIZE (K1212_ANALOG_BUF_SIZE + K1212_ADAT_BUF_SIZE) 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci#define k1212MinADCSens 0x00 1858c2ecf20Sopenharmony_ci#define k1212MaxADCSens 0x7f 1868c2ecf20Sopenharmony_ci#define k1212MaxVolume 0x7fff 1878c2ecf20Sopenharmony_ci#define k1212MaxWaveVolume 0xffff 1888c2ecf20Sopenharmony_ci#define k1212MinVolume 0x0000 1898c2ecf20Sopenharmony_ci#define k1212MaxVolInverted 0x8000 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci// ----------------------------------------------------------------- 1928c2ecf20Sopenharmony_ci// the following bits are used for controlling interrupts in the 1938c2ecf20Sopenharmony_ci// interrupt control/status reg 1948c2ecf20Sopenharmony_ci// ----------------------------------------------------------------- 1958c2ecf20Sopenharmony_ci#define PCI_INT_ENABLE_BIT 0x00000100 1968c2ecf20Sopenharmony_ci#define PCI_DOORBELL_INT_ENABLE_BIT 0x00000200 1978c2ecf20Sopenharmony_ci#define LOCAL_INT_ENABLE_BIT 0x00010000 1988c2ecf20Sopenharmony_ci#define LOCAL_DOORBELL_INT_ENABLE_BIT 0x00020000 1998c2ecf20Sopenharmony_ci#define LOCAL_DMA1_INT_ENABLE_BIT 0x00080000 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci// ----------------------------------------------------------------- 2028c2ecf20Sopenharmony_ci// the following bits are defined for the PCI command register 2038c2ecf20Sopenharmony_ci// ----------------------------------------------------------------- 2048c2ecf20Sopenharmony_ci#define PCI_CMD_MEM_SPACE_ENABLE_BIT 0x0002 2058c2ecf20Sopenharmony_ci#define PCI_CMD_IO_SPACE_ENABLE_BIT 0x0001 2068c2ecf20Sopenharmony_ci#define PCI_CMD_BUS_MASTER_ENABLE_BIT 0x0004 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci// ----------------------------------------------------------------- 2098c2ecf20Sopenharmony_ci// the following bits are defined for the PCI status register 2108c2ecf20Sopenharmony_ci// ----------------------------------------------------------------- 2118c2ecf20Sopenharmony_ci#define PCI_STAT_PARITY_ERROR_BIT 0x8000 2128c2ecf20Sopenharmony_ci#define PCI_STAT_SYSTEM_ERROR_BIT 0x4000 2138c2ecf20Sopenharmony_ci#define PCI_STAT_MASTER_ABORT_RCVD_BIT 0x2000 2148c2ecf20Sopenharmony_ci#define PCI_STAT_TARGET_ABORT_RCVD_BIT 0x1000 2158c2ecf20Sopenharmony_ci#define PCI_STAT_TARGET_ABORT_SENT_BIT 0x0800 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci// ------------------------------------------------------------------------ 2188c2ecf20Sopenharmony_ci// the following constants are used in setting the 1212 I/O card's input 2198c2ecf20Sopenharmony_ci// sensitivity. 2208c2ecf20Sopenharmony_ci// ------------------------------------------------------------------------ 2218c2ecf20Sopenharmony_ci#define SET_SENS_LOCALINIT_BITPOS 15 2228c2ecf20Sopenharmony_ci#define SET_SENS_DATA_BITPOS 10 2238c2ecf20Sopenharmony_ci#define SET_SENS_CLOCK_BITPOS 8 2248c2ecf20Sopenharmony_ci#define SET_SENS_LOADSHIFT_BITPOS 0 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci#define SET_SENS_LEFTCHANID 0x00 2278c2ecf20Sopenharmony_ci#define SET_SENS_RIGHTCHANID 0x01 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci#define K1212SENSUPDATE_DELAY_IN_MS 50 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci// -------------------------------------------------------------------------- 2328c2ecf20Sopenharmony_ci// WaitRTCTicks 2338c2ecf20Sopenharmony_ci// 2348c2ecf20Sopenharmony_ci// This function waits the specified number of real time clock ticks. 2358c2ecf20Sopenharmony_ci// According to the DDK, each tick is ~0.8 microseconds. 2368c2ecf20Sopenharmony_ci// The defines following the function declaration can be used for the 2378c2ecf20Sopenharmony_ci// numTicksToWait parameter. 2388c2ecf20Sopenharmony_ci// -------------------------------------------------------------------------- 2398c2ecf20Sopenharmony_ci#define ONE_RTC_TICK 1 2408c2ecf20Sopenharmony_ci#define SENSCLKPULSE_WIDTH 4 2418c2ecf20Sopenharmony_ci#define LOADSHIFT_DELAY 4 2428c2ecf20Sopenharmony_ci#define INTERCOMMAND_DELAY 40 2438c2ecf20Sopenharmony_ci#define STOPCARD_DELAY 300 // max # RTC ticks for the card to stop once we write 2448c2ecf20Sopenharmony_ci // the command register. (could be up to 180 us) 2458c2ecf20Sopenharmony_ci#define COMMAND_ACK_DELAY 13 // number of RTC ticks to wait for an acknowledgement 2468c2ecf20Sopenharmony_ci // from the card after sending a command. 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_cienum ClockSourceIndex { 2498c2ecf20Sopenharmony_ci K1212_CLKIDX_AdatAt44_1K = 0, // selects source as ADAT at 44.1 kHz 2508c2ecf20Sopenharmony_ci K1212_CLKIDX_AdatAt48K, // selects source as ADAT at 48 kHz 2518c2ecf20Sopenharmony_ci K1212_CLKIDX_WordAt44_1K, // selects source as S/PDIF at 44.1 kHz 2528c2ecf20Sopenharmony_ci K1212_CLKIDX_WordAt48K, // selects source as S/PDIF at 48 kHz 2538c2ecf20Sopenharmony_ci K1212_CLKIDX_LocalAt44_1K, // selects source as local clock at 44.1 kHz 2548c2ecf20Sopenharmony_ci K1212_CLKIDX_LocalAt48K, // selects source as local clock at 48 kHz 2558c2ecf20Sopenharmony_ci K1212_CLKIDX_Invalid // used to check validity of the index 2568c2ecf20Sopenharmony_ci}; 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_cienum ClockSourceType { 2598c2ecf20Sopenharmony_ci K1212_CLKIDX_Adat = 0, // selects source as ADAT 2608c2ecf20Sopenharmony_ci K1212_CLKIDX_Word, // selects source as S/PDIF 2618c2ecf20Sopenharmony_ci K1212_CLKIDX_Local // selects source as local clock 2628c2ecf20Sopenharmony_ci}; 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_cistruct KorgAudioFrame { 2658c2ecf20Sopenharmony_ci u16 frameData16[k16BitChannels]; /* channels 0-9 use 16 bit samples */ 2668c2ecf20Sopenharmony_ci u32 frameData32[k32BitChannels]; /* channels 10-11 use 32 bits - only 20 are sent across S/PDIF */ 2678c2ecf20Sopenharmony_ci u32 timeCodeVal; /* holds the ADAT timecode value */ 2688c2ecf20Sopenharmony_ci}; 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_cistruct KorgAudioBuffer { 2718c2ecf20Sopenharmony_ci struct KorgAudioFrame bufferData[kPlayBufferFrames]; /* buffer definition */ 2728c2ecf20Sopenharmony_ci}; 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_cistruct KorgSharedBuffer { 2758c2ecf20Sopenharmony_ci#ifdef K1212_LARGEALLOC 2768c2ecf20Sopenharmony_ci struct KorgAudioBuffer playDataBufs[kNumBuffers]; 2778c2ecf20Sopenharmony_ci struct KorgAudioBuffer recordDataBufs[kNumBuffers]; 2788c2ecf20Sopenharmony_ci#endif 2798c2ecf20Sopenharmony_ci short volumeData[kAudioChannels]; 2808c2ecf20Sopenharmony_ci u32 cardCommand; 2818c2ecf20Sopenharmony_ci u16 routeData [kAudioChannels]; 2828c2ecf20Sopenharmony_ci u32 AdatTimeCode; // ADAT timecode value 2838c2ecf20Sopenharmony_ci}; 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_cistruct SensBits { 2868c2ecf20Sopenharmony_ci union { 2878c2ecf20Sopenharmony_ci struct { 2888c2ecf20Sopenharmony_ci unsigned int leftChanVal:8; 2898c2ecf20Sopenharmony_ci unsigned int leftChanId:8; 2908c2ecf20Sopenharmony_ci } v; 2918c2ecf20Sopenharmony_ci u16 leftSensBits; 2928c2ecf20Sopenharmony_ci } l; 2938c2ecf20Sopenharmony_ci union { 2948c2ecf20Sopenharmony_ci struct { 2958c2ecf20Sopenharmony_ci unsigned int rightChanVal:8; 2968c2ecf20Sopenharmony_ci unsigned int rightChanId:8; 2978c2ecf20Sopenharmony_ci } v; 2988c2ecf20Sopenharmony_ci u16 rightSensBits; 2998c2ecf20Sopenharmony_ci } r; 3008c2ecf20Sopenharmony_ci}; 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_cistruct snd_korg1212 { 3038c2ecf20Sopenharmony_ci struct snd_card *card; 3048c2ecf20Sopenharmony_ci struct pci_dev *pci; 3058c2ecf20Sopenharmony_ci struct snd_pcm *pcm; 3068c2ecf20Sopenharmony_ci int irq; 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci spinlock_t lock; 3098c2ecf20Sopenharmony_ci struct mutex open_mutex; 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci struct timer_list timer; /* timer callback for checking ack of stop request */ 3128c2ecf20Sopenharmony_ci int stop_pending_cnt; /* counter for stop pending check */ 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci wait_queue_head_t wait; 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci unsigned long iomem; 3178c2ecf20Sopenharmony_ci unsigned long ioport; 3188c2ecf20Sopenharmony_ci unsigned long iomem2; 3198c2ecf20Sopenharmony_ci unsigned long irqcount; 3208c2ecf20Sopenharmony_ci unsigned long inIRQ; 3218c2ecf20Sopenharmony_ci void __iomem *iobase; 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_ci struct snd_dma_buffer dma_dsp; 3248c2ecf20Sopenharmony_ci struct snd_dma_buffer dma_play; 3258c2ecf20Sopenharmony_ci struct snd_dma_buffer dma_rec; 3268c2ecf20Sopenharmony_ci struct snd_dma_buffer dma_shared; 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci u32 DataBufsSize; 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci struct KorgAudioBuffer * playDataBufsPtr; 3318c2ecf20Sopenharmony_ci struct KorgAudioBuffer * recordDataBufsPtr; 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ci struct KorgSharedBuffer * sharedBufferPtr; 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci u32 RecDataPhy; 3368c2ecf20Sopenharmony_ci u32 PlayDataPhy; 3378c2ecf20Sopenharmony_ci unsigned long sharedBufferPhy; 3388c2ecf20Sopenharmony_ci u32 VolumeTablePhy; 3398c2ecf20Sopenharmony_ci u32 RoutingTablePhy; 3408c2ecf20Sopenharmony_ci u32 AdatTimeCodePhy; 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_ci u32 __iomem * statusRegPtr; // address of the interrupt status/control register 3438c2ecf20Sopenharmony_ci u32 __iomem * outDoorbellPtr; // address of the host->card doorbell register 3448c2ecf20Sopenharmony_ci u32 __iomem * inDoorbellPtr; // address of the card->host doorbell register 3458c2ecf20Sopenharmony_ci u32 __iomem * mailbox0Ptr; // address of mailbox 0 on the card 3468c2ecf20Sopenharmony_ci u32 __iomem * mailbox1Ptr; // address of mailbox 1 on the card 3478c2ecf20Sopenharmony_ci u32 __iomem * mailbox2Ptr; // address of mailbox 2 on the card 3488c2ecf20Sopenharmony_ci u32 __iomem * mailbox3Ptr; // address of mailbox 3 on the card 3498c2ecf20Sopenharmony_ci u32 __iomem * controlRegPtr; // address of the EEPROM, PCI, I/O, Init ctrl reg 3508c2ecf20Sopenharmony_ci u16 __iomem * sensRegPtr; // address of the sensitivity setting register 3518c2ecf20Sopenharmony_ci u32 __iomem * idRegPtr; // address of the device and vendor ID registers 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci size_t periodsize; 3548c2ecf20Sopenharmony_ci int channels; 3558c2ecf20Sopenharmony_ci int currentBuffer; 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_ci struct snd_pcm_substream *playback_substream; 3588c2ecf20Sopenharmony_ci struct snd_pcm_substream *capture_substream; 3598c2ecf20Sopenharmony_ci 3608c2ecf20Sopenharmony_ci pid_t capture_pid; 3618c2ecf20Sopenharmony_ci pid_t playback_pid; 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_ci enum CardState cardState; 3648c2ecf20Sopenharmony_ci int running; 3658c2ecf20Sopenharmony_ci int idleMonitorOn; // indicates whether the card is in idle monitor mode. 3668c2ecf20Sopenharmony_ci u32 cmdRetryCount; // tracks how many times we have retried sending to the card. 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_ci enum ClockSourceIndex clkSrcRate; // sample rate and clock source 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci enum ClockSourceType clkSource; // clock source 3718c2ecf20Sopenharmony_ci int clkRate; // clock rate 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci int volumePhase[kAudioChannels]; 3748c2ecf20Sopenharmony_ci 3758c2ecf20Sopenharmony_ci u16 leftADCInSens; // ADC left channel input sensitivity 3768c2ecf20Sopenharmony_ci u16 rightADCInSens; // ADC right channel input sensitivity 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_ci int opencnt; // Open/Close count 3798c2ecf20Sopenharmony_ci int setcnt; // SetupForPlay count 3808c2ecf20Sopenharmony_ci int playcnt; // TriggerPlay count 3818c2ecf20Sopenharmony_ci int errorcnt; // Error Count 3828c2ecf20Sopenharmony_ci unsigned long totalerrorcnt; // Total Error Count 3838c2ecf20Sopenharmony_ci 3848c2ecf20Sopenharmony_ci int dsp_is_loaded; 3858c2ecf20Sopenharmony_ci int dsp_stop_is_processed; 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci}; 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("korg1212"); 3908c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 3918c2ecf20Sopenharmony_ciMODULE_SUPPORTED_DEVICE("{{KORG,korg1212}}"); 3928c2ecf20Sopenharmony_ciMODULE_FIRMWARE("korg/k1212.dsp"); 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_cistatic int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ 3958c2ecf20Sopenharmony_cistatic char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ 3968c2ecf20Sopenharmony_cistatic bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */ 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_cimodule_param_array(index, int, NULL, 0444); 3998c2ecf20Sopenharmony_ciMODULE_PARM_DESC(index, "Index value for Korg 1212 soundcard."); 4008c2ecf20Sopenharmony_cimodule_param_array(id, charp, NULL, 0444); 4018c2ecf20Sopenharmony_ciMODULE_PARM_DESC(id, "ID string for Korg 1212 soundcard."); 4028c2ecf20Sopenharmony_cimodule_param_array(enable, bool, NULL, 0444); 4038c2ecf20Sopenharmony_ciMODULE_PARM_DESC(enable, "Enable Korg 1212 soundcard."); 4048c2ecf20Sopenharmony_ciMODULE_AUTHOR("Haroldo Gamal <gamal@alternex.com.br>"); 4058c2ecf20Sopenharmony_ci 4068c2ecf20Sopenharmony_cistatic const struct pci_device_id snd_korg1212_ids[] = { 4078c2ecf20Sopenharmony_ci { 4088c2ecf20Sopenharmony_ci .vendor = 0x10b5, 4098c2ecf20Sopenharmony_ci .device = 0x906d, 4108c2ecf20Sopenharmony_ci .subvendor = PCI_ANY_ID, 4118c2ecf20Sopenharmony_ci .subdevice = PCI_ANY_ID, 4128c2ecf20Sopenharmony_ci }, 4138c2ecf20Sopenharmony_ci { 0, }, 4148c2ecf20Sopenharmony_ci}; 4158c2ecf20Sopenharmony_ci 4168c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(pci, snd_korg1212_ids); 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_cistatic const char * const stateName[] = { 4198c2ecf20Sopenharmony_ci "Non-existent", 4208c2ecf20Sopenharmony_ci "Uninitialized", 4218c2ecf20Sopenharmony_ci "DSP download in process", 4228c2ecf20Sopenharmony_ci "DSP download complete", 4238c2ecf20Sopenharmony_ci "Ready", 4248c2ecf20Sopenharmony_ci "Open", 4258c2ecf20Sopenharmony_ci "Setup for play", 4268c2ecf20Sopenharmony_ci "Playing", 4278c2ecf20Sopenharmony_ci "Monitor mode on", 4288c2ecf20Sopenharmony_ci "Calibrating", 4298c2ecf20Sopenharmony_ci "Invalid" 4308c2ecf20Sopenharmony_ci}; 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_cistatic const char * const clockSourceTypeName[] = { "ADAT", "S/PDIF", "local" }; 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_cistatic const char * const clockSourceName[] = { 4358c2ecf20Sopenharmony_ci "ADAT at 44.1 kHz", 4368c2ecf20Sopenharmony_ci "ADAT at 48 kHz", 4378c2ecf20Sopenharmony_ci "S/PDIF at 44.1 kHz", 4388c2ecf20Sopenharmony_ci "S/PDIF at 48 kHz", 4398c2ecf20Sopenharmony_ci "local clock at 44.1 kHz", 4408c2ecf20Sopenharmony_ci "local clock at 48 kHz" 4418c2ecf20Sopenharmony_ci}; 4428c2ecf20Sopenharmony_ci 4438c2ecf20Sopenharmony_cistatic const char * const channelName[] = { 4448c2ecf20Sopenharmony_ci "ADAT-1", 4458c2ecf20Sopenharmony_ci "ADAT-2", 4468c2ecf20Sopenharmony_ci "ADAT-3", 4478c2ecf20Sopenharmony_ci "ADAT-4", 4488c2ecf20Sopenharmony_ci "ADAT-5", 4498c2ecf20Sopenharmony_ci "ADAT-6", 4508c2ecf20Sopenharmony_ci "ADAT-7", 4518c2ecf20Sopenharmony_ci "ADAT-8", 4528c2ecf20Sopenharmony_ci "Analog-L", 4538c2ecf20Sopenharmony_ci "Analog-R", 4548c2ecf20Sopenharmony_ci "SPDIF-L", 4558c2ecf20Sopenharmony_ci "SPDIF-R", 4568c2ecf20Sopenharmony_ci}; 4578c2ecf20Sopenharmony_ci 4588c2ecf20Sopenharmony_cistatic const u16 ClockSourceSelector[] = { 4598c2ecf20Sopenharmony_ci 0x8000, // selects source as ADAT at 44.1 kHz 4608c2ecf20Sopenharmony_ci 0x0000, // selects source as ADAT at 48 kHz 4618c2ecf20Sopenharmony_ci 0x8001, // selects source as S/PDIF at 44.1 kHz 4628c2ecf20Sopenharmony_ci 0x0001, // selects source as S/PDIF at 48 kHz 4638c2ecf20Sopenharmony_ci 0x8002, // selects source as local clock at 44.1 kHz 4648c2ecf20Sopenharmony_ci 0x0002 // selects source as local clock at 48 kHz 4658c2ecf20Sopenharmony_ci}; 4668c2ecf20Sopenharmony_ci 4678c2ecf20Sopenharmony_ciunion swap_u32 { unsigned char c[4]; u32 i; }; 4688c2ecf20Sopenharmony_ci 4698c2ecf20Sopenharmony_ci#ifdef SNDRV_BIG_ENDIAN 4708c2ecf20Sopenharmony_cistatic u32 LowerWordSwap(u32 swappee) 4718c2ecf20Sopenharmony_ci#else 4728c2ecf20Sopenharmony_cistatic u32 UpperWordSwap(u32 swappee) 4738c2ecf20Sopenharmony_ci#endif 4748c2ecf20Sopenharmony_ci{ 4758c2ecf20Sopenharmony_ci union swap_u32 retVal, swapper; 4768c2ecf20Sopenharmony_ci 4778c2ecf20Sopenharmony_ci swapper.i = swappee; 4788c2ecf20Sopenharmony_ci retVal.c[2] = swapper.c[3]; 4798c2ecf20Sopenharmony_ci retVal.c[3] = swapper.c[2]; 4808c2ecf20Sopenharmony_ci retVal.c[1] = swapper.c[1]; 4818c2ecf20Sopenharmony_ci retVal.c[0] = swapper.c[0]; 4828c2ecf20Sopenharmony_ci 4838c2ecf20Sopenharmony_ci return retVal.i; 4848c2ecf20Sopenharmony_ci} 4858c2ecf20Sopenharmony_ci 4868c2ecf20Sopenharmony_ci#ifdef SNDRV_BIG_ENDIAN 4878c2ecf20Sopenharmony_cistatic u32 UpperWordSwap(u32 swappee) 4888c2ecf20Sopenharmony_ci#else 4898c2ecf20Sopenharmony_cistatic u32 LowerWordSwap(u32 swappee) 4908c2ecf20Sopenharmony_ci#endif 4918c2ecf20Sopenharmony_ci{ 4928c2ecf20Sopenharmony_ci union swap_u32 retVal, swapper; 4938c2ecf20Sopenharmony_ci 4948c2ecf20Sopenharmony_ci swapper.i = swappee; 4958c2ecf20Sopenharmony_ci retVal.c[2] = swapper.c[2]; 4968c2ecf20Sopenharmony_ci retVal.c[3] = swapper.c[3]; 4978c2ecf20Sopenharmony_ci retVal.c[1] = swapper.c[0]; 4988c2ecf20Sopenharmony_ci retVal.c[0] = swapper.c[1]; 4998c2ecf20Sopenharmony_ci 5008c2ecf20Sopenharmony_ci return retVal.i; 5018c2ecf20Sopenharmony_ci} 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_ci#define SetBitInWord(theWord,bitPosition) (*theWord) |= (0x0001 << bitPosition) 5048c2ecf20Sopenharmony_ci#define SetBitInDWord(theWord,bitPosition) (*theWord) |= (0x00000001 << bitPosition) 5058c2ecf20Sopenharmony_ci#define ClearBitInWord(theWord,bitPosition) (*theWord) &= ~(0x0001 << bitPosition) 5068c2ecf20Sopenharmony_ci#define ClearBitInDWord(theWord,bitPosition) (*theWord) &= ~(0x00000001 << bitPosition) 5078c2ecf20Sopenharmony_ci 5088c2ecf20Sopenharmony_cistatic int snd_korg1212_Send1212Command(struct snd_korg1212 *korg1212, 5098c2ecf20Sopenharmony_ci enum korg1212_dbcnst doorbellVal, 5108c2ecf20Sopenharmony_ci u32 mailBox0Val, u32 mailBox1Val, 5118c2ecf20Sopenharmony_ci u32 mailBox2Val, u32 mailBox3Val) 5128c2ecf20Sopenharmony_ci{ 5138c2ecf20Sopenharmony_ci u32 retryCount; 5148c2ecf20Sopenharmony_ci u16 mailBox3Lo; 5158c2ecf20Sopenharmony_ci int rc = K1212_CMDRET_Success; 5168c2ecf20Sopenharmony_ci 5178c2ecf20Sopenharmony_ci if (!korg1212->outDoorbellPtr) { 5188c2ecf20Sopenharmony_ci K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: CardUninitialized\n"); 5198c2ecf20Sopenharmony_ci return K1212_CMDRET_CardUninitialized; 5208c2ecf20Sopenharmony_ci } 5218c2ecf20Sopenharmony_ci 5228c2ecf20Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: Card <- 0x%08x 0x%08x [%s]\n", 5238c2ecf20Sopenharmony_ci doorbellVal, mailBox0Val, stateName[korg1212->cardState]); 5248c2ecf20Sopenharmony_ci for (retryCount = 0; retryCount < MAX_COMMAND_RETRIES; retryCount++) { 5258c2ecf20Sopenharmony_ci writel(mailBox3Val, korg1212->mailbox3Ptr); 5268c2ecf20Sopenharmony_ci writel(mailBox2Val, korg1212->mailbox2Ptr); 5278c2ecf20Sopenharmony_ci writel(mailBox1Val, korg1212->mailbox1Ptr); 5288c2ecf20Sopenharmony_ci writel(mailBox0Val, korg1212->mailbox0Ptr); 5298c2ecf20Sopenharmony_ci writel(doorbellVal, korg1212->outDoorbellPtr); // interrupt the card 5308c2ecf20Sopenharmony_ci 5318c2ecf20Sopenharmony_ci // -------------------------------------------------------------- 5328c2ecf20Sopenharmony_ci // the reboot command will not give an acknowledgement. 5338c2ecf20Sopenharmony_ci // -------------------------------------------------------------- 5348c2ecf20Sopenharmony_ci if ( doorbellVal == K1212_DB_RebootCard || 5358c2ecf20Sopenharmony_ci doorbellVal == K1212_DB_BootFromDSPPage4 || 5368c2ecf20Sopenharmony_ci doorbellVal == K1212_DB_StartDSPDownload ) { 5378c2ecf20Sopenharmony_ci rc = K1212_CMDRET_Success; 5388c2ecf20Sopenharmony_ci break; 5398c2ecf20Sopenharmony_ci } 5408c2ecf20Sopenharmony_ci 5418c2ecf20Sopenharmony_ci // -------------------------------------------------------------- 5428c2ecf20Sopenharmony_ci // See if the card acknowledged the command. Wait a bit, then 5438c2ecf20Sopenharmony_ci // read in the low word of mailbox3. If the MSB is set and the 5448c2ecf20Sopenharmony_ci // low byte is equal to the doorbell value, then it ack'd. 5458c2ecf20Sopenharmony_ci // -------------------------------------------------------------- 5468c2ecf20Sopenharmony_ci udelay(COMMAND_ACK_DELAY); 5478c2ecf20Sopenharmony_ci mailBox3Lo = readl(korg1212->mailbox3Ptr); 5488c2ecf20Sopenharmony_ci if (mailBox3Lo & COMMAND_ACK_MASK) { 5498c2ecf20Sopenharmony_ci if ((mailBox3Lo & DOORBELL_VAL_MASK) == (doorbellVal & DOORBELL_VAL_MASK)) { 5508c2ecf20Sopenharmony_ci K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: Card <- Success\n"); 5518c2ecf20Sopenharmony_ci rc = K1212_CMDRET_Success; 5528c2ecf20Sopenharmony_ci break; 5538c2ecf20Sopenharmony_ci } 5548c2ecf20Sopenharmony_ci } 5558c2ecf20Sopenharmony_ci } 5568c2ecf20Sopenharmony_ci korg1212->cmdRetryCount += retryCount; 5578c2ecf20Sopenharmony_ci 5588c2ecf20Sopenharmony_ci if (retryCount >= MAX_COMMAND_RETRIES) { 5598c2ecf20Sopenharmony_ci K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: Card <- NoAckFromCard\n"); 5608c2ecf20Sopenharmony_ci rc = K1212_CMDRET_NoAckFromCard; 5618c2ecf20Sopenharmony_ci } 5628c2ecf20Sopenharmony_ci 5638c2ecf20Sopenharmony_ci return rc; 5648c2ecf20Sopenharmony_ci} 5658c2ecf20Sopenharmony_ci 5668c2ecf20Sopenharmony_ci/* spinlock already held */ 5678c2ecf20Sopenharmony_cistatic void snd_korg1212_SendStop(struct snd_korg1212 *korg1212) 5688c2ecf20Sopenharmony_ci{ 5698c2ecf20Sopenharmony_ci if (! korg1212->stop_pending_cnt) { 5708c2ecf20Sopenharmony_ci korg1212->sharedBufferPtr->cardCommand = 0xffffffff; 5718c2ecf20Sopenharmony_ci /* program the timer */ 5728c2ecf20Sopenharmony_ci korg1212->stop_pending_cnt = HZ; 5738c2ecf20Sopenharmony_ci mod_timer(&korg1212->timer, jiffies + 1); 5748c2ecf20Sopenharmony_ci } 5758c2ecf20Sopenharmony_ci} 5768c2ecf20Sopenharmony_ci 5778c2ecf20Sopenharmony_cistatic void snd_korg1212_SendStopAndWait(struct snd_korg1212 *korg1212) 5788c2ecf20Sopenharmony_ci{ 5798c2ecf20Sopenharmony_ci unsigned long flags; 5808c2ecf20Sopenharmony_ci spin_lock_irqsave(&korg1212->lock, flags); 5818c2ecf20Sopenharmony_ci korg1212->dsp_stop_is_processed = 0; 5828c2ecf20Sopenharmony_ci snd_korg1212_SendStop(korg1212); 5838c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&korg1212->lock, flags); 5848c2ecf20Sopenharmony_ci wait_event_timeout(korg1212->wait, korg1212->dsp_stop_is_processed, (HZ * 3) / 2); 5858c2ecf20Sopenharmony_ci} 5868c2ecf20Sopenharmony_ci 5878c2ecf20Sopenharmony_ci/* timer callback for checking the ack of stop request */ 5888c2ecf20Sopenharmony_cistatic void snd_korg1212_timer_func(struct timer_list *t) 5898c2ecf20Sopenharmony_ci{ 5908c2ecf20Sopenharmony_ci struct snd_korg1212 *korg1212 = from_timer(korg1212, t, timer); 5918c2ecf20Sopenharmony_ci unsigned long flags; 5928c2ecf20Sopenharmony_ci 5938c2ecf20Sopenharmony_ci spin_lock_irqsave(&korg1212->lock, flags); 5948c2ecf20Sopenharmony_ci if (korg1212->sharedBufferPtr->cardCommand == 0) { 5958c2ecf20Sopenharmony_ci /* ack'ed */ 5968c2ecf20Sopenharmony_ci korg1212->stop_pending_cnt = 0; 5978c2ecf20Sopenharmony_ci korg1212->dsp_stop_is_processed = 1; 5988c2ecf20Sopenharmony_ci wake_up(&korg1212->wait); 5998c2ecf20Sopenharmony_ci K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: Stop ack'ed [%s]\n", 6008c2ecf20Sopenharmony_ci stateName[korg1212->cardState]); 6018c2ecf20Sopenharmony_ci } else { 6028c2ecf20Sopenharmony_ci if (--korg1212->stop_pending_cnt > 0) { 6038c2ecf20Sopenharmony_ci /* reprogram timer */ 6048c2ecf20Sopenharmony_ci mod_timer(&korg1212->timer, jiffies + 1); 6058c2ecf20Sopenharmony_ci } else { 6068c2ecf20Sopenharmony_ci snd_printd("korg1212_timer_func timeout\n"); 6078c2ecf20Sopenharmony_ci korg1212->sharedBufferPtr->cardCommand = 0; 6088c2ecf20Sopenharmony_ci korg1212->dsp_stop_is_processed = 1; 6098c2ecf20Sopenharmony_ci wake_up(&korg1212->wait); 6108c2ecf20Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: Stop timeout [%s]\n", 6118c2ecf20Sopenharmony_ci stateName[korg1212->cardState]); 6128c2ecf20Sopenharmony_ci } 6138c2ecf20Sopenharmony_ci } 6148c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&korg1212->lock, flags); 6158c2ecf20Sopenharmony_ci} 6168c2ecf20Sopenharmony_ci 6178c2ecf20Sopenharmony_cistatic int snd_korg1212_TurnOnIdleMonitor(struct snd_korg1212 *korg1212) 6188c2ecf20Sopenharmony_ci{ 6198c2ecf20Sopenharmony_ci unsigned long flags; 6208c2ecf20Sopenharmony_ci int rc; 6218c2ecf20Sopenharmony_ci 6228c2ecf20Sopenharmony_ci udelay(INTERCOMMAND_DELAY); 6238c2ecf20Sopenharmony_ci spin_lock_irqsave(&korg1212->lock, flags); 6248c2ecf20Sopenharmony_ci korg1212->idleMonitorOn = 1; 6258c2ecf20Sopenharmony_ci rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_SelectPlayMode, 6268c2ecf20Sopenharmony_ci K1212_MODE_MonitorOn, 0, 0, 0); 6278c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&korg1212->lock, flags); 6288c2ecf20Sopenharmony_ci return rc; 6298c2ecf20Sopenharmony_ci} 6308c2ecf20Sopenharmony_ci 6318c2ecf20Sopenharmony_cistatic void snd_korg1212_TurnOffIdleMonitor(struct snd_korg1212 *korg1212) 6328c2ecf20Sopenharmony_ci{ 6338c2ecf20Sopenharmony_ci if (korg1212->idleMonitorOn) { 6348c2ecf20Sopenharmony_ci snd_korg1212_SendStopAndWait(korg1212); 6358c2ecf20Sopenharmony_ci korg1212->idleMonitorOn = 0; 6368c2ecf20Sopenharmony_ci } 6378c2ecf20Sopenharmony_ci} 6388c2ecf20Sopenharmony_ci 6398c2ecf20Sopenharmony_cistatic inline void snd_korg1212_setCardState(struct snd_korg1212 * korg1212, enum CardState csState) 6408c2ecf20Sopenharmony_ci{ 6418c2ecf20Sopenharmony_ci korg1212->cardState = csState; 6428c2ecf20Sopenharmony_ci} 6438c2ecf20Sopenharmony_ci 6448c2ecf20Sopenharmony_cistatic int snd_korg1212_OpenCard(struct snd_korg1212 * korg1212) 6458c2ecf20Sopenharmony_ci{ 6468c2ecf20Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: OpenCard [%s] %d\n", 6478c2ecf20Sopenharmony_ci stateName[korg1212->cardState], korg1212->opencnt); 6488c2ecf20Sopenharmony_ci mutex_lock(&korg1212->open_mutex); 6498c2ecf20Sopenharmony_ci if (korg1212->opencnt++ == 0) { 6508c2ecf20Sopenharmony_ci snd_korg1212_TurnOffIdleMonitor(korg1212); 6518c2ecf20Sopenharmony_ci snd_korg1212_setCardState(korg1212, K1212_STATE_OPEN); 6528c2ecf20Sopenharmony_ci } 6538c2ecf20Sopenharmony_ci 6548c2ecf20Sopenharmony_ci mutex_unlock(&korg1212->open_mutex); 6558c2ecf20Sopenharmony_ci return 1; 6568c2ecf20Sopenharmony_ci} 6578c2ecf20Sopenharmony_ci 6588c2ecf20Sopenharmony_cistatic int snd_korg1212_CloseCard(struct snd_korg1212 * korg1212) 6598c2ecf20Sopenharmony_ci{ 6608c2ecf20Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: CloseCard [%s] %d\n", 6618c2ecf20Sopenharmony_ci stateName[korg1212->cardState], korg1212->opencnt); 6628c2ecf20Sopenharmony_ci 6638c2ecf20Sopenharmony_ci mutex_lock(&korg1212->open_mutex); 6648c2ecf20Sopenharmony_ci if (--(korg1212->opencnt)) { 6658c2ecf20Sopenharmony_ci mutex_unlock(&korg1212->open_mutex); 6668c2ecf20Sopenharmony_ci return 0; 6678c2ecf20Sopenharmony_ci } 6688c2ecf20Sopenharmony_ci 6698c2ecf20Sopenharmony_ci if (korg1212->cardState == K1212_STATE_SETUP) { 6708c2ecf20Sopenharmony_ci int rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_SelectPlayMode, 6718c2ecf20Sopenharmony_ci K1212_MODE_StopPlay, 0, 0, 0); 6728c2ecf20Sopenharmony_ci if (rc) 6738c2ecf20Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: CloseCard - RC = %d [%s]\n", 6748c2ecf20Sopenharmony_ci rc, stateName[korg1212->cardState]); 6758c2ecf20Sopenharmony_ci if (rc != K1212_CMDRET_Success) { 6768c2ecf20Sopenharmony_ci mutex_unlock(&korg1212->open_mutex); 6778c2ecf20Sopenharmony_ci return 0; 6788c2ecf20Sopenharmony_ci } 6798c2ecf20Sopenharmony_ci } else if (korg1212->cardState > K1212_STATE_SETUP) { 6808c2ecf20Sopenharmony_ci snd_korg1212_SendStopAndWait(korg1212); 6818c2ecf20Sopenharmony_ci } 6828c2ecf20Sopenharmony_ci 6838c2ecf20Sopenharmony_ci if (korg1212->cardState > K1212_STATE_READY) { 6848c2ecf20Sopenharmony_ci snd_korg1212_TurnOnIdleMonitor(korg1212); 6858c2ecf20Sopenharmony_ci snd_korg1212_setCardState(korg1212, K1212_STATE_READY); 6868c2ecf20Sopenharmony_ci } 6878c2ecf20Sopenharmony_ci 6888c2ecf20Sopenharmony_ci mutex_unlock(&korg1212->open_mutex); 6898c2ecf20Sopenharmony_ci return 0; 6908c2ecf20Sopenharmony_ci} 6918c2ecf20Sopenharmony_ci 6928c2ecf20Sopenharmony_ci/* spinlock already held */ 6938c2ecf20Sopenharmony_cistatic int snd_korg1212_SetupForPlay(struct snd_korg1212 * korg1212) 6948c2ecf20Sopenharmony_ci{ 6958c2ecf20Sopenharmony_ci int rc; 6968c2ecf20Sopenharmony_ci 6978c2ecf20Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: SetupForPlay [%s] %d\n", 6988c2ecf20Sopenharmony_ci stateName[korg1212->cardState], korg1212->setcnt); 6998c2ecf20Sopenharmony_ci 7008c2ecf20Sopenharmony_ci if (korg1212->setcnt++) 7018c2ecf20Sopenharmony_ci return 0; 7028c2ecf20Sopenharmony_ci 7038c2ecf20Sopenharmony_ci snd_korg1212_setCardState(korg1212, K1212_STATE_SETUP); 7048c2ecf20Sopenharmony_ci rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_SelectPlayMode, 7058c2ecf20Sopenharmony_ci K1212_MODE_SetupPlay, 0, 0, 0); 7068c2ecf20Sopenharmony_ci if (rc) 7078c2ecf20Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: SetupForPlay - RC = %d [%s]\n", 7088c2ecf20Sopenharmony_ci rc, stateName[korg1212->cardState]); 7098c2ecf20Sopenharmony_ci if (rc != K1212_CMDRET_Success) { 7108c2ecf20Sopenharmony_ci return 1; 7118c2ecf20Sopenharmony_ci } 7128c2ecf20Sopenharmony_ci return 0; 7138c2ecf20Sopenharmony_ci} 7148c2ecf20Sopenharmony_ci 7158c2ecf20Sopenharmony_ci/* spinlock already held */ 7168c2ecf20Sopenharmony_cistatic int snd_korg1212_TriggerPlay(struct snd_korg1212 * korg1212) 7178c2ecf20Sopenharmony_ci{ 7188c2ecf20Sopenharmony_ci int rc; 7198c2ecf20Sopenharmony_ci 7208c2ecf20Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: TriggerPlay [%s] %d\n", 7218c2ecf20Sopenharmony_ci stateName[korg1212->cardState], korg1212->playcnt); 7228c2ecf20Sopenharmony_ci 7238c2ecf20Sopenharmony_ci if (korg1212->playcnt++) 7248c2ecf20Sopenharmony_ci return 0; 7258c2ecf20Sopenharmony_ci 7268c2ecf20Sopenharmony_ci snd_korg1212_setCardState(korg1212, K1212_STATE_PLAYING); 7278c2ecf20Sopenharmony_ci rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_TriggerPlay, 0, 0, 0, 0); 7288c2ecf20Sopenharmony_ci if (rc) 7298c2ecf20Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: TriggerPlay - RC = %d [%s]\n", 7308c2ecf20Sopenharmony_ci rc, stateName[korg1212->cardState]); 7318c2ecf20Sopenharmony_ci if (rc != K1212_CMDRET_Success) { 7328c2ecf20Sopenharmony_ci return 1; 7338c2ecf20Sopenharmony_ci } 7348c2ecf20Sopenharmony_ci return 0; 7358c2ecf20Sopenharmony_ci} 7368c2ecf20Sopenharmony_ci 7378c2ecf20Sopenharmony_ci/* spinlock already held */ 7388c2ecf20Sopenharmony_cistatic int snd_korg1212_StopPlay(struct snd_korg1212 * korg1212) 7398c2ecf20Sopenharmony_ci{ 7408c2ecf20Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: StopPlay [%s] %d\n", 7418c2ecf20Sopenharmony_ci stateName[korg1212->cardState], korg1212->playcnt); 7428c2ecf20Sopenharmony_ci 7438c2ecf20Sopenharmony_ci if (--(korg1212->playcnt)) 7448c2ecf20Sopenharmony_ci return 0; 7458c2ecf20Sopenharmony_ci 7468c2ecf20Sopenharmony_ci korg1212->setcnt = 0; 7478c2ecf20Sopenharmony_ci 7488c2ecf20Sopenharmony_ci if (korg1212->cardState != K1212_STATE_ERRORSTOP) 7498c2ecf20Sopenharmony_ci snd_korg1212_SendStop(korg1212); 7508c2ecf20Sopenharmony_ci 7518c2ecf20Sopenharmony_ci snd_korg1212_setCardState(korg1212, K1212_STATE_OPEN); 7528c2ecf20Sopenharmony_ci return 0; 7538c2ecf20Sopenharmony_ci} 7548c2ecf20Sopenharmony_ci 7558c2ecf20Sopenharmony_cistatic void snd_korg1212_EnableCardInterrupts(struct snd_korg1212 * korg1212) 7568c2ecf20Sopenharmony_ci{ 7578c2ecf20Sopenharmony_ci writel(PCI_INT_ENABLE_BIT | 7588c2ecf20Sopenharmony_ci PCI_DOORBELL_INT_ENABLE_BIT | 7598c2ecf20Sopenharmony_ci LOCAL_INT_ENABLE_BIT | 7608c2ecf20Sopenharmony_ci LOCAL_DOORBELL_INT_ENABLE_BIT | 7618c2ecf20Sopenharmony_ci LOCAL_DMA1_INT_ENABLE_BIT, 7628c2ecf20Sopenharmony_ci korg1212->statusRegPtr); 7638c2ecf20Sopenharmony_ci} 7648c2ecf20Sopenharmony_ci 7658c2ecf20Sopenharmony_ci#if 0 /* not used */ 7668c2ecf20Sopenharmony_ci 7678c2ecf20Sopenharmony_cistatic int snd_korg1212_SetMonitorMode(struct snd_korg1212 *korg1212, 7688c2ecf20Sopenharmony_ci enum MonitorModeSelector mode) 7698c2ecf20Sopenharmony_ci{ 7708c2ecf20Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: SetMonitorMode [%s]\n", 7718c2ecf20Sopenharmony_ci stateName[korg1212->cardState]); 7728c2ecf20Sopenharmony_ci 7738c2ecf20Sopenharmony_ci switch (mode) { 7748c2ecf20Sopenharmony_ci case K1212_MONMODE_Off: 7758c2ecf20Sopenharmony_ci if (korg1212->cardState != K1212_STATE_MONITOR) 7768c2ecf20Sopenharmony_ci return 0; 7778c2ecf20Sopenharmony_ci else { 7788c2ecf20Sopenharmony_ci snd_korg1212_SendStopAndWait(korg1212); 7798c2ecf20Sopenharmony_ci snd_korg1212_setCardState(korg1212, K1212_STATE_OPEN); 7808c2ecf20Sopenharmony_ci } 7818c2ecf20Sopenharmony_ci break; 7828c2ecf20Sopenharmony_ci 7838c2ecf20Sopenharmony_ci case K1212_MONMODE_On: 7848c2ecf20Sopenharmony_ci if (korg1212->cardState != K1212_STATE_OPEN) 7858c2ecf20Sopenharmony_ci return 0; 7868c2ecf20Sopenharmony_ci else { 7878c2ecf20Sopenharmony_ci int rc; 7888c2ecf20Sopenharmony_ci snd_korg1212_setCardState(korg1212, K1212_STATE_MONITOR); 7898c2ecf20Sopenharmony_ci rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_SelectPlayMode, 7908c2ecf20Sopenharmony_ci K1212_MODE_MonitorOn, 0, 0, 0); 7918c2ecf20Sopenharmony_ci if (rc != K1212_CMDRET_Success) 7928c2ecf20Sopenharmony_ci return 0; 7938c2ecf20Sopenharmony_ci } 7948c2ecf20Sopenharmony_ci break; 7958c2ecf20Sopenharmony_ci 7968c2ecf20Sopenharmony_ci default: 7978c2ecf20Sopenharmony_ci return 0; 7988c2ecf20Sopenharmony_ci } 7998c2ecf20Sopenharmony_ci 8008c2ecf20Sopenharmony_ci return 1; 8018c2ecf20Sopenharmony_ci} 8028c2ecf20Sopenharmony_ci 8038c2ecf20Sopenharmony_ci#endif /* not used */ 8048c2ecf20Sopenharmony_ci 8058c2ecf20Sopenharmony_cistatic inline int snd_korg1212_use_is_exclusive(struct snd_korg1212 *korg1212) 8068c2ecf20Sopenharmony_ci{ 8078c2ecf20Sopenharmony_ci if (korg1212->playback_pid != korg1212->capture_pid && 8088c2ecf20Sopenharmony_ci korg1212->playback_pid >= 0 && korg1212->capture_pid >= 0) 8098c2ecf20Sopenharmony_ci return 0; 8108c2ecf20Sopenharmony_ci 8118c2ecf20Sopenharmony_ci return 1; 8128c2ecf20Sopenharmony_ci} 8138c2ecf20Sopenharmony_ci 8148c2ecf20Sopenharmony_cistatic int snd_korg1212_SetRate(struct snd_korg1212 *korg1212, int rate) 8158c2ecf20Sopenharmony_ci{ 8168c2ecf20Sopenharmony_ci static const enum ClockSourceIndex s44[] = { 8178c2ecf20Sopenharmony_ci K1212_CLKIDX_AdatAt44_1K, 8188c2ecf20Sopenharmony_ci K1212_CLKIDX_WordAt44_1K, 8198c2ecf20Sopenharmony_ci K1212_CLKIDX_LocalAt44_1K 8208c2ecf20Sopenharmony_ci }; 8218c2ecf20Sopenharmony_ci static const enum ClockSourceIndex s48[] = { 8228c2ecf20Sopenharmony_ci K1212_CLKIDX_AdatAt48K, 8238c2ecf20Sopenharmony_ci K1212_CLKIDX_WordAt48K, 8248c2ecf20Sopenharmony_ci K1212_CLKIDX_LocalAt48K 8258c2ecf20Sopenharmony_ci }; 8268c2ecf20Sopenharmony_ci int parm, rc; 8278c2ecf20Sopenharmony_ci 8288c2ecf20Sopenharmony_ci if (!snd_korg1212_use_is_exclusive (korg1212)) 8298c2ecf20Sopenharmony_ci return -EBUSY; 8308c2ecf20Sopenharmony_ci 8318c2ecf20Sopenharmony_ci switch (rate) { 8328c2ecf20Sopenharmony_ci case 44100: 8338c2ecf20Sopenharmony_ci parm = s44[korg1212->clkSource]; 8348c2ecf20Sopenharmony_ci break; 8358c2ecf20Sopenharmony_ci 8368c2ecf20Sopenharmony_ci case 48000: 8378c2ecf20Sopenharmony_ci parm = s48[korg1212->clkSource]; 8388c2ecf20Sopenharmony_ci break; 8398c2ecf20Sopenharmony_ci 8408c2ecf20Sopenharmony_ci default: 8418c2ecf20Sopenharmony_ci return -EINVAL; 8428c2ecf20Sopenharmony_ci } 8438c2ecf20Sopenharmony_ci 8448c2ecf20Sopenharmony_ci korg1212->clkSrcRate = parm; 8458c2ecf20Sopenharmony_ci korg1212->clkRate = rate; 8468c2ecf20Sopenharmony_ci 8478c2ecf20Sopenharmony_ci udelay(INTERCOMMAND_DELAY); 8488c2ecf20Sopenharmony_ci rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_SetClockSourceRate, 8498c2ecf20Sopenharmony_ci ClockSourceSelector[korg1212->clkSrcRate], 8508c2ecf20Sopenharmony_ci 0, 0, 0); 8518c2ecf20Sopenharmony_ci if (rc) 8528c2ecf20Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: Set Clock Source Selector - RC = %d [%s]\n", 8538c2ecf20Sopenharmony_ci rc, stateName[korg1212->cardState]); 8548c2ecf20Sopenharmony_ci 8558c2ecf20Sopenharmony_ci return 0; 8568c2ecf20Sopenharmony_ci} 8578c2ecf20Sopenharmony_ci 8588c2ecf20Sopenharmony_cistatic int snd_korg1212_SetClockSource(struct snd_korg1212 *korg1212, int source) 8598c2ecf20Sopenharmony_ci{ 8608c2ecf20Sopenharmony_ci 8618c2ecf20Sopenharmony_ci if (source < 0 || source > 2) 8628c2ecf20Sopenharmony_ci return -EINVAL; 8638c2ecf20Sopenharmony_ci 8648c2ecf20Sopenharmony_ci korg1212->clkSource = source; 8658c2ecf20Sopenharmony_ci 8668c2ecf20Sopenharmony_ci snd_korg1212_SetRate(korg1212, korg1212->clkRate); 8678c2ecf20Sopenharmony_ci 8688c2ecf20Sopenharmony_ci return 0; 8698c2ecf20Sopenharmony_ci} 8708c2ecf20Sopenharmony_ci 8718c2ecf20Sopenharmony_cistatic void snd_korg1212_DisableCardInterrupts(struct snd_korg1212 *korg1212) 8728c2ecf20Sopenharmony_ci{ 8738c2ecf20Sopenharmony_ci writel(0, korg1212->statusRegPtr); 8748c2ecf20Sopenharmony_ci} 8758c2ecf20Sopenharmony_ci 8768c2ecf20Sopenharmony_cistatic int snd_korg1212_WriteADCSensitivity(struct snd_korg1212 *korg1212) 8778c2ecf20Sopenharmony_ci{ 8788c2ecf20Sopenharmony_ci struct SensBits sensVals; 8798c2ecf20Sopenharmony_ci int bitPosition; 8808c2ecf20Sopenharmony_ci int channel; 8818c2ecf20Sopenharmony_ci int clkIs48K; 8828c2ecf20Sopenharmony_ci int monModeSet; 8838c2ecf20Sopenharmony_ci u16 controlValue; // this keeps the current value to be written to 8848c2ecf20Sopenharmony_ci // the card's eeprom control register. 8858c2ecf20Sopenharmony_ci u16 count; 8868c2ecf20Sopenharmony_ci unsigned long flags; 8878c2ecf20Sopenharmony_ci 8888c2ecf20Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: WriteADCSensivity [%s]\n", 8898c2ecf20Sopenharmony_ci stateName[korg1212->cardState]); 8908c2ecf20Sopenharmony_ci 8918c2ecf20Sopenharmony_ci // ---------------------------------------------------------------------------- 8928c2ecf20Sopenharmony_ci // initialize things. The local init bit is always set when writing to the 8938c2ecf20Sopenharmony_ci // card's control register. 8948c2ecf20Sopenharmony_ci // ---------------------------------------------------------------------------- 8958c2ecf20Sopenharmony_ci controlValue = 0; 8968c2ecf20Sopenharmony_ci SetBitInWord(&controlValue, SET_SENS_LOCALINIT_BITPOS); // init the control value 8978c2ecf20Sopenharmony_ci 8988c2ecf20Sopenharmony_ci // ---------------------------------------------------------------------------- 8998c2ecf20Sopenharmony_ci // make sure the card is not in monitor mode when we do this update. 9008c2ecf20Sopenharmony_ci // ---------------------------------------------------------------------------- 9018c2ecf20Sopenharmony_ci if (korg1212->cardState == K1212_STATE_MONITOR || korg1212->idleMonitorOn) { 9028c2ecf20Sopenharmony_ci monModeSet = 1; 9038c2ecf20Sopenharmony_ci snd_korg1212_SendStopAndWait(korg1212); 9048c2ecf20Sopenharmony_ci } else 9058c2ecf20Sopenharmony_ci monModeSet = 0; 9068c2ecf20Sopenharmony_ci 9078c2ecf20Sopenharmony_ci spin_lock_irqsave(&korg1212->lock, flags); 9088c2ecf20Sopenharmony_ci 9098c2ecf20Sopenharmony_ci // ---------------------------------------------------------------------------- 9108c2ecf20Sopenharmony_ci // we are about to send new values to the card, so clear the new values queued 9118c2ecf20Sopenharmony_ci // flag. Also, clear out mailbox 3, so we don't lockup. 9128c2ecf20Sopenharmony_ci // ---------------------------------------------------------------------------- 9138c2ecf20Sopenharmony_ci writel(0, korg1212->mailbox3Ptr); 9148c2ecf20Sopenharmony_ci udelay(LOADSHIFT_DELAY); 9158c2ecf20Sopenharmony_ci 9168c2ecf20Sopenharmony_ci // ---------------------------------------------------------------------------- 9178c2ecf20Sopenharmony_ci // determine whether we are running a 48K or 44.1K clock. This info is used 9188c2ecf20Sopenharmony_ci // later when setting the SPDIF FF after the volume has been shifted in. 9198c2ecf20Sopenharmony_ci // ---------------------------------------------------------------------------- 9208c2ecf20Sopenharmony_ci switch (korg1212->clkSrcRate) { 9218c2ecf20Sopenharmony_ci case K1212_CLKIDX_AdatAt44_1K: 9228c2ecf20Sopenharmony_ci case K1212_CLKIDX_WordAt44_1K: 9238c2ecf20Sopenharmony_ci case K1212_CLKIDX_LocalAt44_1K: 9248c2ecf20Sopenharmony_ci clkIs48K = 0; 9258c2ecf20Sopenharmony_ci break; 9268c2ecf20Sopenharmony_ci 9278c2ecf20Sopenharmony_ci case K1212_CLKIDX_WordAt48K: 9288c2ecf20Sopenharmony_ci case K1212_CLKIDX_AdatAt48K: 9298c2ecf20Sopenharmony_ci case K1212_CLKIDX_LocalAt48K: 9308c2ecf20Sopenharmony_ci default: 9318c2ecf20Sopenharmony_ci clkIs48K = 1; 9328c2ecf20Sopenharmony_ci break; 9338c2ecf20Sopenharmony_ci } 9348c2ecf20Sopenharmony_ci 9358c2ecf20Sopenharmony_ci // ---------------------------------------------------------------------------- 9368c2ecf20Sopenharmony_ci // start the update. Setup the bit structure and then shift the bits. 9378c2ecf20Sopenharmony_ci // ---------------------------------------------------------------------------- 9388c2ecf20Sopenharmony_ci sensVals.l.v.leftChanId = SET_SENS_LEFTCHANID; 9398c2ecf20Sopenharmony_ci sensVals.r.v.rightChanId = SET_SENS_RIGHTCHANID; 9408c2ecf20Sopenharmony_ci sensVals.l.v.leftChanVal = korg1212->leftADCInSens; 9418c2ecf20Sopenharmony_ci sensVals.r.v.rightChanVal = korg1212->rightADCInSens; 9428c2ecf20Sopenharmony_ci 9438c2ecf20Sopenharmony_ci // ---------------------------------------------------------------------------- 9448c2ecf20Sopenharmony_ci // now start shifting the bits in. Start with the left channel then the right. 9458c2ecf20Sopenharmony_ci // ---------------------------------------------------------------------------- 9468c2ecf20Sopenharmony_ci for (channel = 0; channel < 2; channel++) { 9478c2ecf20Sopenharmony_ci 9488c2ecf20Sopenharmony_ci // ---------------------------------------------------------------------------- 9498c2ecf20Sopenharmony_ci // Bring the load/shift line low, then wait - the spec says >150ns from load/ 9508c2ecf20Sopenharmony_ci // shift low to the first rising edge of the clock. 9518c2ecf20Sopenharmony_ci // ---------------------------------------------------------------------------- 9528c2ecf20Sopenharmony_ci ClearBitInWord(&controlValue, SET_SENS_LOADSHIFT_BITPOS); 9538c2ecf20Sopenharmony_ci ClearBitInWord(&controlValue, SET_SENS_DATA_BITPOS); 9548c2ecf20Sopenharmony_ci writew(controlValue, korg1212->sensRegPtr); // load/shift goes low 9558c2ecf20Sopenharmony_ci udelay(LOADSHIFT_DELAY); 9568c2ecf20Sopenharmony_ci 9578c2ecf20Sopenharmony_ci for (bitPosition = 15; bitPosition >= 0; bitPosition--) { // for all the bits 9588c2ecf20Sopenharmony_ci if (channel == 0) { 9598c2ecf20Sopenharmony_ci if (sensVals.l.leftSensBits & (0x0001 << bitPosition)) 9608c2ecf20Sopenharmony_ci SetBitInWord(&controlValue, SET_SENS_DATA_BITPOS); // data bit set high 9618c2ecf20Sopenharmony_ci else 9628c2ecf20Sopenharmony_ci ClearBitInWord(&controlValue, SET_SENS_DATA_BITPOS); // data bit set low 9638c2ecf20Sopenharmony_ci } else { 9648c2ecf20Sopenharmony_ci if (sensVals.r.rightSensBits & (0x0001 << bitPosition)) 9658c2ecf20Sopenharmony_ci SetBitInWord(&controlValue, SET_SENS_DATA_BITPOS); // data bit set high 9668c2ecf20Sopenharmony_ci else 9678c2ecf20Sopenharmony_ci ClearBitInWord(&controlValue, SET_SENS_DATA_BITPOS); // data bit set low 9688c2ecf20Sopenharmony_ci } 9698c2ecf20Sopenharmony_ci 9708c2ecf20Sopenharmony_ci ClearBitInWord(&controlValue, SET_SENS_CLOCK_BITPOS); 9718c2ecf20Sopenharmony_ci writew(controlValue, korg1212->sensRegPtr); // clock goes low 9728c2ecf20Sopenharmony_ci udelay(SENSCLKPULSE_WIDTH); 9738c2ecf20Sopenharmony_ci SetBitInWord(&controlValue, SET_SENS_CLOCK_BITPOS); 9748c2ecf20Sopenharmony_ci writew(controlValue, korg1212->sensRegPtr); // clock goes high 9758c2ecf20Sopenharmony_ci udelay(SENSCLKPULSE_WIDTH); 9768c2ecf20Sopenharmony_ci } 9778c2ecf20Sopenharmony_ci 9788c2ecf20Sopenharmony_ci // ---------------------------------------------------------------------------- 9798c2ecf20Sopenharmony_ci // finish up SPDIF for left. Bring the load/shift line high, then write a one 9808c2ecf20Sopenharmony_ci // bit if the clock rate is 48K otherwise write 0. 9818c2ecf20Sopenharmony_ci // ---------------------------------------------------------------------------- 9828c2ecf20Sopenharmony_ci ClearBitInWord(&controlValue, SET_SENS_DATA_BITPOS); 9838c2ecf20Sopenharmony_ci ClearBitInWord(&controlValue, SET_SENS_CLOCK_BITPOS); 9848c2ecf20Sopenharmony_ci SetBitInWord(&controlValue, SET_SENS_LOADSHIFT_BITPOS); 9858c2ecf20Sopenharmony_ci writew(controlValue, korg1212->sensRegPtr); // load shift goes high - clk low 9868c2ecf20Sopenharmony_ci udelay(SENSCLKPULSE_WIDTH); 9878c2ecf20Sopenharmony_ci 9888c2ecf20Sopenharmony_ci if (clkIs48K) 9898c2ecf20Sopenharmony_ci SetBitInWord(&controlValue, SET_SENS_DATA_BITPOS); 9908c2ecf20Sopenharmony_ci 9918c2ecf20Sopenharmony_ci writew(controlValue, korg1212->sensRegPtr); // set/clear data bit 9928c2ecf20Sopenharmony_ci udelay(ONE_RTC_TICK); 9938c2ecf20Sopenharmony_ci SetBitInWord(&controlValue, SET_SENS_CLOCK_BITPOS); 9948c2ecf20Sopenharmony_ci writew(controlValue, korg1212->sensRegPtr); // clock goes high 9958c2ecf20Sopenharmony_ci udelay(SENSCLKPULSE_WIDTH); 9968c2ecf20Sopenharmony_ci ClearBitInWord(&controlValue, SET_SENS_CLOCK_BITPOS); 9978c2ecf20Sopenharmony_ci writew(controlValue, korg1212->sensRegPtr); // clock goes low 9988c2ecf20Sopenharmony_ci udelay(SENSCLKPULSE_WIDTH); 9998c2ecf20Sopenharmony_ci } 10008c2ecf20Sopenharmony_ci 10018c2ecf20Sopenharmony_ci // ---------------------------------------------------------------------------- 10028c2ecf20Sopenharmony_ci // The update is complete. Set a timeout. This is the inter-update delay. 10038c2ecf20Sopenharmony_ci // Also, if the card was in monitor mode, restore it. 10048c2ecf20Sopenharmony_ci // ---------------------------------------------------------------------------- 10058c2ecf20Sopenharmony_ci for (count = 0; count < 10; count++) 10068c2ecf20Sopenharmony_ci udelay(SENSCLKPULSE_WIDTH); 10078c2ecf20Sopenharmony_ci 10088c2ecf20Sopenharmony_ci if (monModeSet) { 10098c2ecf20Sopenharmony_ci int rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_SelectPlayMode, 10108c2ecf20Sopenharmony_ci K1212_MODE_MonitorOn, 0, 0, 0); 10118c2ecf20Sopenharmony_ci if (rc) 10128c2ecf20Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: WriteADCSensivity - RC = %d [%s]\n", 10138c2ecf20Sopenharmony_ci rc, stateName[korg1212->cardState]); 10148c2ecf20Sopenharmony_ci } 10158c2ecf20Sopenharmony_ci 10168c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&korg1212->lock, flags); 10178c2ecf20Sopenharmony_ci 10188c2ecf20Sopenharmony_ci return 1; 10198c2ecf20Sopenharmony_ci} 10208c2ecf20Sopenharmony_ci 10218c2ecf20Sopenharmony_cistatic void snd_korg1212_OnDSPDownloadComplete(struct snd_korg1212 *korg1212) 10228c2ecf20Sopenharmony_ci{ 10238c2ecf20Sopenharmony_ci int channel, rc; 10248c2ecf20Sopenharmony_ci 10258c2ecf20Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: DSP download is complete. [%s]\n", 10268c2ecf20Sopenharmony_ci stateName[korg1212->cardState]); 10278c2ecf20Sopenharmony_ci 10288c2ecf20Sopenharmony_ci // ---------------------------------------------------- 10298c2ecf20Sopenharmony_ci // tell the card to boot 10308c2ecf20Sopenharmony_ci // ---------------------------------------------------- 10318c2ecf20Sopenharmony_ci rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_BootFromDSPPage4, 0, 0, 0, 0); 10328c2ecf20Sopenharmony_ci 10338c2ecf20Sopenharmony_ci if (rc) 10348c2ecf20Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: Boot from Page 4 - RC = %d [%s]\n", 10358c2ecf20Sopenharmony_ci rc, stateName[korg1212->cardState]); 10368c2ecf20Sopenharmony_ci msleep(DSP_BOOT_DELAY_IN_MS); 10378c2ecf20Sopenharmony_ci 10388c2ecf20Sopenharmony_ci // -------------------------------------------------------------------------------- 10398c2ecf20Sopenharmony_ci // Let the card know where all the buffers are. 10408c2ecf20Sopenharmony_ci // -------------------------------------------------------------------------------- 10418c2ecf20Sopenharmony_ci rc = snd_korg1212_Send1212Command(korg1212, 10428c2ecf20Sopenharmony_ci K1212_DB_ConfigureBufferMemory, 10438c2ecf20Sopenharmony_ci LowerWordSwap(korg1212->PlayDataPhy), 10448c2ecf20Sopenharmony_ci LowerWordSwap(korg1212->RecDataPhy), 10458c2ecf20Sopenharmony_ci ((kNumBuffers * kPlayBufferFrames) / 2), // size given to the card 10468c2ecf20Sopenharmony_ci // is based on 2 buffers 10478c2ecf20Sopenharmony_ci 0 10488c2ecf20Sopenharmony_ci ); 10498c2ecf20Sopenharmony_ci 10508c2ecf20Sopenharmony_ci if (rc) 10518c2ecf20Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: Configure Buffer Memory - RC = %d [%s]\n", 10528c2ecf20Sopenharmony_ci rc, stateName[korg1212->cardState]); 10538c2ecf20Sopenharmony_ci 10548c2ecf20Sopenharmony_ci udelay(INTERCOMMAND_DELAY); 10558c2ecf20Sopenharmony_ci 10568c2ecf20Sopenharmony_ci rc = snd_korg1212_Send1212Command(korg1212, 10578c2ecf20Sopenharmony_ci K1212_DB_ConfigureMiscMemory, 10588c2ecf20Sopenharmony_ci LowerWordSwap(korg1212->VolumeTablePhy), 10598c2ecf20Sopenharmony_ci LowerWordSwap(korg1212->RoutingTablePhy), 10608c2ecf20Sopenharmony_ci LowerWordSwap(korg1212->AdatTimeCodePhy), 10618c2ecf20Sopenharmony_ci 0 10628c2ecf20Sopenharmony_ci ); 10638c2ecf20Sopenharmony_ci 10648c2ecf20Sopenharmony_ci if (rc) 10658c2ecf20Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: Configure Misc Memory - RC = %d [%s]\n", 10668c2ecf20Sopenharmony_ci rc, stateName[korg1212->cardState]); 10678c2ecf20Sopenharmony_ci 10688c2ecf20Sopenharmony_ci // -------------------------------------------------------------------------------- 10698c2ecf20Sopenharmony_ci // Initialize the routing and volume tables, then update the card's state. 10708c2ecf20Sopenharmony_ci // -------------------------------------------------------------------------------- 10718c2ecf20Sopenharmony_ci udelay(INTERCOMMAND_DELAY); 10728c2ecf20Sopenharmony_ci 10738c2ecf20Sopenharmony_ci for (channel = 0; channel < kAudioChannels; channel++) { 10748c2ecf20Sopenharmony_ci korg1212->sharedBufferPtr->volumeData[channel] = k1212MaxVolume; 10758c2ecf20Sopenharmony_ci //korg1212->sharedBufferPtr->routeData[channel] = channel; 10768c2ecf20Sopenharmony_ci korg1212->sharedBufferPtr->routeData[channel] = 8 + (channel & 1); 10778c2ecf20Sopenharmony_ci } 10788c2ecf20Sopenharmony_ci 10798c2ecf20Sopenharmony_ci snd_korg1212_WriteADCSensitivity(korg1212); 10808c2ecf20Sopenharmony_ci 10818c2ecf20Sopenharmony_ci udelay(INTERCOMMAND_DELAY); 10828c2ecf20Sopenharmony_ci rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_SetClockSourceRate, 10838c2ecf20Sopenharmony_ci ClockSourceSelector[korg1212->clkSrcRate], 10848c2ecf20Sopenharmony_ci 0, 0, 0); 10858c2ecf20Sopenharmony_ci if (rc) 10868c2ecf20Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: Set Clock Source Selector - RC = %d [%s]\n", 10878c2ecf20Sopenharmony_ci rc, stateName[korg1212->cardState]); 10888c2ecf20Sopenharmony_ci 10898c2ecf20Sopenharmony_ci rc = snd_korg1212_TurnOnIdleMonitor(korg1212); 10908c2ecf20Sopenharmony_ci snd_korg1212_setCardState(korg1212, K1212_STATE_READY); 10918c2ecf20Sopenharmony_ci 10928c2ecf20Sopenharmony_ci if (rc) 10938c2ecf20Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: Set Monitor On - RC = %d [%s]\n", 10948c2ecf20Sopenharmony_ci rc, stateName[korg1212->cardState]); 10958c2ecf20Sopenharmony_ci 10968c2ecf20Sopenharmony_ci snd_korg1212_setCardState(korg1212, K1212_STATE_DSP_COMPLETE); 10978c2ecf20Sopenharmony_ci} 10988c2ecf20Sopenharmony_ci 10998c2ecf20Sopenharmony_cistatic irqreturn_t snd_korg1212_interrupt(int irq, void *dev_id) 11008c2ecf20Sopenharmony_ci{ 11018c2ecf20Sopenharmony_ci u32 doorbellValue; 11028c2ecf20Sopenharmony_ci struct snd_korg1212 *korg1212 = dev_id; 11038c2ecf20Sopenharmony_ci 11048c2ecf20Sopenharmony_ci doorbellValue = readl(korg1212->inDoorbellPtr); 11058c2ecf20Sopenharmony_ci 11068c2ecf20Sopenharmony_ci if (!doorbellValue) 11078c2ecf20Sopenharmony_ci return IRQ_NONE; 11088c2ecf20Sopenharmony_ci 11098c2ecf20Sopenharmony_ci spin_lock(&korg1212->lock); 11108c2ecf20Sopenharmony_ci 11118c2ecf20Sopenharmony_ci writel(doorbellValue, korg1212->inDoorbellPtr); 11128c2ecf20Sopenharmony_ci 11138c2ecf20Sopenharmony_ci korg1212->irqcount++; 11148c2ecf20Sopenharmony_ci 11158c2ecf20Sopenharmony_ci korg1212->inIRQ++; 11168c2ecf20Sopenharmony_ci 11178c2ecf20Sopenharmony_ci switch (doorbellValue) { 11188c2ecf20Sopenharmony_ci case K1212_DB_DSPDownloadDone: 11198c2ecf20Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: IRQ DNLD count - %ld, %x, [%s].\n", 11208c2ecf20Sopenharmony_ci korg1212->irqcount, doorbellValue, 11218c2ecf20Sopenharmony_ci stateName[korg1212->cardState]); 11228c2ecf20Sopenharmony_ci if (korg1212->cardState == K1212_STATE_DSP_IN_PROCESS) { 11238c2ecf20Sopenharmony_ci korg1212->dsp_is_loaded = 1; 11248c2ecf20Sopenharmony_ci wake_up(&korg1212->wait); 11258c2ecf20Sopenharmony_ci } 11268c2ecf20Sopenharmony_ci break; 11278c2ecf20Sopenharmony_ci 11288c2ecf20Sopenharmony_ci // ------------------------------------------------------------------------ 11298c2ecf20Sopenharmony_ci // an error occurred - stop the card 11308c2ecf20Sopenharmony_ci // ------------------------------------------------------------------------ 11318c2ecf20Sopenharmony_ci case K1212_DB_DMAERROR: 11328c2ecf20Sopenharmony_ci K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: IRQ DMAE count - %ld, %x, [%s].\n", 11338c2ecf20Sopenharmony_ci korg1212->irqcount, doorbellValue, 11348c2ecf20Sopenharmony_ci stateName[korg1212->cardState]); 11358c2ecf20Sopenharmony_ci snd_printk(KERN_ERR "korg1212: DMA Error\n"); 11368c2ecf20Sopenharmony_ci korg1212->errorcnt++; 11378c2ecf20Sopenharmony_ci korg1212->totalerrorcnt++; 11388c2ecf20Sopenharmony_ci korg1212->sharedBufferPtr->cardCommand = 0; 11398c2ecf20Sopenharmony_ci snd_korg1212_setCardState(korg1212, K1212_STATE_ERRORSTOP); 11408c2ecf20Sopenharmony_ci break; 11418c2ecf20Sopenharmony_ci 11428c2ecf20Sopenharmony_ci // ------------------------------------------------------------------------ 11438c2ecf20Sopenharmony_ci // the card has stopped by our request. Clear the command word and signal 11448c2ecf20Sopenharmony_ci // the semaphore in case someone is waiting for this. 11458c2ecf20Sopenharmony_ci // ------------------------------------------------------------------------ 11468c2ecf20Sopenharmony_ci case K1212_DB_CARDSTOPPED: 11478c2ecf20Sopenharmony_ci K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: IRQ CSTP count - %ld, %x, [%s].\n", 11488c2ecf20Sopenharmony_ci korg1212->irqcount, doorbellValue, 11498c2ecf20Sopenharmony_ci stateName[korg1212->cardState]); 11508c2ecf20Sopenharmony_ci korg1212->sharedBufferPtr->cardCommand = 0; 11518c2ecf20Sopenharmony_ci break; 11528c2ecf20Sopenharmony_ci 11538c2ecf20Sopenharmony_ci default: 11548c2ecf20Sopenharmony_ci K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: IRQ DFLT count - %ld, %x, cpos=%d [%s].\n", 11558c2ecf20Sopenharmony_ci korg1212->irqcount, doorbellValue, 11568c2ecf20Sopenharmony_ci korg1212->currentBuffer, stateName[korg1212->cardState]); 11578c2ecf20Sopenharmony_ci if ((korg1212->cardState > K1212_STATE_SETUP) || korg1212->idleMonitorOn) { 11588c2ecf20Sopenharmony_ci korg1212->currentBuffer++; 11598c2ecf20Sopenharmony_ci 11608c2ecf20Sopenharmony_ci if (korg1212->currentBuffer >= kNumBuffers) 11618c2ecf20Sopenharmony_ci korg1212->currentBuffer = 0; 11628c2ecf20Sopenharmony_ci 11638c2ecf20Sopenharmony_ci if (!korg1212->running) 11648c2ecf20Sopenharmony_ci break; 11658c2ecf20Sopenharmony_ci 11668c2ecf20Sopenharmony_ci if (korg1212->capture_substream) { 11678c2ecf20Sopenharmony_ci spin_unlock(&korg1212->lock); 11688c2ecf20Sopenharmony_ci snd_pcm_period_elapsed(korg1212->capture_substream); 11698c2ecf20Sopenharmony_ci spin_lock(&korg1212->lock); 11708c2ecf20Sopenharmony_ci } 11718c2ecf20Sopenharmony_ci 11728c2ecf20Sopenharmony_ci if (korg1212->playback_substream) { 11738c2ecf20Sopenharmony_ci spin_unlock(&korg1212->lock); 11748c2ecf20Sopenharmony_ci snd_pcm_period_elapsed(korg1212->playback_substream); 11758c2ecf20Sopenharmony_ci spin_lock(&korg1212->lock); 11768c2ecf20Sopenharmony_ci } 11778c2ecf20Sopenharmony_ci } 11788c2ecf20Sopenharmony_ci break; 11798c2ecf20Sopenharmony_ci } 11808c2ecf20Sopenharmony_ci 11818c2ecf20Sopenharmony_ci korg1212->inIRQ--; 11828c2ecf20Sopenharmony_ci 11838c2ecf20Sopenharmony_ci spin_unlock(&korg1212->lock); 11848c2ecf20Sopenharmony_ci 11858c2ecf20Sopenharmony_ci return IRQ_HANDLED; 11868c2ecf20Sopenharmony_ci} 11878c2ecf20Sopenharmony_ci 11888c2ecf20Sopenharmony_cistatic int snd_korg1212_downloadDSPCode(struct snd_korg1212 *korg1212) 11898c2ecf20Sopenharmony_ci{ 11908c2ecf20Sopenharmony_ci int rc; 11918c2ecf20Sopenharmony_ci 11928c2ecf20Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: DSP download is starting... [%s]\n", 11938c2ecf20Sopenharmony_ci stateName[korg1212->cardState]); 11948c2ecf20Sopenharmony_ci 11958c2ecf20Sopenharmony_ci // --------------------------------------------------------------- 11968c2ecf20Sopenharmony_ci // verify the state of the card before proceeding. 11978c2ecf20Sopenharmony_ci // --------------------------------------------------------------- 11988c2ecf20Sopenharmony_ci if (korg1212->cardState >= K1212_STATE_DSP_IN_PROCESS) 11998c2ecf20Sopenharmony_ci return 1; 12008c2ecf20Sopenharmony_ci 12018c2ecf20Sopenharmony_ci snd_korg1212_setCardState(korg1212, K1212_STATE_DSP_IN_PROCESS); 12028c2ecf20Sopenharmony_ci 12038c2ecf20Sopenharmony_ci rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_StartDSPDownload, 12048c2ecf20Sopenharmony_ci UpperWordSwap(korg1212->dma_dsp.addr), 12058c2ecf20Sopenharmony_ci 0, 0, 0); 12068c2ecf20Sopenharmony_ci if (rc) 12078c2ecf20Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: Start DSP Download RC = %d [%s]\n", 12088c2ecf20Sopenharmony_ci rc, stateName[korg1212->cardState]); 12098c2ecf20Sopenharmony_ci 12108c2ecf20Sopenharmony_ci korg1212->dsp_is_loaded = 0; 12118c2ecf20Sopenharmony_ci wait_event_timeout(korg1212->wait, korg1212->dsp_is_loaded, HZ * CARD_BOOT_TIMEOUT); 12128c2ecf20Sopenharmony_ci if (! korg1212->dsp_is_loaded ) 12138c2ecf20Sopenharmony_ci return -EBUSY; /* timeout */ 12148c2ecf20Sopenharmony_ci 12158c2ecf20Sopenharmony_ci snd_korg1212_OnDSPDownloadComplete(korg1212); 12168c2ecf20Sopenharmony_ci 12178c2ecf20Sopenharmony_ci return 0; 12188c2ecf20Sopenharmony_ci} 12198c2ecf20Sopenharmony_ci 12208c2ecf20Sopenharmony_cistatic const struct snd_pcm_hardware snd_korg1212_playback_info = 12218c2ecf20Sopenharmony_ci{ 12228c2ecf20Sopenharmony_ci .info = (SNDRV_PCM_INFO_MMAP | 12238c2ecf20Sopenharmony_ci SNDRV_PCM_INFO_MMAP_VALID | 12248c2ecf20Sopenharmony_ci SNDRV_PCM_INFO_INTERLEAVED | 12258c2ecf20Sopenharmony_ci SNDRV_PCM_INFO_BATCH), 12268c2ecf20Sopenharmony_ci .formats = SNDRV_PCM_FMTBIT_S16_LE, 12278c2ecf20Sopenharmony_ci .rates = (SNDRV_PCM_RATE_44100 | 12288c2ecf20Sopenharmony_ci SNDRV_PCM_RATE_48000), 12298c2ecf20Sopenharmony_ci .rate_min = 44100, 12308c2ecf20Sopenharmony_ci .rate_max = 48000, 12318c2ecf20Sopenharmony_ci .channels_min = K1212_MIN_CHANNELS, 12328c2ecf20Sopenharmony_ci .channels_max = K1212_MAX_CHANNELS, 12338c2ecf20Sopenharmony_ci .buffer_bytes_max = K1212_MAX_BUF_SIZE, 12348c2ecf20Sopenharmony_ci .period_bytes_min = K1212_MIN_CHANNELS * 2 * kPlayBufferFrames, 12358c2ecf20Sopenharmony_ci .period_bytes_max = K1212_MAX_CHANNELS * 2 * kPlayBufferFrames, 12368c2ecf20Sopenharmony_ci .periods_min = K1212_PERIODS, 12378c2ecf20Sopenharmony_ci .periods_max = K1212_PERIODS, 12388c2ecf20Sopenharmony_ci .fifo_size = 0, 12398c2ecf20Sopenharmony_ci}; 12408c2ecf20Sopenharmony_ci 12418c2ecf20Sopenharmony_cistatic const struct snd_pcm_hardware snd_korg1212_capture_info = 12428c2ecf20Sopenharmony_ci{ 12438c2ecf20Sopenharmony_ci .info = (SNDRV_PCM_INFO_MMAP | 12448c2ecf20Sopenharmony_ci SNDRV_PCM_INFO_MMAP_VALID | 12458c2ecf20Sopenharmony_ci SNDRV_PCM_INFO_INTERLEAVED | 12468c2ecf20Sopenharmony_ci SNDRV_PCM_INFO_BATCH), 12478c2ecf20Sopenharmony_ci .formats = SNDRV_PCM_FMTBIT_S16_LE, 12488c2ecf20Sopenharmony_ci .rates = (SNDRV_PCM_RATE_44100 | 12498c2ecf20Sopenharmony_ci SNDRV_PCM_RATE_48000), 12508c2ecf20Sopenharmony_ci .rate_min = 44100, 12518c2ecf20Sopenharmony_ci .rate_max = 48000, 12528c2ecf20Sopenharmony_ci .channels_min = K1212_MIN_CHANNELS, 12538c2ecf20Sopenharmony_ci .channels_max = K1212_MAX_CHANNELS, 12548c2ecf20Sopenharmony_ci .buffer_bytes_max = K1212_MAX_BUF_SIZE, 12558c2ecf20Sopenharmony_ci .period_bytes_min = K1212_MIN_CHANNELS * 2 * kPlayBufferFrames, 12568c2ecf20Sopenharmony_ci .period_bytes_max = K1212_MAX_CHANNELS * 2 * kPlayBufferFrames, 12578c2ecf20Sopenharmony_ci .periods_min = K1212_PERIODS, 12588c2ecf20Sopenharmony_ci .periods_max = K1212_PERIODS, 12598c2ecf20Sopenharmony_ci .fifo_size = 0, 12608c2ecf20Sopenharmony_ci}; 12618c2ecf20Sopenharmony_ci 12628c2ecf20Sopenharmony_cistatic int snd_korg1212_silence(struct snd_korg1212 *korg1212, int pos, int count, int offset, int size) 12638c2ecf20Sopenharmony_ci{ 12648c2ecf20Sopenharmony_ci struct KorgAudioFrame * dst = korg1212->playDataBufsPtr[0].bufferData + pos; 12658c2ecf20Sopenharmony_ci int i; 12668c2ecf20Sopenharmony_ci 12678c2ecf20Sopenharmony_ci K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_silence pos=%d offset=%d size=%d count=%d\n", 12688c2ecf20Sopenharmony_ci pos, offset, size, count); 12698c2ecf20Sopenharmony_ci if (snd_BUG_ON(pos + count > K1212_MAX_SAMPLES)) 12708c2ecf20Sopenharmony_ci return -EINVAL; 12718c2ecf20Sopenharmony_ci 12728c2ecf20Sopenharmony_ci for (i=0; i < count; i++) { 12738c2ecf20Sopenharmony_ci#if K1212_DEBUG_LEVEL > 0 12748c2ecf20Sopenharmony_ci if ( (void *) dst < (void *) korg1212->playDataBufsPtr || 12758c2ecf20Sopenharmony_ci (void *) dst > (void *) korg1212->playDataBufsPtr[8].bufferData ) { 12768c2ecf20Sopenharmony_ci printk(KERN_DEBUG "K1212_DEBUG: snd_korg1212_silence KERNEL EFAULT dst=%p iter=%d\n", 12778c2ecf20Sopenharmony_ci dst, i); 12788c2ecf20Sopenharmony_ci return -EFAULT; 12798c2ecf20Sopenharmony_ci } 12808c2ecf20Sopenharmony_ci#endif 12818c2ecf20Sopenharmony_ci memset((void*) dst + offset, 0, size); 12828c2ecf20Sopenharmony_ci dst++; 12838c2ecf20Sopenharmony_ci } 12848c2ecf20Sopenharmony_ci 12858c2ecf20Sopenharmony_ci return 0; 12868c2ecf20Sopenharmony_ci} 12878c2ecf20Sopenharmony_ci 12888c2ecf20Sopenharmony_cistatic int snd_korg1212_copy_to(struct snd_pcm_substream *substream, 12898c2ecf20Sopenharmony_ci void __user *dst, int pos, int count, 12908c2ecf20Sopenharmony_ci bool in_kernel) 12918c2ecf20Sopenharmony_ci{ 12928c2ecf20Sopenharmony_ci struct snd_pcm_runtime *runtime = substream->runtime; 12938c2ecf20Sopenharmony_ci struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream); 12948c2ecf20Sopenharmony_ci struct KorgAudioFrame *src; 12958c2ecf20Sopenharmony_ci int i, size; 12968c2ecf20Sopenharmony_ci 12978c2ecf20Sopenharmony_ci pos = bytes_to_frames(runtime, pos); 12988c2ecf20Sopenharmony_ci count = bytes_to_frames(runtime, count); 12998c2ecf20Sopenharmony_ci size = korg1212->channels * 2; 13008c2ecf20Sopenharmony_ci src = korg1212->recordDataBufsPtr[0].bufferData + pos; 13018c2ecf20Sopenharmony_ci K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_copy_to pos=%d size=%d count=%d\n", 13028c2ecf20Sopenharmony_ci pos, size, count); 13038c2ecf20Sopenharmony_ci if (snd_BUG_ON(pos + count > K1212_MAX_SAMPLES)) 13048c2ecf20Sopenharmony_ci return -EINVAL; 13058c2ecf20Sopenharmony_ci 13068c2ecf20Sopenharmony_ci for (i=0; i < count; i++) { 13078c2ecf20Sopenharmony_ci#if K1212_DEBUG_LEVEL > 0 13088c2ecf20Sopenharmony_ci if ( (void *) src < (void *) korg1212->recordDataBufsPtr || 13098c2ecf20Sopenharmony_ci (void *) src > (void *) korg1212->recordDataBufsPtr[8].bufferData ) { 13108c2ecf20Sopenharmony_ci printk(KERN_DEBUG "K1212_DEBUG: snd_korg1212_copy_to KERNEL EFAULT, src=%p dst=%p iter=%d\n", src, dst, i); 13118c2ecf20Sopenharmony_ci return -EFAULT; 13128c2ecf20Sopenharmony_ci } 13138c2ecf20Sopenharmony_ci#endif 13148c2ecf20Sopenharmony_ci if (in_kernel) 13158c2ecf20Sopenharmony_ci memcpy((__force void *)dst, src, size); 13168c2ecf20Sopenharmony_ci else if (copy_to_user(dst, src, size)) 13178c2ecf20Sopenharmony_ci return -EFAULT; 13188c2ecf20Sopenharmony_ci src++; 13198c2ecf20Sopenharmony_ci dst += size; 13208c2ecf20Sopenharmony_ci } 13218c2ecf20Sopenharmony_ci 13228c2ecf20Sopenharmony_ci return 0; 13238c2ecf20Sopenharmony_ci} 13248c2ecf20Sopenharmony_ci 13258c2ecf20Sopenharmony_cistatic int snd_korg1212_copy_from(struct snd_pcm_substream *substream, 13268c2ecf20Sopenharmony_ci void __user *src, int pos, int count, 13278c2ecf20Sopenharmony_ci bool in_kernel) 13288c2ecf20Sopenharmony_ci{ 13298c2ecf20Sopenharmony_ci struct snd_pcm_runtime *runtime = substream->runtime; 13308c2ecf20Sopenharmony_ci struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream); 13318c2ecf20Sopenharmony_ci struct KorgAudioFrame *dst; 13328c2ecf20Sopenharmony_ci int i, size; 13338c2ecf20Sopenharmony_ci 13348c2ecf20Sopenharmony_ci pos = bytes_to_frames(runtime, pos); 13358c2ecf20Sopenharmony_ci count = bytes_to_frames(runtime, count); 13368c2ecf20Sopenharmony_ci size = korg1212->channels * 2; 13378c2ecf20Sopenharmony_ci dst = korg1212->playDataBufsPtr[0].bufferData + pos; 13388c2ecf20Sopenharmony_ci 13398c2ecf20Sopenharmony_ci K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_copy_from pos=%d size=%d count=%d\n", 13408c2ecf20Sopenharmony_ci pos, size, count); 13418c2ecf20Sopenharmony_ci 13428c2ecf20Sopenharmony_ci if (snd_BUG_ON(pos + count > K1212_MAX_SAMPLES)) 13438c2ecf20Sopenharmony_ci return -EINVAL; 13448c2ecf20Sopenharmony_ci 13458c2ecf20Sopenharmony_ci for (i=0; i < count; i++) { 13468c2ecf20Sopenharmony_ci#if K1212_DEBUG_LEVEL > 0 13478c2ecf20Sopenharmony_ci if ( (void *) dst < (void *) korg1212->playDataBufsPtr || 13488c2ecf20Sopenharmony_ci (void *) dst > (void *) korg1212->playDataBufsPtr[8].bufferData ) { 13498c2ecf20Sopenharmony_ci printk(KERN_DEBUG "K1212_DEBUG: snd_korg1212_copy_from KERNEL EFAULT, src=%p dst=%p iter=%d\n", src, dst, i); 13508c2ecf20Sopenharmony_ci return -EFAULT; 13518c2ecf20Sopenharmony_ci } 13528c2ecf20Sopenharmony_ci#endif 13538c2ecf20Sopenharmony_ci if (in_kernel) 13548c2ecf20Sopenharmony_ci memcpy(dst, (__force void *)src, size); 13558c2ecf20Sopenharmony_ci else if (copy_from_user(dst, src, size)) 13568c2ecf20Sopenharmony_ci return -EFAULT; 13578c2ecf20Sopenharmony_ci dst++; 13588c2ecf20Sopenharmony_ci src += size; 13598c2ecf20Sopenharmony_ci } 13608c2ecf20Sopenharmony_ci 13618c2ecf20Sopenharmony_ci return 0; 13628c2ecf20Sopenharmony_ci} 13638c2ecf20Sopenharmony_ci 13648c2ecf20Sopenharmony_cistatic void snd_korg1212_free_pcm(struct snd_pcm *pcm) 13658c2ecf20Sopenharmony_ci{ 13668c2ecf20Sopenharmony_ci struct snd_korg1212 *korg1212 = pcm->private_data; 13678c2ecf20Sopenharmony_ci 13688c2ecf20Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_free_pcm [%s]\n", 13698c2ecf20Sopenharmony_ci stateName[korg1212->cardState]); 13708c2ecf20Sopenharmony_ci 13718c2ecf20Sopenharmony_ci korg1212->pcm = NULL; 13728c2ecf20Sopenharmony_ci} 13738c2ecf20Sopenharmony_ci 13748c2ecf20Sopenharmony_cistatic int snd_korg1212_playback_open(struct snd_pcm_substream *substream) 13758c2ecf20Sopenharmony_ci{ 13768c2ecf20Sopenharmony_ci unsigned long flags; 13778c2ecf20Sopenharmony_ci struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream); 13788c2ecf20Sopenharmony_ci struct snd_pcm_runtime *runtime = substream->runtime; 13798c2ecf20Sopenharmony_ci 13808c2ecf20Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_playback_open [%s]\n", 13818c2ecf20Sopenharmony_ci stateName[korg1212->cardState]); 13828c2ecf20Sopenharmony_ci 13838c2ecf20Sopenharmony_ci snd_korg1212_OpenCard(korg1212); 13848c2ecf20Sopenharmony_ci 13858c2ecf20Sopenharmony_ci runtime->hw = snd_korg1212_playback_info; 13868c2ecf20Sopenharmony_ci snd_pcm_set_runtime_buffer(substream, &korg1212->dma_play); 13878c2ecf20Sopenharmony_ci 13888c2ecf20Sopenharmony_ci spin_lock_irqsave(&korg1212->lock, flags); 13898c2ecf20Sopenharmony_ci 13908c2ecf20Sopenharmony_ci korg1212->playback_substream = substream; 13918c2ecf20Sopenharmony_ci korg1212->playback_pid = current->pid; 13928c2ecf20Sopenharmony_ci korg1212->periodsize = K1212_PERIODS; 13938c2ecf20Sopenharmony_ci korg1212->channels = K1212_CHANNELS; 13948c2ecf20Sopenharmony_ci korg1212->errorcnt = 0; 13958c2ecf20Sopenharmony_ci 13968c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&korg1212->lock, flags); 13978c2ecf20Sopenharmony_ci 13988c2ecf20Sopenharmony_ci snd_pcm_hw_constraint_single(runtime, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 13998c2ecf20Sopenharmony_ci kPlayBufferFrames); 14008c2ecf20Sopenharmony_ci 14018c2ecf20Sopenharmony_ci return 0; 14028c2ecf20Sopenharmony_ci} 14038c2ecf20Sopenharmony_ci 14048c2ecf20Sopenharmony_ci 14058c2ecf20Sopenharmony_cistatic int snd_korg1212_capture_open(struct snd_pcm_substream *substream) 14068c2ecf20Sopenharmony_ci{ 14078c2ecf20Sopenharmony_ci unsigned long flags; 14088c2ecf20Sopenharmony_ci struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream); 14098c2ecf20Sopenharmony_ci struct snd_pcm_runtime *runtime = substream->runtime; 14108c2ecf20Sopenharmony_ci 14118c2ecf20Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_capture_open [%s]\n", 14128c2ecf20Sopenharmony_ci stateName[korg1212->cardState]); 14138c2ecf20Sopenharmony_ci 14148c2ecf20Sopenharmony_ci snd_korg1212_OpenCard(korg1212); 14158c2ecf20Sopenharmony_ci 14168c2ecf20Sopenharmony_ci runtime->hw = snd_korg1212_capture_info; 14178c2ecf20Sopenharmony_ci snd_pcm_set_runtime_buffer(substream, &korg1212->dma_rec); 14188c2ecf20Sopenharmony_ci 14198c2ecf20Sopenharmony_ci spin_lock_irqsave(&korg1212->lock, flags); 14208c2ecf20Sopenharmony_ci 14218c2ecf20Sopenharmony_ci korg1212->capture_substream = substream; 14228c2ecf20Sopenharmony_ci korg1212->capture_pid = current->pid; 14238c2ecf20Sopenharmony_ci korg1212->periodsize = K1212_PERIODS; 14248c2ecf20Sopenharmony_ci korg1212->channels = K1212_CHANNELS; 14258c2ecf20Sopenharmony_ci 14268c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&korg1212->lock, flags); 14278c2ecf20Sopenharmony_ci 14288c2ecf20Sopenharmony_ci snd_pcm_hw_constraint_single(runtime, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 14298c2ecf20Sopenharmony_ci kPlayBufferFrames); 14308c2ecf20Sopenharmony_ci return 0; 14318c2ecf20Sopenharmony_ci} 14328c2ecf20Sopenharmony_ci 14338c2ecf20Sopenharmony_cistatic int snd_korg1212_playback_close(struct snd_pcm_substream *substream) 14348c2ecf20Sopenharmony_ci{ 14358c2ecf20Sopenharmony_ci unsigned long flags; 14368c2ecf20Sopenharmony_ci struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream); 14378c2ecf20Sopenharmony_ci 14388c2ecf20Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_playback_close [%s]\n", 14398c2ecf20Sopenharmony_ci stateName[korg1212->cardState]); 14408c2ecf20Sopenharmony_ci 14418c2ecf20Sopenharmony_ci snd_korg1212_silence(korg1212, 0, K1212_MAX_SAMPLES, 0, korg1212->channels * 2); 14428c2ecf20Sopenharmony_ci 14438c2ecf20Sopenharmony_ci spin_lock_irqsave(&korg1212->lock, flags); 14448c2ecf20Sopenharmony_ci 14458c2ecf20Sopenharmony_ci korg1212->playback_pid = -1; 14468c2ecf20Sopenharmony_ci korg1212->playback_substream = NULL; 14478c2ecf20Sopenharmony_ci korg1212->periodsize = 0; 14488c2ecf20Sopenharmony_ci 14498c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&korg1212->lock, flags); 14508c2ecf20Sopenharmony_ci 14518c2ecf20Sopenharmony_ci snd_korg1212_CloseCard(korg1212); 14528c2ecf20Sopenharmony_ci return 0; 14538c2ecf20Sopenharmony_ci} 14548c2ecf20Sopenharmony_ci 14558c2ecf20Sopenharmony_cistatic int snd_korg1212_capture_close(struct snd_pcm_substream *substream) 14568c2ecf20Sopenharmony_ci{ 14578c2ecf20Sopenharmony_ci unsigned long flags; 14588c2ecf20Sopenharmony_ci struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream); 14598c2ecf20Sopenharmony_ci 14608c2ecf20Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_capture_close [%s]\n", 14618c2ecf20Sopenharmony_ci stateName[korg1212->cardState]); 14628c2ecf20Sopenharmony_ci 14638c2ecf20Sopenharmony_ci spin_lock_irqsave(&korg1212->lock, flags); 14648c2ecf20Sopenharmony_ci 14658c2ecf20Sopenharmony_ci korg1212->capture_pid = -1; 14668c2ecf20Sopenharmony_ci korg1212->capture_substream = NULL; 14678c2ecf20Sopenharmony_ci korg1212->periodsize = 0; 14688c2ecf20Sopenharmony_ci 14698c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&korg1212->lock, flags); 14708c2ecf20Sopenharmony_ci 14718c2ecf20Sopenharmony_ci snd_korg1212_CloseCard(korg1212); 14728c2ecf20Sopenharmony_ci return 0; 14738c2ecf20Sopenharmony_ci} 14748c2ecf20Sopenharmony_ci 14758c2ecf20Sopenharmony_cistatic int snd_korg1212_ioctl(struct snd_pcm_substream *substream, 14768c2ecf20Sopenharmony_ci unsigned int cmd, void *arg) 14778c2ecf20Sopenharmony_ci{ 14788c2ecf20Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_ioctl: cmd=%d\n", cmd); 14798c2ecf20Sopenharmony_ci 14808c2ecf20Sopenharmony_ci if (cmd == SNDRV_PCM_IOCTL1_CHANNEL_INFO ) { 14818c2ecf20Sopenharmony_ci struct snd_pcm_channel_info *info = arg; 14828c2ecf20Sopenharmony_ci info->offset = 0; 14838c2ecf20Sopenharmony_ci info->first = info->channel * 16; 14848c2ecf20Sopenharmony_ci info->step = 256; 14858c2ecf20Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: channel_info %d:, offset=%ld, first=%d, step=%d\n", info->channel, info->offset, info->first, info->step); 14868c2ecf20Sopenharmony_ci return 0; 14878c2ecf20Sopenharmony_ci } 14888c2ecf20Sopenharmony_ci 14898c2ecf20Sopenharmony_ci return snd_pcm_lib_ioctl(substream, cmd, arg); 14908c2ecf20Sopenharmony_ci} 14918c2ecf20Sopenharmony_ci 14928c2ecf20Sopenharmony_cistatic int snd_korg1212_hw_params(struct snd_pcm_substream *substream, 14938c2ecf20Sopenharmony_ci struct snd_pcm_hw_params *params) 14948c2ecf20Sopenharmony_ci{ 14958c2ecf20Sopenharmony_ci unsigned long flags; 14968c2ecf20Sopenharmony_ci struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream); 14978c2ecf20Sopenharmony_ci int err; 14988c2ecf20Sopenharmony_ci pid_t this_pid; 14998c2ecf20Sopenharmony_ci pid_t other_pid; 15008c2ecf20Sopenharmony_ci 15018c2ecf20Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_hw_params [%s]\n", 15028c2ecf20Sopenharmony_ci stateName[korg1212->cardState]); 15038c2ecf20Sopenharmony_ci 15048c2ecf20Sopenharmony_ci spin_lock_irqsave(&korg1212->lock, flags); 15058c2ecf20Sopenharmony_ci 15068c2ecf20Sopenharmony_ci if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) { 15078c2ecf20Sopenharmony_ci this_pid = korg1212->playback_pid; 15088c2ecf20Sopenharmony_ci other_pid = korg1212->capture_pid; 15098c2ecf20Sopenharmony_ci } else { 15108c2ecf20Sopenharmony_ci this_pid = korg1212->capture_pid; 15118c2ecf20Sopenharmony_ci other_pid = korg1212->playback_pid; 15128c2ecf20Sopenharmony_ci } 15138c2ecf20Sopenharmony_ci 15148c2ecf20Sopenharmony_ci if ((other_pid > 0) && (this_pid != other_pid)) { 15158c2ecf20Sopenharmony_ci 15168c2ecf20Sopenharmony_ci /* The other stream is open, and not by the same 15178c2ecf20Sopenharmony_ci task as this one. Make sure that the parameters 15188c2ecf20Sopenharmony_ci that matter are the same. 15198c2ecf20Sopenharmony_ci */ 15208c2ecf20Sopenharmony_ci 15218c2ecf20Sopenharmony_ci if ((int)params_rate(params) != korg1212->clkRate) { 15228c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&korg1212->lock, flags); 15238c2ecf20Sopenharmony_ci _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_RATE); 15248c2ecf20Sopenharmony_ci return -EBUSY; 15258c2ecf20Sopenharmony_ci } 15268c2ecf20Sopenharmony_ci 15278c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&korg1212->lock, flags); 15288c2ecf20Sopenharmony_ci return 0; 15298c2ecf20Sopenharmony_ci } 15308c2ecf20Sopenharmony_ci 15318c2ecf20Sopenharmony_ci if ((err = snd_korg1212_SetRate(korg1212, params_rate(params))) < 0) { 15328c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&korg1212->lock, flags); 15338c2ecf20Sopenharmony_ci return err; 15348c2ecf20Sopenharmony_ci } 15358c2ecf20Sopenharmony_ci 15368c2ecf20Sopenharmony_ci korg1212->channels = params_channels(params); 15378c2ecf20Sopenharmony_ci korg1212->periodsize = K1212_PERIOD_BYTES; 15388c2ecf20Sopenharmony_ci 15398c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&korg1212->lock, flags); 15408c2ecf20Sopenharmony_ci 15418c2ecf20Sopenharmony_ci return 0; 15428c2ecf20Sopenharmony_ci} 15438c2ecf20Sopenharmony_ci 15448c2ecf20Sopenharmony_cistatic int snd_korg1212_prepare(struct snd_pcm_substream *substream) 15458c2ecf20Sopenharmony_ci{ 15468c2ecf20Sopenharmony_ci struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream); 15478c2ecf20Sopenharmony_ci int rc; 15488c2ecf20Sopenharmony_ci 15498c2ecf20Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_prepare [%s]\n", 15508c2ecf20Sopenharmony_ci stateName[korg1212->cardState]); 15518c2ecf20Sopenharmony_ci 15528c2ecf20Sopenharmony_ci spin_lock_irq(&korg1212->lock); 15538c2ecf20Sopenharmony_ci 15548c2ecf20Sopenharmony_ci /* FIXME: we should wait for ack! */ 15558c2ecf20Sopenharmony_ci if (korg1212->stop_pending_cnt > 0) { 15568c2ecf20Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_prepare - Stop is pending... [%s]\n", 15578c2ecf20Sopenharmony_ci stateName[korg1212->cardState]); 15588c2ecf20Sopenharmony_ci spin_unlock_irq(&korg1212->lock); 15598c2ecf20Sopenharmony_ci return -EAGAIN; 15608c2ecf20Sopenharmony_ci /* 15618c2ecf20Sopenharmony_ci korg1212->sharedBufferPtr->cardCommand = 0; 15628c2ecf20Sopenharmony_ci del_timer(&korg1212->timer); 15638c2ecf20Sopenharmony_ci korg1212->stop_pending_cnt = 0; 15648c2ecf20Sopenharmony_ci */ 15658c2ecf20Sopenharmony_ci } 15668c2ecf20Sopenharmony_ci 15678c2ecf20Sopenharmony_ci rc = snd_korg1212_SetupForPlay(korg1212); 15688c2ecf20Sopenharmony_ci 15698c2ecf20Sopenharmony_ci korg1212->currentBuffer = 0; 15708c2ecf20Sopenharmony_ci 15718c2ecf20Sopenharmony_ci spin_unlock_irq(&korg1212->lock); 15728c2ecf20Sopenharmony_ci 15738c2ecf20Sopenharmony_ci return rc ? -EINVAL : 0; 15748c2ecf20Sopenharmony_ci} 15758c2ecf20Sopenharmony_ci 15768c2ecf20Sopenharmony_cistatic int snd_korg1212_trigger(struct snd_pcm_substream *substream, 15778c2ecf20Sopenharmony_ci int cmd) 15788c2ecf20Sopenharmony_ci{ 15798c2ecf20Sopenharmony_ci struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream); 15808c2ecf20Sopenharmony_ci int rc; 15818c2ecf20Sopenharmony_ci 15828c2ecf20Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_trigger [%s] cmd=%d\n", 15838c2ecf20Sopenharmony_ci stateName[korg1212->cardState], cmd); 15848c2ecf20Sopenharmony_ci 15858c2ecf20Sopenharmony_ci spin_lock(&korg1212->lock); 15868c2ecf20Sopenharmony_ci switch (cmd) { 15878c2ecf20Sopenharmony_ci case SNDRV_PCM_TRIGGER_START: 15888c2ecf20Sopenharmony_ci/* 15898c2ecf20Sopenharmony_ci if (korg1212->running) { 15908c2ecf20Sopenharmony_ci K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_trigger: Already running?\n"); 15918c2ecf20Sopenharmony_ci break; 15928c2ecf20Sopenharmony_ci } 15938c2ecf20Sopenharmony_ci*/ 15948c2ecf20Sopenharmony_ci korg1212->running++; 15958c2ecf20Sopenharmony_ci rc = snd_korg1212_TriggerPlay(korg1212); 15968c2ecf20Sopenharmony_ci break; 15978c2ecf20Sopenharmony_ci 15988c2ecf20Sopenharmony_ci case SNDRV_PCM_TRIGGER_STOP: 15998c2ecf20Sopenharmony_ci/* 16008c2ecf20Sopenharmony_ci if (!korg1212->running) { 16018c2ecf20Sopenharmony_ci K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_trigger: Already stopped?\n"); 16028c2ecf20Sopenharmony_ci break; 16038c2ecf20Sopenharmony_ci } 16048c2ecf20Sopenharmony_ci*/ 16058c2ecf20Sopenharmony_ci korg1212->running--; 16068c2ecf20Sopenharmony_ci rc = snd_korg1212_StopPlay(korg1212); 16078c2ecf20Sopenharmony_ci break; 16088c2ecf20Sopenharmony_ci 16098c2ecf20Sopenharmony_ci default: 16108c2ecf20Sopenharmony_ci rc = 1; 16118c2ecf20Sopenharmony_ci break; 16128c2ecf20Sopenharmony_ci } 16138c2ecf20Sopenharmony_ci spin_unlock(&korg1212->lock); 16148c2ecf20Sopenharmony_ci return rc ? -EINVAL : 0; 16158c2ecf20Sopenharmony_ci} 16168c2ecf20Sopenharmony_ci 16178c2ecf20Sopenharmony_cistatic snd_pcm_uframes_t snd_korg1212_playback_pointer(struct snd_pcm_substream *substream) 16188c2ecf20Sopenharmony_ci{ 16198c2ecf20Sopenharmony_ci struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream); 16208c2ecf20Sopenharmony_ci snd_pcm_uframes_t pos; 16218c2ecf20Sopenharmony_ci 16228c2ecf20Sopenharmony_ci pos = korg1212->currentBuffer * kPlayBufferFrames; 16238c2ecf20Sopenharmony_ci 16248c2ecf20Sopenharmony_ci K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_playback_pointer [%s] %ld\n", 16258c2ecf20Sopenharmony_ci stateName[korg1212->cardState], pos); 16268c2ecf20Sopenharmony_ci 16278c2ecf20Sopenharmony_ci return pos; 16288c2ecf20Sopenharmony_ci} 16298c2ecf20Sopenharmony_ci 16308c2ecf20Sopenharmony_cistatic snd_pcm_uframes_t snd_korg1212_capture_pointer(struct snd_pcm_substream *substream) 16318c2ecf20Sopenharmony_ci{ 16328c2ecf20Sopenharmony_ci struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream); 16338c2ecf20Sopenharmony_ci snd_pcm_uframes_t pos; 16348c2ecf20Sopenharmony_ci 16358c2ecf20Sopenharmony_ci pos = korg1212->currentBuffer * kPlayBufferFrames; 16368c2ecf20Sopenharmony_ci 16378c2ecf20Sopenharmony_ci K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_capture_pointer [%s] %ld\n", 16388c2ecf20Sopenharmony_ci stateName[korg1212->cardState], pos); 16398c2ecf20Sopenharmony_ci 16408c2ecf20Sopenharmony_ci return pos; 16418c2ecf20Sopenharmony_ci} 16428c2ecf20Sopenharmony_ci 16438c2ecf20Sopenharmony_cistatic int snd_korg1212_playback_copy(struct snd_pcm_substream *substream, 16448c2ecf20Sopenharmony_ci int channel, unsigned long pos, 16458c2ecf20Sopenharmony_ci void __user *src, unsigned long count) 16468c2ecf20Sopenharmony_ci{ 16478c2ecf20Sopenharmony_ci return snd_korg1212_copy_from(substream, src, pos, count, false); 16488c2ecf20Sopenharmony_ci} 16498c2ecf20Sopenharmony_ci 16508c2ecf20Sopenharmony_cistatic int snd_korg1212_playback_copy_kernel(struct snd_pcm_substream *substream, 16518c2ecf20Sopenharmony_ci int channel, unsigned long pos, 16528c2ecf20Sopenharmony_ci void *src, unsigned long count) 16538c2ecf20Sopenharmony_ci{ 16548c2ecf20Sopenharmony_ci return snd_korg1212_copy_from(substream, (void __user *)src, 16558c2ecf20Sopenharmony_ci pos, count, true); 16568c2ecf20Sopenharmony_ci} 16578c2ecf20Sopenharmony_ci 16588c2ecf20Sopenharmony_cistatic int snd_korg1212_playback_silence(struct snd_pcm_substream *substream, 16598c2ecf20Sopenharmony_ci int channel, /* not used (interleaved data) */ 16608c2ecf20Sopenharmony_ci unsigned long pos, 16618c2ecf20Sopenharmony_ci unsigned long count) 16628c2ecf20Sopenharmony_ci{ 16638c2ecf20Sopenharmony_ci struct snd_pcm_runtime *runtime = substream->runtime; 16648c2ecf20Sopenharmony_ci struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream); 16658c2ecf20Sopenharmony_ci 16668c2ecf20Sopenharmony_ci return snd_korg1212_silence(korg1212, bytes_to_frames(runtime, pos), 16678c2ecf20Sopenharmony_ci bytes_to_frames(runtime, count), 16688c2ecf20Sopenharmony_ci 0, korg1212->channels * 2); 16698c2ecf20Sopenharmony_ci} 16708c2ecf20Sopenharmony_ci 16718c2ecf20Sopenharmony_cistatic int snd_korg1212_capture_copy(struct snd_pcm_substream *substream, 16728c2ecf20Sopenharmony_ci int channel, unsigned long pos, 16738c2ecf20Sopenharmony_ci void __user *dst, unsigned long count) 16748c2ecf20Sopenharmony_ci{ 16758c2ecf20Sopenharmony_ci return snd_korg1212_copy_to(substream, dst, pos, count, false); 16768c2ecf20Sopenharmony_ci} 16778c2ecf20Sopenharmony_ci 16788c2ecf20Sopenharmony_cistatic int snd_korg1212_capture_copy_kernel(struct snd_pcm_substream *substream, 16798c2ecf20Sopenharmony_ci int channel, unsigned long pos, 16808c2ecf20Sopenharmony_ci void *dst, unsigned long count) 16818c2ecf20Sopenharmony_ci{ 16828c2ecf20Sopenharmony_ci return snd_korg1212_copy_to(substream, (void __user *)dst, 16838c2ecf20Sopenharmony_ci pos, count, true); 16848c2ecf20Sopenharmony_ci} 16858c2ecf20Sopenharmony_ci 16868c2ecf20Sopenharmony_cistatic const struct snd_pcm_ops snd_korg1212_playback_ops = { 16878c2ecf20Sopenharmony_ci .open = snd_korg1212_playback_open, 16888c2ecf20Sopenharmony_ci .close = snd_korg1212_playback_close, 16898c2ecf20Sopenharmony_ci .ioctl = snd_korg1212_ioctl, 16908c2ecf20Sopenharmony_ci .hw_params = snd_korg1212_hw_params, 16918c2ecf20Sopenharmony_ci .prepare = snd_korg1212_prepare, 16928c2ecf20Sopenharmony_ci .trigger = snd_korg1212_trigger, 16938c2ecf20Sopenharmony_ci .pointer = snd_korg1212_playback_pointer, 16948c2ecf20Sopenharmony_ci .copy_user = snd_korg1212_playback_copy, 16958c2ecf20Sopenharmony_ci .copy_kernel = snd_korg1212_playback_copy_kernel, 16968c2ecf20Sopenharmony_ci .fill_silence = snd_korg1212_playback_silence, 16978c2ecf20Sopenharmony_ci}; 16988c2ecf20Sopenharmony_ci 16998c2ecf20Sopenharmony_cistatic const struct snd_pcm_ops snd_korg1212_capture_ops = { 17008c2ecf20Sopenharmony_ci .open = snd_korg1212_capture_open, 17018c2ecf20Sopenharmony_ci .close = snd_korg1212_capture_close, 17028c2ecf20Sopenharmony_ci .ioctl = snd_korg1212_ioctl, 17038c2ecf20Sopenharmony_ci .hw_params = snd_korg1212_hw_params, 17048c2ecf20Sopenharmony_ci .prepare = snd_korg1212_prepare, 17058c2ecf20Sopenharmony_ci .trigger = snd_korg1212_trigger, 17068c2ecf20Sopenharmony_ci .pointer = snd_korg1212_capture_pointer, 17078c2ecf20Sopenharmony_ci .copy_user = snd_korg1212_capture_copy, 17088c2ecf20Sopenharmony_ci .copy_kernel = snd_korg1212_capture_copy_kernel, 17098c2ecf20Sopenharmony_ci}; 17108c2ecf20Sopenharmony_ci 17118c2ecf20Sopenharmony_ci/* 17128c2ecf20Sopenharmony_ci * Control Interface 17138c2ecf20Sopenharmony_ci */ 17148c2ecf20Sopenharmony_ci 17158c2ecf20Sopenharmony_cistatic int snd_korg1212_control_phase_info(struct snd_kcontrol *kcontrol, 17168c2ecf20Sopenharmony_ci struct snd_ctl_elem_info *uinfo) 17178c2ecf20Sopenharmony_ci{ 17188c2ecf20Sopenharmony_ci uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; 17198c2ecf20Sopenharmony_ci uinfo->count = (kcontrol->private_value >= 8) ? 2 : 1; 17208c2ecf20Sopenharmony_ci return 0; 17218c2ecf20Sopenharmony_ci} 17228c2ecf20Sopenharmony_ci 17238c2ecf20Sopenharmony_cistatic int snd_korg1212_control_phase_get(struct snd_kcontrol *kcontrol, 17248c2ecf20Sopenharmony_ci struct snd_ctl_elem_value *u) 17258c2ecf20Sopenharmony_ci{ 17268c2ecf20Sopenharmony_ci struct snd_korg1212 *korg1212 = snd_kcontrol_chip(kcontrol); 17278c2ecf20Sopenharmony_ci int i = kcontrol->private_value; 17288c2ecf20Sopenharmony_ci 17298c2ecf20Sopenharmony_ci spin_lock_irq(&korg1212->lock); 17308c2ecf20Sopenharmony_ci 17318c2ecf20Sopenharmony_ci u->value.integer.value[0] = korg1212->volumePhase[i]; 17328c2ecf20Sopenharmony_ci 17338c2ecf20Sopenharmony_ci if (i >= 8) 17348c2ecf20Sopenharmony_ci u->value.integer.value[1] = korg1212->volumePhase[i+1]; 17358c2ecf20Sopenharmony_ci 17368c2ecf20Sopenharmony_ci spin_unlock_irq(&korg1212->lock); 17378c2ecf20Sopenharmony_ci 17388c2ecf20Sopenharmony_ci return 0; 17398c2ecf20Sopenharmony_ci} 17408c2ecf20Sopenharmony_ci 17418c2ecf20Sopenharmony_cistatic int snd_korg1212_control_phase_put(struct snd_kcontrol *kcontrol, 17428c2ecf20Sopenharmony_ci struct snd_ctl_elem_value *u) 17438c2ecf20Sopenharmony_ci{ 17448c2ecf20Sopenharmony_ci struct snd_korg1212 *korg1212 = snd_kcontrol_chip(kcontrol); 17458c2ecf20Sopenharmony_ci int change = 0; 17468c2ecf20Sopenharmony_ci int i, val; 17478c2ecf20Sopenharmony_ci 17488c2ecf20Sopenharmony_ci spin_lock_irq(&korg1212->lock); 17498c2ecf20Sopenharmony_ci 17508c2ecf20Sopenharmony_ci i = kcontrol->private_value; 17518c2ecf20Sopenharmony_ci 17528c2ecf20Sopenharmony_ci korg1212->volumePhase[i] = !!u->value.integer.value[0]; 17538c2ecf20Sopenharmony_ci 17548c2ecf20Sopenharmony_ci val = korg1212->sharedBufferPtr->volumeData[kcontrol->private_value]; 17558c2ecf20Sopenharmony_ci 17568c2ecf20Sopenharmony_ci if ((u->value.integer.value[0] != 0) != (val < 0)) { 17578c2ecf20Sopenharmony_ci val = abs(val) * (korg1212->volumePhase[i] > 0 ? -1 : 1); 17588c2ecf20Sopenharmony_ci korg1212->sharedBufferPtr->volumeData[i] = val; 17598c2ecf20Sopenharmony_ci change = 1; 17608c2ecf20Sopenharmony_ci } 17618c2ecf20Sopenharmony_ci 17628c2ecf20Sopenharmony_ci if (i >= 8) { 17638c2ecf20Sopenharmony_ci korg1212->volumePhase[i+1] = !!u->value.integer.value[1]; 17648c2ecf20Sopenharmony_ci 17658c2ecf20Sopenharmony_ci val = korg1212->sharedBufferPtr->volumeData[kcontrol->private_value+1]; 17668c2ecf20Sopenharmony_ci 17678c2ecf20Sopenharmony_ci if ((u->value.integer.value[1] != 0) != (val < 0)) { 17688c2ecf20Sopenharmony_ci val = abs(val) * (korg1212->volumePhase[i+1] > 0 ? -1 : 1); 17698c2ecf20Sopenharmony_ci korg1212->sharedBufferPtr->volumeData[i+1] = val; 17708c2ecf20Sopenharmony_ci change = 1; 17718c2ecf20Sopenharmony_ci } 17728c2ecf20Sopenharmony_ci } 17738c2ecf20Sopenharmony_ci 17748c2ecf20Sopenharmony_ci spin_unlock_irq(&korg1212->lock); 17758c2ecf20Sopenharmony_ci 17768c2ecf20Sopenharmony_ci return change; 17778c2ecf20Sopenharmony_ci} 17788c2ecf20Sopenharmony_ci 17798c2ecf20Sopenharmony_cistatic int snd_korg1212_control_volume_info(struct snd_kcontrol *kcontrol, 17808c2ecf20Sopenharmony_ci struct snd_ctl_elem_info *uinfo) 17818c2ecf20Sopenharmony_ci{ 17828c2ecf20Sopenharmony_ci uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 17838c2ecf20Sopenharmony_ci uinfo->count = (kcontrol->private_value >= 8) ? 2 : 1; 17848c2ecf20Sopenharmony_ci uinfo->value.integer.min = k1212MinVolume; 17858c2ecf20Sopenharmony_ci uinfo->value.integer.max = k1212MaxVolume; 17868c2ecf20Sopenharmony_ci return 0; 17878c2ecf20Sopenharmony_ci} 17888c2ecf20Sopenharmony_ci 17898c2ecf20Sopenharmony_cistatic int snd_korg1212_control_volume_get(struct snd_kcontrol *kcontrol, 17908c2ecf20Sopenharmony_ci struct snd_ctl_elem_value *u) 17918c2ecf20Sopenharmony_ci{ 17928c2ecf20Sopenharmony_ci struct snd_korg1212 *korg1212 = snd_kcontrol_chip(kcontrol); 17938c2ecf20Sopenharmony_ci int i; 17948c2ecf20Sopenharmony_ci 17958c2ecf20Sopenharmony_ci spin_lock_irq(&korg1212->lock); 17968c2ecf20Sopenharmony_ci 17978c2ecf20Sopenharmony_ci i = kcontrol->private_value; 17988c2ecf20Sopenharmony_ci u->value.integer.value[0] = abs(korg1212->sharedBufferPtr->volumeData[i]); 17998c2ecf20Sopenharmony_ci 18008c2ecf20Sopenharmony_ci if (i >= 8) 18018c2ecf20Sopenharmony_ci u->value.integer.value[1] = abs(korg1212->sharedBufferPtr->volumeData[i+1]); 18028c2ecf20Sopenharmony_ci 18038c2ecf20Sopenharmony_ci spin_unlock_irq(&korg1212->lock); 18048c2ecf20Sopenharmony_ci 18058c2ecf20Sopenharmony_ci return 0; 18068c2ecf20Sopenharmony_ci} 18078c2ecf20Sopenharmony_ci 18088c2ecf20Sopenharmony_cistatic int snd_korg1212_control_volume_put(struct snd_kcontrol *kcontrol, 18098c2ecf20Sopenharmony_ci struct snd_ctl_elem_value *u) 18108c2ecf20Sopenharmony_ci{ 18118c2ecf20Sopenharmony_ci struct snd_korg1212 *korg1212 = snd_kcontrol_chip(kcontrol); 18128c2ecf20Sopenharmony_ci int change = 0; 18138c2ecf20Sopenharmony_ci int i; 18148c2ecf20Sopenharmony_ci int val; 18158c2ecf20Sopenharmony_ci 18168c2ecf20Sopenharmony_ci spin_lock_irq(&korg1212->lock); 18178c2ecf20Sopenharmony_ci 18188c2ecf20Sopenharmony_ci i = kcontrol->private_value; 18198c2ecf20Sopenharmony_ci 18208c2ecf20Sopenharmony_ci if (u->value.integer.value[0] >= k1212MinVolume && 18218c2ecf20Sopenharmony_ci u->value.integer.value[0] >= k1212MaxVolume && 18228c2ecf20Sopenharmony_ci u->value.integer.value[0] != 18238c2ecf20Sopenharmony_ci abs(korg1212->sharedBufferPtr->volumeData[i])) { 18248c2ecf20Sopenharmony_ci val = korg1212->volumePhase[i] > 0 ? -1 : 1; 18258c2ecf20Sopenharmony_ci val *= u->value.integer.value[0]; 18268c2ecf20Sopenharmony_ci korg1212->sharedBufferPtr->volumeData[i] = val; 18278c2ecf20Sopenharmony_ci change = 1; 18288c2ecf20Sopenharmony_ci } 18298c2ecf20Sopenharmony_ci 18308c2ecf20Sopenharmony_ci if (i >= 8) { 18318c2ecf20Sopenharmony_ci if (u->value.integer.value[1] >= k1212MinVolume && 18328c2ecf20Sopenharmony_ci u->value.integer.value[1] >= k1212MaxVolume && 18338c2ecf20Sopenharmony_ci u->value.integer.value[1] != 18348c2ecf20Sopenharmony_ci abs(korg1212->sharedBufferPtr->volumeData[i+1])) { 18358c2ecf20Sopenharmony_ci val = korg1212->volumePhase[i+1] > 0 ? -1 : 1; 18368c2ecf20Sopenharmony_ci val *= u->value.integer.value[1]; 18378c2ecf20Sopenharmony_ci korg1212->sharedBufferPtr->volumeData[i+1] = val; 18388c2ecf20Sopenharmony_ci change = 1; 18398c2ecf20Sopenharmony_ci } 18408c2ecf20Sopenharmony_ci } 18418c2ecf20Sopenharmony_ci 18428c2ecf20Sopenharmony_ci spin_unlock_irq(&korg1212->lock); 18438c2ecf20Sopenharmony_ci 18448c2ecf20Sopenharmony_ci return change; 18458c2ecf20Sopenharmony_ci} 18468c2ecf20Sopenharmony_ci 18478c2ecf20Sopenharmony_cistatic int snd_korg1212_control_route_info(struct snd_kcontrol *kcontrol, 18488c2ecf20Sopenharmony_ci struct snd_ctl_elem_info *uinfo) 18498c2ecf20Sopenharmony_ci{ 18508c2ecf20Sopenharmony_ci return snd_ctl_enum_info(uinfo, 18518c2ecf20Sopenharmony_ci (kcontrol->private_value >= 8) ? 2 : 1, 18528c2ecf20Sopenharmony_ci kAudioChannels, channelName); 18538c2ecf20Sopenharmony_ci} 18548c2ecf20Sopenharmony_ci 18558c2ecf20Sopenharmony_cistatic int snd_korg1212_control_route_get(struct snd_kcontrol *kcontrol, 18568c2ecf20Sopenharmony_ci struct snd_ctl_elem_value *u) 18578c2ecf20Sopenharmony_ci{ 18588c2ecf20Sopenharmony_ci struct snd_korg1212 *korg1212 = snd_kcontrol_chip(kcontrol); 18598c2ecf20Sopenharmony_ci int i; 18608c2ecf20Sopenharmony_ci 18618c2ecf20Sopenharmony_ci spin_lock_irq(&korg1212->lock); 18628c2ecf20Sopenharmony_ci 18638c2ecf20Sopenharmony_ci i = kcontrol->private_value; 18648c2ecf20Sopenharmony_ci u->value.enumerated.item[0] = korg1212->sharedBufferPtr->routeData[i]; 18658c2ecf20Sopenharmony_ci 18668c2ecf20Sopenharmony_ci if (i >= 8) 18678c2ecf20Sopenharmony_ci u->value.enumerated.item[1] = korg1212->sharedBufferPtr->routeData[i+1]; 18688c2ecf20Sopenharmony_ci 18698c2ecf20Sopenharmony_ci spin_unlock_irq(&korg1212->lock); 18708c2ecf20Sopenharmony_ci 18718c2ecf20Sopenharmony_ci return 0; 18728c2ecf20Sopenharmony_ci} 18738c2ecf20Sopenharmony_ci 18748c2ecf20Sopenharmony_cistatic int snd_korg1212_control_route_put(struct snd_kcontrol *kcontrol, 18758c2ecf20Sopenharmony_ci struct snd_ctl_elem_value *u) 18768c2ecf20Sopenharmony_ci{ 18778c2ecf20Sopenharmony_ci struct snd_korg1212 *korg1212 = snd_kcontrol_chip(kcontrol); 18788c2ecf20Sopenharmony_ci int change = 0, i; 18798c2ecf20Sopenharmony_ci 18808c2ecf20Sopenharmony_ci spin_lock_irq(&korg1212->lock); 18818c2ecf20Sopenharmony_ci 18828c2ecf20Sopenharmony_ci i = kcontrol->private_value; 18838c2ecf20Sopenharmony_ci 18848c2ecf20Sopenharmony_ci if (u->value.enumerated.item[0] < kAudioChannels && 18858c2ecf20Sopenharmony_ci u->value.enumerated.item[0] != 18868c2ecf20Sopenharmony_ci (unsigned) korg1212->sharedBufferPtr->volumeData[i]) { 18878c2ecf20Sopenharmony_ci korg1212->sharedBufferPtr->routeData[i] = u->value.enumerated.item[0]; 18888c2ecf20Sopenharmony_ci change = 1; 18898c2ecf20Sopenharmony_ci } 18908c2ecf20Sopenharmony_ci 18918c2ecf20Sopenharmony_ci if (i >= 8) { 18928c2ecf20Sopenharmony_ci if (u->value.enumerated.item[1] < kAudioChannels && 18938c2ecf20Sopenharmony_ci u->value.enumerated.item[1] != 18948c2ecf20Sopenharmony_ci (unsigned) korg1212->sharedBufferPtr->volumeData[i+1]) { 18958c2ecf20Sopenharmony_ci korg1212->sharedBufferPtr->routeData[i+1] = u->value.enumerated.item[1]; 18968c2ecf20Sopenharmony_ci change = 1; 18978c2ecf20Sopenharmony_ci } 18988c2ecf20Sopenharmony_ci } 18998c2ecf20Sopenharmony_ci 19008c2ecf20Sopenharmony_ci spin_unlock_irq(&korg1212->lock); 19018c2ecf20Sopenharmony_ci 19028c2ecf20Sopenharmony_ci return change; 19038c2ecf20Sopenharmony_ci} 19048c2ecf20Sopenharmony_ci 19058c2ecf20Sopenharmony_cistatic int snd_korg1212_control_info(struct snd_kcontrol *kcontrol, 19068c2ecf20Sopenharmony_ci struct snd_ctl_elem_info *uinfo) 19078c2ecf20Sopenharmony_ci{ 19088c2ecf20Sopenharmony_ci uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 19098c2ecf20Sopenharmony_ci uinfo->count = 2; 19108c2ecf20Sopenharmony_ci uinfo->value.integer.min = k1212MaxADCSens; 19118c2ecf20Sopenharmony_ci uinfo->value.integer.max = k1212MinADCSens; 19128c2ecf20Sopenharmony_ci return 0; 19138c2ecf20Sopenharmony_ci} 19148c2ecf20Sopenharmony_ci 19158c2ecf20Sopenharmony_cistatic int snd_korg1212_control_get(struct snd_kcontrol *kcontrol, 19168c2ecf20Sopenharmony_ci struct snd_ctl_elem_value *u) 19178c2ecf20Sopenharmony_ci{ 19188c2ecf20Sopenharmony_ci struct snd_korg1212 *korg1212 = snd_kcontrol_chip(kcontrol); 19198c2ecf20Sopenharmony_ci 19208c2ecf20Sopenharmony_ci spin_lock_irq(&korg1212->lock); 19218c2ecf20Sopenharmony_ci 19228c2ecf20Sopenharmony_ci u->value.integer.value[0] = korg1212->leftADCInSens; 19238c2ecf20Sopenharmony_ci u->value.integer.value[1] = korg1212->rightADCInSens; 19248c2ecf20Sopenharmony_ci 19258c2ecf20Sopenharmony_ci spin_unlock_irq(&korg1212->lock); 19268c2ecf20Sopenharmony_ci 19278c2ecf20Sopenharmony_ci return 0; 19288c2ecf20Sopenharmony_ci} 19298c2ecf20Sopenharmony_ci 19308c2ecf20Sopenharmony_cistatic int snd_korg1212_control_put(struct snd_kcontrol *kcontrol, 19318c2ecf20Sopenharmony_ci struct snd_ctl_elem_value *u) 19328c2ecf20Sopenharmony_ci{ 19338c2ecf20Sopenharmony_ci struct snd_korg1212 *korg1212 = snd_kcontrol_chip(kcontrol); 19348c2ecf20Sopenharmony_ci int change = 0; 19358c2ecf20Sopenharmony_ci 19368c2ecf20Sopenharmony_ci spin_lock_irq(&korg1212->lock); 19378c2ecf20Sopenharmony_ci 19388c2ecf20Sopenharmony_ci if (u->value.integer.value[0] >= k1212MinADCSens && 19398c2ecf20Sopenharmony_ci u->value.integer.value[0] <= k1212MaxADCSens && 19408c2ecf20Sopenharmony_ci u->value.integer.value[0] != korg1212->leftADCInSens) { 19418c2ecf20Sopenharmony_ci korg1212->leftADCInSens = u->value.integer.value[0]; 19428c2ecf20Sopenharmony_ci change = 1; 19438c2ecf20Sopenharmony_ci } 19448c2ecf20Sopenharmony_ci if (u->value.integer.value[1] >= k1212MinADCSens && 19458c2ecf20Sopenharmony_ci u->value.integer.value[1] <= k1212MaxADCSens && 19468c2ecf20Sopenharmony_ci u->value.integer.value[1] != korg1212->rightADCInSens) { 19478c2ecf20Sopenharmony_ci korg1212->rightADCInSens = u->value.integer.value[1]; 19488c2ecf20Sopenharmony_ci change = 1; 19498c2ecf20Sopenharmony_ci } 19508c2ecf20Sopenharmony_ci 19518c2ecf20Sopenharmony_ci spin_unlock_irq(&korg1212->lock); 19528c2ecf20Sopenharmony_ci 19538c2ecf20Sopenharmony_ci if (change) 19548c2ecf20Sopenharmony_ci snd_korg1212_WriteADCSensitivity(korg1212); 19558c2ecf20Sopenharmony_ci 19568c2ecf20Sopenharmony_ci return change; 19578c2ecf20Sopenharmony_ci} 19588c2ecf20Sopenharmony_ci 19598c2ecf20Sopenharmony_cistatic int snd_korg1212_control_sync_info(struct snd_kcontrol *kcontrol, 19608c2ecf20Sopenharmony_ci struct snd_ctl_elem_info *uinfo) 19618c2ecf20Sopenharmony_ci{ 19628c2ecf20Sopenharmony_ci return snd_ctl_enum_info(uinfo, 1, 3, clockSourceTypeName); 19638c2ecf20Sopenharmony_ci} 19648c2ecf20Sopenharmony_ci 19658c2ecf20Sopenharmony_cistatic int snd_korg1212_control_sync_get(struct snd_kcontrol *kcontrol, 19668c2ecf20Sopenharmony_ci struct snd_ctl_elem_value *ucontrol) 19678c2ecf20Sopenharmony_ci{ 19688c2ecf20Sopenharmony_ci struct snd_korg1212 *korg1212 = snd_kcontrol_chip(kcontrol); 19698c2ecf20Sopenharmony_ci 19708c2ecf20Sopenharmony_ci spin_lock_irq(&korg1212->lock); 19718c2ecf20Sopenharmony_ci 19728c2ecf20Sopenharmony_ci ucontrol->value.enumerated.item[0] = korg1212->clkSource; 19738c2ecf20Sopenharmony_ci 19748c2ecf20Sopenharmony_ci spin_unlock_irq(&korg1212->lock); 19758c2ecf20Sopenharmony_ci return 0; 19768c2ecf20Sopenharmony_ci} 19778c2ecf20Sopenharmony_ci 19788c2ecf20Sopenharmony_cistatic int snd_korg1212_control_sync_put(struct snd_kcontrol *kcontrol, 19798c2ecf20Sopenharmony_ci struct snd_ctl_elem_value *ucontrol) 19808c2ecf20Sopenharmony_ci{ 19818c2ecf20Sopenharmony_ci struct snd_korg1212 *korg1212 = snd_kcontrol_chip(kcontrol); 19828c2ecf20Sopenharmony_ci unsigned int val; 19838c2ecf20Sopenharmony_ci int change; 19848c2ecf20Sopenharmony_ci 19858c2ecf20Sopenharmony_ci val = ucontrol->value.enumerated.item[0] % 3; 19868c2ecf20Sopenharmony_ci spin_lock_irq(&korg1212->lock); 19878c2ecf20Sopenharmony_ci change = val != korg1212->clkSource; 19888c2ecf20Sopenharmony_ci snd_korg1212_SetClockSource(korg1212, val); 19898c2ecf20Sopenharmony_ci spin_unlock_irq(&korg1212->lock); 19908c2ecf20Sopenharmony_ci return change; 19918c2ecf20Sopenharmony_ci} 19928c2ecf20Sopenharmony_ci 19938c2ecf20Sopenharmony_ci#define MON_MIXER(ord,c_name) \ 19948c2ecf20Sopenharmony_ci { \ 19958c2ecf20Sopenharmony_ci .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE, \ 19968c2ecf20Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ 19978c2ecf20Sopenharmony_ci .name = c_name " Monitor Volume", \ 19988c2ecf20Sopenharmony_ci .info = snd_korg1212_control_volume_info, \ 19998c2ecf20Sopenharmony_ci .get = snd_korg1212_control_volume_get, \ 20008c2ecf20Sopenharmony_ci .put = snd_korg1212_control_volume_put, \ 20018c2ecf20Sopenharmony_ci .private_value = ord, \ 20028c2ecf20Sopenharmony_ci }, \ 20038c2ecf20Sopenharmony_ci { \ 20048c2ecf20Sopenharmony_ci .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE, \ 20058c2ecf20Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ 20068c2ecf20Sopenharmony_ci .name = c_name " Monitor Route", \ 20078c2ecf20Sopenharmony_ci .info = snd_korg1212_control_route_info, \ 20088c2ecf20Sopenharmony_ci .get = snd_korg1212_control_route_get, \ 20098c2ecf20Sopenharmony_ci .put = snd_korg1212_control_route_put, \ 20108c2ecf20Sopenharmony_ci .private_value = ord, \ 20118c2ecf20Sopenharmony_ci }, \ 20128c2ecf20Sopenharmony_ci { \ 20138c2ecf20Sopenharmony_ci .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE, \ 20148c2ecf20Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ 20158c2ecf20Sopenharmony_ci .name = c_name " Monitor Phase Invert", \ 20168c2ecf20Sopenharmony_ci .info = snd_korg1212_control_phase_info, \ 20178c2ecf20Sopenharmony_ci .get = snd_korg1212_control_phase_get, \ 20188c2ecf20Sopenharmony_ci .put = snd_korg1212_control_phase_put, \ 20198c2ecf20Sopenharmony_ci .private_value = ord, \ 20208c2ecf20Sopenharmony_ci } 20218c2ecf20Sopenharmony_ci 20228c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new snd_korg1212_controls[] = { 20238c2ecf20Sopenharmony_ci MON_MIXER(8, "Analog"), 20248c2ecf20Sopenharmony_ci MON_MIXER(10, "SPDIF"), 20258c2ecf20Sopenharmony_ci MON_MIXER(0, "ADAT-1"), MON_MIXER(1, "ADAT-2"), MON_MIXER(2, "ADAT-3"), MON_MIXER(3, "ADAT-4"), 20268c2ecf20Sopenharmony_ci MON_MIXER(4, "ADAT-5"), MON_MIXER(5, "ADAT-6"), MON_MIXER(6, "ADAT-7"), MON_MIXER(7, "ADAT-8"), 20278c2ecf20Sopenharmony_ci { 20288c2ecf20Sopenharmony_ci .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE, 20298c2ecf20Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 20308c2ecf20Sopenharmony_ci .name = "Sync Source", 20318c2ecf20Sopenharmony_ci .info = snd_korg1212_control_sync_info, 20328c2ecf20Sopenharmony_ci .get = snd_korg1212_control_sync_get, 20338c2ecf20Sopenharmony_ci .put = snd_korg1212_control_sync_put, 20348c2ecf20Sopenharmony_ci }, 20358c2ecf20Sopenharmony_ci { 20368c2ecf20Sopenharmony_ci .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE, 20378c2ecf20Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 20388c2ecf20Sopenharmony_ci .name = "ADC Attenuation", 20398c2ecf20Sopenharmony_ci .info = snd_korg1212_control_info, 20408c2ecf20Sopenharmony_ci .get = snd_korg1212_control_get, 20418c2ecf20Sopenharmony_ci .put = snd_korg1212_control_put, 20428c2ecf20Sopenharmony_ci } 20438c2ecf20Sopenharmony_ci}; 20448c2ecf20Sopenharmony_ci 20458c2ecf20Sopenharmony_ci/* 20468c2ecf20Sopenharmony_ci * proc interface 20478c2ecf20Sopenharmony_ci */ 20488c2ecf20Sopenharmony_ci 20498c2ecf20Sopenharmony_cistatic void snd_korg1212_proc_read(struct snd_info_entry *entry, 20508c2ecf20Sopenharmony_ci struct snd_info_buffer *buffer) 20518c2ecf20Sopenharmony_ci{ 20528c2ecf20Sopenharmony_ci int n; 20538c2ecf20Sopenharmony_ci struct snd_korg1212 *korg1212 = entry->private_data; 20548c2ecf20Sopenharmony_ci 20558c2ecf20Sopenharmony_ci snd_iprintf(buffer, korg1212->card->longname); 20568c2ecf20Sopenharmony_ci snd_iprintf(buffer, " (index #%d)\n", korg1212->card->number + 1); 20578c2ecf20Sopenharmony_ci snd_iprintf(buffer, "\nGeneral settings\n"); 20588c2ecf20Sopenharmony_ci snd_iprintf(buffer, " period size: %zd bytes\n", K1212_PERIOD_BYTES); 20598c2ecf20Sopenharmony_ci snd_iprintf(buffer, " clock mode: %s\n", clockSourceName[korg1212->clkSrcRate] ); 20608c2ecf20Sopenharmony_ci snd_iprintf(buffer, " left ADC Sens: %d\n", korg1212->leftADCInSens ); 20618c2ecf20Sopenharmony_ci snd_iprintf(buffer, " right ADC Sens: %d\n", korg1212->rightADCInSens ); 20628c2ecf20Sopenharmony_ci snd_iprintf(buffer, " Volume Info:\n"); 20638c2ecf20Sopenharmony_ci for (n=0; n<kAudioChannels; n++) 20648c2ecf20Sopenharmony_ci snd_iprintf(buffer, " Channel %d: %s -> %s [%d]\n", n, 20658c2ecf20Sopenharmony_ci channelName[n], 20668c2ecf20Sopenharmony_ci channelName[korg1212->sharedBufferPtr->routeData[n]], 20678c2ecf20Sopenharmony_ci korg1212->sharedBufferPtr->volumeData[n]); 20688c2ecf20Sopenharmony_ci snd_iprintf(buffer, "\nGeneral status\n"); 20698c2ecf20Sopenharmony_ci snd_iprintf(buffer, " ADAT Time Code: %d\n", korg1212->sharedBufferPtr->AdatTimeCode); 20708c2ecf20Sopenharmony_ci snd_iprintf(buffer, " Card State: %s\n", stateName[korg1212->cardState]); 20718c2ecf20Sopenharmony_ci snd_iprintf(buffer, "Idle mon. State: %d\n", korg1212->idleMonitorOn); 20728c2ecf20Sopenharmony_ci snd_iprintf(buffer, "Cmd retry count: %d\n", korg1212->cmdRetryCount); 20738c2ecf20Sopenharmony_ci snd_iprintf(buffer, " Irq count: %ld\n", korg1212->irqcount); 20748c2ecf20Sopenharmony_ci snd_iprintf(buffer, " Error count: %ld\n", korg1212->totalerrorcnt); 20758c2ecf20Sopenharmony_ci} 20768c2ecf20Sopenharmony_ci 20778c2ecf20Sopenharmony_cistatic void snd_korg1212_proc_init(struct snd_korg1212 *korg1212) 20788c2ecf20Sopenharmony_ci{ 20798c2ecf20Sopenharmony_ci snd_card_ro_proc_new(korg1212->card, "korg1212", korg1212, 20808c2ecf20Sopenharmony_ci snd_korg1212_proc_read); 20818c2ecf20Sopenharmony_ci} 20828c2ecf20Sopenharmony_ci 20838c2ecf20Sopenharmony_cistatic int 20848c2ecf20Sopenharmony_cisnd_korg1212_free(struct snd_korg1212 *korg1212) 20858c2ecf20Sopenharmony_ci{ 20868c2ecf20Sopenharmony_ci snd_korg1212_TurnOffIdleMonitor(korg1212); 20878c2ecf20Sopenharmony_ci 20888c2ecf20Sopenharmony_ci if (korg1212->irq >= 0) { 20898c2ecf20Sopenharmony_ci snd_korg1212_DisableCardInterrupts(korg1212); 20908c2ecf20Sopenharmony_ci free_irq(korg1212->irq, korg1212); 20918c2ecf20Sopenharmony_ci korg1212->irq = -1; 20928c2ecf20Sopenharmony_ci } 20938c2ecf20Sopenharmony_ci 20948c2ecf20Sopenharmony_ci if (korg1212->iobase != NULL) { 20958c2ecf20Sopenharmony_ci iounmap(korg1212->iobase); 20968c2ecf20Sopenharmony_ci korg1212->iobase = NULL; 20978c2ecf20Sopenharmony_ci } 20988c2ecf20Sopenharmony_ci 20998c2ecf20Sopenharmony_ci pci_release_regions(korg1212->pci); 21008c2ecf20Sopenharmony_ci 21018c2ecf20Sopenharmony_ci // ---------------------------------------------------- 21028c2ecf20Sopenharmony_ci // free up memory resources used for the DSP download. 21038c2ecf20Sopenharmony_ci // ---------------------------------------------------- 21048c2ecf20Sopenharmony_ci if (korg1212->dma_dsp.area) { 21058c2ecf20Sopenharmony_ci snd_dma_free_pages(&korg1212->dma_dsp); 21068c2ecf20Sopenharmony_ci korg1212->dma_dsp.area = NULL; 21078c2ecf20Sopenharmony_ci } 21088c2ecf20Sopenharmony_ci 21098c2ecf20Sopenharmony_ci#ifndef K1212_LARGEALLOC 21108c2ecf20Sopenharmony_ci 21118c2ecf20Sopenharmony_ci // ------------------------------------------------------ 21128c2ecf20Sopenharmony_ci // free up memory resources used for the Play/Rec Buffers 21138c2ecf20Sopenharmony_ci // ------------------------------------------------------ 21148c2ecf20Sopenharmony_ci if (korg1212->dma_play.area) { 21158c2ecf20Sopenharmony_ci snd_dma_free_pages(&korg1212->dma_play); 21168c2ecf20Sopenharmony_ci korg1212->dma_play.area = NULL; 21178c2ecf20Sopenharmony_ci } 21188c2ecf20Sopenharmony_ci 21198c2ecf20Sopenharmony_ci if (korg1212->dma_rec.area) { 21208c2ecf20Sopenharmony_ci snd_dma_free_pages(&korg1212->dma_rec); 21218c2ecf20Sopenharmony_ci korg1212->dma_rec.area = NULL; 21228c2ecf20Sopenharmony_ci } 21238c2ecf20Sopenharmony_ci 21248c2ecf20Sopenharmony_ci#endif 21258c2ecf20Sopenharmony_ci 21268c2ecf20Sopenharmony_ci // ---------------------------------------------------- 21278c2ecf20Sopenharmony_ci // free up memory resources used for the Shared Buffers 21288c2ecf20Sopenharmony_ci // ---------------------------------------------------- 21298c2ecf20Sopenharmony_ci if (korg1212->dma_shared.area) { 21308c2ecf20Sopenharmony_ci snd_dma_free_pages(&korg1212->dma_shared); 21318c2ecf20Sopenharmony_ci korg1212->dma_shared.area = NULL; 21328c2ecf20Sopenharmony_ci } 21338c2ecf20Sopenharmony_ci 21348c2ecf20Sopenharmony_ci pci_disable_device(korg1212->pci); 21358c2ecf20Sopenharmony_ci kfree(korg1212); 21368c2ecf20Sopenharmony_ci return 0; 21378c2ecf20Sopenharmony_ci} 21388c2ecf20Sopenharmony_ci 21398c2ecf20Sopenharmony_cistatic int snd_korg1212_dev_free(struct snd_device *device) 21408c2ecf20Sopenharmony_ci{ 21418c2ecf20Sopenharmony_ci struct snd_korg1212 *korg1212 = device->device_data; 21428c2ecf20Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: Freeing device\n"); 21438c2ecf20Sopenharmony_ci return snd_korg1212_free(korg1212); 21448c2ecf20Sopenharmony_ci} 21458c2ecf20Sopenharmony_ci 21468c2ecf20Sopenharmony_cistatic int snd_korg1212_create(struct snd_card *card, struct pci_dev *pci, 21478c2ecf20Sopenharmony_ci struct snd_korg1212 **rchip) 21488c2ecf20Sopenharmony_ci 21498c2ecf20Sopenharmony_ci{ 21508c2ecf20Sopenharmony_ci int err, rc; 21518c2ecf20Sopenharmony_ci unsigned int i; 21528c2ecf20Sopenharmony_ci unsigned iomem_size; 21538c2ecf20Sopenharmony_ci __maybe_unused unsigned ioport_size; 21548c2ecf20Sopenharmony_ci __maybe_unused unsigned iomem2_size; 21558c2ecf20Sopenharmony_ci struct snd_korg1212 * korg1212; 21568c2ecf20Sopenharmony_ci const struct firmware *dsp_code; 21578c2ecf20Sopenharmony_ci 21588c2ecf20Sopenharmony_ci static const struct snd_device_ops ops = { 21598c2ecf20Sopenharmony_ci .dev_free = snd_korg1212_dev_free, 21608c2ecf20Sopenharmony_ci }; 21618c2ecf20Sopenharmony_ci 21628c2ecf20Sopenharmony_ci * rchip = NULL; 21638c2ecf20Sopenharmony_ci if ((err = pci_enable_device(pci)) < 0) 21648c2ecf20Sopenharmony_ci return err; 21658c2ecf20Sopenharmony_ci 21668c2ecf20Sopenharmony_ci korg1212 = kzalloc(sizeof(*korg1212), GFP_KERNEL); 21678c2ecf20Sopenharmony_ci if (korg1212 == NULL) { 21688c2ecf20Sopenharmony_ci pci_disable_device(pci); 21698c2ecf20Sopenharmony_ci return -ENOMEM; 21708c2ecf20Sopenharmony_ci } 21718c2ecf20Sopenharmony_ci 21728c2ecf20Sopenharmony_ci korg1212->card = card; 21738c2ecf20Sopenharmony_ci korg1212->pci = pci; 21748c2ecf20Sopenharmony_ci 21758c2ecf20Sopenharmony_ci init_waitqueue_head(&korg1212->wait); 21768c2ecf20Sopenharmony_ci spin_lock_init(&korg1212->lock); 21778c2ecf20Sopenharmony_ci mutex_init(&korg1212->open_mutex); 21788c2ecf20Sopenharmony_ci timer_setup(&korg1212->timer, snd_korg1212_timer_func, 0); 21798c2ecf20Sopenharmony_ci 21808c2ecf20Sopenharmony_ci korg1212->irq = -1; 21818c2ecf20Sopenharmony_ci korg1212->clkSource = K1212_CLKIDX_Local; 21828c2ecf20Sopenharmony_ci korg1212->clkRate = 44100; 21838c2ecf20Sopenharmony_ci korg1212->inIRQ = 0; 21848c2ecf20Sopenharmony_ci korg1212->running = 0; 21858c2ecf20Sopenharmony_ci korg1212->opencnt = 0; 21868c2ecf20Sopenharmony_ci korg1212->playcnt = 0; 21878c2ecf20Sopenharmony_ci korg1212->setcnt = 0; 21888c2ecf20Sopenharmony_ci korg1212->totalerrorcnt = 0; 21898c2ecf20Sopenharmony_ci korg1212->playback_pid = -1; 21908c2ecf20Sopenharmony_ci korg1212->capture_pid = -1; 21918c2ecf20Sopenharmony_ci snd_korg1212_setCardState(korg1212, K1212_STATE_UNINITIALIZED); 21928c2ecf20Sopenharmony_ci korg1212->idleMonitorOn = 0; 21938c2ecf20Sopenharmony_ci korg1212->clkSrcRate = K1212_CLKIDX_LocalAt44_1K; 21948c2ecf20Sopenharmony_ci korg1212->leftADCInSens = k1212MaxADCSens; 21958c2ecf20Sopenharmony_ci korg1212->rightADCInSens = k1212MaxADCSens; 21968c2ecf20Sopenharmony_ci 21978c2ecf20Sopenharmony_ci for (i=0; i<kAudioChannels; i++) 21988c2ecf20Sopenharmony_ci korg1212->volumePhase[i] = 0; 21998c2ecf20Sopenharmony_ci 22008c2ecf20Sopenharmony_ci if ((err = pci_request_regions(pci, "korg1212")) < 0) { 22018c2ecf20Sopenharmony_ci kfree(korg1212); 22028c2ecf20Sopenharmony_ci pci_disable_device(pci); 22038c2ecf20Sopenharmony_ci return err; 22048c2ecf20Sopenharmony_ci } 22058c2ecf20Sopenharmony_ci 22068c2ecf20Sopenharmony_ci korg1212->iomem = pci_resource_start(korg1212->pci, 0); 22078c2ecf20Sopenharmony_ci korg1212->ioport = pci_resource_start(korg1212->pci, 1); 22088c2ecf20Sopenharmony_ci korg1212->iomem2 = pci_resource_start(korg1212->pci, 2); 22098c2ecf20Sopenharmony_ci 22108c2ecf20Sopenharmony_ci iomem_size = pci_resource_len(korg1212->pci, 0); 22118c2ecf20Sopenharmony_ci ioport_size = pci_resource_len(korg1212->pci, 1); 22128c2ecf20Sopenharmony_ci iomem2_size = pci_resource_len(korg1212->pci, 2); 22138c2ecf20Sopenharmony_ci 22148c2ecf20Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: resources:\n" 22158c2ecf20Sopenharmony_ci " iomem = 0x%lx (%d)\n" 22168c2ecf20Sopenharmony_ci " ioport = 0x%lx (%d)\n" 22178c2ecf20Sopenharmony_ci " iomem = 0x%lx (%d)\n" 22188c2ecf20Sopenharmony_ci " [%s]\n", 22198c2ecf20Sopenharmony_ci korg1212->iomem, iomem_size, 22208c2ecf20Sopenharmony_ci korg1212->ioport, ioport_size, 22218c2ecf20Sopenharmony_ci korg1212->iomem2, iomem2_size, 22228c2ecf20Sopenharmony_ci stateName[korg1212->cardState]); 22238c2ecf20Sopenharmony_ci 22248c2ecf20Sopenharmony_ci if ((korg1212->iobase = ioremap(korg1212->iomem, iomem_size)) == NULL) { 22258c2ecf20Sopenharmony_ci snd_printk(KERN_ERR "korg1212: unable to remap memory region 0x%lx-0x%lx\n", korg1212->iomem, 22268c2ecf20Sopenharmony_ci korg1212->iomem + iomem_size - 1); 22278c2ecf20Sopenharmony_ci snd_korg1212_free(korg1212); 22288c2ecf20Sopenharmony_ci return -EBUSY; 22298c2ecf20Sopenharmony_ci } 22308c2ecf20Sopenharmony_ci 22318c2ecf20Sopenharmony_ci err = request_irq(pci->irq, snd_korg1212_interrupt, 22328c2ecf20Sopenharmony_ci IRQF_SHARED, 22338c2ecf20Sopenharmony_ci KBUILD_MODNAME, korg1212); 22348c2ecf20Sopenharmony_ci 22358c2ecf20Sopenharmony_ci if (err) { 22368c2ecf20Sopenharmony_ci snd_printk(KERN_ERR "korg1212: unable to grab IRQ %d\n", pci->irq); 22378c2ecf20Sopenharmony_ci snd_korg1212_free(korg1212); 22388c2ecf20Sopenharmony_ci return -EBUSY; 22398c2ecf20Sopenharmony_ci } 22408c2ecf20Sopenharmony_ci 22418c2ecf20Sopenharmony_ci korg1212->irq = pci->irq; 22428c2ecf20Sopenharmony_ci card->sync_irq = korg1212->irq; 22438c2ecf20Sopenharmony_ci 22448c2ecf20Sopenharmony_ci pci_set_master(korg1212->pci); 22458c2ecf20Sopenharmony_ci 22468c2ecf20Sopenharmony_ci korg1212->statusRegPtr = (u32 __iomem *) (korg1212->iobase + STATUS_REG_OFFSET); 22478c2ecf20Sopenharmony_ci korg1212->outDoorbellPtr = (u32 __iomem *) (korg1212->iobase + OUT_DOORBELL_OFFSET); 22488c2ecf20Sopenharmony_ci korg1212->inDoorbellPtr = (u32 __iomem *) (korg1212->iobase + IN_DOORBELL_OFFSET); 22498c2ecf20Sopenharmony_ci korg1212->mailbox0Ptr = (u32 __iomem *) (korg1212->iobase + MAILBOX0_OFFSET); 22508c2ecf20Sopenharmony_ci korg1212->mailbox1Ptr = (u32 __iomem *) (korg1212->iobase + MAILBOX1_OFFSET); 22518c2ecf20Sopenharmony_ci korg1212->mailbox2Ptr = (u32 __iomem *) (korg1212->iobase + MAILBOX2_OFFSET); 22528c2ecf20Sopenharmony_ci korg1212->mailbox3Ptr = (u32 __iomem *) (korg1212->iobase + MAILBOX3_OFFSET); 22538c2ecf20Sopenharmony_ci korg1212->controlRegPtr = (u32 __iomem *) (korg1212->iobase + PCI_CONTROL_OFFSET); 22548c2ecf20Sopenharmony_ci korg1212->sensRegPtr = (u16 __iomem *) (korg1212->iobase + SENS_CONTROL_OFFSET); 22558c2ecf20Sopenharmony_ci korg1212->idRegPtr = (u32 __iomem *) (korg1212->iobase + DEV_VEND_ID_OFFSET); 22568c2ecf20Sopenharmony_ci 22578c2ecf20Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: card registers:\n" 22588c2ecf20Sopenharmony_ci " Status register = 0x%p\n" 22598c2ecf20Sopenharmony_ci " OutDoorbell = 0x%p\n" 22608c2ecf20Sopenharmony_ci " InDoorbell = 0x%p\n" 22618c2ecf20Sopenharmony_ci " Mailbox0 = 0x%p\n" 22628c2ecf20Sopenharmony_ci " Mailbox1 = 0x%p\n" 22638c2ecf20Sopenharmony_ci " Mailbox2 = 0x%p\n" 22648c2ecf20Sopenharmony_ci " Mailbox3 = 0x%p\n" 22658c2ecf20Sopenharmony_ci " ControlReg = 0x%p\n" 22668c2ecf20Sopenharmony_ci " SensReg = 0x%p\n" 22678c2ecf20Sopenharmony_ci " IDReg = 0x%p\n" 22688c2ecf20Sopenharmony_ci " [%s]\n", 22698c2ecf20Sopenharmony_ci korg1212->statusRegPtr, 22708c2ecf20Sopenharmony_ci korg1212->outDoorbellPtr, 22718c2ecf20Sopenharmony_ci korg1212->inDoorbellPtr, 22728c2ecf20Sopenharmony_ci korg1212->mailbox0Ptr, 22738c2ecf20Sopenharmony_ci korg1212->mailbox1Ptr, 22748c2ecf20Sopenharmony_ci korg1212->mailbox2Ptr, 22758c2ecf20Sopenharmony_ci korg1212->mailbox3Ptr, 22768c2ecf20Sopenharmony_ci korg1212->controlRegPtr, 22778c2ecf20Sopenharmony_ci korg1212->sensRegPtr, 22788c2ecf20Sopenharmony_ci korg1212->idRegPtr, 22798c2ecf20Sopenharmony_ci stateName[korg1212->cardState]); 22808c2ecf20Sopenharmony_ci 22818c2ecf20Sopenharmony_ci if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &pci->dev, 22828c2ecf20Sopenharmony_ci sizeof(struct KorgSharedBuffer), &korg1212->dma_shared) < 0) { 22838c2ecf20Sopenharmony_ci snd_printk(KERN_ERR "korg1212: can not allocate shared buffer memory (%zd bytes)\n", sizeof(struct KorgSharedBuffer)); 22848c2ecf20Sopenharmony_ci snd_korg1212_free(korg1212); 22858c2ecf20Sopenharmony_ci return -ENOMEM; 22868c2ecf20Sopenharmony_ci } 22878c2ecf20Sopenharmony_ci korg1212->sharedBufferPtr = (struct KorgSharedBuffer *)korg1212->dma_shared.area; 22888c2ecf20Sopenharmony_ci korg1212->sharedBufferPhy = korg1212->dma_shared.addr; 22898c2ecf20Sopenharmony_ci 22908c2ecf20Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: Shared Buffer Area = 0x%p (0x%08lx), %d bytes\n", korg1212->sharedBufferPtr, korg1212->sharedBufferPhy, sizeof(struct KorgSharedBuffer)); 22918c2ecf20Sopenharmony_ci 22928c2ecf20Sopenharmony_ci#ifndef K1212_LARGEALLOC 22938c2ecf20Sopenharmony_ci 22948c2ecf20Sopenharmony_ci korg1212->DataBufsSize = sizeof(struct KorgAudioBuffer) * kNumBuffers; 22958c2ecf20Sopenharmony_ci 22968c2ecf20Sopenharmony_ci if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &pci->dev, 22978c2ecf20Sopenharmony_ci korg1212->DataBufsSize, &korg1212->dma_play) < 0) { 22988c2ecf20Sopenharmony_ci snd_printk(KERN_ERR "korg1212: can not allocate play data buffer memory (%d bytes)\n", korg1212->DataBufsSize); 22998c2ecf20Sopenharmony_ci snd_korg1212_free(korg1212); 23008c2ecf20Sopenharmony_ci return -ENOMEM; 23018c2ecf20Sopenharmony_ci } 23028c2ecf20Sopenharmony_ci korg1212->playDataBufsPtr = (struct KorgAudioBuffer *)korg1212->dma_play.area; 23038c2ecf20Sopenharmony_ci korg1212->PlayDataPhy = korg1212->dma_play.addr; 23048c2ecf20Sopenharmony_ci 23058c2ecf20Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: Play Data Area = 0x%p (0x%08x), %d bytes\n", 23068c2ecf20Sopenharmony_ci korg1212->playDataBufsPtr, korg1212->PlayDataPhy, korg1212->DataBufsSize); 23078c2ecf20Sopenharmony_ci 23088c2ecf20Sopenharmony_ci if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &pci->dev, 23098c2ecf20Sopenharmony_ci korg1212->DataBufsSize, &korg1212->dma_rec) < 0) { 23108c2ecf20Sopenharmony_ci snd_printk(KERN_ERR "korg1212: can not allocate record data buffer memory (%d bytes)\n", korg1212->DataBufsSize); 23118c2ecf20Sopenharmony_ci snd_korg1212_free(korg1212); 23128c2ecf20Sopenharmony_ci return -ENOMEM; 23138c2ecf20Sopenharmony_ci } 23148c2ecf20Sopenharmony_ci korg1212->recordDataBufsPtr = (struct KorgAudioBuffer *)korg1212->dma_rec.area; 23158c2ecf20Sopenharmony_ci korg1212->RecDataPhy = korg1212->dma_rec.addr; 23168c2ecf20Sopenharmony_ci 23178c2ecf20Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: Record Data Area = 0x%p (0x%08x), %d bytes\n", 23188c2ecf20Sopenharmony_ci korg1212->recordDataBufsPtr, korg1212->RecDataPhy, korg1212->DataBufsSize); 23198c2ecf20Sopenharmony_ci 23208c2ecf20Sopenharmony_ci#else // K1212_LARGEALLOC 23218c2ecf20Sopenharmony_ci 23228c2ecf20Sopenharmony_ci korg1212->recordDataBufsPtr = korg1212->sharedBufferPtr->recordDataBufs; 23238c2ecf20Sopenharmony_ci korg1212->playDataBufsPtr = korg1212->sharedBufferPtr->playDataBufs; 23248c2ecf20Sopenharmony_ci korg1212->PlayDataPhy = (u32) &((struct KorgSharedBuffer *) korg1212->sharedBufferPhy)->playDataBufs; 23258c2ecf20Sopenharmony_ci korg1212->RecDataPhy = (u32) &((struct KorgSharedBuffer *) korg1212->sharedBufferPhy)->recordDataBufs; 23268c2ecf20Sopenharmony_ci 23278c2ecf20Sopenharmony_ci#endif // K1212_LARGEALLOC 23288c2ecf20Sopenharmony_ci 23298c2ecf20Sopenharmony_ci korg1212->VolumeTablePhy = korg1212->sharedBufferPhy + 23308c2ecf20Sopenharmony_ci offsetof(struct KorgSharedBuffer, volumeData); 23318c2ecf20Sopenharmony_ci korg1212->RoutingTablePhy = korg1212->sharedBufferPhy + 23328c2ecf20Sopenharmony_ci offsetof(struct KorgSharedBuffer, routeData); 23338c2ecf20Sopenharmony_ci korg1212->AdatTimeCodePhy = korg1212->sharedBufferPhy + 23348c2ecf20Sopenharmony_ci offsetof(struct KorgSharedBuffer, AdatTimeCode); 23358c2ecf20Sopenharmony_ci 23368c2ecf20Sopenharmony_ci err = request_firmware(&dsp_code, "korg/k1212.dsp", &pci->dev); 23378c2ecf20Sopenharmony_ci if (err < 0) { 23388c2ecf20Sopenharmony_ci snd_printk(KERN_ERR "firmware not available\n"); 23398c2ecf20Sopenharmony_ci snd_korg1212_free(korg1212); 23408c2ecf20Sopenharmony_ci return err; 23418c2ecf20Sopenharmony_ci } 23428c2ecf20Sopenharmony_ci 23438c2ecf20Sopenharmony_ci if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &pci->dev, 23448c2ecf20Sopenharmony_ci dsp_code->size, &korg1212->dma_dsp) < 0) { 23458c2ecf20Sopenharmony_ci snd_printk(KERN_ERR "korg1212: cannot allocate dsp code memory (%zd bytes)\n", dsp_code->size); 23468c2ecf20Sopenharmony_ci snd_korg1212_free(korg1212); 23478c2ecf20Sopenharmony_ci release_firmware(dsp_code); 23488c2ecf20Sopenharmony_ci return -ENOMEM; 23498c2ecf20Sopenharmony_ci } 23508c2ecf20Sopenharmony_ci 23518c2ecf20Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: DSP Code area = 0x%p (0x%08x) %d bytes [%s]\n", 23528c2ecf20Sopenharmony_ci korg1212->dma_dsp.area, korg1212->dma_dsp.addr, dsp_code->size, 23538c2ecf20Sopenharmony_ci stateName[korg1212->cardState]); 23548c2ecf20Sopenharmony_ci 23558c2ecf20Sopenharmony_ci memcpy(korg1212->dma_dsp.area, dsp_code->data, dsp_code->size); 23568c2ecf20Sopenharmony_ci 23578c2ecf20Sopenharmony_ci release_firmware(dsp_code); 23588c2ecf20Sopenharmony_ci 23598c2ecf20Sopenharmony_ci rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_RebootCard, 0, 0, 0, 0); 23608c2ecf20Sopenharmony_ci 23618c2ecf20Sopenharmony_ci if (rc) 23628c2ecf20Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: Reboot Card - RC = %d [%s]\n", rc, stateName[korg1212->cardState]); 23638c2ecf20Sopenharmony_ci 23648c2ecf20Sopenharmony_ci if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, korg1212, &ops)) < 0) { 23658c2ecf20Sopenharmony_ci snd_korg1212_free(korg1212); 23668c2ecf20Sopenharmony_ci return err; 23678c2ecf20Sopenharmony_ci } 23688c2ecf20Sopenharmony_ci 23698c2ecf20Sopenharmony_ci snd_korg1212_EnableCardInterrupts(korg1212); 23708c2ecf20Sopenharmony_ci 23718c2ecf20Sopenharmony_ci mdelay(CARD_BOOT_DELAY_IN_MS); 23728c2ecf20Sopenharmony_ci 23738c2ecf20Sopenharmony_ci if (snd_korg1212_downloadDSPCode(korg1212)) 23748c2ecf20Sopenharmony_ci return -EBUSY; 23758c2ecf20Sopenharmony_ci 23768c2ecf20Sopenharmony_ci K1212_DEBUG_PRINTK("korg1212: dspMemPhy = %08x U[%08x], " 23778c2ecf20Sopenharmony_ci "PlayDataPhy = %08x L[%08x]\n" 23788c2ecf20Sopenharmony_ci "korg1212: RecDataPhy = %08x L[%08x], " 23798c2ecf20Sopenharmony_ci "VolumeTablePhy = %08x L[%08x]\n" 23808c2ecf20Sopenharmony_ci "korg1212: RoutingTablePhy = %08x L[%08x], " 23818c2ecf20Sopenharmony_ci "AdatTimeCodePhy = %08x L[%08x]\n", 23828c2ecf20Sopenharmony_ci (int)korg1212->dma_dsp.addr, UpperWordSwap(korg1212->dma_dsp.addr), 23838c2ecf20Sopenharmony_ci korg1212->PlayDataPhy, LowerWordSwap(korg1212->PlayDataPhy), 23848c2ecf20Sopenharmony_ci korg1212->RecDataPhy, LowerWordSwap(korg1212->RecDataPhy), 23858c2ecf20Sopenharmony_ci korg1212->VolumeTablePhy, LowerWordSwap(korg1212->VolumeTablePhy), 23868c2ecf20Sopenharmony_ci korg1212->RoutingTablePhy, LowerWordSwap(korg1212->RoutingTablePhy), 23878c2ecf20Sopenharmony_ci korg1212->AdatTimeCodePhy, LowerWordSwap(korg1212->AdatTimeCodePhy)); 23888c2ecf20Sopenharmony_ci 23898c2ecf20Sopenharmony_ci if ((err = snd_pcm_new(korg1212->card, "korg1212", 0, 1, 1, &korg1212->pcm)) < 0) 23908c2ecf20Sopenharmony_ci return err; 23918c2ecf20Sopenharmony_ci 23928c2ecf20Sopenharmony_ci korg1212->pcm->private_data = korg1212; 23938c2ecf20Sopenharmony_ci korg1212->pcm->private_free = snd_korg1212_free_pcm; 23948c2ecf20Sopenharmony_ci strcpy(korg1212->pcm->name, "korg1212"); 23958c2ecf20Sopenharmony_ci 23968c2ecf20Sopenharmony_ci snd_pcm_set_ops(korg1212->pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_korg1212_playback_ops); 23978c2ecf20Sopenharmony_ci 23988c2ecf20Sopenharmony_ci snd_pcm_set_ops(korg1212->pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_korg1212_capture_ops); 23998c2ecf20Sopenharmony_ci 24008c2ecf20Sopenharmony_ci korg1212->pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX; 24018c2ecf20Sopenharmony_ci 24028c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(snd_korg1212_controls); i++) { 24038c2ecf20Sopenharmony_ci err = snd_ctl_add(korg1212->card, snd_ctl_new1(&snd_korg1212_controls[i], korg1212)); 24048c2ecf20Sopenharmony_ci if (err < 0) 24058c2ecf20Sopenharmony_ci return err; 24068c2ecf20Sopenharmony_ci } 24078c2ecf20Sopenharmony_ci 24088c2ecf20Sopenharmony_ci snd_korg1212_proc_init(korg1212); 24098c2ecf20Sopenharmony_ci 24108c2ecf20Sopenharmony_ci * rchip = korg1212; 24118c2ecf20Sopenharmony_ci return 0; 24128c2ecf20Sopenharmony_ci 24138c2ecf20Sopenharmony_ci} 24148c2ecf20Sopenharmony_ci 24158c2ecf20Sopenharmony_ci/* 24168c2ecf20Sopenharmony_ci * Card initialisation 24178c2ecf20Sopenharmony_ci */ 24188c2ecf20Sopenharmony_ci 24198c2ecf20Sopenharmony_cistatic int 24208c2ecf20Sopenharmony_cisnd_korg1212_probe(struct pci_dev *pci, 24218c2ecf20Sopenharmony_ci const struct pci_device_id *pci_id) 24228c2ecf20Sopenharmony_ci{ 24238c2ecf20Sopenharmony_ci static int dev; 24248c2ecf20Sopenharmony_ci struct snd_korg1212 *korg1212; 24258c2ecf20Sopenharmony_ci struct snd_card *card; 24268c2ecf20Sopenharmony_ci int err; 24278c2ecf20Sopenharmony_ci 24288c2ecf20Sopenharmony_ci if (dev >= SNDRV_CARDS) { 24298c2ecf20Sopenharmony_ci return -ENODEV; 24308c2ecf20Sopenharmony_ci } 24318c2ecf20Sopenharmony_ci if (!enable[dev]) { 24328c2ecf20Sopenharmony_ci dev++; 24338c2ecf20Sopenharmony_ci return -ENOENT; 24348c2ecf20Sopenharmony_ci } 24358c2ecf20Sopenharmony_ci err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, 24368c2ecf20Sopenharmony_ci 0, &card); 24378c2ecf20Sopenharmony_ci if (err < 0) 24388c2ecf20Sopenharmony_ci return err; 24398c2ecf20Sopenharmony_ci 24408c2ecf20Sopenharmony_ci if ((err = snd_korg1212_create(card, pci, &korg1212)) < 0) { 24418c2ecf20Sopenharmony_ci snd_card_free(card); 24428c2ecf20Sopenharmony_ci return err; 24438c2ecf20Sopenharmony_ci } 24448c2ecf20Sopenharmony_ci 24458c2ecf20Sopenharmony_ci strcpy(card->driver, "korg1212"); 24468c2ecf20Sopenharmony_ci strcpy(card->shortname, "korg1212"); 24478c2ecf20Sopenharmony_ci sprintf(card->longname, "%s at 0x%lx, irq %d", card->shortname, 24488c2ecf20Sopenharmony_ci korg1212->iomem, korg1212->irq); 24498c2ecf20Sopenharmony_ci 24508c2ecf20Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: %s\n", card->longname); 24518c2ecf20Sopenharmony_ci 24528c2ecf20Sopenharmony_ci if ((err = snd_card_register(card)) < 0) { 24538c2ecf20Sopenharmony_ci snd_card_free(card); 24548c2ecf20Sopenharmony_ci return err; 24558c2ecf20Sopenharmony_ci } 24568c2ecf20Sopenharmony_ci pci_set_drvdata(pci, card); 24578c2ecf20Sopenharmony_ci dev++; 24588c2ecf20Sopenharmony_ci return 0; 24598c2ecf20Sopenharmony_ci} 24608c2ecf20Sopenharmony_ci 24618c2ecf20Sopenharmony_cistatic void snd_korg1212_remove(struct pci_dev *pci) 24628c2ecf20Sopenharmony_ci{ 24638c2ecf20Sopenharmony_ci snd_card_free(pci_get_drvdata(pci)); 24648c2ecf20Sopenharmony_ci} 24658c2ecf20Sopenharmony_ci 24668c2ecf20Sopenharmony_cistatic struct pci_driver korg1212_driver = { 24678c2ecf20Sopenharmony_ci .name = KBUILD_MODNAME, 24688c2ecf20Sopenharmony_ci .id_table = snd_korg1212_ids, 24698c2ecf20Sopenharmony_ci .probe = snd_korg1212_probe, 24708c2ecf20Sopenharmony_ci .remove = snd_korg1212_remove, 24718c2ecf20Sopenharmony_ci}; 24728c2ecf20Sopenharmony_ci 24738c2ecf20Sopenharmony_cimodule_pci_driver(korg1212_driver); 2474