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 } 148 149 pci_disable_device(pdev); 150 v4l2_device_unregister(&solo_dev->v4l2_dev); 151 pci_set_drvdata(pdev, NULL); 152 153 kfree(solo_dev); 154 } 155 156 static ssize_t eeprom_store(struct device *dev, struct device_attribute *attr, 157 const char *buf, size_t count) 158 { 159 struct solo_dev *solo_dev = 160 container_of(dev, struct solo_dev, dev); 161 u16 *p = (u16 *)buf; 162 int i; 163 164 if (count & 0x1) 165 dev_warn(dev, "EEPROM Write not aligned (truncating)\n"); 166 167 if (!full_eeprom && count > 64) { 168 dev_warn(dev, "EEPROM Write truncated to 64 bytes\n"); 169 count = 64; 170 } else if (full_eeprom && count > 128) { 171 dev_warn(dev, "EEPROM Write truncated to 128 bytes\n"); 172 count = 128; 173 } 174 175 solo_eeprom_ewen(solo_dev, 1); 176 177 for (i = full_eeprom ? 0 : 32; i < min((int)(full_eeprom ? 64 : 32), 178 (int)(count / 2)); i++) 179 solo_eeprom_write(solo_dev, i, cpu_to_be16(p[i])); 180 181 solo_eeprom_ewen(solo_dev, 0); 182 183 return count; 184 } 185 186 static ssize_t eeprom_show(struct device *dev, struct device_attribute *attr, 187 char *buf) 188 { 189 struct solo_dev *solo_dev = 190 container_of(dev, struct solo_dev, dev); 191 u16 *p = (u16 *)buf; 192 int count = (full_eeprom ? 128 : 64); 193 int i; 194 195 for (i = (full_eeprom ? 0 : 32); i < (count / 2); i++) 196 p[i] = be16_to_cpu(solo_eeprom_read(solo_dev, i)); 197 198 return count; 199 } 200 201 static ssize_t p2m_timeouts_show(struct device *dev, 202 struct device_attribute *attr, 203 char *buf) 204 { 205 struct solo_dev *solo_dev = 206 container_of(dev, struct solo_dev, dev); 207 208 return sprintf(buf, "%d\n", solo_dev->p2m_timeouts); 209 } 210 211 static ssize_t sdram_size_show(struct device *dev, 212 struct device_attribute *attr, 213 char *buf) 214 { 215 struct solo_dev *solo_dev = 216 container_of(dev, struct solo_dev, dev); 217 218 return sprintf(buf, "%dMegs\n", solo_dev->sdram_size >> 20); 219 } 220 221 static ssize_t tw28xx_show(struct device *dev, 222 struct device_attribute *attr, 223 char *buf) 224 { 225 struct solo_dev *solo_dev = 226 container_of(dev, struct solo_dev, dev); 227 228 return sprintf(buf, "tw2815[%d] tw2864[%d] tw2865[%d]\n", 229 hweight32(solo_dev->tw2815), 230 hweight32(solo_dev->tw2864), 231 hweight32(solo_dev->tw2865)); 232 } 233 234 static ssize_t input_map_show(struct device *dev, 235 struct device_attribute *attr, 236 char *buf) 237 { 238 struct solo_dev *solo_dev = 239 container_of(dev, struct solo_dev, dev); 240 unsigned int val; 241 char *out = buf; 242 243 val = solo_reg_read(solo_dev, SOLO_VI_CH_SWITCH_0); 244 out += sprintf(out, "Channel 0 => Input %d\n", val & 0x1f); 245 out += sprintf(out, "Channel 1 => Input %d\n", (val >> 5) & 0x1f); 246 out += sprintf(out, "Channel 2 => Input %d\n", (val >> 10) & 0x1f); 247 out += sprintf(out, "Channel 3 => Input %d\n", (val >> 15) & 0x1f); 248 out += sprintf(out, "Channel 4 => Input %d\n", (val >> 20) & 0x1f); 249 out += sprintf(out, "Channel 5 => Input %d\n", (val >> 25) & 0x1f); 250 251 val = solo_reg_read(solo_dev, SOLO_VI_CH_SWITCH_1); 252 out += sprintf(out, "Channel 6 => Input %d\n", val & 0x1f); 253 out += sprintf(out, "Channel 7 => Input %d\n", (val >> 5) & 0x1f); 254 out += sprintf(out, "Channel 8 => Input %d\n", (val >> 10) & 0x1f); 255 out += sprintf(out, "Channel 9 => Input %d\n", (val >> 15) & 0x1f); 256 out += sprintf(out, "Channel 10 => Input %d\n", (val >> 20) & 0x1f); 257 out += sprintf(out, "Channel 11 => Input %d\n", (val >> 25) & 0x1f); 258 259 val = solo_reg_read(solo_dev, SOLO_VI_CH_SWITCH_2); 260 out += sprintf(out, "Channel 12 => Input %d\n", val & 0x1f); 261 out += sprintf(out, "Channel 13 => Input %d\n", (val >> 5) & 0x1f); 262 out += sprintf(out, "Channel 14 => Input %d\n", (val >> 10) & 0x1f); 263 out += sprintf(out, "Channel 15 => Input %d\n", (val >> 15) & 0x1f); 264 out += sprintf(out, "Spot Output => Input %d\n", (val >> 20) & 0x1f); 265 266 return out - buf; 267 } 268 269 static ssize_t p2m_timeout_store(struct device *dev, 270 struct device_attribute *attr, 271 const char *buf, size_t count) 272 { 273 struct solo_dev *solo_dev = 274 container_of(dev, struct solo_dev, dev); 275 unsigned long ms; 276 int ret = kstrtoul(buf, 10, &ms); 277 278 if (ret < 0 || ms > 200) 279 return -EINVAL; 280 solo_dev->p2m_jiffies = msecs_to_jiffies(ms); 281 282 return count; 283 } 284 285 static ssize_t p2m_timeout_show(struct device *dev, 286 struct device_attribute *attr, 287 char *buf) 288 { 289 struct solo_dev *solo_dev = 290 container_of(dev, struct solo_dev, dev); 291 292 return sprintf(buf, "%ums\n", jiffies_to_msecs(solo_dev->p2m_jiffies)); 293 } 294 295 static ssize_t intervals_show(struct device *dev, 296 struct device_attribute *attr, 297 char *buf) 298 { 299 struct solo_dev *solo_dev = 300 container_of(dev, struct solo_dev, dev); 301 char *out = buf; 302 int fps = solo_dev->fps; 303 int i; 304 305 for (i = 0; i < solo_dev->nr_chans; i++) { 306 out += sprintf(out, "Channel %d: %d/%d (0x%08x)\n", 307 i, solo_dev->v4l2_enc[i]->interval, fps, 308 solo_reg_read(solo_dev, SOLO_CAP_CH_INTV(i))); 309 } 310 311 return out - buf; 312 } 313 314 static ssize_t sdram_offsets_show(struct device *dev, 315 struct device_attribute *attr, 316 char *buf) 317 { 318 struct solo_dev *solo_dev = 319 container_of(dev, struct solo_dev, dev); 320 char *out = buf; 321 322 out += sprintf(out, "DISP: 0x%08x @ 0x%08x\n", 323 SOLO_DISP_EXT_ADDR, 324 SOLO_DISP_EXT_SIZE); 325 326 out += sprintf(out, "EOSD: 0x%08x @ 0x%08x (0x%08x * %d)\n", 327 SOLO_EOSD_EXT_ADDR, 328 SOLO_EOSD_EXT_AREA(solo_dev), 329 SOLO_EOSD_EXT_SIZE(solo_dev), 330 SOLO_EOSD_EXT_AREA(solo_dev) / 331 SOLO_EOSD_EXT_SIZE(solo_dev)); 332 333 out += sprintf(out, "MOTI: 0x%08x @ 0x%08x\n", 334 SOLO_MOTION_EXT_ADDR(solo_dev), 335 SOLO_MOTION_EXT_SIZE); 336 337 out += sprintf(out, "G723: 0x%08x @ 0x%08x\n", 338 SOLO_G723_EXT_ADDR(solo_dev), 339 SOLO_G723_EXT_SIZE); 340 341 out += sprintf(out, "CAPT: 0x%08x @ 0x%08x (0x%08x * %d)\n", 342 SOLO_CAP_EXT_ADDR(solo_dev), 343 SOLO_CAP_EXT_SIZE(solo_dev), 344 SOLO_CAP_PAGE_SIZE, 345 SOLO_CAP_EXT_SIZE(solo_dev) / SOLO_CAP_PAGE_SIZE); 346 347 out += sprintf(out, "EREF: 0x%08x @ 0x%08x (0x%08x * %d)\n", 348 SOLO_EREF_EXT_ADDR(solo_dev), 349 SOLO_EREF_EXT_AREA(solo_dev), 350 SOLO_EREF_EXT_SIZE, 351 SOLO_EREF_EXT_AREA(solo_dev) / SOLO_EREF_EXT_SIZE); 352 353 out += sprintf(out, "MPEG: 0x%08x @ 0x%08x\n", 354 SOLO_MP4E_EXT_ADDR(solo_dev), 355 SOLO_MP4E_EXT_SIZE(solo_dev)); 356 357 out += sprintf(out, "JPEG: 0x%08x @ 0x%08x\n", 358 SOLO_JPEG_EXT_ADDR(solo_dev), 359 SOLO_JPEG_EXT_SIZE(solo_dev)); 360 361 return out - buf; 362 } 363 364 static ssize_t sdram_show(struct file *file, struct kobject *kobj, 365 struct bin_attribute *a, char *buf, 366 loff_t off, size_t count) 367 { 368 struct device *dev = kobj_to_dev(kobj); 369 struct solo_dev *solo_dev = 370 container_of(dev, struct solo_dev, dev); 371 const int size = solo_dev->sdram_size; 372 373 if (off >= size) 374 return 0; 375 376 if (off + count > size) 377 count = size - off; 378 379 if (solo_p2m_dma(solo_dev, 0, buf, off, count, 0, 0)) 380 return -EIO; 381 382 return count; 383 } 384 385 static const struct device_attribute solo_dev_attrs[] = { 386 __ATTR(eeprom, 0640, eeprom_show, eeprom_store), 387 __ATTR(p2m_timeout, 0644, p2m_timeout_show, p2m_timeout_store), 388 __ATTR_RO(p2m_timeouts), 389 __ATTR_RO(sdram_size), 390 __ATTR_RO(tw28xx), 391 __ATTR_RO(input_map), 392 __ATTR_RO(intervals), 393 __ATTR_RO(sdram_offsets), 394 }; 395 396 static void solo_device_release(struct device *dev) 397 { 398 /* Do nothing */ 399 } 400 401 static int solo_sysfs_init(struct solo_dev *solo_dev) 402 { 403 struct bin_attribute *sdram_attr = &solo_dev->sdram_attr; 404 struct device *dev = &solo_dev->dev; 405 const char *driver; 406 int i; 407 408 if (solo_dev->type == SOLO_DEV_6110) 409 driver = "solo6110"; 410 else 411 driver = "solo6010"; 412 413 dev->release = solo_device_release; 414 dev->parent = &solo_dev->pdev->dev; 415 set_dev_node(dev, dev_to_node(&solo_dev->pdev->dev)); 416 dev_set_name(dev, "%s-%d-%d", driver, solo_dev->vfd->num, 417 solo_dev->nr_chans); 418 419 if (device_register(dev)) { 420 put_device(dev); 421 dev->parent = NULL; 422 return -ENOMEM; 423 } 424 425 for (i = 0; i < ARRAY_SIZE(solo_dev_attrs); i++) { 426 if (device_create_file(dev, &solo_dev_attrs[i])) { 427 device_unregister(dev); 428 return -ENOMEM; 429 } 430 } 431 432 sysfs_attr_init(&sdram_attr->attr); 433 sdram_attr->attr.name = "sdram"; 434 sdram_attr->attr.mode = 0440; 435 sdram_attr->read = sdram_show; 436 sdram_attr->size = solo_dev->sdram_size; 437 438 if (device_create_bin_file(dev, sdram_attr)) { 439 device_unregister(dev); 440 return -ENOMEM; 441 } 442 443 return 0; 444 } 445 446 static int solo_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) 447 { 448 struct solo_dev *solo_dev; 449 int ret; 450 u8 chip_id; 451 452 solo_dev = kzalloc(sizeof(*solo_dev), GFP_KERNEL); 453 if (solo_dev == NULL) 454 return -ENOMEM; 455 456 if (id->driver_data == SOLO_DEV_6010) 457 dev_info(&pdev->dev, "Probing Softlogic 6010\n"); 458 else 459 dev_info(&pdev->dev, "Probing Softlogic 6110\n"); 460 461 solo_dev->type = id->driver_data; 462 solo_dev->pdev = pdev; 463 ret = v4l2_device_register(&pdev->dev, &solo_dev->v4l2_dev); 464 if (ret) 465 goto fail_probe; 466 467 /* Only for during init */ 468 solo_dev->p2m_jiffies = msecs_to_jiffies(100); 469 470 ret = pci_enable_device(pdev); 471 if (ret) 472 goto fail_probe; 473 474 pci_set_master(pdev); 475 476 /* RETRY/TRDY Timeout disabled */ 477 pci_write_config_byte(pdev, 0x40, 0x00); 478 pci_write_config_byte(pdev, 0x41, 0x00); 479 480 ret = pcim_iomap_regions(pdev, BIT(0), SOLO6X10_NAME); 481 if (ret) 482 goto fail_probe; 483 solo_dev->reg_base = pcim_iomap_table(pdev)[0]; 484 485 chip_id = solo_reg_read(solo_dev, SOLO_CHIP_OPTION) & 486 SOLO_CHIP_ID_MASK; 487 switch (chip_id) { 488 case 7: 489 solo_dev->nr_chans = 16; 490 solo_dev->nr_ext = 5; 491 break; 492 case 6: 493 solo_dev->nr_chans = 8; 494 solo_dev->nr_ext = 2; 495 break; 496 default: 497 dev_warn(&pdev->dev, "Invalid chip_id 0x%02x, assuming 4 ch\n", 498 chip_id); 499 fallthrough; 500 case 5: 501 solo_dev->nr_chans = 4; 502 solo_dev->nr_ext = 1; 503 } 504 505 /* Disable all interrupts to start */ 506 solo_irq_off(solo_dev, ~0); 507 508 /* Initial global settings */ 509 if (solo_dev->type == SOLO_DEV_6010) { 510 solo_dev->clock_mhz = 108; 511 solo_dev->sys_config = SOLO_SYS_CFG_SDRAM64BIT 512 | SOLO_SYS_CFG_INPUTDIV(25) 513 | SOLO_SYS_CFG_FEEDBACKDIV(solo_dev->clock_mhz * 2 - 2) 514 | SOLO_SYS_CFG_OUTDIV(3); 515 solo_reg_write(solo_dev, SOLO_SYS_CFG, solo_dev->sys_config); 516 } else { 517 u32 divq, divf; 518 519 solo_dev->clock_mhz = 135; 520 521 if (solo_dev->clock_mhz < 125) { 522 divq = 3; 523 divf = (solo_dev->clock_mhz * 4) / 3 - 1; 524 } else { 525 divq = 2; 526 divf = (solo_dev->clock_mhz * 2) / 3 - 1; 527 } 528 529 solo_reg_write(solo_dev, SOLO_PLL_CONFIG, 530 (1 << 20) | /* PLL_RANGE */ 531 (8 << 15) | /* PLL_DIVR */ 532 (divq << 12) | 533 (divf << 4) | 534 (1 << 1) /* PLL_FSEN */); 535 536 solo_dev->sys_config = SOLO_SYS_CFG_SDRAM64BIT; 537 } 538 539 solo_reg_write(solo_dev, SOLO_SYS_CFG, solo_dev->sys_config); 540 solo_reg_write(solo_dev, SOLO_TIMER_CLOCK_NUM, 541 solo_dev->clock_mhz - 1); 542 543 /* PLL locking time of 1ms */ 544 mdelay(1); 545 546 ret = devm_request_irq(&pdev->dev, pdev->irq, solo_isr, IRQF_SHARED, 547 SOLO6X10_NAME, solo_dev); 548 if (ret) 549 goto fail_probe; 550 551 /* Handle this from the start */ 552 solo_irq_on(solo_dev, SOLO_IRQ_PCI_ERR); 553 554 ret = solo_i2c_init(solo_dev); 555 if (ret) 556 goto fail_probe; 557 558 /* Setup the DMA engine */ 559 solo_reg_write(solo_dev, SOLO_DMA_CTRL, 560 SOLO_DMA_CTRL_REFRESH_CYCLE(1) | 561 SOLO_DMA_CTRL_SDRAM_SIZE(2) | 562 SOLO_DMA_CTRL_SDRAM_CLK_INVERT | 563 SOLO_DMA_CTRL_READ_CLK_SELECT | 564 SOLO_DMA_CTRL_LATENCY(1)); 565 566 /* Undocumented crap */ 567 solo_reg_write(solo_dev, SOLO_DMA_CTRL1, 568 solo_dev->type == SOLO_DEV_6010 ? 0x100 : 0x300); 569 570 if (solo_dev->type != SOLO_DEV_6010) { 571 solo_dev->usec_lsb = 0x3f; 572 solo_set_time(solo_dev); 573 } 574 575 /* Disable watchdog */ 576 solo_reg_write(solo_dev, SOLO_WATCHDOG, 0); 577 578 /* Initialize sub components */ 579 580 ret = solo_p2m_init(solo_dev); 581 if (ret) 582 goto fail_probe; 583 584 ret = solo_disp_init(solo_dev); 585 if (ret) 586 goto fail_probe; 587 588 ret = solo_gpio_init(solo_dev); 589 if (ret) 590 goto fail_probe; 591 592 ret = solo_tw28_init(solo_dev); 593 if (ret) 594 goto fail_probe; 595 596 ret = solo_v4l2_init(solo_dev, video_nr); 597 if (ret) 598 goto fail_probe; 599 600 ret = solo_enc_init(solo_dev); 601 if (ret) 602 goto fail_probe; 603 604 ret = solo_enc_v4l2_init(solo_dev, video_nr); 605 if (ret) 606 goto fail_probe; 607 608 ret = solo_g723_init(solo_dev); 609 if (ret) 610 goto fail_probe; 611 612 ret = solo_sysfs_init(solo_dev); 613 if (ret) 614 goto fail_probe; 615 616 /* Now that init is over, set this lower */ 617 solo_dev->p2m_jiffies = msecs_to_jiffies(20); 618 619 return 0; 620 621 fail_probe: 622 free_solo_dev(solo_dev); 623 return ret; 624 } 625 626 static void solo_pci_remove(struct pci_dev *pdev) 627 { 628 struct v4l2_device *v4l2_dev = pci_get_drvdata(pdev); 629 struct solo_dev *solo_dev = container_of(v4l2_dev, struct solo_dev, v4l2_dev); 630 631 free_solo_dev(solo_dev); 632 } 633 634 static const struct pci_device_id solo_id_table[] = { 635 /* 6010 based cards */ 636 { PCI_DEVICE(PCI_VENDOR_ID_SOFTLOGIC, PCI_DEVICE_ID_SOLO6010), 637 .driver_data = SOLO_DEV_6010 }, 638 { PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_NEUSOLO_4), 639 .driver_data = SOLO_DEV_6010 }, 640 { PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_NEUSOLO_9), 641 .driver_data = SOLO_DEV_6010 }, 642 { PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_NEUSOLO_16), 643 .driver_data = SOLO_DEV_6010 }, 644 { PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_SOLO_4), 645 .driver_data = SOLO_DEV_6010 }, 646 { PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_SOLO_9), 647 .driver_data = SOLO_DEV_6010 }, 648 { PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_SOLO_16), 649 .driver_data = SOLO_DEV_6010 }, 650 /* 6110 based cards */ 651 { PCI_DEVICE(PCI_VENDOR_ID_SOFTLOGIC, PCI_DEVICE_ID_SOLO6110), 652 .driver_data = SOLO_DEV_6110 }, 653 { PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_6110_4), 654 .driver_data = SOLO_DEV_6110 }, 655 { PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_6110_8), 656 .driver_data = SOLO_DEV_6110 }, 657 { PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_6110_16), 658 .driver_data = SOLO_DEV_6110 }, 659 {0,} 660 }; 661 662 MODULE_DEVICE_TABLE(pci, solo_id_table); 663 664 static struct pci_driver solo_pci_driver = { 665 .name = SOLO6X10_NAME, 666 .id_table = solo_id_table, 667 .probe = solo_pci_probe, 668 .remove = solo_pci_remove, 669 }; 670 671 module_pci_driver(solo_pci_driver); 672