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