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