2167 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Matt Wu <Matt_Wu@acersoftech.com.cn>4 * Apr 26, 20015 * Routines for control of ALi pci audio M54516 *7 * BUGS:8 * --9 *10 * TODO:11 * --12 */13 14#include <linux/io.h>15#include <linux/delay.h>16#include <linux/interrupt.h>17#include <linux/init.h>18#include <linux/pci.h>19#include <linux/slab.h>20#include <linux/module.h>21#include <linux/dma-mapping.h>22#include <sound/core.h>23#include <sound/pcm.h>24#include <sound/info.h>25#include <sound/ac97_codec.h>26#include <sound/mpu401.h>27#include <sound/initval.h>28 29MODULE_AUTHOR("Matt Wu <Matt_Wu@acersoftech.com.cn>");30MODULE_DESCRIPTION("ALI M5451");31MODULE_LICENSE("GPL");32 33static int index = SNDRV_DEFAULT_IDX1; /* Index */34static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */35static int pcm_channels = 32;36static bool spdif;37 38module_param(index, int, 0444);39MODULE_PARM_DESC(index, "Index value for ALI M5451 PCI Audio.");40module_param(id, charp, 0444);41MODULE_PARM_DESC(id, "ID string for ALI M5451 PCI Audio.");42module_param(pcm_channels, int, 0444);43MODULE_PARM_DESC(pcm_channels, "PCM Channels");44module_param(spdif, bool, 0444);45MODULE_PARM_DESC(spdif, "Support SPDIF I/O");46 47/* just for backward compatibility */48static bool enable;49module_param(enable, bool, 0444);50 51 52/*53 * Constants definition54 */55 56#define DEVICE_ID_ALI5451 ((PCI_VENDOR_ID_AL<<16)|PCI_DEVICE_ID_AL_M5451)57 58 59#define ALI_CHANNELS 3260 61#define ALI_PCM_IN_CHANNEL 3162#define ALI_SPDIF_IN_CHANNEL 1963#define ALI_SPDIF_OUT_CHANNEL 1564#define ALI_CENTER_CHANNEL 2465#define ALI_LEF_CHANNEL 2366#define ALI_SURR_LEFT_CHANNEL 2667#define ALI_SURR_RIGHT_CHANNEL 2568#define ALI_MODEM_IN_CHANNEL 2169#define ALI_MODEM_OUT_CHANNEL 2070 71#define SNDRV_ALI_VOICE_TYPE_PCM 0172#define SNDRV_ALI_VOICE_TYPE_OTH 0273 74#define ALI_5451_V02 0x0275 76/*77 * Direct Registers78 */79 80#define ALI_LEGACY_DMAR0 0x00 /* ADR0 */81#define ALI_LEGACY_DMAR4 0x04 /* CNT0 */82#define ALI_LEGACY_DMAR11 0x0b /* MOD */83#define ALI_LEGACY_DMAR15 0x0f /* MMR */84#define ALI_MPUR0 0x2085#define ALI_MPUR1 0x2186#define ALI_MPUR2 0x2287#define ALI_MPUR3 0x2388 89#define ALI_AC97_WRITE 0x4090#define ALI_AC97_READ 0x4491 92#define ALI_SCTRL 0x4893#define ALI_SPDIF_OUT_ENABLE 0x2094#define ALI_SCTRL_LINE_IN2 (1 << 9)95#define ALI_SCTRL_GPIO_IN2 (1 << 13)96#define ALI_SCTRL_LINE_OUT_EN (1 << 20)97#define ALI_SCTRL_GPIO_OUT_EN (1 << 23)98#define ALI_SCTRL_CODEC1_READY (1 << 24)99#define ALI_SCTRL_CODEC2_READY (1 << 25)100#define ALI_AC97_GPIO 0x4c101#define ALI_AC97_GPIO_ENABLE 0x8000102#define ALI_AC97_GPIO_DATA_SHIFT 16103#define ALI_SPDIF_CS 0x70104#define ALI_SPDIF_CTRL 0x74105#define ALI_SPDIF_IN_FUNC_ENABLE 0x02106#define ALI_SPDIF_IN_CH_STATUS 0x40107#define ALI_SPDIF_OUT_CH_STATUS 0xbf108#define ALI_START 0x80109#define ALI_STOP 0x84110#define ALI_CSPF 0x90111#define ALI_AINT 0x98112#define ALI_GC_CIR 0xa0113 #define ENDLP_IE 0x00001000114 #define MIDLP_IE 0x00002000115#define ALI_AINTEN 0xa4116#define ALI_VOLUME 0xa8117#define ALI_SBDELTA_DELTA_R 0xac118#define ALI_MISCINT 0xb0119 #define ADDRESS_IRQ 0x00000020120 #define TARGET_REACHED 0x00008000121 #define MIXER_OVERFLOW 0x00000800122 #define MIXER_UNDERFLOW 0x00000400123 #define GPIO_IRQ 0x01000000124#define ALI_SBBL_SBCL 0xc0125#define ALI_SBCTRL_SBE2R_SBDD 0xc4126#define ALI_STIMER 0xc8127#define ALI_GLOBAL_CONTROL 0xd4128#define ALI_SPDIF_OUT_SEL_PCM 0x00000400 /* bit 10 */129#define ALI_SPDIF_IN_SUPPORT 0x00000800 /* bit 11 */130#define ALI_SPDIF_OUT_CH_ENABLE 0x00008000 /* bit 15 */131#define ALI_SPDIF_IN_CH_ENABLE 0x00080000 /* bit 19 */132#define ALI_PCM_IN_ENABLE 0x80000000 /* bit 31 */133 134#define ALI_CSO_ALPHA_FMS 0xe0135#define ALI_LBA 0xe4136#define ALI_ESO_DELTA 0xe8137#define ALI_GVSEL_PAN_VOC_CTRL_EC 0xf0138#define ALI_EBUF1 0xf4139#define ALI_EBUF2 0xf8140 141#define ALI_REG(codec, x) ((codec)->port + x)142 143#define MAX_CODECS 2144 145 146struct snd_ali;147struct snd_ali_voice;148 149struct snd_ali_channel_control {150 /* register data */151 struct REGDATA {152 unsigned int start;153 unsigned int stop;154 unsigned int aint;155 unsigned int ainten;156 } data;157 158 /* register addresses */159 struct REGS {160 unsigned int start;161 unsigned int stop;162 unsigned int aint;163 unsigned int ainten;164 unsigned int ac97read;165 unsigned int ac97write;166 } regs;167 168};169 170struct snd_ali_voice {171 unsigned int number;172 unsigned int use :1,173 pcm :1,174 midi :1,175 mode :1,176 synth :1,177 running :1;178 179 /* PCM data */180 struct snd_ali *codec;181 struct snd_pcm_substream *substream;182 struct snd_ali_voice *extra;183 184 int eso; /* final ESO value for channel */185 int count; /* runtime->period_size */186 187 /* --- */188 189 void *private_data;190 void (*private_free)(void *private_data);191};192 193 194struct snd_alidev {195 196 struct snd_ali_voice voices[ALI_CHANNELS]; 197 198 unsigned int chcnt; /* num of opened channels */199 unsigned int chmap; /* bitmap for opened channels */200 unsigned int synthcount;201 202};203 204 205#define ALI_GLOBAL_REGS 56206#define ALI_CHANNEL_REGS 8207struct snd_ali_image {208 u32 regs[ALI_GLOBAL_REGS];209 u32 channel_regs[ALI_CHANNELS][ALI_CHANNEL_REGS];210};211 212 213struct snd_ali {214 int irq;215 unsigned long port;216 unsigned char revision;217 218 unsigned int hw_initialized :1;219 unsigned int spdif_support :1;220 221 struct pci_dev *pci;222 struct pci_dev *pci_m1533;223 struct pci_dev *pci_m7101;224 225 struct snd_card *card;226 struct snd_pcm *pcm[MAX_CODECS];227 struct snd_alidev synth;228 struct snd_ali_channel_control chregs;229 230 /* S/PDIF Mask */231 unsigned int spdif_mask;232 233 unsigned int spurious_irq_count;234 unsigned int spurious_irq_max_delta;235 236 unsigned int num_of_codecs;237 238 struct snd_ac97_bus *ac97_bus;239 struct snd_ac97 *ac97[MAX_CODECS];240 unsigned short ac97_ext_id;241 unsigned short ac97_ext_status;242 243 spinlock_t reg_lock;244 spinlock_t voice_alloc;245 246 struct snd_ali_image image;247};248 249static const struct pci_device_id snd_ali_ids[] = {250 {PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5451), 0, 0, 0},251 {0, }252};253MODULE_DEVICE_TABLE(pci, snd_ali_ids);254 255static void snd_ali_clear_voices(struct snd_ali *, unsigned int, unsigned int);256static unsigned short snd_ali_codec_peek(struct snd_ali *, int, unsigned short);257static void snd_ali_codec_poke(struct snd_ali *, int, unsigned short,258 unsigned short);259 260/*261 * AC97 ACCESS262 */263 264static inline unsigned int snd_ali_5451_peek(struct snd_ali *codec,265 unsigned int port)266{267 return (unsigned int)inl(ALI_REG(codec, port)); 268}269 270static inline void snd_ali_5451_poke(struct snd_ali *codec,271 unsigned int port,272 unsigned int val)273{274 outl((unsigned int)val, ALI_REG(codec, port));275}276 277static int snd_ali_codec_ready(struct snd_ali *codec,278 unsigned int port)279{280 unsigned long end_time;281 unsigned int res;282 283 end_time = jiffies + msecs_to_jiffies(250);284 285 for (;;) {286 res = snd_ali_5451_peek(codec,port);287 if (!(res & 0x8000))288 return 0;289 if (!time_after_eq(end_time, jiffies))290 break;291 schedule_timeout_uninterruptible(1);292 }293 294 snd_ali_5451_poke(codec, port, res & ~0x8000);295 dev_dbg(codec->card->dev, "ali_codec_ready: codec is not ready.\n");296 return -EIO;297}298 299static int snd_ali_stimer_ready(struct snd_ali *codec)300{301 unsigned long end_time;302 unsigned long dwChk1,dwChk2;303 304 dwChk1 = snd_ali_5451_peek(codec, ALI_STIMER);305 end_time = jiffies + msecs_to_jiffies(250);306 307 for (;;) {308 dwChk2 = snd_ali_5451_peek(codec, ALI_STIMER);309 if (dwChk2 != dwChk1)310 return 0;311 if (!time_after_eq(end_time, jiffies))312 break;313 schedule_timeout_uninterruptible(1);314 }315 316 dev_err(codec->card->dev, "ali_stimer_read: stimer is not ready.\n");317 return -EIO;318}319 320static void snd_ali_codec_poke(struct snd_ali *codec,int secondary,321 unsigned short reg,322 unsigned short val)323{324 unsigned int dwVal;325 unsigned int port;326 327 if (reg >= 0x80) {328 dev_err(codec->card->dev,329 "ali_codec_poke: reg(%xh) invalid.\n", reg);330 return;331 }332 333 port = codec->chregs.regs.ac97write;334 335 if (snd_ali_codec_ready(codec, port) < 0)336 return;337 if (snd_ali_stimer_ready(codec) < 0)338 return;339 340 dwVal = (unsigned int) (reg & 0xff);341 dwVal |= 0x8000 | (val << 16);342 if (secondary)343 dwVal |= 0x0080;344 if (codec->revision == ALI_5451_V02)345 dwVal |= 0x0100;346 347 snd_ali_5451_poke(codec, port, dwVal);348 349 return ;350}351 352static unsigned short snd_ali_codec_peek(struct snd_ali *codec,353 int secondary,354 unsigned short reg)355{356 unsigned int dwVal;357 unsigned int port;358 359 if (reg >= 0x80) {360 dev_err(codec->card->dev,361 "ali_codec_peek: reg(%xh) invalid.\n", reg);362 return ~0;363 }364 365 port = codec->chregs.regs.ac97read;366 367 if (snd_ali_codec_ready(codec, port) < 0)368 return ~0;369 if (snd_ali_stimer_ready(codec) < 0)370 return ~0;371 372 dwVal = (unsigned int) (reg & 0xff);373 dwVal |= 0x8000; /* bit 15*/374 if (secondary)375 dwVal |= 0x0080;376 377 snd_ali_5451_poke(codec, port, dwVal);378 379 if (snd_ali_stimer_ready(codec) < 0)380 return ~0;381 if (snd_ali_codec_ready(codec, port) < 0)382 return ~0;383 384 return (snd_ali_5451_peek(codec, port) & 0xffff0000) >> 16;385}386 387static void snd_ali_codec_write(struct snd_ac97 *ac97,388 unsigned short reg,389 unsigned short val )390{391 struct snd_ali *codec = ac97->private_data;392 393 dev_dbg(codec->card->dev, "codec_write: reg=%xh data=%xh.\n", reg, val);394 if (reg == AC97_GPIO_STATUS) {395 outl((val << ALI_AC97_GPIO_DATA_SHIFT) | ALI_AC97_GPIO_ENABLE,396 ALI_REG(codec, ALI_AC97_GPIO));397 return;398 }399 snd_ali_codec_poke(codec, ac97->num, reg, val);400 return ;401}402 403 404static unsigned short snd_ali_codec_read(struct snd_ac97 *ac97,405 unsigned short reg)406{407 struct snd_ali *codec = ac97->private_data;408 409 dev_dbg(codec->card->dev, "codec_read reg=%xh.\n", reg);410 return snd_ali_codec_peek(codec, ac97->num, reg);411}412 413/*414 * AC97 Reset415 */416 417static int snd_ali_reset_5451(struct snd_ali *codec)418{419 struct pci_dev *pci_dev;420 unsigned short wCount, wReg;421 unsigned int dwVal;422 423 pci_dev = codec->pci_m1533;424 if (pci_dev) {425 pci_read_config_dword(pci_dev, 0x7c, &dwVal);426 pci_write_config_dword(pci_dev, 0x7c, dwVal | 0x08000000);427 mdelay(5);428 pci_read_config_dword(pci_dev, 0x7c, &dwVal);429 pci_write_config_dword(pci_dev, 0x7c, dwVal & 0xf7ffffff);430 mdelay(5);431 }432 433 pci_dev = codec->pci;434 pci_read_config_dword(pci_dev, 0x44, &dwVal);435 pci_write_config_dword(pci_dev, 0x44, dwVal | 0x000c0000);436 udelay(500);437 pci_read_config_dword(pci_dev, 0x44, &dwVal);438 pci_write_config_dword(pci_dev, 0x44, dwVal & 0xfffbffff);439 mdelay(5);440 441 wCount = 200;442 while(wCount--) {443 wReg = snd_ali_codec_peek(codec, 0, AC97_POWERDOWN);444 if ((wReg & 0x000f) == 0x000f)445 return 0;446 mdelay(5);447 }448 449 /* non-fatal if you have a non PM capable codec */450 /* dev_warn(codec->card->dev, "ali5451: reset time out\n"); */451 return 0;452}453 454/*455 * ALI 5451 Controller456 */457 458static void snd_ali_enable_special_channel(struct snd_ali *codec,459 unsigned int channel)460{461 unsigned long dwVal;462 463 dwVal = inl(ALI_REG(codec, ALI_GLOBAL_CONTROL));464 dwVal |= 1 << (channel & 0x0000001f);465 outl(dwVal, ALI_REG(codec, ALI_GLOBAL_CONTROL));466}467 468static void snd_ali_disable_special_channel(struct snd_ali *codec,469 unsigned int channel)470{471 unsigned long dwVal;472 473 dwVal = inl(ALI_REG(codec, ALI_GLOBAL_CONTROL));474 dwVal &= ~(1 << (channel & 0x0000001f));475 outl(dwVal, ALI_REG(codec, ALI_GLOBAL_CONTROL));476}477 478static void snd_ali_enable_address_interrupt(struct snd_ali *codec)479{480 unsigned int gc;481 482 gc = inl(ALI_REG(codec, ALI_GC_CIR));483 gc |= ENDLP_IE;484 gc |= MIDLP_IE;485 outl( gc, ALI_REG(codec, ALI_GC_CIR));486}487 488static void snd_ali_disable_address_interrupt(struct snd_ali *codec)489{490 unsigned int gc;491 492 gc = inl(ALI_REG(codec, ALI_GC_CIR));493 gc &= ~ENDLP_IE;494 gc &= ~MIDLP_IE;495 outl(gc, ALI_REG(codec, ALI_GC_CIR));496}497 498static void snd_ali_disable_voice_irq(struct snd_ali *codec,499 unsigned int channel)500{501 unsigned int mask;502 struct snd_ali_channel_control *pchregs = &(codec->chregs);503 504 dev_dbg(codec->card->dev, "disable_voice_irq channel=%d\n", channel);505 506 mask = 1 << (channel & 0x1f);507 pchregs->data.ainten = inl(ALI_REG(codec, pchregs->regs.ainten));508 pchregs->data.ainten &= ~mask;509 outl(pchregs->data.ainten, ALI_REG(codec, pchregs->regs.ainten));510}511 512static int snd_ali_alloc_pcm_channel(struct snd_ali *codec, int channel)513{514 unsigned int idx = channel & 0x1f;515 516 if (codec->synth.chcnt >= ALI_CHANNELS){517 dev_err(codec->card->dev,518 "ali_alloc_pcm_channel: no free channels.\n");519 return -1;520 }521 522 if (!(codec->synth.chmap & (1 << idx))) {523 codec->synth.chmap |= 1 << idx;524 codec->synth.chcnt++;525 dev_dbg(codec->card->dev, "alloc_pcm_channel no. %d.\n", idx);526 return idx;527 }528 return -1;529}530 531static int snd_ali_find_free_channel(struct snd_ali * codec, int rec)532{533 int idx;534 int result = -1;535 536 dev_dbg(codec->card->dev,537 "find_free_channel: for %s\n", rec ? "rec" : "pcm");538 539 /* recording */540 if (rec) {541 if (codec->spdif_support &&542 (inl(ALI_REG(codec, ALI_GLOBAL_CONTROL)) &543 ALI_SPDIF_IN_SUPPORT))544 idx = ALI_SPDIF_IN_CHANNEL;545 else546 idx = ALI_PCM_IN_CHANNEL;547 548 result = snd_ali_alloc_pcm_channel(codec, idx);549 if (result >= 0)550 return result;551 else {552 dev_err(codec->card->dev,553 "ali_find_free_channel: record channel is busy now.\n");554 return -1;555 }556 }557 558 /* playback... */559 if (codec->spdif_support &&560 (inl(ALI_REG(codec, ALI_GLOBAL_CONTROL)) &561 ALI_SPDIF_OUT_CH_ENABLE)) {562 idx = ALI_SPDIF_OUT_CHANNEL;563 result = snd_ali_alloc_pcm_channel(codec, idx);564 if (result >= 0)565 return result;566 else567 dev_err(codec->card->dev,568 "ali_find_free_channel: S/PDIF out channel is in busy now.\n");569 }570 571 for (idx = 0; idx < ALI_CHANNELS; idx++) {572 result = snd_ali_alloc_pcm_channel(codec, idx);573 if (result >= 0)574 return result;575 }576 dev_err(codec->card->dev, "ali_find_free_channel: no free channels.\n");577 return -1;578}579 580static void snd_ali_free_channel_pcm(struct snd_ali *codec, int channel)581{582 unsigned int idx = channel & 0x0000001f;583 584 dev_dbg(codec->card->dev, "free_channel_pcm channel=%d\n", channel);585 586 if (channel < 0 || channel >= ALI_CHANNELS)587 return;588 589 if (!(codec->synth.chmap & (1 << idx))) {590 dev_err(codec->card->dev,591 "ali_free_channel_pcm: channel %d is not in use.\n",592 channel);593 return;594 } else {595 codec->synth.chmap &= ~(1 << idx);596 codec->synth.chcnt--;597 }598}599 600static void snd_ali_stop_voice(struct snd_ali *codec, unsigned int channel)601{602 unsigned int mask = 1 << (channel & 0x1f);603 604 dev_dbg(codec->card->dev, "stop_voice: channel=%d\n", channel);605 outl(mask, ALI_REG(codec, codec->chregs.regs.stop));606}607 608/*609 * S/PDIF Part610 */611 612static void snd_ali_delay(struct snd_ali *codec,int interval)613{614 unsigned long begintimer,currenttimer;615 616 begintimer = inl(ALI_REG(codec, ALI_STIMER));617 currenttimer = inl(ALI_REG(codec, ALI_STIMER));618 619 while (currenttimer < begintimer + interval) {620 if (snd_ali_stimer_ready(codec) < 0)621 break;622 currenttimer = inl(ALI_REG(codec, ALI_STIMER));623 cpu_relax();624 }625}626 627static void snd_ali_detect_spdif_rate(struct snd_ali *codec)628{629 u16 wval;630 u16 count = 0;631 u8 bval, R1 = 0, R2;632 633 bval = inb(ALI_REG(codec, ALI_SPDIF_CTRL + 1));634 bval |= 0x1F;635 outb(bval, ALI_REG(codec, ALI_SPDIF_CTRL + 1));636 637 while ((R1 < 0x0b || R1 > 0x0e) && R1 != 0x12 && count <= 50000) {638 count ++;639 snd_ali_delay(codec, 6);640 bval = inb(ALI_REG(codec, ALI_SPDIF_CTRL + 1));641 R1 = bval & 0x1F;642 }643 644 if (count > 50000) {645 dev_err(codec->card->dev, "ali_detect_spdif_rate: timeout!\n");646 return;647 }648 649 for (count = 0; count <= 50000; count++) {650 snd_ali_delay(codec, 6);651 bval = inb(ALI_REG(codec,ALI_SPDIF_CTRL + 1));652 R2 = bval & 0x1F;653 if (R2 != R1)654 R1 = R2;655 else656 break;657 }658 659 if (count > 50000) {660 dev_err(codec->card->dev, "ali_detect_spdif_rate: timeout!\n");661 return;662 }663 664 if (R2 >= 0x0b && R2 <= 0x0e) {665 wval = inw(ALI_REG(codec, ALI_SPDIF_CTRL + 2));666 wval &= 0xe0f0;667 wval |= (0x09 << 8) | 0x05;668 outw(wval, ALI_REG(codec, ALI_SPDIF_CTRL + 2));669 670 bval = inb(ALI_REG(codec, ALI_SPDIF_CS + 3)) & 0xf0;671 outb(bval | 0x02, ALI_REG(codec, ALI_SPDIF_CS + 3));672 } else if (R2 == 0x12) {673 wval = inw(ALI_REG(codec, ALI_SPDIF_CTRL + 2));674 wval &= 0xe0f0;675 wval |= (0x0e << 8) | 0x08;676 outw(wval, ALI_REG(codec, ALI_SPDIF_CTRL + 2));677 678 bval = inb(ALI_REG(codec,ALI_SPDIF_CS + 3)) & 0xf0;679 outb(bval | 0x03, ALI_REG(codec, ALI_SPDIF_CS + 3));680 }681}682 683static unsigned int snd_ali_get_spdif_in_rate(struct snd_ali *codec)684{685 u32 dwRate;686 u8 bval;687 688 bval = inb(ALI_REG(codec, ALI_SPDIF_CTRL));689 bval &= 0x7f;690 bval |= 0x40;691 outb(bval, ALI_REG(codec, ALI_SPDIF_CTRL));692 693 snd_ali_detect_spdif_rate(codec);694 695 bval = inb(ALI_REG(codec, ALI_SPDIF_CS + 3));696 bval &= 0x0f;697 698 switch (bval) {699 case 0: dwRate = 44100; break;700 case 1: dwRate = 48000; break;701 case 2: dwRate = 32000; break;702 default: dwRate = 0; break;703 }704 705 return dwRate;706}707 708static void snd_ali_enable_spdif_in(struct snd_ali *codec)709{ 710 unsigned int dwVal;711 712 dwVal = inl(ALI_REG(codec, ALI_GLOBAL_CONTROL));713 dwVal |= ALI_SPDIF_IN_SUPPORT;714 outl(dwVal, ALI_REG(codec, ALI_GLOBAL_CONTROL));715 716 dwVal = inb(ALI_REG(codec, ALI_SPDIF_CTRL));717 dwVal |= 0x02;718 outb(dwVal, ALI_REG(codec, ALI_SPDIF_CTRL));719 720 snd_ali_enable_special_channel(codec, ALI_SPDIF_IN_CHANNEL);721}722 723static void snd_ali_disable_spdif_in(struct snd_ali *codec)724{725 unsigned int dwVal;726 727 dwVal = inl(ALI_REG(codec, ALI_GLOBAL_CONTROL));728 dwVal &= ~ALI_SPDIF_IN_SUPPORT;729 outl(dwVal, ALI_REG(codec, ALI_GLOBAL_CONTROL));730 731 snd_ali_disable_special_channel(codec, ALI_SPDIF_IN_CHANNEL); 732}733 734 735static void snd_ali_set_spdif_out_rate(struct snd_ali *codec, unsigned int rate)736{737 unsigned char bVal;738 unsigned int dwRate;739 740 switch (rate) {741 case 32000: dwRate = 0x300; break;742 case 48000: dwRate = 0x200; break;743 default: dwRate = 0; break;744 }745 746 bVal = inb(ALI_REG(codec, ALI_SPDIF_CTRL));747 bVal &= (unsigned char)(~(1<<6));748 749 bVal |= 0x80; /* select right */750 outb(bVal, ALI_REG(codec, ALI_SPDIF_CTRL));751 outb(dwRate | 0x20, ALI_REG(codec, ALI_SPDIF_CS + 2));752 753 bVal &= ~0x80; /* select left */754 outb(bVal, ALI_REG(codec, ALI_SPDIF_CTRL));755 outw(rate | 0x10, ALI_REG(codec, ALI_SPDIF_CS + 2));756}757 758static void snd_ali_enable_spdif_out(struct snd_ali *codec)759{760 unsigned short wVal;761 unsigned char bVal;762 struct pci_dev *pci_dev;763 764 pci_dev = codec->pci_m1533;765 if (pci_dev == NULL)766 return;767 pci_read_config_byte(pci_dev, 0x61, &bVal);768 bVal |= 0x40;769 pci_write_config_byte(pci_dev, 0x61, bVal);770 pci_read_config_byte(pci_dev, 0x7d, &bVal);771 bVal |= 0x01;772 pci_write_config_byte(pci_dev, 0x7d, bVal);773 774 pci_read_config_byte(pci_dev, 0x7e, &bVal);775 bVal &= (~0x20);776 bVal |= 0x10;777 pci_write_config_byte(pci_dev, 0x7e, bVal);778 779 bVal = inb(ALI_REG(codec, ALI_SCTRL));780 outb(bVal | ALI_SPDIF_OUT_ENABLE, ALI_REG(codec, ALI_SCTRL));781 782 bVal = inb(ALI_REG(codec, ALI_SPDIF_CTRL));783 outb(bVal & ALI_SPDIF_OUT_CH_STATUS, ALI_REG(codec, ALI_SPDIF_CTRL));784 785 wVal = inw(ALI_REG(codec, ALI_GLOBAL_CONTROL));786 wVal |= ALI_SPDIF_OUT_SEL_PCM;787 outw(wVal, ALI_REG(codec, ALI_GLOBAL_CONTROL));788 snd_ali_disable_special_channel(codec, ALI_SPDIF_OUT_CHANNEL);789}790 791static void snd_ali_enable_spdif_chnout(struct snd_ali *codec)792{793 unsigned short wVal;794 795 wVal = inw(ALI_REG(codec, ALI_GLOBAL_CONTROL));796 wVal &= ~ALI_SPDIF_OUT_SEL_PCM;797 outw(wVal, ALI_REG(codec, ALI_GLOBAL_CONTROL));798/*799 wVal = inw(ALI_REG(codec, ALI_SPDIF_CS));800 if (flag & ALI_SPDIF_OUT_NON_PCM)801 wVal |= 0x0002;802 else 803 wVal &= (~0x0002);804 outw(wVal, ALI_REG(codec, ALI_SPDIF_CS));805*/806 snd_ali_enable_special_channel(codec, ALI_SPDIF_OUT_CHANNEL);807}808 809static void snd_ali_disable_spdif_chnout(struct snd_ali *codec)810{811 unsigned short wVal;812 813 wVal = inw(ALI_REG(codec, ALI_GLOBAL_CONTROL));814 wVal |= ALI_SPDIF_OUT_SEL_PCM;815 outw(wVal, ALI_REG(codec, ALI_GLOBAL_CONTROL));816 817 snd_ali_enable_special_channel(codec, ALI_SPDIF_OUT_CHANNEL);818}819 820static void snd_ali_disable_spdif_out(struct snd_ali *codec)821{822 unsigned char bVal;823 824 bVal = inb(ALI_REG(codec, ALI_SCTRL));825 outb(bVal & ~ALI_SPDIF_OUT_ENABLE, ALI_REG(codec, ALI_SCTRL));826 827 snd_ali_disable_spdif_chnout(codec);828}829 830static void snd_ali_update_ptr(struct snd_ali *codec, int channel)831{832 struct snd_ali_voice *pvoice;833 struct snd_ali_channel_control *pchregs;834 unsigned int old, mask;835 836 pchregs = &(codec->chregs);837 838 /* check if interrupt occurred for channel */839 old = pchregs->data.aint;840 mask = 1U << (channel & 0x1f);841 842 if (!(old & mask))843 return;844 845 pvoice = &codec->synth.voices[channel];846 847 udelay(100);848 spin_lock(&codec->reg_lock);849 850 if (pvoice->pcm && pvoice->substream) {851 /* pcm interrupt */852 if (pvoice->running) {853 dev_dbg(codec->card->dev,854 "update_ptr: cso=%4.4x cspf=%d.\n",855 inw(ALI_REG(codec, ALI_CSO_ALPHA_FMS + 2)),856 (inl(ALI_REG(codec, ALI_CSPF)) & mask) == mask);857 spin_unlock(&codec->reg_lock);858 snd_pcm_period_elapsed(pvoice->substream);859 spin_lock(&codec->reg_lock);860 } else {861 snd_ali_stop_voice(codec, channel);862 snd_ali_disable_voice_irq(codec, channel);863 } 864 } else if (codec->synth.voices[channel].synth) {865 /* synth interrupt */866 } else if (codec->synth.voices[channel].midi) {867 /* midi interrupt */868 } else {869 /* unknown interrupt */870 snd_ali_stop_voice(codec, channel);871 snd_ali_disable_voice_irq(codec, channel);872 }873 spin_unlock(&codec->reg_lock);874 outl(mask,ALI_REG(codec,pchregs->regs.aint));875 pchregs->data.aint = old & (~mask);876}877 878static irqreturn_t snd_ali_card_interrupt(int irq, void *dev_id)879{880 struct snd_ali *codec = dev_id;881 int channel;882 unsigned int audio_int;883 struct snd_ali_channel_control *pchregs;884 885 if (codec == NULL || !codec->hw_initialized)886 return IRQ_NONE;887 888 audio_int = inl(ALI_REG(codec, ALI_MISCINT));889 if (!audio_int)890 return IRQ_NONE;891 892 pchregs = &(codec->chregs);893 if (audio_int & ADDRESS_IRQ) {894 /* get interrupt status for all channels */895 pchregs->data.aint = inl(ALI_REG(codec, pchregs->regs.aint));896 for (channel = 0; channel < ALI_CHANNELS; channel++)897 snd_ali_update_ptr(codec, channel);898 }899 outl((TARGET_REACHED | MIXER_OVERFLOW | MIXER_UNDERFLOW),900 ALI_REG(codec, ALI_MISCINT));901 902 return IRQ_HANDLED;903}904 905 906static struct snd_ali_voice *snd_ali_alloc_voice(struct snd_ali * codec,907 int type, int rec, int channel)908{909 struct snd_ali_voice *pvoice;910 int idx;911 912 dev_dbg(codec->card->dev, "alloc_voice: type=%d rec=%d\n", type, rec);913 914 spin_lock_irq(&codec->voice_alloc);915 if (type == SNDRV_ALI_VOICE_TYPE_PCM) {916 idx = channel > 0 ? snd_ali_alloc_pcm_channel(codec, channel) :917 snd_ali_find_free_channel(codec,rec);918 if (idx < 0) {919 dev_err(codec->card->dev, "ali_alloc_voice: err.\n");920 spin_unlock_irq(&codec->voice_alloc);921 return NULL;922 }923 pvoice = &(codec->synth.voices[idx]);924 pvoice->codec = codec;925 pvoice->use = 1;926 pvoice->pcm = 1;927 pvoice->mode = rec;928 spin_unlock_irq(&codec->voice_alloc);929 return pvoice;930 }931 spin_unlock_irq(&codec->voice_alloc);932 return NULL;933}934 935 936static void snd_ali_free_voice(struct snd_ali * codec,937 struct snd_ali_voice *pvoice)938{939 void (*private_free)(void *);940 void *private_data;941 942 dev_dbg(codec->card->dev, "free_voice: channel=%d\n", pvoice->number);943 if (!pvoice->use)944 return;945 snd_ali_clear_voices(codec, pvoice->number, pvoice->number);946 spin_lock_irq(&codec->voice_alloc);947 private_free = pvoice->private_free;948 private_data = pvoice->private_data;949 pvoice->private_free = NULL;950 pvoice->private_data = NULL;951 if (pvoice->pcm)952 snd_ali_free_channel_pcm(codec, pvoice->number);953 pvoice->use = pvoice->pcm = pvoice->synth = 0;954 pvoice->substream = NULL;955 spin_unlock_irq(&codec->voice_alloc);956 if (private_free)957 private_free(private_data);958}959 960 961static void snd_ali_clear_voices(struct snd_ali *codec,962 unsigned int v_min,963 unsigned int v_max)964{965 unsigned int i;966 967 for (i = v_min; i <= v_max; i++) {968 snd_ali_stop_voice(codec, i);969 snd_ali_disable_voice_irq(codec, i);970 }971}972 973static void snd_ali_write_voice_regs(struct snd_ali *codec,974 unsigned int Channel,975 unsigned int LBA,976 unsigned int CSO,977 unsigned int ESO,978 unsigned int DELTA,979 unsigned int ALPHA_FMS,980 unsigned int GVSEL,981 unsigned int PAN,982 unsigned int VOL,983 unsigned int CTRL,984 unsigned int EC)985{986 unsigned int ctlcmds[4];987 988 outb((unsigned char)(Channel & 0x001f), ALI_REG(codec, ALI_GC_CIR));989 990 ctlcmds[0] = (CSO << 16) | (ALPHA_FMS & 0x0000ffff);991 ctlcmds[1] = LBA;992 ctlcmds[2] = (ESO << 16) | (DELTA & 0x0ffff);993 ctlcmds[3] = (GVSEL << 31) |994 ((PAN & 0x0000007f) << 24) |995 ((VOL & 0x000000ff) << 16) |996 ((CTRL & 0x0000000f) << 12) |997 (EC & 0x00000fff);998 999 outb(Channel, ALI_REG(codec, ALI_GC_CIR));1000 1001 outl(ctlcmds[0], ALI_REG(codec, ALI_CSO_ALPHA_FMS));1002 outl(ctlcmds[1], ALI_REG(codec, ALI_LBA));1003 outl(ctlcmds[2], ALI_REG(codec, ALI_ESO_DELTA));1004 outl(ctlcmds[3], ALI_REG(codec, ALI_GVSEL_PAN_VOC_CTRL_EC));1005 1006 outl(0x30000000, ALI_REG(codec, ALI_EBUF1)); /* Still Mode */1007 outl(0x30000000, ALI_REG(codec, ALI_EBUF2)); /* Still Mode */1008}1009 1010static unsigned int snd_ali_convert_rate(unsigned int rate, int rec)1011{1012 unsigned int delta;1013 1014 if (rate < 4000)1015 rate = 4000;1016 if (rate > 48000)1017 rate = 48000;1018 1019 if (rec) {1020 if (rate == 44100)1021 delta = 0x116a;1022 else if (rate == 8000)1023 delta = 0x6000;1024 else if (rate == 48000)1025 delta = 0x1000;1026 else1027 delta = ((48000 << 12) / rate) & 0x0000ffff;1028 } else {1029 if (rate == 44100)1030 delta = 0xeb3;1031 else if (rate == 8000)1032 delta = 0x2ab;1033 else if (rate == 48000)1034 delta = 0x1000;1035 else 1036 delta = (((rate << 12) + rate) / 48000) & 0x0000ffff;1037 }1038 1039 return delta;1040}1041 1042static unsigned int snd_ali_control_mode(struct snd_pcm_substream *substream)1043{1044 unsigned int CTRL;1045 struct snd_pcm_runtime *runtime = substream->runtime;1046 1047 /* set ctrl mode1048 CTRL default: 8-bit (unsigned) mono, loop mode enabled1049 */1050 CTRL = 0x00000001;1051 if (snd_pcm_format_width(runtime->format) == 16)1052 CTRL |= 0x00000008; /* 16-bit data */1053 if (!snd_pcm_format_unsigned(runtime->format))1054 CTRL |= 0x00000002; /* signed data */1055 if (runtime->channels > 1)1056 CTRL |= 0x00000004; /* stereo data */1057 return CTRL;1058}1059 1060/*1061 * PCM part1062 */1063 1064static int snd_ali_trigger(struct snd_pcm_substream *substream,1065 int cmd)1066 1067{1068 struct snd_ali *codec = snd_pcm_substream_chip(substream);1069 struct snd_pcm_substream *s;1070 unsigned int what, whati;1071 struct snd_ali_voice *pvoice, *evoice;1072 unsigned int val;1073 int do_start;1074 1075 switch (cmd) {1076 case SNDRV_PCM_TRIGGER_START:1077 case SNDRV_PCM_TRIGGER_RESUME:1078 do_start = 1;1079 break;1080 case SNDRV_PCM_TRIGGER_STOP:1081 case SNDRV_PCM_TRIGGER_SUSPEND:1082 do_start = 0;1083 break;1084 default:1085 return -EINVAL;1086 }1087 1088 what = whati = 0;1089 snd_pcm_group_for_each_entry(s, substream) {1090 if ((struct snd_ali *) snd_pcm_substream_chip(s) == codec) {1091 pvoice = s->runtime->private_data;1092 evoice = pvoice->extra;1093 what |= 1 << (pvoice->number & 0x1f);1094 if (evoice == NULL)1095 whati |= 1 << (pvoice->number & 0x1f);1096 else {1097 whati |= 1 << (evoice->number & 0x1f);1098 what |= 1 << (evoice->number & 0x1f);1099 }1100 if (do_start) {1101 pvoice->running = 1;1102 if (evoice != NULL)1103 evoice->running = 1;1104 } else {1105 pvoice->running = 0;1106 if (evoice != NULL)1107 evoice->running = 0;1108 }1109 snd_pcm_trigger_done(s, substream);1110 }1111 }1112 spin_lock(&codec->reg_lock);1113 if (!do_start)1114 outl(what, ALI_REG(codec, ALI_STOP));1115 val = inl(ALI_REG(codec, ALI_AINTEN));1116 if (do_start)1117 val |= whati;1118 else1119 val &= ~whati;1120 outl(val, ALI_REG(codec, ALI_AINTEN));1121 if (do_start)1122 outl(what, ALI_REG(codec, ALI_START));1123 dev_dbg(codec->card->dev, "trigger: what=%xh whati=%xh\n", what, whati);1124 spin_unlock(&codec->reg_lock);1125 1126 return 0;1127}1128 1129static int snd_ali_playback_hw_params(struct snd_pcm_substream *substream,1130 struct snd_pcm_hw_params *hw_params)1131{1132 struct snd_ali *codec = snd_pcm_substream_chip(substream);1133 struct snd_pcm_runtime *runtime = substream->runtime;1134 struct snd_ali_voice *pvoice = runtime->private_data;1135 struct snd_ali_voice *evoice = pvoice->extra;1136 1137 /* voice management */1138 1139 if (params_buffer_size(hw_params) / 2 !=1140 params_period_size(hw_params)) {1141 if (!evoice) {1142 evoice = snd_ali_alloc_voice(codec,1143 SNDRV_ALI_VOICE_TYPE_PCM,1144 0, -1);1145 if (!evoice)1146 return -ENOMEM;1147 pvoice->extra = evoice;1148 evoice->substream = substream;1149 }1150 } else {1151 if (evoice) {1152 snd_ali_free_voice(codec, evoice);1153 pvoice->extra = evoice = NULL;1154 }1155 }1156 1157 return 0;1158}1159 1160static int snd_ali_playback_hw_free(struct snd_pcm_substream *substream)1161{1162 struct snd_ali *codec = snd_pcm_substream_chip(substream);1163 struct snd_pcm_runtime *runtime = substream->runtime;1164 struct snd_ali_voice *pvoice = runtime->private_data;1165 struct snd_ali_voice *evoice = pvoice ? pvoice->extra : NULL;1166 1167 if (evoice) {1168 snd_ali_free_voice(codec, evoice);1169 pvoice->extra = NULL;1170 }1171 return 0;1172}1173 1174static int snd_ali_playback_prepare(struct snd_pcm_substream *substream)1175{1176 struct snd_ali *codec = snd_pcm_substream_chip(substream);1177 struct snd_pcm_runtime *runtime = substream->runtime;1178 struct snd_ali_voice *pvoice = runtime->private_data;1179 struct snd_ali_voice *evoice = pvoice->extra;1180 1181 unsigned int LBA;1182 unsigned int Delta;1183 unsigned int ESO;1184 unsigned int CTRL;1185 unsigned int GVSEL;1186 unsigned int PAN;1187 unsigned int VOL;1188 unsigned int EC;1189 1190 dev_dbg(codec->card->dev, "playback_prepare ...\n");1191 1192 spin_lock_irq(&codec->reg_lock); 1193 1194 /* set Delta (rate) value */1195 Delta = snd_ali_convert_rate(runtime->rate, 0);1196 1197 if (pvoice->number == ALI_SPDIF_IN_CHANNEL || 1198 pvoice->number == ALI_PCM_IN_CHANNEL)1199 snd_ali_disable_special_channel(codec, pvoice->number);1200 else if (codec->spdif_support &&1201 (inl(ALI_REG(codec, ALI_GLOBAL_CONTROL)) &1202 ALI_SPDIF_OUT_CH_ENABLE)1203 && pvoice->number == ALI_SPDIF_OUT_CHANNEL) {1204 snd_ali_set_spdif_out_rate(codec, runtime->rate);1205 Delta = 0x1000;1206 }1207 1208 /* set Loop Back Address */1209 LBA = runtime->dma_addr;1210 1211 /* set interrupt count size */1212 pvoice->count = runtime->period_size;1213 1214 /* set target ESO for channel */1215 pvoice->eso = runtime->buffer_size; 1216 1217 dev_dbg(codec->card->dev, "playback_prepare: eso=%xh count=%xh\n",1218 pvoice->eso, pvoice->count);1219 1220 /* set ESO to capture first MIDLP interrupt */1221 ESO = pvoice->eso -1;1222 /* set ctrl mode */1223 CTRL = snd_ali_control_mode(substream);1224 1225 GVSEL = 1;1226 PAN = 0;1227 VOL = 0;1228 EC = 0;1229 dev_dbg(codec->card->dev, "playback_prepare:\n");1230 dev_dbg(codec->card->dev,1231 "ch=%d, Rate=%d Delta=%xh,GVSEL=%xh,PAN=%xh,CTRL=%xh\n",1232 pvoice->number,runtime->rate,Delta,GVSEL,PAN,CTRL);1233 snd_ali_write_voice_regs(codec,1234 pvoice->number,1235 LBA,1236 0, /* cso */1237 ESO,1238 Delta,1239 0, /* alpha */1240 GVSEL,1241 PAN,1242 VOL,1243 CTRL,1244 EC);1245 if (evoice) {1246 evoice->count = pvoice->count;1247 evoice->eso = pvoice->count << 1;1248 ESO = evoice->eso - 1;1249 snd_ali_write_voice_regs(codec,1250 evoice->number,1251 LBA,1252 0, /* cso */1253 ESO,1254 Delta,1255 0, /* alpha */1256 GVSEL,1257 0x7f,1258 0x3ff,1259 CTRL,1260 EC);1261 }1262 spin_unlock_irq(&codec->reg_lock);1263 return 0;1264}1265 1266 1267static int snd_ali_prepare(struct snd_pcm_substream *substream)1268{1269 struct snd_ali *codec = snd_pcm_substream_chip(substream);1270 struct snd_pcm_runtime *runtime = substream->runtime;1271 struct snd_ali_voice *pvoice = runtime->private_data;1272 unsigned int LBA;1273 unsigned int Delta;1274 unsigned int ESO;1275 unsigned int CTRL;1276 unsigned int GVSEL;1277 unsigned int PAN;1278 unsigned int VOL;1279 unsigned int EC;1280 u8 bValue;1281 1282 spin_lock_irq(&codec->reg_lock);1283 1284 dev_dbg(codec->card->dev, "ali_prepare...\n");1285 1286 snd_ali_enable_special_channel(codec,pvoice->number);1287 1288 Delta = (pvoice->number == ALI_MODEM_IN_CHANNEL ||1289 pvoice->number == ALI_MODEM_OUT_CHANNEL) ? 1290 0x1000 : snd_ali_convert_rate(runtime->rate, pvoice->mode);1291 1292 /* Prepare capture intr channel */1293 if (pvoice->number == ALI_SPDIF_IN_CHANNEL) {1294 1295 unsigned int rate;1296 1297 spin_unlock_irq(&codec->reg_lock);1298 if (codec->revision != ALI_5451_V02)1299 return -1;1300 1301 rate = snd_ali_get_spdif_in_rate(codec);1302 if (rate == 0) {1303 dev_warn(codec->card->dev,1304 "ali_capture_prepare: spdif rate detect err!\n");1305 rate = 48000;1306 }1307 spin_lock_irq(&codec->reg_lock);1308 bValue = inb(ALI_REG(codec,ALI_SPDIF_CTRL));1309 if (bValue & 0x10) {1310 outb(bValue,ALI_REG(codec,ALI_SPDIF_CTRL));1311 dev_warn(codec->card->dev,1312 "clear SPDIF parity error flag.\n");1313 }1314 1315 if (rate != 48000)1316 Delta = ((rate << 12) / runtime->rate) & 0x00ffff;1317 }1318 1319 /* set target ESO for channel */1320 pvoice->eso = runtime->buffer_size; 1321 1322 /* set interrupt count size */1323 pvoice->count = runtime->period_size;1324 1325 /* set Loop Back Address */1326 LBA = runtime->dma_addr;1327 1328 /* set ESO to capture first MIDLP interrupt */1329 ESO = pvoice->eso - 1;1330 CTRL = snd_ali_control_mode(substream);1331 GVSEL = 0;1332 PAN = 0x00;1333 VOL = 0x00;1334 EC = 0;1335 1336 snd_ali_write_voice_regs( codec,1337 pvoice->number,1338 LBA,1339 0, /* cso */1340 ESO,1341 Delta,1342 0, /* alpha */1343 GVSEL,1344 PAN,1345 VOL,1346 CTRL,1347 EC);1348 1349 spin_unlock_irq(&codec->reg_lock);1350 1351 return 0;1352}1353 1354 1355static snd_pcm_uframes_t1356snd_ali_playback_pointer(struct snd_pcm_substream *substream)1357{1358 struct snd_ali *codec = snd_pcm_substream_chip(substream);1359 struct snd_pcm_runtime *runtime = substream->runtime;1360 struct snd_ali_voice *pvoice = runtime->private_data;1361 unsigned int cso;1362 1363 spin_lock(&codec->reg_lock);1364 if (!pvoice->running) {1365 spin_unlock(&codec->reg_lock);1366 return 0;1367 }1368 outb(pvoice->number, ALI_REG(codec, ALI_GC_CIR));1369 cso = inw(ALI_REG(codec, ALI_CSO_ALPHA_FMS + 2));1370 spin_unlock(&codec->reg_lock);1371 dev_dbg(codec->card->dev, "playback pointer returned cso=%xh.\n", cso);1372 1373 cso %= runtime->buffer_size;1374 return cso;1375}1376 1377 1378static snd_pcm_uframes_t snd_ali_pointer(struct snd_pcm_substream *substream)1379{1380 struct snd_ali *codec = snd_pcm_substream_chip(substream);1381 struct snd_pcm_runtime *runtime = substream->runtime;1382 struct snd_ali_voice *pvoice = runtime->private_data;1383 unsigned int cso;1384 1385 spin_lock(&codec->reg_lock);1386 if (!pvoice->running) {1387 spin_unlock(&codec->reg_lock);1388 return 0;1389 }1390 outb(pvoice->number, ALI_REG(codec, ALI_GC_CIR));1391 cso = inw(ALI_REG(codec, ALI_CSO_ALPHA_FMS + 2));1392 spin_unlock(&codec->reg_lock);1393 1394 cso %= runtime->buffer_size;1395 return cso;1396}1397 1398static const struct snd_pcm_hardware snd_ali_playback =1399{1400 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |1401 SNDRV_PCM_INFO_BLOCK_TRANSFER |1402 SNDRV_PCM_INFO_MMAP_VALID |1403 SNDRV_PCM_INFO_RESUME |1404 SNDRV_PCM_INFO_SYNC_START),1405 .formats = (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE |1406 SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U16_LE),1407 .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,1408 .rate_min = 4000,1409 .rate_max = 48000,1410 .channels_min = 1,1411 .channels_max = 2,1412 .buffer_bytes_max = (256*1024),1413 .period_bytes_min = 64,1414 .period_bytes_max = (256*1024),1415 .periods_min = 1,1416 .periods_max = 1024,1417 .fifo_size = 0,1418};1419 1420/*1421 * Capture support device description1422 */1423 1424static const struct snd_pcm_hardware snd_ali_capture =1425{1426 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |1427 SNDRV_PCM_INFO_BLOCK_TRANSFER |1428 SNDRV_PCM_INFO_MMAP_VALID |1429 SNDRV_PCM_INFO_RESUME |1430 SNDRV_PCM_INFO_SYNC_START),1431 .formats = (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE |1432 SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U16_LE),1433 .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,1434 .rate_min = 4000,1435 .rate_max = 48000,1436 .channels_min = 1,1437 .channels_max = 2,1438 .buffer_bytes_max = (128*1024),1439 .period_bytes_min = 64,1440 .period_bytes_max = (128*1024),1441 .periods_min = 1,1442 .periods_max = 1024,1443 .fifo_size = 0,1444};1445 1446static void snd_ali_pcm_free_substream(struct snd_pcm_runtime *runtime)1447{1448 struct snd_ali_voice *pvoice = runtime->private_data;1449 1450 if (pvoice)1451 snd_ali_free_voice(pvoice->codec, pvoice);1452}1453 1454static int snd_ali_open(struct snd_pcm_substream *substream, int rec,1455 int channel, const struct snd_pcm_hardware *phw)1456{1457 struct snd_ali *codec = snd_pcm_substream_chip(substream);1458 struct snd_pcm_runtime *runtime = substream->runtime;1459 struct snd_ali_voice *pvoice;1460 1461 pvoice = snd_ali_alloc_voice(codec, SNDRV_ALI_VOICE_TYPE_PCM, rec,1462 channel);1463 if (!pvoice)1464 return -EAGAIN;1465 1466 pvoice->substream = substream;1467 runtime->private_data = pvoice;1468 runtime->private_free = snd_ali_pcm_free_substream;1469 1470 runtime->hw = *phw;1471 snd_pcm_set_sync(substream);1472 snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE,1473 0, 64*1024);1474 return 0;1475}1476 1477static int snd_ali_playback_open(struct snd_pcm_substream *substream)1478{1479 return snd_ali_open(substream, 0, -1, &snd_ali_playback);1480}1481 1482static int snd_ali_capture_open(struct snd_pcm_substream *substream)1483{1484 return snd_ali_open(substream, 1, -1, &snd_ali_capture);1485}1486 1487static int snd_ali_playback_close(struct snd_pcm_substream *substream)1488{1489 return 0;1490}1491 1492static int snd_ali_close(struct snd_pcm_substream *substream)1493{1494 struct snd_ali *codec = snd_pcm_substream_chip(substream);1495 struct snd_ali_voice *pvoice = substream->runtime->private_data;1496 1497 snd_ali_disable_special_channel(codec,pvoice->number);1498 1499 return 0;1500}1501 1502static const struct snd_pcm_ops snd_ali_playback_ops = {1503 .open = snd_ali_playback_open,1504 .close = snd_ali_playback_close,1505 .hw_params = snd_ali_playback_hw_params,1506 .hw_free = snd_ali_playback_hw_free,1507 .prepare = snd_ali_playback_prepare,1508 .trigger = snd_ali_trigger,1509 .pointer = snd_ali_playback_pointer,1510};1511 1512static const struct snd_pcm_ops snd_ali_capture_ops = {1513 .open = snd_ali_capture_open,1514 .close = snd_ali_close,1515 .prepare = snd_ali_prepare,1516 .trigger = snd_ali_trigger,1517 .pointer = snd_ali_pointer,1518};1519 1520/*1521 * Modem PCM1522 */1523 1524static int snd_ali_modem_hw_params(struct snd_pcm_substream *substream,1525 struct snd_pcm_hw_params *hw_params)1526{1527 struct snd_ali *chip = snd_pcm_substream_chip(substream);1528 unsigned int modem_num = chip->num_of_codecs - 1;1529 snd_ac97_write(chip->ac97[modem_num], AC97_LINE1_RATE,1530 params_rate(hw_params));1531 snd_ac97_write(chip->ac97[modem_num], AC97_LINE1_LEVEL, 0);1532 return 0;1533}1534 1535static const struct snd_pcm_hardware snd_ali_modem =1536{1537 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |1538 SNDRV_PCM_INFO_BLOCK_TRANSFER |1539 SNDRV_PCM_INFO_MMAP_VALID |1540 SNDRV_PCM_INFO_RESUME |1541 SNDRV_PCM_INFO_SYNC_START),1542 .formats = SNDRV_PCM_FMTBIT_S16_LE,1543 .rates = (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000 |1544 SNDRV_PCM_RATE_16000),1545 .rate_min = 8000,1546 .rate_max = 16000,1547 .channels_min = 1,1548 .channels_max = 1,1549 .buffer_bytes_max = (256*1024),1550 .period_bytes_min = 64,1551 .period_bytes_max = (256*1024),1552 .periods_min = 1,1553 .periods_max = 1024,1554 .fifo_size = 0,1555};1556 1557static int snd_ali_modem_open(struct snd_pcm_substream *substream, int rec,1558 int channel)1559{1560 static const unsigned int rates[] = {8000, 9600, 12000, 16000};1561 static const struct snd_pcm_hw_constraint_list hw_constraint_rates = {1562 .count = ARRAY_SIZE(rates),1563 .list = rates,1564 .mask = 0,1565 };1566 int err = snd_ali_open(substream, rec, channel, &snd_ali_modem);1567 1568 if (err)1569 return err;1570 return snd_pcm_hw_constraint_list(substream->runtime, 0,1571 SNDRV_PCM_HW_PARAM_RATE, &hw_constraint_rates);1572}1573 1574static int snd_ali_modem_playback_open(struct snd_pcm_substream *substream)1575{1576 return snd_ali_modem_open(substream, 0, ALI_MODEM_OUT_CHANNEL);1577}1578 1579static int snd_ali_modem_capture_open(struct snd_pcm_substream *substream)1580{1581 return snd_ali_modem_open(substream, 1, ALI_MODEM_IN_CHANNEL);1582}1583 1584static const struct snd_pcm_ops snd_ali_modem_playback_ops = {1585 .open = snd_ali_modem_playback_open,1586 .close = snd_ali_close,1587 .hw_params = snd_ali_modem_hw_params,1588 .prepare = snd_ali_prepare,1589 .trigger = snd_ali_trigger,1590 .pointer = snd_ali_pointer,1591};1592 1593static const struct snd_pcm_ops snd_ali_modem_capture_ops = {1594 .open = snd_ali_modem_capture_open,1595 .close = snd_ali_close,1596 .hw_params = snd_ali_modem_hw_params,1597 .prepare = snd_ali_prepare,1598 .trigger = snd_ali_trigger,1599 .pointer = snd_ali_pointer,1600};1601 1602 1603struct ali_pcm_description {1604 char *name;1605 unsigned int playback_num;1606 unsigned int capture_num;1607 const struct snd_pcm_ops *playback_ops;1608 const struct snd_pcm_ops *capture_ops;1609 unsigned short class;1610};1611 1612 1613static void snd_ali_pcm_free(struct snd_pcm *pcm)1614{1615 struct snd_ali *codec = pcm->private_data;1616 codec->pcm[pcm->device] = NULL;1617}1618 1619 1620static int snd_ali_pcm(struct snd_ali *codec, int device,1621 struct ali_pcm_description *desc)1622{1623 struct snd_pcm *pcm;1624 int err;1625 1626 err = snd_pcm_new(codec->card, desc->name, device,1627 desc->playback_num, desc->capture_num, &pcm);1628 if (err < 0) {1629 dev_err(codec->card->dev,1630 "snd_ali_pcm: err called snd_pcm_new.\n");1631 return err;1632 }1633 pcm->private_data = codec;1634 pcm->private_free = snd_ali_pcm_free;1635 if (desc->playback_ops)1636 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,1637 desc->playback_ops);1638 if (desc->capture_ops)1639 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,1640 desc->capture_ops);1641 1642 snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,1643 &codec->pci->dev, 64*1024, 128*1024);1644 1645 pcm->info_flags = 0;1646 pcm->dev_class = desc->class;1647 pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;1648 strcpy(pcm->name, desc->name);1649 codec->pcm[0] = pcm;1650 return 0;1651}1652 1653static struct ali_pcm_description ali_pcms[] = {1654 { .name = "ALI 5451",1655 .playback_num = ALI_CHANNELS,1656 .capture_num = 1,1657 .playback_ops = &snd_ali_playback_ops,1658 .capture_ops = &snd_ali_capture_ops1659 },1660 { .name = "ALI 5451 modem",1661 .playback_num = 1,1662 .capture_num = 1,1663 .playback_ops = &snd_ali_modem_playback_ops,1664 .capture_ops = &snd_ali_modem_capture_ops,1665 .class = SNDRV_PCM_CLASS_MODEM1666 }1667};1668 1669static int snd_ali_build_pcms(struct snd_ali *codec)1670{1671 int i, err;1672 for (i = 0; i < codec->num_of_codecs && i < ARRAY_SIZE(ali_pcms); i++) {1673 err = snd_ali_pcm(codec, i, &ali_pcms[i]);1674 if (err < 0)1675 return err;1676 }1677 return 0;1678}1679 1680 1681#define ALI5451_SPDIF(xname, xindex, value) \1682{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\1683.info = snd_ali5451_spdif_info, .get = snd_ali5451_spdif_get, \1684.put = snd_ali5451_spdif_put, .private_value = value}1685 1686#define snd_ali5451_spdif_info snd_ctl_boolean_mono_info1687 1688static int snd_ali5451_spdif_get(struct snd_kcontrol *kcontrol,1689 struct snd_ctl_elem_value *ucontrol)1690{1691 struct snd_ali *codec = kcontrol->private_data;1692 unsigned int spdif_enable;1693 1694 spdif_enable = ucontrol->value.integer.value[0] ? 1 : 0;1695 1696 spin_lock_irq(&codec->reg_lock);1697 switch (kcontrol->private_value) {1698 case 0:1699 spdif_enable = (codec->spdif_mask & 0x02) ? 1 : 0;1700 break;1701 case 1:1702 spdif_enable = ((codec->spdif_mask & 0x02) &&1703 (codec->spdif_mask & 0x04)) ? 1 : 0;1704 break;1705 case 2:1706 spdif_enable = (codec->spdif_mask & 0x01) ? 1 : 0;1707 break;1708 default:1709 break;1710 }1711 ucontrol->value.integer.value[0] = spdif_enable;1712 spin_unlock_irq(&codec->reg_lock);1713 return 0;1714}1715 1716static int snd_ali5451_spdif_put(struct snd_kcontrol *kcontrol,1717 struct snd_ctl_elem_value *ucontrol)1718{1719 struct snd_ali *codec = kcontrol->private_data;1720 unsigned int change = 0, spdif_enable = 0;1721 1722 spdif_enable = ucontrol->value.integer.value[0] ? 1 : 0;1723 1724 spin_lock_irq(&codec->reg_lock);1725 switch (kcontrol->private_value) {1726 case 0:1727 change = (codec->spdif_mask & 0x02) ? 1 : 0;1728 change = change ^ spdif_enable;1729 if (change) {1730 if (spdif_enable) {1731 codec->spdif_mask |= 0x02;1732 snd_ali_enable_spdif_out(codec);1733 } else {1734 codec->spdif_mask &= ~(0x02);1735 codec->spdif_mask &= ~(0x04);1736 snd_ali_disable_spdif_out(codec);1737 }1738 }1739 break;1740 case 1: 1741 change = (codec->spdif_mask & 0x04) ? 1 : 0;1742 change = change ^ spdif_enable;1743 if (change && (codec->spdif_mask & 0x02)) {1744 if (spdif_enable) {1745 codec->spdif_mask |= 0x04;1746 snd_ali_enable_spdif_chnout(codec);1747 } else {1748 codec->spdif_mask &= ~(0x04);1749 snd_ali_disable_spdif_chnout(codec);1750 }1751 }1752 break;1753 case 2:1754 change = (codec->spdif_mask & 0x01) ? 1 : 0;1755 change = change ^ spdif_enable;1756 if (change) {1757 if (spdif_enable) {1758 codec->spdif_mask |= 0x01;1759 snd_ali_enable_spdif_in(codec);1760 } else {1761 codec->spdif_mask &= ~(0x01);1762 snd_ali_disable_spdif_in(codec);1763 }1764 }1765 break;1766 default:1767 break;1768 }1769 spin_unlock_irq(&codec->reg_lock);1770 1771 return change;1772}1773 1774static const struct snd_kcontrol_new snd_ali5451_mixer_spdif[] = {1775 /* spdif aplayback switch */1776 /* FIXME: "IEC958 Playback Switch" may conflict with one on ac97_codec */1777 ALI5451_SPDIF(SNDRV_CTL_NAME_IEC958("Output ",NONE,SWITCH), 0, 0),1778 /* spdif out to spdif channel */1779 ALI5451_SPDIF(SNDRV_CTL_NAME_IEC958("Channel Output ",NONE,SWITCH), 0, 1),1780 /* spdif in from spdif channel */1781 ALI5451_SPDIF(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), 0, 2)1782};1783 1784static int snd_ali_mixer(struct snd_ali *codec)1785{1786 struct snd_ac97_template ac97;1787 unsigned int idx;1788 int i, err;1789 static const struct snd_ac97_bus_ops ops = {1790 .write = snd_ali_codec_write,1791 .read = snd_ali_codec_read,1792 };1793 1794 err = snd_ac97_bus(codec->card, 0, &ops, codec, &codec->ac97_bus);1795 if (err < 0)1796 return err;1797 1798 memset(&ac97, 0, sizeof(ac97));1799 ac97.private_data = codec;1800 1801 for (i = 0; i < codec->num_of_codecs; i++) {1802 ac97.num = i;1803 err = snd_ac97_mixer(codec->ac97_bus, &ac97, &codec->ac97[i]);1804 if (err < 0) {1805 dev_err(codec->card->dev,1806 "ali mixer %d creating error.\n", i);1807 if (i == 0)1808 return err;1809 codec->num_of_codecs = 1;1810 break;1811 }1812 }1813 1814 if (codec->spdif_support) {1815 for (idx = 0; idx < ARRAY_SIZE(snd_ali5451_mixer_spdif); idx++) {1816 err = snd_ctl_add(codec->card,1817 snd_ctl_new1(&snd_ali5451_mixer_spdif[idx], codec));1818 if (err < 0)1819 return err;1820 }1821 }1822 return 0;1823}1824 1825static int ali_suspend(struct device *dev)1826{1827 struct snd_card *card = dev_get_drvdata(dev);1828 struct snd_ali *chip = card->private_data;1829 struct snd_ali_image *im = &chip->image;1830 int i, j;1831 1832 snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);1833 for (i = 0; i < chip->num_of_codecs; i++)1834 snd_ac97_suspend(chip->ac97[i]);1835 1836 spin_lock_irq(&chip->reg_lock);1837 1838 im->regs[ALI_MISCINT >> 2] = inl(ALI_REG(chip, ALI_MISCINT));1839 /* im->regs[ALI_START >> 2] = inl(ALI_REG(chip, ALI_START)); */1840 im->regs[ALI_STOP >> 2] = inl(ALI_REG(chip, ALI_STOP));1841 1842 /* disable all IRQ bits */1843 outl(0, ALI_REG(chip, ALI_MISCINT));1844 1845 for (i = 0; i < ALI_GLOBAL_REGS; i++) { 1846 if ((i*4 == ALI_MISCINT) || (i*4 == ALI_STOP))1847 continue;1848 im->regs[i] = inl(ALI_REG(chip, i*4));1849 }1850 1851 for (i = 0; i < ALI_CHANNELS; i++) {1852 outb(i, ALI_REG(chip, ALI_GC_CIR));1853 for (j = 0; j < ALI_CHANNEL_REGS; j++) 1854 im->channel_regs[i][j] = inl(ALI_REG(chip, j*4 + 0xe0));1855 }1856 1857 /* stop all HW channel */1858 outl(0xffffffff, ALI_REG(chip, ALI_STOP));1859 1860 spin_unlock_irq(&chip->reg_lock);1861 return 0;1862}1863 1864static int ali_resume(struct device *dev)1865{1866 struct snd_card *card = dev_get_drvdata(dev);1867 struct snd_ali *chip = card->private_data;1868 struct snd_ali_image *im = &chip->image;1869 int i, j;1870 1871 spin_lock_irq(&chip->reg_lock);1872 1873 for (i = 0; i < ALI_CHANNELS; i++) {1874 outb(i, ALI_REG(chip, ALI_GC_CIR));1875 for (j = 0; j < ALI_CHANNEL_REGS; j++) 1876 outl(im->channel_regs[i][j], ALI_REG(chip, j*4 + 0xe0));1877 }1878 1879 for (i = 0; i < ALI_GLOBAL_REGS; i++) { 1880 if ((i*4 == ALI_MISCINT) || (i*4 == ALI_STOP) ||1881 (i*4 == ALI_START))1882 continue;1883 outl(im->regs[i], ALI_REG(chip, i*4));1884 }1885 1886 /* start HW channel */1887 outl(im->regs[ALI_START >> 2], ALI_REG(chip, ALI_START));1888 /* restore IRQ enable bits */1889 outl(im->regs[ALI_MISCINT >> 2], ALI_REG(chip, ALI_MISCINT));1890 1891 spin_unlock_irq(&chip->reg_lock);1892 1893 for (i = 0 ; i < chip->num_of_codecs; i++)1894 snd_ac97_resume(chip->ac97[i]);1895 1896 snd_power_change_state(card, SNDRV_CTL_POWER_D0);1897 return 0;1898}1899 1900static DEFINE_SIMPLE_DEV_PM_OPS(ali_pm, ali_suspend, ali_resume);1901 1902static void snd_ali_free(struct snd_card *card)1903{1904 struct snd_ali *codec = card->private_data;1905 1906 if (codec->hw_initialized)1907 snd_ali_disable_address_interrupt(codec);1908 pci_dev_put(codec->pci_m1533);1909 pci_dev_put(codec->pci_m7101);1910}1911 1912static int snd_ali_chip_init(struct snd_ali *codec)1913{1914 unsigned int legacy;1915 unsigned char temp;1916 struct pci_dev *pci_dev;1917 1918 dev_dbg(codec->card->dev, "chip initializing ...\n");1919 1920 if (snd_ali_reset_5451(codec)) {1921 dev_err(codec->card->dev, "ali_chip_init: reset 5451 error.\n");1922 return -1;1923 }1924 1925 if (codec->revision == ALI_5451_V02) {1926 pci_dev = codec->pci_m1533;1927 pci_read_config_byte(pci_dev, 0x59, &temp);1928 temp |= 0x80;1929 pci_write_config_byte(pci_dev, 0x59, temp);1930 1931 pci_dev = codec->pci_m7101;1932 pci_read_config_byte(pci_dev, 0xb8, &temp);1933 temp |= 0x20;1934 pci_write_config_byte(pci_dev, 0xB8, temp);1935 }1936 1937 pci_read_config_dword(codec->pci, 0x44, &legacy);1938 legacy &= 0xff00ff00;1939 legacy |= 0x000800aa;1940 pci_write_config_dword(codec->pci, 0x44, legacy);1941 1942 outl(0x80000001, ALI_REG(codec, ALI_GLOBAL_CONTROL));1943 outl(0x00000000, ALI_REG(codec, ALI_AINTEN));1944 outl(0xffffffff, ALI_REG(codec, ALI_AINT));1945 outl(0x00000000, ALI_REG(codec, ALI_VOLUME));1946 outb(0x10, ALI_REG(codec, ALI_MPUR2));1947 1948 codec->ac97_ext_id = snd_ali_codec_peek(codec, 0, AC97_EXTENDED_ID);1949 codec->ac97_ext_status = snd_ali_codec_peek(codec, 0,1950 AC97_EXTENDED_STATUS);1951 if (codec->spdif_support) {1952 snd_ali_enable_spdif_out(codec);1953 codec->spdif_mask = 0x00000002;1954 }1955 1956 codec->num_of_codecs = 1;1957 1958 /* secondary codec - modem */1959 if (inl(ALI_REG(codec, ALI_SCTRL)) & ALI_SCTRL_CODEC2_READY) {1960 codec->num_of_codecs++;1961 outl(inl(ALI_REG(codec, ALI_SCTRL)) |1962 (ALI_SCTRL_LINE_IN2 | ALI_SCTRL_GPIO_IN2 |1963 ALI_SCTRL_LINE_OUT_EN),1964 ALI_REG(codec, ALI_SCTRL));1965 }1966 1967 dev_dbg(codec->card->dev, "chip initialize succeed.\n");1968 return 0;1969 1970}1971 1972/* proc for register dump */1973static void snd_ali_proc_read(struct snd_info_entry *entry,1974 struct snd_info_buffer *buf)1975{1976 struct snd_ali *codec = entry->private_data;1977 int i;1978 for (i = 0; i < 256 ; i+= 4)1979 snd_iprintf(buf, "%02x: %08x\n", i, inl(ALI_REG(codec, i)));1980}1981 1982static void snd_ali_proc_init(struct snd_ali *codec)1983{1984 snd_card_ro_proc_new(codec->card, "ali5451", codec, snd_ali_proc_read);1985}1986 1987static int snd_ali_resources(struct snd_ali *codec)1988{1989 int err;1990 1991 dev_dbg(codec->card->dev, "resources allocation ...\n");1992 err = pci_request_regions(codec->pci, "ALI 5451");1993 if (err < 0)1994 return err;1995 codec->port = pci_resource_start(codec->pci, 0);1996 1997 if (devm_request_irq(&codec->pci->dev, codec->pci->irq,1998 snd_ali_card_interrupt,1999 IRQF_SHARED, KBUILD_MODNAME, codec)) {2000 dev_err(codec->card->dev, "Unable to request irq.\n");2001 return -EBUSY;2002 }2003 codec->irq = codec->pci->irq;2004 codec->card->sync_irq = codec->irq;2005 dev_dbg(codec->card->dev, "resources allocated.\n");2006 return 0;2007}2008 2009static int snd_ali_create(struct snd_card *card,2010 struct pci_dev *pci,2011 int pcm_streams,2012 int spdif_support)2013{2014 struct snd_ali *codec = card->private_data;2015 int i, err;2016 unsigned short cmdw;2017 2018 dev_dbg(card->dev, "creating ...\n");2019 2020 /* enable PCI device */2021 err = pcim_enable_device(pci);2022 if (err < 0)2023 return err;2024 /* check, if we can restrict PCI DMA transfers to 31 bits */2025 if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(31))) {2026 dev_err(card->dev,2027 "architecture does not support 31bit PCI busmaster DMA\n");2028 return -ENXIO;2029 }2030 2031 spin_lock_init(&codec->reg_lock);2032 spin_lock_init(&codec->voice_alloc);2033 2034 codec->card = card;2035 codec->pci = pci;2036 codec->irq = -1;2037 codec->revision = pci->revision;2038 codec->spdif_support = spdif_support;2039 2040 if (pcm_streams < 1)2041 pcm_streams = 1;2042 if (pcm_streams > 32)2043 pcm_streams = 32;2044 2045 pci_set_master(pci);2046 pci_read_config_word(pci, PCI_COMMAND, &cmdw);2047 if ((cmdw & PCI_COMMAND_IO) != PCI_COMMAND_IO) {2048 cmdw |= PCI_COMMAND_IO;2049 pci_write_config_word(pci, PCI_COMMAND, cmdw);2050 }2051 2052 if (snd_ali_resources(codec))2053 return -EBUSY;2054 card->private_free = snd_ali_free;2055 2056 codec->synth.chmap = 0;2057 codec->synth.chcnt = 0;2058 codec->spdif_mask = 0;2059 codec->synth.synthcount = 0;2060 2061 if (codec->revision == ALI_5451_V02)2062 codec->chregs.regs.ac97read = ALI_AC97_WRITE;2063 else2064 codec->chregs.regs.ac97read = ALI_AC97_READ;2065 codec->chregs.regs.ac97write = ALI_AC97_WRITE;2066 2067 codec->chregs.regs.start = ALI_START;2068 codec->chregs.regs.stop = ALI_STOP;2069 codec->chregs.regs.aint = ALI_AINT;2070 codec->chregs.regs.ainten = ALI_AINTEN;2071 2072 codec->chregs.data.start = 0x00;2073 codec->chregs.data.stop = 0x00;2074 codec->chregs.data.aint = 0x00;2075 codec->chregs.data.ainten = 0x00;2076 2077 /* M1533: southbridge */2078 codec->pci_m1533 = pci_get_device(0x10b9, 0x1533, NULL);2079 if (!codec->pci_m1533) {2080 dev_err(card->dev, "cannot find ALi 1533 chip.\n");2081 return -ENODEV;2082 }2083 /* M7101: power management */2084 codec->pci_m7101 = pci_get_device(0x10b9, 0x7101, NULL);2085 if (!codec->pci_m7101 && codec->revision == ALI_5451_V02) {2086 dev_err(card->dev, "cannot find ALi 7101 chip.\n");2087 return -ENODEV;2088 }2089 2090 /* initialise synth voices*/2091 for (i = 0; i < ALI_CHANNELS; i++)2092 codec->synth.voices[i].number = i;2093 2094 err = snd_ali_chip_init(codec);2095 if (err < 0) {2096 dev_err(card->dev, "ali create: chip init error.\n");2097 return err;2098 }2099 2100 snd_ali_enable_address_interrupt(codec);2101 codec->hw_initialized = 1;2102 return 0;2103}2104 2105static int __snd_ali_probe(struct pci_dev *pci,2106 const struct pci_device_id *pci_id)2107{2108 struct snd_card *card;2109 struct snd_ali *codec;2110 int err;2111 2112 dev_dbg(&pci->dev, "probe ...\n");2113 2114 err = snd_devm_card_new(&pci->dev, index, id, THIS_MODULE,2115 sizeof(*codec), &card);2116 if (err < 0)2117 return err;2118 codec = card->private_data;2119 2120 err = snd_ali_create(card, pci, pcm_channels, spdif);2121 if (err < 0)2122 return err;2123 2124 dev_dbg(&pci->dev, "mixer building ...\n");2125 err = snd_ali_mixer(codec);2126 if (err < 0)2127 return err;2128 2129 dev_dbg(&pci->dev, "pcm building ...\n");2130 err = snd_ali_build_pcms(codec);2131 if (err < 0)2132 return err;2133 2134 snd_ali_proc_init(codec);2135 2136 strcpy(card->driver, "ALI5451");2137 strcpy(card->shortname, "ALI 5451");2138 2139 sprintf(card->longname, "%s at 0x%lx, irq %i",2140 card->shortname, codec->port, codec->irq);2141 2142 dev_dbg(&pci->dev, "register card.\n");2143 err = snd_card_register(card);2144 if (err < 0)2145 return err;2146 2147 pci_set_drvdata(pci, card);2148 return 0;2149}2150 2151static int snd_ali_probe(struct pci_dev *pci,2152 const struct pci_device_id *pci_id)2153{2154 return snd_card_free_on_error(&pci->dev, __snd_ali_probe(pci, pci_id));2155}2156 2157static struct pci_driver ali5451_driver = {2158 .name = KBUILD_MODNAME,2159 .id_table = snd_ali_ids,2160 .probe = snd_ali_probe,2161 .driver = {2162 .pm = &ali_pm,2163 },2164}; 2165 2166module_pci_driver(ali5451_driver);2167