1 /* 2 * Driver for Digigram pcxhr compatible soundcards 3 * 4 * low level interface with interrupt and message handling implementation 5 * 6 * Copyright (c) 2004 by Digigram <alsa@digigram.com> 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 */ 22 23 #include <linux/delay.h> 24 #include <linux/firmware.h> 25 #include <linux/interrupt.h> 26 #include <linux/pci.h> 27 #include <asm/io.h> 28 #include <sound/core.h> 29 #include "pcxhr.h" 30 #include "pcxhr_mixer.h" 31 #include "pcxhr_hwdep.h" 32 #include "pcxhr_core.h" 33 34 35 /* registers used on the PLX (port 1) */ 36 #define PCXHR_PLX_OFFSET_MIN 0x40 37 #define PCXHR_PLX_MBOX0 0x40 38 #define PCXHR_PLX_MBOX1 0x44 39 #define PCXHR_PLX_MBOX2 0x48 40 #define PCXHR_PLX_MBOX3 0x4C 41 #define PCXHR_PLX_MBOX4 0x50 42 #define PCXHR_PLX_MBOX5 0x54 43 #define PCXHR_PLX_MBOX6 0x58 44 #define PCXHR_PLX_MBOX7 0x5C 45 #define PCXHR_PLX_L2PCIDB 0x64 46 #define PCXHR_PLX_IRQCS 0x68 47 #define PCXHR_PLX_CHIPSC 0x6C 48 49 /* registers used on the DSP (port 2) */ 50 #define PCXHR_DSP_ICR 0x00 51 #define PCXHR_DSP_CVR 0x04 52 #define PCXHR_DSP_ISR 0x08 53 #define PCXHR_DSP_IVR 0x0C 54 #define PCXHR_DSP_RXH 0x14 55 #define PCXHR_DSP_TXH 0x14 56 #define PCXHR_DSP_RXM 0x18 57 #define PCXHR_DSP_TXM 0x18 58 #define PCXHR_DSP_RXL 0x1C 59 #define PCXHR_DSP_TXL 0x1C 60 #define PCXHR_DSP_RESET 0x20 61 #define PCXHR_DSP_OFFSET_MAX 0x20 62 63 /* access to the card */ 64 #define PCXHR_PLX 1 65 #define PCXHR_DSP 2 66 67 #if (PCXHR_DSP_OFFSET_MAX > PCXHR_PLX_OFFSET_MIN) 68 #undef PCXHR_REG_TO_PORT(x) 69 #else 70 #define PCXHR_REG_TO_PORT(x) ((x)>PCXHR_DSP_OFFSET_MAX ? PCXHR_PLX : PCXHR_DSP) 71 #endif 72 #define PCXHR_INPB(mgr,x) inb((mgr)->port[PCXHR_REG_TO_PORT(x)] + (x)) 73 #define PCXHR_INPL(mgr,x) inl((mgr)->port[PCXHR_REG_TO_PORT(x)] + (x)) 74 #define PCXHR_OUTPB(mgr,x,data) outb((data), (mgr)->port[PCXHR_REG_TO_PORT(x)] + (x)) 75 #define PCXHR_OUTPL(mgr,x,data) outl((data), (mgr)->port[PCXHR_REG_TO_PORT(x)] + (x)) 76 /* attention : access the PCXHR_DSP_* registers with inb and outb only ! */ 77 78 /* params used with PCXHR_PLX_MBOX0 */ 79 #define PCXHR_MBOX0_HF5 (1 << 0) 80 #define PCXHR_MBOX0_HF4 (1 << 1) 81 #define PCXHR_MBOX0_BOOT_HERE (1 << 23) 82 /* params used with PCXHR_PLX_IRQCS */ 83 #define PCXHR_IRQCS_ENABLE_PCIIRQ (1 << 8) 84 #define PCXHR_IRQCS_ENABLE_PCIDB (1 << 9) 85 #define PCXHR_IRQCS_ACTIVE_PCIDB (1 << 13) 86 /* params used with PCXHR_PLX_CHIPSC */ 87 #define PCXHR_CHIPSC_INIT_VALUE 0x100D767E 88 #define PCXHR_CHIPSC_RESET_XILINX (1 << 16) 89 #define PCXHR_CHIPSC_GPI_USERI (1 << 17) 90 #define PCXHR_CHIPSC_DATA_CLK (1 << 24) 91 #define PCXHR_CHIPSC_DATA_IN (1 << 26) 92 93 /* params used with PCXHR_DSP_ICR */ 94 #define PCXHR_ICR_HI08_RREQ 0x01 95 #define PCXHR_ICR_HI08_TREQ 0x02 96 #define PCXHR_ICR_HI08_HDRQ 0x04 97 #define PCXHR_ICR_HI08_HF0 0x08 98 #define PCXHR_ICR_HI08_HF1 0x10 99 #define PCXHR_ICR_HI08_HLEND 0x20 100 #define PCXHR_ICR_HI08_INIT 0x80 101 /* params used with PCXHR_DSP_CVR */ 102 #define PCXHR_CVR_HI08_HC 0x80 103 /* params used with PCXHR_DSP_ISR */ 104 #define PCXHR_ISR_HI08_RXDF 0x01 105 #define PCXHR_ISR_HI08_TXDE 0x02 106 #define PCXHR_ISR_HI08_TRDY 0x04 107 #define PCXHR_ISR_HI08_ERR 0x08 108 #define PCXHR_ISR_HI08_CHK 0x10 109 #define PCXHR_ISR_HI08_HREQ 0x80 110 111 112 /* constants used for delay in msec */ 113 #define PCXHR_WAIT_DEFAULT 2 114 #define PCXHR_WAIT_IT 25 115 #define PCXHR_WAIT_IT_EXTRA 65 116 117 /* 118 * pcxhr_check_reg_bit - wait for the specified bit is set/reset on a register 119 * @reg: register to check 120 * @mask: bit mask 121 * @bit: resultant bit to be checked 122 * @time: time-out of loop in msec 123 * 124 * returns zero if a bit matches, or a negative error code. 125 */ 126 static int pcxhr_check_reg_bit(struct pcxhr_mgr *mgr, unsigned int reg, 127 unsigned char mask, unsigned char bit, int time, 128 unsigned char* read) 129 { 130 int i = 0; 131 unsigned long end_time = jiffies + (time * HZ + 999) / 1000; 132 do { 133 *read = PCXHR_INPB(mgr, reg); 134 if ((*read & mask) == bit) { 135 if (i > 100) 136 dev_dbg(&mgr->pci->dev, 137 "ATTENTION! check_reg(%x) loopcount=%d\n", 138 reg, i); 139 return 0; 140 } 141 i++; 142 } while (time_after_eq(end_time, jiffies)); 143 dev_err(&mgr->pci->dev, 144 "pcxhr_check_reg_bit: timeout, reg=%x, mask=0x%x, val=%x\n", 145 reg, mask, *read); 146 return -EIO; 147 } 148 149 /* constants used with pcxhr_check_reg_bit() */ 150 #define PCXHR_TIMEOUT_DSP 200 151 152 153 #define PCXHR_MASK_EXTRA_INFO 0x0000FE 154 #define PCXHR_MASK_IT_HF0 0x000100 155 #define PCXHR_MASK_IT_HF1 0x000200 156 #define PCXHR_MASK_IT_NO_HF0_HF1 0x000400 157 #define PCXHR_MASK_IT_MANAGE_HF5 0x000800 158 #define PCXHR_MASK_IT_WAIT 0x010000 159 #define PCXHR_MASK_IT_WAIT_EXTRA 0x020000 160 161 #define PCXHR_IT_SEND_BYTE_XILINX (0x0000003C | PCXHR_MASK_IT_HF0) 162 #define PCXHR_IT_TEST_XILINX (0x0000003C | PCXHR_MASK_IT_HF1 | \ 163 PCXHR_MASK_IT_MANAGE_HF5) 164 #define PCXHR_IT_DOWNLOAD_BOOT (0x0000000C | PCXHR_MASK_IT_HF1 | \ 165 PCXHR_MASK_IT_MANAGE_HF5 | \ 166 PCXHR_MASK_IT_WAIT) 167 #define PCXHR_IT_RESET_BOARD_FUNC (0x0000000C | PCXHR_MASK_IT_HF0 | \ 168 PCXHR_MASK_IT_MANAGE_HF5 | \ 169 PCXHR_MASK_IT_WAIT_EXTRA) 170 #define PCXHR_IT_DOWNLOAD_DSP (0x0000000C | \ 171 PCXHR_MASK_IT_MANAGE_HF5 | \ 172 PCXHR_MASK_IT_WAIT) 173 #define PCXHR_IT_DEBUG (0x0000005A | PCXHR_MASK_IT_NO_HF0_HF1) 174 #define PCXHR_IT_RESET_SEMAPHORE (0x0000005C | PCXHR_MASK_IT_NO_HF0_HF1) 175 #define PCXHR_IT_MESSAGE (0x00000074 | PCXHR_MASK_IT_NO_HF0_HF1) 176 #define PCXHR_IT_RESET_CHK (0x00000076 | PCXHR_MASK_IT_NO_HF0_HF1) 177 #define PCXHR_IT_UPDATE_RBUFFER (0x00000078 | PCXHR_MASK_IT_NO_HF0_HF1) 178 179 static int pcxhr_send_it_dsp(struct pcxhr_mgr *mgr, 180 unsigned int itdsp, int atomic) 181 { 182 int err; 183 unsigned char reg; 184 185 if (itdsp & PCXHR_MASK_IT_MANAGE_HF5) { 186 /* clear hf5 bit */ 187 PCXHR_OUTPL(mgr, PCXHR_PLX_MBOX0, 188 PCXHR_INPL(mgr, PCXHR_PLX_MBOX0) & 189 ~PCXHR_MBOX0_HF5); 190 } 191 if ((itdsp & PCXHR_MASK_IT_NO_HF0_HF1) == 0) { 192 reg = (PCXHR_ICR_HI08_RREQ | 193 PCXHR_ICR_HI08_TREQ | 194 PCXHR_ICR_HI08_HDRQ); 195 if (itdsp & PCXHR_MASK_IT_HF0) 196 reg |= PCXHR_ICR_HI08_HF0; 197 if (itdsp & PCXHR_MASK_IT_HF1) 198 reg |= PCXHR_ICR_HI08_HF1; 199 PCXHR_OUTPB(mgr, PCXHR_DSP_ICR, reg); 200 } 201 reg = (unsigned char)(((itdsp & PCXHR_MASK_EXTRA_INFO) >> 1) | 202 PCXHR_CVR_HI08_HC); 203 PCXHR_OUTPB(mgr, PCXHR_DSP_CVR, reg); 204 if (itdsp & PCXHR_MASK_IT_WAIT) { 205 if (atomic) 206 mdelay(PCXHR_WAIT_IT); 207 else 208 msleep(PCXHR_WAIT_IT); 209 } 210 if (itdsp & PCXHR_MASK_IT_WAIT_EXTRA) { 211 if (atomic) 212 mdelay(PCXHR_WAIT_IT_EXTRA); 213 else 214 msleep(PCXHR_WAIT_IT); 215 } 216 /* wait for CVR_HI08_HC == 0 */ 217 err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_CVR, PCXHR_CVR_HI08_HC, 0, 218 PCXHR_TIMEOUT_DSP, ®); 219 if (err) { 220 dev_err(&mgr->pci->dev, "pcxhr_send_it_dsp : TIMEOUT CVR\n"); 221 return err; 222 } 223 if (itdsp & PCXHR_MASK_IT_MANAGE_HF5) { 224 /* wait for hf5 bit */ 225 err = pcxhr_check_reg_bit(mgr, PCXHR_PLX_MBOX0, 226 PCXHR_MBOX0_HF5, 227 PCXHR_MBOX0_HF5, 228 PCXHR_TIMEOUT_DSP, 229 ®); 230 if (err) { 231 dev_err(&mgr->pci->dev, 232 "pcxhr_send_it_dsp : TIMEOUT HF5\n"); 233 return err; 234 } 235 } 236 return 0; /* retry not handled here */ 237 } 238 239 void pcxhr_reset_xilinx_com(struct pcxhr_mgr *mgr) 240 { 241 /* reset second xilinx */ 242 PCXHR_OUTPL(mgr, PCXHR_PLX_CHIPSC, 243 PCXHR_CHIPSC_INIT_VALUE & ~PCXHR_CHIPSC_RESET_XILINX); 244 } 245 246 static void pcxhr_enable_irq(struct pcxhr_mgr *mgr, int enable) 247 { 248 unsigned int reg = PCXHR_INPL(mgr, PCXHR_PLX_IRQCS); 249 /* enable/disable interrupts */ 250 if (enable) 251 reg |= (PCXHR_IRQCS_ENABLE_PCIIRQ | PCXHR_IRQCS_ENABLE_PCIDB); 252 else 253 reg &= ~(PCXHR_IRQCS_ENABLE_PCIIRQ | PCXHR_IRQCS_ENABLE_PCIDB); 254 PCXHR_OUTPL(mgr, PCXHR_PLX_IRQCS, reg); 255 } 256 257 void pcxhr_reset_dsp(struct pcxhr_mgr *mgr) 258 { 259 /* disable interrupts */ 260 pcxhr_enable_irq(mgr, 0); 261 262 /* let's reset the DSP */ 263 PCXHR_OUTPB(mgr, PCXHR_DSP_RESET, 0); 264 msleep( PCXHR_WAIT_DEFAULT ); /* wait 2 msec */ 265 PCXHR_OUTPB(mgr, PCXHR_DSP_RESET, 3); 266 msleep( PCXHR_WAIT_DEFAULT ); /* wait 2 msec */ 267 268 /* reset mailbox */ 269 PCXHR_OUTPL(mgr, PCXHR_PLX_MBOX0, 0); 270 } 271 272 void pcxhr_enable_dsp(struct pcxhr_mgr *mgr) 273 { 274 /* enable interrupts */ 275 pcxhr_enable_irq(mgr, 1); 276 } 277 278 /* 279 * load the xilinx image 280 */ 281 int pcxhr_load_xilinx_binary(struct pcxhr_mgr *mgr, 282 const struct firmware *xilinx, int second) 283 { 284 unsigned int i; 285 unsigned int chipsc; 286 unsigned char data; 287 unsigned char mask; 288 const unsigned char *image; 289 290 /* test first xilinx */ 291 chipsc = PCXHR_INPL(mgr, PCXHR_PLX_CHIPSC); 292 /* REV01 cards do not support the PCXHR_CHIPSC_GPI_USERI bit anymore */ 293 /* this bit will always be 1; 294 * no possibility to test presence of first xilinx 295 */ 296 if(second) { 297 if ((chipsc & PCXHR_CHIPSC_GPI_USERI) == 0) { 298 dev_err(&mgr->pci->dev, "error loading first xilinx\n"); 299 return -EINVAL; 300 } 301 /* activate second xilinx */ 302 chipsc |= PCXHR_CHIPSC_RESET_XILINX; 303 PCXHR_OUTPL(mgr, PCXHR_PLX_CHIPSC, chipsc); 304 msleep( PCXHR_WAIT_DEFAULT ); /* wait 2 msec */ 305 } 306 image = xilinx->data; 307 for (i = 0; i < xilinx->size; i++, image++) { 308 data = *image; 309 mask = 0x80; 310 while (mask) { 311 chipsc &= ~(PCXHR_CHIPSC_DATA_CLK | 312 PCXHR_CHIPSC_DATA_IN); 313 if (data & mask) 314 chipsc |= PCXHR_CHIPSC_DATA_IN; 315 PCXHR_OUTPL(mgr, PCXHR_PLX_CHIPSC, chipsc); 316 chipsc |= PCXHR_CHIPSC_DATA_CLK; 317 PCXHR_OUTPL(mgr, PCXHR_PLX_CHIPSC, chipsc); 318 mask >>= 1; 319 } 320 /* don't take too much time in this loop... */ 321 cond_resched(); 322 } 323 chipsc &= ~(PCXHR_CHIPSC_DATA_CLK | PCXHR_CHIPSC_DATA_IN); 324 PCXHR_OUTPL(mgr, PCXHR_PLX_CHIPSC, chipsc); 325 /* wait 2 msec (time to boot the xilinx before any access) */ 326 msleep( PCXHR_WAIT_DEFAULT ); 327 return 0; 328 } 329 330 /* 331 * send an executable file to the DSP 332 */ 333 static int pcxhr_download_dsp(struct pcxhr_mgr *mgr, const struct firmware *dsp) 334 { 335 int err; 336 unsigned int i; 337 unsigned int len; 338 const unsigned char *data; 339 unsigned char dummy; 340 /* check the length of boot image */ 341 if (dsp->size <= 0) 342 return -EINVAL; 343 if (dsp->size % 3) 344 return -EINVAL; 345 if (snd_BUG_ON(!dsp->data)) 346 return -EINVAL; 347 /* transfert data buffer from PC to DSP */ 348 for (i = 0; i < dsp->size; i += 3) { 349 data = dsp->data + i; 350 if (i == 0) { 351 /* test data header consistency */ 352 len = (unsigned int)((data[0]<<16) + 353 (data[1]<<8) + 354 data[2]); 355 if (len && (dsp->size != (len + 2) * 3)) 356 return -EINVAL; 357 } 358 /* wait DSP ready for new transfer */ 359 err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, 360 PCXHR_ISR_HI08_TRDY, 361 PCXHR_ISR_HI08_TRDY, 362 PCXHR_TIMEOUT_DSP, &dummy); 363 if (err) { 364 dev_err(&mgr->pci->dev, 365 "dsp loading error at position %d\n", i); 366 return err; 367 } 368 /* send host data */ 369 PCXHR_OUTPB(mgr, PCXHR_DSP_TXH, data[0]); 370 PCXHR_OUTPB(mgr, PCXHR_DSP_TXM, data[1]); 371 PCXHR_OUTPB(mgr, PCXHR_DSP_TXL, data[2]); 372 373 /* don't take too much time in this loop... */ 374 cond_resched(); 375 } 376 /* give some time to boot the DSP */ 377 msleep(PCXHR_WAIT_DEFAULT); 378 return 0; 379 } 380 381 /* 382 * load the eeprom image 383 */ 384 int pcxhr_load_eeprom_binary(struct pcxhr_mgr *mgr, 385 const struct firmware *eeprom) 386 { 387 int err; 388 unsigned char reg; 389 390 /* init value of the ICR register */ 391 reg = PCXHR_ICR_HI08_RREQ | PCXHR_ICR_HI08_TREQ | PCXHR_ICR_HI08_HDRQ; 392 if (PCXHR_INPL(mgr, PCXHR_PLX_MBOX0) & PCXHR_MBOX0_BOOT_HERE) { 393 /* no need to load the eeprom binary, 394 * but init the HI08 interface 395 */ 396 PCXHR_OUTPB(mgr, PCXHR_DSP_ICR, reg | PCXHR_ICR_HI08_INIT); 397 msleep(PCXHR_WAIT_DEFAULT); 398 PCXHR_OUTPB(mgr, PCXHR_DSP_ICR, reg); 399 msleep(PCXHR_WAIT_DEFAULT); 400 dev_dbg(&mgr->pci->dev, "no need to load eeprom boot\n"); 401 return 0; 402 } 403 PCXHR_OUTPB(mgr, PCXHR_DSP_ICR, reg); 404 405 err = pcxhr_download_dsp(mgr, eeprom); 406 if (err) 407 return err; 408 /* wait for chk bit */ 409 return pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, PCXHR_ISR_HI08_CHK, 410 PCXHR_ISR_HI08_CHK, PCXHR_TIMEOUT_DSP, ®); 411 } 412 413 /* 414 * load the boot image 415 */ 416 int pcxhr_load_boot_binary(struct pcxhr_mgr *mgr, const struct firmware *boot) 417 { 418 int err; 419 unsigned int physaddr = mgr->hostport.addr; 420 unsigned char dummy; 421 422 /* send the hostport address to the DSP (only the upper 24 bit !) */ 423 if (snd_BUG_ON(physaddr & 0xff)) 424 return -EINVAL; 425 PCXHR_OUTPL(mgr, PCXHR_PLX_MBOX1, (physaddr >> 8)); 426 427 err = pcxhr_send_it_dsp(mgr, PCXHR_IT_DOWNLOAD_BOOT, 0); 428 if (err) 429 return err; 430 /* clear hf5 bit */ 431 PCXHR_OUTPL(mgr, PCXHR_PLX_MBOX0, 432 PCXHR_INPL(mgr, PCXHR_PLX_MBOX0) & ~PCXHR_MBOX0_HF5); 433 434 err = pcxhr_download_dsp(mgr, boot); 435 if (err) 436 return err; 437 /* wait for hf5 bit */ 438 return pcxhr_check_reg_bit(mgr, PCXHR_PLX_MBOX0, PCXHR_MBOX0_HF5, 439 PCXHR_MBOX0_HF5, PCXHR_TIMEOUT_DSP, &dummy); 440 } 441 442 /* 443 * load the final dsp image 444 */ 445 int pcxhr_load_dsp_binary(struct pcxhr_mgr *mgr, const struct firmware *dsp) 446 { 447 int err; 448 unsigned char dummy; 449 err = pcxhr_send_it_dsp(mgr, PCXHR_IT_RESET_BOARD_FUNC, 0); 450 if (err) 451 return err; 452 err = pcxhr_send_it_dsp(mgr, PCXHR_IT_DOWNLOAD_DSP, 0); 453 if (err) 454 return err; 455 err = pcxhr_download_dsp(mgr, dsp); 456 if (err) 457 return err; 458 /* wait for chk bit */ 459 return pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, 460 PCXHR_ISR_HI08_CHK, 461 PCXHR_ISR_HI08_CHK, 462 PCXHR_TIMEOUT_DSP, &dummy); 463 } 464 465 466 struct pcxhr_cmd_info { 467 u32 opcode; /* command word */ 468 u16 st_length; /* status length */ 469 u16 st_type; /* status type (RMH_SSIZE_XXX) */ 470 }; 471 472 /* RMH status type */ 473 enum { 474 RMH_SSIZE_FIXED = 0, /* status size fix (st_length = 0..x) */ 475 RMH_SSIZE_ARG = 1, /* status size given in the LSB byte */ 476 RMH_SSIZE_MASK = 2, /* status size given in bitmask */ 477 }; 478 479 /* 480 * Array of DSP commands 481 */ 482 static struct pcxhr_cmd_info pcxhr_dsp_cmds[] = { 483 [CMD_VERSION] = { 0x010000, 1, RMH_SSIZE_FIXED }, 484 [CMD_SUPPORTED] = { 0x020000, 4, RMH_SSIZE_FIXED }, 485 [CMD_TEST_IT] = { 0x040000, 1, RMH_SSIZE_FIXED }, 486 [CMD_SEND_IRQA] = { 0x070001, 0, RMH_SSIZE_FIXED }, 487 [CMD_ACCESS_IO_WRITE] = { 0x090000, 1, RMH_SSIZE_ARG }, 488 [CMD_ACCESS_IO_READ] = { 0x094000, 1, RMH_SSIZE_ARG }, 489 [CMD_ASYNC] = { 0x0a0000, 1, RMH_SSIZE_ARG }, 490 [CMD_MODIFY_CLOCK] = { 0x0d0000, 0, RMH_SSIZE_FIXED }, 491 [CMD_RESYNC_AUDIO_INPUTS] = { 0x0e0000, 0, RMH_SSIZE_FIXED }, 492 [CMD_GET_DSP_RESOURCES] = { 0x100000, 4, RMH_SSIZE_FIXED }, 493 [CMD_SET_TIMER_INTERRUPT] = { 0x110000, 0, RMH_SSIZE_FIXED }, 494 [CMD_RES_PIPE] = { 0x400000, 0, RMH_SSIZE_FIXED }, 495 [CMD_FREE_PIPE] = { 0x410000, 0, RMH_SSIZE_FIXED }, 496 [CMD_CONF_PIPE] = { 0x422101, 0, RMH_SSIZE_FIXED }, 497 [CMD_STOP_PIPE] = { 0x470004, 0, RMH_SSIZE_FIXED }, 498 [CMD_PIPE_SAMPLE_COUNT] = { 0x49a000, 2, RMH_SSIZE_FIXED }, 499 [CMD_CAN_START_PIPE] = { 0x4b0000, 1, RMH_SSIZE_FIXED }, 500 [CMD_START_STREAM] = { 0x802000, 0, RMH_SSIZE_FIXED }, 501 [CMD_STREAM_OUT_LEVEL_ADJUST] = { 0x822000, 0, RMH_SSIZE_FIXED }, 502 [CMD_STOP_STREAM] = { 0x832000, 0, RMH_SSIZE_FIXED }, 503 [CMD_UPDATE_R_BUFFERS] = { 0x840000, 0, RMH_SSIZE_FIXED }, 504 [CMD_FORMAT_STREAM_OUT] = { 0x860000, 0, RMH_SSIZE_FIXED }, 505 [CMD_FORMAT_STREAM_IN] = { 0x870000, 0, RMH_SSIZE_FIXED }, 506 [CMD_STREAM_SAMPLE_COUNT] = { 0x902000, 2, RMH_SSIZE_FIXED }, 507 [CMD_AUDIO_LEVEL_ADJUST] = { 0xc22000, 0, RMH_SSIZE_FIXED }, 508 [CMD_GET_TIME_CODE] = { 0x060000, 5, RMH_SSIZE_FIXED }, 509 [CMD_MANAGE_SIGNAL] = { 0x0f0000, 0, RMH_SSIZE_FIXED }, 510 }; 511 512 #ifdef CONFIG_SND_DEBUG_VERBOSE 513 static char* cmd_names[] = { 514 [CMD_VERSION] = "CMD_VERSION", 515 [CMD_SUPPORTED] = "CMD_SUPPORTED", 516 [CMD_TEST_IT] = "CMD_TEST_IT", 517 [CMD_SEND_IRQA] = "CMD_SEND_IRQA", 518 [CMD_ACCESS_IO_WRITE] = "CMD_ACCESS_IO_WRITE", 519 [CMD_ACCESS_IO_READ] = "CMD_ACCESS_IO_READ", 520 [CMD_ASYNC] = "CMD_ASYNC", 521 [CMD_MODIFY_CLOCK] = "CMD_MODIFY_CLOCK", 522 [CMD_RESYNC_AUDIO_INPUTS] = "CMD_RESYNC_AUDIO_INPUTS", 523 [CMD_GET_DSP_RESOURCES] = "CMD_GET_DSP_RESOURCES", 524 [CMD_SET_TIMER_INTERRUPT] = "CMD_SET_TIMER_INTERRUPT", 525 [CMD_RES_PIPE] = "CMD_RES_PIPE", 526 [CMD_FREE_PIPE] = "CMD_FREE_PIPE", 527 [CMD_CONF_PIPE] = "CMD_CONF_PIPE", 528 [CMD_STOP_PIPE] = "CMD_STOP_PIPE", 529 [CMD_PIPE_SAMPLE_COUNT] = "CMD_PIPE_SAMPLE_COUNT", 530 [CMD_CAN_START_PIPE] = "CMD_CAN_START_PIPE", 531 [CMD_START_STREAM] = "CMD_START_STREAM", 532 [CMD_STREAM_OUT_LEVEL_ADJUST] = "CMD_STREAM_OUT_LEVEL_ADJUST", 533 [CMD_STOP_STREAM] = "CMD_STOP_STREAM", 534 [CMD_UPDATE_R_BUFFERS] = "CMD_UPDATE_R_BUFFERS", 535 [CMD_FORMAT_STREAM_OUT] = "CMD_FORMAT_STREAM_OUT", 536 [CMD_FORMAT_STREAM_IN] = "CMD_FORMAT_STREAM_IN", 537 [CMD_STREAM_SAMPLE_COUNT] = "CMD_STREAM_SAMPLE_COUNT", 538 [CMD_AUDIO_LEVEL_ADJUST] = "CMD_AUDIO_LEVEL_ADJUST", 539 [CMD_GET_TIME_CODE] = "CMD_GET_TIME_CODE", 540 [CMD_MANAGE_SIGNAL] = "CMD_MANAGE_SIGNAL", 541 }; 542 #endif 543 544 545 static int pcxhr_read_rmh_status(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh) 546 { 547 int err; 548 int i; 549 u32 data; 550 u32 size_mask; 551 unsigned char reg; 552 int max_stat_len; 553 554 if (rmh->stat_len < PCXHR_SIZE_MAX_STATUS) 555 max_stat_len = PCXHR_SIZE_MAX_STATUS; 556 else max_stat_len = rmh->stat_len; 557 558 for (i = 0; i < rmh->stat_len; i++) { 559 /* wait for receiver full */ 560 err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, 561 PCXHR_ISR_HI08_RXDF, 562 PCXHR_ISR_HI08_RXDF, 563 PCXHR_TIMEOUT_DSP, ®); 564 if (err) { 565 dev_err(&mgr->pci->dev, 566 "ERROR RMH stat: ISR:RXDF=1 (ISR = %x; i=%d )\n", 567 reg, i); 568 return err; 569 } 570 /* read data */ 571 data = PCXHR_INPB(mgr, PCXHR_DSP_TXH) << 16; 572 data |= PCXHR_INPB(mgr, PCXHR_DSP_TXM) << 8; 573 data |= PCXHR_INPB(mgr, PCXHR_DSP_TXL); 574 575 /* need to update rmh->stat_len on the fly ?? */ 576 if (!i) { 577 if (rmh->dsp_stat != RMH_SSIZE_FIXED) { 578 if (rmh->dsp_stat == RMH_SSIZE_ARG) { 579 rmh->stat_len = (data & 0x0000ff) + 1; 580 data &= 0xffff00; 581 } else { 582 /* rmh->dsp_stat == RMH_SSIZE_MASK */ 583 rmh->stat_len = 1; 584 size_mask = data; 585 while (size_mask) { 586 if (size_mask & 1) 587 rmh->stat_len++; 588 size_mask >>= 1; 589 } 590 } 591 } 592 } 593 #ifdef CONFIG_SND_DEBUG_VERBOSE 594 if (rmh->cmd_idx < CMD_LAST_INDEX) 595 dev_dbg(&mgr->pci->dev, " stat[%d]=%x\n", i, data); 596 #endif 597 if (i < max_stat_len) 598 rmh->stat[i] = data; 599 } 600 if (rmh->stat_len > max_stat_len) { 601 dev_dbg(&mgr->pci->dev, "PCXHR : rmh->stat_len=%x too big\n", 602 rmh->stat_len); 603 rmh->stat_len = max_stat_len; 604 } 605 return 0; 606 } 607 608 static int pcxhr_send_msg_nolock(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh) 609 { 610 int err; 611 int i; 612 u32 data; 613 unsigned char reg; 614 615 if (snd_BUG_ON(rmh->cmd_len >= PCXHR_SIZE_MAX_CMD)) 616 return -EINVAL; 617 err = pcxhr_send_it_dsp(mgr, PCXHR_IT_MESSAGE, 1); 618 if (err) { 619 dev_err(&mgr->pci->dev, 620 "pcxhr_send_message : ED_DSP_CRASHED\n"); 621 return err; 622 } 623 /* wait for chk bit */ 624 err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, PCXHR_ISR_HI08_CHK, 625 PCXHR_ISR_HI08_CHK, PCXHR_TIMEOUT_DSP, ®); 626 if (err) 627 return err; 628 /* reset irq chk */ 629 err = pcxhr_send_it_dsp(mgr, PCXHR_IT_RESET_CHK, 1); 630 if (err) 631 return err; 632 /* wait for chk bit == 0*/ 633 err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, PCXHR_ISR_HI08_CHK, 0, 634 PCXHR_TIMEOUT_DSP, ®); 635 if (err) 636 return err; 637 638 data = rmh->cmd[0]; 639 640 if (rmh->cmd_len > 1) 641 data |= 0x008000; /* MASK_MORE_THAN_1_WORD_COMMAND */ 642 else 643 data &= 0xff7fff; /* MASK_1_WORD_COMMAND */ 644 #ifdef CONFIG_SND_DEBUG_VERBOSE 645 if (rmh->cmd_idx < CMD_LAST_INDEX) 646 dev_dbg(&mgr->pci->dev, "MSG cmd[0]=%x (%s)\n", 647 data, cmd_names[rmh->cmd_idx]); 648 #endif 649 650 err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, PCXHR_ISR_HI08_TRDY, 651 PCXHR_ISR_HI08_TRDY, PCXHR_TIMEOUT_DSP, ®); 652 if (err) 653 return err; 654 PCXHR_OUTPB(mgr, PCXHR_DSP_TXH, (data>>16)&0xFF); 655 PCXHR_OUTPB(mgr, PCXHR_DSP_TXM, (data>>8)&0xFF); 656 PCXHR_OUTPB(mgr, PCXHR_DSP_TXL, (data&0xFF)); 657 658 if (rmh->cmd_len > 1) { 659 /* send length */ 660 data = rmh->cmd_len - 1; 661 err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, 662 PCXHR_ISR_HI08_TRDY, 663 PCXHR_ISR_HI08_TRDY, 664 PCXHR_TIMEOUT_DSP, ®); 665 if (err) 666 return err; 667 PCXHR_OUTPB(mgr, PCXHR_DSP_TXH, (data>>16)&0xFF); 668 PCXHR_OUTPB(mgr, PCXHR_DSP_TXM, (data>>8)&0xFF); 669 PCXHR_OUTPB(mgr, PCXHR_DSP_TXL, (data&0xFF)); 670 671 for (i=1; i < rmh->cmd_len; i++) { 672 /* send other words */ 673 data = rmh->cmd[i]; 674 #ifdef CONFIG_SND_DEBUG_VERBOSE 675 if (rmh->cmd_idx < CMD_LAST_INDEX) 676 dev_dbg(&mgr->pci->dev, 677 " cmd[%d]=%x\n", i, data); 678 #endif 679 err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, 680 PCXHR_ISR_HI08_TRDY, 681 PCXHR_ISR_HI08_TRDY, 682 PCXHR_TIMEOUT_DSP, ®); 683 if (err) 684 return err; 685 PCXHR_OUTPB(mgr, PCXHR_DSP_TXH, (data>>16)&0xFF); 686 PCXHR_OUTPB(mgr, PCXHR_DSP_TXM, (data>>8)&0xFF); 687 PCXHR_OUTPB(mgr, PCXHR_DSP_TXL, (data&0xFF)); 688 } 689 } 690 /* wait for chk bit */ 691 err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, PCXHR_ISR_HI08_CHK, 692 PCXHR_ISR_HI08_CHK, PCXHR_TIMEOUT_DSP, ®); 693 if (err) 694 return err; 695 /* test status ISR */ 696 if (reg & PCXHR_ISR_HI08_ERR) { 697 /* ERROR, wait for receiver full */ 698 err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, 699 PCXHR_ISR_HI08_RXDF, 700 PCXHR_ISR_HI08_RXDF, 701 PCXHR_TIMEOUT_DSP, ®); 702 if (err) { 703 dev_err(&mgr->pci->dev, 704 "ERROR RMH: ISR:RXDF=1 (ISR = %x)\n", reg); 705 return err; 706 } 707 /* read error code */ 708 data = PCXHR_INPB(mgr, PCXHR_DSP_TXH) << 16; 709 data |= PCXHR_INPB(mgr, PCXHR_DSP_TXM) << 8; 710 data |= PCXHR_INPB(mgr, PCXHR_DSP_TXL); 711 dev_err(&mgr->pci->dev, "ERROR RMH(%d): 0x%x\n", 712 rmh->cmd_idx, data); 713 err = -EINVAL; 714 } else { 715 /* read the response data */ 716 err = pcxhr_read_rmh_status(mgr, rmh); 717 } 718 /* reset semaphore */ 719 if (pcxhr_send_it_dsp(mgr, PCXHR_IT_RESET_SEMAPHORE, 1) < 0) 720 return -EIO; 721 return err; 722 } 723 724 725 /** 726 * pcxhr_init_rmh - initialize the RMH instance 727 * @rmh: the rmh pointer to be initialized 728 * @cmd: the rmh command to be set 729 */ 730 void pcxhr_init_rmh(struct pcxhr_rmh *rmh, int cmd) 731 { 732 if (snd_BUG_ON(cmd >= CMD_LAST_INDEX)) 733 return; 734 rmh->cmd[0] = pcxhr_dsp_cmds[cmd].opcode; 735 rmh->cmd_len = 1; 736 rmh->stat_len = pcxhr_dsp_cmds[cmd].st_length; 737 rmh->dsp_stat = pcxhr_dsp_cmds[cmd].st_type; 738 rmh->cmd_idx = cmd; 739 } 740 741 742 void pcxhr_set_pipe_cmd_params(struct pcxhr_rmh *rmh, int capture, 743 unsigned int param1, unsigned int param2, 744 unsigned int param3) 745 { 746 snd_BUG_ON(param1 > MASK_FIRST_FIELD); 747 if (capture) 748 rmh->cmd[0] |= 0x800; /* COMMAND_RECORD_MASK */ 749 if (param1) 750 rmh->cmd[0] |= (param1 << FIELD_SIZE); 751 if (param2) { 752 snd_BUG_ON(param2 > MASK_FIRST_FIELD); 753 rmh->cmd[0] |= param2; 754 } 755 if(param3) { 756 snd_BUG_ON(param3 > MASK_DSP_WORD); 757 rmh->cmd[1] = param3; 758 rmh->cmd_len = 2; 759 } 760 } 761 762 /* 763 * pcxhr_send_msg - send a DSP message with spinlock 764 * @rmh: the rmh record to send and receive 765 * 766 * returns 0 if successful, or a negative error code. 767 */ 768 int pcxhr_send_msg(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh) 769 { 770 unsigned long flags; 771 int err; 772 spin_lock_irqsave(&mgr->msg_lock, flags); 773 err = pcxhr_send_msg_nolock(mgr, rmh); 774 spin_unlock_irqrestore(&mgr->msg_lock, flags); 775 return err; 776 } 777 778 static inline int pcxhr_pipes_running(struct pcxhr_mgr *mgr) 779 { 780 int start_mask = PCXHR_INPL(mgr, PCXHR_PLX_MBOX2); 781 /* least segnificant 12 bits are the pipe states 782 * for the playback audios 783 * next 12 bits are the pipe states for the capture audios 784 * (PCXHR_PIPE_STATE_CAPTURE_OFFSET) 785 */ 786 start_mask &= 0xffffff; 787 dev_dbg(&mgr->pci->dev, "CMD_PIPE_STATE MBOX2=0x%06x\n", start_mask); 788 return start_mask; 789 } 790 791 #define PCXHR_PIPE_STATE_CAPTURE_OFFSET 12 792 #define MAX_WAIT_FOR_DSP 20 793 794 static int pcxhr_prepair_pipe_start(struct pcxhr_mgr *mgr, 795 int audio_mask, int *retry) 796 { 797 struct pcxhr_rmh rmh; 798 int err; 799 int audio = 0; 800 801 *retry = 0; 802 while (audio_mask) { 803 if (audio_mask & 1) { 804 pcxhr_init_rmh(&rmh, CMD_CAN_START_PIPE); 805 if (audio < PCXHR_PIPE_STATE_CAPTURE_OFFSET) { 806 /* can start playback pipe */ 807 pcxhr_set_pipe_cmd_params(&rmh, 0, audio, 0, 0); 808 } else { 809 /* can start capture pipe */ 810 pcxhr_set_pipe_cmd_params(&rmh, 1, audio - 811 PCXHR_PIPE_STATE_CAPTURE_OFFSET, 812 0, 0); 813 } 814 err = pcxhr_send_msg(mgr, &rmh); 815 if (err) { 816 dev_err(&mgr->pci->dev, 817 "error pipe start " 818 "(CMD_CAN_START_PIPE) err=%x!\n", 819 err); 820 return err; 821 } 822 /* if the pipe couldn't be prepaired for start, 823 * retry it later 824 */ 825 if (rmh.stat[0] == 0) 826 *retry |= (1<<audio); 827 } 828 audio_mask>>=1; 829 audio++; 830 } 831 return 0; 832 } 833 834 static int pcxhr_stop_pipes(struct pcxhr_mgr *mgr, int audio_mask) 835 { 836 struct pcxhr_rmh rmh; 837 int err; 838 int audio = 0; 839 840 while (audio_mask) { 841 if (audio_mask & 1) { 842 pcxhr_init_rmh(&rmh, CMD_STOP_PIPE); 843 if (audio < PCXHR_PIPE_STATE_CAPTURE_OFFSET) { 844 /* stop playback pipe */ 845 pcxhr_set_pipe_cmd_params(&rmh, 0, audio, 0, 0); 846 } else { 847 /* stop capture pipe */ 848 pcxhr_set_pipe_cmd_params(&rmh, 1, audio - 849 PCXHR_PIPE_STATE_CAPTURE_OFFSET, 850 0, 0); 851 } 852 err = pcxhr_send_msg(mgr, &rmh); 853 if (err) { 854 dev_err(&mgr->pci->dev, 855 "error pipe stop " 856 "(CMD_STOP_PIPE) err=%x!\n", err); 857 return err; 858 } 859 } 860 audio_mask>>=1; 861 audio++; 862 } 863 return 0; 864 } 865 866 static int pcxhr_toggle_pipes(struct pcxhr_mgr *mgr, int audio_mask) 867 { 868 struct pcxhr_rmh rmh; 869 int err; 870 int audio = 0; 871 872 while (audio_mask) { 873 if (audio_mask & 1) { 874 pcxhr_init_rmh(&rmh, CMD_CONF_PIPE); 875 if (audio < PCXHR_PIPE_STATE_CAPTURE_OFFSET) 876 pcxhr_set_pipe_cmd_params(&rmh, 0, 0, 0, 877 1 << audio); 878 else 879 pcxhr_set_pipe_cmd_params(&rmh, 1, 0, 0, 880 1 << (audio - PCXHR_PIPE_STATE_CAPTURE_OFFSET)); 881 err = pcxhr_send_msg(mgr, &rmh); 882 if (err) { 883 dev_err(&mgr->pci->dev, 884 "error pipe start " 885 "(CMD_CONF_PIPE) err=%x!\n", err); 886 return err; 887 } 888 } 889 audio_mask>>=1; 890 audio++; 891 } 892 /* now fire the interrupt on the card */ 893 pcxhr_init_rmh(&rmh, CMD_SEND_IRQA); 894 err = pcxhr_send_msg(mgr, &rmh); 895 if (err) { 896 dev_err(&mgr->pci->dev, 897 "error pipe start (CMD_SEND_IRQA) err=%x!\n", 898 err); 899 return err; 900 } 901 return 0; 902 } 903 904 905 906 int pcxhr_set_pipe_state(struct pcxhr_mgr *mgr, int playback_mask, 907 int capture_mask, int start) 908 { 909 int state, i, err; 910 int audio_mask; 911 912 #ifdef CONFIG_SND_DEBUG_VERBOSE 913 struct timeval my_tv1, my_tv2; 914 do_gettimeofday(&my_tv1); 915 #endif 916 audio_mask = (playback_mask | 917 (capture_mask << PCXHR_PIPE_STATE_CAPTURE_OFFSET)); 918 /* current pipe state (playback + record) */ 919 state = pcxhr_pipes_running(mgr); 920 dev_dbg(&mgr->pci->dev, 921 "pcxhr_set_pipe_state %s (mask %x current %x)\n", 922 start ? "START" : "STOP", audio_mask, state); 923 if (start) { 924 /* start only pipes that are not yet started */ 925 audio_mask &= ~state; 926 state = audio_mask; 927 for (i = 0; i < MAX_WAIT_FOR_DSP; i++) { 928 err = pcxhr_prepair_pipe_start(mgr, state, &state); 929 if (err) 930 return err; 931 if (state == 0) 932 break; /* success, all pipes prepaired */ 933 mdelay(1); /* wait 1 millisecond and retry */ 934 } 935 } else { 936 audio_mask &= state; /* stop only pipes that are started */ 937 } 938 if (audio_mask == 0) 939 return 0; 940 941 err = pcxhr_toggle_pipes(mgr, audio_mask); 942 if (err) 943 return err; 944 945 i = 0; 946 while (1) { 947 state = pcxhr_pipes_running(mgr); 948 /* have all pipes the new state ? */ 949 if ((state & audio_mask) == (start ? audio_mask : 0)) 950 break; 951 if (++i >= MAX_WAIT_FOR_DSP * 100) { 952 dev_err(&mgr->pci->dev, "error pipe start/stop\n"); 953 return -EBUSY; 954 } 955 udelay(10); /* wait 10 microseconds */ 956 } 957 if (!start) { 958 err = pcxhr_stop_pipes(mgr, audio_mask); 959 if (err) 960 return err; 961 } 962 #ifdef CONFIG_SND_DEBUG_VERBOSE 963 do_gettimeofday(&my_tv2); 964 dev_dbg(&mgr->pci->dev, "***SET PIPE STATE*** TIME = %ld (err = %x)\n", 965 (long)(my_tv2.tv_usec - my_tv1.tv_usec), err); 966 #endif 967 return 0; 968 } 969 970 int pcxhr_write_io_num_reg_cont(struct pcxhr_mgr *mgr, unsigned int mask, 971 unsigned int value, int *changed) 972 { 973 struct pcxhr_rmh rmh; 974 unsigned long flags; 975 int err; 976 977 spin_lock_irqsave(&mgr->msg_lock, flags); 978 if ((mgr->io_num_reg_cont & mask) == value) { 979 dev_dbg(&mgr->pci->dev, 980 "IO_NUM_REG_CONT mask %x already is set to %x\n", 981 mask, value); 982 if (changed) 983 *changed = 0; 984 spin_unlock_irqrestore(&mgr->msg_lock, flags); 985 return 0; /* already programmed */ 986 } 987 pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE); 988 rmh.cmd[0] |= IO_NUM_REG_CONT; 989 rmh.cmd[1] = mask; 990 rmh.cmd[2] = value; 991 rmh.cmd_len = 3; 992 err = pcxhr_send_msg_nolock(mgr, &rmh); 993 if (err == 0) { 994 mgr->io_num_reg_cont &= ~mask; 995 mgr->io_num_reg_cont |= value; 996 if (changed) 997 *changed = 1; 998 } 999 spin_unlock_irqrestore(&mgr->msg_lock, flags); 1000 return err; 1001 } 1002 1003 #define PCXHR_IRQ_TIMER 0x000300 1004 #define PCXHR_IRQ_FREQ_CHANGE 0x000800 1005 #define PCXHR_IRQ_TIME_CODE 0x001000 1006 #define PCXHR_IRQ_NOTIFY 0x002000 1007 #define PCXHR_IRQ_ASYNC 0x008000 1008 #define PCXHR_IRQ_MASK 0x00bb00 1009 #define PCXHR_FATAL_DSP_ERR 0xff0000 1010 1011 enum pcxhr_async_err_src { 1012 PCXHR_ERR_PIPE, 1013 PCXHR_ERR_STREAM, 1014 PCXHR_ERR_AUDIO 1015 }; 1016 1017 static int pcxhr_handle_async_err(struct pcxhr_mgr *mgr, u32 err, 1018 enum pcxhr_async_err_src err_src, int pipe, 1019 int is_capture) 1020 { 1021 static char* err_src_name[] = { 1022 [PCXHR_ERR_PIPE] = "Pipe", 1023 [PCXHR_ERR_STREAM] = "Stream", 1024 [PCXHR_ERR_AUDIO] = "Audio" 1025 }; 1026 1027 if (err & 0xfff) 1028 err &= 0xfff; 1029 else 1030 err = ((err >> 12) & 0xfff); 1031 if (!err) 1032 return 0; 1033 dev_dbg(&mgr->pci->dev, "CMD_ASYNC : Error %s %s Pipe %d err=%x\n", 1034 err_src_name[err_src], 1035 is_capture ? "Record" : "Play", pipe, err); 1036 if (err == 0xe01) 1037 mgr->async_err_stream_xrun++; 1038 else if (err == 0xe10) 1039 mgr->async_err_pipe_xrun++; 1040 else 1041 mgr->async_err_other_last = (int)err; 1042 return 1; 1043 } 1044 1045 1046 void pcxhr_msg_tasklet(unsigned long arg) 1047 { 1048 struct pcxhr_mgr *mgr = (struct pcxhr_mgr *)(arg); 1049 struct pcxhr_rmh *prmh = mgr->prmh; 1050 int err; 1051 int i, j; 1052 1053 if (mgr->src_it_dsp & PCXHR_IRQ_FREQ_CHANGE) 1054 dev_dbg(&mgr->pci->dev, 1055 "TASKLET : PCXHR_IRQ_FREQ_CHANGE event occurred\n"); 1056 if (mgr->src_it_dsp & PCXHR_IRQ_TIME_CODE) 1057 dev_dbg(&mgr->pci->dev, 1058 "TASKLET : PCXHR_IRQ_TIME_CODE event occurred\n"); 1059 if (mgr->src_it_dsp & PCXHR_IRQ_NOTIFY) 1060 dev_dbg(&mgr->pci->dev, 1061 "TASKLET : PCXHR_IRQ_NOTIFY event occurred\n"); 1062 if (mgr->src_it_dsp & (PCXHR_IRQ_FREQ_CHANGE | PCXHR_IRQ_TIME_CODE)) { 1063 /* clear events FREQ_CHANGE and TIME_CODE */ 1064 pcxhr_init_rmh(prmh, CMD_TEST_IT); 1065 err = pcxhr_send_msg(mgr, prmh); 1066 dev_dbg(&mgr->pci->dev, "CMD_TEST_IT : err=%x, stat=%x\n", 1067 err, prmh->stat[0]); 1068 } 1069 if (mgr->src_it_dsp & PCXHR_IRQ_ASYNC) { 1070 dev_dbg(&mgr->pci->dev, 1071 "TASKLET : PCXHR_IRQ_ASYNC event occurred\n"); 1072 1073 pcxhr_init_rmh(prmh, CMD_ASYNC); 1074 prmh->cmd[0] |= 1; /* add SEL_ASYNC_EVENTS */ 1075 /* this is the only one extra long response command */ 1076 prmh->stat_len = PCXHR_SIZE_MAX_LONG_STATUS; 1077 err = pcxhr_send_msg(mgr, prmh); 1078 if (err) 1079 dev_err(&mgr->pci->dev, "ERROR pcxhr_msg_tasklet=%x;\n", 1080 err); 1081 i = 1; 1082 while (i < prmh->stat_len) { 1083 int nb_audio = ((prmh->stat[i] >> FIELD_SIZE) & 1084 MASK_FIRST_FIELD); 1085 int nb_stream = ((prmh->stat[i] >> (2*FIELD_SIZE)) & 1086 MASK_FIRST_FIELD); 1087 int pipe = prmh->stat[i] & MASK_FIRST_FIELD; 1088 int is_capture = prmh->stat[i] & 0x400000; 1089 u32 err2; 1090 1091 if (prmh->stat[i] & 0x800000) { /* if BIT_END */ 1092 dev_dbg(&mgr->pci->dev, 1093 "TASKLET : End%sPipe %d\n", 1094 is_capture ? "Record" : "Play", 1095 pipe); 1096 } 1097 i++; 1098 err2 = prmh->stat[i] ? prmh->stat[i] : prmh->stat[i+1]; 1099 if (err2) 1100 pcxhr_handle_async_err(mgr, err2, 1101 PCXHR_ERR_PIPE, 1102 pipe, is_capture); 1103 i += 2; 1104 for (j = 0; j < nb_stream; j++) { 1105 err2 = prmh->stat[i] ? 1106 prmh->stat[i] : prmh->stat[i+1]; 1107 if (err2) 1108 pcxhr_handle_async_err(mgr, err2, 1109 PCXHR_ERR_STREAM, 1110 pipe, 1111 is_capture); 1112 i += 2; 1113 } 1114 for (j = 0; j < nb_audio; j++) { 1115 err2 = prmh->stat[i] ? 1116 prmh->stat[i] : prmh->stat[i+1]; 1117 if (err2) 1118 pcxhr_handle_async_err(mgr, err2, 1119 PCXHR_ERR_AUDIO, 1120 pipe, 1121 is_capture); 1122 i += 2; 1123 } 1124 } 1125 } 1126 } 1127 1128 static u_int64_t pcxhr_stream_read_position(struct pcxhr_mgr *mgr, 1129 struct pcxhr_stream *stream) 1130 { 1131 u_int64_t hw_sample_count; 1132 struct pcxhr_rmh rmh; 1133 int err, stream_mask; 1134 1135 stream_mask = stream->pipe->is_capture ? 1 : 1<<stream->substream->number; 1136 1137 /* get sample count for one stream */ 1138 pcxhr_init_rmh(&rmh, CMD_STREAM_SAMPLE_COUNT); 1139 pcxhr_set_pipe_cmd_params(&rmh, stream->pipe->is_capture, 1140 stream->pipe->first_audio, 0, stream_mask); 1141 /* rmh.stat_len = 2; */ /* 2 resp data for each stream of the pipe */ 1142 1143 err = pcxhr_send_msg(mgr, &rmh); 1144 if (err) 1145 return 0; 1146 1147 hw_sample_count = ((u_int64_t)rmh.stat[0]) << 24; 1148 hw_sample_count += (u_int64_t)rmh.stat[1]; 1149 1150 dev_dbg(&mgr->pci->dev, 1151 "stream %c%d : abs samples real(%llu) timer(%llu)\n", 1152 stream->pipe->is_capture ? 'C' : 'P', 1153 stream->substream->number, 1154 hw_sample_count, 1155 stream->timer_abs_periods + stream->timer_period_frag + 1156 mgr->granularity); 1157 return hw_sample_count; 1158 } 1159 1160 static void pcxhr_update_timer_pos(struct pcxhr_mgr *mgr, 1161 struct pcxhr_stream *stream, 1162 int samples_to_add) 1163 { 1164 if (stream->substream && 1165 (stream->status == PCXHR_STREAM_STATUS_RUNNING)) { 1166 u_int64_t new_sample_count; 1167 int elapsed = 0; 1168 int hardware_read = 0; 1169 struct snd_pcm_runtime *runtime = stream->substream->runtime; 1170 1171 if (samples_to_add < 0) { 1172 stream->timer_is_synced = 0; 1173 /* add default if no hardware_read possible */ 1174 samples_to_add = mgr->granularity; 1175 } 1176 1177 if (!stream->timer_is_synced) { 1178 if ((stream->timer_abs_periods != 0) || 1179 ((stream->timer_period_frag + samples_to_add) >= 1180 runtime->period_size)) { 1181 new_sample_count = 1182 pcxhr_stream_read_position(mgr, stream); 1183 hardware_read = 1; 1184 if (new_sample_count >= mgr->granularity) { 1185 /* sub security offset because of 1186 * jitter and finer granularity of 1187 * dsp time (MBOX4) 1188 */ 1189 new_sample_count -= mgr->granularity; 1190 stream->timer_is_synced = 1; 1191 } 1192 } 1193 } 1194 if (!hardware_read) { 1195 /* if we didn't try to sync the position, increment it 1196 * by PCXHR_GRANULARITY every timer interrupt 1197 */ 1198 new_sample_count = stream->timer_abs_periods + 1199 stream->timer_period_frag + samples_to_add; 1200 } 1201 while (1) { 1202 u_int64_t new_elapse_pos = stream->timer_abs_periods + 1203 runtime->period_size; 1204 if (new_elapse_pos > new_sample_count) 1205 break; 1206 elapsed = 1; 1207 stream->timer_buf_periods++; 1208 if (stream->timer_buf_periods >= runtime->periods) 1209 stream->timer_buf_periods = 0; 1210 stream->timer_abs_periods = new_elapse_pos; 1211 } 1212 if (new_sample_count >= stream->timer_abs_periods) { 1213 stream->timer_period_frag = 1214 (u_int32_t)(new_sample_count - 1215 stream->timer_abs_periods); 1216 } else { 1217 dev_err(&mgr->pci->dev, 1218 "ERROR new_sample_count too small ??? %ld\n", 1219 (long unsigned int)new_sample_count); 1220 } 1221 1222 if (elapsed) { 1223 spin_unlock(&mgr->lock); 1224 snd_pcm_period_elapsed(stream->substream); 1225 spin_lock(&mgr->lock); 1226 } 1227 } 1228 } 1229 1230 irqreturn_t pcxhr_interrupt(int irq, void *dev_id) 1231 { 1232 struct pcxhr_mgr *mgr = dev_id; 1233 unsigned int reg; 1234 int i, j; 1235 struct snd_pcxhr *chip; 1236 1237 spin_lock(&mgr->lock); 1238 1239 reg = PCXHR_INPL(mgr, PCXHR_PLX_IRQCS); 1240 if (! (reg & PCXHR_IRQCS_ACTIVE_PCIDB)) { 1241 spin_unlock(&mgr->lock); 1242 /* this device did not cause the interrupt */ 1243 return IRQ_NONE; 1244 } 1245 1246 /* clear interrupt */ 1247 reg = PCXHR_INPL(mgr, PCXHR_PLX_L2PCIDB); 1248 PCXHR_OUTPL(mgr, PCXHR_PLX_L2PCIDB, reg); 1249 1250 /* timer irq occurred */ 1251 if (reg & PCXHR_IRQ_TIMER) { 1252 int timer_toggle = reg & PCXHR_IRQ_TIMER; 1253 /* is a 24 bit counter */ 1254 int dsp_time_new = 1255 PCXHR_INPL(mgr, PCXHR_PLX_MBOX4) & PCXHR_DSP_TIME_MASK; 1256 int dsp_time_diff = dsp_time_new - mgr->dsp_time_last; 1257 1258 if ((dsp_time_diff < 0) && 1259 (mgr->dsp_time_last != PCXHR_DSP_TIME_INVALID)) { 1260 /* handle dsp counter wraparound without resync */ 1261 int tmp_diff = dsp_time_diff + PCXHR_DSP_TIME_MASK + 1; 1262 dev_dbg(&mgr->pci->dev, 1263 "WARNING DSP timestamp old(%d) new(%d)", 1264 mgr->dsp_time_last, dsp_time_new); 1265 if (tmp_diff > 0 && tmp_diff <= (2*mgr->granularity)) { 1266 dev_dbg(&mgr->pci->dev, 1267 "-> timestamp wraparound OK: " 1268 "diff=%d\n", tmp_diff); 1269 dsp_time_diff = tmp_diff; 1270 } else { 1271 dev_dbg(&mgr->pci->dev, 1272 "-> resynchronize all streams\n"); 1273 mgr->dsp_time_err++; 1274 } 1275 } 1276 #ifdef CONFIG_SND_DEBUG_VERBOSE 1277 if (dsp_time_diff == 0) 1278 dev_dbg(&mgr->pci->dev, 1279 "ERROR DSP TIME NO DIFF time(%d)\n", 1280 dsp_time_new); 1281 else if (dsp_time_diff >= (2*mgr->granularity)) 1282 dev_dbg(&mgr->pci->dev, 1283 "ERROR DSP TIME TOO BIG old(%d) add(%d)\n", 1284 mgr->dsp_time_last, 1285 dsp_time_new - mgr->dsp_time_last); 1286 else if (dsp_time_diff % mgr->granularity) 1287 dev_dbg(&mgr->pci->dev, 1288 "ERROR DSP TIME increased by %d\n", 1289 dsp_time_diff); 1290 #endif 1291 mgr->dsp_time_last = dsp_time_new; 1292 1293 if (timer_toggle == mgr->timer_toggle) { 1294 dev_dbg(&mgr->pci->dev, "ERROR TIMER TOGGLE\n"); 1295 mgr->dsp_time_err++; 1296 } 1297 mgr->timer_toggle = timer_toggle; 1298 1299 reg &= ~PCXHR_IRQ_TIMER; 1300 for (i = 0; i < mgr->num_cards; i++) { 1301 chip = mgr->chip[i]; 1302 for (j = 0; j < chip->nb_streams_capt; j++) 1303 pcxhr_update_timer_pos(mgr, 1304 &chip->capture_stream[j], 1305 dsp_time_diff); 1306 } 1307 for (i = 0; i < mgr->num_cards; i++) { 1308 chip = mgr->chip[i]; 1309 for (j = 0; j < chip->nb_streams_play; j++) 1310 pcxhr_update_timer_pos(mgr, 1311 &chip->playback_stream[j], 1312 dsp_time_diff); 1313 } 1314 } 1315 /* other irq's handled in the tasklet */ 1316 if (reg & PCXHR_IRQ_MASK) { 1317 if (reg & PCXHR_IRQ_ASYNC) { 1318 /* as we didn't request any async notifications, 1319 * some kind of xrun error will probably occurred 1320 */ 1321 /* better resynchronize all streams next interrupt : */ 1322 mgr->dsp_time_last = PCXHR_DSP_TIME_INVALID; 1323 } 1324 mgr->src_it_dsp = reg; 1325 tasklet_schedule(&mgr->msg_taskq); 1326 } 1327 #ifdef CONFIG_SND_DEBUG_VERBOSE 1328 if (reg & PCXHR_FATAL_DSP_ERR) 1329 dev_dbg(&mgr->pci->dev, "FATAL DSP ERROR : %x\n", reg); 1330 #endif 1331 spin_unlock(&mgr->lock); 1332 return IRQ_HANDLED; /* this device caused the interrupt */ 1333 } 1334