1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (C) 2010-2013 Bluecherry, LLC <https://www.bluecherrydvr.com> 4 * 5 * Original author: 6 * Ben Collins <bcollins@ubuntu.com> 7 * 8 * Additional work by: 9 * John Brooks <john.brooks@bluecherry.net> 10 */ 11 12 #include <linux/kernel.h> 13 #include <linux/module.h> 14 #include <linux/pci.h> 15 #include <linux/interrupt.h> 16 #include <linux/videodev2.h> 17 #include <linux/delay.h> 18 #include <linux/sysfs.h> 19 #include <linux/ktime.h> 20 #include <linux/slab.h> 21 22 #include "solo6x10.h" 23 #include "solo6x10-tw28.h" 24 25 MODULE_DESCRIPTION("Softlogic 6x10 MPEG4/H.264/G.723 CODEC V4L2/ALSA Driver"); 26 MODULE_AUTHOR("Bluecherry <maintainers@bluecherrydvr.com>"); 27 MODULE_VERSION(SOLO6X10_VERSION); 28 MODULE_LICENSE("GPL"); 29 30 static unsigned video_nr = -1; 31 module_param(video_nr, uint, 0644); 32 MODULE_PARM_DESC(video_nr, "videoX start number, -1 is autodetect (default)"); 33 34 static int full_eeprom; /* default is only top 64B */ 35 module_param(full_eeprom, uint, 0644); 36 MODULE_PARM_DESC(full_eeprom, "Allow access to full 128B EEPROM (dangerous)"); 37 38 39 static void solo_set_time(struct solo_dev *solo_dev) 40 { 41 struct timespec64 ts; 42 43 ktime_get_ts64(&ts); 44 45 /* no overflow because we use monotonic timestamps */ 46 solo_reg_write(solo_dev, SOLO_TIMER_SEC, (u32)ts.tv_sec); 47 solo_reg_write(solo_dev, SOLO_TIMER_USEC, (u32)ts.tv_nsec / NSEC_PER_USEC); 48 } 49 50 static void solo_timer_sync(struct solo_dev *solo_dev) 51 { 52 u32 sec, usec; 53 struct timespec64 ts; 54 long diff; 55 56 if (solo_dev->type != SOLO_DEV_6110) 57 return; 58 59 if (++solo_dev->time_sync < 60) 60 return; 61 62 solo_dev->time_sync = 0; 63 64 sec = solo_reg_read(solo_dev, SOLO_TIMER_SEC); 65 usec = solo_reg_read(solo_dev, SOLO_TIMER_USEC); 66 67 ktime_get_ts64(&ts); 68 69 diff = (s32)ts.tv_sec - (s32)sec; 70 diff = (diff * 1000000) 71 + ((s32)(ts.tv_nsec / NSEC_PER_USEC) - (s32)usec); 72 73 if (diff > 1000 || diff < -1000) { 74 solo_set_time(solo_dev); 75 } else if (diff) { 76 long usec_lsb = solo_dev->usec_lsb; 77 78 usec_lsb -= diff / 4; 79 if (usec_lsb < 0) 80 usec_lsb = 0; 81 else if (usec_lsb > 255) 82 usec_lsb = 255; 83 84 solo_dev->usec_lsb = usec_lsb; 85 solo_reg_write(solo_dev, SOLO_TIMER_USEC_LSB, 86 solo_dev->usec_lsb); 87 } 88 } 89 90 static irqreturn_t solo_isr(int irq, void *data) 91 { 92 struct solo_dev *solo_dev = data; 93 u32 status; 94 int i; 95 96 status = solo_reg_read(solo_dev, SOLO_IRQ_STAT); 97 if (!status) 98 return IRQ_NONE; 99 100 /* Acknowledge all interrupts immediately */ 101 solo_reg_write(solo_dev, SOLO_IRQ_STAT, status); 102 103 if (status & SOLO_IRQ_PCI_ERR) 104 solo_p2m_error_isr(solo_dev); 105 106 for (i = 0; i < SOLO_NR_P2M; i++) 107 if (status & SOLO_IRQ_P2M(i)) 108 solo_p2m_isr(solo_dev, i); 109 110 if (status & SOLO_IRQ_IIC) 111 solo_i2c_isr(solo_dev); 112 113 if (status & SOLO_IRQ_VIDEO_IN) { 114 solo_video_in_isr(solo_dev); 115 solo_timer_sync(solo_dev); 116 } 117 118 if (status & SOLO_IRQ_ENCODER) 119 solo_enc_v4l2_isr(solo_dev); 120 121 if (status & SOLO_IRQ_G723) 122 solo_g723_isr(solo_dev); 123 124 return IRQ_HANDLED; 125 } 126 127 static void free_solo_dev(struct solo_dev *solo_dev) 128 { 129 struct pci_dev *pdev = solo_dev->pdev; 130 131 if (solo_dev->dev.parent) 132 device_unregister(&solo_dev->dev); 133 134 if (solo_dev->reg_base) { 135 /* Bring down the sub-devices first */ 136 solo_g723_exit(solo_dev); 137 solo_enc_v4l2_exit(solo_dev); 138 solo_enc_exit(solo_dev); 139 solo_v4l2_exit(solo_dev); 140 solo_disp_exit(solo_dev); 141 solo_gpio_exit(solo_dev); 142 solo_p2m_exit(solo_dev); 143 solo_i2c_exit(solo_dev); 144 145 /* Now cleanup the PCI device */ 146 solo_irq_off(solo_dev, ~0); 147 free_irq(pdev->irq, solo_dev); 148 pci_iounmap(pdev, solo_dev->reg_base); 149 } 150 151 pci_release_regions(pdev); 152 pci_disable_device(pdev); 153 v4l2_device_unregister(&solo_dev->v4l2_dev); 154 pci_set_drvdata(pdev, NULL); 155 156 kfree(solo_dev); 157 } 158 159 static ssize_t eeprom_store(struct device *dev, struct device_attribute *attr, 160 const char *buf, size_t count) 161 { 162 struct solo_dev *solo_dev = 163 container_of(dev, struct solo_dev, dev); 164 u16 *p = (u16 *)buf; 165 int i; 166 167 if (count & 0x1) 168 dev_warn(dev, "EEPROM Write not aligned (truncating)\n"); 169 170 if (!full_eeprom && count > 64) { 171 dev_warn(dev, "EEPROM Write truncated to 64 bytes\n"); 172 count = 64; 173 } else if (full_eeprom && count > 128) { 174 dev_warn(dev, "EEPROM Write truncated to 128 bytes\n"); 175 count = 128; 176 } 177 178 solo_eeprom_ewen(solo_dev, 1); 179 180 for (i = full_eeprom ? 0 : 32; i < min((int)(full_eeprom ? 64 : 32), 181 (int)(count / 2)); i++) 182 solo_eeprom_write(solo_dev, i, cpu_to_be16(p[i])); 183 184 solo_eeprom_ewen(solo_dev, 0); 185 186 return count; 187 } 188 189 static ssize_t eeprom_show(struct device *dev, struct device_attribute *attr, 190 char *buf) 191 { 192 struct solo_dev *solo_dev = 193 container_of(dev, struct solo_dev, dev); 194 u16 *p = (u16 *)buf; 195 int count = (full_eeprom ? 128 : 64); 196 int i; 197 198 for (i = (full_eeprom ? 0 : 32); i < (count / 2); i++) 199 p[i] = be16_to_cpu(solo_eeprom_read(solo_dev, i)); 200 201 return count; 202 } 203 204 static ssize_t p2m_timeouts_show(struct device *dev, 205 struct device_attribute *attr, 206 char *buf) 207 { 208 struct solo_dev *solo_dev = 209 container_of(dev, struct solo_dev, dev); 210 211 return sprintf(buf, "%d\n", solo_dev->p2m_timeouts); 212 } 213 214 static ssize_t sdram_size_show(struct device *dev, 215 struct device_attribute *attr, 216 char *buf) 217 { 218 struct solo_dev *solo_dev = 219 container_of(dev, struct solo_dev, dev); 220 221 return sprintf(buf, "%dMegs\n", solo_dev->sdram_size >> 20); 222 } 223 224 static ssize_t tw28xx_show(struct device *dev, 225 struct device_attribute *attr, 226 char *buf) 227 { 228 struct solo_dev *solo_dev = 229 container_of(dev, struct solo_dev, dev); 230 231 return sprintf(buf, "tw2815[%d] tw2864[%d] tw2865[%d]\n", 232 hweight32(solo_dev->tw2815), 233 hweight32(solo_dev->tw2864), 234 hweight32(solo_dev->tw2865)); 235 } 236 237 static ssize_t input_map_show(struct device *dev, 238 struct device_attribute *attr, 239 char *buf) 240 { 241 struct solo_dev *solo_dev = 242 container_of(dev, struct solo_dev, dev); 243 unsigned int val; 244 char *out = buf; 245 246 val = solo_reg_read(solo_dev, SOLO_VI_CH_SWITCH_0); 247 out += sprintf(out, "Channel 0 => Input %d\n", val & 0x1f); 248 out += sprintf(out, "Channel 1 => Input %d\n", (val >> 5) & 0x1f); 249 out += sprintf(out, "Channel 2 => Input %d\n", (val >> 10) & 0x1f); 250 out += sprintf(out, "Channel 3 => Input %d\n", (val >> 15) & 0x1f); 251 out += sprintf(out, "Channel 4 => Input %d\n", (val >> 20) & 0x1f); 252 out += sprintf(out, "Channel 5 => Input %d\n", (val >> 25) & 0x1f); 253 254 val = solo_reg_read(solo_dev, SOLO_VI_CH_SWITCH_1); 255 out += sprintf(out, "Channel 6 => Input %d\n", val & 0x1f); 256 out += sprintf(out, "Channel 7 => Input %d\n", (val >> 5) & 0x1f); 257 out += sprintf(out, "Channel 8 => Input %d\n", (val >> 10) & 0x1f); 258 out += sprintf(out, "Channel 9 => Input %d\n", (val >> 15) & 0x1f); 259 out += sprintf(out, "Channel 10 => Input %d\n", (val >> 20) & 0x1f); 260 out += sprintf(out, "Channel 11 => Input %d\n", (val >> 25) & 0x1f); 261 262 val = solo_reg_read(solo_dev, SOLO_VI_CH_SWITCH_2); 263 out += sprintf(out, "Channel 12 => Input %d\n", val & 0x1f); 264 out += sprintf(out, "Channel 13 => Input %d\n", (val >> 5) & 0x1f); 265 out += sprintf(out, "Channel 14 => Input %d\n", (val >> 10) & 0x1f); 266 out += sprintf(out, "Channel 15 => Input %d\n", (val >> 15) & 0x1f); 267 out += sprintf(out, "Spot Output => Input %d\n", (val >> 20) & 0x1f); 268 269 return out - buf; 270 } 271 272 static ssize_t p2m_timeout_store(struct device *dev, 273 struct device_attribute *attr, 274 const char *buf, size_t count) 275 { 276 struct solo_dev *solo_dev = 277 container_of(dev, struct solo_dev, dev); 278 unsigned long ms; 279 int ret = kstrtoul(buf, 10, &ms); 280 281 if (ret < 0 || ms > 200) 282 return -EINVAL; 283 solo_dev->p2m_jiffies = msecs_to_jiffies(ms); 284 285 return count; 286 } 287 288 static ssize_t p2m_timeout_show(struct device *dev, 289 struct device_attribute *attr, 290 char *buf) 291 { 292 struct solo_dev *solo_dev = 293 container_of(dev, struct solo_dev, dev); 294 295 return sprintf(buf, "%ums\n", jiffies_to_msecs(solo_dev->p2m_jiffies)); 296 } 297 298 static ssize_t intervals_show(struct device *dev, 299 struct device_attribute *attr, 300 char *buf) 301 { 302 struct solo_dev *solo_dev = 303 container_of(dev, struct solo_dev, dev); 304 char *out = buf; 305 int fps = solo_dev->fps; 306 int i; 307 308 for (i = 0; i < solo_dev->nr_chans; i++) { 309 out += sprintf(out, "Channel %d: %d/%d (0x%08x)\n", 310 i, solo_dev->v4l2_enc[i]->interval, fps, 311 solo_reg_read(solo_dev, SOLO_CAP_CH_INTV(i))); 312 } 313 314 return out - buf; 315 } 316 317 static ssize_t sdram_offsets_show(struct device *dev, 318 struct device_attribute *attr, 319 char *buf) 320 { 321 struct solo_dev *solo_dev = 322 container_of(dev, struct solo_dev, dev); 323 char *out = buf; 324 325 out += sprintf(out, "DISP: 0x%08x @ 0x%08x\n", 326 SOLO_DISP_EXT_ADDR, 327 SOLO_DISP_EXT_SIZE); 328 329 out += sprintf(out, "EOSD: 0x%08x @ 0x%08x (0x%08x * %d)\n", 330 SOLO_EOSD_EXT_ADDR, 331 SOLO_EOSD_EXT_AREA(solo_dev), 332 SOLO_EOSD_EXT_SIZE(solo_dev), 333 SOLO_EOSD_EXT_AREA(solo_dev) / 334 SOLO_EOSD_EXT_SIZE(solo_dev)); 335 336 out += sprintf(out, "MOTI: 0x%08x @ 0x%08x\n", 337 SOLO_MOTION_EXT_ADDR(solo_dev), 338 SOLO_MOTION_EXT_SIZE); 339 340 out += sprintf(out, "G723: 0x%08x @ 0x%08x\n", 341 SOLO_G723_EXT_ADDR(solo_dev), 342 SOLO_G723_EXT_SIZE); 343 344 out += sprintf(out, "CAPT: 0x%08x @ 0x%08x (0x%08x * %d)\n", 345 SOLO_CAP_EXT_ADDR(solo_dev), 346 SOLO_CAP_EXT_SIZE(solo_dev), 347 SOLO_CAP_PAGE_SIZE, 348 SOLO_CAP_EXT_SIZE(solo_dev) / SOLO_CAP_PAGE_SIZE); 349 350 out += sprintf(out, "EREF: 0x%08x @ 0x%08x (0x%08x * %d)\n", 351 SOLO_EREF_EXT_ADDR(solo_dev), 352 SOLO_EREF_EXT_AREA(solo_dev), 353 SOLO_EREF_EXT_SIZE, 354 SOLO_EREF_EXT_AREA(solo_dev) / SOLO_EREF_EXT_SIZE); 355 356 out += sprintf(out, "MPEG: 0x%08x @ 0x%08x\n", 357 SOLO_MP4E_EXT_ADDR(solo_dev), 358 SOLO_MP4E_EXT_SIZE(solo_dev)); 359 360 out += sprintf(out, "JPEG: 0x%08x @ 0x%08x\n", 361 SOLO_JPEG_EXT_ADDR(solo_dev), 362 SOLO_JPEG_EXT_SIZE(solo_dev)); 363 364 return out - buf; 365 } 366 367 static ssize_t sdram_show(struct file *file, struct kobject *kobj, 368 struct bin_attribute *a, char *buf, 369 loff_t off, size_t count) 370 { 371 struct device *dev = kobj_to_dev(kobj); 372 struct solo_dev *solo_dev = 373 container_of(dev, struct solo_dev, dev); 374 const int size = solo_dev->sdram_size; 375 376 if (off >= size) 377 return 0; 378 379 if (off + count > size) 380 count = size - off; 381 382 if (solo_p2m_dma(solo_dev, 0, buf, off, count, 0, 0)) 383 return -EIO; 384 385 return count; 386 } 387 388 static const struct device_attribute solo_dev_attrs[] = { 389 __ATTR(eeprom, 0640, eeprom_show, eeprom_store), 390 __ATTR(p2m_timeout, 0644, p2m_timeout_show, p2m_timeout_store), 391 __ATTR_RO(p2m_timeouts), 392 __ATTR_RO(sdram_size), 393 __ATTR_RO(tw28xx), 394 __ATTR_RO(input_map), 395 __ATTR_RO(intervals), 396 __ATTR_RO(sdram_offsets), 397 }; 398 399 static void solo_device_release(struct device *dev) 400 { 401 /* Do nothing */ 402 } 403 404 static int solo_sysfs_init(struct solo_dev *solo_dev) 405 { 406 struct bin_attribute *sdram_attr = &solo_dev->sdram_attr; 407 struct device *dev = &solo_dev->dev; 408 const char *driver; 409 int i; 410 411 if (solo_dev->type == SOLO_DEV_6110) 412 driver = "solo6110"; 413 else 414 driver = "solo6010"; 415 416 dev->release = solo_device_release; 417 dev->parent = &solo_dev->pdev->dev; 418 set_dev_node(dev, dev_to_node(&solo_dev->pdev->dev)); 419 dev_set_name(dev, "%s-%d-%d", driver, solo_dev->vfd->num, 420 solo_dev->nr_chans); 421 422 if (device_register(dev)) { 423 put_device(dev); 424 dev->parent = NULL; 425 return -ENOMEM; 426 } 427 428 for (i = 0; i < ARRAY_SIZE(solo_dev_attrs); i++) { 429 if (device_create_file(dev, &solo_dev_attrs[i])) { 430 device_unregister(dev); 431 return -ENOMEM; 432 } 433 } 434 435 sysfs_attr_init(&sdram_attr->attr); 436 sdram_attr->attr.name = "sdram"; 437 sdram_attr->attr.mode = 0440; 438 sdram_attr->read = sdram_show; 439 sdram_attr->size = solo_dev->sdram_size; 440 441 if (device_create_bin_file(dev, sdram_attr)) { 442 device_unregister(dev); 443 return -ENOMEM; 444 } 445 446 return 0; 447 } 448 449 static int solo_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) 450 { 451 struct solo_dev *solo_dev; 452 int ret; 453 u8 chip_id; 454 455 solo_dev = kzalloc(sizeof(*solo_dev), GFP_KERNEL); 456 if (solo_dev == NULL) 457 return -ENOMEM; 458 459 if (id->driver_data == SOLO_DEV_6010) 460 dev_info(&pdev->dev, "Probing Softlogic 6010\n"); 461 else 462 dev_info(&pdev->dev, "Probing Softlogic 6110\n"); 463 464 solo_dev->type = id->driver_data; 465 solo_dev->pdev = pdev; 466 ret = v4l2_device_register(&pdev->dev, &solo_dev->v4l2_dev); 467 if (ret) 468 goto fail_probe; 469 470 /* Only for during init */ 471 solo_dev->p2m_jiffies = msecs_to_jiffies(100); 472 473 ret = pci_enable_device(pdev); 474 if (ret) 475 goto fail_probe; 476 477 pci_set_master(pdev); 478 479 /* RETRY/TRDY Timeout disabled */ 480 pci_write_config_byte(pdev, 0x40, 0x00); 481 pci_write_config_byte(pdev, 0x41, 0x00); 482 483 ret = pci_request_regions(pdev, SOLO6X10_NAME); 484 if (ret) 485 goto fail_probe; 486 487 solo_dev->reg_base = pci_ioremap_bar(pdev, 0); 488 if (solo_dev->reg_base == NULL) { 489 ret = -ENOMEM; 490 goto fail_probe; 491 } 492 493 chip_id = solo_reg_read(solo_dev, SOLO_CHIP_OPTION) & 494 SOLO_CHIP_ID_MASK; 495 switch (chip_id) { 496 case 7: 497 solo_dev->nr_chans = 16; 498 solo_dev->nr_ext = 5; 499 break; 500 case 6: 501 solo_dev->nr_chans = 8; 502 solo_dev->nr_ext = 2; 503 break; 504 default: 505 dev_warn(&pdev->dev, "Invalid chip_id 0x%02x, assuming 4 ch\n", 506 chip_id); 507 fallthrough; 508 case 5: 509 solo_dev->nr_chans = 4; 510 solo_dev->nr_ext = 1; 511 } 512 513 /* Disable all interrupts to start */ 514 solo_irq_off(solo_dev, ~0); 515 516 /* Initial global settings */ 517 if (solo_dev->type == SOLO_DEV_6010) { 518 solo_dev->clock_mhz = 108; 519 solo_dev->sys_config = SOLO_SYS_CFG_SDRAM64BIT 520 | SOLO_SYS_CFG_INPUTDIV(25) 521 | SOLO_SYS_CFG_FEEDBACKDIV(solo_dev->clock_mhz * 2 - 2) 522 | SOLO_SYS_CFG_OUTDIV(3); 523 solo_reg_write(solo_dev, SOLO_SYS_CFG, solo_dev->sys_config); 524 } else { 525 u32 divq, divf; 526 527 solo_dev->clock_mhz = 135; 528 529 if (solo_dev->clock_mhz < 125) { 530 divq = 3; 531 divf = (solo_dev->clock_mhz * 4) / 3 - 1; 532 } else { 533 divq = 2; 534 divf = (solo_dev->clock_mhz * 2) / 3 - 1; 535 } 536 537 solo_reg_write(solo_dev, SOLO_PLL_CONFIG, 538 (1 << 20) | /* PLL_RANGE */ 539 (8 << 15) | /* PLL_DIVR */ 540 (divq << 12) | 541 (divf << 4) | 542 (1 << 1) /* PLL_FSEN */); 543 544 solo_dev->sys_config = SOLO_SYS_CFG_SDRAM64BIT; 545 } 546 547 solo_reg_write(solo_dev, SOLO_SYS_CFG, solo_dev->sys_config); 548 solo_reg_write(solo_dev, SOLO_TIMER_CLOCK_NUM, 549 solo_dev->clock_mhz - 1); 550 551 /* PLL locking time of 1ms */ 552 mdelay(1); 553 554 ret = request_irq(pdev->irq, solo_isr, IRQF_SHARED, SOLO6X10_NAME, 555 solo_dev); 556 if (ret) 557 goto fail_probe; 558 559 /* Handle this from the start */ 560 solo_irq_on(solo_dev, SOLO_IRQ_PCI_ERR); 561 562 ret = solo_i2c_init(solo_dev); 563 if (ret) 564 goto fail_probe; 565 566 /* Setup the DMA engine */ 567 solo_reg_write(solo_dev, SOLO_DMA_CTRL, 568 SOLO_DMA_CTRL_REFRESH_CYCLE(1) | 569 SOLO_DMA_CTRL_SDRAM_SIZE(2) | 570 SOLO_DMA_CTRL_SDRAM_CLK_INVERT | 571 SOLO_DMA_CTRL_READ_CLK_SELECT | 572 SOLO_DMA_CTRL_LATENCY(1)); 573 574 /* Undocumented crap */ 575 solo_reg_write(solo_dev, SOLO_DMA_CTRL1, 576 solo_dev->type == SOLO_DEV_6010 ? 0x100 : 0x300); 577 578 if (solo_dev->type != SOLO_DEV_6010) { 579 solo_dev->usec_lsb = 0x3f; 580 solo_set_time(solo_dev); 581 } 582 583 /* Disable watchdog */ 584 solo_reg_write(solo_dev, SOLO_WATCHDOG, 0); 585 586 /* Initialize sub components */ 587 588 ret = solo_p2m_init(solo_dev); 589 if (ret) 590 goto fail_probe; 591 592 ret = solo_disp_init(solo_dev); 593 if (ret) 594 goto fail_probe; 595 596 ret = solo_gpio_init(solo_dev); 597 if (ret) 598 goto fail_probe; 599 600 ret = solo_tw28_init(solo_dev); 601 if (ret) 602 goto fail_probe; 603 604 ret = solo_v4l2_init(solo_dev, video_nr); 605 if (ret) 606 goto fail_probe; 607 608 ret = solo_enc_init(solo_dev); 609 if (ret) 610 goto fail_probe; 611 612 ret = solo_enc_v4l2_init(solo_dev, video_nr); 613 if (ret) 614 goto fail_probe; 615 616 ret = solo_g723_init(solo_dev); 617 if (ret) 618 goto fail_probe; 619 620 ret = solo_sysfs_init(solo_dev); 621 if (ret) 622 goto fail_probe; 623 624 /* Now that init is over, set this lower */ 625 solo_dev->p2m_jiffies = msecs_to_jiffies(20); 626 627 return 0; 628 629 fail_probe: 630 free_solo_dev(solo_dev); 631 return ret; 632 } 633 634 static void solo_pci_remove(struct pci_dev *pdev) 635 { 636 struct v4l2_device *v4l2_dev = pci_get_drvdata(pdev); 637 struct solo_dev *solo_dev = container_of(v4l2_dev, struct solo_dev, v4l2_dev); 638 639 free_solo_dev(solo_dev); 640 } 641 642 static const struct pci_device_id solo_id_table[] = { 643 /* 6010 based cards */ 644 { PCI_DEVICE(PCI_VENDOR_ID_SOFTLOGIC, PCI_DEVICE_ID_SOLO6010), 645 .driver_data = SOLO_DEV_6010 }, 646 { PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_NEUSOLO_4), 647 .driver_data = SOLO_DEV_6010 }, 648 { PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_NEUSOLO_9), 649 .driver_data = SOLO_DEV_6010 }, 650 { PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_NEUSOLO_16), 651 .driver_data = SOLO_DEV_6010 }, 652 { PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_SOLO_4), 653 .driver_data = SOLO_DEV_6010 }, 654 { PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_SOLO_9), 655 .driver_data = SOLO_DEV_6010 }, 656 { PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_SOLO_16), 657 .driver_data = SOLO_DEV_6010 }, 658 /* 6110 based cards */ 659 { PCI_DEVICE(PCI_VENDOR_ID_SOFTLOGIC, PCI_DEVICE_ID_SOLO6110), 660 .driver_data = SOLO_DEV_6110 }, 661 { PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_6110_4), 662 .driver_data = SOLO_DEV_6110 }, 663 { PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_6110_8), 664 .driver_data = SOLO_DEV_6110 }, 665 { PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_6110_16), 666 .driver_data = SOLO_DEV_6110 }, 667 {0,} 668 }; 669 670 MODULE_DEVICE_TABLE(pci, solo_id_table); 671 672 static struct pci_driver solo_pci_driver = { 673 .name = SOLO6X10_NAME, 674 .id_table = solo_id_table, 675 .probe = solo_pci_probe, 676 .remove = solo_pci_remove, 677 }; 678 679 module_pci_driver(solo_pci_driver); 680