109c434b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
21bd9debfSTakashi Iwai /*
31bd9debfSTakashi Iwai * Driver for DBRI sound chip found on Sparcs.
44338829eSMartin Habets * Copyright (C) 2004, 2005 Martin Habets (mhabets@users.sourceforge.net)
51bd9debfSTakashi Iwai *
61be54c82SKrzysztof Helt * Converted to ring buffered version by Krzysztof Helt (krzysztof.h1@wp.pl)
71be54c82SKrzysztof Helt *
81bd9debfSTakashi Iwai * Based entirely upon drivers/sbus/audio/dbri.c which is:
91bd9debfSTakashi Iwai * Copyright (C) 1997 Rudolf Koenig (rfkoenig@immd4.informatik.uni-erlangen.de)
101bd9debfSTakashi Iwai * Copyright (C) 1998, 1999 Brent Baccala (baccala@freesoft.org)
111bd9debfSTakashi Iwai *
121bd9debfSTakashi Iwai * This is the low level driver for the DBRI & MMCODEC duo used for ISDN & AUDIO
13098ccbc5SKrzysztof Helt * on Sun SPARCStation 10, 20, LX and Voyager models.
141bd9debfSTakashi Iwai *
151bd9debfSTakashi Iwai * - DBRI: AT&T T5900FX Dual Basic Rates ISDN Interface. It is a 32 channel
161bd9debfSTakashi Iwai * data time multiplexer with ISDN support (aka T7259)
171bd9debfSTakashi Iwai * Interfaces: SBus,ISDN NT & TE, CHI, 4 bits parallel.
181bd9debfSTakashi Iwai * CHI: (spelled ki) Concentration Highway Interface (AT&T or Intel bus ?).
191bd9debfSTakashi Iwai * Documentation:
20098ccbc5SKrzysztof Helt * - "STP 4000SBus Dual Basic Rate ISDN (DBRI) Transceiver" from
211bd9debfSTakashi Iwai * Sparc Technology Business (courtesy of Sun Support)
221bd9debfSTakashi Iwai * - Data sheet of the T7903, a newer but very similar ISA bus equivalent
23098ccbc5SKrzysztof Helt * available from the Lucent (formerly AT&T microelectronics) home
241bd9debfSTakashi Iwai * page.
257ed33ea6SAlexander A. Klimov * - https://www.freesoft.org/Linux/DBRI/
261bd9debfSTakashi Iwai * - MMCODEC: Crystal Semiconductor CS4215 16 bit Multimedia Audio Codec
271bd9debfSTakashi Iwai * Interfaces: CHI, Audio In & Out, 2 bits parallel
281bd9debfSTakashi Iwai * Documentation: from the Crystal Semiconductor home page.
291bd9debfSTakashi Iwai *
301bd9debfSTakashi Iwai * The DBRI is a 32 pipe machine, each pipe can transfer some bits between
31098ccbc5SKrzysztof Helt * memory and a serial device (long pipes, no. 0-15) or between two serial
32098ccbc5SKrzysztof Helt * devices (short pipes, no. 16-31), or simply send a fixed data to a serial
331bd9debfSTakashi Iwai * device (short pipes).
34098ccbc5SKrzysztof Helt * A timeslot defines the bit-offset and no. of bits read from a serial device.
351bd9debfSTakashi Iwai * The timeslots are linked to 6 circular lists, one for each direction for
361bd9debfSTakashi Iwai * each serial device (NT,TE,CHI). A timeslot is associated to 1 or 2 pipes
371bd9debfSTakashi Iwai * (the second one is a monitor/tee pipe, valid only for serial input).
381bd9debfSTakashi Iwai *
391bd9debfSTakashi Iwai * The mmcodec is connected via the CHI bus and needs the data & some
405fc3a2b2SKrzysztof Helt * parameters (volume, output selection) time multiplexed in 8 byte
411bd9debfSTakashi Iwai * chunks. It also has a control mode, which serves for audio format setting.
421bd9debfSTakashi Iwai *
431bd9debfSTakashi Iwai * Looking at the CS4215 data sheet it is easy to set up 2 or 4 codecs on
44098ccbc5SKrzysztof Helt * the same CHI bus, so I thought perhaps it is possible to use the on-board
45098ccbc5SKrzysztof Helt * & the speakerbox codec simultaneously, giving 2 (not very independent :-)
461bd9debfSTakashi Iwai * audio devices. But the SUN HW group decided against it, at least on my
471bd9debfSTakashi Iwai * LX the speakerbox connector has at least 1 pin missing and 1 wrongly
481bd9debfSTakashi Iwai * connected.
494338829eSMartin Habets *
504338829eSMartin Habets * I've tried to stick to the following function naming conventions:
514338829eSMartin Habets * snd_* ALSA stuff
52d254c8f7SAdrian Bunk * cs4215_* CS4215 codec specific stuff
534338829eSMartin Habets * dbri_* DBRI high-level stuff
544338829eSMartin Habets * other DBRI low-level stuff
551bd9debfSTakashi Iwai */
561bd9debfSTakashi Iwai
571bd9debfSTakashi Iwai #include <linux/interrupt.h>
581bd9debfSTakashi Iwai #include <linux/delay.h>
59098ccbc5SKrzysztof Helt #include <linux/irq.h>
60098ccbc5SKrzysztof Helt #include <linux/io.h>
61738f2b7bSDavid S. Miller #include <linux/dma-mapping.h>
625a0e3ad6STejun Heo #include <linux/gfp.h>
631bd9debfSTakashi Iwai
641bd9debfSTakashi Iwai #include <sound/core.h>
651bd9debfSTakashi Iwai #include <sound/pcm.h>
661bd9debfSTakashi Iwai #include <sound/pcm_params.h>
671bd9debfSTakashi Iwai #include <sound/info.h>
681bd9debfSTakashi Iwai #include <sound/control.h>
691bd9debfSTakashi Iwai #include <sound/initval.h>
701bd9debfSTakashi Iwai
71ef285fe6SKrzysztof Helt #include <linux/of.h>
72*7e9f2839SRob Herring #include <linux/platform_device.h>
7360063497SArun Sharma #include <linux/atomic.h>
74da155d5bSPaul Gortmaker #include <linux/module.h>
751bd9debfSTakashi Iwai
761bd9debfSTakashi Iwai MODULE_AUTHOR("Rudolf Koenig, Brent Baccala and Martin Habets");
771bd9debfSTakashi Iwai MODULE_DESCRIPTION("Sun DBRI");
781bd9debfSTakashi Iwai MODULE_LICENSE("GPL");
791bd9debfSTakashi Iwai
801bd9debfSTakashi Iwai static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
811bd9debfSTakashi Iwai static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
82098ccbc5SKrzysztof Helt /* Enable this card */
83a67ff6a5SRusty Russell static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
841bd9debfSTakashi Iwai
851bd9debfSTakashi Iwai module_param_array(index, int, NULL, 0444);
861bd9debfSTakashi Iwai MODULE_PARM_DESC(index, "Index value for Sun DBRI soundcard.");
871bd9debfSTakashi Iwai module_param_array(id, charp, NULL, 0444);
881bd9debfSTakashi Iwai MODULE_PARM_DESC(id, "ID string for Sun DBRI soundcard.");
891bd9debfSTakashi Iwai module_param_array(enable, bool, NULL, 0444);
901bd9debfSTakashi Iwai MODULE_PARM_DESC(enable, "Enable Sun DBRI soundcard.");
911bd9debfSTakashi Iwai
92ab93c7aeSKrzysztof Helt #undef DBRI_DEBUG
931bd9debfSTakashi Iwai
941bd9debfSTakashi Iwai #define D_INT (1<<0)
951bd9debfSTakashi Iwai #define D_GEN (1<<1)
961bd9debfSTakashi Iwai #define D_CMD (1<<2)
971bd9debfSTakashi Iwai #define D_MM (1<<3)
981bd9debfSTakashi Iwai #define D_USR (1<<4)
991bd9debfSTakashi Iwai #define D_DESC (1<<5)
1001bd9debfSTakashi Iwai
1016581f4e7STakashi Iwai static int dbri_debug;
1024338829eSMartin Habets module_param(dbri_debug, int, 0644);
1031bd9debfSTakashi Iwai MODULE_PARM_DESC(dbri_debug, "Debug value for Sun DBRI soundcard.");
1041bd9debfSTakashi Iwai
1051bd9debfSTakashi Iwai #ifdef DBRI_DEBUG
106121f46beSTakashi Iwai static const char * const cmds[] = {
1071bd9debfSTakashi Iwai "WAIT", "PAUSE", "JUMP", "IIQ", "REX", "SDP", "CDP", "DTS",
1081bd9debfSTakashi Iwai "SSP", "CHI", "NT", "TE", "CDEC", "TEST", "CDM", "RESRV"
1091bd9debfSTakashi Iwai };
1101bd9debfSTakashi Iwai
1111bd9debfSTakashi Iwai #define dprintk(a, x...) if (dbri_debug & a) printk(KERN_DEBUG x)
1121bd9debfSTakashi Iwai
1131bd9debfSTakashi Iwai #else
114aaad3653SKrzysztof Helt #define dprintk(a, x...) do { } while (0)
1151bd9debfSTakashi Iwai
11642fe7647SKrzysztof Helt #endif /* DBRI_DEBUG */
11742fe7647SKrzysztof Helt
1181bd9debfSTakashi Iwai #define DBRI_CMD(cmd, intr, value) ((cmd << 28) | \
1191bd9debfSTakashi Iwai (intr << 27) | \
1201bd9debfSTakashi Iwai value)
1211bd9debfSTakashi Iwai
1221bd9debfSTakashi Iwai /***************************************************************************
1231bd9debfSTakashi Iwai CS4215 specific definitions and structures
1241bd9debfSTakashi Iwai ****************************************************************************/
1251bd9debfSTakashi Iwai
1261bd9debfSTakashi Iwai struct cs4215 {
1271bd9debfSTakashi Iwai __u8 data[4]; /* Data mode: Time slots 5-8 */
1281bd9debfSTakashi Iwai __u8 ctrl[4]; /* Ctrl mode: Time slots 1-4 */
1291bd9debfSTakashi Iwai __u8 onboard;
1301bd9debfSTakashi Iwai __u8 offset; /* Bit offset from frame sync to time slot 1 */
1311bd9debfSTakashi Iwai volatile __u32 status;
1321bd9debfSTakashi Iwai volatile __u32 version;
1331bd9debfSTakashi Iwai __u8 precision; /* In bits, either 8 or 16 */
1341bd9debfSTakashi Iwai __u8 channels; /* 1 or 2 */
1351bd9debfSTakashi Iwai };
1361bd9debfSTakashi Iwai
1371bd9debfSTakashi Iwai /*
1381bd9debfSTakashi Iwai * Control mode first
1391bd9debfSTakashi Iwai */
1401bd9debfSTakashi Iwai
1411bd9debfSTakashi Iwai /* Time Slot 1, Status register */
1421bd9debfSTakashi Iwai #define CS4215_CLB (1<<2) /* Control Latch Bit */
1431bd9debfSTakashi Iwai #define CS4215_OLB (1<<3) /* 1: line: 2.0V, speaker 4V */
1441bd9debfSTakashi Iwai /* 0: line: 2.8V, speaker 8V */
1451bd9debfSTakashi Iwai #define CS4215_MLB (1<<4) /* 1: Microphone: 20dB gain disabled */
1461bd9debfSTakashi Iwai #define CS4215_RSRVD_1 (1<<5)
1471bd9debfSTakashi Iwai
1481bd9debfSTakashi Iwai /* Time Slot 2, Data Format Register */
1491bd9debfSTakashi Iwai #define CS4215_DFR_LINEAR16 0
1501bd9debfSTakashi Iwai #define CS4215_DFR_ULAW 1
1511bd9debfSTakashi Iwai #define CS4215_DFR_ALAW 2
1521bd9debfSTakashi Iwai #define CS4215_DFR_LINEAR8 3
1531bd9debfSTakashi Iwai #define CS4215_DFR_STEREO (1<<2)
1541bd9debfSTakashi Iwai static struct {
1551bd9debfSTakashi Iwai unsigned short freq;
1561bd9debfSTakashi Iwai unsigned char xtal;
1571bd9debfSTakashi Iwai unsigned char csval;
1581bd9debfSTakashi Iwai } CS4215_FREQ[] = {
1591bd9debfSTakashi Iwai { 8000, (1 << 4), (0 << 3) },
1601bd9debfSTakashi Iwai { 16000, (1 << 4), (1 << 3) },
1611bd9debfSTakashi Iwai { 27429, (1 << 4), (2 << 3) }, /* Actually 24428.57 */
1621bd9debfSTakashi Iwai { 32000, (1 << 4), (3 << 3) },
1631bd9debfSTakashi Iwai /* { NA, (1 << 4), (4 << 3) }, */
1641bd9debfSTakashi Iwai /* { NA, (1 << 4), (5 << 3) }, */
1651bd9debfSTakashi Iwai { 48000, (1 << 4), (6 << 3) },
1661bd9debfSTakashi Iwai { 9600, (1 << 4), (7 << 3) },
167ab93c7aeSKrzysztof Helt { 5512, (2 << 4), (0 << 3) }, /* Actually 5512.5 */
1681bd9debfSTakashi Iwai { 11025, (2 << 4), (1 << 3) },
1691bd9debfSTakashi Iwai { 18900, (2 << 4), (2 << 3) },
1701bd9debfSTakashi Iwai { 22050, (2 << 4), (3 << 3) },
1711bd9debfSTakashi Iwai { 37800, (2 << 4), (4 << 3) },
1721bd9debfSTakashi Iwai { 44100, (2 << 4), (5 << 3) },
1731bd9debfSTakashi Iwai { 33075, (2 << 4), (6 << 3) },
1741bd9debfSTakashi Iwai { 6615, (2 << 4), (7 << 3) },
1751bd9debfSTakashi Iwai { 0, 0, 0}
1761bd9debfSTakashi Iwai };
1771bd9debfSTakashi Iwai
1781bd9debfSTakashi Iwai #define CS4215_HPF (1<<7) /* High Pass Filter, 1: Enabled */
1791bd9debfSTakashi Iwai
1801bd9debfSTakashi Iwai #define CS4215_12_MASK 0xfcbf /* Mask off reserved bits in slot 1 & 2 */
1811bd9debfSTakashi Iwai
1821bd9debfSTakashi Iwai /* Time Slot 3, Serial Port Control register */
1831bd9debfSTakashi Iwai #define CS4215_XEN (1<<0) /* 0: Enable serial output */
1841bd9debfSTakashi Iwai #define CS4215_XCLK (1<<1) /* 1: Master mode: Generate SCLK */
1851bd9debfSTakashi Iwai #define CS4215_BSEL_64 (0<<2) /* Bitrate: 64 bits per frame */
1861bd9debfSTakashi Iwai #define CS4215_BSEL_128 (1<<2)
1871bd9debfSTakashi Iwai #define CS4215_BSEL_256 (2<<2)
1881bd9debfSTakashi Iwai #define CS4215_MCK_MAST (0<<4) /* Master clock */
1891bd9debfSTakashi Iwai #define CS4215_MCK_XTL1 (1<<4) /* 24.576 MHz clock source */
1901bd9debfSTakashi Iwai #define CS4215_MCK_XTL2 (2<<4) /* 16.9344 MHz clock source */
1911bd9debfSTakashi Iwai #define CS4215_MCK_CLK1 (3<<4) /* Clockin, 256 x Fs */
1921bd9debfSTakashi Iwai #define CS4215_MCK_CLK2 (4<<4) /* Clockin, see DFR */
1931bd9debfSTakashi Iwai
1941bd9debfSTakashi Iwai /* Time Slot 4, Test Register */
1951bd9debfSTakashi Iwai #define CS4215_DAD (1<<0) /* 0:Digital-Dig loop, 1:Dig-Analog-Dig loop */
1961bd9debfSTakashi Iwai #define CS4215_ENL (1<<1) /* Enable Loopback Testing */
1971bd9debfSTakashi Iwai
1981bd9debfSTakashi Iwai /* Time Slot 5, Parallel Port Register */
1991bd9debfSTakashi Iwai /* Read only here and the same as the in data mode */
2001bd9debfSTakashi Iwai
2011bd9debfSTakashi Iwai /* Time Slot 6, Reserved */
2021bd9debfSTakashi Iwai
2031bd9debfSTakashi Iwai /* Time Slot 7, Version Register */
2041bd9debfSTakashi Iwai #define CS4215_VERSION_MASK 0xf /* Known versions 0/C, 1/D, 2/E */
2051bd9debfSTakashi Iwai
2061bd9debfSTakashi Iwai /* Time Slot 8, Reserved */
2071bd9debfSTakashi Iwai
2081bd9debfSTakashi Iwai /*
2091bd9debfSTakashi Iwai * Data mode
2101bd9debfSTakashi Iwai */
2111bd9debfSTakashi Iwai /* Time Slot 1-2: Left Channel Data, 2-3: Right Channel Data */
2121bd9debfSTakashi Iwai
2131bd9debfSTakashi Iwai /* Time Slot 5, Output Setting */
2141bd9debfSTakashi Iwai #define CS4215_LO(v) v /* Left Output Attenuation 0x3f: -94.5 dB */
2151bd9debfSTakashi Iwai #define CS4215_LE (1<<6) /* Line Out Enable */
2161bd9debfSTakashi Iwai #define CS4215_HE (1<<7) /* Headphone Enable */
2171bd9debfSTakashi Iwai
2181bd9debfSTakashi Iwai /* Time Slot 6, Output Setting */
2191bd9debfSTakashi Iwai #define CS4215_RO(v) v /* Right Output Attenuation 0x3f: -94.5 dB */
2201bd9debfSTakashi Iwai #define CS4215_SE (1<<6) /* Speaker Enable */
2211bd9debfSTakashi Iwai #define CS4215_ADI (1<<7) /* A/D Data Invalid: Busy in calibration */
2221bd9debfSTakashi Iwai
2231bd9debfSTakashi Iwai /* Time Slot 7, Input Setting */
2241bd9debfSTakashi Iwai #define CS4215_LG(v) v /* Left Gain Setting 0xf: 22.5 dB */
2251bd9debfSTakashi Iwai #define CS4215_IS (1<<4) /* Input Select: 1=Microphone, 0=Line */
2261bd9debfSTakashi Iwai #define CS4215_OVR (1<<5) /* 1: Over range condition occurred */
2271bd9debfSTakashi Iwai #define CS4215_PIO0 (1<<6) /* Parallel I/O 0 */
2281bd9debfSTakashi Iwai #define CS4215_PIO1 (1<<7)
2291bd9debfSTakashi Iwai
2301bd9debfSTakashi Iwai /* Time Slot 8, Input Setting */
2311bd9debfSTakashi Iwai #define CS4215_RG(v) v /* Right Gain Setting 0xf: 22.5 dB */
2321bd9debfSTakashi Iwai #define CS4215_MA(v) (v<<4) /* Monitor Path Attenuation 0xf: mute */
2331bd9debfSTakashi Iwai
2341bd9debfSTakashi Iwai /***************************************************************************
2351bd9debfSTakashi Iwai DBRI specific definitions and structures
2361bd9debfSTakashi Iwai ****************************************************************************/
2371bd9debfSTakashi Iwai
2381bd9debfSTakashi Iwai /* DBRI main registers */
239cf68d212SKrzysztof Helt #define REG0 0x00 /* Status and Control */
240cf68d212SKrzysztof Helt #define REG1 0x04 /* Mode and Interrupt */
241cf68d212SKrzysztof Helt #define REG2 0x08 /* Parallel IO */
242cf68d212SKrzysztof Helt #define REG3 0x0c /* Test */
243cf68d212SKrzysztof Helt #define REG8 0x20 /* Command Queue Pointer */
244cf68d212SKrzysztof Helt #define REG9 0x24 /* Interrupt Queue Pointer */
2451bd9debfSTakashi Iwai
2461bd9debfSTakashi Iwai #define DBRI_NO_CMDS 64
2471bd9debfSTakashi Iwai #define DBRI_INT_BLK 64
2481bd9debfSTakashi Iwai #define DBRI_NO_DESCS 64
2491bd9debfSTakashi Iwai #define DBRI_NO_PIPES 32
250470f1f1aSKrzysztof Helt #define DBRI_MAX_PIPE (DBRI_NO_PIPES - 1)
2511bd9debfSTakashi Iwai
2521bd9debfSTakashi Iwai #define DBRI_REC 0
2531bd9debfSTakashi Iwai #define DBRI_PLAY 1
2541bd9debfSTakashi Iwai #define DBRI_NO_STREAMS 2
2551bd9debfSTakashi Iwai
2561bd9debfSTakashi Iwai /* One transmit/receive descriptor */
257c2735446SKrzysztof Helt /* When ba != 0 descriptor is used */
2581bd9debfSTakashi Iwai struct dbri_mem {
2591bd9debfSTakashi Iwai volatile __u32 word1;
26016727d94SKrzysztof Helt __u32 ba; /* Transmit/Receive Buffer Address */
26116727d94SKrzysztof Helt __u32 nda; /* Next Descriptor Address */
2621bd9debfSTakashi Iwai volatile __u32 word4;
2631bd9debfSTakashi Iwai };
2641bd9debfSTakashi Iwai
2651bd9debfSTakashi Iwai /* This structure is in a DMA region where it can accessed by both
2661bd9debfSTakashi Iwai * the CPU and the DBRI
2671bd9debfSTakashi Iwai */
2681bd9debfSTakashi Iwai struct dbri_dma {
2691be54c82SKrzysztof Helt s32 cmd[DBRI_NO_CMDS]; /* Place for commands */
2706fb98280SKrzysztof Helt volatile s32 intr[DBRI_INT_BLK]; /* Interrupt field */
2711bd9debfSTakashi Iwai struct dbri_mem desc[DBRI_NO_DESCS]; /* Xmit/receive descriptors */
2721bd9debfSTakashi Iwai };
2731bd9debfSTakashi Iwai
2741bd9debfSTakashi Iwai #define dbri_dma_off(member, elem) \
2751bd9debfSTakashi Iwai ((u32)(unsigned long) \
2761bd9debfSTakashi Iwai (&(((struct dbri_dma *)0)->member[elem])))
2771bd9debfSTakashi Iwai
2781bd9debfSTakashi Iwai enum in_or_out { PIPEinput, PIPEoutput };
2791bd9debfSTakashi Iwai
2801bd9debfSTakashi Iwai struct dbri_pipe {
2811bd9debfSTakashi Iwai u32 sdp; /* SDP command word */
2821bd9debfSTakashi Iwai int nextpipe; /* Next pipe in linked list */
2831bd9debfSTakashi Iwai int length; /* Length of timeslot (bits) */
2841bd9debfSTakashi Iwai int first_desc; /* Index of first descriptor */
2851bd9debfSTakashi Iwai int desc; /* Index of active descriptor */
2861bd9debfSTakashi Iwai volatile __u32 *recv_fixed_ptr; /* Ptr to receive fixed data */
2871bd9debfSTakashi Iwai };
2881bd9debfSTakashi Iwai
2891bd9debfSTakashi Iwai /* Per stream (playback or record) information */
290475675d6STakashi Iwai struct dbri_streaminfo {
291475675d6STakashi Iwai struct snd_pcm_substream *substream;
292098ccbc5SKrzysztof Helt u32 dvma_buffer; /* Device view of ALSA DMA buffer */
2931bd9debfSTakashi Iwai int size; /* Size of DMA buffer */
2941bd9debfSTakashi Iwai size_t offset; /* offset in user buffer */
2951bd9debfSTakashi Iwai int pipe; /* Data pipe used */
2961bd9debfSTakashi Iwai int left_gain; /* mixer elements */
2971bd9debfSTakashi Iwai int right_gain;
298475675d6STakashi Iwai };
2991bd9debfSTakashi Iwai
3001bd9debfSTakashi Iwai /* This structure holds the information for both chips (DBRI & CS4215) */
301475675d6STakashi Iwai struct snd_dbri {
3021bd9debfSTakashi Iwai int regs_size, irq; /* Needed for unload */
3032dc11581SGrant Likely struct platform_device *op; /* OF device info */
3041bd9debfSTakashi Iwai spinlock_t lock;
3051bd9debfSTakashi Iwai
30616727d94SKrzysztof Helt struct dbri_dma *dma; /* Pointer to our DMA block */
30716f46050STushar Dave dma_addr_t dma_dvma; /* DBRI visible DMA address */
3081bd9debfSTakashi Iwai
3091bd9debfSTakashi Iwai void __iomem *regs; /* dbri HW regs */
3101bd9debfSTakashi Iwai int dbri_irqp; /* intr queue pointer */
3111bd9debfSTakashi Iwai
3121bd9debfSTakashi Iwai struct dbri_pipe pipes[DBRI_NO_PIPES]; /* DBRI's 32 data pipes */
313c2735446SKrzysztof Helt int next_desc[DBRI_NO_DESCS]; /* Index of next desc, or -1 */
3141be54c82SKrzysztof Helt spinlock_t cmdlock; /* Protects cmd queue accesses */
3151be54c82SKrzysztof Helt s32 *cmdptr; /* Pointer to the last queued cmd */
3161bd9debfSTakashi Iwai
3171bd9debfSTakashi Iwai int chi_bpf;
3181bd9debfSTakashi Iwai
3191bd9debfSTakashi Iwai struct cs4215 mm; /* mmcodec special info */
3201bd9debfSTakashi Iwai /* per stream (playback/record) info */
3211bd9debfSTakashi Iwai struct dbri_streaminfo stream_info[DBRI_NO_STREAMS];
322475675d6STakashi Iwai };
3231bd9debfSTakashi Iwai
3241bd9debfSTakashi Iwai #define DBRI_MAX_VOLUME 63 /* Output volume */
3251bd9debfSTakashi Iwai #define DBRI_MAX_GAIN 15 /* Input gain */
3261bd9debfSTakashi Iwai
3271bd9debfSTakashi Iwai /* DBRI Reg0 - Status Control Register - defines. (Page 17) */
3281bd9debfSTakashi Iwai #define D_P (1<<15) /* Program command & queue pointer valid */
3291bd9debfSTakashi Iwai #define D_G (1<<14) /* Allow 4-Word SBus Burst */
3301bd9debfSTakashi Iwai #define D_S (1<<13) /* Allow 16-Word SBus Burst */
3311bd9debfSTakashi Iwai #define D_E (1<<12) /* Allow 8-Word SBus Burst */
3321bd9debfSTakashi Iwai #define D_X (1<<7) /* Sanity Timer Disable */
3331bd9debfSTakashi Iwai #define D_T (1<<6) /* Permit activation of the TE interface */
3341bd9debfSTakashi Iwai #define D_N (1<<5) /* Permit activation of the NT interface */
3351bd9debfSTakashi Iwai #define D_C (1<<4) /* Permit activation of the CHI interface */
3361bd9debfSTakashi Iwai #define D_F (1<<3) /* Force Sanity Timer Time-Out */
3371bd9debfSTakashi Iwai #define D_D (1<<2) /* Disable Master Mode */
3381bd9debfSTakashi Iwai #define D_H (1<<1) /* Halt for Analysis */
3391bd9debfSTakashi Iwai #define D_R (1<<0) /* Soft Reset */
3401bd9debfSTakashi Iwai
3411bd9debfSTakashi Iwai /* DBRI Reg1 - Mode and Interrupt Register - defines. (Page 18) */
3421bd9debfSTakashi Iwai #define D_LITTLE_END (1<<8) /* Byte Order */
3431bd9debfSTakashi Iwai #define D_BIG_END (0<<8) /* Byte Order */
3441bd9debfSTakashi Iwai #define D_MRR (1<<4) /* Multiple Error Ack on SBus (read only) */
3451bd9debfSTakashi Iwai #define D_MLE (1<<3) /* Multiple Late Error on SBus (read only) */
3461bd9debfSTakashi Iwai #define D_LBG (1<<2) /* Lost Bus Grant on SBus (read only) */
3471bd9debfSTakashi Iwai #define D_MBE (1<<1) /* Burst Error on SBus (read only) */
3481bd9debfSTakashi Iwai #define D_IR (1<<0) /* Interrupt Indicator (read only) */
3491bd9debfSTakashi Iwai
3501bd9debfSTakashi Iwai /* DBRI Reg2 - Parallel IO Register - defines. (Page 18) */
3511bd9debfSTakashi Iwai #define D_ENPIO3 (1<<7) /* Enable Pin 3 */
3521bd9debfSTakashi Iwai #define D_ENPIO2 (1<<6) /* Enable Pin 2 */
3531bd9debfSTakashi Iwai #define D_ENPIO1 (1<<5) /* Enable Pin 1 */
3541bd9debfSTakashi Iwai #define D_ENPIO0 (1<<4) /* Enable Pin 0 */
3551bd9debfSTakashi Iwai #define D_ENPIO (0xf0) /* Enable all the pins */
3561bd9debfSTakashi Iwai #define D_PIO3 (1<<3) /* Pin 3: 1: Data mode, 0: Ctrl mode */
3571bd9debfSTakashi Iwai #define D_PIO2 (1<<2) /* Pin 2: 1: Onboard PDN */
3581bd9debfSTakashi Iwai #define D_PIO1 (1<<1) /* Pin 1: 0: Reset */
3591bd9debfSTakashi Iwai #define D_PIO0 (1<<0) /* Pin 0: 1: Speakerbox PDN */
3601bd9debfSTakashi Iwai
3611bd9debfSTakashi Iwai /* DBRI Commands (Page 20) */
3621bd9debfSTakashi Iwai #define D_WAIT 0x0 /* Stop execution */
3631bd9debfSTakashi Iwai #define D_PAUSE 0x1 /* Flush long pipes */
3641bd9debfSTakashi Iwai #define D_JUMP 0x2 /* New command queue */
3651bd9debfSTakashi Iwai #define D_IIQ 0x3 /* Initialize Interrupt Queue */
3661bd9debfSTakashi Iwai #define D_REX 0x4 /* Report command execution via interrupt */
3671bd9debfSTakashi Iwai #define D_SDP 0x5 /* Setup Data Pipe */
3681bd9debfSTakashi Iwai #define D_CDP 0x6 /* Continue Data Pipe (reread NULL Pointer) */
3691bd9debfSTakashi Iwai #define D_DTS 0x7 /* Define Time Slot */
3701bd9debfSTakashi Iwai #define D_SSP 0x8 /* Set short Data Pipe */
3711bd9debfSTakashi Iwai #define D_CHI 0x9 /* Set CHI Global Mode */
3721bd9debfSTakashi Iwai #define D_NT 0xa /* NT Command */
3731bd9debfSTakashi Iwai #define D_TE 0xb /* TE Command */
3741bd9debfSTakashi Iwai #define D_CDEC 0xc /* Codec setup */
3751bd9debfSTakashi Iwai #define D_TEST 0xd /* No comment */
3761bd9debfSTakashi Iwai #define D_CDM 0xe /* CHI Data mode command */
3771bd9debfSTakashi Iwai
3781bd9debfSTakashi Iwai /* Special bits for some commands */
379098ccbc5SKrzysztof Helt #define D_PIPE(v) ((v)<<0) /* Pipe No.: 0-15 long, 16-21 short */
3801bd9debfSTakashi Iwai
3811bd9debfSTakashi Iwai /* Setup Data Pipe */
3821bd9debfSTakashi Iwai /* IRM */
383098ccbc5SKrzysztof Helt #define D_SDP_2SAME (1<<18) /* Report 2nd time in a row value received */
3841bd9debfSTakashi Iwai #define D_SDP_CHANGE (2<<18) /* Report any changes */
3851bd9debfSTakashi Iwai #define D_SDP_EVERY (3<<18) /* Report any changes */
3861bd9debfSTakashi Iwai #define D_SDP_EOL (1<<17) /* EOL interrupt enable */
3871bd9debfSTakashi Iwai #define D_SDP_IDLE (1<<16) /* HDLC idle interrupt enable */
3881bd9debfSTakashi Iwai
3891bd9debfSTakashi Iwai /* Pipe data MODE */
3901bd9debfSTakashi Iwai #define D_SDP_MEM (0<<13) /* To/from memory */
3911bd9debfSTakashi Iwai #define D_SDP_HDLC (2<<13)
3921bd9debfSTakashi Iwai #define D_SDP_HDLC_D (3<<13) /* D Channel (prio control) */
3931bd9debfSTakashi Iwai #define D_SDP_SER (4<<13) /* Serial to serial */
3941bd9debfSTakashi Iwai #define D_SDP_FIXED (6<<13) /* Short only */
3951bd9debfSTakashi Iwai #define D_SDP_MODE(v) ((v)&(7<<13))
3961bd9debfSTakashi Iwai
3971bd9debfSTakashi Iwai #define D_SDP_TO_SER (1<<12) /* Direction */
3981bd9debfSTakashi Iwai #define D_SDP_FROM_SER (0<<12) /* Direction */
3991bd9debfSTakashi Iwai #define D_SDP_MSB (1<<11) /* Bit order within Byte */
4001bd9debfSTakashi Iwai #define D_SDP_LSB (0<<11) /* Bit order within Byte */
4011bd9debfSTakashi Iwai #define D_SDP_P (1<<10) /* Pointer Valid */
4021bd9debfSTakashi Iwai #define D_SDP_A (1<<8) /* Abort */
4031bd9debfSTakashi Iwai #define D_SDP_C (1<<7) /* Clear */
4041bd9debfSTakashi Iwai
4051bd9debfSTakashi Iwai /* Define Time Slot */
4061bd9debfSTakashi Iwai #define D_DTS_VI (1<<17) /* Valid Input Time-Slot Descriptor */
4071bd9debfSTakashi Iwai #define D_DTS_VO (1<<16) /* Valid Output Time-Slot Descriptor */
4081bd9debfSTakashi Iwai #define D_DTS_INS (1<<15) /* Insert Time Slot */
4091bd9debfSTakashi Iwai #define D_DTS_DEL (0<<15) /* Delete Time Slot */
4101bd9debfSTakashi Iwai #define D_DTS_PRVIN(v) ((v)<<10) /* Previous In Pipe */
4111bd9debfSTakashi Iwai #define D_DTS_PRVOUT(v) ((v)<<5) /* Previous Out Pipe */
4121bd9debfSTakashi Iwai
4131bd9debfSTakashi Iwai /* Time Slot defines */
4141bd9debfSTakashi Iwai #define D_TS_LEN(v) ((v)<<24) /* Number of bits in this time slot */
4151bd9debfSTakashi Iwai #define D_TS_CYCLE(v) ((v)<<14) /* Bit Count at start of TS */
4161bd9debfSTakashi Iwai #define D_TS_DI (1<<13) /* Data Invert */
4171bd9debfSTakashi Iwai #define D_TS_1CHANNEL (0<<10) /* Single Channel / Normal mode */
4181bd9debfSTakashi Iwai #define D_TS_MONITOR (2<<10) /* Monitor pipe */
4191bd9debfSTakashi Iwai #define D_TS_NONCONTIG (3<<10) /* Non contiguous mode */
4201bd9debfSTakashi Iwai #define D_TS_ANCHOR (7<<10) /* Starting short pipes */
4211bd9debfSTakashi Iwai #define D_TS_MON(v) ((v)<<5) /* Monitor Pipe */
422098ccbc5SKrzysztof Helt #define D_TS_NEXT(v) ((v)<<0) /* Pipe no.: 0-15 long, 16-21 short */
4231bd9debfSTakashi Iwai
4241bd9debfSTakashi Iwai /* Concentration Highway Interface Modes */
4251bd9debfSTakashi Iwai #define D_CHI_CHICM(v) ((v)<<16) /* Clock mode */
4261bd9debfSTakashi Iwai #define D_CHI_IR (1<<15) /* Immediate Interrupt Report */
4271bd9debfSTakashi Iwai #define D_CHI_EN (1<<14) /* CHIL Interrupt enabled */
4281bd9debfSTakashi Iwai #define D_CHI_OD (1<<13) /* Open Drain Enable */
4291bd9debfSTakashi Iwai #define D_CHI_FE (1<<12) /* Sample CHIFS on Rising Frame Edge */
4301bd9debfSTakashi Iwai #define D_CHI_FD (1<<11) /* Frame Drive */
4311bd9debfSTakashi Iwai #define D_CHI_BPF(v) ((v)<<0) /* Bits per Frame */
4321bd9debfSTakashi Iwai
4331bd9debfSTakashi Iwai /* NT: These are here for completeness */
4341bd9debfSTakashi Iwai #define D_NT_FBIT (1<<17) /* Frame Bit */
4351bd9debfSTakashi Iwai #define D_NT_NBF (1<<16) /* Number of bad frames to loose framing */
4361bd9debfSTakashi Iwai #define D_NT_IRM_IMM (1<<15) /* Interrupt Report & Mask: Immediate */
4371bd9debfSTakashi Iwai #define D_NT_IRM_EN (1<<14) /* Interrupt Report & Mask: Enable */
438098ccbc5SKrzysztof Helt #define D_NT_ISNT (1<<13) /* Configure interface as NT */
4391bd9debfSTakashi Iwai #define D_NT_FT (1<<12) /* Fixed Timing */
4401bd9debfSTakashi Iwai #define D_NT_EZ (1<<11) /* Echo Channel is Zeros */
4411bd9debfSTakashi Iwai #define D_NT_IFA (1<<10) /* Inhibit Final Activation */
4421bd9debfSTakashi Iwai #define D_NT_ACT (1<<9) /* Activate Interface */
4431bd9debfSTakashi Iwai #define D_NT_MFE (1<<8) /* Multiframe Enable */
4441bd9debfSTakashi Iwai #define D_NT_RLB(v) ((v)<<5) /* Remote Loopback */
4451bd9debfSTakashi Iwai #define D_NT_LLB(v) ((v)<<2) /* Local Loopback */
4461bd9debfSTakashi Iwai #define D_NT_FACT (1<<1) /* Force Activation */
4471bd9debfSTakashi Iwai #define D_NT_ABV (1<<0) /* Activate Bipolar Violation */
4481bd9debfSTakashi Iwai
4491bd9debfSTakashi Iwai /* Codec Setup */
4501bd9debfSTakashi Iwai #define D_CDEC_CK(v) ((v)<<24) /* Clock Select */
4511bd9debfSTakashi Iwai #define D_CDEC_FED(v) ((v)<<12) /* FSCOD Falling Edge Delay */
4521bd9debfSTakashi Iwai #define D_CDEC_RED(v) ((v)<<0) /* FSCOD Rising Edge Delay */
4531bd9debfSTakashi Iwai
4541bd9debfSTakashi Iwai /* Test */
4551bd9debfSTakashi Iwai #define D_TEST_RAM(v) ((v)<<16) /* RAM Pointer */
4561bd9debfSTakashi Iwai #define D_TEST_SIZE(v) ((v)<<11) /* */
4571bd9debfSTakashi Iwai #define D_TEST_ROMONOFF 0x5 /* Toggle ROM opcode monitor on/off */
458098ccbc5SKrzysztof Helt #define D_TEST_PROC 0x6 /* Microprocessor test */
4591bd9debfSTakashi Iwai #define D_TEST_SER 0x7 /* Serial-Controller test */
4601bd9debfSTakashi Iwai #define D_TEST_RAMREAD 0x8 /* Copy from Ram to system memory */
4611bd9debfSTakashi Iwai #define D_TEST_RAMWRITE 0x9 /* Copy into Ram from system memory */
4621bd9debfSTakashi Iwai #define D_TEST_RAMBIST 0xa /* RAM Built-In Self Test */
4631bd9debfSTakashi Iwai #define D_TEST_MCBIST 0xb /* Microcontroller Built-In Self Test */
4641bd9debfSTakashi Iwai #define D_TEST_DUMP 0xe /* ROM Dump */
4651bd9debfSTakashi Iwai
4661bd9debfSTakashi Iwai /* CHI Data Mode */
4671bd9debfSTakashi Iwai #define D_CDM_THI (1 << 8) /* Transmit Data on CHIDR Pin */
4681bd9debfSTakashi Iwai #define D_CDM_RHI (1 << 7) /* Receive Data on CHIDX Pin */
4691bd9debfSTakashi Iwai #define D_CDM_RCE (1 << 6) /* Receive on Rising Edge of CHICK */
4701bd9debfSTakashi Iwai #define D_CDM_XCE (1 << 2) /* Transmit Data on Rising Edge of CHICK */
4711bd9debfSTakashi Iwai #define D_CDM_XEN (1 << 1) /* Transmit Highway Enable */
4721bd9debfSTakashi Iwai #define D_CDM_REN (1 << 0) /* Receive Highway Enable */
4731bd9debfSTakashi Iwai
4741bd9debfSTakashi Iwai /* The Interrupts */
4751bd9debfSTakashi Iwai #define D_INTR_BRDY 1 /* Buffer Ready for processing */
4761bd9debfSTakashi Iwai #define D_INTR_MINT 2 /* Marked Interrupt in RD/TD */
4771bd9debfSTakashi Iwai #define D_INTR_IBEG 3 /* Flag to idle transition detected (HDLC) */
4781bd9debfSTakashi Iwai #define D_INTR_IEND 4 /* Idle to flag transition detected (HDLC) */
4791bd9debfSTakashi Iwai #define D_INTR_EOL 5 /* End of List */
4801bd9debfSTakashi Iwai #define D_INTR_CMDI 6 /* Command has bean read */
4811bd9debfSTakashi Iwai #define D_INTR_XCMP 8 /* Transmission of frame complete */
4821bd9debfSTakashi Iwai #define D_INTR_SBRI 9 /* BRI status change info */
4831bd9debfSTakashi Iwai #define D_INTR_FXDT 10 /* Fixed data change */
4841bd9debfSTakashi Iwai #define D_INTR_CHIL 11 /* CHI lost frame sync (channel 36 only) */
4851bd9debfSTakashi Iwai #define D_INTR_COLL 11 /* Unrecoverable D-Channel collision */
4861bd9debfSTakashi Iwai #define D_INTR_DBYT 12 /* Dropped by frame slip */
4871bd9debfSTakashi Iwai #define D_INTR_RBYT 13 /* Repeated by frame slip */
4881bd9debfSTakashi Iwai #define D_INTR_LINT 14 /* Lost Interrupt */
4891bd9debfSTakashi Iwai #define D_INTR_UNDR 15 /* DMA underrun */
4901bd9debfSTakashi Iwai
4911bd9debfSTakashi Iwai #define D_INTR_TE 32
4921bd9debfSTakashi Iwai #define D_INTR_NT 34
4931bd9debfSTakashi Iwai #define D_INTR_CHI 36
4941bd9debfSTakashi Iwai #define D_INTR_CMD 38
4951bd9debfSTakashi Iwai
4961bd9debfSTakashi Iwai #define D_INTR_GETCHAN(v) (((v) >> 24) & 0x3f)
4971bd9debfSTakashi Iwai #define D_INTR_GETCODE(v) (((v) >> 20) & 0xf)
4981bd9debfSTakashi Iwai #define D_INTR_GETCMD(v) (((v) >> 16) & 0xf)
4991bd9debfSTakashi Iwai #define D_INTR_GETVAL(v) ((v) & 0xffff)
5001bd9debfSTakashi Iwai #define D_INTR_GETRVAL(v) ((v) & 0xfffff)
5011bd9debfSTakashi Iwai
5021bd9debfSTakashi Iwai #define D_P_0 0 /* TE receive anchor */
5031bd9debfSTakashi Iwai #define D_P_1 1 /* TE transmit anchor */
5041bd9debfSTakashi Iwai #define D_P_2 2 /* NT transmit anchor */
5051bd9debfSTakashi Iwai #define D_P_3 3 /* NT receive anchor */
5061bd9debfSTakashi Iwai #define D_P_4 4 /* CHI send data */
5071bd9debfSTakashi Iwai #define D_P_5 5 /* CHI receive data */
5081bd9debfSTakashi Iwai #define D_P_6 6 /* */
5091bd9debfSTakashi Iwai #define D_P_7 7 /* */
5101bd9debfSTakashi Iwai #define D_P_8 8 /* */
5111bd9debfSTakashi Iwai #define D_P_9 9 /* */
5121bd9debfSTakashi Iwai #define D_P_10 10 /* */
5131bd9debfSTakashi Iwai #define D_P_11 11 /* */
5141bd9debfSTakashi Iwai #define D_P_12 12 /* */
5151bd9debfSTakashi Iwai #define D_P_13 13 /* */
5161bd9debfSTakashi Iwai #define D_P_14 14 /* */
5171bd9debfSTakashi Iwai #define D_P_15 15 /* */
5181bd9debfSTakashi Iwai #define D_P_16 16 /* CHI anchor pipe */
5191bd9debfSTakashi Iwai #define D_P_17 17 /* CHI send */
5201bd9debfSTakashi Iwai #define D_P_18 18 /* CHI receive */
5211bd9debfSTakashi Iwai #define D_P_19 19 /* CHI receive */
5221bd9debfSTakashi Iwai #define D_P_20 20 /* CHI receive */
5231bd9debfSTakashi Iwai #define D_P_21 21 /* */
5241bd9debfSTakashi Iwai #define D_P_22 22 /* */
5251bd9debfSTakashi Iwai #define D_P_23 23 /* */
5261bd9debfSTakashi Iwai #define D_P_24 24 /* */
5271bd9debfSTakashi Iwai #define D_P_25 25 /* */
5281bd9debfSTakashi Iwai #define D_P_26 26 /* */
5291bd9debfSTakashi Iwai #define D_P_27 27 /* */
5301bd9debfSTakashi Iwai #define D_P_28 28 /* */
5311bd9debfSTakashi Iwai #define D_P_29 29 /* */
5321bd9debfSTakashi Iwai #define D_P_30 30 /* */
5331bd9debfSTakashi Iwai #define D_P_31 31 /* */
5341bd9debfSTakashi Iwai
5351bd9debfSTakashi Iwai /* Transmit descriptor defines */
5361bd9debfSTakashi Iwai #define DBRI_TD_F (1 << 31) /* End of Frame */
5371bd9debfSTakashi Iwai #define DBRI_TD_D (1 << 30) /* Do not append CRC */
5381bd9debfSTakashi Iwai #define DBRI_TD_CNT(v) ((v) << 16) /* Number of valid bytes in the buffer */
5391bd9debfSTakashi Iwai #define DBRI_TD_B (1 << 15) /* Final interrupt */
5401bd9debfSTakashi Iwai #define DBRI_TD_M (1 << 14) /* Marker interrupt */
5411bd9debfSTakashi Iwai #define DBRI_TD_I (1 << 13) /* Transmit Idle Characters */
5421bd9debfSTakashi Iwai #define DBRI_TD_FCNT(v) (v) /* Flag Count */
5431bd9debfSTakashi Iwai #define DBRI_TD_UNR (1 << 3) /* Underrun: transmitter is out of data */
5441bd9debfSTakashi Iwai #define DBRI_TD_ABT (1 << 2) /* Abort: frame aborted */
5451bd9debfSTakashi Iwai #define DBRI_TD_TBC (1 << 0) /* Transmit buffer Complete */
5461bd9debfSTakashi Iwai #define DBRI_TD_STATUS(v) ((v) & 0xff) /* Transmit status */
547098ccbc5SKrzysztof Helt /* Maximum buffer size per TD: almost 8KB */
5481be54c82SKrzysztof Helt #define DBRI_TD_MAXCNT ((1 << 13) - 4)
5491bd9debfSTakashi Iwai
5501bd9debfSTakashi Iwai /* Receive descriptor defines */
5511bd9debfSTakashi Iwai #define DBRI_RD_F (1 << 31) /* End of Frame */
5521bd9debfSTakashi Iwai #define DBRI_RD_C (1 << 30) /* Completed buffer */
5531bd9debfSTakashi Iwai #define DBRI_RD_B (1 << 15) /* Final interrupt */
5541bd9debfSTakashi Iwai #define DBRI_RD_M (1 << 14) /* Marker interrupt */
5551bd9debfSTakashi Iwai #define DBRI_RD_BCNT(v) (v) /* Buffer size */
5561bd9debfSTakashi Iwai #define DBRI_RD_CRC (1 << 7) /* 0: CRC is correct */
5571bd9debfSTakashi Iwai #define DBRI_RD_BBC (1 << 6) /* 1: Bad Byte received */
5581bd9debfSTakashi Iwai #define DBRI_RD_ABT (1 << 5) /* Abort: frame aborted */
5591bd9debfSTakashi Iwai #define DBRI_RD_OVRN (1 << 3) /* Overrun: data lost */
5601bd9debfSTakashi Iwai #define DBRI_RD_STATUS(v) ((v) & 0xff) /* Receive status */
5611bd9debfSTakashi Iwai #define DBRI_RD_CNT(v) (((v) >> 16) & 0x1fff) /* Valid bytes in the buffer */
5621bd9debfSTakashi Iwai
5631bd9debfSTakashi Iwai /* stream_info[] access */
5641bd9debfSTakashi Iwai /* Translate the ALSA direction into the array index */
5651bd9debfSTakashi Iwai #define DBRI_STREAMNO(substream) \
5661bd9debfSTakashi Iwai (substream->stream == \
5671bd9debfSTakashi Iwai SNDRV_PCM_STREAM_PLAYBACK ? DBRI_PLAY: DBRI_REC)
5681bd9debfSTakashi Iwai
5691bd9debfSTakashi Iwai /* Return a pointer to dbri_streaminfo */
570098ccbc5SKrzysztof Helt #define DBRI_STREAM(dbri, substream) \
571098ccbc5SKrzysztof Helt &dbri->stream_info[DBRI_STREAMNO(substream)]
5721bd9debfSTakashi Iwai
5731bd9debfSTakashi Iwai /*
5741bd9debfSTakashi Iwai * Short data pipes transmit LSB first. The CS4215 receives MSB first. Grrr.
5751bd9debfSTakashi Iwai * So we have to reverse the bits. Note: not all bit lengths are supported
5761bd9debfSTakashi Iwai */
reverse_bytes(__u32 b,int len)5771bd9debfSTakashi Iwai static __u32 reverse_bytes(__u32 b, int len)
5781bd9debfSTakashi Iwai {
5791bd9debfSTakashi Iwai switch (len) {
5801bd9debfSTakashi Iwai case 32:
5811bd9debfSTakashi Iwai b = ((b & 0xffff0000) >> 16) | ((b & 0x0000ffff) << 16);
582c0dbbdadSGustavo A. R. Silva fallthrough;
5831bd9debfSTakashi Iwai case 16:
5841bd9debfSTakashi Iwai b = ((b & 0xff00ff00) >> 8) | ((b & 0x00ff00ff) << 8);
585c0dbbdadSGustavo A. R. Silva fallthrough;
5861bd9debfSTakashi Iwai case 8:
5871bd9debfSTakashi Iwai b = ((b & 0xf0f0f0f0) >> 4) | ((b & 0x0f0f0f0f) << 4);
588c0dbbdadSGustavo A. R. Silva fallthrough;
5891bd9debfSTakashi Iwai case 4:
5901bd9debfSTakashi Iwai b = ((b & 0xcccccccc) >> 2) | ((b & 0x33333333) << 2);
591c0dbbdadSGustavo A. R. Silva fallthrough;
5921bd9debfSTakashi Iwai case 2:
5931bd9debfSTakashi Iwai b = ((b & 0xaaaaaaaa) >> 1) | ((b & 0x55555555) << 1);
5941bd9debfSTakashi Iwai case 1:
5951bd9debfSTakashi Iwai case 0:
5961bd9debfSTakashi Iwai break;
5971bd9debfSTakashi Iwai default:
5981bd9debfSTakashi Iwai printk(KERN_ERR "DBRI reverse_bytes: unsupported length\n");
599395d9dd5SPeter Senna Tschudin }
6001bd9debfSTakashi Iwai
6011bd9debfSTakashi Iwai return b;
6021bd9debfSTakashi Iwai }
6031bd9debfSTakashi Iwai
6041bd9debfSTakashi Iwai /*
6051bd9debfSTakashi Iwai ****************************************************************************
6061bd9debfSTakashi Iwai ************** DBRI initialization and command synchronization *************
6071bd9debfSTakashi Iwai ****************************************************************************
6081bd9debfSTakashi Iwai
6091bd9debfSTakashi Iwai Commands are sent to the DBRI by building a list of them in memory,
6101bd9debfSTakashi Iwai then writing the address of the first list item to DBRI register 8.
6114338829eSMartin Habets The list is terminated with a WAIT command, which generates a
6124338829eSMartin Habets CPU interrupt to signal completion.
6131bd9debfSTakashi Iwai
6141bd9debfSTakashi Iwai Since the DBRI can run in parallel with the CPU, several means of
615cf68d212SKrzysztof Helt synchronization present themselves. The method implemented here uses
616cf68d212SKrzysztof Helt the dbri_cmdwait() to wait for execution of batch of sent commands.
6171bd9debfSTakashi Iwai
6181be54c82SKrzysztof Helt A circular command buffer is used here. A new command is being added
619aaad3653SKrzysztof Helt while another can be executed. The scheme works by adding two WAIT commands
6201be54c82SKrzysztof Helt after each sent batch of commands. When the next batch is prepared it is
6211be54c82SKrzysztof Helt added after the WAIT commands then the WAITs are replaced with single JUMP
622a97cbcd0SRandy Dunlap command to the new batch. Then the DBRI is forced to reread the last WAIT
6231be54c82SKrzysztof Helt command (replaced by the JUMP by then). If the DBRI is still executing
6241be54c82SKrzysztof Helt previous commands the request to reread the WAIT command is ignored.
6251bd9debfSTakashi Iwai
6261bd9debfSTakashi Iwai Every time a routine wants to write commands to the DBRI, it must
6271be54c82SKrzysztof Helt first call dbri_cmdlock() and get pointer to a free space in
6281be54c82SKrzysztof Helt dbri->dma->cmd buffer. After this, the commands can be written to
6291be54c82SKrzysztof Helt the buffer, and dbri_cmdsend() is called with the final pointer value
6301be54c82SKrzysztof Helt to send them to the DBRI.
6311bd9debfSTakashi Iwai
6321bd9debfSTakashi Iwai */
6331bd9debfSTakashi Iwai
634aaad3653SKrzysztof Helt #define MAXLOOPS 20
6351be54c82SKrzysztof Helt /*
6361be54c82SKrzysztof Helt * Wait for the current command string to execute
6371be54c82SKrzysztof Helt */
dbri_cmdwait(struct snd_dbri * dbri)6381be54c82SKrzysztof Helt static void dbri_cmdwait(struct snd_dbri *dbri)
6391bd9debfSTakashi Iwai {
6404338829eSMartin Habets int maxloops = MAXLOOPS;
641ea543f1eSKrzysztof Helt unsigned long flags;
6424338829eSMartin Habets
6434338829eSMartin Habets /* Delay if previous commands are still being processed */
644ea543f1eSKrzysztof Helt spin_lock_irqsave(&dbri->lock, flags);
645ea543f1eSKrzysztof Helt while ((--maxloops) > 0 && (sbus_readl(dbri->regs + REG0) & D_P)) {
646ea543f1eSKrzysztof Helt spin_unlock_irqrestore(&dbri->lock, flags);
6474338829eSMartin Habets msleep_interruptible(1);
648ea543f1eSKrzysztof Helt spin_lock_irqsave(&dbri->lock, flags);
649ea543f1eSKrzysztof Helt }
650ea543f1eSKrzysztof Helt spin_unlock_irqrestore(&dbri->lock, flags);
6511be54c82SKrzysztof Helt
652cf68d212SKrzysztof Helt if (maxloops == 0)
6531be54c82SKrzysztof Helt printk(KERN_ERR "DBRI: Chip never completed command buffer\n");
654cf68d212SKrzysztof Helt else
6554338829eSMartin Habets dprintk(D_CMD, "Chip completed command buffer (%d)\n",
6564338829eSMartin Habets MAXLOOPS - maxloops - 1);
6574338829eSMartin Habets }
6581be54c82SKrzysztof Helt /*
659cf68d212SKrzysztof Helt * Lock the command queue and return pointer to space for len cmd words
6601be54c82SKrzysztof Helt * It locks the cmdlock spinlock.
6611be54c82SKrzysztof Helt */
dbri_cmdlock(struct snd_dbri * dbri,int len)6621be54c82SKrzysztof Helt static s32 *dbri_cmdlock(struct snd_dbri *dbri, int len)
6631be54c82SKrzysztof Helt {
66416f46050STushar Dave u32 dvma_addr = (u32)dbri->dma_dvma;
66516f46050STushar Dave
6661be54c82SKrzysztof Helt /* Space for 2 WAIT cmds (replaced later by 1 JUMP cmd) */
6671be54c82SKrzysztof Helt len += 2;
6681be54c82SKrzysztof Helt spin_lock(&dbri->cmdlock);
6691be54c82SKrzysztof Helt if (dbri->cmdptr - dbri->dma->cmd + len < DBRI_NO_CMDS - 2)
6701be54c82SKrzysztof Helt return dbri->cmdptr + 2;
67116f46050STushar Dave else if (len < sbus_readl(dbri->regs + REG8) - dvma_addr)
6721be54c82SKrzysztof Helt return dbri->dma->cmd;
6731be54c82SKrzysztof Helt else
6741be54c82SKrzysztof Helt printk(KERN_ERR "DBRI: no space for commands.");
6754338829eSMartin Habets
676ae97dd9aSAl Viro return NULL;
6771bd9debfSTakashi Iwai }
6781bd9debfSTakashi Iwai
6791be54c82SKrzysztof Helt /*
680beb7dd86SRobert P. J. Day * Send prepared cmd string. It works by writing a JUMP cmd into
6811be54c82SKrzysztof Helt * the last WAIT cmd and force DBRI to reread the cmd.
682ab93c7aeSKrzysztof Helt * The JUMP cmd points to the new cmd string.
6831be54c82SKrzysztof Helt * It also releases the cmdlock spinlock.
684ea543f1eSKrzysztof Helt *
685ca405870SKrzysztof Helt * Lock must be held before calling this.
6861be54c82SKrzysztof Helt */
dbri_cmdsend(struct snd_dbri * dbri,s32 * cmd,int len)6871be54c82SKrzysztof Helt static void dbri_cmdsend(struct snd_dbri *dbri, s32 *cmd, int len)
6881bd9debfSTakashi Iwai {
68916f46050STushar Dave u32 dvma_addr = (u32)dbri->dma_dvma;
6901be54c82SKrzysztof Helt s32 tmp, addr;
691808709d7SJason Wang static int wait_id;
6921bd9debfSTakashi Iwai
6931be54c82SKrzysztof Helt wait_id++;
6941be54c82SKrzysztof Helt wait_id &= 0xffff; /* restrict it to a 16 bit counter. */
6951be54c82SKrzysztof Helt *(cmd) = DBRI_CMD(D_WAIT, 1, wait_id);
6961be54c82SKrzysztof Helt *(cmd+1) = DBRI_CMD(D_WAIT, 1, wait_id);
6971be54c82SKrzysztof Helt
6981be54c82SKrzysztof Helt /* Replace the last command with JUMP */
69916f46050STushar Dave addr = dvma_addr + (cmd - len - dbri->dma->cmd) * sizeof(s32);
7001be54c82SKrzysztof Helt *(dbri->cmdptr+1) = addr;
7011be54c82SKrzysztof Helt *(dbri->cmdptr) = DBRI_CMD(D_JUMP, 0, 0);
7021be54c82SKrzysztof Helt
7031be54c82SKrzysztof Helt #ifdef DBRI_DEBUG
704ab93c7aeSKrzysztof Helt if (cmd > dbri->cmdptr) {
705ab93c7aeSKrzysztof Helt s32 *ptr;
706ab93c7aeSKrzysztof Helt
707aaad3653SKrzysztof Helt for (ptr = dbri->cmdptr; ptr < cmd+2; ptr++)
708098ccbc5SKrzysztof Helt dprintk(D_CMD, "cmd: %lx:%08x\n",
709098ccbc5SKrzysztof Helt (unsigned long)ptr, *ptr);
710ab93c7aeSKrzysztof Helt } else {
711ab93c7aeSKrzysztof Helt s32 *ptr = dbri->cmdptr;
712ab93c7aeSKrzysztof Helt
7131be54c82SKrzysztof Helt dprintk(D_CMD, "cmd: %lx:%08x\n", (unsigned long)ptr, *ptr);
714ab93c7aeSKrzysztof Helt ptr++;
7151be54c82SKrzysztof Helt dprintk(D_CMD, "cmd: %lx:%08x\n", (unsigned long)ptr, *ptr);
716098ccbc5SKrzysztof Helt for (ptr = dbri->dma->cmd; ptr < cmd+2; ptr++)
717098ccbc5SKrzysztof Helt dprintk(D_CMD, "cmd: %lx:%08x\n",
718098ccbc5SKrzysztof Helt (unsigned long)ptr, *ptr);
7191be54c82SKrzysztof Helt }
7201be54c82SKrzysztof Helt #endif
7211bd9debfSTakashi Iwai
7221be54c82SKrzysztof Helt /* Reread the last command */
7231be54c82SKrzysztof Helt tmp = sbus_readl(dbri->regs + REG0);
7241be54c82SKrzysztof Helt tmp |= D_P;
7251be54c82SKrzysztof Helt sbus_writel(tmp, dbri->regs + REG0);
7264338829eSMartin Habets
7271be54c82SKrzysztof Helt dbri->cmdptr = cmd;
7281be54c82SKrzysztof Helt spin_unlock(&dbri->cmdlock);
7291bd9debfSTakashi Iwai }
7301bd9debfSTakashi Iwai
7311bd9debfSTakashi Iwai /* Lock must be held when calling this */
dbri_reset(struct snd_dbri * dbri)732475675d6STakashi Iwai static void dbri_reset(struct snd_dbri *dbri)
7331bd9debfSTakashi Iwai {
7341bd9debfSTakashi Iwai int i;
735d1fdf07eSKrzysztof Helt u32 tmp;
7361bd9debfSTakashi Iwai
7371bd9debfSTakashi Iwai dprintk(D_GEN, "reset 0:%x 2:%x 8:%x 9:%x\n",
7381bd9debfSTakashi Iwai sbus_readl(dbri->regs + REG0),
7391bd9debfSTakashi Iwai sbus_readl(dbri->regs + REG2),
7401bd9debfSTakashi Iwai sbus_readl(dbri->regs + REG8), sbus_readl(dbri->regs + REG9));
7411bd9debfSTakashi Iwai
7421bd9debfSTakashi Iwai sbus_writel(D_R, dbri->regs + REG0); /* Soft Reset */
7431bd9debfSTakashi Iwai for (i = 0; (sbus_readl(dbri->regs + REG0) & D_R) && i < 64; i++)
7441bd9debfSTakashi Iwai udelay(10);
745d1fdf07eSKrzysztof Helt
746d1fdf07eSKrzysztof Helt /* A brute approach - DBRI falls back to working burst size by itself
747d1fdf07eSKrzysztof Helt * On SS20 D_S does not work, so do not try so high. */
748d1fdf07eSKrzysztof Helt tmp = sbus_readl(dbri->regs + REG0);
749d1fdf07eSKrzysztof Helt tmp |= D_G | D_E;
750d1fdf07eSKrzysztof Helt tmp &= ~D_S;
751d1fdf07eSKrzysztof Helt sbus_writel(tmp, dbri->regs + REG0);
7521bd9debfSTakashi Iwai }
7531bd9debfSTakashi Iwai
7541bd9debfSTakashi Iwai /* Lock must not be held before calling this */
dbri_initialize(struct snd_dbri * dbri)75532e02a7bSBill Pemberton static void dbri_initialize(struct snd_dbri *dbri)
7561bd9debfSTakashi Iwai {
75716f46050STushar Dave u32 dvma_addr = (u32)dbri->dma_dvma;
7581be54c82SKrzysztof Helt s32 *cmd;
759d1fdf07eSKrzysztof Helt u32 dma_addr;
7601bd9debfSTakashi Iwai unsigned long flags;
7611bd9debfSTakashi Iwai int n;
7621bd9debfSTakashi Iwai
7631bd9debfSTakashi Iwai spin_lock_irqsave(&dbri->lock, flags);
7641bd9debfSTakashi Iwai
7651bd9debfSTakashi Iwai dbri_reset(dbri);
7661bd9debfSTakashi Iwai
7671bd9debfSTakashi Iwai /* Initialize pipes */
7681bd9debfSTakashi Iwai for (n = 0; n < DBRI_NO_PIPES; n++)
7691bd9debfSTakashi Iwai dbri->pipes[n].desc = dbri->pipes[n].first_desc = -1;
7701bd9debfSTakashi Iwai
7711be54c82SKrzysztof Helt spin_lock_init(&dbri->cmdlock);
7721bd9debfSTakashi Iwai /*
7736fb98280SKrzysztof Helt * Initialize the interrupt ring buffer.
7741bd9debfSTakashi Iwai */
77516f46050STushar Dave dma_addr = dvma_addr + dbri_dma_off(intr, 0);
7766fb98280SKrzysztof Helt dbri->dma->intr[0] = dma_addr;
7776fb98280SKrzysztof Helt dbri->dbri_irqp = 1;
7786fb98280SKrzysztof Helt /*
7796fb98280SKrzysztof Helt * Set up the interrupt queue
7806fb98280SKrzysztof Helt */
7811be54c82SKrzysztof Helt spin_lock(&dbri->cmdlock);
7821be54c82SKrzysztof Helt cmd = dbri->cmdptr = dbri->dma->cmd;
7831bd9debfSTakashi Iwai *(cmd++) = DBRI_CMD(D_IIQ, 0, 0);
7841bd9debfSTakashi Iwai *(cmd++) = dma_addr;
7851be54c82SKrzysztof Helt *(cmd++) = DBRI_CMD(D_PAUSE, 0, 0);
7861be54c82SKrzysztof Helt dbri->cmdptr = cmd;
7871be54c82SKrzysztof Helt *(cmd++) = DBRI_CMD(D_WAIT, 1, 0);
7881be54c82SKrzysztof Helt *(cmd++) = DBRI_CMD(D_WAIT, 1, 0);
78916f46050STushar Dave dma_addr = dvma_addr + dbri_dma_off(cmd, 0);
7901be54c82SKrzysztof Helt sbus_writel(dma_addr, dbri->regs + REG8);
7911be54c82SKrzysztof Helt spin_unlock(&dbri->cmdlock);
7921bd9debfSTakashi Iwai
7931bd9debfSTakashi Iwai spin_unlock_irqrestore(&dbri->lock, flags);
794ea543f1eSKrzysztof Helt dbri_cmdwait(dbri);
7951bd9debfSTakashi Iwai }
7961bd9debfSTakashi Iwai
7971bd9debfSTakashi Iwai /*
7981bd9debfSTakashi Iwai ****************************************************************************
7991bd9debfSTakashi Iwai ************************** DBRI data pipe management ***********************
8001bd9debfSTakashi Iwai ****************************************************************************
8011bd9debfSTakashi Iwai
8021bd9debfSTakashi Iwai While DBRI control functions use the command and interrupt buffers, the
8031bd9debfSTakashi Iwai main data path takes the form of data pipes, which can be short (command
8041bd9debfSTakashi Iwai and interrupt driven), or long (attached to DMA buffers). These functions
8051bd9debfSTakashi Iwai provide a rudimentary means of setting up and managing the DBRI's pipes,
8061bd9debfSTakashi Iwai but the calling functions have to make sure they respect the pipes' linked
8071bd9debfSTakashi Iwai list ordering, among other things. The transmit and receive functions
8081bd9debfSTakashi Iwai here interface closely with the transmit and receive interrupt code.
8091bd9debfSTakashi Iwai
8101bd9debfSTakashi Iwai */
pipe_active(struct snd_dbri * dbri,int pipe)811cf68d212SKrzysztof Helt static inline int pipe_active(struct snd_dbri *dbri, int pipe)
8121bd9debfSTakashi Iwai {
8131bd9debfSTakashi Iwai return ((pipe >= 0) && (dbri->pipes[pipe].desc != -1));
8141bd9debfSTakashi Iwai }
8151bd9debfSTakashi Iwai
8161bd9debfSTakashi Iwai /* reset_pipe(dbri, pipe)
8171bd9debfSTakashi Iwai *
8181bd9debfSTakashi Iwai * Called on an in-use pipe to clear anything being transmitted or received
8191bd9debfSTakashi Iwai * Lock must be held before calling this.
8201bd9debfSTakashi Iwai */
reset_pipe(struct snd_dbri * dbri,int pipe)821475675d6STakashi Iwai static void reset_pipe(struct snd_dbri *dbri, int pipe)
8221bd9debfSTakashi Iwai {
8231bd9debfSTakashi Iwai int sdp;
8241bd9debfSTakashi Iwai int desc;
8251be54c82SKrzysztof Helt s32 *cmd;
8261bd9debfSTakashi Iwai
827470f1f1aSKrzysztof Helt if (pipe < 0 || pipe > DBRI_MAX_PIPE) {
828098ccbc5SKrzysztof Helt printk(KERN_ERR "DBRI: reset_pipe called with "
829098ccbc5SKrzysztof Helt "illegal pipe number\n");
8301bd9debfSTakashi Iwai return;
8311bd9debfSTakashi Iwai }
8321bd9debfSTakashi Iwai
8331bd9debfSTakashi Iwai sdp = dbri->pipes[pipe].sdp;
8341bd9debfSTakashi Iwai if (sdp == 0) {
835098ccbc5SKrzysztof Helt printk(KERN_ERR "DBRI: reset_pipe called "
836098ccbc5SKrzysztof Helt "on uninitialized pipe\n");
8371bd9debfSTakashi Iwai return;
8381bd9debfSTakashi Iwai }
8391bd9debfSTakashi Iwai
8401be54c82SKrzysztof Helt cmd = dbri_cmdlock(dbri, 3);
8411bd9debfSTakashi Iwai *(cmd++) = DBRI_CMD(D_SDP, 0, sdp | D_SDP_C | D_SDP_P);
8421bd9debfSTakashi Iwai *(cmd++) = 0;
8431be54c82SKrzysztof Helt *(cmd++) = DBRI_CMD(D_PAUSE, 0, 0);
8441be54c82SKrzysztof Helt dbri_cmdsend(dbri, cmd, 3);
8451bd9debfSTakashi Iwai
8461bd9debfSTakashi Iwai desc = dbri->pipes[pipe].first_desc;
8471be54c82SKrzysztof Helt if (desc >= 0)
8481be54c82SKrzysztof Helt do {
849098ccbc5SKrzysztof Helt dbri->dma->desc[desc].ba = 0;
850098ccbc5SKrzysztof Helt dbri->dma->desc[desc].nda = 0;
851c2735446SKrzysztof Helt desc = dbri->next_desc[desc];
8521be54c82SKrzysztof Helt } while (desc != -1 && desc != dbri->pipes[pipe].first_desc);
8531bd9debfSTakashi Iwai
8541bd9debfSTakashi Iwai dbri->pipes[pipe].desc = -1;
8551bd9debfSTakashi Iwai dbri->pipes[pipe].first_desc = -1;
8561bd9debfSTakashi Iwai }
8571bd9debfSTakashi Iwai
858ea543f1eSKrzysztof Helt /*
859ea543f1eSKrzysztof Helt * Lock must be held before calling this.
860ea543f1eSKrzysztof Helt */
setup_pipe(struct snd_dbri * dbri,int pipe,int sdp)861475675d6STakashi Iwai static void setup_pipe(struct snd_dbri *dbri, int pipe, int sdp)
8621bd9debfSTakashi Iwai {
863470f1f1aSKrzysztof Helt if (pipe < 0 || pipe > DBRI_MAX_PIPE) {
864098ccbc5SKrzysztof Helt printk(KERN_ERR "DBRI: setup_pipe called "
865098ccbc5SKrzysztof Helt "with illegal pipe number\n");
8661bd9debfSTakashi Iwai return;
8671bd9debfSTakashi Iwai }
8681bd9debfSTakashi Iwai
8691bd9debfSTakashi Iwai if ((sdp & 0xf800) != sdp) {
870098ccbc5SKrzysztof Helt printk(KERN_ERR "DBRI: setup_pipe called "
871098ccbc5SKrzysztof Helt "with strange SDP value\n");
8721bd9debfSTakashi Iwai /* sdp &= 0xf800; */
8731bd9debfSTakashi Iwai }
8741bd9debfSTakashi Iwai
8751bd9debfSTakashi Iwai /* If this is a fixed receive pipe, arrange for an interrupt
8761bd9debfSTakashi Iwai * every time its data changes
8771bd9debfSTakashi Iwai */
8781bd9debfSTakashi Iwai if (D_SDP_MODE(sdp) == D_SDP_FIXED && !(sdp & D_SDP_TO_SER))
8791bd9debfSTakashi Iwai sdp |= D_SDP_CHANGE;
8801bd9debfSTakashi Iwai
8811bd9debfSTakashi Iwai sdp |= D_PIPE(pipe);
8821bd9debfSTakashi Iwai dbri->pipes[pipe].sdp = sdp;
8831bd9debfSTakashi Iwai dbri->pipes[pipe].desc = -1;
8841bd9debfSTakashi Iwai dbri->pipes[pipe].first_desc = -1;
8851bd9debfSTakashi Iwai
8861bd9debfSTakashi Iwai reset_pipe(dbri, pipe);
8871bd9debfSTakashi Iwai }
8881bd9debfSTakashi Iwai
889ea543f1eSKrzysztof Helt /*
890ea543f1eSKrzysztof Helt * Lock must be held before calling this.
891ea543f1eSKrzysztof Helt */
link_time_slot(struct snd_dbri * dbri,int pipe,int prevpipe,int nextpipe,int length,int cycle)892475675d6STakashi Iwai static void link_time_slot(struct snd_dbri *dbri, int pipe,
893294a30dcSKrzysztof Helt int prevpipe, int nextpipe,
8941bd9debfSTakashi Iwai int length, int cycle)
8951bd9debfSTakashi Iwai {
8961be54c82SKrzysztof Helt s32 *cmd;
8971bd9debfSTakashi Iwai int val;
8981bd9debfSTakashi Iwai
899294a30dcSKrzysztof Helt if (pipe < 0 || pipe > DBRI_MAX_PIPE
900294a30dcSKrzysztof Helt || prevpipe < 0 || prevpipe > DBRI_MAX_PIPE
901294a30dcSKrzysztof Helt || nextpipe < 0 || nextpipe > DBRI_MAX_PIPE) {
9024338829eSMartin Habets printk(KERN_ERR
9034338829eSMartin Habets "DBRI: link_time_slot called with illegal pipe number\n");
9041bd9debfSTakashi Iwai return;
9051bd9debfSTakashi Iwai }
9061bd9debfSTakashi Iwai
907294a30dcSKrzysztof Helt if (dbri->pipes[pipe].sdp == 0
908294a30dcSKrzysztof Helt || dbri->pipes[prevpipe].sdp == 0
909294a30dcSKrzysztof Helt || dbri->pipes[nextpipe].sdp == 0) {
910098ccbc5SKrzysztof Helt printk(KERN_ERR "DBRI: link_time_slot called "
911098ccbc5SKrzysztof Helt "on uninitialized pipe\n");
9121bd9debfSTakashi Iwai return;
9131bd9debfSTakashi Iwai }
9141bd9debfSTakashi Iwai
915294a30dcSKrzysztof Helt dbri->pipes[prevpipe].nextpipe = pipe;
916294a30dcSKrzysztof Helt dbri->pipes[pipe].nextpipe = nextpipe;
917294a30dcSKrzysztof Helt dbri->pipes[pipe].length = length;
918294a30dcSKrzysztof Helt
9191be54c82SKrzysztof Helt cmd = dbri_cmdlock(dbri, 4);
920294a30dcSKrzysztof Helt
921294a30dcSKrzysztof Helt if (dbri->pipes[pipe].sdp & D_SDP_TO_SER) {
9221bd9debfSTakashi Iwai /* Deal with CHI special case:
9231bd9debfSTakashi Iwai * "If transmission on edges 0 or 1 is desired, then cycle n
9241bd9debfSTakashi Iwai * (where n = # of bit times per frame...) must be used."
9251bd9debfSTakashi Iwai * - DBRI data sheet, page 11
9261bd9debfSTakashi Iwai */
927294a30dcSKrzysztof Helt if (prevpipe == 16 && cycle == 0)
9281bd9debfSTakashi Iwai cycle = dbri->chi_bpf;
9291bd9debfSTakashi Iwai
9301bd9debfSTakashi Iwai val = D_DTS_VO | D_DTS_INS | D_DTS_PRVOUT(prevpipe) | pipe;
9311bd9debfSTakashi Iwai *(cmd++) = DBRI_CMD(D_DTS, 0, val);
9321bd9debfSTakashi Iwai *(cmd++) = 0;
9331bd9debfSTakashi Iwai *(cmd++) =
9341bd9debfSTakashi Iwai D_TS_LEN(length) | D_TS_CYCLE(cycle) | D_TS_NEXT(nextpipe);
935294a30dcSKrzysztof Helt } else {
936294a30dcSKrzysztof Helt val = D_DTS_VI | D_DTS_INS | D_DTS_PRVIN(prevpipe) | pipe;
937294a30dcSKrzysztof Helt *(cmd++) = DBRI_CMD(D_DTS, 0, val);
938294a30dcSKrzysztof Helt *(cmd++) =
939294a30dcSKrzysztof Helt D_TS_LEN(length) | D_TS_CYCLE(cycle) | D_TS_NEXT(nextpipe);
940294a30dcSKrzysztof Helt *(cmd++) = 0;
9411bd9debfSTakashi Iwai }
9421be54c82SKrzysztof Helt *(cmd++) = DBRI_CMD(D_PAUSE, 0, 0);
9431bd9debfSTakashi Iwai
9441be54c82SKrzysztof Helt dbri_cmdsend(dbri, cmd, 4);
9451bd9debfSTakashi Iwai }
9461bd9debfSTakashi Iwai
947ea543f1eSKrzysztof Helt #if 0
948ea543f1eSKrzysztof Helt /*
949ea543f1eSKrzysztof Helt * Lock must be held before calling this.
950ea543f1eSKrzysztof Helt */
951475675d6STakashi Iwai static void unlink_time_slot(struct snd_dbri *dbri, int pipe,
9521bd9debfSTakashi Iwai enum in_or_out direction, int prevpipe,
9531bd9debfSTakashi Iwai int nextpipe)
9541bd9debfSTakashi Iwai {
9551be54c82SKrzysztof Helt s32 *cmd;
9561bd9debfSTakashi Iwai int val;
9571bd9debfSTakashi Iwai
958470f1f1aSKrzysztof Helt if (pipe < 0 || pipe > DBRI_MAX_PIPE
9591be54c82SKrzysztof Helt || prevpipe < 0 || prevpipe > DBRI_MAX_PIPE
9601be54c82SKrzysztof Helt || nextpipe < 0 || nextpipe > DBRI_MAX_PIPE) {
9614338829eSMartin Habets printk(KERN_ERR
9624338829eSMartin Habets "DBRI: unlink_time_slot called with illegal pipe number\n");
9631bd9debfSTakashi Iwai return;
9641bd9debfSTakashi Iwai }
9651bd9debfSTakashi Iwai
9661be54c82SKrzysztof Helt cmd = dbri_cmdlock(dbri, 4);
9671bd9debfSTakashi Iwai
9681bd9debfSTakashi Iwai if (direction == PIPEinput) {
9691bd9debfSTakashi Iwai val = D_DTS_VI | D_DTS_DEL | D_DTS_PRVIN(prevpipe) | pipe;
9701bd9debfSTakashi Iwai *(cmd++) = DBRI_CMD(D_DTS, 0, val);
9711bd9debfSTakashi Iwai *(cmd++) = D_TS_NEXT(nextpipe);
9721bd9debfSTakashi Iwai *(cmd++) = 0;
9731bd9debfSTakashi Iwai } else {
9741bd9debfSTakashi Iwai val = D_DTS_VO | D_DTS_DEL | D_DTS_PRVOUT(prevpipe) | pipe;
9751bd9debfSTakashi Iwai *(cmd++) = DBRI_CMD(D_DTS, 0, val);
9761bd9debfSTakashi Iwai *(cmd++) = 0;
9771bd9debfSTakashi Iwai *(cmd++) = D_TS_NEXT(nextpipe);
9781bd9debfSTakashi Iwai }
9791be54c82SKrzysztof Helt *(cmd++) = DBRI_CMD(D_PAUSE, 0, 0);
9801bd9debfSTakashi Iwai
9811be54c82SKrzysztof Helt dbri_cmdsend(dbri, cmd, 4);
9821bd9debfSTakashi Iwai }
983ea543f1eSKrzysztof Helt #endif
9841bd9debfSTakashi Iwai
9851bd9debfSTakashi Iwai /* xmit_fixed() / recv_fixed()
9861bd9debfSTakashi Iwai *
9871bd9debfSTakashi Iwai * Transmit/receive data on a "fixed" pipe - i.e, one whose contents are not
9881bd9debfSTakashi Iwai * expected to change much, and which we don't need to buffer.
9891bd9debfSTakashi Iwai * The DBRI only interrupts us when the data changes (receive pipes),
9901bd9debfSTakashi Iwai * or only changes the data when this function is called (transmit pipes).
9911bd9debfSTakashi Iwai * Only short pipes (numbers 16-31) can be used in fixed data mode.
9921bd9debfSTakashi Iwai *
9931bd9debfSTakashi Iwai * These function operate on a 32-bit field, no matter how large
9941bd9debfSTakashi Iwai * the actual time slot is. The interrupt handler takes care of bit
9951bd9debfSTakashi Iwai * ordering and alignment. An 8-bit time slot will always end up
9961bd9debfSTakashi Iwai * in the low-order 8 bits, filled either MSB-first or LSB-first,
997ea543f1eSKrzysztof Helt * depending on the settings passed to setup_pipe().
998ea543f1eSKrzysztof Helt *
999ea543f1eSKrzysztof Helt * Lock must not be held before calling it.
10001bd9debfSTakashi Iwai */
xmit_fixed(struct snd_dbri * dbri,int pipe,unsigned int data)1001475675d6STakashi Iwai static void xmit_fixed(struct snd_dbri *dbri, int pipe, unsigned int data)
10021bd9debfSTakashi Iwai {
10031be54c82SKrzysztof Helt s32 *cmd;
1004ea543f1eSKrzysztof Helt unsigned long flags;
10051bd9debfSTakashi Iwai
1006470f1f1aSKrzysztof Helt if (pipe < 16 || pipe > DBRI_MAX_PIPE) {
10074338829eSMartin Habets printk(KERN_ERR "DBRI: xmit_fixed: Illegal pipe number\n");
10081bd9debfSTakashi Iwai return;
10091bd9debfSTakashi Iwai }
10101bd9debfSTakashi Iwai
10111bd9debfSTakashi Iwai if (D_SDP_MODE(dbri->pipes[pipe].sdp) == 0) {
1012098ccbc5SKrzysztof Helt printk(KERN_ERR "DBRI: xmit_fixed: "
1013098ccbc5SKrzysztof Helt "Uninitialized pipe %d\n", pipe);
10141bd9debfSTakashi Iwai return;
10151bd9debfSTakashi Iwai }
10161bd9debfSTakashi Iwai
10171bd9debfSTakashi Iwai if (D_SDP_MODE(dbri->pipes[pipe].sdp) != D_SDP_FIXED) {
10184338829eSMartin Habets printk(KERN_ERR "DBRI: xmit_fixed: Non-fixed pipe %d\n", pipe);
10191bd9debfSTakashi Iwai return;
10201bd9debfSTakashi Iwai }
10211bd9debfSTakashi Iwai
10221bd9debfSTakashi Iwai if (!(dbri->pipes[pipe].sdp & D_SDP_TO_SER)) {
1023098ccbc5SKrzysztof Helt printk(KERN_ERR "DBRI: xmit_fixed: Called on receive pipe %d\n",
1024098ccbc5SKrzysztof Helt pipe);
10251bd9debfSTakashi Iwai return;
10261bd9debfSTakashi Iwai }
10271bd9debfSTakashi Iwai
10281bd9debfSTakashi Iwai /* DBRI short pipes always transmit LSB first */
10291bd9debfSTakashi Iwai
10301bd9debfSTakashi Iwai if (dbri->pipes[pipe].sdp & D_SDP_MSB)
10311bd9debfSTakashi Iwai data = reverse_bytes(data, dbri->pipes[pipe].length);
10321bd9debfSTakashi Iwai
10331be54c82SKrzysztof Helt cmd = dbri_cmdlock(dbri, 3);
10341bd9debfSTakashi Iwai
10351bd9debfSTakashi Iwai *(cmd++) = DBRI_CMD(D_SSP, 0, pipe);
10361bd9debfSTakashi Iwai *(cmd++) = data;
10371be54c82SKrzysztof Helt *(cmd++) = DBRI_CMD(D_PAUSE, 0, 0);
10381bd9debfSTakashi Iwai
1039ea543f1eSKrzysztof Helt spin_lock_irqsave(&dbri->lock, flags);
10401be54c82SKrzysztof Helt dbri_cmdsend(dbri, cmd, 3);
1041ea543f1eSKrzysztof Helt spin_unlock_irqrestore(&dbri->lock, flags);
10421be54c82SKrzysztof Helt dbri_cmdwait(dbri);
1043ea543f1eSKrzysztof Helt
10441bd9debfSTakashi Iwai }
10451bd9debfSTakashi Iwai
recv_fixed(struct snd_dbri * dbri,int pipe,volatile __u32 * ptr)1046475675d6STakashi Iwai static void recv_fixed(struct snd_dbri *dbri, int pipe, volatile __u32 *ptr)
10471bd9debfSTakashi Iwai {
1048470f1f1aSKrzysztof Helt if (pipe < 16 || pipe > DBRI_MAX_PIPE) {
1049098ccbc5SKrzysztof Helt printk(KERN_ERR "DBRI: recv_fixed called with "
1050098ccbc5SKrzysztof Helt "illegal pipe number\n");
10511bd9debfSTakashi Iwai return;
10521bd9debfSTakashi Iwai }
10531bd9debfSTakashi Iwai
10541bd9debfSTakashi Iwai if (D_SDP_MODE(dbri->pipes[pipe].sdp) != D_SDP_FIXED) {
1055098ccbc5SKrzysztof Helt printk(KERN_ERR "DBRI: recv_fixed called on "
1056098ccbc5SKrzysztof Helt "non-fixed pipe %d\n", pipe);
10571bd9debfSTakashi Iwai return;
10581bd9debfSTakashi Iwai }
10591bd9debfSTakashi Iwai
10601bd9debfSTakashi Iwai if (dbri->pipes[pipe].sdp & D_SDP_TO_SER) {
1061098ccbc5SKrzysztof Helt printk(KERN_ERR "DBRI: recv_fixed called on "
1062098ccbc5SKrzysztof Helt "transmit pipe %d\n", pipe);
10631bd9debfSTakashi Iwai return;
10641bd9debfSTakashi Iwai }
10651bd9debfSTakashi Iwai
10661bd9debfSTakashi Iwai dbri->pipes[pipe].recv_fixed_ptr = ptr;
10671bd9debfSTakashi Iwai }
10681bd9debfSTakashi Iwai
10691bd9debfSTakashi Iwai /* setup_descs()
10701bd9debfSTakashi Iwai *
10711bd9debfSTakashi Iwai * Setup transmit/receive data on a "long" pipe - i.e, one associated
10721bd9debfSTakashi Iwai * with a DMA buffer.
10731bd9debfSTakashi Iwai *
10741bd9debfSTakashi Iwai * Only pipe numbers 0-15 can be used in this mode.
10751bd9debfSTakashi Iwai *
10761bd9debfSTakashi Iwai * This function takes a stream number pointing to a data buffer,
10771bd9debfSTakashi Iwai * and work by building chains of descriptors which identify the
10781bd9debfSTakashi Iwai * data buffers. Buffers too large for a single descriptor will
10791bd9debfSTakashi Iwai * be spread across multiple descriptors.
10801be54c82SKrzysztof Helt *
10811be54c82SKrzysztof Helt * All descriptors create a ring buffer.
1082ea543f1eSKrzysztof Helt *
1083ea543f1eSKrzysztof Helt * Lock must be held before calling this.
10841bd9debfSTakashi Iwai */
setup_descs(struct snd_dbri * dbri,int streamno,unsigned int period)1085475675d6STakashi Iwai static int setup_descs(struct snd_dbri *dbri, int streamno, unsigned int period)
10861bd9debfSTakashi Iwai {
1087475675d6STakashi Iwai struct dbri_streaminfo *info = &dbri->stream_info[streamno];
108816f46050STushar Dave u32 dvma_addr = (u32)dbri->dma_dvma;
10891bd9debfSTakashi Iwai __u32 dvma_buffer;
109099dabfe7SKrzysztof Helt int desc;
10911bd9debfSTakashi Iwai int len;
10921bd9debfSTakashi Iwai int first_desc = -1;
10931bd9debfSTakashi Iwai int last_desc = -1;
10941bd9debfSTakashi Iwai
10951bd9debfSTakashi Iwai if (info->pipe < 0 || info->pipe > 15) {
10964338829eSMartin Habets printk(KERN_ERR "DBRI: setup_descs: Illegal pipe number\n");
10971bd9debfSTakashi Iwai return -2;
10981bd9debfSTakashi Iwai }
10991bd9debfSTakashi Iwai
11001bd9debfSTakashi Iwai if (dbri->pipes[info->pipe].sdp == 0) {
11014338829eSMartin Habets printk(KERN_ERR "DBRI: setup_descs: Uninitialized pipe %d\n",
11021bd9debfSTakashi Iwai info->pipe);
11031bd9debfSTakashi Iwai return -2;
11041bd9debfSTakashi Iwai }
11051bd9debfSTakashi Iwai
11061bd9debfSTakashi Iwai dvma_buffer = info->dvma_buffer;
11071bd9debfSTakashi Iwai len = info->size;
11081bd9debfSTakashi Iwai
11091bd9debfSTakashi Iwai if (streamno == DBRI_PLAY) {
11101bd9debfSTakashi Iwai if (!(dbri->pipes[info->pipe].sdp & D_SDP_TO_SER)) {
1111098ccbc5SKrzysztof Helt printk(KERN_ERR "DBRI: setup_descs: "
1112098ccbc5SKrzysztof Helt "Called on receive pipe %d\n", info->pipe);
11131bd9debfSTakashi Iwai return -2;
11141bd9debfSTakashi Iwai }
11151bd9debfSTakashi Iwai } else {
11161bd9debfSTakashi Iwai if (dbri->pipes[info->pipe].sdp & D_SDP_TO_SER) {
11174338829eSMartin Habets printk(KERN_ERR
11184338829eSMartin Habets "DBRI: setup_descs: Called on transmit pipe %d\n",
11191bd9debfSTakashi Iwai info->pipe);
11201bd9debfSTakashi Iwai return -2;
11211bd9debfSTakashi Iwai }
1122098ccbc5SKrzysztof Helt /* Should be able to queue multiple buffers
1123098ccbc5SKrzysztof Helt * to receive on a pipe
1124098ccbc5SKrzysztof Helt */
11251bd9debfSTakashi Iwai if (pipe_active(dbri, info->pipe)) {
1126098ccbc5SKrzysztof Helt printk(KERN_ERR "DBRI: recv_on_pipe: "
1127098ccbc5SKrzysztof Helt "Called on active pipe %d\n", info->pipe);
11281bd9debfSTakashi Iwai return -2;
11291bd9debfSTakashi Iwai }
11301bd9debfSTakashi Iwai
11311bd9debfSTakashi Iwai /* Make sure buffer size is multiple of four */
11321bd9debfSTakashi Iwai len &= ~3;
11331bd9debfSTakashi Iwai }
11341bd9debfSTakashi Iwai
113599dabfe7SKrzysztof Helt /* Free descriptors if pipe has any */
113699dabfe7SKrzysztof Helt desc = dbri->pipes[info->pipe].first_desc;
113799dabfe7SKrzysztof Helt if (desc >= 0)
113899dabfe7SKrzysztof Helt do {
1139098ccbc5SKrzysztof Helt dbri->dma->desc[desc].ba = 0;
1140098ccbc5SKrzysztof Helt dbri->dma->desc[desc].nda = 0;
114199dabfe7SKrzysztof Helt desc = dbri->next_desc[desc];
1142098ccbc5SKrzysztof Helt } while (desc != -1 &&
1143098ccbc5SKrzysztof Helt desc != dbri->pipes[info->pipe].first_desc);
114499dabfe7SKrzysztof Helt
114599dabfe7SKrzysztof Helt dbri->pipes[info->pipe].desc = -1;
114699dabfe7SKrzysztof Helt dbri->pipes[info->pipe].first_desc = -1;
114799dabfe7SKrzysztof Helt
114899dabfe7SKrzysztof Helt desc = 0;
11491bd9debfSTakashi Iwai while (len > 0) {
11501bd9debfSTakashi Iwai int mylen;
11511bd9debfSTakashi Iwai
11521bd9debfSTakashi Iwai for (; desc < DBRI_NO_DESCS; desc++) {
1153c2735446SKrzysztof Helt if (!dbri->dma->desc[desc].ba)
11541bd9debfSTakashi Iwai break;
11551bd9debfSTakashi Iwai }
1156cf68d212SKrzysztof Helt
11571bd9debfSTakashi Iwai if (desc == DBRI_NO_DESCS) {
11584338829eSMartin Habets printk(KERN_ERR "DBRI: setup_descs: No descriptors\n");
11591bd9debfSTakashi Iwai return -1;
11601bd9debfSTakashi Iwai }
11611bd9debfSTakashi Iwai
11621be54c82SKrzysztof Helt if (len > DBRI_TD_MAXCNT)
11631be54c82SKrzysztof Helt mylen = DBRI_TD_MAXCNT; /* 8KB - 4 */
11641be54c82SKrzysztof Helt else
11651bd9debfSTakashi Iwai mylen = len;
11661be54c82SKrzysztof Helt
11671be54c82SKrzysztof Helt if (mylen > period)
11681bd9debfSTakashi Iwai mylen = period;
11691bd9debfSTakashi Iwai
1170c2735446SKrzysztof Helt dbri->next_desc[desc] = -1;
11711bd9debfSTakashi Iwai dbri->dma->desc[desc].ba = dvma_buffer;
11721bd9debfSTakashi Iwai dbri->dma->desc[desc].nda = 0;
11731bd9debfSTakashi Iwai
11741bd9debfSTakashi Iwai if (streamno == DBRI_PLAY) {
11751bd9debfSTakashi Iwai dbri->dma->desc[desc].word1 = DBRI_TD_CNT(mylen);
11761bd9debfSTakashi Iwai dbri->dma->desc[desc].word4 = 0;
1177098ccbc5SKrzysztof Helt dbri->dma->desc[desc].word1 |= DBRI_TD_F | DBRI_TD_B;
11781bd9debfSTakashi Iwai } else {
11791bd9debfSTakashi Iwai dbri->dma->desc[desc].word1 = 0;
11801bd9debfSTakashi Iwai dbri->dma->desc[desc].word4 =
11811bd9debfSTakashi Iwai DBRI_RD_B | DBRI_RD_BCNT(mylen);
11821bd9debfSTakashi Iwai }
11831bd9debfSTakashi Iwai
11841be54c82SKrzysztof Helt if (first_desc == -1)
11851bd9debfSTakashi Iwai first_desc = desc;
11861be54c82SKrzysztof Helt else {
1187c2735446SKrzysztof Helt dbri->next_desc[last_desc] = desc;
11881bd9debfSTakashi Iwai dbri->dma->desc[last_desc].nda =
118916f46050STushar Dave dvma_addr + dbri_dma_off(desc, desc);
11901bd9debfSTakashi Iwai }
11911bd9debfSTakashi Iwai
11921bd9debfSTakashi Iwai last_desc = desc;
11931bd9debfSTakashi Iwai dvma_buffer += mylen;
11941bd9debfSTakashi Iwai len -= mylen;
11951bd9debfSTakashi Iwai }
11961bd9debfSTakashi Iwai
11971bd9debfSTakashi Iwai if (first_desc == -1 || last_desc == -1) {
1198098ccbc5SKrzysztof Helt printk(KERN_ERR "DBRI: setup_descs: "
1199098ccbc5SKrzysztof Helt " Not enough descriptors available\n");
12001bd9debfSTakashi Iwai return -1;
12011bd9debfSTakashi Iwai }
12021bd9debfSTakashi Iwai
12031be54c82SKrzysztof Helt dbri->dma->desc[last_desc].nda =
120416f46050STushar Dave dvma_addr + dbri_dma_off(desc, first_desc);
12051be54c82SKrzysztof Helt dbri->next_desc[last_desc] = first_desc;
12061bd9debfSTakashi Iwai dbri->pipes[info->pipe].first_desc = first_desc;
12071bd9debfSTakashi Iwai dbri->pipes[info->pipe].desc = first_desc;
12081bd9debfSTakashi Iwai
12091be54c82SKrzysztof Helt #ifdef DBRI_DEBUG
12101be54c82SKrzysztof Helt for (desc = first_desc; desc != -1;) {
12111bd9debfSTakashi Iwai dprintk(D_DESC, "DESC %d: %08x %08x %08x %08x\n",
12121bd9debfSTakashi Iwai desc,
12131bd9debfSTakashi Iwai dbri->dma->desc[desc].word1,
12141bd9debfSTakashi Iwai dbri->dma->desc[desc].ba,
12151bd9debfSTakashi Iwai dbri->dma->desc[desc].nda, dbri->dma->desc[desc].word4);
12161be54c82SKrzysztof Helt desc = dbri->next_desc[desc];
12171be54c82SKrzysztof Helt if (desc == first_desc)
12181be54c82SKrzysztof Helt break;
12191bd9debfSTakashi Iwai }
12201be54c82SKrzysztof Helt #endif
12211bd9debfSTakashi Iwai return 0;
12221bd9debfSTakashi Iwai }
12231bd9debfSTakashi Iwai
12241bd9debfSTakashi Iwai /*
12251bd9debfSTakashi Iwai ****************************************************************************
12261bd9debfSTakashi Iwai ************************** DBRI - CHI interface ****************************
12271bd9debfSTakashi Iwai ****************************************************************************
12281bd9debfSTakashi Iwai
12291bd9debfSTakashi Iwai The CHI is a four-wire (clock, frame sync, data in, data out) time-division
12301bd9debfSTakashi Iwai multiplexed serial interface which the DBRI can operate in either master
12311bd9debfSTakashi Iwai (give clock/frame sync) or slave (take clock/frame sync) mode.
12321bd9debfSTakashi Iwai
12331bd9debfSTakashi Iwai */
12341bd9debfSTakashi Iwai
12351bd9debfSTakashi Iwai enum master_or_slave { CHImaster, CHIslave };
12361bd9debfSTakashi Iwai
1237ea543f1eSKrzysztof Helt /*
1238ea543f1eSKrzysztof Helt * Lock must not be held before calling it.
1239ea543f1eSKrzysztof Helt */
reset_chi(struct snd_dbri * dbri,enum master_or_slave master_or_slave,int bits_per_frame)1240098ccbc5SKrzysztof Helt static void reset_chi(struct snd_dbri *dbri,
1241098ccbc5SKrzysztof Helt enum master_or_slave master_or_slave,
12421bd9debfSTakashi Iwai int bits_per_frame)
12431bd9debfSTakashi Iwai {
12441be54c82SKrzysztof Helt s32 *cmd;
12451bd9debfSTakashi Iwai int val;
12461bd9debfSTakashi Iwai
12471bd9debfSTakashi Iwai /* Set CHI Anchor: Pipe 16 */
12481bd9debfSTakashi Iwai
12491be54c82SKrzysztof Helt cmd = dbri_cmdlock(dbri, 4);
1250470f1f1aSKrzysztof Helt val = D_DTS_VO | D_DTS_VI | D_DTS_INS
1251470f1f1aSKrzysztof Helt | D_DTS_PRVIN(16) | D_PIPE(16) | D_DTS_PRVOUT(16);
12521bd9debfSTakashi Iwai *(cmd++) = DBRI_CMD(D_DTS, 0, val);
12531bd9debfSTakashi Iwai *(cmd++) = D_TS_ANCHOR | D_TS_NEXT(16);
12541bd9debfSTakashi Iwai *(cmd++) = D_TS_ANCHOR | D_TS_NEXT(16);
12551be54c82SKrzysztof Helt *(cmd++) = DBRI_CMD(D_PAUSE, 0, 0);
12561be54c82SKrzysztof Helt dbri_cmdsend(dbri, cmd, 4);
12571bd9debfSTakashi Iwai
12581bd9debfSTakashi Iwai dbri->pipes[16].sdp = 1;
12591bd9debfSTakashi Iwai dbri->pipes[16].nextpipe = 16;
12601bd9debfSTakashi Iwai
12611be54c82SKrzysztof Helt cmd = dbri_cmdlock(dbri, 4);
12621bd9debfSTakashi Iwai
12631bd9debfSTakashi Iwai if (master_or_slave == CHIslave) {
12641bd9debfSTakashi Iwai /* Setup DBRI for CHI Slave - receive clock, frame sync (FS)
12651bd9debfSTakashi Iwai *
12661bd9debfSTakashi Iwai * CHICM = 0 (slave mode, 8 kHz frame rate)
12671bd9debfSTakashi Iwai * IR = give immediate CHI status interrupt
12681bd9debfSTakashi Iwai * EN = give CHI status interrupt upon change
12691bd9debfSTakashi Iwai */
12701bd9debfSTakashi Iwai *(cmd++) = DBRI_CMD(D_CHI, 0, D_CHI_CHICM(0));
12711bd9debfSTakashi Iwai } else {
12721bd9debfSTakashi Iwai /* Setup DBRI for CHI Master - generate clock, FS
12731bd9debfSTakashi Iwai *
12741bd9debfSTakashi Iwai * BPF = bits per 8 kHz frame
12751bd9debfSTakashi Iwai * 12.288 MHz / CHICM_divisor = clock rate
12761bd9debfSTakashi Iwai * FD = 1 - drive CHIFS on rising edge of CHICK
12771bd9debfSTakashi Iwai */
12781bd9debfSTakashi Iwai int clockrate = bits_per_frame * 8;
12791bd9debfSTakashi Iwai int divisor = 12288 / clockrate;
12801bd9debfSTakashi Iwai
12811bd9debfSTakashi Iwai if (divisor > 255 || divisor * clockrate != 12288)
1282098ccbc5SKrzysztof Helt printk(KERN_ERR "DBRI: illegal bits_per_frame "
1283098ccbc5SKrzysztof Helt "in setup_chi\n");
12841bd9debfSTakashi Iwai
12851bd9debfSTakashi Iwai *(cmd++) = DBRI_CMD(D_CHI, 0, D_CHI_CHICM(divisor) | D_CHI_FD
12861bd9debfSTakashi Iwai | D_CHI_BPF(bits_per_frame));
12871bd9debfSTakashi Iwai }
12881bd9debfSTakashi Iwai
12891bd9debfSTakashi Iwai dbri->chi_bpf = bits_per_frame;
12901bd9debfSTakashi Iwai
12911bd9debfSTakashi Iwai /* CHI Data Mode
12921bd9debfSTakashi Iwai *
12931bd9debfSTakashi Iwai * RCE = 0 - receive on falling edge of CHICK
12941bd9debfSTakashi Iwai * XCE = 1 - transmit on rising edge of CHICK
12951bd9debfSTakashi Iwai * XEN = 1 - enable transmitter
12961bd9debfSTakashi Iwai * REN = 1 - enable receiver
12971bd9debfSTakashi Iwai */
12981bd9debfSTakashi Iwai
12991bd9debfSTakashi Iwai *(cmd++) = DBRI_CMD(D_PAUSE, 0, 0);
13001bd9debfSTakashi Iwai *(cmd++) = DBRI_CMD(D_CDM, 0, D_CDM_XCE | D_CDM_XEN | D_CDM_REN);
13011be54c82SKrzysztof Helt *(cmd++) = DBRI_CMD(D_PAUSE, 0, 0);
13021bd9debfSTakashi Iwai
13031be54c82SKrzysztof Helt dbri_cmdsend(dbri, cmd, 4);
13041bd9debfSTakashi Iwai }
13051bd9debfSTakashi Iwai
13061bd9debfSTakashi Iwai /*
13071bd9debfSTakashi Iwai ****************************************************************************
13081bd9debfSTakashi Iwai *********************** CS4215 audio codec management **********************
13091bd9debfSTakashi Iwai ****************************************************************************
13101bd9debfSTakashi Iwai
13111bd9debfSTakashi Iwai In the standard SPARC audio configuration, the CS4215 codec is attached
13121bd9debfSTakashi Iwai to the DBRI via the CHI interface and few of the DBRI's PIO pins.
13131bd9debfSTakashi Iwai
1314ea543f1eSKrzysztof Helt * Lock must not be held before calling it.
1315ea543f1eSKrzysztof Helt
13161bd9debfSTakashi Iwai */
cs4215_setup_pipes(struct snd_dbri * dbri)131732e02a7bSBill Pemberton static void cs4215_setup_pipes(struct snd_dbri *dbri)
13181bd9debfSTakashi Iwai {
1319ea543f1eSKrzysztof Helt unsigned long flags;
1320ea543f1eSKrzysztof Helt
1321ea543f1eSKrzysztof Helt spin_lock_irqsave(&dbri->lock, flags);
13221bd9debfSTakashi Iwai /*
13231bd9debfSTakashi Iwai * Data mode:
13241bd9debfSTakashi Iwai * Pipe 4: Send timeslots 1-4 (audio data)
13251bd9debfSTakashi Iwai * Pipe 20: Send timeslots 5-8 (part of ctrl data)
13261bd9debfSTakashi Iwai * Pipe 6: Receive timeslots 1-4 (audio data)
13271bd9debfSTakashi Iwai * Pipe 21: Receive timeslots 6-7. We can only receive 20 bits via
13281bd9debfSTakashi Iwai * interrupt, and the rest of the data (slot 5 and 8) is
13291bd9debfSTakashi Iwai * not relevant for us (only for doublechecking).
13301bd9debfSTakashi Iwai *
13311bd9debfSTakashi Iwai * Control mode:
13321bd9debfSTakashi Iwai * Pipe 17: Send timeslots 1-4 (slots 5-8 are read only)
13331bd9debfSTakashi Iwai * Pipe 18: Receive timeslot 1 (clb).
13341bd9debfSTakashi Iwai * Pipe 19: Receive timeslot 7 (version).
13351bd9debfSTakashi Iwai */
13361bd9debfSTakashi Iwai
13371bd9debfSTakashi Iwai setup_pipe(dbri, 4, D_SDP_MEM | D_SDP_TO_SER | D_SDP_MSB);
13381bd9debfSTakashi Iwai setup_pipe(dbri, 20, D_SDP_FIXED | D_SDP_TO_SER | D_SDP_MSB);
13391bd9debfSTakashi Iwai setup_pipe(dbri, 6, D_SDP_MEM | D_SDP_FROM_SER | D_SDP_MSB);
13401bd9debfSTakashi Iwai setup_pipe(dbri, 21, D_SDP_FIXED | D_SDP_FROM_SER | D_SDP_MSB);
13411bd9debfSTakashi Iwai
13421bd9debfSTakashi Iwai setup_pipe(dbri, 17, D_SDP_FIXED | D_SDP_TO_SER | D_SDP_MSB);
13431bd9debfSTakashi Iwai setup_pipe(dbri, 18, D_SDP_FIXED | D_SDP_FROM_SER | D_SDP_MSB);
13441bd9debfSTakashi Iwai setup_pipe(dbri, 19, D_SDP_FIXED | D_SDP_FROM_SER | D_SDP_MSB);
1345ea543f1eSKrzysztof Helt spin_unlock_irqrestore(&dbri->lock, flags);
13461be54c82SKrzysztof Helt
13471be54c82SKrzysztof Helt dbri_cmdwait(dbri);
13481bd9debfSTakashi Iwai }
13491bd9debfSTakashi Iwai
cs4215_init_data(struct cs4215 * mm)135032e02a7bSBill Pemberton static int cs4215_init_data(struct cs4215 *mm)
13511bd9debfSTakashi Iwai {
13521bd9debfSTakashi Iwai /*
13531bd9debfSTakashi Iwai * No action, memory resetting only.
13541bd9debfSTakashi Iwai *
13551bd9debfSTakashi Iwai * Data Time Slot 5-8
13561bd9debfSTakashi Iwai * Speaker,Line and Headphone enable. Gain set to the half.
13571bd9debfSTakashi Iwai * Input is mike.
13581bd9debfSTakashi Iwai */
13591bd9debfSTakashi Iwai mm->data[0] = CS4215_LO(0x20) | CS4215_HE | CS4215_LE;
13601bd9debfSTakashi Iwai mm->data[1] = CS4215_RO(0x20) | CS4215_SE;
13611bd9debfSTakashi Iwai mm->data[2] = CS4215_LG(0x8) | CS4215_IS | CS4215_PIO0 | CS4215_PIO1;
13621bd9debfSTakashi Iwai mm->data[3] = CS4215_RG(0x8) | CS4215_MA(0xf);
13631bd9debfSTakashi Iwai
13641bd9debfSTakashi Iwai /*
13651bd9debfSTakashi Iwai * Control Time Slot 1-4
13661bd9debfSTakashi Iwai * 0: Default I/O voltage scale
13671bd9debfSTakashi Iwai * 1: 8 bit ulaw, 8kHz, mono, high pass filter disabled
13681bd9debfSTakashi Iwai * 2: Serial enable, CHI master, 128 bits per frame, clock 1
13691bd9debfSTakashi Iwai * 3: Tests disabled
13701bd9debfSTakashi Iwai */
13711bd9debfSTakashi Iwai mm->ctrl[0] = CS4215_RSRVD_1 | CS4215_MLB;
13721bd9debfSTakashi Iwai mm->ctrl[1] = CS4215_DFR_ULAW | CS4215_FREQ[0].csval;
13731bd9debfSTakashi Iwai mm->ctrl[2] = CS4215_XCLK | CS4215_BSEL_128 | CS4215_FREQ[0].xtal;
13741bd9debfSTakashi Iwai mm->ctrl[3] = 0;
13751bd9debfSTakashi Iwai
13761bd9debfSTakashi Iwai mm->status = 0;
13771bd9debfSTakashi Iwai mm->version = 0xff;
13781bd9debfSTakashi Iwai mm->precision = 8; /* For ULAW */
13791be54c82SKrzysztof Helt mm->channels = 1;
13801bd9debfSTakashi Iwai
13811bd9debfSTakashi Iwai return 0;
13821bd9debfSTakashi Iwai }
13831bd9debfSTakashi Iwai
cs4215_setdata(struct snd_dbri * dbri,int muted)1384475675d6STakashi Iwai static void cs4215_setdata(struct snd_dbri *dbri, int muted)
13851bd9debfSTakashi Iwai {
13861bd9debfSTakashi Iwai if (muted) {
13871bd9debfSTakashi Iwai dbri->mm.data[0] |= 63;
13881bd9debfSTakashi Iwai dbri->mm.data[1] |= 63;
13891bd9debfSTakashi Iwai dbri->mm.data[2] &= ~15;
13901bd9debfSTakashi Iwai dbri->mm.data[3] &= ~15;
13911bd9debfSTakashi Iwai } else {
13921bd9debfSTakashi Iwai /* Start by setting the playback attenuation. */
1393475675d6STakashi Iwai struct dbri_streaminfo *info = &dbri->stream_info[DBRI_PLAY];
1394470f1f1aSKrzysztof Helt int left_gain = info->left_gain & 0x3f;
1395470f1f1aSKrzysztof Helt int right_gain = info->right_gain & 0x3f;
13961bd9debfSTakashi Iwai
13971bd9debfSTakashi Iwai dbri->mm.data[0] &= ~0x3f; /* Reset the volume bits */
13981bd9debfSTakashi Iwai dbri->mm.data[1] &= ~0x3f;
13991bd9debfSTakashi Iwai dbri->mm.data[0] |= (DBRI_MAX_VOLUME - left_gain);
14001bd9debfSTakashi Iwai dbri->mm.data[1] |= (DBRI_MAX_VOLUME - right_gain);
14011bd9debfSTakashi Iwai
14021bd9debfSTakashi Iwai /* Now set the recording gain. */
14031bd9debfSTakashi Iwai info = &dbri->stream_info[DBRI_REC];
1404470f1f1aSKrzysztof Helt left_gain = info->left_gain & 0xf;
1405470f1f1aSKrzysztof Helt right_gain = info->right_gain & 0xf;
14061bd9debfSTakashi Iwai dbri->mm.data[2] |= CS4215_LG(left_gain);
14071bd9debfSTakashi Iwai dbri->mm.data[3] |= CS4215_RG(right_gain);
14081bd9debfSTakashi Iwai }
14091bd9debfSTakashi Iwai
14101bd9debfSTakashi Iwai xmit_fixed(dbri, 20, *(int *)dbri->mm.data);
14111bd9debfSTakashi Iwai }
14121bd9debfSTakashi Iwai
14131bd9debfSTakashi Iwai /*
14141bd9debfSTakashi Iwai * Set the CS4215 to data mode.
14151bd9debfSTakashi Iwai */
cs4215_open(struct snd_dbri * dbri)1416475675d6STakashi Iwai static void cs4215_open(struct snd_dbri *dbri)
14171bd9debfSTakashi Iwai {
14181bd9debfSTakashi Iwai int data_width;
14191bd9debfSTakashi Iwai u32 tmp;
1420ea543f1eSKrzysztof Helt unsigned long flags;
14211bd9debfSTakashi Iwai
14221bd9debfSTakashi Iwai dprintk(D_MM, "cs4215_open: %d channels, %d bits\n",
14231bd9debfSTakashi Iwai dbri->mm.channels, dbri->mm.precision);
14241bd9debfSTakashi Iwai
14251bd9debfSTakashi Iwai /* Temporarily mute outputs, and wait 1/8000 sec (125 us)
14261bd9debfSTakashi Iwai * to make sure this takes. This avoids clicking noises.
14271bd9debfSTakashi Iwai */
14281bd9debfSTakashi Iwai
14291bd9debfSTakashi Iwai cs4215_setdata(dbri, 1);
14301bd9debfSTakashi Iwai udelay(125);
14311bd9debfSTakashi Iwai
14321bd9debfSTakashi Iwai /*
14331bd9debfSTakashi Iwai * Data mode:
14341bd9debfSTakashi Iwai * Pipe 4: Send timeslots 1-4 (audio data)
14351bd9debfSTakashi Iwai * Pipe 20: Send timeslots 5-8 (part of ctrl data)
14361bd9debfSTakashi Iwai * Pipe 6: Receive timeslots 1-4 (audio data)
14371bd9debfSTakashi Iwai * Pipe 21: Receive timeslots 6-7. We can only receive 20 bits via
14381bd9debfSTakashi Iwai * interrupt, and the rest of the data (slot 5 and 8) is
14391bd9debfSTakashi Iwai * not relevant for us (only for doublechecking).
14401bd9debfSTakashi Iwai *
14411bd9debfSTakashi Iwai * Just like in control mode, the time slots are all offset by eight
14421bd9debfSTakashi Iwai * bits. The CS4215, it seems, observes TSIN (the delayed signal)
14431bd9debfSTakashi Iwai * even if it's the CHI master. Don't ask me...
14441bd9debfSTakashi Iwai */
1445ea543f1eSKrzysztof Helt spin_lock_irqsave(&dbri->lock, flags);
14461bd9debfSTakashi Iwai tmp = sbus_readl(dbri->regs + REG0);
14471bd9debfSTakashi Iwai tmp &= ~(D_C); /* Disable CHI */
14481bd9debfSTakashi Iwai sbus_writel(tmp, dbri->regs + REG0);
14491bd9debfSTakashi Iwai
14501bd9debfSTakashi Iwai /* Switch CS4215 to data mode - set PIO3 to 1 */
14511bd9debfSTakashi Iwai sbus_writel(D_ENPIO | D_PIO1 | D_PIO3 |
14521bd9debfSTakashi Iwai (dbri->mm.onboard ? D_PIO0 : D_PIO2), dbri->regs + REG2);
14531bd9debfSTakashi Iwai
14541bd9debfSTakashi Iwai reset_chi(dbri, CHIslave, 128);
14551bd9debfSTakashi Iwai
14561bd9debfSTakashi Iwai /* Note: this next doesn't work for 8-bit stereo, because the two
14571bd9debfSTakashi Iwai * channels would be on timeslots 1 and 3, with 2 and 4 idle.
14581bd9debfSTakashi Iwai * (See CS4215 datasheet Fig 15)
14591bd9debfSTakashi Iwai *
14601bd9debfSTakashi Iwai * DBRI non-contiguous mode would be required to make this work.
14611bd9debfSTakashi Iwai */
14621bd9debfSTakashi Iwai data_width = dbri->mm.channels * dbri->mm.precision;
14631bd9debfSTakashi Iwai
1464294a30dcSKrzysztof Helt link_time_slot(dbri, 4, 16, 16, data_width, dbri->mm.offset);
1465294a30dcSKrzysztof Helt link_time_slot(dbri, 20, 4, 16, 32, dbri->mm.offset + 32);
1466294a30dcSKrzysztof Helt link_time_slot(dbri, 6, 16, 16, data_width, dbri->mm.offset);
1467294a30dcSKrzysztof Helt link_time_slot(dbri, 21, 6, 16, 16, dbri->mm.offset + 40);
14681bd9debfSTakashi Iwai
14691bd9debfSTakashi Iwai /* FIXME: enable CHI after _setdata? */
14701bd9debfSTakashi Iwai tmp = sbus_readl(dbri->regs + REG0);
14711bd9debfSTakashi Iwai tmp |= D_C; /* Enable CHI */
14721bd9debfSTakashi Iwai sbus_writel(tmp, dbri->regs + REG0);
1473ea543f1eSKrzysztof Helt spin_unlock_irqrestore(&dbri->lock, flags);
14741bd9debfSTakashi Iwai
14751bd9debfSTakashi Iwai cs4215_setdata(dbri, 0);
14761bd9debfSTakashi Iwai }
14771bd9debfSTakashi Iwai
14781bd9debfSTakashi Iwai /*
14791bd9debfSTakashi Iwai * Send the control information (i.e. audio format)
14801bd9debfSTakashi Iwai */
cs4215_setctrl(struct snd_dbri * dbri)1481475675d6STakashi Iwai static int cs4215_setctrl(struct snd_dbri *dbri)
14821bd9debfSTakashi Iwai {
14831bd9debfSTakashi Iwai int i, val;
14841bd9debfSTakashi Iwai u32 tmp;
1485ea543f1eSKrzysztof Helt unsigned long flags;
14861bd9debfSTakashi Iwai
14871bd9debfSTakashi Iwai /* FIXME - let the CPU do something useful during these delays */
14881bd9debfSTakashi Iwai
14891bd9debfSTakashi Iwai /* Temporarily mute outputs, and wait 1/8000 sec (125 us)
14901bd9debfSTakashi Iwai * to make sure this takes. This avoids clicking noises.
14911bd9debfSTakashi Iwai */
14921bd9debfSTakashi Iwai cs4215_setdata(dbri, 1);
14931bd9debfSTakashi Iwai udelay(125);
14941bd9debfSTakashi Iwai
14951bd9debfSTakashi Iwai /*
14961bd9debfSTakashi Iwai * Enable Control mode: Set DBRI's PIO3 (4215's D/~C) to 0, then wait
14971bd9debfSTakashi Iwai * 12 cycles <= 12/(5512.5*64) sec = 34.01 usec
14981bd9debfSTakashi Iwai */
14991bd9debfSTakashi Iwai val = D_ENPIO | D_PIO1 | (dbri->mm.onboard ? D_PIO0 : D_PIO2);
15001bd9debfSTakashi Iwai sbus_writel(val, dbri->regs + REG2);
15011bd9debfSTakashi Iwai dprintk(D_MM, "cs4215_setctrl: reg2=0x%x\n", val);
15021bd9debfSTakashi Iwai udelay(34);
15031bd9debfSTakashi Iwai
15041bd9debfSTakashi Iwai /* In Control mode, the CS4215 is a slave device, so the DBRI must
15051bd9debfSTakashi Iwai * operate as CHI master, supplying clocking and frame synchronization.
15061bd9debfSTakashi Iwai *
15071bd9debfSTakashi Iwai * In Data mode, however, the CS4215 must be CHI master to insure
15081bd9debfSTakashi Iwai * that its data stream is synchronous with its codec.
15091bd9debfSTakashi Iwai *
15101bd9debfSTakashi Iwai * The upshot of all this? We start by putting the DBRI into master
15111bd9debfSTakashi Iwai * mode, program the CS4215 in Control mode, then switch the CS4215
15121bd9debfSTakashi Iwai * into Data mode and put the DBRI into slave mode. Various timing
15131bd9debfSTakashi Iwai * requirements must be observed along the way.
15141bd9debfSTakashi Iwai *
15151bd9debfSTakashi Iwai * Oh, and one more thing, on a SPARCStation 20 (and maybe
15161bd9debfSTakashi Iwai * others?), the addressing of the CS4215's time slots is
15171bd9debfSTakashi Iwai * offset by eight bits, so we add eight to all the "cycle"
15181bd9debfSTakashi Iwai * values in the Define Time Slot (DTS) commands. This is
15191bd9debfSTakashi Iwai * done in hardware by a TI 248 that delays the DBRI->4215
15201bd9debfSTakashi Iwai * frame sync signal by eight clock cycles. Anybody know why?
15211bd9debfSTakashi Iwai */
1522ea543f1eSKrzysztof Helt spin_lock_irqsave(&dbri->lock, flags);
15231bd9debfSTakashi Iwai tmp = sbus_readl(dbri->regs + REG0);
15241bd9debfSTakashi Iwai tmp &= ~D_C; /* Disable CHI */
15251bd9debfSTakashi Iwai sbus_writel(tmp, dbri->regs + REG0);
15261bd9debfSTakashi Iwai
15271bd9debfSTakashi Iwai reset_chi(dbri, CHImaster, 128);
15281bd9debfSTakashi Iwai
15291bd9debfSTakashi Iwai /*
15301bd9debfSTakashi Iwai * Control mode:
15311bd9debfSTakashi Iwai * Pipe 17: Send timeslots 1-4 (slots 5-8 are read only)
15321bd9debfSTakashi Iwai * Pipe 18: Receive timeslot 1 (clb).
15331bd9debfSTakashi Iwai * Pipe 19: Receive timeslot 7 (version).
15341bd9debfSTakashi Iwai */
15351bd9debfSTakashi Iwai
1536294a30dcSKrzysztof Helt link_time_slot(dbri, 17, 16, 16, 32, dbri->mm.offset);
1537294a30dcSKrzysztof Helt link_time_slot(dbri, 18, 16, 16, 8, dbri->mm.offset);
1538294a30dcSKrzysztof Helt link_time_slot(dbri, 19, 18, 16, 8, dbri->mm.offset + 48);
1539ea543f1eSKrzysztof Helt spin_unlock_irqrestore(&dbri->lock, flags);
15401bd9debfSTakashi Iwai
15411bd9debfSTakashi Iwai /* Wait for the chip to echo back CLB (Control Latch Bit) as zero */
15421bd9debfSTakashi Iwai dbri->mm.ctrl[0] &= ~CS4215_CLB;
15431bd9debfSTakashi Iwai xmit_fixed(dbri, 17, *(int *)dbri->mm.ctrl);
15441bd9debfSTakashi Iwai
1545ea543f1eSKrzysztof Helt spin_lock_irqsave(&dbri->lock, flags);
15461bd9debfSTakashi Iwai tmp = sbus_readl(dbri->regs + REG0);
15471bd9debfSTakashi Iwai tmp |= D_C; /* Enable CHI */
15481bd9debfSTakashi Iwai sbus_writel(tmp, dbri->regs + REG0);
1549ea543f1eSKrzysztof Helt spin_unlock_irqrestore(&dbri->lock, flags);
15501bd9debfSTakashi Iwai
1551098ccbc5SKrzysztof Helt for (i = 10; ((dbri->mm.status & 0xe4) != 0x20); --i)
15524338829eSMartin Habets msleep_interruptible(1);
1553098ccbc5SKrzysztof Helt
15541bd9debfSTakashi Iwai if (i == 0) {
15551bd9debfSTakashi Iwai dprintk(D_MM, "CS4215 didn't respond to CLB (0x%02x)\n",
15561bd9debfSTakashi Iwai dbri->mm.status);
15571bd9debfSTakashi Iwai return -1;
15581bd9debfSTakashi Iwai }
15591bd9debfSTakashi Iwai
15601bd9debfSTakashi Iwai /* Disable changes to our copy of the version number, as we are about
15611bd9debfSTakashi Iwai * to leave control mode.
15621bd9debfSTakashi Iwai */
15631bd9debfSTakashi Iwai recv_fixed(dbri, 19, NULL);
15641bd9debfSTakashi Iwai
15651bd9debfSTakashi Iwai /* Terminate CS4215 control mode - data sheet says
15661bd9debfSTakashi Iwai * "Set CLB=1 and send two more frames of valid control info"
15671bd9debfSTakashi Iwai */
15681bd9debfSTakashi Iwai dbri->mm.ctrl[0] |= CS4215_CLB;
15691bd9debfSTakashi Iwai xmit_fixed(dbri, 17, *(int *)dbri->mm.ctrl);
15701bd9debfSTakashi Iwai
15711bd9debfSTakashi Iwai /* Two frames of control info @ 8kHz frame rate = 250 us delay */
15721bd9debfSTakashi Iwai udelay(250);
15731bd9debfSTakashi Iwai
15741bd9debfSTakashi Iwai cs4215_setdata(dbri, 0);
15751bd9debfSTakashi Iwai
15761bd9debfSTakashi Iwai return 0;
15771bd9debfSTakashi Iwai }
15781bd9debfSTakashi Iwai
15791bd9debfSTakashi Iwai /*
15801bd9debfSTakashi Iwai * Setup the codec with the sampling rate, audio format and number of
15811bd9debfSTakashi Iwai * channels.
15821bd9debfSTakashi Iwai * As part of the process we resend the settings for the data
15831bd9debfSTakashi Iwai * timeslots as well.
15841bd9debfSTakashi Iwai */
cs4215_prepare(struct snd_dbri * dbri,unsigned int rate,snd_pcm_format_t format,unsigned int channels)1585475675d6STakashi Iwai static int cs4215_prepare(struct snd_dbri *dbri, unsigned int rate,
15861bd9debfSTakashi Iwai snd_pcm_format_t format, unsigned int channels)
15871bd9debfSTakashi Iwai {
15881bd9debfSTakashi Iwai int freq_idx;
15891bd9debfSTakashi Iwai int ret = 0;
15901bd9debfSTakashi Iwai
15911bd9debfSTakashi Iwai /* Lookup index for this rate */
15921bd9debfSTakashi Iwai for (freq_idx = 0; CS4215_FREQ[freq_idx].freq != 0; freq_idx++) {
15931bd9debfSTakashi Iwai if (CS4215_FREQ[freq_idx].freq == rate)
15941bd9debfSTakashi Iwai break;
15951bd9debfSTakashi Iwai }
15961bd9debfSTakashi Iwai if (CS4215_FREQ[freq_idx].freq != rate) {
15971bd9debfSTakashi Iwai printk(KERN_WARNING "DBRI: Unsupported rate %d Hz\n", rate);
15981bd9debfSTakashi Iwai return -1;
15991bd9debfSTakashi Iwai }
16001bd9debfSTakashi Iwai
16011bd9debfSTakashi Iwai switch (format) {
16021bd9debfSTakashi Iwai case SNDRV_PCM_FORMAT_MU_LAW:
16031bd9debfSTakashi Iwai dbri->mm.ctrl[1] = CS4215_DFR_ULAW;
16041bd9debfSTakashi Iwai dbri->mm.precision = 8;
16051bd9debfSTakashi Iwai break;
16061bd9debfSTakashi Iwai case SNDRV_PCM_FORMAT_A_LAW:
16071bd9debfSTakashi Iwai dbri->mm.ctrl[1] = CS4215_DFR_ALAW;
16081bd9debfSTakashi Iwai dbri->mm.precision = 8;
16091bd9debfSTakashi Iwai break;
16101bd9debfSTakashi Iwai case SNDRV_PCM_FORMAT_U8:
16111bd9debfSTakashi Iwai dbri->mm.ctrl[1] = CS4215_DFR_LINEAR8;
16121bd9debfSTakashi Iwai dbri->mm.precision = 8;
16131bd9debfSTakashi Iwai break;
16141bd9debfSTakashi Iwai case SNDRV_PCM_FORMAT_S16_BE:
16151bd9debfSTakashi Iwai dbri->mm.ctrl[1] = CS4215_DFR_LINEAR16;
16161bd9debfSTakashi Iwai dbri->mm.precision = 16;
16171bd9debfSTakashi Iwai break;
16181bd9debfSTakashi Iwai default:
16191bd9debfSTakashi Iwai printk(KERN_WARNING "DBRI: Unsupported format %d\n", format);
16201bd9debfSTakashi Iwai return -1;
16211bd9debfSTakashi Iwai }
16221bd9debfSTakashi Iwai
16231bd9debfSTakashi Iwai /* Add rate parameters */
16241bd9debfSTakashi Iwai dbri->mm.ctrl[1] |= CS4215_FREQ[freq_idx].csval;
16251bd9debfSTakashi Iwai dbri->mm.ctrl[2] = CS4215_XCLK |
16261bd9debfSTakashi Iwai CS4215_BSEL_128 | CS4215_FREQ[freq_idx].xtal;
16271bd9debfSTakashi Iwai
16281bd9debfSTakashi Iwai dbri->mm.channels = channels;
1629ab93c7aeSKrzysztof Helt if (channels == 2)
16301bd9debfSTakashi Iwai dbri->mm.ctrl[1] |= CS4215_DFR_STEREO;
16311bd9debfSTakashi Iwai
16321bd9debfSTakashi Iwai ret = cs4215_setctrl(dbri);
16331bd9debfSTakashi Iwai if (ret == 0)
16341bd9debfSTakashi Iwai cs4215_open(dbri); /* set codec to data mode */
16351bd9debfSTakashi Iwai
16361bd9debfSTakashi Iwai return ret;
16371bd9debfSTakashi Iwai }
16381bd9debfSTakashi Iwai
16391bd9debfSTakashi Iwai /*
16401bd9debfSTakashi Iwai *
16411bd9debfSTakashi Iwai */
cs4215_init(struct snd_dbri * dbri)164232e02a7bSBill Pemberton static int cs4215_init(struct snd_dbri *dbri)
16431bd9debfSTakashi Iwai {
16441bd9debfSTakashi Iwai u32 reg2 = sbus_readl(dbri->regs + REG2);
16451bd9debfSTakashi Iwai dprintk(D_MM, "cs4215_init: reg2=0x%x\n", reg2);
16461bd9debfSTakashi Iwai
16471bd9debfSTakashi Iwai /* Look for the cs4215 chips */
16481bd9debfSTakashi Iwai if (reg2 & D_PIO2) {
16491bd9debfSTakashi Iwai dprintk(D_MM, "Onboard CS4215 detected\n");
16501bd9debfSTakashi Iwai dbri->mm.onboard = 1;
16511bd9debfSTakashi Iwai }
16521bd9debfSTakashi Iwai if (reg2 & D_PIO0) {
16531bd9debfSTakashi Iwai dprintk(D_MM, "Speakerbox detected\n");
16541bd9debfSTakashi Iwai dbri->mm.onboard = 0;
16551bd9debfSTakashi Iwai
16561bd9debfSTakashi Iwai if (reg2 & D_PIO2) {
16571bd9debfSTakashi Iwai printk(KERN_INFO "DBRI: Using speakerbox / "
16581bd9debfSTakashi Iwai "ignoring onboard mmcodec.\n");
16591bd9debfSTakashi Iwai sbus_writel(D_ENPIO2, dbri->regs + REG2);
16601bd9debfSTakashi Iwai }
16611bd9debfSTakashi Iwai }
16621bd9debfSTakashi Iwai
16631bd9debfSTakashi Iwai if (!(reg2 & (D_PIO0 | D_PIO2))) {
16641bd9debfSTakashi Iwai printk(KERN_ERR "DBRI: no mmcodec found.\n");
16651bd9debfSTakashi Iwai return -EIO;
16661bd9debfSTakashi Iwai }
16671bd9debfSTakashi Iwai
16681bd9debfSTakashi Iwai cs4215_setup_pipes(dbri);
16691bd9debfSTakashi Iwai cs4215_init_data(&dbri->mm);
16701bd9debfSTakashi Iwai
16711bd9debfSTakashi Iwai /* Enable capture of the status & version timeslots. */
16721bd9debfSTakashi Iwai recv_fixed(dbri, 18, &dbri->mm.status);
16731bd9debfSTakashi Iwai recv_fixed(dbri, 19, &dbri->mm.version);
16741bd9debfSTakashi Iwai
16751bd9debfSTakashi Iwai dbri->mm.offset = dbri->mm.onboard ? 0 : 8;
16761bd9debfSTakashi Iwai if (cs4215_setctrl(dbri) == -1 || dbri->mm.version == 0xff) {
16771bd9debfSTakashi Iwai dprintk(D_MM, "CS4215 failed probe at offset %d\n",
16781bd9debfSTakashi Iwai dbri->mm.offset);
16791bd9debfSTakashi Iwai return -EIO;
16801bd9debfSTakashi Iwai }
16811bd9debfSTakashi Iwai dprintk(D_MM, "Found CS4215 at offset %d\n", dbri->mm.offset);
16821bd9debfSTakashi Iwai
16831bd9debfSTakashi Iwai return 0;
16841bd9debfSTakashi Iwai }
16851bd9debfSTakashi Iwai
16861bd9debfSTakashi Iwai /*
16871bd9debfSTakashi Iwai ****************************************************************************
16881bd9debfSTakashi Iwai *************************** DBRI interrupt handler *************************
16891bd9debfSTakashi Iwai ****************************************************************************
16901bd9debfSTakashi Iwai
16911bd9debfSTakashi Iwai The DBRI communicates with the CPU mainly via a circular interrupt
16921bd9debfSTakashi Iwai buffer. When an interrupt is signaled, the CPU walks through the
16931bd9debfSTakashi Iwai buffer and calls dbri_process_one_interrupt() for each interrupt word.
16941bd9debfSTakashi Iwai Complicated interrupts are handled by dedicated functions (which
16951bd9debfSTakashi Iwai appear first in this file). Any pending interrupts can be serviced by
16961bd9debfSTakashi Iwai calling dbri_process_interrupt_buffer(), which works even if the CPU's
16971be54c82SKrzysztof Helt interrupts are disabled.
16981bd9debfSTakashi Iwai
16991bd9debfSTakashi Iwai */
17001bd9debfSTakashi Iwai
17011bd9debfSTakashi Iwai /* xmit_descs()
17021bd9debfSTakashi Iwai *
1703098ccbc5SKrzysztof Helt * Starts transmitting the current TD's for recording/playing.
17041bd9debfSTakashi Iwai * For playback, ALSA has filled the DMA memory with new data (we hope).
17051bd9debfSTakashi Iwai */
xmit_descs(struct snd_dbri * dbri)17061be54c82SKrzysztof Helt static void xmit_descs(struct snd_dbri *dbri)
17071bd9debfSTakashi Iwai {
1708475675d6STakashi Iwai struct dbri_streaminfo *info;
1709163117e8SDan Carpenter u32 dvma_addr;
17101be54c82SKrzysztof Helt s32 *cmd;
17111bd9debfSTakashi Iwai unsigned long flags;
17121bd9debfSTakashi Iwai int first_td;
17131bd9debfSTakashi Iwai
17141bd9debfSTakashi Iwai if (dbri == NULL)
17151bd9debfSTakashi Iwai return; /* Disabled */
17161bd9debfSTakashi Iwai
1717163117e8SDan Carpenter dvma_addr = (u32)dbri->dma_dvma;
17181bd9debfSTakashi Iwai info = &dbri->stream_info[DBRI_REC];
17191bd9debfSTakashi Iwai spin_lock_irqsave(&dbri->lock, flags);
17201bd9debfSTakashi Iwai
17211be54c82SKrzysztof Helt if (info->pipe >= 0) {
17221bd9debfSTakashi Iwai first_td = dbri->pipes[info->pipe].first_desc;
17231bd9debfSTakashi Iwai
17241bd9debfSTakashi Iwai dprintk(D_DESC, "xmit_descs rec @ TD %d\n", first_td);
17251bd9debfSTakashi Iwai
17261bd9debfSTakashi Iwai /* Stream could be closed by the time we run. */
1727aaad3653SKrzysztof Helt if (first_td >= 0) {
17281be54c82SKrzysztof Helt cmd = dbri_cmdlock(dbri, 2);
17291bd9debfSTakashi Iwai *(cmd++) = DBRI_CMD(D_SDP, 0,
17301bd9debfSTakashi Iwai dbri->pipes[info->pipe].sdp
17311bd9debfSTakashi Iwai | D_SDP_P | D_SDP_EVERY | D_SDP_C);
173216f46050STushar Dave *(cmd++) = dvma_addr +
1733098ccbc5SKrzysztof Helt dbri_dma_off(desc, first_td);
17341be54c82SKrzysztof Helt dbri_cmdsend(dbri, cmd, 2);
17351bd9debfSTakashi Iwai
1736aaad3653SKrzysztof Helt /* Reset our admin of the pipe. */
17371bd9debfSTakashi Iwai dbri->pipes[info->pipe].desc = first_td;
17381bd9debfSTakashi Iwai }
1739aaad3653SKrzysztof Helt }
17401bd9debfSTakashi Iwai
17411bd9debfSTakashi Iwai info = &dbri->stream_info[DBRI_PLAY];
17421bd9debfSTakashi Iwai
17431be54c82SKrzysztof Helt if (info->pipe >= 0) {
17441bd9debfSTakashi Iwai first_td = dbri->pipes[info->pipe].first_desc;
17451bd9debfSTakashi Iwai
17461bd9debfSTakashi Iwai dprintk(D_DESC, "xmit_descs play @ TD %d\n", first_td);
17471bd9debfSTakashi Iwai
17481bd9debfSTakashi Iwai /* Stream could be closed by the time we run. */
17491be54c82SKrzysztof Helt if (first_td >= 0) {
17501be54c82SKrzysztof Helt cmd = dbri_cmdlock(dbri, 2);
17511bd9debfSTakashi Iwai *(cmd++) = DBRI_CMD(D_SDP, 0,
17521bd9debfSTakashi Iwai dbri->pipes[info->pipe].sdp
17531bd9debfSTakashi Iwai | D_SDP_P | D_SDP_EVERY | D_SDP_C);
175416f46050STushar Dave *(cmd++) = dvma_addr +
1755098ccbc5SKrzysztof Helt dbri_dma_off(desc, first_td);
17561be54c82SKrzysztof Helt dbri_cmdsend(dbri, cmd, 2);
17571bd9debfSTakashi Iwai
1758aaad3653SKrzysztof Helt /* Reset our admin of the pipe. */
17591bd9debfSTakashi Iwai dbri->pipes[info->pipe].desc = first_td;
17601be54c82SKrzysztof Helt }
17611bd9debfSTakashi Iwai }
1762ea543f1eSKrzysztof Helt
17631bd9debfSTakashi Iwai spin_unlock_irqrestore(&dbri->lock, flags);
17641bd9debfSTakashi Iwai }
17651bd9debfSTakashi Iwai
17661bd9debfSTakashi Iwai /* transmission_complete_intr()
17671bd9debfSTakashi Iwai *
17681bd9debfSTakashi Iwai * Called by main interrupt handler when DBRI signals transmission complete
17691bd9debfSTakashi Iwai * on a pipe (interrupt triggered by the B bit in a transmit descriptor).
17701bd9debfSTakashi Iwai *
17714338829eSMartin Habets * Walks through the pipe's list of transmit buffer descriptors and marks
17724338829eSMartin Habets * them as available. Stops when the first descriptor is found without
17731bd9debfSTakashi Iwai * TBC (Transmit Buffer Complete) set, or we've run through them all.
17744338829eSMartin Habets *
1775ab93c7aeSKrzysztof Helt * The DMA buffers are not released. They form a ring buffer and
1776ab93c7aeSKrzysztof Helt * they are filled by ALSA while others are transmitted by DMA.
1777ab93c7aeSKrzysztof Helt *
17781bd9debfSTakashi Iwai */
17791bd9debfSTakashi Iwai
transmission_complete_intr(struct snd_dbri * dbri,int pipe)1780475675d6STakashi Iwai static void transmission_complete_intr(struct snd_dbri *dbri, int pipe)
17811bd9debfSTakashi Iwai {
1782cf68d212SKrzysztof Helt struct dbri_streaminfo *info = &dbri->stream_info[DBRI_PLAY];
1783cf68d212SKrzysztof Helt int td = dbri->pipes[pipe].desc;
17841bd9debfSTakashi Iwai int status;
17851bd9debfSTakashi Iwai
17861bd9debfSTakashi Iwai while (td >= 0) {
17871bd9debfSTakashi Iwai if (td >= DBRI_NO_DESCS) {
17881bd9debfSTakashi Iwai printk(KERN_ERR "DBRI: invalid td on pipe %d\n", pipe);
17891bd9debfSTakashi Iwai return;
17901bd9debfSTakashi Iwai }
17911bd9debfSTakashi Iwai
17921bd9debfSTakashi Iwai status = DBRI_TD_STATUS(dbri->dma->desc[td].word4);
1793098ccbc5SKrzysztof Helt if (!(status & DBRI_TD_TBC))
17941bd9debfSTakashi Iwai break;
17951bd9debfSTakashi Iwai
17961bd9debfSTakashi Iwai dprintk(D_INT, "TD %d, status 0x%02x\n", td, status);
17971bd9debfSTakashi Iwai
17981bd9debfSTakashi Iwai dbri->dma->desc[td].word4 = 0; /* Reset it for next time. */
17991be54c82SKrzysztof Helt info->offset += DBRI_RD_CNT(dbri->dma->desc[td].word1);
18001bd9debfSTakashi Iwai
1801c2735446SKrzysztof Helt td = dbri->next_desc[td];
18021bd9debfSTakashi Iwai dbri->pipes[pipe].desc = td;
18031bd9debfSTakashi Iwai }
18041bd9debfSTakashi Iwai
18051bd9debfSTakashi Iwai /* Notify ALSA */
18061bd9debfSTakashi Iwai spin_unlock(&dbri->lock);
18071bd9debfSTakashi Iwai snd_pcm_period_elapsed(info->substream);
18081bd9debfSTakashi Iwai spin_lock(&dbri->lock);
18091bd9debfSTakashi Iwai }
18101bd9debfSTakashi Iwai
reception_complete_intr(struct snd_dbri * dbri,int pipe)1811475675d6STakashi Iwai static void reception_complete_intr(struct snd_dbri *dbri, int pipe)
18121bd9debfSTakashi Iwai {
1813475675d6STakashi Iwai struct dbri_streaminfo *info;
18141bd9debfSTakashi Iwai int rd = dbri->pipes[pipe].desc;
18151bd9debfSTakashi Iwai s32 status;
18161bd9debfSTakashi Iwai
18171bd9debfSTakashi Iwai if (rd < 0 || rd >= DBRI_NO_DESCS) {
18181bd9debfSTakashi Iwai printk(KERN_ERR "DBRI: invalid rd on pipe %d\n", pipe);
18191bd9debfSTakashi Iwai return;
18201bd9debfSTakashi Iwai }
18211bd9debfSTakashi Iwai
1822c2735446SKrzysztof Helt dbri->pipes[pipe].desc = dbri->next_desc[rd];
18231bd9debfSTakashi Iwai status = dbri->dma->desc[rd].word1;
18241bd9debfSTakashi Iwai dbri->dma->desc[rd].word1 = 0; /* Reset it for next time. */
18251bd9debfSTakashi Iwai
18261bd9debfSTakashi Iwai info = &dbri->stream_info[DBRI_REC];
18271bd9debfSTakashi Iwai info->offset += DBRI_RD_CNT(status);
18281bd9debfSTakashi Iwai
18291bd9debfSTakashi Iwai /* FIXME: Check status */
18301bd9debfSTakashi Iwai
18311bd9debfSTakashi Iwai dprintk(D_INT, "Recv RD %d, status 0x%02x, len %d\n",
18321bd9debfSTakashi Iwai rd, DBRI_RD_STATUS(status), DBRI_RD_CNT(status));
18331bd9debfSTakashi Iwai
18341bd9debfSTakashi Iwai /* Notify ALSA */
18351bd9debfSTakashi Iwai spin_unlock(&dbri->lock);
18361bd9debfSTakashi Iwai snd_pcm_period_elapsed(info->substream);
18371bd9debfSTakashi Iwai spin_lock(&dbri->lock);
18381bd9debfSTakashi Iwai }
18391bd9debfSTakashi Iwai
dbri_process_one_interrupt(struct snd_dbri * dbri,int x)1840475675d6STakashi Iwai static void dbri_process_one_interrupt(struct snd_dbri *dbri, int x)
18411bd9debfSTakashi Iwai {
18421bd9debfSTakashi Iwai int val = D_INTR_GETVAL(x);
18431bd9debfSTakashi Iwai int channel = D_INTR_GETCHAN(x);
18441bd9debfSTakashi Iwai int command = D_INTR_GETCMD(x);
18451bd9debfSTakashi Iwai int code = D_INTR_GETCODE(x);
18461bd9debfSTakashi Iwai #ifdef DBRI_DEBUG
18471bd9debfSTakashi Iwai int rval = D_INTR_GETRVAL(x);
18481bd9debfSTakashi Iwai #endif
18491bd9debfSTakashi Iwai
18501bd9debfSTakashi Iwai if (channel == D_INTR_CMD) {
18511bd9debfSTakashi Iwai dprintk(D_CMD, "INTR: Command: %-5s Value:%d\n",
18521bd9debfSTakashi Iwai cmds[command], val);
18531bd9debfSTakashi Iwai } else {
18541bd9debfSTakashi Iwai dprintk(D_INT, "INTR: Chan:%d Code:%d Val:%#x\n",
18551bd9debfSTakashi Iwai channel, code, rval);
18561bd9debfSTakashi Iwai }
18571bd9debfSTakashi Iwai
18581bd9debfSTakashi Iwai switch (code) {
18591be54c82SKrzysztof Helt case D_INTR_CMDI:
18601be54c82SKrzysztof Helt if (command != D_WAIT)
18611be54c82SKrzysztof Helt printk(KERN_ERR "DBRI: Command read interrupt\n");
18621be54c82SKrzysztof Helt break;
18631bd9debfSTakashi Iwai case D_INTR_BRDY:
18641bd9debfSTakashi Iwai reception_complete_intr(dbri, channel);
18651bd9debfSTakashi Iwai break;
18661bd9debfSTakashi Iwai case D_INTR_XCMP:
18671bd9debfSTakashi Iwai case D_INTR_MINT:
18681bd9debfSTakashi Iwai transmission_complete_intr(dbri, channel);
18691bd9debfSTakashi Iwai break;
18701bd9debfSTakashi Iwai case D_INTR_UNDR:
18711bd9debfSTakashi Iwai /* UNDR - Transmission underrun
18721bd9debfSTakashi Iwai * resend SDP command with clear pipe bit (C) set
18731bd9debfSTakashi Iwai */
18741bd9debfSTakashi Iwai {
18751be54c82SKrzysztof Helt /* FIXME: do something useful in case of underrun */
18761be54c82SKrzysztof Helt printk(KERN_ERR "DBRI: Underrun error\n");
18771be54c82SKrzysztof Helt #if 0
18781be54c82SKrzysztof Helt s32 *cmd;
18791bd9debfSTakashi Iwai int pipe = channel;
18801bd9debfSTakashi Iwai int td = dbri->pipes[pipe].desc;
18811bd9debfSTakashi Iwai
18821bd9debfSTakashi Iwai dbri->dma->desc[td].word4 = 0;
18831bd9debfSTakashi Iwai cmd = dbri_cmdlock(dbri, NoGetLock);
18841bd9debfSTakashi Iwai *(cmd++) = DBRI_CMD(D_SDP, 0,
18851bd9debfSTakashi Iwai dbri->pipes[pipe].sdp
18861bd9debfSTakashi Iwai | D_SDP_P | D_SDP_C | D_SDP_2SAME);
18871bd9debfSTakashi Iwai *(cmd++) = dbri->dma_dvma + dbri_dma_off(desc, td);
18881bd9debfSTakashi Iwai dbri_cmdsend(dbri, cmd);
18891be54c82SKrzysztof Helt #endif
18901bd9debfSTakashi Iwai }
18911bd9debfSTakashi Iwai break;
18921bd9debfSTakashi Iwai case D_INTR_FXDT:
18931bd9debfSTakashi Iwai /* FXDT - Fixed data change */
18941bd9debfSTakashi Iwai if (dbri->pipes[channel].sdp & D_SDP_MSB)
18951bd9debfSTakashi Iwai val = reverse_bytes(val, dbri->pipes[channel].length);
18961bd9debfSTakashi Iwai
18971bd9debfSTakashi Iwai if (dbri->pipes[channel].recv_fixed_ptr)
18981bd9debfSTakashi Iwai *(dbri->pipes[channel].recv_fixed_ptr) = val;
18991bd9debfSTakashi Iwai break;
19001bd9debfSTakashi Iwai default:
19011bd9debfSTakashi Iwai if (channel != D_INTR_CMD)
19021bd9debfSTakashi Iwai printk(KERN_WARNING
19031bd9debfSTakashi Iwai "DBRI: Ignored Interrupt: %d (0x%x)\n", code, x);
19041bd9debfSTakashi Iwai }
19051bd9debfSTakashi Iwai }
19061bd9debfSTakashi Iwai
19071bd9debfSTakashi Iwai /* dbri_process_interrupt_buffer advances through the DBRI's interrupt
19081bd9debfSTakashi Iwai * buffer until it finds a zero word (indicating nothing more to do
19091bd9debfSTakashi Iwai * right now). Non-zero words require processing and are handed off
19101be54c82SKrzysztof Helt * to dbri_process_one_interrupt AFTER advancing the pointer.
19111bd9debfSTakashi Iwai */
dbri_process_interrupt_buffer(struct snd_dbri * dbri)1912475675d6STakashi Iwai static void dbri_process_interrupt_buffer(struct snd_dbri *dbri)
19131bd9debfSTakashi Iwai {
19141bd9debfSTakashi Iwai s32 x;
19151bd9debfSTakashi Iwai
19161bd9debfSTakashi Iwai while ((x = dbri->dma->intr[dbri->dbri_irqp]) != 0) {
19171bd9debfSTakashi Iwai dbri->dma->intr[dbri->dbri_irqp] = 0;
19181bd9debfSTakashi Iwai dbri->dbri_irqp++;
19196fb98280SKrzysztof Helt if (dbri->dbri_irqp == DBRI_INT_BLK)
19201bd9debfSTakashi Iwai dbri->dbri_irqp = 1;
19211bd9debfSTakashi Iwai
19221bd9debfSTakashi Iwai dbri_process_one_interrupt(dbri, x);
19231bd9debfSTakashi Iwai }
19241bd9debfSTakashi Iwai }
19251bd9debfSTakashi Iwai
snd_dbri_interrupt(int irq,void * dev_id)19267d12e780SDavid Howells static irqreturn_t snd_dbri_interrupt(int irq, void *dev_id)
19271bd9debfSTakashi Iwai {
1928475675d6STakashi Iwai struct snd_dbri *dbri = dev_id;
1929808709d7SJason Wang static int errcnt;
19301bd9debfSTakashi Iwai int x;
19311bd9debfSTakashi Iwai
19321bd9debfSTakashi Iwai if (dbri == NULL)
19331bd9debfSTakashi Iwai return IRQ_NONE;
19341bd9debfSTakashi Iwai spin_lock(&dbri->lock);
19351bd9debfSTakashi Iwai
19361bd9debfSTakashi Iwai /*
19371bd9debfSTakashi Iwai * Read it, so the interrupt goes away.
19381bd9debfSTakashi Iwai */
19391bd9debfSTakashi Iwai x = sbus_readl(dbri->regs + REG1);
19401bd9debfSTakashi Iwai
19411bd9debfSTakashi Iwai if (x & (D_MRR | D_MLE | D_LBG | D_MBE)) {
19421bd9debfSTakashi Iwai u32 tmp;
19431bd9debfSTakashi Iwai
19441bd9debfSTakashi Iwai if (x & D_MRR)
19451bd9debfSTakashi Iwai printk(KERN_ERR
19461bd9debfSTakashi Iwai "DBRI: Multiple Error Ack on SBus reg1=0x%x\n",
19471bd9debfSTakashi Iwai x);
19481bd9debfSTakashi Iwai if (x & D_MLE)
19491bd9debfSTakashi Iwai printk(KERN_ERR
19501bd9debfSTakashi Iwai "DBRI: Multiple Late Error on SBus reg1=0x%x\n",
19511bd9debfSTakashi Iwai x);
19521bd9debfSTakashi Iwai if (x & D_LBG)
19531bd9debfSTakashi Iwai printk(KERN_ERR
19541bd9debfSTakashi Iwai "DBRI: Lost Bus Grant on SBus reg1=0x%x\n", x);
19551bd9debfSTakashi Iwai if (x & D_MBE)
19561bd9debfSTakashi Iwai printk(KERN_ERR
19571bd9debfSTakashi Iwai "DBRI: Burst Error on SBus reg1=0x%x\n", x);
19581bd9debfSTakashi Iwai
19591bd9debfSTakashi Iwai /* Some of these SBus errors cause the chip's SBus circuitry
19601bd9debfSTakashi Iwai * to be disabled, so just re-enable and try to keep going.
19611bd9debfSTakashi Iwai *
19621bd9debfSTakashi Iwai * The only one I've seen is MRR, which will be triggered
19631bd9debfSTakashi Iwai * if you let a transmit pipe underrun, then try to CDP it.
19641bd9debfSTakashi Iwai *
19654338829eSMartin Habets * If these things persist, we reset the chip.
19661bd9debfSTakashi Iwai */
19671bd9debfSTakashi Iwai if ((++errcnt) % 10 == 0) {
19681bd9debfSTakashi Iwai dprintk(D_INT, "Interrupt errors exceeded.\n");
19691bd9debfSTakashi Iwai dbri_reset(dbri);
19701bd9debfSTakashi Iwai } else {
19711bd9debfSTakashi Iwai tmp = sbus_readl(dbri->regs + REG0);
19721bd9debfSTakashi Iwai tmp &= ~(D_D);
19731bd9debfSTakashi Iwai sbus_writel(tmp, dbri->regs + REG0);
19741bd9debfSTakashi Iwai }
19751bd9debfSTakashi Iwai }
19761bd9debfSTakashi Iwai
19771bd9debfSTakashi Iwai dbri_process_interrupt_buffer(dbri);
19781bd9debfSTakashi Iwai
19791bd9debfSTakashi Iwai spin_unlock(&dbri->lock);
19801bd9debfSTakashi Iwai
19811bd9debfSTakashi Iwai return IRQ_HANDLED;
19821bd9debfSTakashi Iwai }
19831bd9debfSTakashi Iwai
19841bd9debfSTakashi Iwai /****************************************************************************
19851bd9debfSTakashi Iwai PCM Interface
19861bd9debfSTakashi Iwai ****************************************************************************/
1987688ed206SBhumika Goyal static const struct snd_pcm_hardware snd_dbri_pcm_hw = {
1988cf68d212SKrzysztof Helt .info = SNDRV_PCM_INFO_MMAP |
19891bd9debfSTakashi Iwai SNDRV_PCM_INFO_INTERLEAVED |
19901bd9debfSTakashi Iwai SNDRV_PCM_INFO_BLOCK_TRANSFER |
19912008f137STakashi Iwai SNDRV_PCM_INFO_MMAP_VALID |
19922008f137STakashi Iwai SNDRV_PCM_INFO_BATCH,
19931bd9debfSTakashi Iwai .formats = SNDRV_PCM_FMTBIT_MU_LAW |
19941bd9debfSTakashi Iwai SNDRV_PCM_FMTBIT_A_LAW |
19951bd9debfSTakashi Iwai SNDRV_PCM_FMTBIT_U8 |
19961bd9debfSTakashi Iwai SNDRV_PCM_FMTBIT_S16_BE,
1997ab93c7aeSKrzysztof Helt .rates = SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_5512,
1998ab93c7aeSKrzysztof Helt .rate_min = 5512,
19991bd9debfSTakashi Iwai .rate_max = 48000,
20001bd9debfSTakashi Iwai .channels_min = 1,
20011bd9debfSTakashi Iwai .channels_max = 2,
2002cf68d212SKrzysztof Helt .buffer_bytes_max = 64 * 1024,
20031bd9debfSTakashi Iwai .period_bytes_min = 1,
20041bd9debfSTakashi Iwai .period_bytes_max = DBRI_TD_MAXCNT,
20051bd9debfSTakashi Iwai .periods_min = 1,
20061bd9debfSTakashi Iwai .periods_max = 1024,
20071bd9debfSTakashi Iwai };
20081bd9debfSTakashi Iwai
snd_hw_rule_format(struct snd_pcm_hw_params * params,struct snd_pcm_hw_rule * rule)2009ab93c7aeSKrzysztof Helt static int snd_hw_rule_format(struct snd_pcm_hw_params *params,
2010ab93c7aeSKrzysztof Helt struct snd_pcm_hw_rule *rule)
2011ab93c7aeSKrzysztof Helt {
2012ab93c7aeSKrzysztof Helt struct snd_interval *c = hw_param_interval(params,
2013ab93c7aeSKrzysztof Helt SNDRV_PCM_HW_PARAM_CHANNELS);
2014ab93c7aeSKrzysztof Helt struct snd_mask *f = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
2015ab93c7aeSKrzysztof Helt struct snd_mask fmt;
2016ab93c7aeSKrzysztof Helt
2017ab93c7aeSKrzysztof Helt snd_mask_any(&fmt);
2018ab93c7aeSKrzysztof Helt if (c->min > 1) {
2019ab93c7aeSKrzysztof Helt fmt.bits[0] &= SNDRV_PCM_FMTBIT_S16_BE;
2020ab93c7aeSKrzysztof Helt return snd_mask_refine(f, &fmt);
2021ab93c7aeSKrzysztof Helt }
2022ab93c7aeSKrzysztof Helt return 0;
2023ab93c7aeSKrzysztof Helt }
2024ab93c7aeSKrzysztof Helt
snd_hw_rule_channels(struct snd_pcm_hw_params * params,struct snd_pcm_hw_rule * rule)2025ab93c7aeSKrzysztof Helt static int snd_hw_rule_channels(struct snd_pcm_hw_params *params,
2026ab93c7aeSKrzysztof Helt struct snd_pcm_hw_rule *rule)
2027ab93c7aeSKrzysztof Helt {
2028ab93c7aeSKrzysztof Helt struct snd_interval *c = hw_param_interval(params,
2029ab93c7aeSKrzysztof Helt SNDRV_PCM_HW_PARAM_CHANNELS);
2030ab93c7aeSKrzysztof Helt struct snd_mask *f = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
2031ab93c7aeSKrzysztof Helt struct snd_interval ch;
2032ab93c7aeSKrzysztof Helt
2033ab93c7aeSKrzysztof Helt snd_interval_any(&ch);
2034ab93c7aeSKrzysztof Helt if (!(f->bits[0] & SNDRV_PCM_FMTBIT_S16_BE)) {
2035098ccbc5SKrzysztof Helt ch.min = 1;
2036098ccbc5SKrzysztof Helt ch.max = 1;
2037ab93c7aeSKrzysztof Helt ch.integer = 1;
2038ab93c7aeSKrzysztof Helt return snd_interval_refine(c, &ch);
2039ab93c7aeSKrzysztof Helt }
2040ab93c7aeSKrzysztof Helt return 0;
2041ab93c7aeSKrzysztof Helt }
2042ab93c7aeSKrzysztof Helt
snd_dbri_open(struct snd_pcm_substream * substream)2043475675d6STakashi Iwai static int snd_dbri_open(struct snd_pcm_substream *substream)
20441bd9debfSTakashi Iwai {
2045475675d6STakashi Iwai struct snd_dbri *dbri = snd_pcm_substream_chip(substream);
2046475675d6STakashi Iwai struct snd_pcm_runtime *runtime = substream->runtime;
2047475675d6STakashi Iwai struct dbri_streaminfo *info = DBRI_STREAM(dbri, substream);
20481bd9debfSTakashi Iwai unsigned long flags;
20491bd9debfSTakashi Iwai
20501bd9debfSTakashi Iwai dprintk(D_USR, "open audio output.\n");
20511bd9debfSTakashi Iwai runtime->hw = snd_dbri_pcm_hw;
20521bd9debfSTakashi Iwai
20531bd9debfSTakashi Iwai spin_lock_irqsave(&dbri->lock, flags);
20541bd9debfSTakashi Iwai info->substream = substream;
20551bd9debfSTakashi Iwai info->offset = 0;
20561bd9debfSTakashi Iwai info->dvma_buffer = 0;
20571bd9debfSTakashi Iwai info->pipe = -1;
20581bd9debfSTakashi Iwai spin_unlock_irqrestore(&dbri->lock, flags);
20591bd9debfSTakashi Iwai
2060ab93c7aeSKrzysztof Helt snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
2061ae97dd9aSAl Viro snd_hw_rule_format, NULL, SNDRV_PCM_HW_PARAM_FORMAT,
2062ab93c7aeSKrzysztof Helt -1);
2063ab93c7aeSKrzysztof Helt snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT,
2064ae97dd9aSAl Viro snd_hw_rule_channels, NULL,
2065ab93c7aeSKrzysztof Helt SNDRV_PCM_HW_PARAM_CHANNELS,
2066ab93c7aeSKrzysztof Helt -1);
2067ab93c7aeSKrzysztof Helt
20681bd9debfSTakashi Iwai cs4215_open(dbri);
20691bd9debfSTakashi Iwai
20701bd9debfSTakashi Iwai return 0;
20711bd9debfSTakashi Iwai }
20721bd9debfSTakashi Iwai
snd_dbri_close(struct snd_pcm_substream * substream)2073475675d6STakashi Iwai static int snd_dbri_close(struct snd_pcm_substream *substream)
20741bd9debfSTakashi Iwai {
2075475675d6STakashi Iwai struct snd_dbri *dbri = snd_pcm_substream_chip(substream);
2076475675d6STakashi Iwai struct dbri_streaminfo *info = DBRI_STREAM(dbri, substream);
20771bd9debfSTakashi Iwai
20781bd9debfSTakashi Iwai dprintk(D_USR, "close audio output.\n");
20791bd9debfSTakashi Iwai info->substream = NULL;
20801bd9debfSTakashi Iwai info->offset = 0;
20811bd9debfSTakashi Iwai
20821bd9debfSTakashi Iwai return 0;
20831bd9debfSTakashi Iwai }
20841bd9debfSTakashi Iwai
snd_dbri_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * hw_params)2085475675d6STakashi Iwai static int snd_dbri_hw_params(struct snd_pcm_substream *substream,
2086475675d6STakashi Iwai struct snd_pcm_hw_params *hw_params)
20871bd9debfSTakashi Iwai {
2088475675d6STakashi Iwai struct snd_pcm_runtime *runtime = substream->runtime;
2089475675d6STakashi Iwai struct snd_dbri *dbri = snd_pcm_substream_chip(substream);
2090475675d6STakashi Iwai struct dbri_streaminfo *info = DBRI_STREAM(dbri, substream);
20911bd9debfSTakashi Iwai int direction;
20921bd9debfSTakashi Iwai int ret;
20931bd9debfSTakashi Iwai
20941bd9debfSTakashi Iwai /* set sampling rate, audio format and number of channels */
20951bd9debfSTakashi Iwai ret = cs4215_prepare(dbri, params_rate(hw_params),
20961bd9debfSTakashi Iwai params_format(hw_params),
20971bd9debfSTakashi Iwai params_channels(hw_params));
20981bd9debfSTakashi Iwai if (ret != 0)
20991bd9debfSTakashi Iwai return ret;
21001bd9debfSTakashi Iwai
21011bd9debfSTakashi Iwai /* hw_params can get called multiple times. Only map the DMA once.
21021bd9debfSTakashi Iwai */
21031bd9debfSTakashi Iwai if (info->dvma_buffer == 0) {
21041bd9debfSTakashi Iwai if (DBRI_STREAMNO(substream) == DBRI_PLAY)
2105738f2b7bSDavid S. Miller direction = DMA_TO_DEVICE;
21061bd9debfSTakashi Iwai else
2107738f2b7bSDavid S. Miller direction = DMA_FROM_DEVICE;
21081bd9debfSTakashi Iwai
21097a715f46SDavid S. Miller info->dvma_buffer =
21102bd320f8SDavid S. Miller dma_map_single(&dbri->op->dev,
21111bd9debfSTakashi Iwai runtime->dma_area,
21121bd9debfSTakashi Iwai params_buffer_bytes(hw_params),
21131bd9debfSTakashi Iwai direction);
21141bd9debfSTakashi Iwai }
21151bd9debfSTakashi Iwai
21161bd9debfSTakashi Iwai direction = params_buffer_bytes(hw_params);
21171bd9debfSTakashi Iwai dprintk(D_USR, "hw_params: %d bytes, dvma=%x\n",
21181bd9debfSTakashi Iwai direction, info->dvma_buffer);
21191bd9debfSTakashi Iwai return 0;
21201bd9debfSTakashi Iwai }
21211bd9debfSTakashi Iwai
snd_dbri_hw_free(struct snd_pcm_substream * substream)2122475675d6STakashi Iwai static int snd_dbri_hw_free(struct snd_pcm_substream *substream)
21231bd9debfSTakashi Iwai {
2124475675d6STakashi Iwai struct snd_dbri *dbri = snd_pcm_substream_chip(substream);
2125475675d6STakashi Iwai struct dbri_streaminfo *info = DBRI_STREAM(dbri, substream);
21261bd9debfSTakashi Iwai int direction;
212799dabfe7SKrzysztof Helt
21281bd9debfSTakashi Iwai dprintk(D_USR, "hw_free.\n");
21291bd9debfSTakashi Iwai
21301bd9debfSTakashi Iwai /* hw_free can get called multiple times. Only unmap the DMA once.
21311bd9debfSTakashi Iwai */
21321bd9debfSTakashi Iwai if (info->dvma_buffer) {
21331bd9debfSTakashi Iwai if (DBRI_STREAMNO(substream) == DBRI_PLAY)
2134738f2b7bSDavid S. Miller direction = DMA_TO_DEVICE;
21351bd9debfSTakashi Iwai else
2136738f2b7bSDavid S. Miller direction = DMA_FROM_DEVICE;
21371bd9debfSTakashi Iwai
21382bd320f8SDavid S. Miller dma_unmap_single(&dbri->op->dev, info->dvma_buffer,
21391bd9debfSTakashi Iwai substream->runtime->buffer_size, direction);
21401bd9debfSTakashi Iwai info->dvma_buffer = 0;
21411bd9debfSTakashi Iwai }
214299dabfe7SKrzysztof Helt if (info->pipe != -1) {
214399dabfe7SKrzysztof Helt reset_pipe(dbri, info->pipe);
21441bd9debfSTakashi Iwai info->pipe = -1;
214599dabfe7SKrzysztof Helt }
21461bd9debfSTakashi Iwai
2147786e90b0STakashi Iwai return 0;
21481bd9debfSTakashi Iwai }
21491bd9debfSTakashi Iwai
snd_dbri_prepare(struct snd_pcm_substream * substream)2150475675d6STakashi Iwai static int snd_dbri_prepare(struct snd_pcm_substream *substream)
21511bd9debfSTakashi Iwai {
2152475675d6STakashi Iwai struct snd_dbri *dbri = snd_pcm_substream_chip(substream);
2153475675d6STakashi Iwai struct dbri_streaminfo *info = DBRI_STREAM(dbri, substream);
21541bd9debfSTakashi Iwai int ret;
21551bd9debfSTakashi Iwai
21561bd9debfSTakashi Iwai info->size = snd_pcm_lib_buffer_bytes(substream);
21571bd9debfSTakashi Iwai if (DBRI_STREAMNO(substream) == DBRI_PLAY)
21581bd9debfSTakashi Iwai info->pipe = 4; /* Send pipe */
21591be54c82SKrzysztof Helt else
21601bd9debfSTakashi Iwai info->pipe = 6; /* Receive pipe */
21611bd9debfSTakashi Iwai
21621bd9debfSTakashi Iwai spin_lock_irq(&dbri->lock);
2163aaad3653SKrzysztof Helt info->offset = 0;
21641bd9debfSTakashi Iwai
2165098ccbc5SKrzysztof Helt /* Setup the all the transmit/receive descriptors to cover the
21661bd9debfSTakashi Iwai * whole DMA buffer.
21671bd9debfSTakashi Iwai */
21681bd9debfSTakashi Iwai ret = setup_descs(dbri, DBRI_STREAMNO(substream),
21691bd9debfSTakashi Iwai snd_pcm_lib_period_bytes(substream));
21701bd9debfSTakashi Iwai
21711bd9debfSTakashi Iwai spin_unlock_irq(&dbri->lock);
21721bd9debfSTakashi Iwai
21731bd9debfSTakashi Iwai dprintk(D_USR, "prepare audio output. %d bytes\n", info->size);
21741bd9debfSTakashi Iwai return ret;
21751bd9debfSTakashi Iwai }
21761bd9debfSTakashi Iwai
snd_dbri_trigger(struct snd_pcm_substream * substream,int cmd)2177475675d6STakashi Iwai static int snd_dbri_trigger(struct snd_pcm_substream *substream, int cmd)
21781bd9debfSTakashi Iwai {
2179475675d6STakashi Iwai struct snd_dbri *dbri = snd_pcm_substream_chip(substream);
2180475675d6STakashi Iwai struct dbri_streaminfo *info = DBRI_STREAM(dbri, substream);
21811bd9debfSTakashi Iwai int ret = 0;
21821bd9debfSTakashi Iwai
21831bd9debfSTakashi Iwai switch (cmd) {
21841bd9debfSTakashi Iwai case SNDRV_PCM_TRIGGER_START:
21851bd9debfSTakashi Iwai dprintk(D_USR, "start audio, period is %d bytes\n",
21861bd9debfSTakashi Iwai (int)snd_pcm_lib_period_bytes(substream));
21871be54c82SKrzysztof Helt /* Re-submit the TDs. */
21881be54c82SKrzysztof Helt xmit_descs(dbri);
21891bd9debfSTakashi Iwai break;
21901bd9debfSTakashi Iwai case SNDRV_PCM_TRIGGER_STOP:
21911bd9debfSTakashi Iwai dprintk(D_USR, "stop audio.\n");
21921bd9debfSTakashi Iwai reset_pipe(dbri, info->pipe);
21931bd9debfSTakashi Iwai break;
21941bd9debfSTakashi Iwai default:
21951bd9debfSTakashi Iwai ret = -EINVAL;
21961bd9debfSTakashi Iwai }
21971bd9debfSTakashi Iwai
21981bd9debfSTakashi Iwai return ret;
21991bd9debfSTakashi Iwai }
22001bd9debfSTakashi Iwai
snd_dbri_pointer(struct snd_pcm_substream * substream)2201475675d6STakashi Iwai static snd_pcm_uframes_t snd_dbri_pointer(struct snd_pcm_substream *substream)
22021bd9debfSTakashi Iwai {
2203475675d6STakashi Iwai struct snd_dbri *dbri = snd_pcm_substream_chip(substream);
2204475675d6STakashi Iwai struct dbri_streaminfo *info = DBRI_STREAM(dbri, substream);
22051bd9debfSTakashi Iwai snd_pcm_uframes_t ret;
22061bd9debfSTakashi Iwai
22071bd9debfSTakashi Iwai ret = bytes_to_frames(substream->runtime, info->offset)
22081bd9debfSTakashi Iwai % substream->runtime->buffer_size;
22091be54c82SKrzysztof Helt dprintk(D_USR, "I/O pointer: %ld frames of %ld.\n",
22101be54c82SKrzysztof Helt ret, substream->runtime->buffer_size);
22111bd9debfSTakashi Iwai return ret;
22121bd9debfSTakashi Iwai }
22131bd9debfSTakashi Iwai
2214544d6272SArvind Yadav static const struct snd_pcm_ops snd_dbri_ops = {
22151bd9debfSTakashi Iwai .open = snd_dbri_open,
22161bd9debfSTakashi Iwai .close = snd_dbri_close,
22171bd9debfSTakashi Iwai .hw_params = snd_dbri_hw_params,
22181bd9debfSTakashi Iwai .hw_free = snd_dbri_hw_free,
22191bd9debfSTakashi Iwai .prepare = snd_dbri_prepare,
22201bd9debfSTakashi Iwai .trigger = snd_dbri_trigger,
22211bd9debfSTakashi Iwai .pointer = snd_dbri_pointer,
22221bd9debfSTakashi Iwai };
22231bd9debfSTakashi Iwai
snd_dbri_pcm(struct snd_card * card)222432e02a7bSBill Pemberton static int snd_dbri_pcm(struct snd_card *card)
22251bd9debfSTakashi Iwai {
2226475675d6STakashi Iwai struct snd_pcm *pcm;
22271bd9debfSTakashi Iwai int err;
22281bd9debfSTakashi Iwai
2229bdab9e5cSTakashi Iwai err = snd_pcm_new(card,
22301bd9debfSTakashi Iwai /* ID */ "sun_dbri",
22311bd9debfSTakashi Iwai /* device */ 0,
22321bd9debfSTakashi Iwai /* playback count */ 1,
2233bdab9e5cSTakashi Iwai /* capture count */ 1, &pcm);
2234bdab9e5cSTakashi Iwai if (err < 0)
22351bd9debfSTakashi Iwai return err;
22361bd9debfSTakashi Iwai
22371bd9debfSTakashi Iwai snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_dbri_ops);
22381bd9debfSTakashi Iwai snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_dbri_ops);
22391bd9debfSTakashi Iwai
2240afeacfd5SKrzysztof Helt pcm->private_data = card->private_data;
22411bd9debfSTakashi Iwai pcm->info_flags = 0;
2242afeacfd5SKrzysztof Helt strcpy(pcm->name, card->shortname);
22431bd9debfSTakashi Iwai
2244786e90b0STakashi Iwai snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
2245786e90b0STakashi Iwai NULL, 64 * 1024, 64 * 1024);
22461bd9debfSTakashi Iwai return 0;
22471bd9debfSTakashi Iwai }
22481bd9debfSTakashi Iwai
22491bd9debfSTakashi Iwai /*****************************************************************************
22501bd9debfSTakashi Iwai Mixer interface
22511bd9debfSTakashi Iwai *****************************************************************************/
22521bd9debfSTakashi Iwai
snd_cs4215_info_volume(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)2253475675d6STakashi Iwai static int snd_cs4215_info_volume(struct snd_kcontrol *kcontrol,
2254475675d6STakashi Iwai struct snd_ctl_elem_info *uinfo)
22551bd9debfSTakashi Iwai {
22561bd9debfSTakashi Iwai uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
22571bd9debfSTakashi Iwai uinfo->count = 2;
22581bd9debfSTakashi Iwai uinfo->value.integer.min = 0;
2259cf68d212SKrzysztof Helt if (kcontrol->private_value == DBRI_PLAY)
22601bd9debfSTakashi Iwai uinfo->value.integer.max = DBRI_MAX_VOLUME;
2261cf68d212SKrzysztof Helt else
22621bd9debfSTakashi Iwai uinfo->value.integer.max = DBRI_MAX_GAIN;
22631bd9debfSTakashi Iwai return 0;
22641bd9debfSTakashi Iwai }
22651bd9debfSTakashi Iwai
snd_cs4215_get_volume(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)2266475675d6STakashi Iwai static int snd_cs4215_get_volume(struct snd_kcontrol *kcontrol,
2267475675d6STakashi Iwai struct snd_ctl_elem_value *ucontrol)
22681bd9debfSTakashi Iwai {
2269475675d6STakashi Iwai struct snd_dbri *dbri = snd_kcontrol_chip(kcontrol);
2270475675d6STakashi Iwai struct dbri_streaminfo *info;
22715e246b85STakashi Iwai
22725e246b85STakashi Iwai if (snd_BUG_ON(!dbri))
22735e246b85STakashi Iwai return -EINVAL;
22741bd9debfSTakashi Iwai info = &dbri->stream_info[kcontrol->private_value];
22751bd9debfSTakashi Iwai
22761bd9debfSTakashi Iwai ucontrol->value.integer.value[0] = info->left_gain;
22771bd9debfSTakashi Iwai ucontrol->value.integer.value[1] = info->right_gain;
22781bd9debfSTakashi Iwai return 0;
22791bd9debfSTakashi Iwai }
22801bd9debfSTakashi Iwai
snd_cs4215_put_volume(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)2281475675d6STakashi Iwai static int snd_cs4215_put_volume(struct snd_kcontrol *kcontrol,
2282475675d6STakashi Iwai struct snd_ctl_elem_value *ucontrol)
22831bd9debfSTakashi Iwai {
2284475675d6STakashi Iwai struct snd_dbri *dbri = snd_kcontrol_chip(kcontrol);
2285098ccbc5SKrzysztof Helt struct dbri_streaminfo *info =
2286098ccbc5SKrzysztof Helt &dbri->stream_info[kcontrol->private_value];
22873b892467STakashi Iwai unsigned int vol[2];
22881bd9debfSTakashi Iwai int changed = 0;
22891bd9debfSTakashi Iwai
22903b892467STakashi Iwai vol[0] = ucontrol->value.integer.value[0];
22913b892467STakashi Iwai vol[1] = ucontrol->value.integer.value[1];
22923b892467STakashi Iwai if (kcontrol->private_value == DBRI_PLAY) {
22933b892467STakashi Iwai if (vol[0] > DBRI_MAX_VOLUME || vol[1] > DBRI_MAX_VOLUME)
22943b892467STakashi Iwai return -EINVAL;
22953b892467STakashi Iwai } else {
22963b892467STakashi Iwai if (vol[0] > DBRI_MAX_GAIN || vol[1] > DBRI_MAX_GAIN)
22973b892467STakashi Iwai return -EINVAL;
22983b892467STakashi Iwai }
22993b892467STakashi Iwai
23004581aa36STakashi Iwai if (info->left_gain != vol[0]) {
23014581aa36STakashi Iwai info->left_gain = vol[0];
23021bd9debfSTakashi Iwai changed = 1;
23031bd9debfSTakashi Iwai }
23044581aa36STakashi Iwai if (info->right_gain != vol[1]) {
23054581aa36STakashi Iwai info->right_gain = vol[1];
23061bd9debfSTakashi Iwai changed = 1;
23071bd9debfSTakashi Iwai }
2308cf68d212SKrzysztof Helt if (changed) {
23091bd9debfSTakashi Iwai /* First mute outputs, and wait 1/8000 sec (125 us)
23101bd9debfSTakashi Iwai * to make sure this takes. This avoids clicking noises.
23111bd9debfSTakashi Iwai */
23121bd9debfSTakashi Iwai cs4215_setdata(dbri, 1);
23131bd9debfSTakashi Iwai udelay(125);
23141bd9debfSTakashi Iwai cs4215_setdata(dbri, 0);
23151bd9debfSTakashi Iwai }
23161bd9debfSTakashi Iwai return changed;
23171bd9debfSTakashi Iwai }
23181bd9debfSTakashi Iwai
snd_cs4215_info_single(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)2319475675d6STakashi Iwai static int snd_cs4215_info_single(struct snd_kcontrol *kcontrol,
2320475675d6STakashi Iwai struct snd_ctl_elem_info *uinfo)
23211bd9debfSTakashi Iwai {
23221bd9debfSTakashi Iwai int mask = (kcontrol->private_value >> 16) & 0xff;
23231bd9debfSTakashi Iwai
23241bd9debfSTakashi Iwai uinfo->type = (mask == 1) ?
23251bd9debfSTakashi Iwai SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
23261bd9debfSTakashi Iwai uinfo->count = 1;
23271bd9debfSTakashi Iwai uinfo->value.integer.min = 0;
23281bd9debfSTakashi Iwai uinfo->value.integer.max = mask;
23291bd9debfSTakashi Iwai return 0;
23301bd9debfSTakashi Iwai }
23311bd9debfSTakashi Iwai
snd_cs4215_get_single(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)2332475675d6STakashi Iwai static int snd_cs4215_get_single(struct snd_kcontrol *kcontrol,
2333475675d6STakashi Iwai struct snd_ctl_elem_value *ucontrol)
23341bd9debfSTakashi Iwai {
2335475675d6STakashi Iwai struct snd_dbri *dbri = snd_kcontrol_chip(kcontrol);
23361bd9debfSTakashi Iwai int elem = kcontrol->private_value & 0xff;
23371bd9debfSTakashi Iwai int shift = (kcontrol->private_value >> 8) & 0xff;
23381bd9debfSTakashi Iwai int mask = (kcontrol->private_value >> 16) & 0xff;
23391bd9debfSTakashi Iwai int invert = (kcontrol->private_value >> 24) & 1;
23405e246b85STakashi Iwai
23415e246b85STakashi Iwai if (snd_BUG_ON(!dbri))
23425e246b85STakashi Iwai return -EINVAL;
23431bd9debfSTakashi Iwai
2344098ccbc5SKrzysztof Helt if (elem < 4)
23451bd9debfSTakashi Iwai ucontrol->value.integer.value[0] =
23461bd9debfSTakashi Iwai (dbri->mm.data[elem] >> shift) & mask;
2347098ccbc5SKrzysztof Helt else
23481bd9debfSTakashi Iwai ucontrol->value.integer.value[0] =
23491bd9debfSTakashi Iwai (dbri->mm.ctrl[elem - 4] >> shift) & mask;
23501bd9debfSTakashi Iwai
2351098ccbc5SKrzysztof Helt if (invert == 1)
23521bd9debfSTakashi Iwai ucontrol->value.integer.value[0] =
23531bd9debfSTakashi Iwai mask - ucontrol->value.integer.value[0];
23541bd9debfSTakashi Iwai return 0;
23551bd9debfSTakashi Iwai }
23561bd9debfSTakashi Iwai
snd_cs4215_put_single(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)2357475675d6STakashi Iwai static int snd_cs4215_put_single(struct snd_kcontrol *kcontrol,
2358475675d6STakashi Iwai struct snd_ctl_elem_value *ucontrol)
23591bd9debfSTakashi Iwai {
2360475675d6STakashi Iwai struct snd_dbri *dbri = snd_kcontrol_chip(kcontrol);
23611bd9debfSTakashi Iwai int elem = kcontrol->private_value & 0xff;
23621bd9debfSTakashi Iwai int shift = (kcontrol->private_value >> 8) & 0xff;
23631bd9debfSTakashi Iwai int mask = (kcontrol->private_value >> 16) & 0xff;
23641bd9debfSTakashi Iwai int invert = (kcontrol->private_value >> 24) & 1;
23651bd9debfSTakashi Iwai int changed = 0;
23661bd9debfSTakashi Iwai unsigned short val;
23675e246b85STakashi Iwai
23685e246b85STakashi Iwai if (snd_BUG_ON(!dbri))
23695e246b85STakashi Iwai return -EINVAL;
23701bd9debfSTakashi Iwai
23711bd9debfSTakashi Iwai val = (ucontrol->value.integer.value[0] & mask);
23721bd9debfSTakashi Iwai if (invert == 1)
23731bd9debfSTakashi Iwai val = mask - val;
23741bd9debfSTakashi Iwai val <<= shift;
23751bd9debfSTakashi Iwai
23761bd9debfSTakashi Iwai if (elem < 4) {
23771bd9debfSTakashi Iwai dbri->mm.data[elem] = (dbri->mm.data[elem] &
23781bd9debfSTakashi Iwai ~(mask << shift)) | val;
23791bd9debfSTakashi Iwai changed = (val != dbri->mm.data[elem]);
23801bd9debfSTakashi Iwai } else {
23811bd9debfSTakashi Iwai dbri->mm.ctrl[elem - 4] = (dbri->mm.ctrl[elem - 4] &
23821bd9debfSTakashi Iwai ~(mask << shift)) | val;
23831bd9debfSTakashi Iwai changed = (val != dbri->mm.ctrl[elem - 4]);
23841bd9debfSTakashi Iwai }
23851bd9debfSTakashi Iwai
23861bd9debfSTakashi Iwai dprintk(D_GEN, "put_single: mask=0x%x, changed=%d, "
23871bd9debfSTakashi Iwai "mixer-value=%ld, mm-value=0x%x\n",
23881bd9debfSTakashi Iwai mask, changed, ucontrol->value.integer.value[0],
23891bd9debfSTakashi Iwai dbri->mm.data[elem & 3]);
23901bd9debfSTakashi Iwai
23911bd9debfSTakashi Iwai if (changed) {
23921bd9debfSTakashi Iwai /* First mute outputs, and wait 1/8000 sec (125 us)
23931bd9debfSTakashi Iwai * to make sure this takes. This avoids clicking noises.
23941bd9debfSTakashi Iwai */
23951bd9debfSTakashi Iwai cs4215_setdata(dbri, 1);
23961bd9debfSTakashi Iwai udelay(125);
23971bd9debfSTakashi Iwai cs4215_setdata(dbri, 0);
23981bd9debfSTakashi Iwai }
23991bd9debfSTakashi Iwai return changed;
24001bd9debfSTakashi Iwai }
24011bd9debfSTakashi Iwai
24021bd9debfSTakashi Iwai /* Entries 0-3 map to the 4 data timeslots, entries 4-7 map to the 4 control
24031bd9debfSTakashi Iwai timeslots. Shift is the bit offset in the timeslot, mask defines the
24041bd9debfSTakashi Iwai number of bits. invert is a boolean for use with attenuation.
24051bd9debfSTakashi Iwai */
24061bd9debfSTakashi Iwai #define CS4215_SINGLE(xname, entry, shift, mask, invert) \
2407098ccbc5SKrzysztof Helt { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
24081bd9debfSTakashi Iwai .info = snd_cs4215_info_single, \
24091bd9debfSTakashi Iwai .get = snd_cs4215_get_single, .put = snd_cs4215_put_single, \
2410098ccbc5SKrzysztof Helt .private_value = (entry) | ((shift) << 8) | ((mask) << 16) | \
2411098ccbc5SKrzysztof Helt ((invert) << 24) },
24121bd9debfSTakashi Iwai
2413f8a32d94STakashi Iwai static const struct snd_kcontrol_new dbri_controls[] = {
24141bd9debfSTakashi Iwai {
24151bd9debfSTakashi Iwai .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
24161bd9debfSTakashi Iwai .name = "Playback Volume",
24171bd9debfSTakashi Iwai .info = snd_cs4215_info_volume,
24181bd9debfSTakashi Iwai .get = snd_cs4215_get_volume,
24191bd9debfSTakashi Iwai .put = snd_cs4215_put_volume,
24201bd9debfSTakashi Iwai .private_value = DBRI_PLAY,
24211bd9debfSTakashi Iwai },
24221bd9debfSTakashi Iwai CS4215_SINGLE("Headphone switch", 0, 7, 1, 0)
24231bd9debfSTakashi Iwai CS4215_SINGLE("Line out switch", 0, 6, 1, 0)
24241bd9debfSTakashi Iwai CS4215_SINGLE("Speaker switch", 1, 6, 1, 0)
24251bd9debfSTakashi Iwai {
24261bd9debfSTakashi Iwai .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
24271bd9debfSTakashi Iwai .name = "Capture Volume",
24281bd9debfSTakashi Iwai .info = snd_cs4215_info_volume,
24291bd9debfSTakashi Iwai .get = snd_cs4215_get_volume,
24301bd9debfSTakashi Iwai .put = snd_cs4215_put_volume,
24311bd9debfSTakashi Iwai .private_value = DBRI_REC,
24321bd9debfSTakashi Iwai },
24331bd9debfSTakashi Iwai /* FIXME: mic/line switch */
24341bd9debfSTakashi Iwai CS4215_SINGLE("Line in switch", 2, 4, 1, 0)
24351bd9debfSTakashi Iwai CS4215_SINGLE("High Pass Filter switch", 5, 7, 1, 0)
24361bd9debfSTakashi Iwai CS4215_SINGLE("Monitor Volume", 3, 4, 0xf, 1)
24371bd9debfSTakashi Iwai CS4215_SINGLE("Mic boost", 4, 4, 1, 1)
24381bd9debfSTakashi Iwai };
24391bd9debfSTakashi Iwai
snd_dbri_mixer(struct snd_card * card)244032e02a7bSBill Pemberton static int snd_dbri_mixer(struct snd_card *card)
24411bd9debfSTakashi Iwai {
24421bd9debfSTakashi Iwai int idx, err;
2443afeacfd5SKrzysztof Helt struct snd_dbri *dbri;
24441bd9debfSTakashi Iwai
24455e246b85STakashi Iwai if (snd_BUG_ON(!card || !card->private_data))
24465e246b85STakashi Iwai return -EINVAL;
2447afeacfd5SKrzysztof Helt dbri = card->private_data;
24481bd9debfSTakashi Iwai
24491bd9debfSTakashi Iwai strcpy(card->mixername, card->shortname);
24501bd9debfSTakashi Iwai
24516c2d8b5dSTobias Klauser for (idx = 0; idx < ARRAY_SIZE(dbri_controls); idx++) {
2452cf68d212SKrzysztof Helt err = snd_ctl_add(card,
2453cf68d212SKrzysztof Helt snd_ctl_new1(&dbri_controls[idx], dbri));
2454cf68d212SKrzysztof Helt if (err < 0)
24551bd9debfSTakashi Iwai return err;
24561bd9debfSTakashi Iwai }
24571bd9debfSTakashi Iwai
24581bd9debfSTakashi Iwai for (idx = DBRI_REC; idx < DBRI_NO_STREAMS; idx++) {
24591bd9debfSTakashi Iwai dbri->stream_info[idx].left_gain = 0;
24601bd9debfSTakashi Iwai dbri->stream_info[idx].right_gain = 0;
24611bd9debfSTakashi Iwai }
24621bd9debfSTakashi Iwai
24631bd9debfSTakashi Iwai return 0;
24641bd9debfSTakashi Iwai }
24651bd9debfSTakashi Iwai
24661bd9debfSTakashi Iwai /****************************************************************************
24671bd9debfSTakashi Iwai /proc interface
24681bd9debfSTakashi Iwai ****************************************************************************/
dbri_regs_read(struct snd_info_entry * entry,struct snd_info_buffer * buffer)2469098ccbc5SKrzysztof Helt static void dbri_regs_read(struct snd_info_entry *entry,
2470098ccbc5SKrzysztof Helt struct snd_info_buffer *buffer)
24711bd9debfSTakashi Iwai {
2472475675d6STakashi Iwai struct snd_dbri *dbri = entry->private_data;
24731bd9debfSTakashi Iwai
24741bd9debfSTakashi Iwai snd_iprintf(buffer, "REG0: 0x%x\n", sbus_readl(dbri->regs + REG0));
24751bd9debfSTakashi Iwai snd_iprintf(buffer, "REG2: 0x%x\n", sbus_readl(dbri->regs + REG2));
24761bd9debfSTakashi Iwai snd_iprintf(buffer, "REG8: 0x%x\n", sbus_readl(dbri->regs + REG8));
24771bd9debfSTakashi Iwai snd_iprintf(buffer, "REG9: 0x%x\n", sbus_readl(dbri->regs + REG9));
24781bd9debfSTakashi Iwai }
24791bd9debfSTakashi Iwai
24801bd9debfSTakashi Iwai #ifdef DBRI_DEBUG
dbri_debug_read(struct snd_info_entry * entry,struct snd_info_buffer * buffer)2481475675d6STakashi Iwai static void dbri_debug_read(struct snd_info_entry *entry,
2482475675d6STakashi Iwai struct snd_info_buffer *buffer)
24831bd9debfSTakashi Iwai {
2484475675d6STakashi Iwai struct snd_dbri *dbri = entry->private_data;
24851bd9debfSTakashi Iwai int pipe;
24861bd9debfSTakashi Iwai snd_iprintf(buffer, "debug=%d\n", dbri_debug);
24871bd9debfSTakashi Iwai
24881bd9debfSTakashi Iwai for (pipe = 0; pipe < 32; pipe++) {
24891bd9debfSTakashi Iwai if (pipe_active(dbri, pipe)) {
24901bd9debfSTakashi Iwai struct dbri_pipe *pptr = &dbri->pipes[pipe];
24911bd9debfSTakashi Iwai snd_iprintf(buffer,
24921bd9debfSTakashi Iwai "Pipe %d: %s SDP=0x%x desc=%d, "
2493294a30dcSKrzysztof Helt "len=%d next %d\n",
24941bd9debfSTakashi Iwai pipe,
2495cf68d212SKrzysztof Helt (pptr->sdp & D_SDP_TO_SER) ? "output" :
2496cf68d212SKrzysztof Helt "input",
24975fc3a2b2SKrzysztof Helt pptr->sdp, pptr->desc,
2498294a30dcSKrzysztof Helt pptr->length, pptr->nextpipe);
24991bd9debfSTakashi Iwai }
25001bd9debfSTakashi Iwai }
25011bd9debfSTakashi Iwai }
25021bd9debfSTakashi Iwai #endif
25031bd9debfSTakashi Iwai
snd_dbri_proc(struct snd_card * card)250432e02a7bSBill Pemberton static void snd_dbri_proc(struct snd_card *card)
25051bd9debfSTakashi Iwai {
2506afeacfd5SKrzysztof Helt struct snd_dbri *dbri = card->private_data;
25071bd9debfSTakashi Iwai
25083c6ee770STakashi Iwai snd_card_ro_proc_new(card, "regs", dbri, dbri_regs_read);
25091bd9debfSTakashi Iwai #ifdef DBRI_DEBUG
25103c6ee770STakashi Iwai snd_card_ro_proc_new(card, "debug", dbri, dbri_debug_read);
25111bd9debfSTakashi Iwai #endif
25121bd9debfSTakashi Iwai }
25131bd9debfSTakashi Iwai
25141bd9debfSTakashi Iwai /*
25151bd9debfSTakashi Iwai ****************************************************************************
25161bd9debfSTakashi Iwai **************************** Initialization ********************************
25171bd9debfSTakashi Iwai ****************************************************************************
25181bd9debfSTakashi Iwai */
2519475675d6STakashi Iwai static void snd_dbri_free(struct snd_dbri *dbri);
25201bd9debfSTakashi Iwai
snd_dbri_create(struct snd_card * card,struct platform_device * op,int irq,int dev)252132e02a7bSBill Pemberton static int snd_dbri_create(struct snd_card *card,
25222dc11581SGrant Likely struct platform_device *op,
2523afeacfd5SKrzysztof Helt int irq, int dev)
25241bd9debfSTakashi Iwai {
2525475675d6STakashi Iwai struct snd_dbri *dbri = card->private_data;
25261bd9debfSTakashi Iwai int err;
25271bd9debfSTakashi Iwai
25281bd9debfSTakashi Iwai spin_lock_init(&dbri->lock);
25292bd320f8SDavid S. Miller dbri->op = op;
2530afeacfd5SKrzysztof Helt dbri->irq = irq;
25311bd9debfSTakashi Iwai
2532750afb08SLuis Chamberlain dbri->dma = dma_alloc_coherent(&op->dev, sizeof(struct dbri_dma),
2533207459a2STakashi Iwai &dbri->dma_dvma, GFP_KERNEL);
2534be376649SFUJITA Tomonori if (!dbri->dma)
2535be376649SFUJITA Tomonori return -ENOMEM;
25361bd9debfSTakashi Iwai
253716f46050STushar Dave dprintk(D_GEN, "DMA Cmd Block 0x%p (%pad)\n",
25381bd9debfSTakashi Iwai dbri->dma, dbri->dma_dvma);
25391bd9debfSTakashi Iwai
25401bd9debfSTakashi Iwai /* Map the registers into memory. */
25412bd320f8SDavid S. Miller dbri->regs_size = resource_size(&op->resource[0]);
25422bd320f8SDavid S. Miller dbri->regs = of_ioremap(&op->resource[0], 0,
25431bd9debfSTakashi Iwai dbri->regs_size, "DBRI Registers");
25441bd9debfSTakashi Iwai if (!dbri->regs) {
25451bd9debfSTakashi Iwai printk(KERN_ERR "DBRI: could not allocate registers\n");
25462bd320f8SDavid S. Miller dma_free_coherent(&op->dev, sizeof(struct dbri_dma),
25471bd9debfSTakashi Iwai (void *)dbri->dma, dbri->dma_dvma);
25481bd9debfSTakashi Iwai return -EIO;
25491bd9debfSTakashi Iwai }
25501bd9debfSTakashi Iwai
255165ca68b3SThomas Gleixner err = request_irq(dbri->irq, snd_dbri_interrupt, IRQF_SHARED,
25521bd9debfSTakashi Iwai "DBRI audio", dbri);
25531bd9debfSTakashi Iwai if (err) {
25541bd9debfSTakashi Iwai printk(KERN_ERR "DBRI: Can't get irq %d\n", dbri->irq);
25552bd320f8SDavid S. Miller of_iounmap(&op->resource[0], dbri->regs, dbri->regs_size);
25562bd320f8SDavid S. Miller dma_free_coherent(&op->dev, sizeof(struct dbri_dma),
25571bd9debfSTakashi Iwai (void *)dbri->dma, dbri->dma_dvma);
25581bd9debfSTakashi Iwai return err;
25591bd9debfSTakashi Iwai }
25601bd9debfSTakashi Iwai
25611bd9debfSTakashi Iwai /* Do low level initialization of the DBRI and CS4215 chips */
25621bd9debfSTakashi Iwai dbri_initialize(dbri);
25631bd9debfSTakashi Iwai err = cs4215_init(dbri);
25641bd9debfSTakashi Iwai if (err) {
25651bd9debfSTakashi Iwai snd_dbri_free(dbri);
25661bd9debfSTakashi Iwai return err;
25671bd9debfSTakashi Iwai }
25681bd9debfSTakashi Iwai
25691bd9debfSTakashi Iwai return 0;
25701bd9debfSTakashi Iwai }
25711bd9debfSTakashi Iwai
snd_dbri_free(struct snd_dbri * dbri)2572475675d6STakashi Iwai static void snd_dbri_free(struct snd_dbri *dbri)
25731bd9debfSTakashi Iwai {
25741bd9debfSTakashi Iwai dprintk(D_GEN, "snd_dbri_free\n");
25751bd9debfSTakashi Iwai dbri_reset(dbri);
25761bd9debfSTakashi Iwai
25771bd9debfSTakashi Iwai if (dbri->irq)
25781bd9debfSTakashi Iwai free_irq(dbri->irq, dbri);
25791bd9debfSTakashi Iwai
25801bd9debfSTakashi Iwai if (dbri->regs)
25812bd320f8SDavid S. Miller of_iounmap(&dbri->op->resource[0], dbri->regs, dbri->regs_size);
25821bd9debfSTakashi Iwai
25831bd9debfSTakashi Iwai if (dbri->dma)
25842bd320f8SDavid S. Miller dma_free_coherent(&dbri->op->dev,
25857a715f46SDavid S. Miller sizeof(struct dbri_dma),
25861bd9debfSTakashi Iwai (void *)dbri->dma, dbri->dma_dvma);
25871bd9debfSTakashi Iwai }
25881bd9debfSTakashi Iwai
dbri_probe(struct platform_device * op)258932e02a7bSBill Pemberton static int dbri_probe(struct platform_device *op)
25901bd9debfSTakashi Iwai {
2591475675d6STakashi Iwai struct snd_dbri *dbri;
25921bd9debfSTakashi Iwai struct resource *rp;
2593475675d6STakashi Iwai struct snd_card *card;
2594808709d7SJason Wang static int dev;
25952bd320f8SDavid S. Miller int irq;
25961bd9debfSTakashi Iwai int err;
25971bd9debfSTakashi Iwai
25981bd9debfSTakashi Iwai if (dev >= SNDRV_CARDS)
25991bd9debfSTakashi Iwai return -ENODEV;
26001bd9debfSTakashi Iwai if (!enable[dev]) {
26011bd9debfSTakashi Iwai dev++;
26021bd9debfSTakashi Iwai return -ENOENT;
26031bd9debfSTakashi Iwai }
26041bd9debfSTakashi Iwai
26051636f8acSGrant Likely irq = op->archdata.irqs[0];
2606afeacfd5SKrzysztof Helt if (irq <= 0) {
2607afeacfd5SKrzysztof Helt printk(KERN_ERR "DBRI-%d: No IRQ.\n", dev);
26084338829eSMartin Habets return -ENODEV;
26094338829eSMartin Habets }
26101bd9debfSTakashi Iwai
2611a2fefc35STakashi Iwai err = snd_card_new(&op->dev, index[dev], id[dev], THIS_MODULE,
2612bd7dd77cSTakashi Iwai sizeof(struct snd_dbri), &card);
2613bd7dd77cSTakashi Iwai if (err < 0)
2614bd7dd77cSTakashi Iwai return err;
26151bd9debfSTakashi Iwai
26161bd9debfSTakashi Iwai strcpy(card->driver, "DBRI");
26171bd9debfSTakashi Iwai strcpy(card->shortname, "Sun DBRI");
26182bd320f8SDavid S. Miller rp = &op->resource[0];
26195863aa65SAndrew Morton sprintf(card->longname, "%s at 0x%02lx:0x%016Lx, irq %d",
26201bd9debfSTakashi Iwai card->shortname,
2621afeacfd5SKrzysztof Helt rp->flags & 0xffL, (unsigned long long)rp->start, irq);
26221bd9debfSTakashi Iwai
26232bd320f8SDavid S. Miller err = snd_dbri_create(card, op, irq, dev);
2624afeacfd5SKrzysztof Helt if (err < 0) {
26251bd9debfSTakashi Iwai snd_card_free(card);
26261bd9debfSTakashi Iwai return err;
26271bd9debfSTakashi Iwai }
26281bd9debfSTakashi Iwai
2629475675d6STakashi Iwai dbri = card->private_data;
2630afeacfd5SKrzysztof Helt err = snd_dbri_pcm(card);
2631cf68d212SKrzysztof Helt if (err < 0)
263216dab54bSTakashi Iwai goto _err;
26331bd9debfSTakashi Iwai
2634afeacfd5SKrzysztof Helt err = snd_dbri_mixer(card);
2635cf68d212SKrzysztof Helt if (err < 0)
263616dab54bSTakashi Iwai goto _err;
26371bd9debfSTakashi Iwai
26381bd9debfSTakashi Iwai /* /proc file handling */
2639afeacfd5SKrzysztof Helt snd_dbri_proc(card);
26402bd320f8SDavid S. Miller dev_set_drvdata(&op->dev, card);
26411bd9debfSTakashi Iwai
2642098ccbc5SKrzysztof Helt err = snd_card_register(card);
2643098ccbc5SKrzysztof Helt if (err < 0)
264416dab54bSTakashi Iwai goto _err;
26451bd9debfSTakashi Iwai
26461bd9debfSTakashi Iwai printk(KERN_INFO "audio%d at %p (irq %d) is DBRI(%c)+CS4215(%d)\n",
26471bd9debfSTakashi Iwai dev, dbri->regs,
264861c7a080SGrant Likely dbri->irq, op->dev.of_node->name[9], dbri->mm.version);
26491bd9debfSTakashi Iwai dev++;
26501bd9debfSTakashi Iwai
26511bd9debfSTakashi Iwai return 0;
265216dab54bSTakashi Iwai
265316dab54bSTakashi Iwai _err:
265416dab54bSTakashi Iwai snd_dbri_free(dbri);
265516dab54bSTakashi Iwai snd_card_free(card);
265616dab54bSTakashi Iwai return err;
26571bd9debfSTakashi Iwai }
26581bd9debfSTakashi Iwai
dbri_remove(struct platform_device * op)26599fa6137dSUwe Kleine-König static void dbri_remove(struct platform_device *op)
2660afeacfd5SKrzysztof Helt {
26612bd320f8SDavid S. Miller struct snd_card *card = dev_get_drvdata(&op->dev);
2662afeacfd5SKrzysztof Helt
2663afeacfd5SKrzysztof Helt snd_dbri_free(card->private_data);
2664afeacfd5SKrzysztof Helt snd_card_free(card);
2665afeacfd5SKrzysztof Helt }
2666afeacfd5SKrzysztof Helt
2667fd098316SDavid S. Miller static const struct of_device_id dbri_match[] = {
2668afeacfd5SKrzysztof Helt {
2669afeacfd5SKrzysztof Helt .name = "SUNW,DBRIe",
2670afeacfd5SKrzysztof Helt },
2671afeacfd5SKrzysztof Helt {
2672afeacfd5SKrzysztof Helt .name = "SUNW,DBRIf",
2673afeacfd5SKrzysztof Helt },
2674afeacfd5SKrzysztof Helt {},
2675afeacfd5SKrzysztof Helt };
2676afeacfd5SKrzysztof Helt
2677afeacfd5SKrzysztof Helt MODULE_DEVICE_TABLE(of, dbri_match);
2678afeacfd5SKrzysztof Helt
2679f07eb223SGrant Likely static struct platform_driver dbri_sbus_driver = {
26804018294bSGrant Likely .driver = {
2681afeacfd5SKrzysztof Helt .name = "dbri",
26824018294bSGrant Likely .of_match_table = dbri_match,
26834018294bSGrant Likely },
2684afeacfd5SKrzysztof Helt .probe = dbri_probe,
26859fa6137dSUwe Kleine-König .remove_new = dbri_remove,
2686afeacfd5SKrzysztof Helt };
2687afeacfd5SKrzysztof Helt
2688a09452eeSAxel Lin module_platform_driver(dbri_sbus_driver);
2689