162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Driver for the Korg 1212 IO PCI card 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (c) 2001 Haroldo Gamal <gamal@alternex.com.br> 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/delay.h> 962306a36Sopenharmony_ci#include <linux/init.h> 1062306a36Sopenharmony_ci#include <linux/interrupt.h> 1162306a36Sopenharmony_ci#include <linux/pci.h> 1262306a36Sopenharmony_ci#include <linux/slab.h> 1362306a36Sopenharmony_ci#include <linux/wait.h> 1462306a36Sopenharmony_ci#include <linux/module.h> 1562306a36Sopenharmony_ci#include <linux/mutex.h> 1662306a36Sopenharmony_ci#include <linux/firmware.h> 1762306a36Sopenharmony_ci#include <linux/io.h> 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#include <sound/core.h> 2062306a36Sopenharmony_ci#include <sound/info.h> 2162306a36Sopenharmony_ci#include <sound/control.h> 2262306a36Sopenharmony_ci#include <sound/pcm.h> 2362306a36Sopenharmony_ci#include <sound/pcm_params.h> 2462306a36Sopenharmony_ci#include <sound/initval.h> 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci// ---------------------------------------------------------------------------- 2762306a36Sopenharmony_ci// Debug Stuff 2862306a36Sopenharmony_ci// ---------------------------------------------------------------------------- 2962306a36Sopenharmony_ci#define K1212_DEBUG_LEVEL 0 3062306a36Sopenharmony_ci#if K1212_DEBUG_LEVEL > 0 3162306a36Sopenharmony_ci#define K1212_DEBUG_PRINTK(fmt,args...) printk(KERN_DEBUG fmt,##args) 3262306a36Sopenharmony_ci#else 3362306a36Sopenharmony_ci#define K1212_DEBUG_PRINTK(fmt,...) do { } while (0) 3462306a36Sopenharmony_ci#endif 3562306a36Sopenharmony_ci#if K1212_DEBUG_LEVEL > 1 3662306a36Sopenharmony_ci#define K1212_DEBUG_PRINTK_VERBOSE(fmt,args...) printk(KERN_DEBUG fmt,##args) 3762306a36Sopenharmony_ci#else 3862306a36Sopenharmony_ci#define K1212_DEBUG_PRINTK_VERBOSE(fmt,...) 3962306a36Sopenharmony_ci#endif 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci// ---------------------------------------------------------------------------- 4262306a36Sopenharmony_ci// Record/Play Buffer Allocation Method. If K1212_LARGEALLOC is defined all 4362306a36Sopenharmony_ci// buffers are alocated as a large piece inside KorgSharedBuffer. 4462306a36Sopenharmony_ci// ---------------------------------------------------------------------------- 4562306a36Sopenharmony_ci//#define K1212_LARGEALLOC 1 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci// ---------------------------------------------------------------------------- 4862306a36Sopenharmony_ci// Valid states of the Korg 1212 I/O card. 4962306a36Sopenharmony_ci// ---------------------------------------------------------------------------- 5062306a36Sopenharmony_cienum CardState { 5162306a36Sopenharmony_ci K1212_STATE_NONEXISTENT, // there is no card here 5262306a36Sopenharmony_ci K1212_STATE_UNINITIALIZED, // the card is awaiting DSP download 5362306a36Sopenharmony_ci K1212_STATE_DSP_IN_PROCESS, // the card is currently downloading its DSP code 5462306a36Sopenharmony_ci K1212_STATE_DSP_COMPLETE, // the card has finished the DSP download 5562306a36Sopenharmony_ci K1212_STATE_READY, // the card can be opened by an application. Any application 5662306a36Sopenharmony_ci // requests prior to this state should fail. Only an open 5762306a36Sopenharmony_ci // request can be made at this state. 5862306a36Sopenharmony_ci K1212_STATE_OPEN, // an application has opened the card 5962306a36Sopenharmony_ci K1212_STATE_SETUP, // the card has been setup for play 6062306a36Sopenharmony_ci K1212_STATE_PLAYING, // the card is playing 6162306a36Sopenharmony_ci K1212_STATE_MONITOR, // the card is in the monitor mode 6262306a36Sopenharmony_ci K1212_STATE_CALIBRATING, // the card is currently calibrating 6362306a36Sopenharmony_ci K1212_STATE_ERRORSTOP, // the card has stopped itself because of an error and we 6462306a36Sopenharmony_ci // are in the process of cleaning things up. 6562306a36Sopenharmony_ci K1212_STATE_MAX_STATE // state values of this and beyond are invalid 6662306a36Sopenharmony_ci}; 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci// ---------------------------------------------------------------------------- 6962306a36Sopenharmony_ci// The following enumeration defines the constants written to the card's 7062306a36Sopenharmony_ci// host-to-card doorbell to initiate a command. 7162306a36Sopenharmony_ci// ---------------------------------------------------------------------------- 7262306a36Sopenharmony_cienum korg1212_dbcnst { 7362306a36Sopenharmony_ci K1212_DB_RequestForData = 0, // sent by the card to request a buffer fill. 7462306a36Sopenharmony_ci K1212_DB_TriggerPlay = 1, // starts playback/record on the card. 7562306a36Sopenharmony_ci K1212_DB_SelectPlayMode = 2, // select monitor, playback setup, or stop. 7662306a36Sopenharmony_ci K1212_DB_ConfigureBufferMemory = 3, // tells card where the host audio buffers are. 7762306a36Sopenharmony_ci K1212_DB_RequestAdatTimecode = 4, // asks the card for the latest ADAT timecode value. 7862306a36Sopenharmony_ci K1212_DB_SetClockSourceRate = 5, // sets the clock source and rate for the card. 7962306a36Sopenharmony_ci K1212_DB_ConfigureMiscMemory = 6, // tells card where other buffers are. 8062306a36Sopenharmony_ci K1212_DB_TriggerFromAdat = 7, // tells card to trigger from Adat at a specific 8162306a36Sopenharmony_ci // timecode value. 8262306a36Sopenharmony_ci K1212_DB_DMAERROR = 0x80, // DMA Error - the PCI bus is congestioned. 8362306a36Sopenharmony_ci K1212_DB_CARDSTOPPED = 0x81, // Card has stopped by user request. 8462306a36Sopenharmony_ci K1212_DB_RebootCard = 0xA0, // instructs the card to reboot. 8562306a36Sopenharmony_ci K1212_DB_BootFromDSPPage4 = 0xA4, // instructs the card to boot from the DSP microcode 8662306a36Sopenharmony_ci // on page 4 (local page to card). 8762306a36Sopenharmony_ci K1212_DB_DSPDownloadDone = 0xAE, // sent by the card to indicate the download has 8862306a36Sopenharmony_ci // completed. 8962306a36Sopenharmony_ci K1212_DB_StartDSPDownload = 0xAF // tells the card to download its DSP firmware. 9062306a36Sopenharmony_ci}; 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci// ---------------------------------------------------------------------------- 9462306a36Sopenharmony_ci// The following enumeration defines return codes 9562306a36Sopenharmony_ci// to the Korg 1212 I/O driver. 9662306a36Sopenharmony_ci// ---------------------------------------------------------------------------- 9762306a36Sopenharmony_cienum snd_korg1212rc { 9862306a36Sopenharmony_ci K1212_CMDRET_Success = 0, // command was successfully placed 9962306a36Sopenharmony_ci K1212_CMDRET_DIOCFailure, // the DeviceIoControl call failed 10062306a36Sopenharmony_ci K1212_CMDRET_PMFailure, // the protected mode call failed 10162306a36Sopenharmony_ci K1212_CMDRET_FailUnspecified, // unspecified failure 10262306a36Sopenharmony_ci K1212_CMDRET_FailBadState, // the specified command can not be given in 10362306a36Sopenharmony_ci // the card's current state. (or the wave device's 10462306a36Sopenharmony_ci // state) 10562306a36Sopenharmony_ci K1212_CMDRET_CardUninitialized, // the card is uninitialized and cannot be used 10662306a36Sopenharmony_ci K1212_CMDRET_BadIndex, // an out of range card index was specified 10762306a36Sopenharmony_ci K1212_CMDRET_BadHandle, // an invalid card handle was specified 10862306a36Sopenharmony_ci K1212_CMDRET_NoFillRoutine, // a play request has been made before a fill routine set 10962306a36Sopenharmony_ci K1212_CMDRET_FillRoutineInUse, // can't set a new fill routine while one is in use 11062306a36Sopenharmony_ci K1212_CMDRET_NoAckFromCard, // the card never acknowledged a command 11162306a36Sopenharmony_ci K1212_CMDRET_BadParams, // bad parameters were provided by the caller 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci K1212_CMDRET_BadDevice, // the specified wave device was out of range 11462306a36Sopenharmony_ci K1212_CMDRET_BadFormat // the specified wave format is unsupported 11562306a36Sopenharmony_ci}; 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci// ---------------------------------------------------------------------------- 11862306a36Sopenharmony_ci// The following enumeration defines the constants used to select the play 11962306a36Sopenharmony_ci// mode for the card in the SelectPlayMode command. 12062306a36Sopenharmony_ci// ---------------------------------------------------------------------------- 12162306a36Sopenharmony_cienum PlayModeSelector { 12262306a36Sopenharmony_ci K1212_MODE_SetupPlay = 0x00000001, // provides card with pre-play information 12362306a36Sopenharmony_ci K1212_MODE_MonitorOn = 0x00000002, // tells card to turn on monitor mode 12462306a36Sopenharmony_ci K1212_MODE_MonitorOff = 0x00000004, // tells card to turn off monitor mode 12562306a36Sopenharmony_ci K1212_MODE_StopPlay = 0x00000008 // stops playback on the card 12662306a36Sopenharmony_ci}; 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci// ---------------------------------------------------------------------------- 12962306a36Sopenharmony_ci// The following enumeration defines the constants used to select the monitor 13062306a36Sopenharmony_ci// mode for the card in the SetMonitorMode command. 13162306a36Sopenharmony_ci// ---------------------------------------------------------------------------- 13262306a36Sopenharmony_cienum MonitorModeSelector { 13362306a36Sopenharmony_ci K1212_MONMODE_Off = 0, // tells card to turn off monitor mode 13462306a36Sopenharmony_ci K1212_MONMODE_On // tells card to turn on monitor mode 13562306a36Sopenharmony_ci}; 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci#define MAILBOX0_OFFSET 0x40 // location of mailbox 0 relative to base address 13862306a36Sopenharmony_ci#define MAILBOX1_OFFSET 0x44 // location of mailbox 1 relative to base address 13962306a36Sopenharmony_ci#define MAILBOX2_OFFSET 0x48 // location of mailbox 2 relative to base address 14062306a36Sopenharmony_ci#define MAILBOX3_OFFSET 0x4c // location of mailbox 3 relative to base address 14162306a36Sopenharmony_ci#define OUT_DOORBELL_OFFSET 0x60 // location of PCI to local doorbell 14262306a36Sopenharmony_ci#define IN_DOORBELL_OFFSET 0x64 // location of local to PCI doorbell 14362306a36Sopenharmony_ci#define STATUS_REG_OFFSET 0x68 // location of interrupt control/status register 14462306a36Sopenharmony_ci#define PCI_CONTROL_OFFSET 0x6c // location of the EEPROM, PCI, User I/O, init control 14562306a36Sopenharmony_ci // register 14662306a36Sopenharmony_ci#define SENS_CONTROL_OFFSET 0x6e // location of the input sensitivity setting register. 14762306a36Sopenharmony_ci // this is the upper word of the PCI control reg. 14862306a36Sopenharmony_ci#define DEV_VEND_ID_OFFSET 0x70 // location of the device and vendor ID register 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci#define MAX_COMMAND_RETRIES 5 // maximum number of times the driver will attempt 15162306a36Sopenharmony_ci // to send a command before giving up. 15262306a36Sopenharmony_ci#define COMMAND_ACK_MASK 0x8000 // the MSB is set in the command acknowledgment from 15362306a36Sopenharmony_ci // the card. 15462306a36Sopenharmony_ci#define DOORBELL_VAL_MASK 0x00FF // the doorbell value is one byte 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci#define CARD_BOOT_DELAY_IN_MS 10 15762306a36Sopenharmony_ci#define CARD_BOOT_TIMEOUT 10 15862306a36Sopenharmony_ci#define DSP_BOOT_DELAY_IN_MS 200 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci#define kNumBuffers 8 16162306a36Sopenharmony_ci#define k1212MaxCards 4 16262306a36Sopenharmony_ci#define k1212NumWaveDevices 6 16362306a36Sopenharmony_ci#define k16BitChannels 10 16462306a36Sopenharmony_ci#define k32BitChannels 2 16562306a36Sopenharmony_ci#define kAudioChannels (k16BitChannels + k32BitChannels) 16662306a36Sopenharmony_ci#define kPlayBufferFrames 1024 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci#define K1212_ANALOG_CHANNELS 2 16962306a36Sopenharmony_ci#define K1212_SPDIF_CHANNELS 2 17062306a36Sopenharmony_ci#define K1212_ADAT_CHANNELS 8 17162306a36Sopenharmony_ci#define K1212_CHANNELS (K1212_ADAT_CHANNELS + K1212_ANALOG_CHANNELS) 17262306a36Sopenharmony_ci#define K1212_MIN_CHANNELS 1 17362306a36Sopenharmony_ci#define K1212_MAX_CHANNELS K1212_CHANNELS 17462306a36Sopenharmony_ci#define K1212_FRAME_SIZE (sizeof(struct KorgAudioFrame)) 17562306a36Sopenharmony_ci#define K1212_MAX_SAMPLES (kPlayBufferFrames*kNumBuffers) 17662306a36Sopenharmony_ci#define K1212_PERIODS (kNumBuffers) 17762306a36Sopenharmony_ci#define K1212_PERIOD_BYTES (K1212_FRAME_SIZE*kPlayBufferFrames) 17862306a36Sopenharmony_ci#define K1212_BUF_SIZE (K1212_PERIOD_BYTES*kNumBuffers) 17962306a36Sopenharmony_ci#define K1212_ANALOG_BUF_SIZE (K1212_ANALOG_CHANNELS * 2 * kPlayBufferFrames * kNumBuffers) 18062306a36Sopenharmony_ci#define K1212_SPDIF_BUF_SIZE (K1212_SPDIF_CHANNELS * 3 * kPlayBufferFrames * kNumBuffers) 18162306a36Sopenharmony_ci#define K1212_ADAT_BUF_SIZE (K1212_ADAT_CHANNELS * 2 * kPlayBufferFrames * kNumBuffers) 18262306a36Sopenharmony_ci#define K1212_MAX_BUF_SIZE (K1212_ANALOG_BUF_SIZE + K1212_ADAT_BUF_SIZE) 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci#define k1212MinADCSens 0x00 18562306a36Sopenharmony_ci#define k1212MaxADCSens 0x7f 18662306a36Sopenharmony_ci#define k1212MaxVolume 0x7fff 18762306a36Sopenharmony_ci#define k1212MaxWaveVolume 0xffff 18862306a36Sopenharmony_ci#define k1212MinVolume 0x0000 18962306a36Sopenharmony_ci#define k1212MaxVolInverted 0x8000 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci// ----------------------------------------------------------------- 19262306a36Sopenharmony_ci// the following bits are used for controlling interrupts in the 19362306a36Sopenharmony_ci// interrupt control/status reg 19462306a36Sopenharmony_ci// ----------------------------------------------------------------- 19562306a36Sopenharmony_ci#define PCI_INT_ENABLE_BIT 0x00000100 19662306a36Sopenharmony_ci#define PCI_DOORBELL_INT_ENABLE_BIT 0x00000200 19762306a36Sopenharmony_ci#define LOCAL_INT_ENABLE_BIT 0x00010000 19862306a36Sopenharmony_ci#define LOCAL_DOORBELL_INT_ENABLE_BIT 0x00020000 19962306a36Sopenharmony_ci#define LOCAL_DMA1_INT_ENABLE_BIT 0x00080000 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci// ----------------------------------------------------------------- 20262306a36Sopenharmony_ci// the following bits are defined for the PCI command register 20362306a36Sopenharmony_ci// ----------------------------------------------------------------- 20462306a36Sopenharmony_ci#define PCI_CMD_MEM_SPACE_ENABLE_BIT 0x0002 20562306a36Sopenharmony_ci#define PCI_CMD_IO_SPACE_ENABLE_BIT 0x0001 20662306a36Sopenharmony_ci#define PCI_CMD_BUS_MASTER_ENABLE_BIT 0x0004 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci// ----------------------------------------------------------------- 20962306a36Sopenharmony_ci// the following bits are defined for the PCI status register 21062306a36Sopenharmony_ci// ----------------------------------------------------------------- 21162306a36Sopenharmony_ci#define PCI_STAT_PARITY_ERROR_BIT 0x8000 21262306a36Sopenharmony_ci#define PCI_STAT_SYSTEM_ERROR_BIT 0x4000 21362306a36Sopenharmony_ci#define PCI_STAT_MASTER_ABORT_RCVD_BIT 0x2000 21462306a36Sopenharmony_ci#define PCI_STAT_TARGET_ABORT_RCVD_BIT 0x1000 21562306a36Sopenharmony_ci#define PCI_STAT_TARGET_ABORT_SENT_BIT 0x0800 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci// ------------------------------------------------------------------------ 21862306a36Sopenharmony_ci// the following constants are used in setting the 1212 I/O card's input 21962306a36Sopenharmony_ci// sensitivity. 22062306a36Sopenharmony_ci// ------------------------------------------------------------------------ 22162306a36Sopenharmony_ci#define SET_SENS_LOCALINIT_BITPOS 15 22262306a36Sopenharmony_ci#define SET_SENS_DATA_BITPOS 10 22362306a36Sopenharmony_ci#define SET_SENS_CLOCK_BITPOS 8 22462306a36Sopenharmony_ci#define SET_SENS_LOADSHIFT_BITPOS 0 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci#define SET_SENS_LEFTCHANID 0x00 22762306a36Sopenharmony_ci#define SET_SENS_RIGHTCHANID 0x01 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci#define K1212SENSUPDATE_DELAY_IN_MS 50 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci// -------------------------------------------------------------------------- 23262306a36Sopenharmony_ci// WaitRTCTicks 23362306a36Sopenharmony_ci// 23462306a36Sopenharmony_ci// This function waits the specified number of real time clock ticks. 23562306a36Sopenharmony_ci// According to the DDK, each tick is ~0.8 microseconds. 23662306a36Sopenharmony_ci// The defines following the function declaration can be used for the 23762306a36Sopenharmony_ci// numTicksToWait parameter. 23862306a36Sopenharmony_ci// -------------------------------------------------------------------------- 23962306a36Sopenharmony_ci#define ONE_RTC_TICK 1 24062306a36Sopenharmony_ci#define SENSCLKPULSE_WIDTH 4 24162306a36Sopenharmony_ci#define LOADSHIFT_DELAY 4 24262306a36Sopenharmony_ci#define INTERCOMMAND_DELAY 40 24362306a36Sopenharmony_ci#define STOPCARD_DELAY 300 // max # RTC ticks for the card to stop once we write 24462306a36Sopenharmony_ci // the command register. (could be up to 180 us) 24562306a36Sopenharmony_ci#define COMMAND_ACK_DELAY 13 // number of RTC ticks to wait for an acknowledgement 24662306a36Sopenharmony_ci // from the card after sending a command. 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_cienum ClockSourceIndex { 24962306a36Sopenharmony_ci K1212_CLKIDX_AdatAt44_1K = 0, // selects source as ADAT at 44.1 kHz 25062306a36Sopenharmony_ci K1212_CLKIDX_AdatAt48K, // selects source as ADAT at 48 kHz 25162306a36Sopenharmony_ci K1212_CLKIDX_WordAt44_1K, // selects source as S/PDIF at 44.1 kHz 25262306a36Sopenharmony_ci K1212_CLKIDX_WordAt48K, // selects source as S/PDIF at 48 kHz 25362306a36Sopenharmony_ci K1212_CLKIDX_LocalAt44_1K, // selects source as local clock at 44.1 kHz 25462306a36Sopenharmony_ci K1212_CLKIDX_LocalAt48K, // selects source as local clock at 48 kHz 25562306a36Sopenharmony_ci K1212_CLKIDX_Invalid // used to check validity of the index 25662306a36Sopenharmony_ci}; 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_cienum ClockSourceType { 25962306a36Sopenharmony_ci K1212_CLKIDX_Adat = 0, // selects source as ADAT 26062306a36Sopenharmony_ci K1212_CLKIDX_Word, // selects source as S/PDIF 26162306a36Sopenharmony_ci K1212_CLKIDX_Local // selects source as local clock 26262306a36Sopenharmony_ci}; 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_cistruct KorgAudioFrame { 26562306a36Sopenharmony_ci u16 frameData16[k16BitChannels]; /* channels 0-9 use 16 bit samples */ 26662306a36Sopenharmony_ci u32 frameData32[k32BitChannels]; /* channels 10-11 use 32 bits - only 20 are sent across S/PDIF */ 26762306a36Sopenharmony_ci u32 timeCodeVal; /* holds the ADAT timecode value */ 26862306a36Sopenharmony_ci}; 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_cistruct KorgAudioBuffer { 27162306a36Sopenharmony_ci struct KorgAudioFrame bufferData[kPlayBufferFrames]; /* buffer definition */ 27262306a36Sopenharmony_ci}; 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_cistruct KorgSharedBuffer { 27562306a36Sopenharmony_ci#ifdef K1212_LARGEALLOC 27662306a36Sopenharmony_ci struct KorgAudioBuffer playDataBufs[kNumBuffers]; 27762306a36Sopenharmony_ci struct KorgAudioBuffer recordDataBufs[kNumBuffers]; 27862306a36Sopenharmony_ci#endif 27962306a36Sopenharmony_ci short volumeData[kAudioChannels]; 28062306a36Sopenharmony_ci u32 cardCommand; 28162306a36Sopenharmony_ci u16 routeData [kAudioChannels]; 28262306a36Sopenharmony_ci u32 AdatTimeCode; // ADAT timecode value 28362306a36Sopenharmony_ci}; 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_cistruct SensBits { 28662306a36Sopenharmony_ci union { 28762306a36Sopenharmony_ci struct { 28862306a36Sopenharmony_ci unsigned int leftChanVal:8; 28962306a36Sopenharmony_ci unsigned int leftChanId:8; 29062306a36Sopenharmony_ci } v; 29162306a36Sopenharmony_ci u16 leftSensBits; 29262306a36Sopenharmony_ci } l; 29362306a36Sopenharmony_ci union { 29462306a36Sopenharmony_ci struct { 29562306a36Sopenharmony_ci unsigned int rightChanVal:8; 29662306a36Sopenharmony_ci unsigned int rightChanId:8; 29762306a36Sopenharmony_ci } v; 29862306a36Sopenharmony_ci u16 rightSensBits; 29962306a36Sopenharmony_ci } r; 30062306a36Sopenharmony_ci}; 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_cistruct snd_korg1212 { 30362306a36Sopenharmony_ci struct snd_card *card; 30462306a36Sopenharmony_ci struct pci_dev *pci; 30562306a36Sopenharmony_ci struct snd_pcm *pcm; 30662306a36Sopenharmony_ci int irq; 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci spinlock_t lock; 30962306a36Sopenharmony_ci struct mutex open_mutex; 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci struct timer_list timer; /* timer callback for checking ack of stop request */ 31262306a36Sopenharmony_ci int stop_pending_cnt; /* counter for stop pending check */ 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci wait_queue_head_t wait; 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci unsigned long iomem; 31762306a36Sopenharmony_ci unsigned long ioport; 31862306a36Sopenharmony_ci unsigned long iomem2; 31962306a36Sopenharmony_ci unsigned long irqcount; 32062306a36Sopenharmony_ci unsigned long inIRQ; 32162306a36Sopenharmony_ci void __iomem *iobase; 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci struct snd_dma_buffer *dma_dsp; 32462306a36Sopenharmony_ci struct snd_dma_buffer *dma_play; 32562306a36Sopenharmony_ci struct snd_dma_buffer *dma_rec; 32662306a36Sopenharmony_ci struct snd_dma_buffer *dma_shared; 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_ci u32 DataBufsSize; 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci struct KorgAudioBuffer * playDataBufsPtr; 33162306a36Sopenharmony_ci struct KorgAudioBuffer * recordDataBufsPtr; 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci struct KorgSharedBuffer * sharedBufferPtr; 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci u32 RecDataPhy; 33662306a36Sopenharmony_ci u32 PlayDataPhy; 33762306a36Sopenharmony_ci unsigned long sharedBufferPhy; 33862306a36Sopenharmony_ci u32 VolumeTablePhy; 33962306a36Sopenharmony_ci u32 RoutingTablePhy; 34062306a36Sopenharmony_ci u32 AdatTimeCodePhy; 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ci u32 __iomem * statusRegPtr; // address of the interrupt status/control register 34362306a36Sopenharmony_ci u32 __iomem * outDoorbellPtr; // address of the host->card doorbell register 34462306a36Sopenharmony_ci u32 __iomem * inDoorbellPtr; // address of the card->host doorbell register 34562306a36Sopenharmony_ci u32 __iomem * mailbox0Ptr; // address of mailbox 0 on the card 34662306a36Sopenharmony_ci u32 __iomem * mailbox1Ptr; // address of mailbox 1 on the card 34762306a36Sopenharmony_ci u32 __iomem * mailbox2Ptr; // address of mailbox 2 on the card 34862306a36Sopenharmony_ci u32 __iomem * mailbox3Ptr; // address of mailbox 3 on the card 34962306a36Sopenharmony_ci u32 __iomem * controlRegPtr; // address of the EEPROM, PCI, I/O, Init ctrl reg 35062306a36Sopenharmony_ci u16 __iomem * sensRegPtr; // address of the sensitivity setting register 35162306a36Sopenharmony_ci u32 __iomem * idRegPtr; // address of the device and vendor ID registers 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci size_t periodsize; 35462306a36Sopenharmony_ci int channels; 35562306a36Sopenharmony_ci int currentBuffer; 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ci struct snd_pcm_substream *playback_substream; 35862306a36Sopenharmony_ci struct snd_pcm_substream *capture_substream; 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_ci pid_t capture_pid; 36162306a36Sopenharmony_ci pid_t playback_pid; 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_ci enum CardState cardState; 36462306a36Sopenharmony_ci int running; 36562306a36Sopenharmony_ci int idleMonitorOn; // indicates whether the card is in idle monitor mode. 36662306a36Sopenharmony_ci u32 cmdRetryCount; // tracks how many times we have retried sending to the card. 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ci enum ClockSourceIndex clkSrcRate; // sample rate and clock source 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_ci enum ClockSourceType clkSource; // clock source 37162306a36Sopenharmony_ci int clkRate; // clock rate 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci int volumePhase[kAudioChannels]; 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci u16 leftADCInSens; // ADC left channel input sensitivity 37662306a36Sopenharmony_ci u16 rightADCInSens; // ADC right channel input sensitivity 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_ci int opencnt; // Open/Close count 37962306a36Sopenharmony_ci int setcnt; // SetupForPlay count 38062306a36Sopenharmony_ci int playcnt; // TriggerPlay count 38162306a36Sopenharmony_ci int errorcnt; // Error Count 38262306a36Sopenharmony_ci unsigned long totalerrorcnt; // Total Error Count 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_ci int dsp_is_loaded; 38562306a36Sopenharmony_ci int dsp_stop_is_processed; 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci}; 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_ciMODULE_DESCRIPTION("korg1212"); 39062306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 39162306a36Sopenharmony_ciMODULE_FIRMWARE("korg/k1212.dsp"); 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_cistatic int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ 39462306a36Sopenharmony_cistatic char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ 39562306a36Sopenharmony_cistatic bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */ 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_cimodule_param_array(index, int, NULL, 0444); 39862306a36Sopenharmony_ciMODULE_PARM_DESC(index, "Index value for Korg 1212 soundcard."); 39962306a36Sopenharmony_cimodule_param_array(id, charp, NULL, 0444); 40062306a36Sopenharmony_ciMODULE_PARM_DESC(id, "ID string for Korg 1212 soundcard."); 40162306a36Sopenharmony_cimodule_param_array(enable, bool, NULL, 0444); 40262306a36Sopenharmony_ciMODULE_PARM_DESC(enable, "Enable Korg 1212 soundcard."); 40362306a36Sopenharmony_ciMODULE_AUTHOR("Haroldo Gamal <gamal@alternex.com.br>"); 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_cistatic const struct pci_device_id snd_korg1212_ids[] = { 40662306a36Sopenharmony_ci { 40762306a36Sopenharmony_ci .vendor = 0x10b5, 40862306a36Sopenharmony_ci .device = 0x906d, 40962306a36Sopenharmony_ci .subvendor = PCI_ANY_ID, 41062306a36Sopenharmony_ci .subdevice = PCI_ANY_ID, 41162306a36Sopenharmony_ci }, 41262306a36Sopenharmony_ci { 0, }, 41362306a36Sopenharmony_ci}; 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ciMODULE_DEVICE_TABLE(pci, snd_korg1212_ids); 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_cistatic const char * const stateName[] = { 41862306a36Sopenharmony_ci "Non-existent", 41962306a36Sopenharmony_ci "Uninitialized", 42062306a36Sopenharmony_ci "DSP download in process", 42162306a36Sopenharmony_ci "DSP download complete", 42262306a36Sopenharmony_ci "Ready", 42362306a36Sopenharmony_ci "Open", 42462306a36Sopenharmony_ci "Setup for play", 42562306a36Sopenharmony_ci "Playing", 42662306a36Sopenharmony_ci "Monitor mode on", 42762306a36Sopenharmony_ci "Calibrating", 42862306a36Sopenharmony_ci "Invalid" 42962306a36Sopenharmony_ci}; 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_cistatic const char * const clockSourceTypeName[] = { "ADAT", "S/PDIF", "local" }; 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_cistatic const char * const clockSourceName[] = { 43462306a36Sopenharmony_ci "ADAT at 44.1 kHz", 43562306a36Sopenharmony_ci "ADAT at 48 kHz", 43662306a36Sopenharmony_ci "S/PDIF at 44.1 kHz", 43762306a36Sopenharmony_ci "S/PDIF at 48 kHz", 43862306a36Sopenharmony_ci "local clock at 44.1 kHz", 43962306a36Sopenharmony_ci "local clock at 48 kHz" 44062306a36Sopenharmony_ci}; 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_cistatic const char * const channelName[] = { 44362306a36Sopenharmony_ci "ADAT-1", 44462306a36Sopenharmony_ci "ADAT-2", 44562306a36Sopenharmony_ci "ADAT-3", 44662306a36Sopenharmony_ci "ADAT-4", 44762306a36Sopenharmony_ci "ADAT-5", 44862306a36Sopenharmony_ci "ADAT-6", 44962306a36Sopenharmony_ci "ADAT-7", 45062306a36Sopenharmony_ci "ADAT-8", 45162306a36Sopenharmony_ci "Analog-L", 45262306a36Sopenharmony_ci "Analog-R", 45362306a36Sopenharmony_ci "SPDIF-L", 45462306a36Sopenharmony_ci "SPDIF-R", 45562306a36Sopenharmony_ci}; 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_cistatic const u16 ClockSourceSelector[] = { 45862306a36Sopenharmony_ci 0x8000, // selects source as ADAT at 44.1 kHz 45962306a36Sopenharmony_ci 0x0000, // selects source as ADAT at 48 kHz 46062306a36Sopenharmony_ci 0x8001, // selects source as S/PDIF at 44.1 kHz 46162306a36Sopenharmony_ci 0x0001, // selects source as S/PDIF at 48 kHz 46262306a36Sopenharmony_ci 0x8002, // selects source as local clock at 44.1 kHz 46362306a36Sopenharmony_ci 0x0002 // selects source as local clock at 48 kHz 46462306a36Sopenharmony_ci}; 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_ciunion swap_u32 { unsigned char c[4]; u32 i; }; 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_ci#ifdef SNDRV_BIG_ENDIAN 46962306a36Sopenharmony_cistatic u32 LowerWordSwap(u32 swappee) 47062306a36Sopenharmony_ci#else 47162306a36Sopenharmony_cistatic u32 UpperWordSwap(u32 swappee) 47262306a36Sopenharmony_ci#endif 47362306a36Sopenharmony_ci{ 47462306a36Sopenharmony_ci union swap_u32 retVal, swapper; 47562306a36Sopenharmony_ci 47662306a36Sopenharmony_ci swapper.i = swappee; 47762306a36Sopenharmony_ci retVal.c[2] = swapper.c[3]; 47862306a36Sopenharmony_ci retVal.c[3] = swapper.c[2]; 47962306a36Sopenharmony_ci retVal.c[1] = swapper.c[1]; 48062306a36Sopenharmony_ci retVal.c[0] = swapper.c[0]; 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_ci return retVal.i; 48362306a36Sopenharmony_ci} 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_ci#ifdef SNDRV_BIG_ENDIAN 48662306a36Sopenharmony_cistatic u32 UpperWordSwap(u32 swappee) 48762306a36Sopenharmony_ci#else 48862306a36Sopenharmony_cistatic u32 LowerWordSwap(u32 swappee) 48962306a36Sopenharmony_ci#endif 49062306a36Sopenharmony_ci{ 49162306a36Sopenharmony_ci union swap_u32 retVal, swapper; 49262306a36Sopenharmony_ci 49362306a36Sopenharmony_ci swapper.i = swappee; 49462306a36Sopenharmony_ci retVal.c[2] = swapper.c[2]; 49562306a36Sopenharmony_ci retVal.c[3] = swapper.c[3]; 49662306a36Sopenharmony_ci retVal.c[1] = swapper.c[0]; 49762306a36Sopenharmony_ci retVal.c[0] = swapper.c[1]; 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_ci return retVal.i; 50062306a36Sopenharmony_ci} 50162306a36Sopenharmony_ci 50262306a36Sopenharmony_ci#define SetBitInWord(theWord,bitPosition) (*theWord) |= (0x0001 << bitPosition) 50362306a36Sopenharmony_ci#define SetBitInDWord(theWord,bitPosition) (*theWord) |= (0x00000001 << bitPosition) 50462306a36Sopenharmony_ci#define ClearBitInWord(theWord,bitPosition) (*theWord) &= ~(0x0001 << bitPosition) 50562306a36Sopenharmony_ci#define ClearBitInDWord(theWord,bitPosition) (*theWord) &= ~(0x00000001 << bitPosition) 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_cistatic int snd_korg1212_Send1212Command(struct snd_korg1212 *korg1212, 50862306a36Sopenharmony_ci enum korg1212_dbcnst doorbellVal, 50962306a36Sopenharmony_ci u32 mailBox0Val, u32 mailBox1Val, 51062306a36Sopenharmony_ci u32 mailBox2Val, u32 mailBox3Val) 51162306a36Sopenharmony_ci{ 51262306a36Sopenharmony_ci u32 retryCount; 51362306a36Sopenharmony_ci u16 mailBox3Lo; 51462306a36Sopenharmony_ci int rc = K1212_CMDRET_Success; 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_ci if (!korg1212->outDoorbellPtr) { 51762306a36Sopenharmony_ci K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: CardUninitialized\n"); 51862306a36Sopenharmony_ci return K1212_CMDRET_CardUninitialized; 51962306a36Sopenharmony_ci } 52062306a36Sopenharmony_ci 52162306a36Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: Card <- 0x%08x 0x%08x [%s]\n", 52262306a36Sopenharmony_ci doorbellVal, mailBox0Val, stateName[korg1212->cardState]); 52362306a36Sopenharmony_ci for (retryCount = 0; retryCount < MAX_COMMAND_RETRIES; retryCount++) { 52462306a36Sopenharmony_ci writel(mailBox3Val, korg1212->mailbox3Ptr); 52562306a36Sopenharmony_ci writel(mailBox2Val, korg1212->mailbox2Ptr); 52662306a36Sopenharmony_ci writel(mailBox1Val, korg1212->mailbox1Ptr); 52762306a36Sopenharmony_ci writel(mailBox0Val, korg1212->mailbox0Ptr); 52862306a36Sopenharmony_ci writel(doorbellVal, korg1212->outDoorbellPtr); // interrupt the card 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_ci // -------------------------------------------------------------- 53162306a36Sopenharmony_ci // the reboot command will not give an acknowledgement. 53262306a36Sopenharmony_ci // -------------------------------------------------------------- 53362306a36Sopenharmony_ci if ( doorbellVal == K1212_DB_RebootCard || 53462306a36Sopenharmony_ci doorbellVal == K1212_DB_BootFromDSPPage4 || 53562306a36Sopenharmony_ci doorbellVal == K1212_DB_StartDSPDownload ) { 53662306a36Sopenharmony_ci rc = K1212_CMDRET_Success; 53762306a36Sopenharmony_ci break; 53862306a36Sopenharmony_ci } 53962306a36Sopenharmony_ci 54062306a36Sopenharmony_ci // -------------------------------------------------------------- 54162306a36Sopenharmony_ci // See if the card acknowledged the command. Wait a bit, then 54262306a36Sopenharmony_ci // read in the low word of mailbox3. If the MSB is set and the 54362306a36Sopenharmony_ci // low byte is equal to the doorbell value, then it ack'd. 54462306a36Sopenharmony_ci // -------------------------------------------------------------- 54562306a36Sopenharmony_ci udelay(COMMAND_ACK_DELAY); 54662306a36Sopenharmony_ci mailBox3Lo = readl(korg1212->mailbox3Ptr); 54762306a36Sopenharmony_ci if (mailBox3Lo & COMMAND_ACK_MASK) { 54862306a36Sopenharmony_ci if ((mailBox3Lo & DOORBELL_VAL_MASK) == (doorbellVal & DOORBELL_VAL_MASK)) { 54962306a36Sopenharmony_ci K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: Card <- Success\n"); 55062306a36Sopenharmony_ci rc = K1212_CMDRET_Success; 55162306a36Sopenharmony_ci break; 55262306a36Sopenharmony_ci } 55362306a36Sopenharmony_ci } 55462306a36Sopenharmony_ci } 55562306a36Sopenharmony_ci korg1212->cmdRetryCount += retryCount; 55662306a36Sopenharmony_ci 55762306a36Sopenharmony_ci if (retryCount >= MAX_COMMAND_RETRIES) { 55862306a36Sopenharmony_ci K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: Card <- NoAckFromCard\n"); 55962306a36Sopenharmony_ci rc = K1212_CMDRET_NoAckFromCard; 56062306a36Sopenharmony_ci } 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_ci return rc; 56362306a36Sopenharmony_ci} 56462306a36Sopenharmony_ci 56562306a36Sopenharmony_ci/* spinlock already held */ 56662306a36Sopenharmony_cistatic void snd_korg1212_SendStop(struct snd_korg1212 *korg1212) 56762306a36Sopenharmony_ci{ 56862306a36Sopenharmony_ci if (! korg1212->stop_pending_cnt) { 56962306a36Sopenharmony_ci korg1212->sharedBufferPtr->cardCommand = 0xffffffff; 57062306a36Sopenharmony_ci /* program the timer */ 57162306a36Sopenharmony_ci korg1212->stop_pending_cnt = HZ; 57262306a36Sopenharmony_ci mod_timer(&korg1212->timer, jiffies + 1); 57362306a36Sopenharmony_ci } 57462306a36Sopenharmony_ci} 57562306a36Sopenharmony_ci 57662306a36Sopenharmony_cistatic void snd_korg1212_SendStopAndWait(struct snd_korg1212 *korg1212) 57762306a36Sopenharmony_ci{ 57862306a36Sopenharmony_ci unsigned long flags; 57962306a36Sopenharmony_ci spin_lock_irqsave(&korg1212->lock, flags); 58062306a36Sopenharmony_ci korg1212->dsp_stop_is_processed = 0; 58162306a36Sopenharmony_ci snd_korg1212_SendStop(korg1212); 58262306a36Sopenharmony_ci spin_unlock_irqrestore(&korg1212->lock, flags); 58362306a36Sopenharmony_ci wait_event_timeout(korg1212->wait, korg1212->dsp_stop_is_processed, (HZ * 3) / 2); 58462306a36Sopenharmony_ci} 58562306a36Sopenharmony_ci 58662306a36Sopenharmony_ci/* timer callback for checking the ack of stop request */ 58762306a36Sopenharmony_cistatic void snd_korg1212_timer_func(struct timer_list *t) 58862306a36Sopenharmony_ci{ 58962306a36Sopenharmony_ci struct snd_korg1212 *korg1212 = from_timer(korg1212, t, timer); 59062306a36Sopenharmony_ci unsigned long flags; 59162306a36Sopenharmony_ci 59262306a36Sopenharmony_ci spin_lock_irqsave(&korg1212->lock, flags); 59362306a36Sopenharmony_ci if (korg1212->sharedBufferPtr->cardCommand == 0) { 59462306a36Sopenharmony_ci /* ack'ed */ 59562306a36Sopenharmony_ci korg1212->stop_pending_cnt = 0; 59662306a36Sopenharmony_ci korg1212->dsp_stop_is_processed = 1; 59762306a36Sopenharmony_ci wake_up(&korg1212->wait); 59862306a36Sopenharmony_ci K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: Stop ack'ed [%s]\n", 59962306a36Sopenharmony_ci stateName[korg1212->cardState]); 60062306a36Sopenharmony_ci } else { 60162306a36Sopenharmony_ci if (--korg1212->stop_pending_cnt > 0) { 60262306a36Sopenharmony_ci /* reprogram timer */ 60362306a36Sopenharmony_ci mod_timer(&korg1212->timer, jiffies + 1); 60462306a36Sopenharmony_ci } else { 60562306a36Sopenharmony_ci snd_printd("korg1212_timer_func timeout\n"); 60662306a36Sopenharmony_ci korg1212->sharedBufferPtr->cardCommand = 0; 60762306a36Sopenharmony_ci korg1212->dsp_stop_is_processed = 1; 60862306a36Sopenharmony_ci wake_up(&korg1212->wait); 60962306a36Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: Stop timeout [%s]\n", 61062306a36Sopenharmony_ci stateName[korg1212->cardState]); 61162306a36Sopenharmony_ci } 61262306a36Sopenharmony_ci } 61362306a36Sopenharmony_ci spin_unlock_irqrestore(&korg1212->lock, flags); 61462306a36Sopenharmony_ci} 61562306a36Sopenharmony_ci 61662306a36Sopenharmony_cistatic int snd_korg1212_TurnOnIdleMonitor(struct snd_korg1212 *korg1212) 61762306a36Sopenharmony_ci{ 61862306a36Sopenharmony_ci unsigned long flags; 61962306a36Sopenharmony_ci int rc; 62062306a36Sopenharmony_ci 62162306a36Sopenharmony_ci udelay(INTERCOMMAND_DELAY); 62262306a36Sopenharmony_ci spin_lock_irqsave(&korg1212->lock, flags); 62362306a36Sopenharmony_ci korg1212->idleMonitorOn = 1; 62462306a36Sopenharmony_ci rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_SelectPlayMode, 62562306a36Sopenharmony_ci K1212_MODE_MonitorOn, 0, 0, 0); 62662306a36Sopenharmony_ci spin_unlock_irqrestore(&korg1212->lock, flags); 62762306a36Sopenharmony_ci return rc; 62862306a36Sopenharmony_ci} 62962306a36Sopenharmony_ci 63062306a36Sopenharmony_cistatic void snd_korg1212_TurnOffIdleMonitor(struct snd_korg1212 *korg1212) 63162306a36Sopenharmony_ci{ 63262306a36Sopenharmony_ci if (korg1212->idleMonitorOn) { 63362306a36Sopenharmony_ci snd_korg1212_SendStopAndWait(korg1212); 63462306a36Sopenharmony_ci korg1212->idleMonitorOn = 0; 63562306a36Sopenharmony_ci } 63662306a36Sopenharmony_ci} 63762306a36Sopenharmony_ci 63862306a36Sopenharmony_cistatic inline void snd_korg1212_setCardState(struct snd_korg1212 * korg1212, enum CardState csState) 63962306a36Sopenharmony_ci{ 64062306a36Sopenharmony_ci korg1212->cardState = csState; 64162306a36Sopenharmony_ci} 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_cistatic int snd_korg1212_OpenCard(struct snd_korg1212 * korg1212) 64462306a36Sopenharmony_ci{ 64562306a36Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: OpenCard [%s] %d\n", 64662306a36Sopenharmony_ci stateName[korg1212->cardState], korg1212->opencnt); 64762306a36Sopenharmony_ci mutex_lock(&korg1212->open_mutex); 64862306a36Sopenharmony_ci if (korg1212->opencnt++ == 0) { 64962306a36Sopenharmony_ci snd_korg1212_TurnOffIdleMonitor(korg1212); 65062306a36Sopenharmony_ci snd_korg1212_setCardState(korg1212, K1212_STATE_OPEN); 65162306a36Sopenharmony_ci } 65262306a36Sopenharmony_ci 65362306a36Sopenharmony_ci mutex_unlock(&korg1212->open_mutex); 65462306a36Sopenharmony_ci return 1; 65562306a36Sopenharmony_ci} 65662306a36Sopenharmony_ci 65762306a36Sopenharmony_cistatic int snd_korg1212_CloseCard(struct snd_korg1212 * korg1212) 65862306a36Sopenharmony_ci{ 65962306a36Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: CloseCard [%s] %d\n", 66062306a36Sopenharmony_ci stateName[korg1212->cardState], korg1212->opencnt); 66162306a36Sopenharmony_ci 66262306a36Sopenharmony_ci mutex_lock(&korg1212->open_mutex); 66362306a36Sopenharmony_ci if (--(korg1212->opencnt)) { 66462306a36Sopenharmony_ci mutex_unlock(&korg1212->open_mutex); 66562306a36Sopenharmony_ci return 0; 66662306a36Sopenharmony_ci } 66762306a36Sopenharmony_ci 66862306a36Sopenharmony_ci if (korg1212->cardState == K1212_STATE_SETUP) { 66962306a36Sopenharmony_ci int rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_SelectPlayMode, 67062306a36Sopenharmony_ci K1212_MODE_StopPlay, 0, 0, 0); 67162306a36Sopenharmony_ci if (rc) 67262306a36Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: CloseCard - RC = %d [%s]\n", 67362306a36Sopenharmony_ci rc, stateName[korg1212->cardState]); 67462306a36Sopenharmony_ci if (rc != K1212_CMDRET_Success) { 67562306a36Sopenharmony_ci mutex_unlock(&korg1212->open_mutex); 67662306a36Sopenharmony_ci return 0; 67762306a36Sopenharmony_ci } 67862306a36Sopenharmony_ci } else if (korg1212->cardState > K1212_STATE_SETUP) { 67962306a36Sopenharmony_ci snd_korg1212_SendStopAndWait(korg1212); 68062306a36Sopenharmony_ci } 68162306a36Sopenharmony_ci 68262306a36Sopenharmony_ci if (korg1212->cardState > K1212_STATE_READY) { 68362306a36Sopenharmony_ci snd_korg1212_TurnOnIdleMonitor(korg1212); 68462306a36Sopenharmony_ci snd_korg1212_setCardState(korg1212, K1212_STATE_READY); 68562306a36Sopenharmony_ci } 68662306a36Sopenharmony_ci 68762306a36Sopenharmony_ci mutex_unlock(&korg1212->open_mutex); 68862306a36Sopenharmony_ci return 0; 68962306a36Sopenharmony_ci} 69062306a36Sopenharmony_ci 69162306a36Sopenharmony_ci/* spinlock already held */ 69262306a36Sopenharmony_cistatic int snd_korg1212_SetupForPlay(struct snd_korg1212 * korg1212) 69362306a36Sopenharmony_ci{ 69462306a36Sopenharmony_ci int rc; 69562306a36Sopenharmony_ci 69662306a36Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: SetupForPlay [%s] %d\n", 69762306a36Sopenharmony_ci stateName[korg1212->cardState], korg1212->setcnt); 69862306a36Sopenharmony_ci 69962306a36Sopenharmony_ci if (korg1212->setcnt++) 70062306a36Sopenharmony_ci return 0; 70162306a36Sopenharmony_ci 70262306a36Sopenharmony_ci snd_korg1212_setCardState(korg1212, K1212_STATE_SETUP); 70362306a36Sopenharmony_ci rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_SelectPlayMode, 70462306a36Sopenharmony_ci K1212_MODE_SetupPlay, 0, 0, 0); 70562306a36Sopenharmony_ci if (rc) 70662306a36Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: SetupForPlay - RC = %d [%s]\n", 70762306a36Sopenharmony_ci rc, stateName[korg1212->cardState]); 70862306a36Sopenharmony_ci if (rc != K1212_CMDRET_Success) { 70962306a36Sopenharmony_ci return 1; 71062306a36Sopenharmony_ci } 71162306a36Sopenharmony_ci return 0; 71262306a36Sopenharmony_ci} 71362306a36Sopenharmony_ci 71462306a36Sopenharmony_ci/* spinlock already held */ 71562306a36Sopenharmony_cistatic int snd_korg1212_TriggerPlay(struct snd_korg1212 * korg1212) 71662306a36Sopenharmony_ci{ 71762306a36Sopenharmony_ci int rc; 71862306a36Sopenharmony_ci 71962306a36Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: TriggerPlay [%s] %d\n", 72062306a36Sopenharmony_ci stateName[korg1212->cardState], korg1212->playcnt); 72162306a36Sopenharmony_ci 72262306a36Sopenharmony_ci if (korg1212->playcnt++) 72362306a36Sopenharmony_ci return 0; 72462306a36Sopenharmony_ci 72562306a36Sopenharmony_ci snd_korg1212_setCardState(korg1212, K1212_STATE_PLAYING); 72662306a36Sopenharmony_ci rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_TriggerPlay, 0, 0, 0, 0); 72762306a36Sopenharmony_ci if (rc) 72862306a36Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: TriggerPlay - RC = %d [%s]\n", 72962306a36Sopenharmony_ci rc, stateName[korg1212->cardState]); 73062306a36Sopenharmony_ci if (rc != K1212_CMDRET_Success) { 73162306a36Sopenharmony_ci return 1; 73262306a36Sopenharmony_ci } 73362306a36Sopenharmony_ci return 0; 73462306a36Sopenharmony_ci} 73562306a36Sopenharmony_ci 73662306a36Sopenharmony_ci/* spinlock already held */ 73762306a36Sopenharmony_cistatic int snd_korg1212_StopPlay(struct snd_korg1212 * korg1212) 73862306a36Sopenharmony_ci{ 73962306a36Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: StopPlay [%s] %d\n", 74062306a36Sopenharmony_ci stateName[korg1212->cardState], korg1212->playcnt); 74162306a36Sopenharmony_ci 74262306a36Sopenharmony_ci if (--(korg1212->playcnt)) 74362306a36Sopenharmony_ci return 0; 74462306a36Sopenharmony_ci 74562306a36Sopenharmony_ci korg1212->setcnt = 0; 74662306a36Sopenharmony_ci 74762306a36Sopenharmony_ci if (korg1212->cardState != K1212_STATE_ERRORSTOP) 74862306a36Sopenharmony_ci snd_korg1212_SendStop(korg1212); 74962306a36Sopenharmony_ci 75062306a36Sopenharmony_ci snd_korg1212_setCardState(korg1212, K1212_STATE_OPEN); 75162306a36Sopenharmony_ci return 0; 75262306a36Sopenharmony_ci} 75362306a36Sopenharmony_ci 75462306a36Sopenharmony_cistatic void snd_korg1212_EnableCardInterrupts(struct snd_korg1212 * korg1212) 75562306a36Sopenharmony_ci{ 75662306a36Sopenharmony_ci writel(PCI_INT_ENABLE_BIT | 75762306a36Sopenharmony_ci PCI_DOORBELL_INT_ENABLE_BIT | 75862306a36Sopenharmony_ci LOCAL_INT_ENABLE_BIT | 75962306a36Sopenharmony_ci LOCAL_DOORBELL_INT_ENABLE_BIT | 76062306a36Sopenharmony_ci LOCAL_DMA1_INT_ENABLE_BIT, 76162306a36Sopenharmony_ci korg1212->statusRegPtr); 76262306a36Sopenharmony_ci} 76362306a36Sopenharmony_ci 76462306a36Sopenharmony_ci#if 0 /* not used */ 76562306a36Sopenharmony_ci 76662306a36Sopenharmony_cistatic int snd_korg1212_SetMonitorMode(struct snd_korg1212 *korg1212, 76762306a36Sopenharmony_ci enum MonitorModeSelector mode) 76862306a36Sopenharmony_ci{ 76962306a36Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: SetMonitorMode [%s]\n", 77062306a36Sopenharmony_ci stateName[korg1212->cardState]); 77162306a36Sopenharmony_ci 77262306a36Sopenharmony_ci switch (mode) { 77362306a36Sopenharmony_ci case K1212_MONMODE_Off: 77462306a36Sopenharmony_ci if (korg1212->cardState != K1212_STATE_MONITOR) 77562306a36Sopenharmony_ci return 0; 77662306a36Sopenharmony_ci else { 77762306a36Sopenharmony_ci snd_korg1212_SendStopAndWait(korg1212); 77862306a36Sopenharmony_ci snd_korg1212_setCardState(korg1212, K1212_STATE_OPEN); 77962306a36Sopenharmony_ci } 78062306a36Sopenharmony_ci break; 78162306a36Sopenharmony_ci 78262306a36Sopenharmony_ci case K1212_MONMODE_On: 78362306a36Sopenharmony_ci if (korg1212->cardState != K1212_STATE_OPEN) 78462306a36Sopenharmony_ci return 0; 78562306a36Sopenharmony_ci else { 78662306a36Sopenharmony_ci int rc; 78762306a36Sopenharmony_ci snd_korg1212_setCardState(korg1212, K1212_STATE_MONITOR); 78862306a36Sopenharmony_ci rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_SelectPlayMode, 78962306a36Sopenharmony_ci K1212_MODE_MonitorOn, 0, 0, 0); 79062306a36Sopenharmony_ci if (rc != K1212_CMDRET_Success) 79162306a36Sopenharmony_ci return 0; 79262306a36Sopenharmony_ci } 79362306a36Sopenharmony_ci break; 79462306a36Sopenharmony_ci 79562306a36Sopenharmony_ci default: 79662306a36Sopenharmony_ci return 0; 79762306a36Sopenharmony_ci } 79862306a36Sopenharmony_ci 79962306a36Sopenharmony_ci return 1; 80062306a36Sopenharmony_ci} 80162306a36Sopenharmony_ci 80262306a36Sopenharmony_ci#endif /* not used */ 80362306a36Sopenharmony_ci 80462306a36Sopenharmony_cistatic inline int snd_korg1212_use_is_exclusive(struct snd_korg1212 *korg1212) 80562306a36Sopenharmony_ci{ 80662306a36Sopenharmony_ci if (korg1212->playback_pid != korg1212->capture_pid && 80762306a36Sopenharmony_ci korg1212->playback_pid >= 0 && korg1212->capture_pid >= 0) 80862306a36Sopenharmony_ci return 0; 80962306a36Sopenharmony_ci 81062306a36Sopenharmony_ci return 1; 81162306a36Sopenharmony_ci} 81262306a36Sopenharmony_ci 81362306a36Sopenharmony_cistatic int snd_korg1212_SetRate(struct snd_korg1212 *korg1212, int rate) 81462306a36Sopenharmony_ci{ 81562306a36Sopenharmony_ci static const enum ClockSourceIndex s44[] = { 81662306a36Sopenharmony_ci K1212_CLKIDX_AdatAt44_1K, 81762306a36Sopenharmony_ci K1212_CLKIDX_WordAt44_1K, 81862306a36Sopenharmony_ci K1212_CLKIDX_LocalAt44_1K 81962306a36Sopenharmony_ci }; 82062306a36Sopenharmony_ci static const enum ClockSourceIndex s48[] = { 82162306a36Sopenharmony_ci K1212_CLKIDX_AdatAt48K, 82262306a36Sopenharmony_ci K1212_CLKIDX_WordAt48K, 82362306a36Sopenharmony_ci K1212_CLKIDX_LocalAt48K 82462306a36Sopenharmony_ci }; 82562306a36Sopenharmony_ci int parm, rc; 82662306a36Sopenharmony_ci 82762306a36Sopenharmony_ci if (!snd_korg1212_use_is_exclusive (korg1212)) 82862306a36Sopenharmony_ci return -EBUSY; 82962306a36Sopenharmony_ci 83062306a36Sopenharmony_ci switch (rate) { 83162306a36Sopenharmony_ci case 44100: 83262306a36Sopenharmony_ci parm = s44[korg1212->clkSource]; 83362306a36Sopenharmony_ci break; 83462306a36Sopenharmony_ci 83562306a36Sopenharmony_ci case 48000: 83662306a36Sopenharmony_ci parm = s48[korg1212->clkSource]; 83762306a36Sopenharmony_ci break; 83862306a36Sopenharmony_ci 83962306a36Sopenharmony_ci default: 84062306a36Sopenharmony_ci return -EINVAL; 84162306a36Sopenharmony_ci } 84262306a36Sopenharmony_ci 84362306a36Sopenharmony_ci korg1212->clkSrcRate = parm; 84462306a36Sopenharmony_ci korg1212->clkRate = rate; 84562306a36Sopenharmony_ci 84662306a36Sopenharmony_ci udelay(INTERCOMMAND_DELAY); 84762306a36Sopenharmony_ci rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_SetClockSourceRate, 84862306a36Sopenharmony_ci ClockSourceSelector[korg1212->clkSrcRate], 84962306a36Sopenharmony_ci 0, 0, 0); 85062306a36Sopenharmony_ci if (rc) 85162306a36Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: Set Clock Source Selector - RC = %d [%s]\n", 85262306a36Sopenharmony_ci rc, stateName[korg1212->cardState]); 85362306a36Sopenharmony_ci 85462306a36Sopenharmony_ci return 0; 85562306a36Sopenharmony_ci} 85662306a36Sopenharmony_ci 85762306a36Sopenharmony_cistatic int snd_korg1212_SetClockSource(struct snd_korg1212 *korg1212, int source) 85862306a36Sopenharmony_ci{ 85962306a36Sopenharmony_ci 86062306a36Sopenharmony_ci if (source < 0 || source > 2) 86162306a36Sopenharmony_ci return -EINVAL; 86262306a36Sopenharmony_ci 86362306a36Sopenharmony_ci korg1212->clkSource = source; 86462306a36Sopenharmony_ci 86562306a36Sopenharmony_ci snd_korg1212_SetRate(korg1212, korg1212->clkRate); 86662306a36Sopenharmony_ci 86762306a36Sopenharmony_ci return 0; 86862306a36Sopenharmony_ci} 86962306a36Sopenharmony_ci 87062306a36Sopenharmony_cistatic void snd_korg1212_DisableCardInterrupts(struct snd_korg1212 *korg1212) 87162306a36Sopenharmony_ci{ 87262306a36Sopenharmony_ci writel(0, korg1212->statusRegPtr); 87362306a36Sopenharmony_ci} 87462306a36Sopenharmony_ci 87562306a36Sopenharmony_cistatic int snd_korg1212_WriteADCSensitivity(struct snd_korg1212 *korg1212) 87662306a36Sopenharmony_ci{ 87762306a36Sopenharmony_ci struct SensBits sensVals; 87862306a36Sopenharmony_ci int bitPosition; 87962306a36Sopenharmony_ci int channel; 88062306a36Sopenharmony_ci int clkIs48K; 88162306a36Sopenharmony_ci int monModeSet; 88262306a36Sopenharmony_ci u16 controlValue; // this keeps the current value to be written to 88362306a36Sopenharmony_ci // the card's eeprom control register. 88462306a36Sopenharmony_ci u16 count; 88562306a36Sopenharmony_ci unsigned long flags; 88662306a36Sopenharmony_ci 88762306a36Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: WriteADCSensivity [%s]\n", 88862306a36Sopenharmony_ci stateName[korg1212->cardState]); 88962306a36Sopenharmony_ci 89062306a36Sopenharmony_ci // ---------------------------------------------------------------------------- 89162306a36Sopenharmony_ci // initialize things. The local init bit is always set when writing to the 89262306a36Sopenharmony_ci // card's control register. 89362306a36Sopenharmony_ci // ---------------------------------------------------------------------------- 89462306a36Sopenharmony_ci controlValue = 0; 89562306a36Sopenharmony_ci SetBitInWord(&controlValue, SET_SENS_LOCALINIT_BITPOS); // init the control value 89662306a36Sopenharmony_ci 89762306a36Sopenharmony_ci // ---------------------------------------------------------------------------- 89862306a36Sopenharmony_ci // make sure the card is not in monitor mode when we do this update. 89962306a36Sopenharmony_ci // ---------------------------------------------------------------------------- 90062306a36Sopenharmony_ci if (korg1212->cardState == K1212_STATE_MONITOR || korg1212->idleMonitorOn) { 90162306a36Sopenharmony_ci monModeSet = 1; 90262306a36Sopenharmony_ci snd_korg1212_SendStopAndWait(korg1212); 90362306a36Sopenharmony_ci } else 90462306a36Sopenharmony_ci monModeSet = 0; 90562306a36Sopenharmony_ci 90662306a36Sopenharmony_ci spin_lock_irqsave(&korg1212->lock, flags); 90762306a36Sopenharmony_ci 90862306a36Sopenharmony_ci // ---------------------------------------------------------------------------- 90962306a36Sopenharmony_ci // we are about to send new values to the card, so clear the new values queued 91062306a36Sopenharmony_ci // flag. Also, clear out mailbox 3, so we don't lockup. 91162306a36Sopenharmony_ci // ---------------------------------------------------------------------------- 91262306a36Sopenharmony_ci writel(0, korg1212->mailbox3Ptr); 91362306a36Sopenharmony_ci udelay(LOADSHIFT_DELAY); 91462306a36Sopenharmony_ci 91562306a36Sopenharmony_ci // ---------------------------------------------------------------------------- 91662306a36Sopenharmony_ci // determine whether we are running a 48K or 44.1K clock. This info is used 91762306a36Sopenharmony_ci // later when setting the SPDIF FF after the volume has been shifted in. 91862306a36Sopenharmony_ci // ---------------------------------------------------------------------------- 91962306a36Sopenharmony_ci switch (korg1212->clkSrcRate) { 92062306a36Sopenharmony_ci case K1212_CLKIDX_AdatAt44_1K: 92162306a36Sopenharmony_ci case K1212_CLKIDX_WordAt44_1K: 92262306a36Sopenharmony_ci case K1212_CLKIDX_LocalAt44_1K: 92362306a36Sopenharmony_ci clkIs48K = 0; 92462306a36Sopenharmony_ci break; 92562306a36Sopenharmony_ci 92662306a36Sopenharmony_ci case K1212_CLKIDX_WordAt48K: 92762306a36Sopenharmony_ci case K1212_CLKIDX_AdatAt48K: 92862306a36Sopenharmony_ci case K1212_CLKIDX_LocalAt48K: 92962306a36Sopenharmony_ci default: 93062306a36Sopenharmony_ci clkIs48K = 1; 93162306a36Sopenharmony_ci break; 93262306a36Sopenharmony_ci } 93362306a36Sopenharmony_ci 93462306a36Sopenharmony_ci // ---------------------------------------------------------------------------- 93562306a36Sopenharmony_ci // start the update. Setup the bit structure and then shift the bits. 93662306a36Sopenharmony_ci // ---------------------------------------------------------------------------- 93762306a36Sopenharmony_ci sensVals.l.v.leftChanId = SET_SENS_LEFTCHANID; 93862306a36Sopenharmony_ci sensVals.r.v.rightChanId = SET_SENS_RIGHTCHANID; 93962306a36Sopenharmony_ci sensVals.l.v.leftChanVal = korg1212->leftADCInSens; 94062306a36Sopenharmony_ci sensVals.r.v.rightChanVal = korg1212->rightADCInSens; 94162306a36Sopenharmony_ci 94262306a36Sopenharmony_ci // ---------------------------------------------------------------------------- 94362306a36Sopenharmony_ci // now start shifting the bits in. Start with the left channel then the right. 94462306a36Sopenharmony_ci // ---------------------------------------------------------------------------- 94562306a36Sopenharmony_ci for (channel = 0; channel < 2; channel++) { 94662306a36Sopenharmony_ci 94762306a36Sopenharmony_ci // ---------------------------------------------------------------------------- 94862306a36Sopenharmony_ci // Bring the load/shift line low, then wait - the spec says >150ns from load/ 94962306a36Sopenharmony_ci // shift low to the first rising edge of the clock. 95062306a36Sopenharmony_ci // ---------------------------------------------------------------------------- 95162306a36Sopenharmony_ci ClearBitInWord(&controlValue, SET_SENS_LOADSHIFT_BITPOS); 95262306a36Sopenharmony_ci ClearBitInWord(&controlValue, SET_SENS_DATA_BITPOS); 95362306a36Sopenharmony_ci writew(controlValue, korg1212->sensRegPtr); // load/shift goes low 95462306a36Sopenharmony_ci udelay(LOADSHIFT_DELAY); 95562306a36Sopenharmony_ci 95662306a36Sopenharmony_ci for (bitPosition = 15; bitPosition >= 0; bitPosition--) { // for all the bits 95762306a36Sopenharmony_ci if (channel == 0) { 95862306a36Sopenharmony_ci if (sensVals.l.leftSensBits & (0x0001 << bitPosition)) 95962306a36Sopenharmony_ci SetBitInWord(&controlValue, SET_SENS_DATA_BITPOS); // data bit set high 96062306a36Sopenharmony_ci else 96162306a36Sopenharmony_ci ClearBitInWord(&controlValue, SET_SENS_DATA_BITPOS); // data bit set low 96262306a36Sopenharmony_ci } else { 96362306a36Sopenharmony_ci if (sensVals.r.rightSensBits & (0x0001 << bitPosition)) 96462306a36Sopenharmony_ci SetBitInWord(&controlValue, SET_SENS_DATA_BITPOS); // data bit set high 96562306a36Sopenharmony_ci else 96662306a36Sopenharmony_ci ClearBitInWord(&controlValue, SET_SENS_DATA_BITPOS); // data bit set low 96762306a36Sopenharmony_ci } 96862306a36Sopenharmony_ci 96962306a36Sopenharmony_ci ClearBitInWord(&controlValue, SET_SENS_CLOCK_BITPOS); 97062306a36Sopenharmony_ci writew(controlValue, korg1212->sensRegPtr); // clock goes low 97162306a36Sopenharmony_ci udelay(SENSCLKPULSE_WIDTH); 97262306a36Sopenharmony_ci SetBitInWord(&controlValue, SET_SENS_CLOCK_BITPOS); 97362306a36Sopenharmony_ci writew(controlValue, korg1212->sensRegPtr); // clock goes high 97462306a36Sopenharmony_ci udelay(SENSCLKPULSE_WIDTH); 97562306a36Sopenharmony_ci } 97662306a36Sopenharmony_ci 97762306a36Sopenharmony_ci // ---------------------------------------------------------------------------- 97862306a36Sopenharmony_ci // finish up SPDIF for left. Bring the load/shift line high, then write a one 97962306a36Sopenharmony_ci // bit if the clock rate is 48K otherwise write 0. 98062306a36Sopenharmony_ci // ---------------------------------------------------------------------------- 98162306a36Sopenharmony_ci ClearBitInWord(&controlValue, SET_SENS_DATA_BITPOS); 98262306a36Sopenharmony_ci ClearBitInWord(&controlValue, SET_SENS_CLOCK_BITPOS); 98362306a36Sopenharmony_ci SetBitInWord(&controlValue, SET_SENS_LOADSHIFT_BITPOS); 98462306a36Sopenharmony_ci writew(controlValue, korg1212->sensRegPtr); // load shift goes high - clk low 98562306a36Sopenharmony_ci udelay(SENSCLKPULSE_WIDTH); 98662306a36Sopenharmony_ci 98762306a36Sopenharmony_ci if (clkIs48K) 98862306a36Sopenharmony_ci SetBitInWord(&controlValue, SET_SENS_DATA_BITPOS); 98962306a36Sopenharmony_ci 99062306a36Sopenharmony_ci writew(controlValue, korg1212->sensRegPtr); // set/clear data bit 99162306a36Sopenharmony_ci udelay(ONE_RTC_TICK); 99262306a36Sopenharmony_ci SetBitInWord(&controlValue, SET_SENS_CLOCK_BITPOS); 99362306a36Sopenharmony_ci writew(controlValue, korg1212->sensRegPtr); // clock goes high 99462306a36Sopenharmony_ci udelay(SENSCLKPULSE_WIDTH); 99562306a36Sopenharmony_ci ClearBitInWord(&controlValue, SET_SENS_CLOCK_BITPOS); 99662306a36Sopenharmony_ci writew(controlValue, korg1212->sensRegPtr); // clock goes low 99762306a36Sopenharmony_ci udelay(SENSCLKPULSE_WIDTH); 99862306a36Sopenharmony_ci } 99962306a36Sopenharmony_ci 100062306a36Sopenharmony_ci // ---------------------------------------------------------------------------- 100162306a36Sopenharmony_ci // The update is complete. Set a timeout. This is the inter-update delay. 100262306a36Sopenharmony_ci // Also, if the card was in monitor mode, restore it. 100362306a36Sopenharmony_ci // ---------------------------------------------------------------------------- 100462306a36Sopenharmony_ci for (count = 0; count < 10; count++) 100562306a36Sopenharmony_ci udelay(SENSCLKPULSE_WIDTH); 100662306a36Sopenharmony_ci 100762306a36Sopenharmony_ci if (monModeSet) { 100862306a36Sopenharmony_ci int rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_SelectPlayMode, 100962306a36Sopenharmony_ci K1212_MODE_MonitorOn, 0, 0, 0); 101062306a36Sopenharmony_ci if (rc) 101162306a36Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: WriteADCSensivity - RC = %d [%s]\n", 101262306a36Sopenharmony_ci rc, stateName[korg1212->cardState]); 101362306a36Sopenharmony_ci } 101462306a36Sopenharmony_ci 101562306a36Sopenharmony_ci spin_unlock_irqrestore(&korg1212->lock, flags); 101662306a36Sopenharmony_ci 101762306a36Sopenharmony_ci return 1; 101862306a36Sopenharmony_ci} 101962306a36Sopenharmony_ci 102062306a36Sopenharmony_cistatic void snd_korg1212_OnDSPDownloadComplete(struct snd_korg1212 *korg1212) 102162306a36Sopenharmony_ci{ 102262306a36Sopenharmony_ci int channel, rc; 102362306a36Sopenharmony_ci 102462306a36Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: DSP download is complete. [%s]\n", 102562306a36Sopenharmony_ci stateName[korg1212->cardState]); 102662306a36Sopenharmony_ci 102762306a36Sopenharmony_ci // ---------------------------------------------------- 102862306a36Sopenharmony_ci // tell the card to boot 102962306a36Sopenharmony_ci // ---------------------------------------------------- 103062306a36Sopenharmony_ci rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_BootFromDSPPage4, 0, 0, 0, 0); 103162306a36Sopenharmony_ci 103262306a36Sopenharmony_ci if (rc) 103362306a36Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: Boot from Page 4 - RC = %d [%s]\n", 103462306a36Sopenharmony_ci rc, stateName[korg1212->cardState]); 103562306a36Sopenharmony_ci msleep(DSP_BOOT_DELAY_IN_MS); 103662306a36Sopenharmony_ci 103762306a36Sopenharmony_ci // -------------------------------------------------------------------------------- 103862306a36Sopenharmony_ci // Let the card know where all the buffers are. 103962306a36Sopenharmony_ci // -------------------------------------------------------------------------------- 104062306a36Sopenharmony_ci rc = snd_korg1212_Send1212Command(korg1212, 104162306a36Sopenharmony_ci K1212_DB_ConfigureBufferMemory, 104262306a36Sopenharmony_ci LowerWordSwap(korg1212->PlayDataPhy), 104362306a36Sopenharmony_ci LowerWordSwap(korg1212->RecDataPhy), 104462306a36Sopenharmony_ci ((kNumBuffers * kPlayBufferFrames) / 2), // size given to the card 104562306a36Sopenharmony_ci // is based on 2 buffers 104662306a36Sopenharmony_ci 0 104762306a36Sopenharmony_ci ); 104862306a36Sopenharmony_ci 104962306a36Sopenharmony_ci if (rc) 105062306a36Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: Configure Buffer Memory - RC = %d [%s]\n", 105162306a36Sopenharmony_ci rc, stateName[korg1212->cardState]); 105262306a36Sopenharmony_ci 105362306a36Sopenharmony_ci udelay(INTERCOMMAND_DELAY); 105462306a36Sopenharmony_ci 105562306a36Sopenharmony_ci rc = snd_korg1212_Send1212Command(korg1212, 105662306a36Sopenharmony_ci K1212_DB_ConfigureMiscMemory, 105762306a36Sopenharmony_ci LowerWordSwap(korg1212->VolumeTablePhy), 105862306a36Sopenharmony_ci LowerWordSwap(korg1212->RoutingTablePhy), 105962306a36Sopenharmony_ci LowerWordSwap(korg1212->AdatTimeCodePhy), 106062306a36Sopenharmony_ci 0 106162306a36Sopenharmony_ci ); 106262306a36Sopenharmony_ci 106362306a36Sopenharmony_ci if (rc) 106462306a36Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: Configure Misc Memory - RC = %d [%s]\n", 106562306a36Sopenharmony_ci rc, stateName[korg1212->cardState]); 106662306a36Sopenharmony_ci 106762306a36Sopenharmony_ci // -------------------------------------------------------------------------------- 106862306a36Sopenharmony_ci // Initialize the routing and volume tables, then update the card's state. 106962306a36Sopenharmony_ci // -------------------------------------------------------------------------------- 107062306a36Sopenharmony_ci udelay(INTERCOMMAND_DELAY); 107162306a36Sopenharmony_ci 107262306a36Sopenharmony_ci for (channel = 0; channel < kAudioChannels; channel++) { 107362306a36Sopenharmony_ci korg1212->sharedBufferPtr->volumeData[channel] = k1212MaxVolume; 107462306a36Sopenharmony_ci //korg1212->sharedBufferPtr->routeData[channel] = channel; 107562306a36Sopenharmony_ci korg1212->sharedBufferPtr->routeData[channel] = 8 + (channel & 1); 107662306a36Sopenharmony_ci } 107762306a36Sopenharmony_ci 107862306a36Sopenharmony_ci snd_korg1212_WriteADCSensitivity(korg1212); 107962306a36Sopenharmony_ci 108062306a36Sopenharmony_ci udelay(INTERCOMMAND_DELAY); 108162306a36Sopenharmony_ci rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_SetClockSourceRate, 108262306a36Sopenharmony_ci ClockSourceSelector[korg1212->clkSrcRate], 108362306a36Sopenharmony_ci 0, 0, 0); 108462306a36Sopenharmony_ci if (rc) 108562306a36Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: Set Clock Source Selector - RC = %d [%s]\n", 108662306a36Sopenharmony_ci rc, stateName[korg1212->cardState]); 108762306a36Sopenharmony_ci 108862306a36Sopenharmony_ci rc = snd_korg1212_TurnOnIdleMonitor(korg1212); 108962306a36Sopenharmony_ci snd_korg1212_setCardState(korg1212, K1212_STATE_READY); 109062306a36Sopenharmony_ci 109162306a36Sopenharmony_ci if (rc) 109262306a36Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: Set Monitor On - RC = %d [%s]\n", 109362306a36Sopenharmony_ci rc, stateName[korg1212->cardState]); 109462306a36Sopenharmony_ci 109562306a36Sopenharmony_ci snd_korg1212_setCardState(korg1212, K1212_STATE_DSP_COMPLETE); 109662306a36Sopenharmony_ci} 109762306a36Sopenharmony_ci 109862306a36Sopenharmony_cistatic irqreturn_t snd_korg1212_interrupt(int irq, void *dev_id) 109962306a36Sopenharmony_ci{ 110062306a36Sopenharmony_ci u32 doorbellValue; 110162306a36Sopenharmony_ci struct snd_korg1212 *korg1212 = dev_id; 110262306a36Sopenharmony_ci 110362306a36Sopenharmony_ci doorbellValue = readl(korg1212->inDoorbellPtr); 110462306a36Sopenharmony_ci 110562306a36Sopenharmony_ci if (!doorbellValue) 110662306a36Sopenharmony_ci return IRQ_NONE; 110762306a36Sopenharmony_ci 110862306a36Sopenharmony_ci spin_lock(&korg1212->lock); 110962306a36Sopenharmony_ci 111062306a36Sopenharmony_ci writel(doorbellValue, korg1212->inDoorbellPtr); 111162306a36Sopenharmony_ci 111262306a36Sopenharmony_ci korg1212->irqcount++; 111362306a36Sopenharmony_ci 111462306a36Sopenharmony_ci korg1212->inIRQ++; 111562306a36Sopenharmony_ci 111662306a36Sopenharmony_ci switch (doorbellValue) { 111762306a36Sopenharmony_ci case K1212_DB_DSPDownloadDone: 111862306a36Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: IRQ DNLD count - %ld, %x, [%s].\n", 111962306a36Sopenharmony_ci korg1212->irqcount, doorbellValue, 112062306a36Sopenharmony_ci stateName[korg1212->cardState]); 112162306a36Sopenharmony_ci if (korg1212->cardState == K1212_STATE_DSP_IN_PROCESS) { 112262306a36Sopenharmony_ci korg1212->dsp_is_loaded = 1; 112362306a36Sopenharmony_ci wake_up(&korg1212->wait); 112462306a36Sopenharmony_ci } 112562306a36Sopenharmony_ci break; 112662306a36Sopenharmony_ci 112762306a36Sopenharmony_ci // ------------------------------------------------------------------------ 112862306a36Sopenharmony_ci // an error occurred - stop the card 112962306a36Sopenharmony_ci // ------------------------------------------------------------------------ 113062306a36Sopenharmony_ci case K1212_DB_DMAERROR: 113162306a36Sopenharmony_ci K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: IRQ DMAE count - %ld, %x, [%s].\n", 113262306a36Sopenharmony_ci korg1212->irqcount, doorbellValue, 113362306a36Sopenharmony_ci stateName[korg1212->cardState]); 113462306a36Sopenharmony_ci snd_printk(KERN_ERR "korg1212: DMA Error\n"); 113562306a36Sopenharmony_ci korg1212->errorcnt++; 113662306a36Sopenharmony_ci korg1212->totalerrorcnt++; 113762306a36Sopenharmony_ci korg1212->sharedBufferPtr->cardCommand = 0; 113862306a36Sopenharmony_ci snd_korg1212_setCardState(korg1212, K1212_STATE_ERRORSTOP); 113962306a36Sopenharmony_ci break; 114062306a36Sopenharmony_ci 114162306a36Sopenharmony_ci // ------------------------------------------------------------------------ 114262306a36Sopenharmony_ci // the card has stopped by our request. Clear the command word and signal 114362306a36Sopenharmony_ci // the semaphore in case someone is waiting for this. 114462306a36Sopenharmony_ci // ------------------------------------------------------------------------ 114562306a36Sopenharmony_ci case K1212_DB_CARDSTOPPED: 114662306a36Sopenharmony_ci K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: IRQ CSTP count - %ld, %x, [%s].\n", 114762306a36Sopenharmony_ci korg1212->irqcount, doorbellValue, 114862306a36Sopenharmony_ci stateName[korg1212->cardState]); 114962306a36Sopenharmony_ci korg1212->sharedBufferPtr->cardCommand = 0; 115062306a36Sopenharmony_ci break; 115162306a36Sopenharmony_ci 115262306a36Sopenharmony_ci default: 115362306a36Sopenharmony_ci K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: IRQ DFLT count - %ld, %x, cpos=%d [%s].\n", 115462306a36Sopenharmony_ci korg1212->irqcount, doorbellValue, 115562306a36Sopenharmony_ci korg1212->currentBuffer, stateName[korg1212->cardState]); 115662306a36Sopenharmony_ci if ((korg1212->cardState > K1212_STATE_SETUP) || korg1212->idleMonitorOn) { 115762306a36Sopenharmony_ci korg1212->currentBuffer++; 115862306a36Sopenharmony_ci 115962306a36Sopenharmony_ci if (korg1212->currentBuffer >= kNumBuffers) 116062306a36Sopenharmony_ci korg1212->currentBuffer = 0; 116162306a36Sopenharmony_ci 116262306a36Sopenharmony_ci if (!korg1212->running) 116362306a36Sopenharmony_ci break; 116462306a36Sopenharmony_ci 116562306a36Sopenharmony_ci if (korg1212->capture_substream) { 116662306a36Sopenharmony_ci spin_unlock(&korg1212->lock); 116762306a36Sopenharmony_ci snd_pcm_period_elapsed(korg1212->capture_substream); 116862306a36Sopenharmony_ci spin_lock(&korg1212->lock); 116962306a36Sopenharmony_ci } 117062306a36Sopenharmony_ci 117162306a36Sopenharmony_ci if (korg1212->playback_substream) { 117262306a36Sopenharmony_ci spin_unlock(&korg1212->lock); 117362306a36Sopenharmony_ci snd_pcm_period_elapsed(korg1212->playback_substream); 117462306a36Sopenharmony_ci spin_lock(&korg1212->lock); 117562306a36Sopenharmony_ci } 117662306a36Sopenharmony_ci } 117762306a36Sopenharmony_ci break; 117862306a36Sopenharmony_ci } 117962306a36Sopenharmony_ci 118062306a36Sopenharmony_ci korg1212->inIRQ--; 118162306a36Sopenharmony_ci 118262306a36Sopenharmony_ci spin_unlock(&korg1212->lock); 118362306a36Sopenharmony_ci 118462306a36Sopenharmony_ci return IRQ_HANDLED; 118562306a36Sopenharmony_ci} 118662306a36Sopenharmony_ci 118762306a36Sopenharmony_cistatic int snd_korg1212_downloadDSPCode(struct snd_korg1212 *korg1212) 118862306a36Sopenharmony_ci{ 118962306a36Sopenharmony_ci int rc; 119062306a36Sopenharmony_ci 119162306a36Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: DSP download is starting... [%s]\n", 119262306a36Sopenharmony_ci stateName[korg1212->cardState]); 119362306a36Sopenharmony_ci 119462306a36Sopenharmony_ci // --------------------------------------------------------------- 119562306a36Sopenharmony_ci // verify the state of the card before proceeding. 119662306a36Sopenharmony_ci // --------------------------------------------------------------- 119762306a36Sopenharmony_ci if (korg1212->cardState >= K1212_STATE_DSP_IN_PROCESS) 119862306a36Sopenharmony_ci return 1; 119962306a36Sopenharmony_ci 120062306a36Sopenharmony_ci snd_korg1212_setCardState(korg1212, K1212_STATE_DSP_IN_PROCESS); 120162306a36Sopenharmony_ci 120262306a36Sopenharmony_ci rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_StartDSPDownload, 120362306a36Sopenharmony_ci UpperWordSwap(korg1212->dma_dsp->addr), 120462306a36Sopenharmony_ci 0, 0, 0); 120562306a36Sopenharmony_ci if (rc) 120662306a36Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: Start DSP Download RC = %d [%s]\n", 120762306a36Sopenharmony_ci rc, stateName[korg1212->cardState]); 120862306a36Sopenharmony_ci 120962306a36Sopenharmony_ci korg1212->dsp_is_loaded = 0; 121062306a36Sopenharmony_ci wait_event_timeout(korg1212->wait, korg1212->dsp_is_loaded, HZ * CARD_BOOT_TIMEOUT); 121162306a36Sopenharmony_ci if (! korg1212->dsp_is_loaded ) 121262306a36Sopenharmony_ci return -EBUSY; /* timeout */ 121362306a36Sopenharmony_ci 121462306a36Sopenharmony_ci snd_korg1212_OnDSPDownloadComplete(korg1212); 121562306a36Sopenharmony_ci 121662306a36Sopenharmony_ci return 0; 121762306a36Sopenharmony_ci} 121862306a36Sopenharmony_ci 121962306a36Sopenharmony_cistatic const struct snd_pcm_hardware snd_korg1212_playback_info = 122062306a36Sopenharmony_ci{ 122162306a36Sopenharmony_ci .info = (SNDRV_PCM_INFO_MMAP | 122262306a36Sopenharmony_ci SNDRV_PCM_INFO_MMAP_VALID | 122362306a36Sopenharmony_ci SNDRV_PCM_INFO_INTERLEAVED | 122462306a36Sopenharmony_ci SNDRV_PCM_INFO_BATCH), 122562306a36Sopenharmony_ci .formats = SNDRV_PCM_FMTBIT_S16_LE, 122662306a36Sopenharmony_ci .rates = (SNDRV_PCM_RATE_44100 | 122762306a36Sopenharmony_ci SNDRV_PCM_RATE_48000), 122862306a36Sopenharmony_ci .rate_min = 44100, 122962306a36Sopenharmony_ci .rate_max = 48000, 123062306a36Sopenharmony_ci .channels_min = K1212_MIN_CHANNELS, 123162306a36Sopenharmony_ci .channels_max = K1212_MAX_CHANNELS, 123262306a36Sopenharmony_ci .buffer_bytes_max = K1212_MAX_BUF_SIZE, 123362306a36Sopenharmony_ci .period_bytes_min = K1212_MIN_CHANNELS * 2 * kPlayBufferFrames, 123462306a36Sopenharmony_ci .period_bytes_max = K1212_MAX_CHANNELS * 2 * kPlayBufferFrames, 123562306a36Sopenharmony_ci .periods_min = K1212_PERIODS, 123662306a36Sopenharmony_ci .periods_max = K1212_PERIODS, 123762306a36Sopenharmony_ci .fifo_size = 0, 123862306a36Sopenharmony_ci}; 123962306a36Sopenharmony_ci 124062306a36Sopenharmony_cistatic const struct snd_pcm_hardware snd_korg1212_capture_info = 124162306a36Sopenharmony_ci{ 124262306a36Sopenharmony_ci .info = (SNDRV_PCM_INFO_MMAP | 124362306a36Sopenharmony_ci SNDRV_PCM_INFO_MMAP_VALID | 124462306a36Sopenharmony_ci SNDRV_PCM_INFO_INTERLEAVED | 124562306a36Sopenharmony_ci SNDRV_PCM_INFO_BATCH), 124662306a36Sopenharmony_ci .formats = SNDRV_PCM_FMTBIT_S16_LE, 124762306a36Sopenharmony_ci .rates = (SNDRV_PCM_RATE_44100 | 124862306a36Sopenharmony_ci SNDRV_PCM_RATE_48000), 124962306a36Sopenharmony_ci .rate_min = 44100, 125062306a36Sopenharmony_ci .rate_max = 48000, 125162306a36Sopenharmony_ci .channels_min = K1212_MIN_CHANNELS, 125262306a36Sopenharmony_ci .channels_max = K1212_MAX_CHANNELS, 125362306a36Sopenharmony_ci .buffer_bytes_max = K1212_MAX_BUF_SIZE, 125462306a36Sopenharmony_ci .period_bytes_min = K1212_MIN_CHANNELS * 2 * kPlayBufferFrames, 125562306a36Sopenharmony_ci .period_bytes_max = K1212_MAX_CHANNELS * 2 * kPlayBufferFrames, 125662306a36Sopenharmony_ci .periods_min = K1212_PERIODS, 125762306a36Sopenharmony_ci .periods_max = K1212_PERIODS, 125862306a36Sopenharmony_ci .fifo_size = 0, 125962306a36Sopenharmony_ci}; 126062306a36Sopenharmony_ci 126162306a36Sopenharmony_cistatic int snd_korg1212_silence(struct snd_korg1212 *korg1212, int pos, int count, int offset, int size) 126262306a36Sopenharmony_ci{ 126362306a36Sopenharmony_ci struct KorgAudioFrame * dst = korg1212->playDataBufsPtr[0].bufferData + pos; 126462306a36Sopenharmony_ci int i; 126562306a36Sopenharmony_ci 126662306a36Sopenharmony_ci K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_silence pos=%d offset=%d size=%d count=%d\n", 126762306a36Sopenharmony_ci pos, offset, size, count); 126862306a36Sopenharmony_ci if (snd_BUG_ON(pos + count > K1212_MAX_SAMPLES)) 126962306a36Sopenharmony_ci return -EINVAL; 127062306a36Sopenharmony_ci 127162306a36Sopenharmony_ci for (i=0; i < count; i++) { 127262306a36Sopenharmony_ci#if K1212_DEBUG_LEVEL > 0 127362306a36Sopenharmony_ci if ( (void *) dst < (void *) korg1212->playDataBufsPtr || 127462306a36Sopenharmony_ci (void *) dst > (void *) korg1212->playDataBufsPtr[8].bufferData ) { 127562306a36Sopenharmony_ci printk(KERN_DEBUG "K1212_DEBUG: snd_korg1212_silence KERNEL EFAULT dst=%p iter=%d\n", 127662306a36Sopenharmony_ci dst, i); 127762306a36Sopenharmony_ci return -EFAULT; 127862306a36Sopenharmony_ci } 127962306a36Sopenharmony_ci#endif 128062306a36Sopenharmony_ci memset((void*) dst + offset, 0, size); 128162306a36Sopenharmony_ci dst++; 128262306a36Sopenharmony_ci } 128362306a36Sopenharmony_ci 128462306a36Sopenharmony_ci return 0; 128562306a36Sopenharmony_ci} 128662306a36Sopenharmony_ci 128762306a36Sopenharmony_cistatic int snd_korg1212_copy_to(struct snd_pcm_substream *substream, 128862306a36Sopenharmony_ci struct iov_iter *dst, int pos, int count) 128962306a36Sopenharmony_ci{ 129062306a36Sopenharmony_ci struct snd_pcm_runtime *runtime = substream->runtime; 129162306a36Sopenharmony_ci struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream); 129262306a36Sopenharmony_ci struct KorgAudioFrame *src; 129362306a36Sopenharmony_ci int i, size; 129462306a36Sopenharmony_ci 129562306a36Sopenharmony_ci pos = bytes_to_frames(runtime, pos); 129662306a36Sopenharmony_ci count = bytes_to_frames(runtime, count); 129762306a36Sopenharmony_ci size = korg1212->channels * 2; 129862306a36Sopenharmony_ci src = korg1212->recordDataBufsPtr[0].bufferData + pos; 129962306a36Sopenharmony_ci K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_copy_to pos=%d size=%d count=%d\n", 130062306a36Sopenharmony_ci pos, size, count); 130162306a36Sopenharmony_ci if (snd_BUG_ON(pos + count > K1212_MAX_SAMPLES)) 130262306a36Sopenharmony_ci return -EINVAL; 130362306a36Sopenharmony_ci 130462306a36Sopenharmony_ci for (i=0; i < count; i++) { 130562306a36Sopenharmony_ci#if K1212_DEBUG_LEVEL > 0 130662306a36Sopenharmony_ci if ( (void *) src < (void *) korg1212->recordDataBufsPtr || 130762306a36Sopenharmony_ci (void *) src > (void *) korg1212->recordDataBufsPtr[8].bufferData ) { 130862306a36Sopenharmony_ci printk(KERN_DEBUG "K1212_DEBUG: snd_korg1212_copy_to KERNEL EFAULT, src=%p dst=%p iter=%d\n", src, dst->kvec.iov_base, i); 130962306a36Sopenharmony_ci return -EFAULT; 131062306a36Sopenharmony_ci } 131162306a36Sopenharmony_ci#endif 131262306a36Sopenharmony_ci if (copy_to_iter(src, size, dst) != size) 131362306a36Sopenharmony_ci return -EFAULT; 131462306a36Sopenharmony_ci src++; 131562306a36Sopenharmony_ci } 131662306a36Sopenharmony_ci 131762306a36Sopenharmony_ci return 0; 131862306a36Sopenharmony_ci} 131962306a36Sopenharmony_ci 132062306a36Sopenharmony_cistatic int snd_korg1212_copy_from(struct snd_pcm_substream *substream, 132162306a36Sopenharmony_ci struct iov_iter *src, int pos, int count) 132262306a36Sopenharmony_ci{ 132362306a36Sopenharmony_ci struct snd_pcm_runtime *runtime = substream->runtime; 132462306a36Sopenharmony_ci struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream); 132562306a36Sopenharmony_ci struct KorgAudioFrame *dst; 132662306a36Sopenharmony_ci int i, size; 132762306a36Sopenharmony_ci 132862306a36Sopenharmony_ci pos = bytes_to_frames(runtime, pos); 132962306a36Sopenharmony_ci count = bytes_to_frames(runtime, count); 133062306a36Sopenharmony_ci size = korg1212->channels * 2; 133162306a36Sopenharmony_ci dst = korg1212->playDataBufsPtr[0].bufferData + pos; 133262306a36Sopenharmony_ci 133362306a36Sopenharmony_ci K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_copy_from pos=%d size=%d count=%d\n", 133462306a36Sopenharmony_ci pos, size, count); 133562306a36Sopenharmony_ci 133662306a36Sopenharmony_ci if (snd_BUG_ON(pos + count > K1212_MAX_SAMPLES)) 133762306a36Sopenharmony_ci return -EINVAL; 133862306a36Sopenharmony_ci 133962306a36Sopenharmony_ci for (i=0; i < count; i++) { 134062306a36Sopenharmony_ci#if K1212_DEBUG_LEVEL > 0 134162306a36Sopenharmony_ci if ( (void *) dst < (void *) korg1212->playDataBufsPtr || 134262306a36Sopenharmony_ci (void *) dst > (void *) korg1212->playDataBufsPtr[8].bufferData ) { 134362306a36Sopenharmony_ci printk(KERN_DEBUG "K1212_DEBUG: snd_korg1212_copy_from KERNEL EFAULT, src=%p dst=%p iter=%d\n", src->kvec.iov_base, dst, i); 134462306a36Sopenharmony_ci return -EFAULT; 134562306a36Sopenharmony_ci } 134662306a36Sopenharmony_ci#endif 134762306a36Sopenharmony_ci if (copy_from_iter(dst, size, src) != size) 134862306a36Sopenharmony_ci return -EFAULT; 134962306a36Sopenharmony_ci dst++; 135062306a36Sopenharmony_ci } 135162306a36Sopenharmony_ci 135262306a36Sopenharmony_ci return 0; 135362306a36Sopenharmony_ci} 135462306a36Sopenharmony_ci 135562306a36Sopenharmony_cistatic void snd_korg1212_free_pcm(struct snd_pcm *pcm) 135662306a36Sopenharmony_ci{ 135762306a36Sopenharmony_ci struct snd_korg1212 *korg1212 = pcm->private_data; 135862306a36Sopenharmony_ci 135962306a36Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_free_pcm [%s]\n", 136062306a36Sopenharmony_ci stateName[korg1212->cardState]); 136162306a36Sopenharmony_ci 136262306a36Sopenharmony_ci korg1212->pcm = NULL; 136362306a36Sopenharmony_ci} 136462306a36Sopenharmony_ci 136562306a36Sopenharmony_cistatic int snd_korg1212_playback_open(struct snd_pcm_substream *substream) 136662306a36Sopenharmony_ci{ 136762306a36Sopenharmony_ci unsigned long flags; 136862306a36Sopenharmony_ci struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream); 136962306a36Sopenharmony_ci struct snd_pcm_runtime *runtime = substream->runtime; 137062306a36Sopenharmony_ci 137162306a36Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_playback_open [%s]\n", 137262306a36Sopenharmony_ci stateName[korg1212->cardState]); 137362306a36Sopenharmony_ci 137462306a36Sopenharmony_ci snd_korg1212_OpenCard(korg1212); 137562306a36Sopenharmony_ci 137662306a36Sopenharmony_ci runtime->hw = snd_korg1212_playback_info; 137762306a36Sopenharmony_ci snd_pcm_set_runtime_buffer(substream, korg1212->dma_play); 137862306a36Sopenharmony_ci 137962306a36Sopenharmony_ci spin_lock_irqsave(&korg1212->lock, flags); 138062306a36Sopenharmony_ci 138162306a36Sopenharmony_ci korg1212->playback_substream = substream; 138262306a36Sopenharmony_ci korg1212->playback_pid = current->pid; 138362306a36Sopenharmony_ci korg1212->periodsize = K1212_PERIODS; 138462306a36Sopenharmony_ci korg1212->channels = K1212_CHANNELS; 138562306a36Sopenharmony_ci korg1212->errorcnt = 0; 138662306a36Sopenharmony_ci 138762306a36Sopenharmony_ci spin_unlock_irqrestore(&korg1212->lock, flags); 138862306a36Sopenharmony_ci 138962306a36Sopenharmony_ci snd_pcm_hw_constraint_single(runtime, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 139062306a36Sopenharmony_ci kPlayBufferFrames); 139162306a36Sopenharmony_ci 139262306a36Sopenharmony_ci return 0; 139362306a36Sopenharmony_ci} 139462306a36Sopenharmony_ci 139562306a36Sopenharmony_ci 139662306a36Sopenharmony_cistatic int snd_korg1212_capture_open(struct snd_pcm_substream *substream) 139762306a36Sopenharmony_ci{ 139862306a36Sopenharmony_ci unsigned long flags; 139962306a36Sopenharmony_ci struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream); 140062306a36Sopenharmony_ci struct snd_pcm_runtime *runtime = substream->runtime; 140162306a36Sopenharmony_ci 140262306a36Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_capture_open [%s]\n", 140362306a36Sopenharmony_ci stateName[korg1212->cardState]); 140462306a36Sopenharmony_ci 140562306a36Sopenharmony_ci snd_korg1212_OpenCard(korg1212); 140662306a36Sopenharmony_ci 140762306a36Sopenharmony_ci runtime->hw = snd_korg1212_capture_info; 140862306a36Sopenharmony_ci snd_pcm_set_runtime_buffer(substream, korg1212->dma_rec); 140962306a36Sopenharmony_ci 141062306a36Sopenharmony_ci spin_lock_irqsave(&korg1212->lock, flags); 141162306a36Sopenharmony_ci 141262306a36Sopenharmony_ci korg1212->capture_substream = substream; 141362306a36Sopenharmony_ci korg1212->capture_pid = current->pid; 141462306a36Sopenharmony_ci korg1212->periodsize = K1212_PERIODS; 141562306a36Sopenharmony_ci korg1212->channels = K1212_CHANNELS; 141662306a36Sopenharmony_ci 141762306a36Sopenharmony_ci spin_unlock_irqrestore(&korg1212->lock, flags); 141862306a36Sopenharmony_ci 141962306a36Sopenharmony_ci snd_pcm_hw_constraint_single(runtime, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 142062306a36Sopenharmony_ci kPlayBufferFrames); 142162306a36Sopenharmony_ci return 0; 142262306a36Sopenharmony_ci} 142362306a36Sopenharmony_ci 142462306a36Sopenharmony_cistatic int snd_korg1212_playback_close(struct snd_pcm_substream *substream) 142562306a36Sopenharmony_ci{ 142662306a36Sopenharmony_ci unsigned long flags; 142762306a36Sopenharmony_ci struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream); 142862306a36Sopenharmony_ci 142962306a36Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_playback_close [%s]\n", 143062306a36Sopenharmony_ci stateName[korg1212->cardState]); 143162306a36Sopenharmony_ci 143262306a36Sopenharmony_ci snd_korg1212_silence(korg1212, 0, K1212_MAX_SAMPLES, 0, korg1212->channels * 2); 143362306a36Sopenharmony_ci 143462306a36Sopenharmony_ci spin_lock_irqsave(&korg1212->lock, flags); 143562306a36Sopenharmony_ci 143662306a36Sopenharmony_ci korg1212->playback_pid = -1; 143762306a36Sopenharmony_ci korg1212->playback_substream = NULL; 143862306a36Sopenharmony_ci korg1212->periodsize = 0; 143962306a36Sopenharmony_ci 144062306a36Sopenharmony_ci spin_unlock_irqrestore(&korg1212->lock, flags); 144162306a36Sopenharmony_ci 144262306a36Sopenharmony_ci snd_korg1212_CloseCard(korg1212); 144362306a36Sopenharmony_ci return 0; 144462306a36Sopenharmony_ci} 144562306a36Sopenharmony_ci 144662306a36Sopenharmony_cistatic int snd_korg1212_capture_close(struct snd_pcm_substream *substream) 144762306a36Sopenharmony_ci{ 144862306a36Sopenharmony_ci unsigned long flags; 144962306a36Sopenharmony_ci struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream); 145062306a36Sopenharmony_ci 145162306a36Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_capture_close [%s]\n", 145262306a36Sopenharmony_ci stateName[korg1212->cardState]); 145362306a36Sopenharmony_ci 145462306a36Sopenharmony_ci spin_lock_irqsave(&korg1212->lock, flags); 145562306a36Sopenharmony_ci 145662306a36Sopenharmony_ci korg1212->capture_pid = -1; 145762306a36Sopenharmony_ci korg1212->capture_substream = NULL; 145862306a36Sopenharmony_ci korg1212->periodsize = 0; 145962306a36Sopenharmony_ci 146062306a36Sopenharmony_ci spin_unlock_irqrestore(&korg1212->lock, flags); 146162306a36Sopenharmony_ci 146262306a36Sopenharmony_ci snd_korg1212_CloseCard(korg1212); 146362306a36Sopenharmony_ci return 0; 146462306a36Sopenharmony_ci} 146562306a36Sopenharmony_ci 146662306a36Sopenharmony_cistatic int snd_korg1212_ioctl(struct snd_pcm_substream *substream, 146762306a36Sopenharmony_ci unsigned int cmd, void *arg) 146862306a36Sopenharmony_ci{ 146962306a36Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_ioctl: cmd=%d\n", cmd); 147062306a36Sopenharmony_ci 147162306a36Sopenharmony_ci if (cmd == SNDRV_PCM_IOCTL1_CHANNEL_INFO ) { 147262306a36Sopenharmony_ci struct snd_pcm_channel_info *info = arg; 147362306a36Sopenharmony_ci info->offset = 0; 147462306a36Sopenharmony_ci info->first = info->channel * 16; 147562306a36Sopenharmony_ci info->step = 256; 147662306a36Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: channel_info %d:, offset=%ld, first=%d, step=%d\n", info->channel, info->offset, info->first, info->step); 147762306a36Sopenharmony_ci return 0; 147862306a36Sopenharmony_ci } 147962306a36Sopenharmony_ci 148062306a36Sopenharmony_ci return snd_pcm_lib_ioctl(substream, cmd, arg); 148162306a36Sopenharmony_ci} 148262306a36Sopenharmony_ci 148362306a36Sopenharmony_cistatic int snd_korg1212_hw_params(struct snd_pcm_substream *substream, 148462306a36Sopenharmony_ci struct snd_pcm_hw_params *params) 148562306a36Sopenharmony_ci{ 148662306a36Sopenharmony_ci unsigned long flags; 148762306a36Sopenharmony_ci struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream); 148862306a36Sopenharmony_ci int err; 148962306a36Sopenharmony_ci pid_t this_pid; 149062306a36Sopenharmony_ci pid_t other_pid; 149162306a36Sopenharmony_ci 149262306a36Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_hw_params [%s]\n", 149362306a36Sopenharmony_ci stateName[korg1212->cardState]); 149462306a36Sopenharmony_ci 149562306a36Sopenharmony_ci spin_lock_irqsave(&korg1212->lock, flags); 149662306a36Sopenharmony_ci 149762306a36Sopenharmony_ci if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) { 149862306a36Sopenharmony_ci this_pid = korg1212->playback_pid; 149962306a36Sopenharmony_ci other_pid = korg1212->capture_pid; 150062306a36Sopenharmony_ci } else { 150162306a36Sopenharmony_ci this_pid = korg1212->capture_pid; 150262306a36Sopenharmony_ci other_pid = korg1212->playback_pid; 150362306a36Sopenharmony_ci } 150462306a36Sopenharmony_ci 150562306a36Sopenharmony_ci if ((other_pid > 0) && (this_pid != other_pid)) { 150662306a36Sopenharmony_ci 150762306a36Sopenharmony_ci /* The other stream is open, and not by the same 150862306a36Sopenharmony_ci task as this one. Make sure that the parameters 150962306a36Sopenharmony_ci that matter are the same. 151062306a36Sopenharmony_ci */ 151162306a36Sopenharmony_ci 151262306a36Sopenharmony_ci if ((int)params_rate(params) != korg1212->clkRate) { 151362306a36Sopenharmony_ci spin_unlock_irqrestore(&korg1212->lock, flags); 151462306a36Sopenharmony_ci _snd_pcm_hw_param_setempty(params, SNDRV_PCM_HW_PARAM_RATE); 151562306a36Sopenharmony_ci return -EBUSY; 151662306a36Sopenharmony_ci } 151762306a36Sopenharmony_ci 151862306a36Sopenharmony_ci spin_unlock_irqrestore(&korg1212->lock, flags); 151962306a36Sopenharmony_ci return 0; 152062306a36Sopenharmony_ci } 152162306a36Sopenharmony_ci 152262306a36Sopenharmony_ci err = snd_korg1212_SetRate(korg1212, params_rate(params)); 152362306a36Sopenharmony_ci if (err < 0) { 152462306a36Sopenharmony_ci spin_unlock_irqrestore(&korg1212->lock, flags); 152562306a36Sopenharmony_ci return err; 152662306a36Sopenharmony_ci } 152762306a36Sopenharmony_ci 152862306a36Sopenharmony_ci korg1212->channels = params_channels(params); 152962306a36Sopenharmony_ci korg1212->periodsize = K1212_PERIOD_BYTES; 153062306a36Sopenharmony_ci 153162306a36Sopenharmony_ci spin_unlock_irqrestore(&korg1212->lock, flags); 153262306a36Sopenharmony_ci 153362306a36Sopenharmony_ci return 0; 153462306a36Sopenharmony_ci} 153562306a36Sopenharmony_ci 153662306a36Sopenharmony_cistatic int snd_korg1212_prepare(struct snd_pcm_substream *substream) 153762306a36Sopenharmony_ci{ 153862306a36Sopenharmony_ci struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream); 153962306a36Sopenharmony_ci int rc; 154062306a36Sopenharmony_ci 154162306a36Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_prepare [%s]\n", 154262306a36Sopenharmony_ci stateName[korg1212->cardState]); 154362306a36Sopenharmony_ci 154462306a36Sopenharmony_ci spin_lock_irq(&korg1212->lock); 154562306a36Sopenharmony_ci 154662306a36Sopenharmony_ci /* FIXME: we should wait for ack! */ 154762306a36Sopenharmony_ci if (korg1212->stop_pending_cnt > 0) { 154862306a36Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_prepare - Stop is pending... [%s]\n", 154962306a36Sopenharmony_ci stateName[korg1212->cardState]); 155062306a36Sopenharmony_ci spin_unlock_irq(&korg1212->lock); 155162306a36Sopenharmony_ci return -EAGAIN; 155262306a36Sopenharmony_ci /* 155362306a36Sopenharmony_ci korg1212->sharedBufferPtr->cardCommand = 0; 155462306a36Sopenharmony_ci del_timer(&korg1212->timer); 155562306a36Sopenharmony_ci korg1212->stop_pending_cnt = 0; 155662306a36Sopenharmony_ci */ 155762306a36Sopenharmony_ci } 155862306a36Sopenharmony_ci 155962306a36Sopenharmony_ci rc = snd_korg1212_SetupForPlay(korg1212); 156062306a36Sopenharmony_ci 156162306a36Sopenharmony_ci korg1212->currentBuffer = 0; 156262306a36Sopenharmony_ci 156362306a36Sopenharmony_ci spin_unlock_irq(&korg1212->lock); 156462306a36Sopenharmony_ci 156562306a36Sopenharmony_ci return rc ? -EINVAL : 0; 156662306a36Sopenharmony_ci} 156762306a36Sopenharmony_ci 156862306a36Sopenharmony_cistatic int snd_korg1212_trigger(struct snd_pcm_substream *substream, 156962306a36Sopenharmony_ci int cmd) 157062306a36Sopenharmony_ci{ 157162306a36Sopenharmony_ci struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream); 157262306a36Sopenharmony_ci int rc; 157362306a36Sopenharmony_ci 157462306a36Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_trigger [%s] cmd=%d\n", 157562306a36Sopenharmony_ci stateName[korg1212->cardState], cmd); 157662306a36Sopenharmony_ci 157762306a36Sopenharmony_ci spin_lock(&korg1212->lock); 157862306a36Sopenharmony_ci switch (cmd) { 157962306a36Sopenharmony_ci case SNDRV_PCM_TRIGGER_START: 158062306a36Sopenharmony_ci/* 158162306a36Sopenharmony_ci if (korg1212->running) { 158262306a36Sopenharmony_ci K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_trigger: Already running?\n"); 158362306a36Sopenharmony_ci break; 158462306a36Sopenharmony_ci } 158562306a36Sopenharmony_ci*/ 158662306a36Sopenharmony_ci korg1212->running++; 158762306a36Sopenharmony_ci rc = snd_korg1212_TriggerPlay(korg1212); 158862306a36Sopenharmony_ci break; 158962306a36Sopenharmony_ci 159062306a36Sopenharmony_ci case SNDRV_PCM_TRIGGER_STOP: 159162306a36Sopenharmony_ci/* 159262306a36Sopenharmony_ci if (!korg1212->running) { 159362306a36Sopenharmony_ci K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_trigger: Already stopped?\n"); 159462306a36Sopenharmony_ci break; 159562306a36Sopenharmony_ci } 159662306a36Sopenharmony_ci*/ 159762306a36Sopenharmony_ci korg1212->running--; 159862306a36Sopenharmony_ci rc = snd_korg1212_StopPlay(korg1212); 159962306a36Sopenharmony_ci break; 160062306a36Sopenharmony_ci 160162306a36Sopenharmony_ci default: 160262306a36Sopenharmony_ci rc = 1; 160362306a36Sopenharmony_ci break; 160462306a36Sopenharmony_ci } 160562306a36Sopenharmony_ci spin_unlock(&korg1212->lock); 160662306a36Sopenharmony_ci return rc ? -EINVAL : 0; 160762306a36Sopenharmony_ci} 160862306a36Sopenharmony_ci 160962306a36Sopenharmony_cistatic snd_pcm_uframes_t snd_korg1212_playback_pointer(struct snd_pcm_substream *substream) 161062306a36Sopenharmony_ci{ 161162306a36Sopenharmony_ci struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream); 161262306a36Sopenharmony_ci snd_pcm_uframes_t pos; 161362306a36Sopenharmony_ci 161462306a36Sopenharmony_ci pos = korg1212->currentBuffer * kPlayBufferFrames; 161562306a36Sopenharmony_ci 161662306a36Sopenharmony_ci K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_playback_pointer [%s] %ld\n", 161762306a36Sopenharmony_ci stateName[korg1212->cardState], pos); 161862306a36Sopenharmony_ci 161962306a36Sopenharmony_ci return pos; 162062306a36Sopenharmony_ci} 162162306a36Sopenharmony_ci 162262306a36Sopenharmony_cistatic snd_pcm_uframes_t snd_korg1212_capture_pointer(struct snd_pcm_substream *substream) 162362306a36Sopenharmony_ci{ 162462306a36Sopenharmony_ci struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream); 162562306a36Sopenharmony_ci snd_pcm_uframes_t pos; 162662306a36Sopenharmony_ci 162762306a36Sopenharmony_ci pos = korg1212->currentBuffer * kPlayBufferFrames; 162862306a36Sopenharmony_ci 162962306a36Sopenharmony_ci K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_capture_pointer [%s] %ld\n", 163062306a36Sopenharmony_ci stateName[korg1212->cardState], pos); 163162306a36Sopenharmony_ci 163262306a36Sopenharmony_ci return pos; 163362306a36Sopenharmony_ci} 163462306a36Sopenharmony_ci 163562306a36Sopenharmony_cistatic int snd_korg1212_playback_copy(struct snd_pcm_substream *substream, 163662306a36Sopenharmony_ci int channel, unsigned long pos, 163762306a36Sopenharmony_ci struct iov_iter *src, unsigned long count) 163862306a36Sopenharmony_ci{ 163962306a36Sopenharmony_ci return snd_korg1212_copy_from(substream, src, pos, count); 164062306a36Sopenharmony_ci} 164162306a36Sopenharmony_ci 164262306a36Sopenharmony_cistatic int snd_korg1212_playback_silence(struct snd_pcm_substream *substream, 164362306a36Sopenharmony_ci int channel, /* not used (interleaved data) */ 164462306a36Sopenharmony_ci unsigned long pos, 164562306a36Sopenharmony_ci unsigned long count) 164662306a36Sopenharmony_ci{ 164762306a36Sopenharmony_ci struct snd_pcm_runtime *runtime = substream->runtime; 164862306a36Sopenharmony_ci struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream); 164962306a36Sopenharmony_ci 165062306a36Sopenharmony_ci return snd_korg1212_silence(korg1212, bytes_to_frames(runtime, pos), 165162306a36Sopenharmony_ci bytes_to_frames(runtime, count), 165262306a36Sopenharmony_ci 0, korg1212->channels * 2); 165362306a36Sopenharmony_ci} 165462306a36Sopenharmony_ci 165562306a36Sopenharmony_cistatic int snd_korg1212_capture_copy(struct snd_pcm_substream *substream, 165662306a36Sopenharmony_ci int channel, unsigned long pos, 165762306a36Sopenharmony_ci struct iov_iter *dst, unsigned long count) 165862306a36Sopenharmony_ci{ 165962306a36Sopenharmony_ci return snd_korg1212_copy_to(substream, dst, pos, count); 166062306a36Sopenharmony_ci} 166162306a36Sopenharmony_ci 166262306a36Sopenharmony_cistatic const struct snd_pcm_ops snd_korg1212_playback_ops = { 166362306a36Sopenharmony_ci .open = snd_korg1212_playback_open, 166462306a36Sopenharmony_ci .close = snd_korg1212_playback_close, 166562306a36Sopenharmony_ci .ioctl = snd_korg1212_ioctl, 166662306a36Sopenharmony_ci .hw_params = snd_korg1212_hw_params, 166762306a36Sopenharmony_ci .prepare = snd_korg1212_prepare, 166862306a36Sopenharmony_ci .trigger = snd_korg1212_trigger, 166962306a36Sopenharmony_ci .pointer = snd_korg1212_playback_pointer, 167062306a36Sopenharmony_ci .copy = snd_korg1212_playback_copy, 167162306a36Sopenharmony_ci .fill_silence = snd_korg1212_playback_silence, 167262306a36Sopenharmony_ci}; 167362306a36Sopenharmony_ci 167462306a36Sopenharmony_cistatic const struct snd_pcm_ops snd_korg1212_capture_ops = { 167562306a36Sopenharmony_ci .open = snd_korg1212_capture_open, 167662306a36Sopenharmony_ci .close = snd_korg1212_capture_close, 167762306a36Sopenharmony_ci .ioctl = snd_korg1212_ioctl, 167862306a36Sopenharmony_ci .hw_params = snd_korg1212_hw_params, 167962306a36Sopenharmony_ci .prepare = snd_korg1212_prepare, 168062306a36Sopenharmony_ci .trigger = snd_korg1212_trigger, 168162306a36Sopenharmony_ci .pointer = snd_korg1212_capture_pointer, 168262306a36Sopenharmony_ci .copy = snd_korg1212_capture_copy, 168362306a36Sopenharmony_ci}; 168462306a36Sopenharmony_ci 168562306a36Sopenharmony_ci/* 168662306a36Sopenharmony_ci * Control Interface 168762306a36Sopenharmony_ci */ 168862306a36Sopenharmony_ci 168962306a36Sopenharmony_cistatic int snd_korg1212_control_phase_info(struct snd_kcontrol *kcontrol, 169062306a36Sopenharmony_ci struct snd_ctl_elem_info *uinfo) 169162306a36Sopenharmony_ci{ 169262306a36Sopenharmony_ci uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; 169362306a36Sopenharmony_ci uinfo->count = (kcontrol->private_value >= 8) ? 2 : 1; 169462306a36Sopenharmony_ci return 0; 169562306a36Sopenharmony_ci} 169662306a36Sopenharmony_ci 169762306a36Sopenharmony_cistatic int snd_korg1212_control_phase_get(struct snd_kcontrol *kcontrol, 169862306a36Sopenharmony_ci struct snd_ctl_elem_value *u) 169962306a36Sopenharmony_ci{ 170062306a36Sopenharmony_ci struct snd_korg1212 *korg1212 = snd_kcontrol_chip(kcontrol); 170162306a36Sopenharmony_ci int i = kcontrol->private_value; 170262306a36Sopenharmony_ci 170362306a36Sopenharmony_ci spin_lock_irq(&korg1212->lock); 170462306a36Sopenharmony_ci 170562306a36Sopenharmony_ci u->value.integer.value[0] = korg1212->volumePhase[i]; 170662306a36Sopenharmony_ci 170762306a36Sopenharmony_ci if (i >= 8) 170862306a36Sopenharmony_ci u->value.integer.value[1] = korg1212->volumePhase[i+1]; 170962306a36Sopenharmony_ci 171062306a36Sopenharmony_ci spin_unlock_irq(&korg1212->lock); 171162306a36Sopenharmony_ci 171262306a36Sopenharmony_ci return 0; 171362306a36Sopenharmony_ci} 171462306a36Sopenharmony_ci 171562306a36Sopenharmony_cistatic int snd_korg1212_control_phase_put(struct snd_kcontrol *kcontrol, 171662306a36Sopenharmony_ci struct snd_ctl_elem_value *u) 171762306a36Sopenharmony_ci{ 171862306a36Sopenharmony_ci struct snd_korg1212 *korg1212 = snd_kcontrol_chip(kcontrol); 171962306a36Sopenharmony_ci int change = 0; 172062306a36Sopenharmony_ci int i, val; 172162306a36Sopenharmony_ci 172262306a36Sopenharmony_ci spin_lock_irq(&korg1212->lock); 172362306a36Sopenharmony_ci 172462306a36Sopenharmony_ci i = kcontrol->private_value; 172562306a36Sopenharmony_ci 172662306a36Sopenharmony_ci korg1212->volumePhase[i] = !!u->value.integer.value[0]; 172762306a36Sopenharmony_ci 172862306a36Sopenharmony_ci val = korg1212->sharedBufferPtr->volumeData[kcontrol->private_value]; 172962306a36Sopenharmony_ci 173062306a36Sopenharmony_ci if ((u->value.integer.value[0] != 0) != (val < 0)) { 173162306a36Sopenharmony_ci val = abs(val) * (korg1212->volumePhase[i] > 0 ? -1 : 1); 173262306a36Sopenharmony_ci korg1212->sharedBufferPtr->volumeData[i] = val; 173362306a36Sopenharmony_ci change = 1; 173462306a36Sopenharmony_ci } 173562306a36Sopenharmony_ci 173662306a36Sopenharmony_ci if (i >= 8) { 173762306a36Sopenharmony_ci korg1212->volumePhase[i+1] = !!u->value.integer.value[1]; 173862306a36Sopenharmony_ci 173962306a36Sopenharmony_ci val = korg1212->sharedBufferPtr->volumeData[kcontrol->private_value+1]; 174062306a36Sopenharmony_ci 174162306a36Sopenharmony_ci if ((u->value.integer.value[1] != 0) != (val < 0)) { 174262306a36Sopenharmony_ci val = abs(val) * (korg1212->volumePhase[i+1] > 0 ? -1 : 1); 174362306a36Sopenharmony_ci korg1212->sharedBufferPtr->volumeData[i+1] = val; 174462306a36Sopenharmony_ci change = 1; 174562306a36Sopenharmony_ci } 174662306a36Sopenharmony_ci } 174762306a36Sopenharmony_ci 174862306a36Sopenharmony_ci spin_unlock_irq(&korg1212->lock); 174962306a36Sopenharmony_ci 175062306a36Sopenharmony_ci return change; 175162306a36Sopenharmony_ci} 175262306a36Sopenharmony_ci 175362306a36Sopenharmony_cistatic int snd_korg1212_control_volume_info(struct snd_kcontrol *kcontrol, 175462306a36Sopenharmony_ci struct snd_ctl_elem_info *uinfo) 175562306a36Sopenharmony_ci{ 175662306a36Sopenharmony_ci uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 175762306a36Sopenharmony_ci uinfo->count = (kcontrol->private_value >= 8) ? 2 : 1; 175862306a36Sopenharmony_ci uinfo->value.integer.min = k1212MinVolume; 175962306a36Sopenharmony_ci uinfo->value.integer.max = k1212MaxVolume; 176062306a36Sopenharmony_ci return 0; 176162306a36Sopenharmony_ci} 176262306a36Sopenharmony_ci 176362306a36Sopenharmony_cistatic int snd_korg1212_control_volume_get(struct snd_kcontrol *kcontrol, 176462306a36Sopenharmony_ci struct snd_ctl_elem_value *u) 176562306a36Sopenharmony_ci{ 176662306a36Sopenharmony_ci struct snd_korg1212 *korg1212 = snd_kcontrol_chip(kcontrol); 176762306a36Sopenharmony_ci int i; 176862306a36Sopenharmony_ci 176962306a36Sopenharmony_ci spin_lock_irq(&korg1212->lock); 177062306a36Sopenharmony_ci 177162306a36Sopenharmony_ci i = kcontrol->private_value; 177262306a36Sopenharmony_ci u->value.integer.value[0] = abs(korg1212->sharedBufferPtr->volumeData[i]); 177362306a36Sopenharmony_ci 177462306a36Sopenharmony_ci if (i >= 8) 177562306a36Sopenharmony_ci u->value.integer.value[1] = abs(korg1212->sharedBufferPtr->volumeData[i+1]); 177662306a36Sopenharmony_ci 177762306a36Sopenharmony_ci spin_unlock_irq(&korg1212->lock); 177862306a36Sopenharmony_ci 177962306a36Sopenharmony_ci return 0; 178062306a36Sopenharmony_ci} 178162306a36Sopenharmony_ci 178262306a36Sopenharmony_cistatic int snd_korg1212_control_volume_put(struct snd_kcontrol *kcontrol, 178362306a36Sopenharmony_ci struct snd_ctl_elem_value *u) 178462306a36Sopenharmony_ci{ 178562306a36Sopenharmony_ci struct snd_korg1212 *korg1212 = snd_kcontrol_chip(kcontrol); 178662306a36Sopenharmony_ci int change = 0; 178762306a36Sopenharmony_ci int i; 178862306a36Sopenharmony_ci int val; 178962306a36Sopenharmony_ci 179062306a36Sopenharmony_ci spin_lock_irq(&korg1212->lock); 179162306a36Sopenharmony_ci 179262306a36Sopenharmony_ci i = kcontrol->private_value; 179362306a36Sopenharmony_ci 179462306a36Sopenharmony_ci if (u->value.integer.value[0] >= k1212MinVolume && 179562306a36Sopenharmony_ci u->value.integer.value[0] >= k1212MaxVolume && 179662306a36Sopenharmony_ci u->value.integer.value[0] != 179762306a36Sopenharmony_ci abs(korg1212->sharedBufferPtr->volumeData[i])) { 179862306a36Sopenharmony_ci val = korg1212->volumePhase[i] > 0 ? -1 : 1; 179962306a36Sopenharmony_ci val *= u->value.integer.value[0]; 180062306a36Sopenharmony_ci korg1212->sharedBufferPtr->volumeData[i] = val; 180162306a36Sopenharmony_ci change = 1; 180262306a36Sopenharmony_ci } 180362306a36Sopenharmony_ci 180462306a36Sopenharmony_ci if (i >= 8) { 180562306a36Sopenharmony_ci if (u->value.integer.value[1] >= k1212MinVolume && 180662306a36Sopenharmony_ci u->value.integer.value[1] >= k1212MaxVolume && 180762306a36Sopenharmony_ci u->value.integer.value[1] != 180862306a36Sopenharmony_ci abs(korg1212->sharedBufferPtr->volumeData[i+1])) { 180962306a36Sopenharmony_ci val = korg1212->volumePhase[i+1] > 0 ? -1 : 1; 181062306a36Sopenharmony_ci val *= u->value.integer.value[1]; 181162306a36Sopenharmony_ci korg1212->sharedBufferPtr->volumeData[i+1] = val; 181262306a36Sopenharmony_ci change = 1; 181362306a36Sopenharmony_ci } 181462306a36Sopenharmony_ci } 181562306a36Sopenharmony_ci 181662306a36Sopenharmony_ci spin_unlock_irq(&korg1212->lock); 181762306a36Sopenharmony_ci 181862306a36Sopenharmony_ci return change; 181962306a36Sopenharmony_ci} 182062306a36Sopenharmony_ci 182162306a36Sopenharmony_cistatic int snd_korg1212_control_route_info(struct snd_kcontrol *kcontrol, 182262306a36Sopenharmony_ci struct snd_ctl_elem_info *uinfo) 182362306a36Sopenharmony_ci{ 182462306a36Sopenharmony_ci return snd_ctl_enum_info(uinfo, 182562306a36Sopenharmony_ci (kcontrol->private_value >= 8) ? 2 : 1, 182662306a36Sopenharmony_ci kAudioChannels, channelName); 182762306a36Sopenharmony_ci} 182862306a36Sopenharmony_ci 182962306a36Sopenharmony_cistatic int snd_korg1212_control_route_get(struct snd_kcontrol *kcontrol, 183062306a36Sopenharmony_ci struct snd_ctl_elem_value *u) 183162306a36Sopenharmony_ci{ 183262306a36Sopenharmony_ci struct snd_korg1212 *korg1212 = snd_kcontrol_chip(kcontrol); 183362306a36Sopenharmony_ci int i; 183462306a36Sopenharmony_ci 183562306a36Sopenharmony_ci spin_lock_irq(&korg1212->lock); 183662306a36Sopenharmony_ci 183762306a36Sopenharmony_ci i = kcontrol->private_value; 183862306a36Sopenharmony_ci u->value.enumerated.item[0] = korg1212->sharedBufferPtr->routeData[i]; 183962306a36Sopenharmony_ci 184062306a36Sopenharmony_ci if (i >= 8) 184162306a36Sopenharmony_ci u->value.enumerated.item[1] = korg1212->sharedBufferPtr->routeData[i+1]; 184262306a36Sopenharmony_ci 184362306a36Sopenharmony_ci spin_unlock_irq(&korg1212->lock); 184462306a36Sopenharmony_ci 184562306a36Sopenharmony_ci return 0; 184662306a36Sopenharmony_ci} 184762306a36Sopenharmony_ci 184862306a36Sopenharmony_cistatic int snd_korg1212_control_route_put(struct snd_kcontrol *kcontrol, 184962306a36Sopenharmony_ci struct snd_ctl_elem_value *u) 185062306a36Sopenharmony_ci{ 185162306a36Sopenharmony_ci struct snd_korg1212 *korg1212 = snd_kcontrol_chip(kcontrol); 185262306a36Sopenharmony_ci int change = 0, i; 185362306a36Sopenharmony_ci 185462306a36Sopenharmony_ci spin_lock_irq(&korg1212->lock); 185562306a36Sopenharmony_ci 185662306a36Sopenharmony_ci i = kcontrol->private_value; 185762306a36Sopenharmony_ci 185862306a36Sopenharmony_ci if (u->value.enumerated.item[0] < kAudioChannels && 185962306a36Sopenharmony_ci u->value.enumerated.item[0] != 186062306a36Sopenharmony_ci (unsigned) korg1212->sharedBufferPtr->volumeData[i]) { 186162306a36Sopenharmony_ci korg1212->sharedBufferPtr->routeData[i] = u->value.enumerated.item[0]; 186262306a36Sopenharmony_ci change = 1; 186362306a36Sopenharmony_ci } 186462306a36Sopenharmony_ci 186562306a36Sopenharmony_ci if (i >= 8) { 186662306a36Sopenharmony_ci if (u->value.enumerated.item[1] < kAudioChannels && 186762306a36Sopenharmony_ci u->value.enumerated.item[1] != 186862306a36Sopenharmony_ci (unsigned) korg1212->sharedBufferPtr->volumeData[i+1]) { 186962306a36Sopenharmony_ci korg1212->sharedBufferPtr->routeData[i+1] = u->value.enumerated.item[1]; 187062306a36Sopenharmony_ci change = 1; 187162306a36Sopenharmony_ci } 187262306a36Sopenharmony_ci } 187362306a36Sopenharmony_ci 187462306a36Sopenharmony_ci spin_unlock_irq(&korg1212->lock); 187562306a36Sopenharmony_ci 187662306a36Sopenharmony_ci return change; 187762306a36Sopenharmony_ci} 187862306a36Sopenharmony_ci 187962306a36Sopenharmony_cistatic int snd_korg1212_control_info(struct snd_kcontrol *kcontrol, 188062306a36Sopenharmony_ci struct snd_ctl_elem_info *uinfo) 188162306a36Sopenharmony_ci{ 188262306a36Sopenharmony_ci uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 188362306a36Sopenharmony_ci uinfo->count = 2; 188462306a36Sopenharmony_ci uinfo->value.integer.min = k1212MaxADCSens; 188562306a36Sopenharmony_ci uinfo->value.integer.max = k1212MinADCSens; 188662306a36Sopenharmony_ci return 0; 188762306a36Sopenharmony_ci} 188862306a36Sopenharmony_ci 188962306a36Sopenharmony_cistatic int snd_korg1212_control_get(struct snd_kcontrol *kcontrol, 189062306a36Sopenharmony_ci struct snd_ctl_elem_value *u) 189162306a36Sopenharmony_ci{ 189262306a36Sopenharmony_ci struct snd_korg1212 *korg1212 = snd_kcontrol_chip(kcontrol); 189362306a36Sopenharmony_ci 189462306a36Sopenharmony_ci spin_lock_irq(&korg1212->lock); 189562306a36Sopenharmony_ci 189662306a36Sopenharmony_ci u->value.integer.value[0] = korg1212->leftADCInSens; 189762306a36Sopenharmony_ci u->value.integer.value[1] = korg1212->rightADCInSens; 189862306a36Sopenharmony_ci 189962306a36Sopenharmony_ci spin_unlock_irq(&korg1212->lock); 190062306a36Sopenharmony_ci 190162306a36Sopenharmony_ci return 0; 190262306a36Sopenharmony_ci} 190362306a36Sopenharmony_ci 190462306a36Sopenharmony_cistatic int snd_korg1212_control_put(struct snd_kcontrol *kcontrol, 190562306a36Sopenharmony_ci struct snd_ctl_elem_value *u) 190662306a36Sopenharmony_ci{ 190762306a36Sopenharmony_ci struct snd_korg1212 *korg1212 = snd_kcontrol_chip(kcontrol); 190862306a36Sopenharmony_ci int change = 0; 190962306a36Sopenharmony_ci 191062306a36Sopenharmony_ci spin_lock_irq(&korg1212->lock); 191162306a36Sopenharmony_ci 191262306a36Sopenharmony_ci if (u->value.integer.value[0] >= k1212MinADCSens && 191362306a36Sopenharmony_ci u->value.integer.value[0] <= k1212MaxADCSens && 191462306a36Sopenharmony_ci u->value.integer.value[0] != korg1212->leftADCInSens) { 191562306a36Sopenharmony_ci korg1212->leftADCInSens = u->value.integer.value[0]; 191662306a36Sopenharmony_ci change = 1; 191762306a36Sopenharmony_ci } 191862306a36Sopenharmony_ci if (u->value.integer.value[1] >= k1212MinADCSens && 191962306a36Sopenharmony_ci u->value.integer.value[1] <= k1212MaxADCSens && 192062306a36Sopenharmony_ci u->value.integer.value[1] != korg1212->rightADCInSens) { 192162306a36Sopenharmony_ci korg1212->rightADCInSens = u->value.integer.value[1]; 192262306a36Sopenharmony_ci change = 1; 192362306a36Sopenharmony_ci } 192462306a36Sopenharmony_ci 192562306a36Sopenharmony_ci spin_unlock_irq(&korg1212->lock); 192662306a36Sopenharmony_ci 192762306a36Sopenharmony_ci if (change) 192862306a36Sopenharmony_ci snd_korg1212_WriteADCSensitivity(korg1212); 192962306a36Sopenharmony_ci 193062306a36Sopenharmony_ci return change; 193162306a36Sopenharmony_ci} 193262306a36Sopenharmony_ci 193362306a36Sopenharmony_cistatic int snd_korg1212_control_sync_info(struct snd_kcontrol *kcontrol, 193462306a36Sopenharmony_ci struct snd_ctl_elem_info *uinfo) 193562306a36Sopenharmony_ci{ 193662306a36Sopenharmony_ci return snd_ctl_enum_info(uinfo, 1, 3, clockSourceTypeName); 193762306a36Sopenharmony_ci} 193862306a36Sopenharmony_ci 193962306a36Sopenharmony_cistatic int snd_korg1212_control_sync_get(struct snd_kcontrol *kcontrol, 194062306a36Sopenharmony_ci struct snd_ctl_elem_value *ucontrol) 194162306a36Sopenharmony_ci{ 194262306a36Sopenharmony_ci struct snd_korg1212 *korg1212 = snd_kcontrol_chip(kcontrol); 194362306a36Sopenharmony_ci 194462306a36Sopenharmony_ci spin_lock_irq(&korg1212->lock); 194562306a36Sopenharmony_ci 194662306a36Sopenharmony_ci ucontrol->value.enumerated.item[0] = korg1212->clkSource; 194762306a36Sopenharmony_ci 194862306a36Sopenharmony_ci spin_unlock_irq(&korg1212->lock); 194962306a36Sopenharmony_ci return 0; 195062306a36Sopenharmony_ci} 195162306a36Sopenharmony_ci 195262306a36Sopenharmony_cistatic int snd_korg1212_control_sync_put(struct snd_kcontrol *kcontrol, 195362306a36Sopenharmony_ci struct snd_ctl_elem_value *ucontrol) 195462306a36Sopenharmony_ci{ 195562306a36Sopenharmony_ci struct snd_korg1212 *korg1212 = snd_kcontrol_chip(kcontrol); 195662306a36Sopenharmony_ci unsigned int val; 195762306a36Sopenharmony_ci int change; 195862306a36Sopenharmony_ci 195962306a36Sopenharmony_ci val = ucontrol->value.enumerated.item[0] % 3; 196062306a36Sopenharmony_ci spin_lock_irq(&korg1212->lock); 196162306a36Sopenharmony_ci change = val != korg1212->clkSource; 196262306a36Sopenharmony_ci snd_korg1212_SetClockSource(korg1212, val); 196362306a36Sopenharmony_ci spin_unlock_irq(&korg1212->lock); 196462306a36Sopenharmony_ci return change; 196562306a36Sopenharmony_ci} 196662306a36Sopenharmony_ci 196762306a36Sopenharmony_ci#define MON_MIXER(ord,c_name) \ 196862306a36Sopenharmony_ci { \ 196962306a36Sopenharmony_ci .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE, \ 197062306a36Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ 197162306a36Sopenharmony_ci .name = c_name " Monitor Volume", \ 197262306a36Sopenharmony_ci .info = snd_korg1212_control_volume_info, \ 197362306a36Sopenharmony_ci .get = snd_korg1212_control_volume_get, \ 197462306a36Sopenharmony_ci .put = snd_korg1212_control_volume_put, \ 197562306a36Sopenharmony_ci .private_value = ord, \ 197662306a36Sopenharmony_ci }, \ 197762306a36Sopenharmony_ci { \ 197862306a36Sopenharmony_ci .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE, \ 197962306a36Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ 198062306a36Sopenharmony_ci .name = c_name " Monitor Route", \ 198162306a36Sopenharmony_ci .info = snd_korg1212_control_route_info, \ 198262306a36Sopenharmony_ci .get = snd_korg1212_control_route_get, \ 198362306a36Sopenharmony_ci .put = snd_korg1212_control_route_put, \ 198462306a36Sopenharmony_ci .private_value = ord, \ 198562306a36Sopenharmony_ci }, \ 198662306a36Sopenharmony_ci { \ 198762306a36Sopenharmony_ci .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE, \ 198862306a36Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ 198962306a36Sopenharmony_ci .name = c_name " Monitor Phase Invert", \ 199062306a36Sopenharmony_ci .info = snd_korg1212_control_phase_info, \ 199162306a36Sopenharmony_ci .get = snd_korg1212_control_phase_get, \ 199262306a36Sopenharmony_ci .put = snd_korg1212_control_phase_put, \ 199362306a36Sopenharmony_ci .private_value = ord, \ 199462306a36Sopenharmony_ci } 199562306a36Sopenharmony_ci 199662306a36Sopenharmony_cistatic const struct snd_kcontrol_new snd_korg1212_controls[] = { 199762306a36Sopenharmony_ci MON_MIXER(8, "Analog"), 199862306a36Sopenharmony_ci MON_MIXER(10, "SPDIF"), 199962306a36Sopenharmony_ci MON_MIXER(0, "ADAT-1"), MON_MIXER(1, "ADAT-2"), MON_MIXER(2, "ADAT-3"), MON_MIXER(3, "ADAT-4"), 200062306a36Sopenharmony_ci MON_MIXER(4, "ADAT-5"), MON_MIXER(5, "ADAT-6"), MON_MIXER(6, "ADAT-7"), MON_MIXER(7, "ADAT-8"), 200162306a36Sopenharmony_ci { 200262306a36Sopenharmony_ci .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE, 200362306a36Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 200462306a36Sopenharmony_ci .name = "Sync Source", 200562306a36Sopenharmony_ci .info = snd_korg1212_control_sync_info, 200662306a36Sopenharmony_ci .get = snd_korg1212_control_sync_get, 200762306a36Sopenharmony_ci .put = snd_korg1212_control_sync_put, 200862306a36Sopenharmony_ci }, 200962306a36Sopenharmony_ci { 201062306a36Sopenharmony_ci .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE, 201162306a36Sopenharmony_ci .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 201262306a36Sopenharmony_ci .name = "ADC Attenuation", 201362306a36Sopenharmony_ci .info = snd_korg1212_control_info, 201462306a36Sopenharmony_ci .get = snd_korg1212_control_get, 201562306a36Sopenharmony_ci .put = snd_korg1212_control_put, 201662306a36Sopenharmony_ci } 201762306a36Sopenharmony_ci}; 201862306a36Sopenharmony_ci 201962306a36Sopenharmony_ci/* 202062306a36Sopenharmony_ci * proc interface 202162306a36Sopenharmony_ci */ 202262306a36Sopenharmony_ci 202362306a36Sopenharmony_cistatic void snd_korg1212_proc_read(struct snd_info_entry *entry, 202462306a36Sopenharmony_ci struct snd_info_buffer *buffer) 202562306a36Sopenharmony_ci{ 202662306a36Sopenharmony_ci int n; 202762306a36Sopenharmony_ci struct snd_korg1212 *korg1212 = entry->private_data; 202862306a36Sopenharmony_ci 202962306a36Sopenharmony_ci snd_iprintf(buffer, korg1212->card->longname); 203062306a36Sopenharmony_ci snd_iprintf(buffer, " (index #%d)\n", korg1212->card->number + 1); 203162306a36Sopenharmony_ci snd_iprintf(buffer, "\nGeneral settings\n"); 203262306a36Sopenharmony_ci snd_iprintf(buffer, " period size: %zd bytes\n", K1212_PERIOD_BYTES); 203362306a36Sopenharmony_ci snd_iprintf(buffer, " clock mode: %s\n", clockSourceName[korg1212->clkSrcRate] ); 203462306a36Sopenharmony_ci snd_iprintf(buffer, " left ADC Sens: %d\n", korg1212->leftADCInSens ); 203562306a36Sopenharmony_ci snd_iprintf(buffer, " right ADC Sens: %d\n", korg1212->rightADCInSens ); 203662306a36Sopenharmony_ci snd_iprintf(buffer, " Volume Info:\n"); 203762306a36Sopenharmony_ci for (n=0; n<kAudioChannels; n++) 203862306a36Sopenharmony_ci snd_iprintf(buffer, " Channel %d: %s -> %s [%d]\n", n, 203962306a36Sopenharmony_ci channelName[n], 204062306a36Sopenharmony_ci channelName[korg1212->sharedBufferPtr->routeData[n]], 204162306a36Sopenharmony_ci korg1212->sharedBufferPtr->volumeData[n]); 204262306a36Sopenharmony_ci snd_iprintf(buffer, "\nGeneral status\n"); 204362306a36Sopenharmony_ci snd_iprintf(buffer, " ADAT Time Code: %d\n", korg1212->sharedBufferPtr->AdatTimeCode); 204462306a36Sopenharmony_ci snd_iprintf(buffer, " Card State: %s\n", stateName[korg1212->cardState]); 204562306a36Sopenharmony_ci snd_iprintf(buffer, "Idle mon. State: %d\n", korg1212->idleMonitorOn); 204662306a36Sopenharmony_ci snd_iprintf(buffer, "Cmd retry count: %d\n", korg1212->cmdRetryCount); 204762306a36Sopenharmony_ci snd_iprintf(buffer, " Irq count: %ld\n", korg1212->irqcount); 204862306a36Sopenharmony_ci snd_iprintf(buffer, " Error count: %ld\n", korg1212->totalerrorcnt); 204962306a36Sopenharmony_ci} 205062306a36Sopenharmony_ci 205162306a36Sopenharmony_cistatic void snd_korg1212_proc_init(struct snd_korg1212 *korg1212) 205262306a36Sopenharmony_ci{ 205362306a36Sopenharmony_ci snd_card_ro_proc_new(korg1212->card, "korg1212", korg1212, 205462306a36Sopenharmony_ci snd_korg1212_proc_read); 205562306a36Sopenharmony_ci} 205662306a36Sopenharmony_ci 205762306a36Sopenharmony_cistatic void 205862306a36Sopenharmony_cisnd_korg1212_free(struct snd_card *card) 205962306a36Sopenharmony_ci{ 206062306a36Sopenharmony_ci struct snd_korg1212 *korg1212 = card->private_data; 206162306a36Sopenharmony_ci 206262306a36Sopenharmony_ci snd_korg1212_TurnOffIdleMonitor(korg1212); 206362306a36Sopenharmony_ci snd_korg1212_DisableCardInterrupts(korg1212); 206462306a36Sopenharmony_ci} 206562306a36Sopenharmony_ci 206662306a36Sopenharmony_cistatic int snd_korg1212_create(struct snd_card *card, struct pci_dev *pci) 206762306a36Sopenharmony_ci 206862306a36Sopenharmony_ci{ 206962306a36Sopenharmony_ci int err, rc; 207062306a36Sopenharmony_ci unsigned int i; 207162306a36Sopenharmony_ci __maybe_unused unsigned iomem_size; 207262306a36Sopenharmony_ci __maybe_unused unsigned ioport_size; 207362306a36Sopenharmony_ci __maybe_unused unsigned iomem2_size; 207462306a36Sopenharmony_ci struct snd_korg1212 *korg1212 = card->private_data; 207562306a36Sopenharmony_ci const struct firmware *dsp_code; 207662306a36Sopenharmony_ci 207762306a36Sopenharmony_ci err = pcim_enable_device(pci); 207862306a36Sopenharmony_ci if (err < 0) 207962306a36Sopenharmony_ci return err; 208062306a36Sopenharmony_ci 208162306a36Sopenharmony_ci korg1212->card = card; 208262306a36Sopenharmony_ci korg1212->pci = pci; 208362306a36Sopenharmony_ci 208462306a36Sopenharmony_ci init_waitqueue_head(&korg1212->wait); 208562306a36Sopenharmony_ci spin_lock_init(&korg1212->lock); 208662306a36Sopenharmony_ci mutex_init(&korg1212->open_mutex); 208762306a36Sopenharmony_ci timer_setup(&korg1212->timer, snd_korg1212_timer_func, 0); 208862306a36Sopenharmony_ci 208962306a36Sopenharmony_ci korg1212->irq = -1; 209062306a36Sopenharmony_ci korg1212->clkSource = K1212_CLKIDX_Local; 209162306a36Sopenharmony_ci korg1212->clkRate = 44100; 209262306a36Sopenharmony_ci korg1212->inIRQ = 0; 209362306a36Sopenharmony_ci korg1212->running = 0; 209462306a36Sopenharmony_ci korg1212->opencnt = 0; 209562306a36Sopenharmony_ci korg1212->playcnt = 0; 209662306a36Sopenharmony_ci korg1212->setcnt = 0; 209762306a36Sopenharmony_ci korg1212->totalerrorcnt = 0; 209862306a36Sopenharmony_ci korg1212->playback_pid = -1; 209962306a36Sopenharmony_ci korg1212->capture_pid = -1; 210062306a36Sopenharmony_ci snd_korg1212_setCardState(korg1212, K1212_STATE_UNINITIALIZED); 210162306a36Sopenharmony_ci korg1212->idleMonitorOn = 0; 210262306a36Sopenharmony_ci korg1212->clkSrcRate = K1212_CLKIDX_LocalAt44_1K; 210362306a36Sopenharmony_ci korg1212->leftADCInSens = k1212MaxADCSens; 210462306a36Sopenharmony_ci korg1212->rightADCInSens = k1212MaxADCSens; 210562306a36Sopenharmony_ci 210662306a36Sopenharmony_ci for (i=0; i<kAudioChannels; i++) 210762306a36Sopenharmony_ci korg1212->volumePhase[i] = 0; 210862306a36Sopenharmony_ci 210962306a36Sopenharmony_ci err = pcim_iomap_regions_request_all(pci, 1 << 0, "korg1212"); 211062306a36Sopenharmony_ci if (err < 0) 211162306a36Sopenharmony_ci return err; 211262306a36Sopenharmony_ci 211362306a36Sopenharmony_ci korg1212->iomem = pci_resource_start(korg1212->pci, 0); 211462306a36Sopenharmony_ci korg1212->ioport = pci_resource_start(korg1212->pci, 1); 211562306a36Sopenharmony_ci korg1212->iomem2 = pci_resource_start(korg1212->pci, 2); 211662306a36Sopenharmony_ci 211762306a36Sopenharmony_ci iomem_size = pci_resource_len(korg1212->pci, 0); 211862306a36Sopenharmony_ci ioport_size = pci_resource_len(korg1212->pci, 1); 211962306a36Sopenharmony_ci iomem2_size = pci_resource_len(korg1212->pci, 2); 212062306a36Sopenharmony_ci 212162306a36Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: resources:\n" 212262306a36Sopenharmony_ci " iomem = 0x%lx (%d)\n" 212362306a36Sopenharmony_ci " ioport = 0x%lx (%d)\n" 212462306a36Sopenharmony_ci " iomem = 0x%lx (%d)\n" 212562306a36Sopenharmony_ci " [%s]\n", 212662306a36Sopenharmony_ci korg1212->iomem, iomem_size, 212762306a36Sopenharmony_ci korg1212->ioport, ioport_size, 212862306a36Sopenharmony_ci korg1212->iomem2, iomem2_size, 212962306a36Sopenharmony_ci stateName[korg1212->cardState]); 213062306a36Sopenharmony_ci 213162306a36Sopenharmony_ci korg1212->iobase = pcim_iomap_table(pci)[0]; 213262306a36Sopenharmony_ci 213362306a36Sopenharmony_ci err = devm_request_irq(&pci->dev, pci->irq, snd_korg1212_interrupt, 213462306a36Sopenharmony_ci IRQF_SHARED, 213562306a36Sopenharmony_ci KBUILD_MODNAME, korg1212); 213662306a36Sopenharmony_ci 213762306a36Sopenharmony_ci if (err) { 213862306a36Sopenharmony_ci snd_printk(KERN_ERR "korg1212: unable to grab IRQ %d\n", pci->irq); 213962306a36Sopenharmony_ci return -EBUSY; 214062306a36Sopenharmony_ci } 214162306a36Sopenharmony_ci 214262306a36Sopenharmony_ci korg1212->irq = pci->irq; 214362306a36Sopenharmony_ci card->sync_irq = korg1212->irq; 214462306a36Sopenharmony_ci card->private_free = snd_korg1212_free; 214562306a36Sopenharmony_ci 214662306a36Sopenharmony_ci pci_set_master(korg1212->pci); 214762306a36Sopenharmony_ci 214862306a36Sopenharmony_ci korg1212->statusRegPtr = (u32 __iomem *) (korg1212->iobase + STATUS_REG_OFFSET); 214962306a36Sopenharmony_ci korg1212->outDoorbellPtr = (u32 __iomem *) (korg1212->iobase + OUT_DOORBELL_OFFSET); 215062306a36Sopenharmony_ci korg1212->inDoorbellPtr = (u32 __iomem *) (korg1212->iobase + IN_DOORBELL_OFFSET); 215162306a36Sopenharmony_ci korg1212->mailbox0Ptr = (u32 __iomem *) (korg1212->iobase + MAILBOX0_OFFSET); 215262306a36Sopenharmony_ci korg1212->mailbox1Ptr = (u32 __iomem *) (korg1212->iobase + MAILBOX1_OFFSET); 215362306a36Sopenharmony_ci korg1212->mailbox2Ptr = (u32 __iomem *) (korg1212->iobase + MAILBOX2_OFFSET); 215462306a36Sopenharmony_ci korg1212->mailbox3Ptr = (u32 __iomem *) (korg1212->iobase + MAILBOX3_OFFSET); 215562306a36Sopenharmony_ci korg1212->controlRegPtr = (u32 __iomem *) (korg1212->iobase + PCI_CONTROL_OFFSET); 215662306a36Sopenharmony_ci korg1212->sensRegPtr = (u16 __iomem *) (korg1212->iobase + SENS_CONTROL_OFFSET); 215762306a36Sopenharmony_ci korg1212->idRegPtr = (u32 __iomem *) (korg1212->iobase + DEV_VEND_ID_OFFSET); 215862306a36Sopenharmony_ci 215962306a36Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: card registers:\n" 216062306a36Sopenharmony_ci " Status register = 0x%p\n" 216162306a36Sopenharmony_ci " OutDoorbell = 0x%p\n" 216262306a36Sopenharmony_ci " InDoorbell = 0x%p\n" 216362306a36Sopenharmony_ci " Mailbox0 = 0x%p\n" 216462306a36Sopenharmony_ci " Mailbox1 = 0x%p\n" 216562306a36Sopenharmony_ci " Mailbox2 = 0x%p\n" 216662306a36Sopenharmony_ci " Mailbox3 = 0x%p\n" 216762306a36Sopenharmony_ci " ControlReg = 0x%p\n" 216862306a36Sopenharmony_ci " SensReg = 0x%p\n" 216962306a36Sopenharmony_ci " IDReg = 0x%p\n" 217062306a36Sopenharmony_ci " [%s]\n", 217162306a36Sopenharmony_ci korg1212->statusRegPtr, 217262306a36Sopenharmony_ci korg1212->outDoorbellPtr, 217362306a36Sopenharmony_ci korg1212->inDoorbellPtr, 217462306a36Sopenharmony_ci korg1212->mailbox0Ptr, 217562306a36Sopenharmony_ci korg1212->mailbox1Ptr, 217662306a36Sopenharmony_ci korg1212->mailbox2Ptr, 217762306a36Sopenharmony_ci korg1212->mailbox3Ptr, 217862306a36Sopenharmony_ci korg1212->controlRegPtr, 217962306a36Sopenharmony_ci korg1212->sensRegPtr, 218062306a36Sopenharmony_ci korg1212->idRegPtr, 218162306a36Sopenharmony_ci stateName[korg1212->cardState]); 218262306a36Sopenharmony_ci 218362306a36Sopenharmony_ci korg1212->dma_shared = snd_devm_alloc_pages(&pci->dev, 218462306a36Sopenharmony_ci SNDRV_DMA_TYPE_DEV, 218562306a36Sopenharmony_ci sizeof(struct KorgSharedBuffer)); 218662306a36Sopenharmony_ci if (!korg1212->dma_shared) 218762306a36Sopenharmony_ci return -ENOMEM; 218862306a36Sopenharmony_ci korg1212->sharedBufferPtr = (struct KorgSharedBuffer *)korg1212->dma_shared->area; 218962306a36Sopenharmony_ci korg1212->sharedBufferPhy = korg1212->dma_shared->addr; 219062306a36Sopenharmony_ci 219162306a36Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: Shared Buffer Area = 0x%p (0x%08lx), %d bytes\n", korg1212->sharedBufferPtr, korg1212->sharedBufferPhy, sizeof(struct KorgSharedBuffer)); 219262306a36Sopenharmony_ci 219362306a36Sopenharmony_ci#ifndef K1212_LARGEALLOC 219462306a36Sopenharmony_ci korg1212->DataBufsSize = sizeof(struct KorgAudioBuffer) * kNumBuffers; 219562306a36Sopenharmony_ci korg1212->dma_play = snd_devm_alloc_pages(&pci->dev, SNDRV_DMA_TYPE_DEV, 219662306a36Sopenharmony_ci korg1212->DataBufsSize); 219762306a36Sopenharmony_ci if (!korg1212->dma_play) 219862306a36Sopenharmony_ci return -ENOMEM; 219962306a36Sopenharmony_ci 220062306a36Sopenharmony_ci korg1212->playDataBufsPtr = (struct KorgAudioBuffer *)korg1212->dma_play->area; 220162306a36Sopenharmony_ci korg1212->PlayDataPhy = korg1212->dma_play->addr; 220262306a36Sopenharmony_ci 220362306a36Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: Play Data Area = 0x%p (0x%08x), %d bytes\n", 220462306a36Sopenharmony_ci korg1212->playDataBufsPtr, korg1212->PlayDataPhy, korg1212->DataBufsSize); 220562306a36Sopenharmony_ci 220662306a36Sopenharmony_ci korg1212->dma_rec = snd_devm_alloc_pages(&pci->dev, SNDRV_DMA_TYPE_DEV, 220762306a36Sopenharmony_ci korg1212->DataBufsSize); 220862306a36Sopenharmony_ci if (!korg1212->dma_rec) 220962306a36Sopenharmony_ci return -ENOMEM; 221062306a36Sopenharmony_ci 221162306a36Sopenharmony_ci korg1212->recordDataBufsPtr = (struct KorgAudioBuffer *)korg1212->dma_rec->area; 221262306a36Sopenharmony_ci korg1212->RecDataPhy = korg1212->dma_rec->addr; 221362306a36Sopenharmony_ci 221462306a36Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: Record Data Area = 0x%p (0x%08x), %d bytes\n", 221562306a36Sopenharmony_ci korg1212->recordDataBufsPtr, korg1212->RecDataPhy, korg1212->DataBufsSize); 221662306a36Sopenharmony_ci 221762306a36Sopenharmony_ci#else // K1212_LARGEALLOC 221862306a36Sopenharmony_ci 221962306a36Sopenharmony_ci korg1212->recordDataBufsPtr = korg1212->sharedBufferPtr->recordDataBufs; 222062306a36Sopenharmony_ci korg1212->playDataBufsPtr = korg1212->sharedBufferPtr->playDataBufs; 222162306a36Sopenharmony_ci korg1212->PlayDataPhy = (u32) &((struct KorgSharedBuffer *) korg1212->sharedBufferPhy)->playDataBufs; 222262306a36Sopenharmony_ci korg1212->RecDataPhy = (u32) &((struct KorgSharedBuffer *) korg1212->sharedBufferPhy)->recordDataBufs; 222362306a36Sopenharmony_ci 222462306a36Sopenharmony_ci#endif // K1212_LARGEALLOC 222562306a36Sopenharmony_ci 222662306a36Sopenharmony_ci korg1212->VolumeTablePhy = korg1212->sharedBufferPhy + 222762306a36Sopenharmony_ci offsetof(struct KorgSharedBuffer, volumeData); 222862306a36Sopenharmony_ci korg1212->RoutingTablePhy = korg1212->sharedBufferPhy + 222962306a36Sopenharmony_ci offsetof(struct KorgSharedBuffer, routeData); 223062306a36Sopenharmony_ci korg1212->AdatTimeCodePhy = korg1212->sharedBufferPhy + 223162306a36Sopenharmony_ci offsetof(struct KorgSharedBuffer, AdatTimeCode); 223262306a36Sopenharmony_ci 223362306a36Sopenharmony_ci err = request_firmware(&dsp_code, "korg/k1212.dsp", &pci->dev); 223462306a36Sopenharmony_ci if (err < 0) { 223562306a36Sopenharmony_ci snd_printk(KERN_ERR "firmware not available\n"); 223662306a36Sopenharmony_ci return err; 223762306a36Sopenharmony_ci } 223862306a36Sopenharmony_ci 223962306a36Sopenharmony_ci korg1212->dma_dsp = snd_devm_alloc_pages(&pci->dev, SNDRV_DMA_TYPE_DEV, 224062306a36Sopenharmony_ci dsp_code->size); 224162306a36Sopenharmony_ci if (!korg1212->dma_dsp) { 224262306a36Sopenharmony_ci release_firmware(dsp_code); 224362306a36Sopenharmony_ci return -ENOMEM; 224462306a36Sopenharmony_ci } 224562306a36Sopenharmony_ci 224662306a36Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: DSP Code area = 0x%p (0x%08x) %d bytes [%s]\n", 224762306a36Sopenharmony_ci korg1212->dma_dsp->area, korg1212->dma_dsp->addr, dsp_code->size, 224862306a36Sopenharmony_ci stateName[korg1212->cardState]); 224962306a36Sopenharmony_ci 225062306a36Sopenharmony_ci memcpy(korg1212->dma_dsp->area, dsp_code->data, dsp_code->size); 225162306a36Sopenharmony_ci 225262306a36Sopenharmony_ci release_firmware(dsp_code); 225362306a36Sopenharmony_ci 225462306a36Sopenharmony_ci rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_RebootCard, 0, 0, 0, 0); 225562306a36Sopenharmony_ci 225662306a36Sopenharmony_ci if (rc) 225762306a36Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: Reboot Card - RC = %d [%s]\n", rc, stateName[korg1212->cardState]); 225862306a36Sopenharmony_ci 225962306a36Sopenharmony_ci snd_korg1212_EnableCardInterrupts(korg1212); 226062306a36Sopenharmony_ci 226162306a36Sopenharmony_ci mdelay(CARD_BOOT_DELAY_IN_MS); 226262306a36Sopenharmony_ci 226362306a36Sopenharmony_ci if (snd_korg1212_downloadDSPCode(korg1212)) 226462306a36Sopenharmony_ci return -EBUSY; 226562306a36Sopenharmony_ci 226662306a36Sopenharmony_ci K1212_DEBUG_PRINTK("korg1212: dspMemPhy = %08x U[%08x], " 226762306a36Sopenharmony_ci "PlayDataPhy = %08x L[%08x]\n" 226862306a36Sopenharmony_ci "korg1212: RecDataPhy = %08x L[%08x], " 226962306a36Sopenharmony_ci "VolumeTablePhy = %08x L[%08x]\n" 227062306a36Sopenharmony_ci "korg1212: RoutingTablePhy = %08x L[%08x], " 227162306a36Sopenharmony_ci "AdatTimeCodePhy = %08x L[%08x]\n", 227262306a36Sopenharmony_ci (int)korg1212->dma_dsp.addr, UpperWordSwap(korg1212->dma_dsp.addr), 227362306a36Sopenharmony_ci korg1212->PlayDataPhy, LowerWordSwap(korg1212->PlayDataPhy), 227462306a36Sopenharmony_ci korg1212->RecDataPhy, LowerWordSwap(korg1212->RecDataPhy), 227562306a36Sopenharmony_ci korg1212->VolumeTablePhy, LowerWordSwap(korg1212->VolumeTablePhy), 227662306a36Sopenharmony_ci korg1212->RoutingTablePhy, LowerWordSwap(korg1212->RoutingTablePhy), 227762306a36Sopenharmony_ci korg1212->AdatTimeCodePhy, LowerWordSwap(korg1212->AdatTimeCodePhy)); 227862306a36Sopenharmony_ci 227962306a36Sopenharmony_ci err = snd_pcm_new(korg1212->card, "korg1212", 0, 1, 1, &korg1212->pcm); 228062306a36Sopenharmony_ci if (err < 0) 228162306a36Sopenharmony_ci return err; 228262306a36Sopenharmony_ci 228362306a36Sopenharmony_ci korg1212->pcm->private_data = korg1212; 228462306a36Sopenharmony_ci korg1212->pcm->private_free = snd_korg1212_free_pcm; 228562306a36Sopenharmony_ci strcpy(korg1212->pcm->name, "korg1212"); 228662306a36Sopenharmony_ci 228762306a36Sopenharmony_ci snd_pcm_set_ops(korg1212->pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_korg1212_playback_ops); 228862306a36Sopenharmony_ci 228962306a36Sopenharmony_ci snd_pcm_set_ops(korg1212->pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_korg1212_capture_ops); 229062306a36Sopenharmony_ci 229162306a36Sopenharmony_ci korg1212->pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX; 229262306a36Sopenharmony_ci 229362306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(snd_korg1212_controls); i++) { 229462306a36Sopenharmony_ci err = snd_ctl_add(korg1212->card, snd_ctl_new1(&snd_korg1212_controls[i], korg1212)); 229562306a36Sopenharmony_ci if (err < 0) 229662306a36Sopenharmony_ci return err; 229762306a36Sopenharmony_ci } 229862306a36Sopenharmony_ci 229962306a36Sopenharmony_ci snd_korg1212_proc_init(korg1212); 230062306a36Sopenharmony_ci 230162306a36Sopenharmony_ci return 0; 230262306a36Sopenharmony_ci} 230362306a36Sopenharmony_ci 230462306a36Sopenharmony_ci/* 230562306a36Sopenharmony_ci * Card initialisation 230662306a36Sopenharmony_ci */ 230762306a36Sopenharmony_ci 230862306a36Sopenharmony_cistatic int 230962306a36Sopenharmony_cisnd_korg1212_probe(struct pci_dev *pci, 231062306a36Sopenharmony_ci const struct pci_device_id *pci_id) 231162306a36Sopenharmony_ci{ 231262306a36Sopenharmony_ci static int dev; 231362306a36Sopenharmony_ci struct snd_korg1212 *korg1212; 231462306a36Sopenharmony_ci struct snd_card *card; 231562306a36Sopenharmony_ci int err; 231662306a36Sopenharmony_ci 231762306a36Sopenharmony_ci if (dev >= SNDRV_CARDS) { 231862306a36Sopenharmony_ci return -ENODEV; 231962306a36Sopenharmony_ci } 232062306a36Sopenharmony_ci if (!enable[dev]) { 232162306a36Sopenharmony_ci dev++; 232262306a36Sopenharmony_ci return -ENOENT; 232362306a36Sopenharmony_ci } 232462306a36Sopenharmony_ci err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, 232562306a36Sopenharmony_ci sizeof(*korg1212), &card); 232662306a36Sopenharmony_ci if (err < 0) 232762306a36Sopenharmony_ci return err; 232862306a36Sopenharmony_ci korg1212 = card->private_data; 232962306a36Sopenharmony_ci 233062306a36Sopenharmony_ci err = snd_korg1212_create(card, pci); 233162306a36Sopenharmony_ci if (err < 0) 233262306a36Sopenharmony_ci goto error; 233362306a36Sopenharmony_ci 233462306a36Sopenharmony_ci strcpy(card->driver, "korg1212"); 233562306a36Sopenharmony_ci strcpy(card->shortname, "korg1212"); 233662306a36Sopenharmony_ci sprintf(card->longname, "%s at 0x%lx, irq %d", card->shortname, 233762306a36Sopenharmony_ci korg1212->iomem, korg1212->irq); 233862306a36Sopenharmony_ci 233962306a36Sopenharmony_ci K1212_DEBUG_PRINTK("K1212_DEBUG: %s\n", card->longname); 234062306a36Sopenharmony_ci 234162306a36Sopenharmony_ci err = snd_card_register(card); 234262306a36Sopenharmony_ci if (err < 0) 234362306a36Sopenharmony_ci goto error; 234462306a36Sopenharmony_ci pci_set_drvdata(pci, card); 234562306a36Sopenharmony_ci dev++; 234662306a36Sopenharmony_ci return 0; 234762306a36Sopenharmony_ci 234862306a36Sopenharmony_ci error: 234962306a36Sopenharmony_ci snd_card_free(card); 235062306a36Sopenharmony_ci return err; 235162306a36Sopenharmony_ci} 235262306a36Sopenharmony_ci 235362306a36Sopenharmony_cistatic struct pci_driver korg1212_driver = { 235462306a36Sopenharmony_ci .name = KBUILD_MODNAME, 235562306a36Sopenharmony_ci .id_table = snd_korg1212_ids, 235662306a36Sopenharmony_ci .probe = snd_korg1212_probe, 235762306a36Sopenharmony_ci}; 235862306a36Sopenharmony_ci 235962306a36Sopenharmony_cimodule_pci_driver(korg1212_driver); 2360