2114 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Driver for CS4231 sound chips found on Sparcs.4 * Copyright (C) 2002, 2008 David S. Miller <davem@davemloft.net>5 *6 * Based entirely upon drivers/sbus/audio/cs4231.c which is:7 * Copyright (C) 1996, 1997, 1998 Derrick J Brashear (shadow@andrew.cmu.edu)8 * and also sound/isa/cs423x/cs4231_lib.c which is:9 * Copyright (c) by Jaroslav Kysela <perex@perex.cz>10 */11 12#include <linux/module.h>13#include <linux/kernel.h>14#include <linux/delay.h>15#include <linux/init.h>16#include <linux/interrupt.h>17#include <linux/moduleparam.h>18#include <linux/irq.h>19#include <linux/io.h>20#include <linux/of.h>21#include <linux/platform_device.h>22 23#include <sound/core.h>24#include <sound/pcm.h>25#include <sound/info.h>26#include <sound/control.h>27#include <sound/timer.h>28#include <sound/initval.h>29#include <sound/pcm_params.h>30 31#ifdef CONFIG_SBUS32#define SBUS_SUPPORT33#endif34 35#if defined(CONFIG_PCI) && defined(CONFIG_SPARC64)36#define EBUS_SUPPORT37#include <linux/pci.h>38#include <asm/ebus_dma.h>39#endif40 41static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */42static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */43/* Enable this card */44static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;45 46module_param_array(index, int, NULL, 0444);47MODULE_PARM_DESC(index, "Index value for Sun CS4231 soundcard.");48module_param_array(id, charp, NULL, 0444);49MODULE_PARM_DESC(id, "ID string for Sun CS4231 soundcard.");50module_param_array(enable, bool, NULL, 0444);51MODULE_PARM_DESC(enable, "Enable Sun CS4231 soundcard.");52MODULE_AUTHOR("Jaroslav Kysela, Derrick J. Brashear and David S. Miller");53MODULE_DESCRIPTION("Sun CS4231");54MODULE_LICENSE("GPL");55 56#ifdef SBUS_SUPPORT57struct sbus_dma_info {58 spinlock_t lock; /* DMA access lock */59 int dir;60 void __iomem *regs;61};62#endif63 64struct snd_cs4231;65struct cs4231_dma_control {66 void (*prepare)(struct cs4231_dma_control *dma_cont,67 int dir);68 void (*enable)(struct cs4231_dma_control *dma_cont, int on);69 int (*request)(struct cs4231_dma_control *dma_cont,70 dma_addr_t bus_addr, size_t len);71 unsigned int (*address)(struct cs4231_dma_control *dma_cont);72#ifdef EBUS_SUPPORT73 struct ebus_dma_info ebus_info;74#endif75#ifdef SBUS_SUPPORT76 struct sbus_dma_info sbus_info;77#endif78};79 80struct snd_cs4231 {81 spinlock_t lock; /* registers access lock */82 void __iomem *port;83 84 struct cs4231_dma_control p_dma;85 struct cs4231_dma_control c_dma;86 87 u32 flags;88#define CS4231_FLAG_EBUS 0x0000000189#define CS4231_FLAG_PLAYBACK 0x0000000290#define CS4231_FLAG_CAPTURE 0x0000000491 92 struct snd_card *card;93 struct snd_pcm *pcm;94 struct snd_pcm_substream *playback_substream;95 unsigned int p_periods_sent;96 struct snd_pcm_substream *capture_substream;97 unsigned int c_periods_sent;98 struct snd_timer *timer;99 100 unsigned short mode;101#define CS4231_MODE_NONE 0x0000102#define CS4231_MODE_PLAY 0x0001103#define CS4231_MODE_RECORD 0x0002104#define CS4231_MODE_TIMER 0x0004105#define CS4231_MODE_OPEN (CS4231_MODE_PLAY | CS4231_MODE_RECORD | \106 CS4231_MODE_TIMER)107 108 unsigned char image[32]; /* registers image */109 int mce_bit;110 int calibrate_mute;111 struct mutex mce_mutex; /* mutex for mce register */112 struct mutex open_mutex; /* mutex for ALSA open/close */113 114 struct platform_device *op;115 unsigned int irq[2];116 unsigned int regs_size;117 struct snd_cs4231 *next;118};119 120/* Eventually we can use sound/isa/cs423x/cs4231_lib.c directly, but for121 * now.... -DaveM122 */123 124/* IO ports */125#include <sound/cs4231-regs.h>126 127/* XXX offsets are different than PC ISA chips... */128#define CS4231U(chip, x) ((chip)->port + ((c_d_c_CS4231##x) << 2))129 130/* SBUS DMA register defines. */131 132#define APCCSR 0x10UL /* APC DMA CSR */133#define APCCVA 0x20UL /* APC Capture DMA Address */134#define APCCC 0x24UL /* APC Capture Count */135#define APCCNVA 0x28UL /* APC Capture DMA Next Address */136#define APCCNC 0x2cUL /* APC Capture Next Count */137#define APCPVA 0x30UL /* APC Play DMA Address */138#define APCPC 0x34UL /* APC Play Count */139#define APCPNVA 0x38UL /* APC Play DMA Next Address */140#define APCPNC 0x3cUL /* APC Play Next Count */141 142/* Defines for SBUS DMA-routines */143 144#define APCVA 0x0UL /* APC DMA Address */145#define APCC 0x4UL /* APC Count */146#define APCNVA 0x8UL /* APC DMA Next Address */147#define APCNC 0xcUL /* APC Next Count */148#define APC_PLAY 0x30UL /* Play registers start at 0x30 */149#define APC_RECORD 0x20UL /* Record registers start at 0x20 */150 151/* APCCSR bits */152 153#define APC_INT_PENDING 0x800000 /* Interrupt Pending */154#define APC_PLAY_INT 0x400000 /* Playback interrupt */155#define APC_CAPT_INT 0x200000 /* Capture interrupt */156#define APC_GENL_INT 0x100000 /* General interrupt */157#define APC_XINT_ENA 0x80000 /* General ext int. enable */158#define APC_XINT_PLAY 0x40000 /* Playback ext intr */159#define APC_XINT_CAPT 0x20000 /* Capture ext intr */160#define APC_XINT_GENL 0x10000 /* Error ext intr */161#define APC_XINT_EMPT 0x8000 /* Pipe empty interrupt (0 write to pva) */162#define APC_XINT_PEMP 0x4000 /* Play pipe empty (pva and pnva not set) */163#define APC_XINT_PNVA 0x2000 /* Playback NVA dirty */164#define APC_XINT_PENA 0x1000 /* play pipe empty Int enable */165#define APC_XINT_COVF 0x800 /* Cap data dropped on floor */166#define APC_XINT_CNVA 0x400 /* Capture NVA dirty */167#define APC_XINT_CEMP 0x200 /* Capture pipe empty (cva and cnva not set) */168#define APC_XINT_CENA 0x100 /* Cap. pipe empty int enable */169#define APC_PPAUSE 0x80 /* Pause the play DMA */170#define APC_CPAUSE 0x40 /* Pause the capture DMA */171#define APC_CDC_RESET 0x20 /* CODEC RESET */172#define APC_PDMA_READY 0x08 /* Play DMA Go */173#define APC_CDMA_READY 0x04 /* Capture DMA Go */174#define APC_CHIP_RESET 0x01 /* Reset the chip */175 176/* EBUS DMA register offsets */177 178#define EBDMA_CSR 0x00UL /* Control/Status */179#define EBDMA_ADDR 0x04UL /* DMA Address */180#define EBDMA_COUNT 0x08UL /* DMA Count */181 182/*183 * Some variables184 */185 186static const unsigned char freq_bits[14] = {187 /* 5510 */ 0x00 | CS4231_XTAL2,188 /* 6620 */ 0x0E | CS4231_XTAL2,189 /* 8000 */ 0x00 | CS4231_XTAL1,190 /* 9600 */ 0x0E | CS4231_XTAL1,191 /* 11025 */ 0x02 | CS4231_XTAL2,192 /* 16000 */ 0x02 | CS4231_XTAL1,193 /* 18900 */ 0x04 | CS4231_XTAL2,194 /* 22050 */ 0x06 | CS4231_XTAL2,195 /* 27042 */ 0x04 | CS4231_XTAL1,196 /* 32000 */ 0x06 | CS4231_XTAL1,197 /* 33075 */ 0x0C | CS4231_XTAL2,198 /* 37800 */ 0x08 | CS4231_XTAL2,199 /* 44100 */ 0x0A | CS4231_XTAL2,200 /* 48000 */ 0x0C | CS4231_XTAL1201};202 203static const unsigned int rates[14] = {204 5510, 6620, 8000, 9600, 11025, 16000, 18900, 22050,205 27042, 32000, 33075, 37800, 44100, 48000206};207 208static const struct snd_pcm_hw_constraint_list hw_constraints_rates = {209 .count = ARRAY_SIZE(rates),210 .list = rates,211};212 213static int snd_cs4231_xrate(struct snd_pcm_runtime *runtime)214{215 return snd_pcm_hw_constraint_list(runtime, 0,216 SNDRV_PCM_HW_PARAM_RATE,217 &hw_constraints_rates);218}219 220static const unsigned char snd_cs4231_original_image[32] =221{222 0x00, /* 00/00 - lic */223 0x00, /* 01/01 - ric */224 0x9f, /* 02/02 - la1ic */225 0x9f, /* 03/03 - ra1ic */226 0x9f, /* 04/04 - la2ic */227 0x9f, /* 05/05 - ra2ic */228 0xbf, /* 06/06 - loc */229 0xbf, /* 07/07 - roc */230 0x20, /* 08/08 - pdfr */231 CS4231_AUTOCALIB, /* 09/09 - ic */232 0x00, /* 0a/10 - pc */233 0x00, /* 0b/11 - ti */234 CS4231_MODE2, /* 0c/12 - mi */235 0x00, /* 0d/13 - lbc */236 0x00, /* 0e/14 - pbru */237 0x00, /* 0f/15 - pbrl */238 0x80, /* 10/16 - afei */239 0x01, /* 11/17 - afeii */240 0x9f, /* 12/18 - llic */241 0x9f, /* 13/19 - rlic */242 0x00, /* 14/20 - tlb */243 0x00, /* 15/21 - thb */244 0x00, /* 16/22 - la3mic/reserved */245 0x00, /* 17/23 - ra3mic/reserved */246 0x00, /* 18/24 - afs */247 0x00, /* 19/25 - lamoc/version */248 0x00, /* 1a/26 - mioc */249 0x00, /* 1b/27 - ramoc/reserved */250 0x20, /* 1c/28 - cdfr */251 0x00, /* 1d/29 - res4 */252 0x00, /* 1e/30 - cbru */253 0x00, /* 1f/31 - cbrl */254};255 256static u8 __cs4231_readb(struct snd_cs4231 *cp, void __iomem *reg_addr)257{258 if (cp->flags & CS4231_FLAG_EBUS)259 return readb(reg_addr);260 else261 return sbus_readb(reg_addr);262}263 264static void __cs4231_writeb(struct snd_cs4231 *cp, u8 val,265 void __iomem *reg_addr)266{267 if (cp->flags & CS4231_FLAG_EBUS)268 return writeb(val, reg_addr);269 else270 return sbus_writeb(val, reg_addr);271}272 273/*274 * Basic I/O functions275 */276 277static void snd_cs4231_ready(struct snd_cs4231 *chip)278{279 int timeout;280 281 for (timeout = 250; timeout > 0; timeout--) {282 int val = __cs4231_readb(chip, CS4231U(chip, REGSEL));283 if ((val & CS4231_INIT) == 0)284 break;285 udelay(100);286 }287}288 289static void snd_cs4231_dout(struct snd_cs4231 *chip, unsigned char reg,290 unsigned char value)291{292 snd_cs4231_ready(chip);293#ifdef CONFIG_SND_DEBUG294 if (__cs4231_readb(chip, CS4231U(chip, REGSEL)) & CS4231_INIT)295 dev_dbg(chip->card->dev,296 "out: auto calibration time out - reg = 0x%x, value = 0x%x\n",297 reg, value);298#endif299 __cs4231_writeb(chip, chip->mce_bit | reg, CS4231U(chip, REGSEL));300 wmb();301 __cs4231_writeb(chip, value, CS4231U(chip, REG));302 mb();303}304 305static inline void snd_cs4231_outm(struct snd_cs4231 *chip, unsigned char reg,306 unsigned char mask, unsigned char value)307{308 unsigned char tmp = (chip->image[reg] & mask) | value;309 310 chip->image[reg] = tmp;311 if (!chip->calibrate_mute)312 snd_cs4231_dout(chip, reg, tmp);313}314 315static void snd_cs4231_out(struct snd_cs4231 *chip, unsigned char reg,316 unsigned char value)317{318 snd_cs4231_dout(chip, reg, value);319 chip->image[reg] = value;320 mb();321}322 323static unsigned char snd_cs4231_in(struct snd_cs4231 *chip, unsigned char reg)324{325 snd_cs4231_ready(chip);326#ifdef CONFIG_SND_DEBUG327 if (__cs4231_readb(chip, CS4231U(chip, REGSEL)) & CS4231_INIT)328 dev_dbg(chip->card->dev,329 "in: auto calibration time out - reg = 0x%x\n",330 reg);331#endif332 __cs4231_writeb(chip, chip->mce_bit | reg, CS4231U(chip, REGSEL));333 mb();334 return __cs4231_readb(chip, CS4231U(chip, REG));335}336 337/*338 * CS4231 detection / MCE routines339 */340 341static void snd_cs4231_busy_wait(struct snd_cs4231 *chip)342{343 int timeout;344 345 /* looks like this sequence is proper for CS4231A chip (GUS MAX) */346 for (timeout = 5; timeout > 0; timeout--)347 __cs4231_readb(chip, CS4231U(chip, REGSEL));348 349 /* end of cleanup sequence */350 for (timeout = 500; timeout > 0; timeout--) {351 int val = __cs4231_readb(chip, CS4231U(chip, REGSEL));352 if ((val & CS4231_INIT) == 0)353 break;354 msleep(1);355 }356}357 358static void snd_cs4231_mce_up(struct snd_cs4231 *chip)359{360 unsigned long flags;361 int timeout;362 363 spin_lock_irqsave(&chip->lock, flags);364 snd_cs4231_ready(chip);365#ifdef CONFIG_SND_DEBUG366 if (__cs4231_readb(chip, CS4231U(chip, REGSEL)) & CS4231_INIT)367 dev_dbg(chip->card->dev,368 "mce_up - auto calibration time out (0)\n");369#endif370 chip->mce_bit |= CS4231_MCE;371 timeout = __cs4231_readb(chip, CS4231U(chip, REGSEL));372 if (timeout == 0x80)373 dev_dbg(chip->card->dev,374 "mce_up [%p]: serious init problem - codec still busy\n",375 chip->port);376 if (!(timeout & CS4231_MCE))377 __cs4231_writeb(chip, chip->mce_bit | (timeout & 0x1f),378 CS4231U(chip, REGSEL));379 spin_unlock_irqrestore(&chip->lock, flags);380}381 382static void snd_cs4231_mce_down(struct snd_cs4231 *chip)383{384 unsigned long flags, timeout;385 int reg;386 387 snd_cs4231_busy_wait(chip);388 spin_lock_irqsave(&chip->lock, flags);389#ifdef CONFIG_SND_DEBUG390 if (__cs4231_readb(chip, CS4231U(chip, REGSEL)) & CS4231_INIT)391 dev_dbg(chip->card->dev,392 "mce_down [%p] - auto calibration time out (0)\n",393 CS4231U(chip, REGSEL));394#endif395 chip->mce_bit &= ~CS4231_MCE;396 reg = __cs4231_readb(chip, CS4231U(chip, REGSEL));397 __cs4231_writeb(chip, chip->mce_bit | (reg & 0x1f),398 CS4231U(chip, REGSEL));399 if (reg == 0x80)400 dev_dbg(chip->card->dev,401 "mce_down [%p]: serious init problem - codec still busy\n",402 chip->port);403 if ((reg & CS4231_MCE) == 0) {404 spin_unlock_irqrestore(&chip->lock, flags);405 return;406 }407 408 /*409 * Wait for auto-calibration (AC) process to finish, i.e. ACI to go low.410 */411 timeout = jiffies + msecs_to_jiffies(250);412 do {413 spin_unlock_irqrestore(&chip->lock, flags);414 msleep(1);415 spin_lock_irqsave(&chip->lock, flags);416 reg = snd_cs4231_in(chip, CS4231_TEST_INIT);417 reg &= CS4231_CALIB_IN_PROGRESS;418 } while (reg && time_before(jiffies, timeout));419 spin_unlock_irqrestore(&chip->lock, flags);420 421 if (reg)422 dev_err(chip->card->dev,423 "mce_down - auto calibration time out (2)\n");424}425 426static void snd_cs4231_advance_dma(struct cs4231_dma_control *dma_cont,427 struct snd_pcm_substream *substream,428 unsigned int *periods_sent)429{430 struct snd_pcm_runtime *runtime = substream->runtime;431 432 while (1) {433 unsigned int period_size = snd_pcm_lib_period_bytes(substream);434 unsigned int offset = period_size * (*periods_sent);435 436 if (WARN_ON(period_size >= (1 << 24)))437 return;438 439 if (dma_cont->request(dma_cont,440 runtime->dma_addr + offset, period_size))441 return;442 (*periods_sent) = ((*periods_sent) + 1) % runtime->periods;443 }444}445 446static void cs4231_dma_trigger(struct snd_pcm_substream *substream,447 unsigned int what, int on)448{449 struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);450 struct cs4231_dma_control *dma_cont;451 452 if (what & CS4231_PLAYBACK_ENABLE) {453 dma_cont = &chip->p_dma;454 if (on) {455 dma_cont->prepare(dma_cont, 0);456 dma_cont->enable(dma_cont, 1);457 snd_cs4231_advance_dma(dma_cont,458 chip->playback_substream,459 &chip->p_periods_sent);460 } else {461 dma_cont->enable(dma_cont, 0);462 }463 }464 if (what & CS4231_RECORD_ENABLE) {465 dma_cont = &chip->c_dma;466 if (on) {467 dma_cont->prepare(dma_cont, 1);468 dma_cont->enable(dma_cont, 1);469 snd_cs4231_advance_dma(dma_cont,470 chip->capture_substream,471 &chip->c_periods_sent);472 } else {473 dma_cont->enable(dma_cont, 0);474 }475 }476}477 478static int snd_cs4231_trigger(struct snd_pcm_substream *substream, int cmd)479{480 struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);481 int result = 0;482 483 switch (cmd) {484 case SNDRV_PCM_TRIGGER_START:485 case SNDRV_PCM_TRIGGER_STOP:486 {487 unsigned int what = 0;488 struct snd_pcm_substream *s;489 unsigned long flags;490 491 snd_pcm_group_for_each_entry(s, substream) {492 if (s == chip->playback_substream) {493 what |= CS4231_PLAYBACK_ENABLE;494 snd_pcm_trigger_done(s, substream);495 } else if (s == chip->capture_substream) {496 what |= CS4231_RECORD_ENABLE;497 snd_pcm_trigger_done(s, substream);498 }499 }500 501 spin_lock_irqsave(&chip->lock, flags);502 if (cmd == SNDRV_PCM_TRIGGER_START) {503 cs4231_dma_trigger(substream, what, 1);504 chip->image[CS4231_IFACE_CTRL] |= what;505 } else {506 cs4231_dma_trigger(substream, what, 0);507 chip->image[CS4231_IFACE_CTRL] &= ~what;508 }509 snd_cs4231_out(chip, CS4231_IFACE_CTRL,510 chip->image[CS4231_IFACE_CTRL]);511 spin_unlock_irqrestore(&chip->lock, flags);512 break;513 }514 default:515 result = -EINVAL;516 break;517 }518 519 return result;520}521 522/*523 * CODEC I/O524 */525 526static unsigned char snd_cs4231_get_rate(unsigned int rate)527{528 int i;529 530 for (i = 0; i < 14; i++)531 if (rate == rates[i])532 return freq_bits[i];533 534 return freq_bits[13];535}536 537static unsigned char snd_cs4231_get_format(struct snd_cs4231 *chip, int format,538 int channels)539{540 unsigned char rformat;541 542 rformat = CS4231_LINEAR_8;543 switch (format) {544 case SNDRV_PCM_FORMAT_MU_LAW:545 rformat = CS4231_ULAW_8;546 break;547 case SNDRV_PCM_FORMAT_A_LAW:548 rformat = CS4231_ALAW_8;549 break;550 case SNDRV_PCM_FORMAT_S16_LE:551 rformat = CS4231_LINEAR_16;552 break;553 case SNDRV_PCM_FORMAT_S16_BE:554 rformat = CS4231_LINEAR_16_BIG;555 break;556 case SNDRV_PCM_FORMAT_IMA_ADPCM:557 rformat = CS4231_ADPCM_16;558 break;559 }560 if (channels > 1)561 rformat |= CS4231_STEREO;562 return rformat;563}564 565static void snd_cs4231_calibrate_mute(struct snd_cs4231 *chip, int mute)566{567 unsigned long flags;568 569 mute = mute ? 1 : 0;570 spin_lock_irqsave(&chip->lock, flags);571 if (chip->calibrate_mute == mute) {572 spin_unlock_irqrestore(&chip->lock, flags);573 return;574 }575 if (!mute) {576 snd_cs4231_dout(chip, CS4231_LEFT_INPUT,577 chip->image[CS4231_LEFT_INPUT]);578 snd_cs4231_dout(chip, CS4231_RIGHT_INPUT,579 chip->image[CS4231_RIGHT_INPUT]);580 snd_cs4231_dout(chip, CS4231_LOOPBACK,581 chip->image[CS4231_LOOPBACK]);582 }583 snd_cs4231_dout(chip, CS4231_AUX1_LEFT_INPUT,584 mute ? 0x80 : chip->image[CS4231_AUX1_LEFT_INPUT]);585 snd_cs4231_dout(chip, CS4231_AUX1_RIGHT_INPUT,586 mute ? 0x80 : chip->image[CS4231_AUX1_RIGHT_INPUT]);587 snd_cs4231_dout(chip, CS4231_AUX2_LEFT_INPUT,588 mute ? 0x80 : chip->image[CS4231_AUX2_LEFT_INPUT]);589 snd_cs4231_dout(chip, CS4231_AUX2_RIGHT_INPUT,590 mute ? 0x80 : chip->image[CS4231_AUX2_RIGHT_INPUT]);591 snd_cs4231_dout(chip, CS4231_LEFT_OUTPUT,592 mute ? 0x80 : chip->image[CS4231_LEFT_OUTPUT]);593 snd_cs4231_dout(chip, CS4231_RIGHT_OUTPUT,594 mute ? 0x80 : chip->image[CS4231_RIGHT_OUTPUT]);595 snd_cs4231_dout(chip, CS4231_LEFT_LINE_IN,596 mute ? 0x80 : chip->image[CS4231_LEFT_LINE_IN]);597 snd_cs4231_dout(chip, CS4231_RIGHT_LINE_IN,598 mute ? 0x80 : chip->image[CS4231_RIGHT_LINE_IN]);599 snd_cs4231_dout(chip, CS4231_MONO_CTRL,600 mute ? 0xc0 : chip->image[CS4231_MONO_CTRL]);601 chip->calibrate_mute = mute;602 spin_unlock_irqrestore(&chip->lock, flags);603}604 605static void snd_cs4231_playback_format(struct snd_cs4231 *chip,606 struct snd_pcm_hw_params *params,607 unsigned char pdfr)608{609 unsigned long flags;610 611 mutex_lock(&chip->mce_mutex);612 snd_cs4231_calibrate_mute(chip, 1);613 614 snd_cs4231_mce_up(chip);615 616 spin_lock_irqsave(&chip->lock, flags);617 snd_cs4231_out(chip, CS4231_PLAYBK_FORMAT,618 (chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE) ?619 (pdfr & 0xf0) | (chip->image[CS4231_REC_FORMAT] & 0x0f) :620 pdfr);621 spin_unlock_irqrestore(&chip->lock, flags);622 623 snd_cs4231_mce_down(chip);624 625 snd_cs4231_calibrate_mute(chip, 0);626 mutex_unlock(&chip->mce_mutex);627}628 629static void snd_cs4231_capture_format(struct snd_cs4231 *chip,630 struct snd_pcm_hw_params *params,631 unsigned char cdfr)632{633 unsigned long flags;634 635 mutex_lock(&chip->mce_mutex);636 snd_cs4231_calibrate_mute(chip, 1);637 638 snd_cs4231_mce_up(chip);639 640 spin_lock_irqsave(&chip->lock, flags);641 if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE)) {642 snd_cs4231_out(chip, CS4231_PLAYBK_FORMAT,643 ((chip->image[CS4231_PLAYBK_FORMAT]) & 0xf0) |644 (cdfr & 0x0f));645 spin_unlock_irqrestore(&chip->lock, flags);646 snd_cs4231_mce_down(chip);647 snd_cs4231_mce_up(chip);648 spin_lock_irqsave(&chip->lock, flags);649 }650 snd_cs4231_out(chip, CS4231_REC_FORMAT, cdfr);651 spin_unlock_irqrestore(&chip->lock, flags);652 653 snd_cs4231_mce_down(chip);654 655 snd_cs4231_calibrate_mute(chip, 0);656 mutex_unlock(&chip->mce_mutex);657}658 659/*660 * Timer interface661 */662 663static unsigned long snd_cs4231_timer_resolution(struct snd_timer *timer)664{665 struct snd_cs4231 *chip = snd_timer_chip(timer);666 667 return chip->image[CS4231_PLAYBK_FORMAT] & 1 ? 9969 : 9920;668}669 670static int snd_cs4231_timer_start(struct snd_timer *timer)671{672 unsigned long flags;673 unsigned int ticks;674 struct snd_cs4231 *chip = snd_timer_chip(timer);675 676 spin_lock_irqsave(&chip->lock, flags);677 ticks = timer->sticks;678 if ((chip->image[CS4231_ALT_FEATURE_1] & CS4231_TIMER_ENABLE) == 0 ||679 (unsigned char)(ticks >> 8) != chip->image[CS4231_TIMER_HIGH] ||680 (unsigned char)ticks != chip->image[CS4231_TIMER_LOW]) {681 snd_cs4231_out(chip, CS4231_TIMER_HIGH,682 chip->image[CS4231_TIMER_HIGH] =683 (unsigned char) (ticks >> 8));684 snd_cs4231_out(chip, CS4231_TIMER_LOW,685 chip->image[CS4231_TIMER_LOW] =686 (unsigned char) ticks);687 snd_cs4231_out(chip, CS4231_ALT_FEATURE_1,688 chip->image[CS4231_ALT_FEATURE_1] |689 CS4231_TIMER_ENABLE);690 }691 spin_unlock_irqrestore(&chip->lock, flags);692 693 return 0;694}695 696static int snd_cs4231_timer_stop(struct snd_timer *timer)697{698 unsigned long flags;699 struct snd_cs4231 *chip = snd_timer_chip(timer);700 701 spin_lock_irqsave(&chip->lock, flags);702 chip->image[CS4231_ALT_FEATURE_1] &= ~CS4231_TIMER_ENABLE;703 snd_cs4231_out(chip, CS4231_ALT_FEATURE_1,704 chip->image[CS4231_ALT_FEATURE_1]);705 spin_unlock_irqrestore(&chip->lock, flags);706 707 return 0;708}709 710static void snd_cs4231_init(struct snd_cs4231 *chip)711{712 unsigned long flags;713 714 snd_cs4231_mce_down(chip);715 716#ifdef SNDRV_DEBUG_MCE717 pr_debug("init: (1)\n");718#endif719 snd_cs4231_mce_up(chip);720 spin_lock_irqsave(&chip->lock, flags);721 chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE |722 CS4231_PLAYBACK_PIO |723 CS4231_RECORD_ENABLE |724 CS4231_RECORD_PIO |725 CS4231_CALIB_MODE);726 chip->image[CS4231_IFACE_CTRL] |= CS4231_AUTOCALIB;727 snd_cs4231_out(chip, CS4231_IFACE_CTRL, chip->image[CS4231_IFACE_CTRL]);728 spin_unlock_irqrestore(&chip->lock, flags);729 snd_cs4231_mce_down(chip);730 731#ifdef SNDRV_DEBUG_MCE732 pr_debug("init: (2)\n");733#endif734 735 snd_cs4231_mce_up(chip);736 spin_lock_irqsave(&chip->lock, flags);737 snd_cs4231_out(chip, CS4231_ALT_FEATURE_1,738 chip->image[CS4231_ALT_FEATURE_1]);739 spin_unlock_irqrestore(&chip->lock, flags);740 snd_cs4231_mce_down(chip);741 742#ifdef SNDRV_DEBUG_MCE743 pr_debug("init: (3) - afei = 0x%x\n",744 chip->image[CS4231_ALT_FEATURE_1]);745#endif746 747 spin_lock_irqsave(&chip->lock, flags);748 snd_cs4231_out(chip, CS4231_ALT_FEATURE_2,749 chip->image[CS4231_ALT_FEATURE_2]);750 spin_unlock_irqrestore(&chip->lock, flags);751 752 snd_cs4231_mce_up(chip);753 spin_lock_irqsave(&chip->lock, flags);754 snd_cs4231_out(chip, CS4231_PLAYBK_FORMAT,755 chip->image[CS4231_PLAYBK_FORMAT]);756 spin_unlock_irqrestore(&chip->lock, flags);757 snd_cs4231_mce_down(chip);758 759#ifdef SNDRV_DEBUG_MCE760 pr_debug("init: (4)\n");761#endif762 763 snd_cs4231_mce_up(chip);764 spin_lock_irqsave(&chip->lock, flags);765 snd_cs4231_out(chip, CS4231_REC_FORMAT, chip->image[CS4231_REC_FORMAT]);766 spin_unlock_irqrestore(&chip->lock, flags);767 snd_cs4231_mce_down(chip);768 769#ifdef SNDRV_DEBUG_MCE770 pr_debug("init: (5)\n");771#endif772}773 774static int snd_cs4231_open(struct snd_cs4231 *chip, unsigned int mode)775{776 unsigned long flags;777 778 mutex_lock(&chip->open_mutex);779 if ((chip->mode & mode)) {780 mutex_unlock(&chip->open_mutex);781 return -EAGAIN;782 }783 if (chip->mode & CS4231_MODE_OPEN) {784 chip->mode |= mode;785 mutex_unlock(&chip->open_mutex);786 return 0;787 }788 /* ok. now enable and ack CODEC IRQ */789 spin_lock_irqsave(&chip->lock, flags);790 snd_cs4231_out(chip, CS4231_IRQ_STATUS, CS4231_PLAYBACK_IRQ |791 CS4231_RECORD_IRQ |792 CS4231_TIMER_IRQ);793 snd_cs4231_out(chip, CS4231_IRQ_STATUS, 0);794 __cs4231_writeb(chip, 0, CS4231U(chip, STATUS)); /* clear IRQ */795 __cs4231_writeb(chip, 0, CS4231U(chip, STATUS)); /* clear IRQ */796 797 snd_cs4231_out(chip, CS4231_IRQ_STATUS, CS4231_PLAYBACK_IRQ |798 CS4231_RECORD_IRQ |799 CS4231_TIMER_IRQ);800 snd_cs4231_out(chip, CS4231_IRQ_STATUS, 0);801 802 spin_unlock_irqrestore(&chip->lock, flags);803 804 chip->mode = mode;805 mutex_unlock(&chip->open_mutex);806 return 0;807}808 809static void snd_cs4231_close(struct snd_cs4231 *chip, unsigned int mode)810{811 unsigned long flags;812 813 mutex_lock(&chip->open_mutex);814 chip->mode &= ~mode;815 if (chip->mode & CS4231_MODE_OPEN) {816 mutex_unlock(&chip->open_mutex);817 return;818 }819 snd_cs4231_calibrate_mute(chip, 1);820 821 /* disable IRQ */822 spin_lock_irqsave(&chip->lock, flags);823 snd_cs4231_out(chip, CS4231_IRQ_STATUS, 0);824 __cs4231_writeb(chip, 0, CS4231U(chip, STATUS)); /* clear IRQ */825 __cs4231_writeb(chip, 0, CS4231U(chip, STATUS)); /* clear IRQ */826 827 /* now disable record & playback */828 829 if (chip->image[CS4231_IFACE_CTRL] &830 (CS4231_PLAYBACK_ENABLE | CS4231_PLAYBACK_PIO |831 CS4231_RECORD_ENABLE | CS4231_RECORD_PIO)) {832 spin_unlock_irqrestore(&chip->lock, flags);833 snd_cs4231_mce_up(chip);834 spin_lock_irqsave(&chip->lock, flags);835 chip->image[CS4231_IFACE_CTRL] &=836 ~(CS4231_PLAYBACK_ENABLE | CS4231_PLAYBACK_PIO |837 CS4231_RECORD_ENABLE | CS4231_RECORD_PIO);838 snd_cs4231_out(chip, CS4231_IFACE_CTRL,839 chip->image[CS4231_IFACE_CTRL]);840 spin_unlock_irqrestore(&chip->lock, flags);841 snd_cs4231_mce_down(chip);842 spin_lock_irqsave(&chip->lock, flags);843 }844 845 /* clear IRQ again */846 snd_cs4231_out(chip, CS4231_IRQ_STATUS, 0);847 __cs4231_writeb(chip, 0, CS4231U(chip, STATUS)); /* clear IRQ */848 __cs4231_writeb(chip, 0, CS4231U(chip, STATUS)); /* clear IRQ */849 spin_unlock_irqrestore(&chip->lock, flags);850 851 snd_cs4231_calibrate_mute(chip, 0);852 853 chip->mode = 0;854 mutex_unlock(&chip->open_mutex);855}856 857/*858 * timer open/close859 */860 861static int snd_cs4231_timer_open(struct snd_timer *timer)862{863 struct snd_cs4231 *chip = snd_timer_chip(timer);864 snd_cs4231_open(chip, CS4231_MODE_TIMER);865 return 0;866}867 868static int snd_cs4231_timer_close(struct snd_timer *timer)869{870 struct snd_cs4231 *chip = snd_timer_chip(timer);871 snd_cs4231_close(chip, CS4231_MODE_TIMER);872 return 0;873}874 875static const struct snd_timer_hardware snd_cs4231_timer_table = {876 .flags = SNDRV_TIMER_HW_AUTO,877 .resolution = 9945,878 .ticks = 65535,879 .open = snd_cs4231_timer_open,880 .close = snd_cs4231_timer_close,881 .c_resolution = snd_cs4231_timer_resolution,882 .start = snd_cs4231_timer_start,883 .stop = snd_cs4231_timer_stop,884};885 886/*887 * ok.. exported functions..888 */889 890static int snd_cs4231_playback_hw_params(struct snd_pcm_substream *substream,891 struct snd_pcm_hw_params *hw_params)892{893 struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);894 unsigned char new_pdfr;895 896 new_pdfr = snd_cs4231_get_format(chip, params_format(hw_params),897 params_channels(hw_params)) |898 snd_cs4231_get_rate(params_rate(hw_params));899 snd_cs4231_playback_format(chip, hw_params, new_pdfr);900 901 return 0;902}903 904static int snd_cs4231_playback_prepare(struct snd_pcm_substream *substream)905{906 struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);907 struct snd_pcm_runtime *runtime = substream->runtime;908 unsigned long flags;909 int ret = 0;910 911 spin_lock_irqsave(&chip->lock, flags);912 913 chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE |914 CS4231_PLAYBACK_PIO);915 916 if (WARN_ON(runtime->period_size > 0xffff + 1)) {917 ret = -EINVAL;918 goto out;919 }920 921 chip->p_periods_sent = 0;922 923out:924 spin_unlock_irqrestore(&chip->lock, flags);925 926 return ret;927}928 929static int snd_cs4231_capture_hw_params(struct snd_pcm_substream *substream,930 struct snd_pcm_hw_params *hw_params)931{932 struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);933 unsigned char new_cdfr;934 935 new_cdfr = snd_cs4231_get_format(chip, params_format(hw_params),936 params_channels(hw_params)) |937 snd_cs4231_get_rate(params_rate(hw_params));938 snd_cs4231_capture_format(chip, hw_params, new_cdfr);939 940 return 0;941}942 943static int snd_cs4231_capture_prepare(struct snd_pcm_substream *substream)944{945 struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);946 unsigned long flags;947 948 spin_lock_irqsave(&chip->lock, flags);949 chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_RECORD_ENABLE |950 CS4231_RECORD_PIO);951 952 953 chip->c_periods_sent = 0;954 spin_unlock_irqrestore(&chip->lock, flags);955 956 return 0;957}958 959static void snd_cs4231_overrange(struct snd_cs4231 *chip)960{961 unsigned long flags;962 unsigned char res;963 964 spin_lock_irqsave(&chip->lock, flags);965 res = snd_cs4231_in(chip, CS4231_TEST_INIT);966 spin_unlock_irqrestore(&chip->lock, flags);967 968 /* detect overrange only above 0dB; may be user selectable? */969 if (res & (0x08 | 0x02))970 chip->capture_substream->runtime->overrange++;971}972 973static void snd_cs4231_play_callback(struct snd_cs4231 *chip)974{975 if (chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE) {976 snd_pcm_period_elapsed(chip->playback_substream);977 snd_cs4231_advance_dma(&chip->p_dma, chip->playback_substream,978 &chip->p_periods_sent);979 }980}981 982static void snd_cs4231_capture_callback(struct snd_cs4231 *chip)983{984 if (chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE) {985 snd_pcm_period_elapsed(chip->capture_substream);986 snd_cs4231_advance_dma(&chip->c_dma, chip->capture_substream,987 &chip->c_periods_sent);988 }989}990 991static snd_pcm_uframes_t snd_cs4231_playback_pointer(992 struct snd_pcm_substream *substream)993{994 struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);995 struct cs4231_dma_control *dma_cont = &chip->p_dma;996 size_t ptr;997 998 if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE))999 return 0;1000 ptr = dma_cont->address(dma_cont);1001 if (ptr != 0)1002 ptr -= substream->runtime->dma_addr;1003 1004 return bytes_to_frames(substream->runtime, ptr);1005}1006 1007static snd_pcm_uframes_t snd_cs4231_capture_pointer(1008 struct snd_pcm_substream *substream)1009{1010 struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);1011 struct cs4231_dma_control *dma_cont = &chip->c_dma;1012 size_t ptr;1013 1014 if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE))1015 return 0;1016 ptr = dma_cont->address(dma_cont);1017 if (ptr != 0)1018 ptr -= substream->runtime->dma_addr;1019 1020 return bytes_to_frames(substream->runtime, ptr);1021}1022 1023static int snd_cs4231_probe(struct snd_cs4231 *chip)1024{1025 unsigned long flags;1026 int i;1027 int id = 0;1028 int vers = 0;1029 unsigned char *ptr;1030 1031 for (i = 0; i < 50; i++) {1032 mb();1033 if (__cs4231_readb(chip, CS4231U(chip, REGSEL)) & CS4231_INIT)1034 msleep(2);1035 else {1036 spin_lock_irqsave(&chip->lock, flags);1037 snd_cs4231_out(chip, CS4231_MISC_INFO, CS4231_MODE2);1038 id = snd_cs4231_in(chip, CS4231_MISC_INFO) & 0x0f;1039 vers = snd_cs4231_in(chip, CS4231_VERSION);1040 spin_unlock_irqrestore(&chip->lock, flags);1041 if (id == 0x0a)1042 break; /* this is valid value */1043 }1044 }1045 dev_dbg(chip->card->dev,1046 "cs4231: port = %p, id = 0x%x\n", chip->port, id);1047 if (id != 0x0a)1048 return -ENODEV; /* no valid device found */1049 1050 spin_lock_irqsave(&chip->lock, flags);1051 1052 /* clear any pendings IRQ */1053 __cs4231_readb(chip, CS4231U(chip, STATUS));1054 __cs4231_writeb(chip, 0, CS4231U(chip, STATUS));1055 mb();1056 1057 spin_unlock_irqrestore(&chip->lock, flags);1058 1059 chip->image[CS4231_MISC_INFO] = CS4231_MODE2;1060 chip->image[CS4231_IFACE_CTRL] =1061 chip->image[CS4231_IFACE_CTRL] & ~CS4231_SINGLE_DMA;1062 chip->image[CS4231_ALT_FEATURE_1] = 0x80;1063 chip->image[CS4231_ALT_FEATURE_2] = 0x01;1064 if (vers & 0x20)1065 chip->image[CS4231_ALT_FEATURE_2] |= 0x02;1066 1067 ptr = (unsigned char *) &chip->image;1068 1069 snd_cs4231_mce_down(chip);1070 1071 spin_lock_irqsave(&chip->lock, flags);1072 1073 for (i = 0; i < 32; i++) /* ok.. fill all CS4231 registers */1074 snd_cs4231_out(chip, i, *ptr++);1075 1076 spin_unlock_irqrestore(&chip->lock, flags);1077 1078 snd_cs4231_mce_up(chip);1079 1080 snd_cs4231_mce_down(chip);1081 1082 mdelay(2);1083 1084 return 0; /* all things are ok.. */1085}1086 1087static const struct snd_pcm_hardware snd_cs4231_playback = {1088 .info = SNDRV_PCM_INFO_MMAP |1089 SNDRV_PCM_INFO_INTERLEAVED |1090 SNDRV_PCM_INFO_MMAP_VALID |1091 SNDRV_PCM_INFO_SYNC_START,1092 .formats = SNDRV_PCM_FMTBIT_MU_LAW |1093 SNDRV_PCM_FMTBIT_A_LAW |1094 SNDRV_PCM_FMTBIT_IMA_ADPCM |1095 SNDRV_PCM_FMTBIT_U8 |1096 SNDRV_PCM_FMTBIT_S16_LE |1097 SNDRV_PCM_FMTBIT_S16_BE,1098 .rates = SNDRV_PCM_RATE_KNOT |1099 SNDRV_PCM_RATE_8000_48000,1100 .rate_min = 5510,1101 .rate_max = 48000,1102 .channels_min = 1,1103 .channels_max = 2,1104 .buffer_bytes_max = 32 * 1024,1105 .period_bytes_min = 64,1106 .period_bytes_max = 32 * 1024,1107 .periods_min = 1,1108 .periods_max = 1024,1109};1110 1111static const struct snd_pcm_hardware snd_cs4231_capture = {1112 .info = SNDRV_PCM_INFO_MMAP |1113 SNDRV_PCM_INFO_INTERLEAVED |1114 SNDRV_PCM_INFO_MMAP_VALID |1115 SNDRV_PCM_INFO_SYNC_START,1116 .formats = SNDRV_PCM_FMTBIT_MU_LAW |1117 SNDRV_PCM_FMTBIT_A_LAW |1118 SNDRV_PCM_FMTBIT_IMA_ADPCM |1119 SNDRV_PCM_FMTBIT_U8 |1120 SNDRV_PCM_FMTBIT_S16_LE |1121 SNDRV_PCM_FMTBIT_S16_BE,1122 .rates = SNDRV_PCM_RATE_KNOT |1123 SNDRV_PCM_RATE_8000_48000,1124 .rate_min = 5510,1125 .rate_max = 48000,1126 .channels_min = 1,1127 .channels_max = 2,1128 .buffer_bytes_max = 32 * 1024,1129 .period_bytes_min = 64,1130 .period_bytes_max = 32 * 1024,1131 .periods_min = 1,1132 .periods_max = 1024,1133};1134 1135static int snd_cs4231_playback_open(struct snd_pcm_substream *substream)1136{1137 struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);1138 struct snd_pcm_runtime *runtime = substream->runtime;1139 int err;1140 1141 runtime->hw = snd_cs4231_playback;1142 1143 err = snd_cs4231_open(chip, CS4231_MODE_PLAY);1144 if (err < 0)1145 return err;1146 chip->playback_substream = substream;1147 chip->p_periods_sent = 0;1148 snd_pcm_set_sync(substream);1149 snd_cs4231_xrate(runtime);1150 1151 return 0;1152}1153 1154static int snd_cs4231_capture_open(struct snd_pcm_substream *substream)1155{1156 struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);1157 struct snd_pcm_runtime *runtime = substream->runtime;1158 int err;1159 1160 runtime->hw = snd_cs4231_capture;1161 1162 err = snd_cs4231_open(chip, CS4231_MODE_RECORD);1163 if (err < 0)1164 return err;1165 chip->capture_substream = substream;1166 chip->c_periods_sent = 0;1167 snd_pcm_set_sync(substream);1168 snd_cs4231_xrate(runtime);1169 1170 return 0;1171}1172 1173static int snd_cs4231_playback_close(struct snd_pcm_substream *substream)1174{1175 struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);1176 1177 snd_cs4231_close(chip, CS4231_MODE_PLAY);1178 chip->playback_substream = NULL;1179 1180 return 0;1181}1182 1183static int snd_cs4231_capture_close(struct snd_pcm_substream *substream)1184{1185 struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);1186 1187 snd_cs4231_close(chip, CS4231_MODE_RECORD);1188 chip->capture_substream = NULL;1189 1190 return 0;1191}1192 1193/* XXX We can do some power-management, in particular on EBUS using1194 * XXX the audio AUXIO register...1195 */1196 1197static const struct snd_pcm_ops snd_cs4231_playback_ops = {1198 .open = snd_cs4231_playback_open,1199 .close = snd_cs4231_playback_close,1200 .hw_params = snd_cs4231_playback_hw_params,1201 .prepare = snd_cs4231_playback_prepare,1202 .trigger = snd_cs4231_trigger,1203 .pointer = snd_cs4231_playback_pointer,1204};1205 1206static const struct snd_pcm_ops snd_cs4231_capture_ops = {1207 .open = snd_cs4231_capture_open,1208 .close = snd_cs4231_capture_close,1209 .hw_params = snd_cs4231_capture_hw_params,1210 .prepare = snd_cs4231_capture_prepare,1211 .trigger = snd_cs4231_trigger,1212 .pointer = snd_cs4231_capture_pointer,1213};1214 1215static int snd_cs4231_pcm(struct snd_card *card)1216{1217 struct snd_cs4231 *chip = card->private_data;1218 struct snd_pcm *pcm;1219 int err;1220 1221 err = snd_pcm_new(card, "CS4231", 0, 1, 1, &pcm);1222 if (err < 0)1223 return err;1224 1225 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,1226 &snd_cs4231_playback_ops);1227 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,1228 &snd_cs4231_capture_ops);1229 1230 /* global setup */1231 pcm->private_data = chip;1232 pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;1233 strcpy(pcm->name, "CS4231");1234 1235 snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,1236 &chip->op->dev, 64 * 1024, 128 * 1024);1237 1238 chip->pcm = pcm;1239 1240 return 0;1241}1242 1243static int snd_cs4231_timer(struct snd_card *card)1244{1245 struct snd_cs4231 *chip = card->private_data;1246 struct snd_timer *timer;1247 struct snd_timer_id tid;1248 int err;1249 1250 /* Timer initialization */1251 tid.dev_class = SNDRV_TIMER_CLASS_CARD;1252 tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE;1253 tid.card = card->number;1254 tid.device = 0;1255 tid.subdevice = 0;1256 err = snd_timer_new(card, "CS4231", &tid, &timer);1257 if (err < 0)1258 return err;1259 strcpy(timer->name, "CS4231");1260 timer->private_data = chip;1261 timer->hw = snd_cs4231_timer_table;1262 chip->timer = timer;1263 1264 return 0;1265}1266 1267/*1268 * MIXER part1269 */1270 1271static int snd_cs4231_info_mux(struct snd_kcontrol *kcontrol,1272 struct snd_ctl_elem_info *uinfo)1273{1274 static const char * const texts[4] = {1275 "Line", "CD", "Mic", "Mix"1276 };1277 1278 return snd_ctl_enum_info(uinfo, 2, 4, texts);1279}1280 1281static int snd_cs4231_get_mux(struct snd_kcontrol *kcontrol,1282 struct snd_ctl_elem_value *ucontrol)1283{1284 struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);1285 unsigned long flags;1286 1287 spin_lock_irqsave(&chip->lock, flags);1288 ucontrol->value.enumerated.item[0] =1289 (chip->image[CS4231_LEFT_INPUT] & CS4231_MIXS_ALL) >> 6;1290 ucontrol->value.enumerated.item[1] =1291 (chip->image[CS4231_RIGHT_INPUT] & CS4231_MIXS_ALL) >> 6;1292 spin_unlock_irqrestore(&chip->lock, flags);1293 1294 return 0;1295}1296 1297static int snd_cs4231_put_mux(struct snd_kcontrol *kcontrol,1298 struct snd_ctl_elem_value *ucontrol)1299{1300 struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);1301 unsigned long flags;1302 unsigned short left, right;1303 int change;1304 1305 if (ucontrol->value.enumerated.item[0] > 3 ||1306 ucontrol->value.enumerated.item[1] > 3)1307 return -EINVAL;1308 left = ucontrol->value.enumerated.item[0] << 6;1309 right = ucontrol->value.enumerated.item[1] << 6;1310 1311 spin_lock_irqsave(&chip->lock, flags);1312 1313 left = (chip->image[CS4231_LEFT_INPUT] & ~CS4231_MIXS_ALL) | left;1314 right = (chip->image[CS4231_RIGHT_INPUT] & ~CS4231_MIXS_ALL) | right;1315 change = left != chip->image[CS4231_LEFT_INPUT] ||1316 right != chip->image[CS4231_RIGHT_INPUT];1317 snd_cs4231_out(chip, CS4231_LEFT_INPUT, left);1318 snd_cs4231_out(chip, CS4231_RIGHT_INPUT, right);1319 1320 spin_unlock_irqrestore(&chip->lock, flags);1321 1322 return change;1323}1324 1325static int snd_cs4231_info_single(struct snd_kcontrol *kcontrol,1326 struct snd_ctl_elem_info *uinfo)1327{1328 int mask = (kcontrol->private_value >> 16) & 0xff;1329 1330 uinfo->type = (mask == 1) ?1331 SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;1332 uinfo->count = 1;1333 uinfo->value.integer.min = 0;1334 uinfo->value.integer.max = mask;1335 1336 return 0;1337}1338 1339static int snd_cs4231_get_single(struct snd_kcontrol *kcontrol,1340 struct snd_ctl_elem_value *ucontrol)1341{1342 struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);1343 unsigned long flags;1344 int reg = kcontrol->private_value & 0xff;1345 int shift = (kcontrol->private_value >> 8) & 0xff;1346 int mask = (kcontrol->private_value >> 16) & 0xff;1347 int invert = (kcontrol->private_value >> 24) & 0xff;1348 1349 spin_lock_irqsave(&chip->lock, flags);1350 1351 ucontrol->value.integer.value[0] = (chip->image[reg] >> shift) & mask;1352 1353 spin_unlock_irqrestore(&chip->lock, flags);1354 1355 if (invert)1356 ucontrol->value.integer.value[0] =1357 (mask - ucontrol->value.integer.value[0]);1358 1359 return 0;1360}1361 1362static int snd_cs4231_put_single(struct snd_kcontrol *kcontrol,1363 struct snd_ctl_elem_value *ucontrol)1364{1365 struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);1366 unsigned long flags;1367 int reg = kcontrol->private_value & 0xff;1368 int shift = (kcontrol->private_value >> 8) & 0xff;1369 int mask = (kcontrol->private_value >> 16) & 0xff;1370 int invert = (kcontrol->private_value >> 24) & 0xff;1371 int change;1372 unsigned short val;1373 1374 val = (ucontrol->value.integer.value[0] & mask);1375 if (invert)1376 val = mask - val;1377 val <<= shift;1378 1379 spin_lock_irqsave(&chip->lock, flags);1380 1381 val = (chip->image[reg] & ~(mask << shift)) | val;1382 change = val != chip->image[reg];1383 snd_cs4231_out(chip, reg, val);1384 1385 spin_unlock_irqrestore(&chip->lock, flags);1386 1387 return change;1388}1389 1390static int snd_cs4231_info_double(struct snd_kcontrol *kcontrol,1391 struct snd_ctl_elem_info *uinfo)1392{1393 int mask = (kcontrol->private_value >> 24) & 0xff;1394 1395 uinfo->type = mask == 1 ?1396 SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;1397 uinfo->count = 2;1398 uinfo->value.integer.min = 0;1399 uinfo->value.integer.max = mask;1400 1401 return 0;1402}1403 1404static int snd_cs4231_get_double(struct snd_kcontrol *kcontrol,1405 struct snd_ctl_elem_value *ucontrol)1406{1407 struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);1408 unsigned long flags;1409 int left_reg = kcontrol->private_value & 0xff;1410 int right_reg = (kcontrol->private_value >> 8) & 0xff;1411 int shift_left = (kcontrol->private_value >> 16) & 0x07;1412 int shift_right = (kcontrol->private_value >> 19) & 0x07;1413 int mask = (kcontrol->private_value >> 24) & 0xff;1414 int invert = (kcontrol->private_value >> 22) & 1;1415 1416 spin_lock_irqsave(&chip->lock, flags);1417 1418 ucontrol->value.integer.value[0] =1419 (chip->image[left_reg] >> shift_left) & mask;1420 ucontrol->value.integer.value[1] =1421 (chip->image[right_reg] >> shift_right) & mask;1422 1423 spin_unlock_irqrestore(&chip->lock, flags);1424 1425 if (invert) {1426 ucontrol->value.integer.value[0] =1427 (mask - ucontrol->value.integer.value[0]);1428 ucontrol->value.integer.value[1] =1429 (mask - ucontrol->value.integer.value[1]);1430 }1431 1432 return 0;1433}1434 1435static int snd_cs4231_put_double(struct snd_kcontrol *kcontrol,1436 struct snd_ctl_elem_value *ucontrol)1437{1438 struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol);1439 unsigned long flags;1440 int left_reg = kcontrol->private_value & 0xff;1441 int right_reg = (kcontrol->private_value >> 8) & 0xff;1442 int shift_left = (kcontrol->private_value >> 16) & 0x07;1443 int shift_right = (kcontrol->private_value >> 19) & 0x07;1444 int mask = (kcontrol->private_value >> 24) & 0xff;1445 int invert = (kcontrol->private_value >> 22) & 1;1446 int change;1447 unsigned short val1, val2;1448 1449 val1 = ucontrol->value.integer.value[0] & mask;1450 val2 = ucontrol->value.integer.value[1] & mask;1451 if (invert) {1452 val1 = mask - val1;1453 val2 = mask - val2;1454 }1455 val1 <<= shift_left;1456 val2 <<= shift_right;1457 1458 spin_lock_irqsave(&chip->lock, flags);1459 1460 val1 = (chip->image[left_reg] & ~(mask << shift_left)) | val1;1461 val2 = (chip->image[right_reg] & ~(mask << shift_right)) | val2;1462 change = val1 != chip->image[left_reg];1463 change |= val2 != chip->image[right_reg];1464 snd_cs4231_out(chip, left_reg, val1);1465 snd_cs4231_out(chip, right_reg, val2);1466 1467 spin_unlock_irqrestore(&chip->lock, flags);1468 1469 return change;1470}1471 1472#define CS4231_SINGLE(xname, xindex, reg, shift, mask, invert) \1473{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), .index = (xindex), \1474 .info = snd_cs4231_info_single, \1475 .get = snd_cs4231_get_single, .put = snd_cs4231_put_single, \1476 .private_value = (reg) | ((shift) << 8) | ((mask) << 16) | ((invert) << 24) }1477 1478#define CS4231_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, \1479 shift_right, mask, invert) \1480{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), .index = (xindex), \1481 .info = snd_cs4231_info_double, \1482 .get = snd_cs4231_get_double, .put = snd_cs4231_put_double, \1483 .private_value = (left_reg) | ((right_reg) << 8) | ((shift_left) << 16) | \1484 ((shift_right) << 19) | ((mask) << 24) | ((invert) << 22) }1485 1486static const struct snd_kcontrol_new snd_cs4231_controls[] = {1487CS4231_DOUBLE("PCM Playback Switch", 0, CS4231_LEFT_OUTPUT,1488 CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),1489CS4231_DOUBLE("PCM Playback Volume", 0, CS4231_LEFT_OUTPUT,1490 CS4231_RIGHT_OUTPUT, 0, 0, 63, 1),1491CS4231_DOUBLE("Line Playback Switch", 0, CS4231_LEFT_LINE_IN,1492 CS4231_RIGHT_LINE_IN, 7, 7, 1, 1),1493CS4231_DOUBLE("Line Playback Volume", 0, CS4231_LEFT_LINE_IN,1494 CS4231_RIGHT_LINE_IN, 0, 0, 31, 1),1495CS4231_DOUBLE("Aux Playback Switch", 0, CS4231_AUX1_LEFT_INPUT,1496 CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1),1497CS4231_DOUBLE("Aux Playback Volume", 0, CS4231_AUX1_LEFT_INPUT,1498 CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1),1499CS4231_DOUBLE("Aux Playback Switch", 1, CS4231_AUX2_LEFT_INPUT,1500 CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1),1501CS4231_DOUBLE("Aux Playback Volume", 1, CS4231_AUX2_LEFT_INPUT,1502 CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1),1503CS4231_SINGLE("Mono Playback Switch", 0, CS4231_MONO_CTRL, 7, 1, 1),1504CS4231_SINGLE("Mono Playback Volume", 0, CS4231_MONO_CTRL, 0, 15, 1),1505CS4231_SINGLE("Mono Output Playback Switch", 0, CS4231_MONO_CTRL, 6, 1, 1),1506CS4231_SINGLE("Mono Output Playback Bypass", 0, CS4231_MONO_CTRL, 5, 1, 0),1507CS4231_DOUBLE("Capture Volume", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 0, 0,1508 15, 0),1509{1510 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,1511 .name = "Capture Source",1512 .info = snd_cs4231_info_mux,1513 .get = snd_cs4231_get_mux,1514 .put = snd_cs4231_put_mux,1515},1516CS4231_DOUBLE("Mic Boost", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 5, 5,1517 1, 0),1518CS4231_SINGLE("Loopback Capture Switch", 0, CS4231_LOOPBACK, 0, 1, 0),1519CS4231_SINGLE("Loopback Capture Volume", 0, CS4231_LOOPBACK, 2, 63, 1),1520/* SPARC specific uses of XCTL{0,1} general purpose outputs. */1521CS4231_SINGLE("Line Out Switch", 0, CS4231_PIN_CTRL, 6, 1, 1),1522CS4231_SINGLE("Headphone Out Switch", 0, CS4231_PIN_CTRL, 7, 1, 1)1523};1524 1525static int snd_cs4231_mixer(struct snd_card *card)1526{1527 struct snd_cs4231 *chip = card->private_data;1528 int err, idx;1529 1530 if (snd_BUG_ON(!chip || !chip->pcm))1531 return -EINVAL;1532 1533 strcpy(card->mixername, chip->pcm->name);1534 1535 for (idx = 0; idx < ARRAY_SIZE(snd_cs4231_controls); idx++) {1536 err = snd_ctl_add(card,1537 snd_ctl_new1(&snd_cs4231_controls[idx], chip));1538 if (err < 0)1539 return err;1540 }1541 return 0;1542}1543 1544static int dev;1545 1546static int cs4231_attach_begin(struct platform_device *op,1547 struct snd_card **rcard)1548{1549 struct snd_card *card;1550 struct snd_cs4231 *chip;1551 int err;1552 1553 *rcard = NULL;1554 1555 if (dev >= SNDRV_CARDS)1556 return -ENODEV;1557 1558 if (!enable[dev]) {1559 dev++;1560 return -ENOENT;1561 }1562 1563 err = snd_card_new(&op->dev, index[dev], id[dev], THIS_MODULE,1564 sizeof(struct snd_cs4231), &card);1565 if (err < 0)1566 return err;1567 1568 strcpy(card->driver, "CS4231");1569 strcpy(card->shortname, "Sun CS4231");1570 1571 chip = card->private_data;1572 chip->card = card;1573 1574 *rcard = card;1575 return 0;1576}1577 1578static int cs4231_attach_finish(struct snd_card *card)1579{1580 struct snd_cs4231 *chip = card->private_data;1581 int err;1582 1583 err = snd_cs4231_pcm(card);1584 if (err < 0)1585 goto out_err;1586 1587 err = snd_cs4231_mixer(card);1588 if (err < 0)1589 goto out_err;1590 1591 err = snd_cs4231_timer(card);1592 if (err < 0)1593 goto out_err;1594 1595 err = snd_card_register(card);1596 if (err < 0)1597 goto out_err;1598 1599 dev_set_drvdata(&chip->op->dev, chip);1600 1601 dev++;1602 return 0;1603 1604out_err:1605 snd_card_free(card);1606 return err;1607}1608 1609#ifdef SBUS_SUPPORT1610 1611static irqreturn_t snd_cs4231_sbus_interrupt(int irq, void *dev_id)1612{1613 unsigned long flags;1614 unsigned char status;1615 u32 csr;1616 struct snd_cs4231 *chip = dev_id;1617 1618 /*This is IRQ is not raised by the cs4231*/1619 if (!(__cs4231_readb(chip, CS4231U(chip, STATUS)) & CS4231_GLOBALIRQ))1620 return IRQ_NONE;1621 1622 /* ACK the APC interrupt. */1623 csr = sbus_readl(chip->port + APCCSR);1624 1625 sbus_writel(csr, chip->port + APCCSR);1626 1627 if ((csr & APC_PDMA_READY) &&1628 (csr & APC_PLAY_INT) &&1629 (csr & APC_XINT_PNVA) &&1630 !(csr & APC_XINT_EMPT))1631 snd_cs4231_play_callback(chip);1632 1633 if ((csr & APC_CDMA_READY) &&1634 (csr & APC_CAPT_INT) &&1635 (csr & APC_XINT_CNVA) &&1636 !(csr & APC_XINT_EMPT))1637 snd_cs4231_capture_callback(chip);1638 1639 status = snd_cs4231_in(chip, CS4231_IRQ_STATUS);1640 1641 if (status & CS4231_TIMER_IRQ) {1642 if (chip->timer)1643 snd_timer_interrupt(chip->timer, chip->timer->sticks);1644 }1645 1646 if ((status & CS4231_RECORD_IRQ) && (csr & APC_CDMA_READY))1647 snd_cs4231_overrange(chip);1648 1649 /* ACK the CS4231 interrupt. */1650 spin_lock_irqsave(&chip->lock, flags);1651 snd_cs4231_outm(chip, CS4231_IRQ_STATUS, ~CS4231_ALL_IRQS | ~status, 0);1652 spin_unlock_irqrestore(&chip->lock, flags);1653 1654 return IRQ_HANDLED;1655}1656 1657/*1658 * SBUS DMA routines1659 */1660 1661static int sbus_dma_request(struct cs4231_dma_control *dma_cont,1662 dma_addr_t bus_addr, size_t len)1663{1664 unsigned long flags;1665 u32 test, csr;1666 int err;1667 struct sbus_dma_info *base = &dma_cont->sbus_info;1668 1669 if (len >= (1 << 24))1670 return -EINVAL;1671 spin_lock_irqsave(&base->lock, flags);1672 csr = sbus_readl(base->regs + APCCSR);1673 err = -EINVAL;1674 test = APC_CDMA_READY;1675 if (base->dir == APC_PLAY)1676 test = APC_PDMA_READY;1677 if (!(csr & test))1678 goto out;1679 err = -EBUSY;1680 test = APC_XINT_CNVA;1681 if (base->dir == APC_PLAY)1682 test = APC_XINT_PNVA;1683 if (!(csr & test))1684 goto out;1685 err = 0;1686 sbus_writel(bus_addr, base->regs + base->dir + APCNVA);1687 sbus_writel(len, base->regs + base->dir + APCNC);1688out:1689 spin_unlock_irqrestore(&base->lock, flags);1690 return err;1691}1692 1693static void sbus_dma_prepare(struct cs4231_dma_control *dma_cont, int d)1694{1695 unsigned long flags;1696 u32 csr, test;1697 struct sbus_dma_info *base = &dma_cont->sbus_info;1698 1699 spin_lock_irqsave(&base->lock, flags);1700 csr = sbus_readl(base->regs + APCCSR);1701 test = APC_GENL_INT | APC_PLAY_INT | APC_XINT_ENA |1702 APC_XINT_PLAY | APC_XINT_PEMP | APC_XINT_GENL |1703 APC_XINT_PENA;1704 if (base->dir == APC_RECORD)1705 test = APC_GENL_INT | APC_CAPT_INT | APC_XINT_ENA |1706 APC_XINT_CAPT | APC_XINT_CEMP | APC_XINT_GENL;1707 csr |= test;1708 sbus_writel(csr, base->regs + APCCSR);1709 spin_unlock_irqrestore(&base->lock, flags);1710}1711 1712static void sbus_dma_enable(struct cs4231_dma_control *dma_cont, int on)1713{1714 unsigned long flags;1715 u32 csr, shift;1716 struct sbus_dma_info *base = &dma_cont->sbus_info;1717 1718 spin_lock_irqsave(&base->lock, flags);1719 if (!on) {1720 sbus_writel(0, base->regs + base->dir + APCNC);1721 sbus_writel(0, base->regs + base->dir + APCNVA);1722 if (base->dir == APC_PLAY) {1723 sbus_writel(0, base->regs + base->dir + APCC);1724 sbus_writel(0, base->regs + base->dir + APCVA);1725 }1726 1727 udelay(1200);1728 }1729 csr = sbus_readl(base->regs + APCCSR);1730 shift = 0;1731 if (base->dir == APC_PLAY)1732 shift = 1;1733 if (on)1734 csr &= ~(APC_CPAUSE << shift);1735 else1736 csr |= (APC_CPAUSE << shift);1737 sbus_writel(csr, base->regs + APCCSR);1738 if (on)1739 csr |= (APC_CDMA_READY << shift);1740 else1741 csr &= ~(APC_CDMA_READY << shift);1742 sbus_writel(csr, base->regs + APCCSR);1743 1744 spin_unlock_irqrestore(&base->lock, flags);1745}1746 1747static unsigned int sbus_dma_addr(struct cs4231_dma_control *dma_cont)1748{1749 struct sbus_dma_info *base = &dma_cont->sbus_info;1750 1751 return sbus_readl(base->regs + base->dir + APCVA);1752}1753 1754/*1755 * Init and exit routines1756 */1757 1758static int snd_cs4231_sbus_free(struct snd_cs4231 *chip)1759{1760 struct platform_device *op = chip->op;1761 1762 if (chip->irq[0])1763 free_irq(chip->irq[0], chip);1764 1765 if (chip->port)1766 of_iounmap(&op->resource[0], chip->port, chip->regs_size);1767 1768 return 0;1769}1770 1771static int snd_cs4231_sbus_dev_free(struct snd_device *device)1772{1773 struct snd_cs4231 *cp = device->device_data;1774 1775 return snd_cs4231_sbus_free(cp);1776}1777 1778static const struct snd_device_ops snd_cs4231_sbus_dev_ops = {1779 .dev_free = snd_cs4231_sbus_dev_free,1780};1781 1782static int snd_cs4231_sbus_create(struct snd_card *card,1783 struct platform_device *op,1784 int dev)1785{1786 struct snd_cs4231 *chip = card->private_data;1787 int err;1788 1789 spin_lock_init(&chip->lock);1790 spin_lock_init(&chip->c_dma.sbus_info.lock);1791 spin_lock_init(&chip->p_dma.sbus_info.lock);1792 mutex_init(&chip->mce_mutex);1793 mutex_init(&chip->open_mutex);1794 chip->op = op;1795 chip->regs_size = resource_size(&op->resource[0]);1796 memcpy(&chip->image, &snd_cs4231_original_image,1797 sizeof(snd_cs4231_original_image));1798 1799 chip->port = of_ioremap(&op->resource[0], 0,1800 chip->regs_size, "cs4231");1801 if (!chip->port) {1802 dev_dbg(chip->card->dev,1803 "cs4231-%d: Unable to map chip registers.\n", dev);1804 return -EIO;1805 }1806 1807 chip->c_dma.sbus_info.regs = chip->port;1808 chip->p_dma.sbus_info.regs = chip->port;1809 chip->c_dma.sbus_info.dir = APC_RECORD;1810 chip->p_dma.sbus_info.dir = APC_PLAY;1811 1812 chip->p_dma.prepare = sbus_dma_prepare;1813 chip->p_dma.enable = sbus_dma_enable;1814 chip->p_dma.request = sbus_dma_request;1815 chip->p_dma.address = sbus_dma_addr;1816 1817 chip->c_dma.prepare = sbus_dma_prepare;1818 chip->c_dma.enable = sbus_dma_enable;1819 chip->c_dma.request = sbus_dma_request;1820 chip->c_dma.address = sbus_dma_addr;1821 1822 if (request_irq(op->archdata.irqs[0], snd_cs4231_sbus_interrupt,1823 IRQF_SHARED, "cs4231", chip)) {1824 dev_dbg(chip->card->dev,1825 "cs4231-%d: Unable to grab SBUS IRQ %d\n",1826 dev, op->archdata.irqs[0]);1827 snd_cs4231_sbus_free(chip);1828 return -EBUSY;1829 }1830 chip->irq[0] = op->archdata.irqs[0];1831 1832 if (snd_cs4231_probe(chip) < 0) {1833 snd_cs4231_sbus_free(chip);1834 return -ENODEV;1835 }1836 snd_cs4231_init(chip);1837 1838 err = snd_device_new(card, SNDRV_DEV_LOWLEVEL,1839 chip, &snd_cs4231_sbus_dev_ops);1840 if (err < 0) {1841 snd_cs4231_sbus_free(chip);1842 return err;1843 }1844 1845 return 0;1846}1847 1848static int cs4231_sbus_probe(struct platform_device *op)1849{1850 struct resource *rp = &op->resource[0];1851 struct snd_card *card;1852 int err;1853 1854 err = cs4231_attach_begin(op, &card);1855 if (err)1856 return err;1857 1858 sprintf(card->longname, "%s at 0x%02lx:0x%016Lx, irq %d",1859 card->shortname,1860 rp->flags & 0xffL,1861 (unsigned long long)rp->start,1862 op->archdata.irqs[0]);1863 1864 err = snd_cs4231_sbus_create(card, op, dev);1865 if (err < 0) {1866 snd_card_free(card);1867 return err;1868 }1869 1870 return cs4231_attach_finish(card);1871}1872#endif1873 1874#ifdef EBUS_SUPPORT1875 1876static void snd_cs4231_ebus_play_callback(struct ebus_dma_info *p, int event,1877 void *cookie)1878{1879 struct snd_cs4231 *chip = cookie;1880 1881 snd_cs4231_play_callback(chip);1882}1883 1884static void snd_cs4231_ebus_capture_callback(struct ebus_dma_info *p,1885 int event, void *cookie)1886{1887 struct snd_cs4231 *chip = cookie;1888 1889 snd_cs4231_capture_callback(chip);1890}1891 1892/*1893 * EBUS DMA wrappers1894 */1895 1896static int _ebus_dma_request(struct cs4231_dma_control *dma_cont,1897 dma_addr_t bus_addr, size_t len)1898{1899 return ebus_dma_request(&dma_cont->ebus_info, bus_addr, len);1900}1901 1902static void _ebus_dma_enable(struct cs4231_dma_control *dma_cont, int on)1903{1904 ebus_dma_enable(&dma_cont->ebus_info, on);1905}1906 1907static void _ebus_dma_prepare(struct cs4231_dma_control *dma_cont, int dir)1908{1909 ebus_dma_prepare(&dma_cont->ebus_info, dir);1910}1911 1912static unsigned int _ebus_dma_addr(struct cs4231_dma_control *dma_cont)1913{1914 return ebus_dma_addr(&dma_cont->ebus_info);1915}1916 1917/*1918 * Init and exit routines1919 */1920 1921static int snd_cs4231_ebus_free(struct snd_cs4231 *chip)1922{1923 struct platform_device *op = chip->op;1924 1925 if (chip->c_dma.ebus_info.regs) {1926 ebus_dma_unregister(&chip->c_dma.ebus_info);1927 of_iounmap(&op->resource[2], chip->c_dma.ebus_info.regs, 0x10);1928 }1929 if (chip->p_dma.ebus_info.regs) {1930 ebus_dma_unregister(&chip->p_dma.ebus_info);1931 of_iounmap(&op->resource[1], chip->p_dma.ebus_info.regs, 0x10);1932 }1933 1934 if (chip->port)1935 of_iounmap(&op->resource[0], chip->port, 0x10);1936 1937 return 0;1938}1939 1940static int snd_cs4231_ebus_dev_free(struct snd_device *device)1941{1942 struct snd_cs4231 *cp = device->device_data;1943 1944 return snd_cs4231_ebus_free(cp);1945}1946 1947static const struct snd_device_ops snd_cs4231_ebus_dev_ops = {1948 .dev_free = snd_cs4231_ebus_dev_free,1949};1950 1951static int snd_cs4231_ebus_create(struct snd_card *card,1952 struct platform_device *op,1953 int dev)1954{1955 struct snd_cs4231 *chip = card->private_data;1956 int err;1957 1958 spin_lock_init(&chip->lock);1959 spin_lock_init(&chip->c_dma.ebus_info.lock);1960 spin_lock_init(&chip->p_dma.ebus_info.lock);1961 mutex_init(&chip->mce_mutex);1962 mutex_init(&chip->open_mutex);1963 chip->flags |= CS4231_FLAG_EBUS;1964 chip->op = op;1965 memcpy(&chip->image, &snd_cs4231_original_image,1966 sizeof(snd_cs4231_original_image));1967 strcpy(chip->c_dma.ebus_info.name, "cs4231(capture)");1968 chip->c_dma.ebus_info.flags = EBUS_DMA_FLAG_USE_EBDMA_HANDLER;1969 chip->c_dma.ebus_info.callback = snd_cs4231_ebus_capture_callback;1970 chip->c_dma.ebus_info.client_cookie = chip;1971 chip->c_dma.ebus_info.irq = op->archdata.irqs[0];1972 strcpy(chip->p_dma.ebus_info.name, "cs4231(play)");1973 chip->p_dma.ebus_info.flags = EBUS_DMA_FLAG_USE_EBDMA_HANDLER;1974 chip->p_dma.ebus_info.callback = snd_cs4231_ebus_play_callback;1975 chip->p_dma.ebus_info.client_cookie = chip;1976 chip->p_dma.ebus_info.irq = op->archdata.irqs[1];1977 1978 chip->p_dma.prepare = _ebus_dma_prepare;1979 chip->p_dma.enable = _ebus_dma_enable;1980 chip->p_dma.request = _ebus_dma_request;1981 chip->p_dma.address = _ebus_dma_addr;1982 1983 chip->c_dma.prepare = _ebus_dma_prepare;1984 chip->c_dma.enable = _ebus_dma_enable;1985 chip->c_dma.request = _ebus_dma_request;1986 chip->c_dma.address = _ebus_dma_addr;1987 1988 chip->port = of_ioremap(&op->resource[0], 0, 0x10, "cs4231");1989 chip->p_dma.ebus_info.regs =1990 of_ioremap(&op->resource[1], 0, 0x10, "cs4231_pdma");1991 chip->c_dma.ebus_info.regs =1992 of_ioremap(&op->resource[2], 0, 0x10, "cs4231_cdma");1993 if (!chip->port || !chip->p_dma.ebus_info.regs ||1994 !chip->c_dma.ebus_info.regs) {1995 snd_cs4231_ebus_free(chip);1996 dev_dbg(chip->card->dev,1997 "cs4231-%d: Unable to map chip registers.\n", dev);1998 return -EIO;1999 }2000 2001 if (ebus_dma_register(&chip->c_dma.ebus_info)) {2002 snd_cs4231_ebus_free(chip);2003 dev_dbg(chip->card->dev,2004 "cs4231-%d: Unable to register EBUS capture DMA\n",2005 dev);2006 return -EBUSY;2007 }2008 if (ebus_dma_irq_enable(&chip->c_dma.ebus_info, 1)) {2009 snd_cs4231_ebus_free(chip);2010 dev_dbg(chip->card->dev,2011 "cs4231-%d: Unable to enable EBUS capture IRQ\n",2012 dev);2013 return -EBUSY;2014 }2015 2016 if (ebus_dma_register(&chip->p_dma.ebus_info)) {2017 snd_cs4231_ebus_free(chip);2018 dev_dbg(chip->card->dev,2019 "cs4231-%d: Unable to register EBUS play DMA\n",2020 dev);2021 return -EBUSY;2022 }2023 if (ebus_dma_irq_enable(&chip->p_dma.ebus_info, 1)) {2024 snd_cs4231_ebus_free(chip);2025 dev_dbg(chip->card->dev,2026 "cs4231-%d: Unable to enable EBUS play IRQ\n", dev);2027 return -EBUSY;2028 }2029 2030 if (snd_cs4231_probe(chip) < 0) {2031 snd_cs4231_ebus_free(chip);2032 return -ENODEV;2033 }2034 snd_cs4231_init(chip);2035 2036 err = snd_device_new(card, SNDRV_DEV_LOWLEVEL,2037 chip, &snd_cs4231_ebus_dev_ops);2038 if (err < 0) {2039 snd_cs4231_ebus_free(chip);2040 return err;2041 }2042 2043 return 0;2044}2045 2046static int cs4231_ebus_probe(struct platform_device *op)2047{2048 struct snd_card *card;2049 int err;2050 2051 err = cs4231_attach_begin(op, &card);2052 if (err)2053 return err;2054 2055 sprintf(card->longname, "%s at 0x%llx, irq %d",2056 card->shortname,2057 op->resource[0].start,2058 op->archdata.irqs[0]);2059 2060 err = snd_cs4231_ebus_create(card, op, dev);2061 if (err < 0) {2062 snd_card_free(card);2063 return err;2064 }2065 2066 return cs4231_attach_finish(card);2067}2068#endif2069 2070static int cs4231_probe(struct platform_device *op)2071{2072#ifdef EBUS_SUPPORT2073 if (of_node_name_eq(op->dev.of_node->parent, "ebus"))2074 return cs4231_ebus_probe(op);2075#endif2076#ifdef SBUS_SUPPORT2077 if (of_node_name_eq(op->dev.of_node->parent, "sbus") ||2078 of_node_name_eq(op->dev.of_node->parent, "sbi"))2079 return cs4231_sbus_probe(op);2080#endif2081 return -ENODEV;2082}2083 2084static void cs4231_remove(struct platform_device *op)2085{2086 struct snd_cs4231 *chip = dev_get_drvdata(&op->dev);2087 2088 snd_card_free(chip->card);2089}2090 2091static const struct of_device_id cs4231_match[] = {2092 {2093 .name = "SUNW,CS4231",2094 },2095 {2096 .name = "audio",2097 .compatible = "SUNW,CS4231",2098 },2099 {},2100};2101 2102MODULE_DEVICE_TABLE(of, cs4231_match);2103 2104static struct platform_driver cs4231_driver = {2105 .driver = {2106 .name = "audio",2107 .of_match_table = cs4231_match,2108 },2109 .probe = cs4231_probe,2110 .remove_new = cs4231_remove,2111};2112 2113module_platform_driver(cs4231_driver);2114